@@ -16,23 +16,17 @@ All rules can be arbitrarily combined and extended as long as the target type ma
16
16
As an example, let's convert from JSON to a struct.
17
17
18
18
``` rust
19
- use refined_type :: Refined ;
20
- use refined_type :: rule :: NonEmptyRule ;
21
- use serde :: Deserialize ;
22
- use serde_json :: json;
23
-
24
19
// define the constraints you expect by combining 'Refined' and 'Rule'.
25
- pub type MyNonEmptyString = Refined <NonEmptyRule <String >>;
26
- pub type MyNonEmptyVec <T > = Refined <NonEmptyRule <Vec <T >>>;
20
+ type MyNonEmptyString = Refined <NonEmptyRule <String >>;
21
+ type MyNonEmptyVec <T > = Refined <NonEmptyRule <Vec <T >>>;
27
22
28
23
// define a struct for converting from JSON.
29
24
#[derive(Debug , Eq , PartialEq , Deserialize )]
30
25
struct Human {
31
26
name : MyNonEmptyString ,
32
- friends : MyNonEmptyVec <String >
27
+ friends : MyNonEmptyVec <String >,
33
28
}
34
29
35
- // In the first example, both 'name' and 'friends' satisfy the rule, so the conversion from JSON will succeed.
36
30
fn example_1 () -> anyhow :: Result <()> {
37
31
let json = json! {{
38
32
" name" : " john" ,
@@ -43,7 +37,7 @@ fn example_1() -> anyhow::Result<()> {
43
37
let actual = serde_json :: from_str :: <Human >(& json )? ;
44
38
let expected = Human {
45
39
name : MyNonEmptyString :: new (" john" . to_string ())? ,
46
- friends : MyNonEmptyVec :: new (vec! [" tom" . to_string (), " taro" . to_string ()])?
40
+ friends : MyNonEmptyVec :: new (vec! [" tom" . to_string (), " taro" . to_string ()])? ,
47
41
};
48
42
assert_eq! (actual , expected );
49
43
Ok (())
@@ -91,7 +85,7 @@ Once the definition is complete, all you need to do is implement the Rule trait.
91
85
Add your preferred conditions as you like.
92
86
93
87
``` rust
94
- fn main () {
88
+ fn example_4 () {
95
89
let non_empty_string_result = Refined :: <NonEmptyStringRule >:: new (" Hello World" . to_string ());
96
90
assert_eq! (non_empty_string_result . unwrap (). deref (), " Hello World" );
97
91
@@ -112,15 +106,14 @@ By using Rule Composer, composite rules can be easily created.
112
106
113
107
``` rust
114
108
struct ContainsHelloRule ;
115
-
116
109
struct ContainsWorldRule ;
117
110
118
111
impl Rule for ContainsHelloRule {
119
112
type Item = String ;
120
113
121
- fn validate (target : Self :: Item ) -> Result <Self :: Item , Error < Self :: Item > > {
114
+ fn validate (target : & Self :: Item ) -> Result <() , Error > {
122
115
if target . contains (" Hello" ) {
123
- Ok (target )
116
+ Ok (() )
124
117
} else {
125
118
Err (Error :: new (format! (" {} does not contain `Hello`" , target )))
126
119
}
@@ -130,9 +123,9 @@ impl Rule for ContainsHelloRule {
130
123
impl Rule for ContainsWorldRule {
131
124
type Item = String ;
132
125
133
- fn validate (target : Self :: Item ) -> Result <Self :: Item , Error < Self :: Item > > {
126
+ fn validate (target : & Self :: Item ) -> Result <() , Error > {
134
127
if target . contains (" World" ) {
135
- Ok (target )
128
+ Ok (() )
136
129
} else {
137
130
Err (Error :: new (format! (" {} does not contain `World`" , target )))
138
131
}
@@ -146,7 +139,7 @@ impl Rule for ContainsWorldRule {
146
139
It is generally effective when you want to narrow down the condition range.
147
140
148
141
``` rust
149
- fn main () {
142
+ fn example_5 () {
150
143
type HelloAndWorldRule = And <ContainsHelloRule , ContainsWorldRule >;
151
144
152
145
let rule_ok = Refined :: <HelloAndWorldRule >:: new (" Hello! World!" . to_string ());
@@ -163,7 +156,7 @@ fn main() {
163
156
It is generally effective when you want to expand the condition range.
164
157
165
158
``` rust
166
- fn main () {
159
+ fn example_6 () {
167
160
type HelloOrWorldRule = Or <ContainsHelloRule , ContainsWorldRule >;
168
161
169
162
let rule_ok_1 = Refined :: <HelloOrWorldRule >:: new (" Hello! World!" . to_string ());
@@ -183,7 +176,7 @@ fn main() {
183
176
It is generally effective when you want to discard only certain situations.
184
177
185
178
``` rust
186
- fn main () {
179
+ fn example_7 () {
187
180
type NotHelloRule = Not <ContainsHelloRule >;
188
181
189
182
let rule_ok = Refined :: <NotHelloRule >:: new (" hello! World!" . to_string ());
@@ -200,18 +193,16 @@ Rule Composer is also a rule.
200
193
Therefore, it can be treated much like a composite function
201
194
202
195
``` rust
203
- struct StartWithHelloRule ;
204
-
205
- struct StartWithByeRule ;
206
-
207
- struct EndWithJohnRule ;
196
+ struct StartsWithHelloRule ;
197
+ struct StartsWithByeRule ;
198
+ struct EndsWithJohnRule ;
208
199
209
200
impl Rule for StartsWithHelloRule {
210
201
type Item = String ;
211
202
212
- fn validate (target : Self :: Item ) -> Result <Self :: Item , Error < Self :: Item > > {
203
+ fn validate (target : & Self :: Item ) -> Result <() , Error > {
213
204
if target . starts_with (" Hello" ) {
214
- Ok (target )
205
+ Ok (() )
215
206
} else {
216
207
Err (Error :: new (format! (" {} does not start with `Hello`" , target )))
217
208
}
@@ -221,34 +212,34 @@ impl Rule for StartsWithHelloRule {
221
212
impl Rule for StartsWithByeRule {
222
213
type Item = String ;
223
214
224
- fn validate (target : Self :: Item ) -> Result <Self :: Item , Error < Self :: Item > > {
215
+ fn validate (target : & Self :: Item ) -> Result <() , Error > {
225
216
if target . starts_with (" Bye" ) {
226
- Ok (target )
217
+ Ok (() )
227
218
} else {
228
219
Err (Error :: new (format! (" {} does not start with `Bye`" , target )))
229
220
}
230
221
}
231
222
}
232
223
233
- impl Rule for EndWithJohnRule {
224
+ impl Rule for EndsWithJohnRule {
234
225
type Item = String ;
235
226
236
- fn validate (target : Self :: Item ) -> Result <Self :: Item , Error < Self :: Item > > {
227
+ fn validate (target : & Self :: Item ) -> Result <() , Error > {
237
228
if target . ends_with (" John" ) {
238
- Ok (target )
229
+ Ok (() )
239
230
} else {
240
231
Err (Error :: new (format! (" {} does not end with `John`" , target )))
241
232
}
242
233
}
243
234
}
244
235
245
- fn main () {
246
- type GreetingRule = And <Or <StartWithHelloRule , StartWithByeRule >, EndWithJohnRule >;
236
+ fn example_8 () {
237
+ type GreetingRule = And <Or <StartsWithHelloRule , StartsWithByeRule >, EndsWithJohnRule >;
247
238
248
- assert! (GreetingRule :: validate (" Hello! Nice to meet you John" . to_string ()). is_ok ());
249
- assert! (GreetingRule :: validate (" Bye! Have a good day John" . to_string ()). is_ok ());
250
- assert! (GreetingRule :: validate (" How are you? Have a good day John" . to_string ()). is_err ());
251
- assert! (GreetingRule :: validate (" Bye! Have a good day Tom" . to_string ()). is_err ());
239
+ assert! (GreetingRule :: validate (& " Hello! Nice to meet you John" . to_string ()). is_ok ());
240
+ assert! (GreetingRule :: validate (& " Bye! Have a good day John" . to_string ()). is_ok ());
241
+ assert! (GreetingRule :: validate (& " How are you? Have a good day John" . to_string ()). is_err ());
242
+ assert! (GreetingRule :: validate (& " Bye! Have a good day Tom" . to_string ()). is_err ());
252
243
}
253
244
```
254
245
@@ -261,16 +252,14 @@ and `Deserialize`.
261
252
### Serialize
262
253
263
254
``` rust
264
- type NonEmptyString = Refined <NonEmptyStringRule >;
265
-
266
- #[derive(Serialize )]
267
- struct Human {
255
+ #[derive(Debug , Eq , PartialEq , Deserialize , Serialize )]
256
+ struct Human2 {
268
257
name : NonEmptyString ,
269
258
age : u8 ,
270
259
}
271
260
272
- fn main () -> anyhow :: Result <()> {
273
- let john = Human {
261
+ fn example_9 () -> anyhow :: Result <()> {
262
+ let john = Human2 {
274
263
name : NonEmptyString :: new (" john" . to_string ())? ,
275
264
age : 8 ,
276
265
};
@@ -288,24 +277,16 @@ fn main() -> anyhow::Result<()> {
288
277
### Deserialize
289
278
290
279
``` rust
291
- type NonEmptyString = Refined <NonEmptyStringRule >;
292
-
293
- #[derive(Debug , Eq , PartialEq , Deserialize )]
294
- struct Human {
295
- name : NonEmptyString ,
296
- age : u8 ,
297
- }
298
-
299
- fn main () -> anyhow :: Result <()> {
280
+ fn example_10 () -> anyhow :: Result <()> {
300
281
let json = json! {{
301
282
" name" : " john" ,
302
283
" age" : 8
303
284
}}
304
285
. to_string ();
305
286
306
- let actual = serde_json :: from_str :: <Human >(& json )? ;
287
+ let actual = serde_json :: from_str :: <Human2 >(& json )? ;
307
288
308
- let expected = Human {
289
+ let expected = Human2 {
309
290
name : NonEmptyString :: new (" john" . to_string ())? ,
310
291
age : 8 ,
311
292
};
@@ -338,15 +319,46 @@ type TargetAgeRule = And<TargetAge18OrMore, TargetAge80OrLess>;
338
319
```
339
320
340
321
# Iterator
322
+ I have also prepared several useful refined types for Iterators.
323
+ ## ` ForAll `
324
+ ` ForAll ` is a rule that applies a specific rule to all elements in the Iterator.
325
+ ``` rust
326
+ fn example_11 () -> anyhow :: Result <()> {
327
+ let vec = vec! [" Hello" . to_string (), " World" . to_string ()];
328
+ let for_all_ok = ForAll :: <NonEmptyStringRule , _ >:: new (vec . clone ())? ;
329
+ assert_eq! (vec , for_all_ok . into_value ());
330
+
331
+ let vec = vec! [" Hello" . to_string (), "" . to_string ()];
332
+ let for_all_err = ForAll :: <NonEmptyStringRule , _ >:: new (vec . clone ());
333
+ assert! (for_all_err . is_err ());
334
+ Ok (())
335
+ }
336
+ ```
341
337
338
+ ## ` Exists `
339
+ ` Exists ` is a rule that applies a specific rule to at least one element in the Iterator.
340
+ ``` rust
341
+ fn example_12 () -> anyhow :: Result <()> {
342
+ let vec = vec! [" Hello" . to_string (), "" . to_string ()];
343
+ let exists_ok = Exists :: <NonEmptyStringRule , _ >:: new (vec . clone ())? ;
344
+ assert_eq! (vec , exists_ok . into_value ());
345
+
346
+ let vec = vec! ["" . to_string (), "" . to_string ()];
347
+ let exists_err = Exists :: <NonEmptyStringRule , _ >:: new (vec . clone ());
348
+ assert! (exists_err . is_err ());
349
+ Ok (())
350
+ }
351
+ ```
352
+ ---
353
+ ## ` into_iter() ` and ` iter() `
342
354
The Iterator I’ve prepared has ` into_iter ` and ` iter ` implemented.
343
355
Therefore, you can easily map or convert it to a different Iterator using ` collect ` .
344
356
Feel free to explore the capabilities of the Iterator you’ve been given!
345
357
346
358
### ` into_iter() `
347
359
348
360
``` rust
349
- fn main () -> anyhow :: Result <()> {
361
+ fn example_11 () -> anyhow :: Result <()> {
350
362
let ne_vec = NonEmptyVec :: new (vec! [1 , 2 , 3 ])? ;
351
363
let ne_vec : NonEmptyVec <i32 > = ne_vec . into_iter (). map (| n | n * 2 ). map (| n | n * 3 ). collect ();
352
364
assert_eq! (ne_vec . into_value (), vec! [6 , 12 , 18 ]);
@@ -357,7 +369,7 @@ fn main() -> anyhow::Result<()> {
357
369
### ` iter() `
358
370
359
371
``` rust
360
- fn main () -> anyhow :: Result <()> {
372
+ fn example_12 () -> anyhow :: Result <()> {
361
373
let ne_vec = NonEmptyVec :: new (vec! [1 , 2 , 3 ])? ;
362
374
let ne_vec : NonEmptyVec <i32 > = ne_vec . iter (). map (| n | n * 2 ). map (| n | n * 3 ). collect ();
363
375
assert_eq! (ne_vec . into_value (), vec! [6 , 12 , 18 ]);
@@ -368,7 +380,7 @@ fn main() -> anyhow::Result<()> {
368
380
### ` NonEmptyVec ` to ` NonEmptyVecDeque ` using ` collect() `
369
381
370
382
``` rust
371
- fn main () -> anyhow :: Result <()> {
383
+ fn example_13 () -> anyhow :: Result <()> {
372
384
let ne_vec = NonEmptyVec :: new (vec! [1 , 2 , 3 ])? ;
373
385
let ne_vec_deque : NonEmptyVecDeque <i32 > = ne_vec . into_iter (). collect ();
374
386
assert_eq! (ne_vec_deque . into_value (), vec! [1 , 2 , 3 ]);
@@ -384,7 +396,7 @@ without downgrading the type level.
384
396
### NonEmptyString
385
397
386
398
``` rust
387
- fn main () -> anyhow :: Result <()> {
399
+ fn example_14 () -> anyhow :: Result <()> {
388
400
let non_empty_string_1 = NonEmptyString :: new (" Hello" . to_string ())? ;
389
401
let non_empty_string_2 = NonEmptyString :: new (" World" . to_string ())? ;
390
402
let non_empty_string = non_empty_string_1 + non_empty_string_2 ; // This is also `NonEmptyString` type
@@ -397,7 +409,7 @@ fn main() -> anyhow::Result<()> {
397
409
### NonEmptyVec
398
410
399
411
``` rust
400
- fn main () -> anyhow :: Result <()> {
412
+ fn example_15 () -> anyhow :: Result <()> {
401
413
let ne_vec_1 = NonEmptyVec :: new (vec! [1 , 2 , 3 ])? ;
402
414
let ne_vec_2 = NonEmptyVec :: new (vec! [4 , 5 , 6 ])? ;
403
415
let ne_vec = ne_vec_1 + ne_vec_2 ; // This is also `NonEmptyVec` type
0 commit comments