validators/
lib.rs

1/*!
2# Validators
3
4This library is designed for validating and modeling user input. The crate includes models, functions, traits, errors, and other dependencies.
5
6## Features
7
8By default, every validators this crate supports will be enabled. You can disable all of them by turning off the default features and enable only the validators that you want to use by adding them to the `features` explicitly.
9
10For example,
11
12```toml
13[dependencies.validators]
14version = "*"
15features = ["base64", "url", "uuid"]
16default-features = false
17```
18
19Certain validators do not require the use of the `std` library. However, if needed, you can explicitly enable the `std` feature.
20
21This library can support the Serde framework and the Rocket framework by enabling the `serde` and `rocket` features, respectively.
22
23## Validators
24
25```rust
26use validators::prelude::*;
27
28/*
29#[derive(Validator)]
30#[validator(validator_name)]
31DEFINE_YOUR_STRUCT_HERE
32*/
33```
34
35When you apply the `#[validator(validator_name)]` attribute to your structs, one or more traits from the `validators::traits` module are automatically implemented. These traits can then be utilized for validation and deserialization purposes.
36
37The struct used as a validator should possess specific components corresponding to its validator type and its associated parameters. For instance, a `base32` validator must be a `struct(String)`, while a `base32_decoded` validator should be a `struct(Vec<u8>)`.
38
39The `#[validator(validator_name)]` attribute cannot be applied to fields within any structs or enums. The decision to use a procedural macro for defining a validator (i.e., a struct) instead of offering built-in structs for each configuration is motivated by the aim to eliminate runtime overhead for configurable validations and to enhance compilation speed.
40
41#### base32
42
43```rust
44# #[cfg(all(feature = "derive", feature = "base32"))]
45# {
46use validators::prelude::*;
47
48#[derive(Validator)]
49#[validator(base32(padding(Must)))]
50pub struct Base32WithPadding(String);
51
52assert!(Base32WithPadding::parse_string("GEZDGNBVGY3TQOI=").is_ok());
53assert!(Base32WithPadding::parse_string("GEZDGNBVGY3TQOI").is_err());
54assert_eq!("GEZDGNBVGY3TQOI=", Base32WithPadding::parse_string("GEZDGNBVGY3TQOI=").unwrap().0);
55# }
56```
57
58* Traits: `ValidateString`, `ValidateBytes`
59* By default, `padding = Allow`
60
61#### base32_decoded
62
63```rust
64# #[cfg(all(feature = "derive", feature = "base32_decoded"))]
65# {
66use validators::prelude::*;
67
68#[derive(Validator)]
69#[validator(base32_decoded(padding(Must)))]
70pub struct Base32WithPaddingDecoded(Vec<u8>);
71
72assert!(Base32WithPaddingDecoded::parse_string("GEZDGNBVGY3TQOI=").is_ok());
73assert!(Base32WithPaddingDecoded::parse_string("GEZDGNBVGY3TQOI").is_err());
74assert_eq!(b"123456789", Base32WithPaddingDecoded::parse_string("GEZDGNBVGY3TQOI=").unwrap().0.as_slice());
75# }
76```
77
78* Traits: `ValidateString`, `ValidateBytes`, `CollectionLength`
79* By default, `padding = Allow`
80
81#### base64
82
83```rust
84# #[cfg(all(feature = "derive", feature = "base64"))]
85# {
86use validators::prelude::*;
87
88#[derive(Validator)]
89#[validator(base64(padding(Must)))]
90pub struct Base64WithPadding(String);
91
92assert!(Base64WithPadding::parse_string("MTIzNDU2Nzg5MA==").is_ok());
93assert!(Base64WithPadding::parse_string("MTIzNDU2Nzg5MA").is_err());
94assert_eq!("MTIzNDU2Nzg5MA==", Base64WithPadding::parse_string("MTIzNDU2Nzg5MA==").unwrap().0);
95# }
96```
97
98* Traits: `ValidateString`, `ValidateBytes`
99* By default, `padding = Allow`
100
101#### base64_decoded
102
103```rust
104# #[cfg(all(feature = "derive", feature = "base64_decoded"))]
105# {
106use validators::prelude::*;
107
108#[derive(Validator)]
109#[validator(base64_decoded(padding(Must)))]
110pub struct Base64WithPaddingDecoded(Vec<u8>);
111
112assert!(Base64WithPaddingDecoded::parse_string("MTIzNDU2Nzg5MA==").is_ok());
113assert!(Base64WithPaddingDecoded::parse_string("MTIzNDU2Nzg5MA").is_err());
114assert_eq!(b"1234567890", Base64WithPaddingDecoded::parse_string("MTIzNDU2Nzg5MA==").unwrap().0.as_slice());
115# }
116```
117
118* Traits: `ValidateString`, `ValidateBytes`, `CollectionLength`
119* By default, `padding = Allow`
120
121#### base64_url
122
123```rust
124# #[cfg(all(feature = "derive", feature = "base64_url"))]
125# {
126use validators::prelude::*;
127
128#[derive(Validator)]
129#[validator(base64_url(padding(Disallow)))]
130pub struct Base64UrlWithoutPadding(String);
131
132assert!(Base64UrlWithoutPadding::parse_string("5LmN5pqW6YKE5a-S5pmC5YCZ").is_ok());
133assert!(Base64UrlWithoutPadding::parse_string("5LmN5pqW6YKE5a+S5pmC5YCZ").is_err());
134assert_eq!("5LmN5pqW6YKE5a-S5pmC5YCZ", Base64UrlWithoutPadding::parse_string("5LmN5pqW6YKE5a-S5pmC5YCZ").unwrap().0);
135# }
136```
137
138* Traits: `ValidateString`, `ValidateBytes`
139* By default, `padding = Allow`
140
141#### base64_url_decoded
142
143```rust
144# #[cfg(all(feature = "derive", feature = "base64_url_decoded"))]
145# {
146use validators::prelude::*;
147
148#[derive(Validator)]
149#[validator(base64_url_decoded(padding(Disallow)))]
150pub struct Base64UrlWithoutPaddingDecoded(Vec<u8>);
151
152assert!(Base64UrlWithoutPaddingDecoded::parse_string("5LmN5pqW6YKE5a-S5pmC5YCZ").is_ok());
153assert!(Base64UrlWithoutPaddingDecoded::parse_string("5LmN5pqW6YKE5a+S5pmC5YCZ").is_err());
154assert_eq!("乍暖還寒時候".as_bytes(), Base64UrlWithoutPaddingDecoded::parse_string("5LmN5pqW6YKE5a-S5pmC5YCZ").unwrap().0.as_slice());
155# }
156```
157
158* Traits: `ValidateString`, `ValidateBytes`, `CollectionLength`
159* By default, `padding = Allow`
160
161#### bit
162
163```rust
164# #[cfg(all(feature = "derive", feature = "bit"))]
165# {
166use validators::prelude::*;
167use validators::byte_unit::Bit;
168
169#[derive(Validator)]
170#[validator(bit(range(min = 1)))]
171pub struct AtLeastOneBit(Bit);
172
173assert!(AtLeastOneBit::parse_string("1kb").is_ok());
174assert!(AtLeastOneBit::parse_string("0b").is_err());
175assert_eq!(1000u64, AtLeastOneBit::parse_string("1kb").unwrap().0);
176# }
177```
178
179* Traits: `ValidateString`, `ValidateUnsignedInteger`
180* By default, the range is unlimited
181
182#### boolean
183
184```rust
185# #[cfg(all(feature = "derive", feature = "boolean"))]
186# {
187use validators::prelude::*;
188
189#[derive(Validator)]
190#[validator(boolean)]
191pub struct Boolean(bool);
192
193assert_eq!(true, Boolean::parse_str("true").unwrap().0);
194assert_eq!(false, Boolean::parse_str("f").unwrap().0);
195assert_eq!(true, Boolean::parse_str("y").unwrap().0);
196assert_eq!(false, Boolean::parse_str("no").unwrap().0);
197assert_eq!(true, Boolean::parse_str("on").unwrap().0);
198assert_eq!(false, Boolean::parse_str("off").unwrap().0);
199assert_eq!(true, Boolean::parse_str("1").unwrap().0);
200
201assert_eq!(true, Boolean::parse_char('t').unwrap().0);
202assert_eq!(false, Boolean::parse_char('0').unwrap().0);
203
204assert_eq!(true, Boolean::parse_isize(1).unwrap().0);
205# }
206```
207
208* Traits: `ValidateString`, `ValidateChar`, `ValidateSignedInteger`, `ValidateUnsignedInteger`, `ValidateBoolean`
209
210#### byte
211
212```rust
213# #[cfg(all(feature = "derive", feature = "byte"))]
214# {
215use validators::prelude::*;
216use validators::byte_unit::Byte;
217
218#[derive(Validator)]
219#[validator(byte(range(min = 1), ignore_case = false))]
220pub struct AtLeastOneByte(Byte);
221
222assert!(AtLeastOneByte::parse_string("1KB").is_ok());
223assert!(AtLeastOneByte::parse_string("0B").is_err());
224assert_eq!(1000u64, AtLeastOneByte::parse_string("1KB").unwrap().0);
225# }
226```
227
228* Traits: `ValidateString`, `ValidateUnsignedInteger`
229* By default, the range is unlimited and `ignore_case = true`
230
231#### domain
232
233```rust
234# #[cfg(all(feature = "derive", feature = "domain"))]
235# {
236use validators::prelude::*;
237
238#[derive(Validator)]
239#[validator(domain(ipv4(Allow), local(Allow), port(Disallow), at_least_two_labels(Allow)))]
240pub struct DomainWithoutPort(pub String);
241
242assert!(DomainWithoutPort::parse_string("example.com").is_ok());
243assert!(DomainWithoutPort::parse_string("example.com.").is_ok());
244assert_eq!("xn--fiq228c.com", DomainWithoutPort::parse_string("中文.com").unwrap().0);
245
246#[derive(Validator)]
247#[validator(domain(ipv4(Allow), local(Allow), port(Allow), at_least_two_labels(Allow)))]
248pub struct DomainAllowPort {
249    pub domain: String,
250    port: Option<u16>,
251}
252
253assert_eq!(Some(8080), DomainAllowPort::parse_string("example.com:8080").unwrap().port);
254# }
255```
256
257* Traits: `ValidateString`, `QualifyDomain`, `ToUriAuthorityString`
258* By default, `ipv4 = Allow, local = Allow, port = Allow, at_least_two_labels = Allow`
259
260#### email
261
262```rust
263# #[cfg(all(feature = "derive", feature = "email"))]
264# {
265use validators::prelude::*;
266use validators::models::Host;
267
268#[derive(Validator)]
269#[validator(email(comment(Allow), ip(Allow), local(Allow), at_least_two_labels(Allow), non_ascii(Allow)))]
270pub struct EmailAllowComment {
271    pub local_part: String,
272    pub need_quoted: bool,
273    pub domain_part: Host,
274    pub comment_before_local_part: Option<String>,
275    pub comment_after_local_part: Option<String>,
276    pub comment_before_domain_part: Option<String>,
277    pub comment_after_domain_part: Option<String>,
278}
279
280assert!(EmailAllowComment::parse_string("(john)joke@example.com").is_ok());
281
282#[derive(Validator)]
283#[validator(email(comment(Disallow), ip(Allow), local(Allow), at_least_two_labels(Allow), non_ascii(Allow)))]
284pub struct EmailWithoutComment {
285    pub local_part: String,
286    pub need_quoted: bool,
287    pub domain_part: Host,
288}
289
290assert!(EmailWithoutComment::parse_string("(john)joke@example.com").is_err());
291# }
292```
293
294* Traits: `ValidateString`, `ToEmailString`
295* By default, `comment = Allow, ip = Allow, local = Allow, at_least_two_labels = Allow, non_ascii = Allow`
296
297#### host
298
299```rust
300# #[cfg(all(feature = "derive", feature = "host"))]
301# {
302use validators::prelude::*;
303use validators::models::Host;
304
305#[derive(Validator)]
306#[validator(host(local(Allow), port(Allow), at_least_two_labels(Must)))]
307pub struct HostMustAtLeastTwoLabelsAllowPort {
308    pub host: Host,
309    pub port: Option<u16>,
310    pub is_local: bool,
311}
312
313assert!(HostMustAtLeastTwoLabelsAllowPort::parse_string("example.com:8000").is_ok());
314assert!(HostMustAtLeastTwoLabelsAllowPort::parse_string("example.com.").is_err());
315assert!(HostMustAtLeastTwoLabelsAllowPort::parse_string("example").is_err());
316# }
317```
318
319* Traits: `ValidateString`, `ToUriAuthorityString`
320* By default, `local = Allow, port = Allow, at_least_two_labels = Allow`
321
322#### http_url
323
324```rust
325# #[cfg(all(feature = "derive", feature = "http_url"))]
326# {
327use validators::prelude::*;
328use validators::url::Url;
329
330#[derive(Validator)]
331#[validator(http_url(local(Allow)))]
332pub struct HttpURL {
333    url: Url,
334    is_https: bool,
335}
336
337assert!(HttpURL::parse_string("https://example.org/").is_ok());
338assert!(HttpURL::parse_string("http://example.org/").is_ok());
339assert!(HttpURL::parse_string("ftp://example.org/").is_err());
340# }
341```
342
343* Traits: `ValidateString`
344* By default, `local = Allow`
345
346#### http_ftp_url
347
348```rust
349# #[cfg(all(feature = "derive", feature = "http_ftp_url"))]
350# {
351use validators::prelude::*;
352use validators::models::Protocol;
353use validators::url::Url;
354
355#[derive(Validator)]
356#[validator(http_ftp_url(local(Allow)))]
357pub struct HttpFtpURL {
358    url: Url,
359    protocol: Protocol,
360}
361
362assert!(HttpFtpURL::parse_string("https://example.org/").is_ok());
363assert!(HttpFtpURL::parse_string("http://example.org/").is_ok());
364assert!(HttpFtpURL::parse_string("ftp://example.org/").is_ok());
365# }
366```
367
368* Traits: `ValidateString`
369* By default, `local = Allow`
370
371#### ip
372
373```rust
374# #[cfg(all(feature = "derive", feature = "ip"))]
375# {
376use std::net::IpAddr;
377
378use validators::prelude::*;
379
380#[derive(Validator)]
381#[validator(ip(local(Allow), port(Allow)))]
382pub struct IpAllowPort {
383    pub ip: IpAddr,
384    pub port: Option<u16>,
385}
386
387assert!(IpAllowPort::parse_string("127.0.0.1").is_ok());
388assert!(IpAllowPort::parse_string("[::ffff:c000:0280]:8000").is_ok());
389# }
390```
391
392* Traits: `ValidateString`, `ToUriAuthorityString`
393* By default, `local = Allow, port = Allow`
394
395#### ipv4
396
397```rust
398# #[cfg(all(feature = "derive", feature = "ipv4"))]
399# {
400use std::net::Ipv4Addr;
401
402use validators::prelude::*;
403
404#[derive(Validator)]
405#[validator(ipv4(local(Allow), port(Allow)))]
406pub struct Ipv4AllowPort {
407    pub ipv4: Ipv4Addr,
408    pub port: Option<u16>,
409}
410
411assert!(Ipv4AllowPort::parse_string("127.0.0.1").is_ok());
412# }
413```
414
415* Traits: `ValidateString`, `ToUriAuthorityString`
416* By default, `local = Allow, port = Allow`
417
418#### ipv6
419
420```rust
421# #[cfg(all(feature = "derive", feature = "ipv6"))]
422# {
423use std::net::Ipv6Addr;
424
425use validators::prelude::*;
426
427#[derive(Validator)]
428#[validator(ipv6(local(Allow), port(Allow)))]
429pub struct Ipv6AllowPort {
430    pub ipv6: Ipv6Addr,
431    pub port: Option<u16>,
432}
433
434assert!(Ipv6AllowPort::parse_string("::ffff:c000:0280").is_ok());
435assert!(Ipv6AllowPort::parse_string("[::ffff:c000:0280]").is_ok());
436# }
437```
438
439* Traits: `ValidateString`, `ToUriAuthorityString`
440* By default, `local = Allow, port = Allow`
441
442#### json
443
444```rust
445# #[cfg(all(feature = "derive", feature = "json"))]
446# {
447use validators::prelude::*;
448
449#[derive(Validator)]
450#[validator(json)]
451pub struct JSONString(pub String);
452
453#[derive(Validator)]
454#[validator(json)]
455pub struct JSONNumber(pub f64);
456
457#[derive(Validator)]
458#[validator(json)]
459pub struct JSONBoolean(pub bool);
460
461assert!(JSONString::parse_string("123").is_err());
462assert!(JSONString::parse_string("\"123\"").is_ok());
463assert!(JSONNumber::parse_u64(123).is_ok());
464assert!(JSONBoolean::parse_bool(false).is_ok());
465# }
466```
467
468* Traits: `ValidateString`, `ValidateSignedInteger`, `ValidateUnsignedInteger`, `ValidateNumber`, `ValidateBoolean`, `ValidateJsonValue`
469
470#### length
471
472```rust
473# #[cfg(all(feature = "derive", feature = "length"))]
474# {
475use validators::prelude::*;
476
477#[derive(Validator)]
478#[validator(length(min = 1, max = 3))]
479pub struct NonEmptyNotTooLongVec(pub Vec<u8>);
480
481assert!(NonEmptyNotTooLongVec::parse_collection(vec![]).is_err());
482assert!(NonEmptyNotTooLongVec::parse_collection(vec![0]).is_ok());
483assert!(NonEmptyNotTooLongVec::parse_collection(vec![0, 1, 2, 3]).is_err());
484# }
485```
486
487* Traits: `ValidateLength`, `CollectionLength`
488* By default, the length is unlimited
489
490#### line
491
492```rust
493# #[cfg(all(feature = "derive", feature = "line"))]
494# {
495use validators::prelude::*;
496
497#[derive(Validator)]
498#[validator(line(char_length(trimmed_min = 1, min = 1, max = 1000)))] // `byte_length` can also be used
499pub struct LineNotAllowEmpty(pub String);
500
501assert!(LineNotAllowEmpty::parse_string("123").is_ok());
502assert!(LineNotAllowEmpty::parse_string("123\0").is_err());
503assert!(LineNotAllowEmpty::parse_string("123\n456").is_err());
504assert!(LineNotAllowEmpty::parse_string("   ").is_err());
505# }
506```
507
508* Traits: `ValidateLength`
509* By default, the length is unlimited
510
511#### mac_address
512
513```rust
514# #[cfg(all(feature = "derive", feature = "mac_address"))]
515# {
516use validators::prelude::*;
517
518#[derive(Validator)]
519#[validator(mac_address(case(Upper), separator(Allow(b':'))))]
520pub struct MacAddress(pub u64);
521
522assert!(MacAddress::parse_string("080027B246C3").is_ok());
523assert!(MacAddress::parse_string("08:00:27:B2:46:C3").is_ok());
524# }
525```
526
527* Traits: `ValidateString`, `ToMacAddressString`
528* By default, `case = Any, separator(Allow(b':')`
529
530#### number
531
532```rust
533# #[cfg(all(feature = "derive", feature = "number"))]
534# {
535use validators::prelude::*;
536
537#[derive(Validator)]
538#[validator(number(nan(Disallow), range(Unlimited)))]
539pub struct Double(pub f64);
540
541assert!(Double::parse_string("123.456").is_ok());
542assert!(Double::parse_string("NaN").is_err());
543assert!(Double::parse_f32(123.4).is_ok());
544
545#[derive(Validator)]
546#[validator(number(nan(Allow), range(Inside(min = 0, max = 1.0))))]
547pub struct SinglePercentage(pub f32);
548
549assert!(SinglePercentage::parse_string("0").is_ok());
550assert!(SinglePercentage::parse_string("1").is_ok());
551assert!(SinglePercentage::parse_string("1.1").is_err());
552assert!(SinglePercentage::parse_string("NaN").is_ok());
553# }
554```
555
556* Traits: `ValidateString`, `ValidateNumber`
557* By default, `nan = Allow, range(Unlimited)`
558
559#### phone
560
561```rust
562# #[cfg(all(feature = "derive", feature = "phone"))]
563# {
564use std::collections::HashMap;
565
566use validators::prelude::*;
567use validators_prelude::phonenumber::PhoneNumber;
568
569#[derive(Validator)]
570#[validator(phone)]
571pub struct InternationalPhone(pub phonenumber::PhoneNumber);
572
573#[derive(Validator)]
574#[validator(phone(countries(TW)))]
575pub struct TWPhone(pub phonenumber::PhoneNumber);
576
577#[derive(Validator)]
578#[validator(phone(countries(TW, US)))]
579pub struct TWorUSPhone(
580    pub HashMap<phonenumber::country::Id, phonenumber::PhoneNumber>,
581);
582
583assert!(InternationalPhone::parse_string("+886912345678").is_ok());
584assert!(InternationalPhone::parse_string("0912345678").is_err());
585assert!(InternationalPhone::parse_string("+14155552671").is_ok());
586
587assert!(TWPhone::parse_string("+886912345678").is_ok());
588assert!(TWPhone::parse_string("0912345678").is_ok());
589assert!(TWPhone::parse_string("+14155552671").is_err());
590
591assert!(TWorUSPhone::parse_string("+886912345678").is_ok());
592assert!(TWorUSPhone::parse_string("0912345678").is_ok());
593assert!(TWorUSPhone::parse_string("+14155552671").is_ok());
594# }
595```
596
597* Traits: `ValidateString`
598* By default, countries is unlimited
599
600#### regex
601
602```rust
603# #[cfg(all(feature = "derive", feature = "regex"))]
604# {
605use validators::prelude::*;
606use validators_prelude::regex::Regex;
607
608use once_cell::sync::Lazy;
609
610static RE_NON_ZERO_NUMBERS: Lazy<Regex> = Lazy::new(|| {
611    Regex::new("^[1-9]+$").unwrap()
612});
613
614static RE_POKER: Lazy<Regex> = Lazy::new(|| {
615    Regex::new("^([AJQK1-9]|10)$").unwrap()
616});
617
618#[derive(Validator)]
619#[validator(regex(regex("^[0-9a-fA-F]+$")))]
620pub struct Hex(pub String); // this doesn't cache the `Regex` instance
621
622#[derive(Validator)]
623#[validator(regex(regex(RE_NON_ZERO_NUMBERS)))]
624pub struct NonZeroNumbers(pub String);
625
626#[derive(Validator)]
627#[validator(regex(regex(RE_POKER)))]
628pub struct Poker(pub String);
629
630assert!(Hex::parse_string("1Ab").is_ok());
631assert!(Hex::parse_string("1AG").is_err());
632
633assert!(NonZeroNumbers::parse_string("12345").is_ok());
634assert!(NonZeroNumbers::parse_string("012345").is_err());
635
636assert!(Poker::parse_string("1").is_ok());
637assert!(Poker::parse_string("10").is_ok());
638assert!(Poker::parse_string("J").is_ok());
639assert!(Poker::parse_string("0").is_err());
640# }
641```
642
643* Traits: `ValidateString`
644* The `regex` parameter must be set to a string literal or an expression
645
646#### semver
647
648```rust
649# #[cfg(all(feature = "derive", feature = "semver"))]
650# {
651use validators::prelude::*;
652use validators_prelude::semver::Version;
653
654#[derive(Validator)]
655#[validator(semver)]
656pub struct SemVer(Version);
657
658assert!(SemVer::parse_string("0.0.0").is_ok());
659assert!(SemVer::parse_string("0.0.0-beta.1").is_ok());
660# }
661```
662
663* Traits: `ValidateString`
664
665#### semver_req
666
667```rust
668# #[cfg(all(feature = "derive", feature = "semver_req"))]
669# {
670use validators::prelude::*;
671use validators_prelude::semver::VersionReq;
672
673#[derive(Validator)]
674#[validator(semver_req)]
675pub struct SemVerReq(VersionReq);
676
677assert!(SemVerReq::parse_string("0.0.0").is_ok());
678assert!(SemVerReq::parse_string(">= 0.4").is_ok());
679# }
680```
681
682* Traits: `ValidateString`
683
684#### signed_integer
685
686```rust
687# #[cfg(all(feature = "derive", feature = "signed_integer"))]
688# {
689use validators::prelude::*;
690
691#[derive(Validator)]
692#[validator(signed_integer(range(Inside(min = -1, max = 100))))]
693pub struct Score(i8);
694
695assert!(Score::parse_string("0").is_ok());
696assert!(Score::parse_string("-2").is_err());
697assert!(Score::parse_i8(4).is_ok());
698
699#[derive(Validator)]
700#[validator(signed_integer(range(Outside(min = 0, max = 0))))]
701pub struct NonZeroShort(i16);
702
703assert!(NonZeroShort::parse_i8(4).is_ok());
704assert!(NonZeroShort::parse_i8(-4).is_ok());
705assert!(NonZeroShort::parse_i8(0).is_err());
706# }
707```
708
709* Traits: `ValidateString`, `ValidateSignedInteger`
710* By default, `range(Unlimited)`
711
712#### text
713
714```rust
715# #[cfg(all(feature = "derive", feature = "text"))]
716# {
717use validators::prelude::*;
718
719#[derive(Validator)]
720#[validator(text(char_length(trimmed_min = 1, min = 1, max = 1000)))] // `byte_length` can also be used
721pub struct TextNotAllowEmpty(pub String);
722
723assert!(TextNotAllowEmpty::parse_string("123").is_ok());
724assert!(TextNotAllowEmpty::parse_string("123\0").is_err());
725assert!(TextNotAllowEmpty::parse_string("123\n456").is_ok());
726assert!(TextNotAllowEmpty::parse_string("   ").is_err());
727# }
728```
729
730* Traits: `ValidateLength`
731* By default, the length is unlimited
732
733#### unsigned_integer
734
735```rust
736# #[cfg(all(feature = "derive", feature = "unsigned_integer"))]
737# {
738use validators::prelude::*;
739
740#[derive(Validator)]
741#[validator(unsigned_integer(range(Inside(min = 1, max = 100))))]
742pub struct Count(u8);
743
744assert!(Count::parse_string("5").is_ok());
745assert!(Count::parse_string("0").is_err());
746assert!(Count::parse_u8(4).is_ok());
747# }
748```
749
750* Traits: `ValidateString`, `ValidateUnsignedInteger`
751* By default, `range(Unlimited)`
752
753#### url
754
755```rust
756# #[cfg(all(feature = "derive", feature = "url"))]
757# {
758use validators::prelude::*;
759use validators_prelude::url::Url;
760
761#[derive(Validator)]
762#[validator(url)]
763pub struct URL(pub Url);
764
765assert!(URL::parse_string("https://example.org/").is_ok());
766assert!(URL::parse_string("https:example.org").is_ok());
767assert!(URL::parse_string("example:").is_ok());
768# }
769```
770
771* Traits: `ValidateString`
772
773#### uuid
774
775```rust
776# #[cfg(all(feature = "derive", feature = "uuid"))]
777# {
778use validators::prelude::*;
779
780#[derive(Validator)]
781#[validator(uuid(case(Upper), separator(Allow(b'-'))))]
782pub struct UUID(pub u128);
783
784assert!(UUID::parse_string("A866664AF9D34DDE89CB182015FA4F41").is_ok());
785assert!(UUID::parse_string("A866664A-F9D3-4DDE-89CB-182015FA4F41").is_ok());
786# }
787```
788
789* Traits: `ValidateString`, `ToUuidString`
790* By default, `case = Any, separator(Allow(b'-')`
791
792## `validators::Result`
793
794When incorporating your validator type into another type, you might desire to obtain the original error instance provided by the validator.
795
796For example, when using the `number` validator with the `#[derive(FromForm)]` attribute from the Rocket framework,
797
798```rust
799# #[cfg(all(feature = "derive", feature = "number", feature = "rocket"))]
800# {
801use rocket::{FromForm, get};
802use validators::prelude::*;
803
804#[derive(Debug, Validator)]
805#[validator(number(range(Outside(max = 0))))]
806pub struct NonZeroNumber(f64);
807
808#[derive(Debug, FromForm)]
809struct User {
810    id:   i32,
811    number: NonZeroNumber,
812}
813
814#[get("/?<user..>")]
815fn index(user: User) -> String {
816    format!("{:?}", user)
817}
818# }
819```
820
821You may want the number field of the `User` instance to be allowed to fail. You can modify the code as follows:
822
823```rust
824# #[cfg(all(feature = "derive", feature = "number", feature = "rocket"))]
825# {
826use rocket::{FromForm, get};
827
828use validators::prelude::*;
829
830#[derive(Debug, Validator)]
831#[validator(number(range(Outside(max = 0))))]
832pub struct NonZeroNumber(f64);
833
834#[derive(Debug, FromForm)]
835struct User {
836    id:   i32,
837    // number: Result<NonZeroNumber, validators::errors::NumberError>, // compile error
838    number: validators::Result<NonZeroNumber, validators::errors::NumberError>,
839}
840
841#[get("/?<user..>")]
842fn index(user: User) -> String {
843    format!("{:?}", user)
844}
845# }
846```
847*/
848
849#![cfg_attr(not(feature = "std"), no_std)]
850#![cfg_attr(docsrs, feature(doc_auto_cfg))]
851
852extern crate alloc;
853
854#[cfg(feature = "byte-unit")]
855pub extern crate byte_unit;
856extern crate core;
857#[cfg(feature = "data-encoding")]
858pub extern crate data_encoding;
859#[cfg(feature = "idna")]
860pub extern crate idna;
861#[cfg(feature = "phonenumber")]
862pub extern crate phonenumber;
863#[cfg(feature = "regex-dep")]
864pub extern crate regex_dep as regex;
865#[cfg(feature = "rocket")]
866pub extern crate rocket;
867#[cfg(feature = "semver-dep")]
868pub extern crate semver_dep as semver;
869#[cfg(feature = "serde")]
870pub extern crate serde;
871#[cfg(feature = "serde_json")]
872pub extern crate serde_json;
873#[cfg(feature = "str-utils")]
874pub extern crate str_utils;
875#[cfg(feature = "url-dep")]
876pub extern crate url_dep as url;
877
878/// Errors from validators.
879pub mod errors;
880/// Functions with validators.
881pub mod functions;
882/// Models with validators.
883pub mod models;
884#[doc(hidden)]
885#[cfg(feature = "test")]
886pub mod test;
887/// Module of traits.
888pub mod traits;
889
890mod result;
891
892pub use result::*;
893#[cfg(feature = "derive")]
894pub use validators_derive::Validator;
895
896/**
897A convenience module appropriate for glob imports.
898
899```rust
900use validators::prelude::*;
901```
902 */
903pub mod prelude {
904    #[doc(hidden)]
905    pub mod validators_prelude {
906        pub use alloc::{borrow::Cow, format, string::String, vec::Vec};
907
908        #[cfg(feature = "byte-unit")]
909        pub use crate::byte_unit;
910        #[cfg(feature = "data-encoding")]
911        pub use crate::data_encoding;
912        pub use crate::errors::*;
913        #[cfg(feature = "idna")]
914        pub use crate::idna;
915        #[cfg(feature = "phonenumber")]
916        pub use crate::phonenumber;
917        #[cfg(feature = "regex")]
918        pub use crate::regex;
919        #[cfg(feature = "rocket")]
920        pub use crate::rocket;
921        #[cfg(feature = "semver-dep")]
922        pub use crate::semver;
923        #[cfg(feature = "serde")]
924        pub use crate::serde;
925        #[cfg(feature = "serde_json")]
926        pub use crate::serde_json;
927        #[cfg(feature = "str-utils")]
928        pub use crate::str_utils;
929        #[cfg(feature = "test")]
930        pub use crate::test::*;
931        #[cfg(feature = "url")]
932        pub use crate::url;
933        #[allow(unused_imports)]
934        pub use crate::{functions::*, models::*};
935    }
936
937    pub use crate::traits::*;
938    #[cfg(feature = "derive")]
939    pub use crate::Validator;
940}