@@ -107,6 +107,7 @@ By using Rule Composer, composite rules can be easily created.
107
107
108
108
``` rust
109
109
struct ContainsHelloRule ;
110
+
110
111
struct ContainsWorldRule ;
111
112
112
113
impl Rule for ContainsHelloRule {
@@ -195,7 +196,9 @@ Therefore, it can be treated much like a composite function
195
196
196
197
``` rust
197
198
struct StartsWithHelloRule ;
199
+
198
200
struct StartsWithByeRule ;
201
+
199
202
struct EndsWithJohnRule ;
200
203
201
204
impl Rule for StartsWithHelloRule {
@@ -320,15 +323,19 @@ type TargetAgeRule = And<TargetAge18OrMore, TargetAge80OrLess>;
320
323
```
321
324
322
325
# Iterator
326
+
323
327
I have also prepared several useful refined types for Iterators.
328
+
324
329
## ` ForAll `
330
+
325
331
` ForAll ` is a rule that applies a specific rule to all elements in the Iterator.
332
+
326
333
``` rust
327
334
fn example_11 () -> anyhow :: Result <()> {
328
335
let vec = vec! [" Hello" . to_string (), " World" . to_string ()];
329
336
let for_all_ok = ForAll :: <NonEmptyStringRule , _ >:: new (vec . clone ())? ;
330
337
assert_eq! (vec , for_all_ok . into_value ());
331
-
338
+
332
339
let vec = vec! [" Hello" . to_string (), "" . to_string ()];
333
340
let for_all_err = ForAll :: <NonEmptyStringRule , _ >:: new (vec . clone ());
334
341
assert! (for_all_err . is_err ());
@@ -337,7 +344,9 @@ fn example_11() -> anyhow::Result<()> {
337
344
```
338
345
339
346
## ` Exists `
347
+
340
348
` Exists ` is a rule that applies a specific rule to at least one element in the Iterator.
349
+
341
350
``` rust
342
351
fn example_12 () -> anyhow :: Result <()> {
343
352
let vec = vec! [" Hello" . to_string (), "" . to_string ()];
@@ -350,8 +359,11 @@ fn example_12() -> anyhow::Result<()> {
350
359
Ok (())
351
360
}
352
361
```
362
+
353
363
---
364
+
354
365
## ` into_iter() ` and ` iter() `
366
+
355
367
The Iterator I’ve prepared has ` into_iter ` and ` iter ` implemented.
356
368
Therefore, you can easily map or convert it to a different Iterator using ` collect ` .
357
369
Feel free to explore the capabilities of the Iterator you’ve been given!
@@ -420,6 +432,122 @@ fn example_15() -> anyhow::Result<()> {
420
432
}
421
433
```
422
434
435
+ # Length
436
+
437
+ You can impose constraints on objects that have a length, such as ` String ` or ` Vec ` .
438
+
439
+ ### String
440
+
441
+ ``` rust
442
+ fn example_16 () -> Result <(), Error > {
443
+ length_greater_than! (5 );
444
+ length_equal! (5 , 10 );
445
+ length_less_than! (10 );
446
+
447
+ type Password = Refined <From5To10Rule <String >>;
448
+
449
+ type From5To10Rule <T > = And <
450
+ Or <LengthEqualRule5 <T >, LengthGreaterThanRule5 <T >>,
451
+ Or <LengthLessThanRule10 <T >, LengthEqualRule10 <T >>,
452
+ >;
453
+
454
+ // length is 8. so, this is valid
455
+ let raw_password = " password" ;
456
+ let password = Password :: new (raw_password . to_string ())? ;
457
+ assert_eq! (password . into_value (), " password" );
458
+
459
+ // length is 4. so, this is invalid
460
+ let raw_password = " pswd" ;
461
+ let password = Password :: new (raw_password . to_string ());
462
+ assert! (password . is_err ());
463
+
464
+ // length is 17. so, this is invalid
465
+ let raw_password = " password password" ;
466
+ let password = Password :: new (raw_password . to_string ());
467
+ assert! (password . is_err ());
468
+
469
+ Ok (())
470
+ }
471
+ ```
472
+
473
+ ### Vec
474
+
475
+ ``` rust
476
+ #[test]
477
+ fn example_17 () -> anyhow :: Result <()> {
478
+ length_greater_than! (5 );
479
+ length_equal! (5 , 10 );
480
+ length_less_than! (10 );
481
+
482
+ type Friends = Refined <From5To10Rule <Vec <String >>>;
483
+
484
+ type From5To10Rule <T > = And <
485
+ Or <LengthEqualRule5 <T >, LengthGreaterThanRule5 <T >>,
486
+ Or <LengthLessThanRule10 <T >, LengthEqualRule10 <T >>,
487
+ >;
488
+
489
+ // length is 6. so, this is valid
490
+ let raw_friends = vec! [
491
+ " Tom" . to_string (),
492
+ " Taro" . to_string (),
493
+ " Jiro" . to_string (),
494
+ " Hanako" . to_string (),
495
+ " Sachiko" . to_string (),
496
+ " Yoshiko" . to_string (),
497
+ ];
498
+ let friends = Friends :: new (raw_friends . clone ())? ;
499
+ assert_eq! (friends . into_value (), raw_friends );
500
+
501
+ // length is 2. so, this is invalid
502
+ let raw_friends = vec! [" Tom" . to_string (), " Taro" . to_string ()];
503
+ let friends = Friends :: new (raw_friends . clone ());
504
+ assert! (friends . is_err ());
505
+
506
+ // length is 11. so, this is invalid
507
+ let raw_friends = vec! [
508
+ " Tom" . to_string (),
509
+ " Taro" . to_string (),
510
+ " Jiro" . to_string (),
511
+ " Hanako" . to_string (),
512
+ " Sachiko" . to_string (),
513
+ " Yuiko" . to_string (),
514
+ " Taiko" . to_string (),
515
+ " John" . to_string (),
516
+ " Jane" . to_string (),
517
+ " Jack" . to_string (),
518
+ " Jill" . to_string (),
519
+ ];
520
+ let friends = Friends :: new (raw_friends . clone ());
521
+ assert! (friends . is_err ());
522
+
523
+ Ok (())
524
+ }
525
+ ```
526
+
527
+ ### Custom Length
528
+
529
+ You can define a length for any type. Therefore, if you want to implement a length that is not provided
530
+ by ` refined_type ` , you can easily do so using ` LengthDefinition ` .
531
+
532
+ ``` rust
533
+ #[test]
534
+ fn example_18 () -> anyhow :: Result <()> {
535
+ length_equal! (5 );
536
+
537
+ #[derive(Debug , PartialEq )]
538
+ struct Hello ;
539
+ impl LengthDefinition for Hello {
540
+ fn length (& self ) -> usize {
541
+ 5
542
+ }
543
+ }
544
+
545
+ let hello = Refined :: <LengthEqualRule5 <Hello >>:: new (Hello )? ;
546
+ assert_eq! (hello . into_value (), Hello );
547
+ Ok (())
548
+ }
549
+ ```
550
+
423
551
# Tips
424
552
425
553
Directly writing ` And ` , ` Or ` , ` Not ` or ` Refined ` can often lead to a decrease in readability.
0 commit comments