1use crate::schemasync::mockmake::format::Format;
2use derive_more::From;
3use ordered_float::OrderedFloat;
4use proc_macro2::TokenStream;
5use quote::{ToTokens, quote};
6use serde::{Deserialize, Serialize};
7use tracing::{debug, trace};
8use try_from_expr::TryFromExpr;
9
10#[derive(Debug, Clone, PartialEq, From, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
11pub enum Validator {
12 StringValidator(StringValidator),
13 NumberValidator(NumberValidator),
14 ArrayValidator(ArrayValidator),
15 DateValidator(DateValidator),
16 BigIntValidator(BigIntValidator),
17 BigDecimalValidator(BigDecimalValidator),
18 DurationValidator(DurationValidator),
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
23pub enum StringValidator {
24 String,
26
27 Alpha,
29
30 Alphanumeric,
32
33 Base64,
35
36 Base64Url,
38
39 Capitalize,
41
42 CapitalizePreformatted,
44
45 CreditCard,
47
48 Date,
50
51 DateEpoch,
53
54 DateEpochParse,
56
57 DateIso,
59
60 DateIsoParse,
62
63 DateParse,
65
66 Digits,
68
69 Email,
71
72 Hex,
74
75 Integer,
77
78 IntegerParse,
80
81 Ip,
83
84 IpV4,
86
87 IpV6,
89
90 Json,
92
93 JsonParse,
95
96 Lower,
98
99 LowerPreformatted,
101
102 Normalize,
104
105 NormalizeNFC,
107
108 NormalizeNFCPreformatted,
110
111 NormalizeNFD,
113
114 NormalizeNFDPreformatted,
116
117 NormalizeNFKC,
119
120 NormalizeNFKCPreformatted,
122
123 NormalizeNFKD,
125
126 NormalizeNFKDPreformatted,
128
129 Numeric,
131
132 NumericParse,
134
135 Regex,
137
138 Semver,
140
141 Trim,
143
144 TrimPreformatted,
146
147 Upper,
149
150 UpperPreformatted,
152
153 Url,
155
156 UrlParse,
158
159 Uuid,
161
162 UuidV1,
164
165 UuidV2,
167
168 UuidV3,
170
171 UuidV4,
173
174 UuidV5,
176
177 UuidV6,
179
180 UuidV7,
182
183 UuidV8,
185
186 Literal(String),
187
188 StringEmbedded(String),
189
190 RegexLiteral(Format),
191
192 Length(String),
193
194 MinLength(usize),
196
197 MaxLength(usize),
199
200 NonEmpty,
202
203 StartsWith(String),
205
206 EndsWith(String),
208
209 Includes(String),
211
212 Trimmed,
214
215 Lowercased,
217
218 Uppercased,
220
221 Capitalized,
223
224 Uncapitalized,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
229pub enum NumberValidator {
230 GreaterThan(OrderedFloat<f64>),
232
233 GreaterThanOrEqualTo(OrderedFloat<f64>),
235
236 LessThan(OrderedFloat<f64>),
238
239 LessThanOrEqualTo(OrderedFloat<f64>),
241
242 Between(OrderedFloat<f64>, OrderedFloat<f64>),
244
245 Int,
247
248 NonNaN,
250
251 Finite,
253
254 Positive,
256
257 NonNegative,
259
260 Negative,
262
263 NonPositive,
265
266 MultipleOf(OrderedFloat<f64>),
268
269 Uint8,
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
275pub enum ArrayValidator {
276 MinItems(usize),
278
279 MaxItems(usize),
281
282 ItemsCount(usize),
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
288pub enum DateValidator {
289 ValidDate,
291
292 GreaterThanDate(String),
294
295 GreaterThanOrEqualToDate(String),
297
298 LessThanDate(String),
300
301 LessThanOrEqualToDate(String),
303
304 BetweenDate(String, String),
306}
307
308#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
310pub enum BigIntValidator {
311 GreaterThanBigInt(String),
313
314 GreaterThanOrEqualToBigInt(String),
316
317 LessThanBigInt(String),
319
320 LessThanOrEqualToBigInt(String),
322
323 BetweenBigInt(String, String),
325
326 PositiveBigInt,
328
329 NonNegativeBigInt,
331
332 NegativeBigInt,
334
335 NonPositiveBigInt,
337}
338
339#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
341pub enum BigDecimalValidator {
342 GreaterThanBigDecimal(String),
344
345 GreaterThanOrEqualToBigDecimal(String),
347
348 LessThanBigDecimal(String),
350
351 LessThanOrEqualToBigDecimal(String),
353
354 BetweenBigDecimal(String, String),
356
357 PositiveBigDecimal,
359
360 NonNegativeBigDecimal,
362
363 NegativeBigDecimal,
365
366 NonPositiveBigDecimal,
368}
369
370#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
372pub enum DurationValidator {
373 GreaterThanDuration(String),
375
376 GreaterThanOrEqualToDuration(String),
378
379 LessThanDuration(String),
381
382 LessThanOrEqualToDuration(String),
384
385 BetweenDuration(String, String),
387}
388
389impl Validator {
390 pub fn get_validation_logic_tokens(&self, value_ident: &str) -> TokenStream {
393 debug!(validator_type = ?self, value_ident = %value_ident, "Generating validation logic tokens");
394 trace!("Validator details: {:?}", self);
395 let value = syn::Ident::new(value_ident, proc_macro2::Span::call_site());
396
397 match self {
398 Validator::StringValidator(string_validator) => match string_validator {
400 StringValidator::String => quote! {
401 },
403 StringValidator::Alpha => quote! {
404 if !#value.chars().all(|c| c.is_alphabetic()) {
405 return Err(serde::de::Error::custom("value must contain only alphabetic characters"));
406 }
407 },
408 StringValidator::Alphanumeric => quote! {
409 if !#value.chars().all(|c| c.is_alphanumeric()) {
410 return Err(serde::de::Error::custom("value must contain only alphanumeric characters"));
411 }
412 },
413 StringValidator::Base64 => quote! {
414 use base64::{Engine as _, engine::general_purpose};
415 if general_purpose::STANDARD.decode(&#value).is_err() {
416 return Err(serde::de::Error::custom("invalid base64 encoding"));
417 }
418 },
419 StringValidator::Base64Url => quote! {
420 use base64::{Engine as _, engine::general_purpose};
421 if general_purpose::URL_SAFE.decode(&#value).is_err() {
422 return Err(serde::de::Error::custom("invalid base64url encoding"));
423 }
424 },
425 StringValidator::Capitalize => quote! {
426 let #value = {
428 let mut chars = &#value.chars();
429 match chars.next() {
430 None => String::new(),
431 Some(first) => first.to_uppercase().collect::<String>() + &chars.as_str().to_lowercase(),
432 }
433 };
434 },
435 StringValidator::CapitalizePreformatted => quote! {
436 if #value.is_empty() {
437 return Err(serde::de::Error::custom("value cannot be empty"));
438 }
439 match #value.chars().next() {
440 Some(first_char) if !first_char.is_uppercase() => {
441 return Err(serde::de::Error::custom("value must be capitalized"));
442 }
443 None => {
444 return Err(serde::de::Error::custom("value cannot be empty"));
445 }
446 _ => {}
447 }
448 },
449 StringValidator::CreditCard => quote! {
450 let digits: Vec<u32> = &#value.chars()
452 .filter(|c| c.is_digit(10))
453 .map(|c| c.to_digit(10).unwrap())
454 .collect();
455
456 if digits.len() < 13 || digits.len() > 19 {
457 return Err(serde::de::Error::custom("invalid credit card number length"));
458 }
459
460 let mut sum = 0;
461 let parity = digits.len() % 2;
462 for (i, digit) in digits.iter().enumerate() {
463 let mut digit = *digit;
464 if i % 2 != parity {
465 digit *= 2;
466 if digit > 9 {
467 digit -= 9;
468 }
469 }
470 sum += digit;
471 }
472
473 if sum % 10 != 0 {
474 return Err(serde::de::Error::custom("invalid credit card number"));
475 }
476 },
477 StringValidator::Date => quote! {
478 if chrono::NaiveDate::parse_from_str(&#value, "%Y-%m-%d").is_err() {
480 return Err(serde::de::Error::custom("invalid date format"));
481 }
482 },
483 StringValidator::DateEpoch => quote! {
484 if #value.parse::<i64>().is_err() {
485 return Err(serde::de::Error::custom("invalid epoch timestamp"));
486 }
487 },
488 StringValidator::DateEpochParse => quote! {
489 let timestamp = &#value.parse::<i64>()
491 .map_err(|_| serde::de::Error::custom("invalid epoch timestamp"))?;
492 let #value = chrono::NaiveDateTime::from_timestamp_opt(timestamp, 0)
493 .ok_or_else(|| serde::de::Error::custom("invalid timestamp"))?;
494 },
495 StringValidator::DateIso => quote! {
496 if chrono::DateTime::<chrono::Utc>::parse_from_rfc3339(&#value).is_err() {
497 return Err(serde::de::Error::custom("invalid ISO 8601 date"));
498 }
499 },
500 StringValidator::DateIsoParse => quote! {
501 let #value = chrono::DateTime::<chrono::Utc>::parse_from_rfc3339(&#value)
502 .map_err(|_| serde::de::Error::custom("invalid ISO 8601 date"))?;
503 },
504 StringValidator::DateParse => quote! {
505 let #value = chrono::NaiveDate::parse_from_str(&#value, "%Y-%m-%d")
507 .map_err(|_| serde::de::Error::custom("invalid date format"))?;
508 },
509 StringValidator::Digits => quote! {
510 if !#value.chars().all(|c| c.is_digit(10)) {
511 return Err(serde::de::Error::custom("value must contain only digits"));
512 }
513 },
514 StringValidator::Email => quote! {
515 let parts: Vec<&str> = #value.split('@').collect();
517 if parts.len() != 2 {
518 return Err(serde::de::Error::custom("invalid email format"));
519 }
520 if parts[0].is_empty() || parts[1].is_empty() {
521 return Err(serde::de::Error::custom("invalid email format"));
522 }
523 if !parts[1].contains('.') {
524 return Err(serde::de::Error::custom("invalid email domain"));
525 }
526 },
527 StringValidator::Hex => quote! {
528 if !#value.chars().all(|c| c.is_ascii_hexdigit()) {
529 return Err(serde::de::Error::custom("value must contain only hexadecimal characters"));
530 }
531 },
532 StringValidator::Integer => quote! {
533 if #value.parse::<i64>().is_err() {
534 return Err(serde::de::Error::custom("value must be a valid integer"));
535 }
536 },
537 StringValidator::IntegerParse => quote! {
538 let #value = &#value.parse::<i64>()
539 .map_err(|_| serde::de::Error::custom("invalid integer"))?;
540 },
541 StringValidator::Ip => quote! {
542 if #value.parse::<std::net::IpAddr>().is_err() {
543 return Err(serde::de::Error::custom("invalid IP address"));
544 }
545 },
546 StringValidator::IpV4 => quote! {
547 if #value.parse::<std::net::Ipv4Addr>().is_err() {
548 return Err(serde::de::Error::custom("invalid IPv4 address"));
549 }
550 },
551 StringValidator::IpV6 => quote! {
552 if #value.parse::<std::net::Ipv6Addr>().is_err() {
553 return Err(serde::de::Error::custom("invalid IPv6 address"));
554 }
555 },
556 StringValidator::Json => quote! {
557 if serde_json::from_str::<serde_json::Value>(&#value).is_err() {
558 return Err(serde::de::Error::custom("invalid JSON"));
559 }
560 },
561 StringValidator::JsonParse => quote! {
562 let #value = serde_json::from_str::<serde_json::Value>(&#value)
563 .map_err(|_| serde::de::Error::custom("invalid JSON"))?;
564 },
565 StringValidator::Lower => quote! {
566 let #value = &#value.to_lowercase();
567 },
568 StringValidator::LowerPreformatted => quote! {
569 if #value.chars().any(|c| c.is_alphabetic() && !c.is_lowercase()) {
570 return Err(serde::de::Error::custom("value must be lowercase"));
571 }
572 },
573 StringValidator::Normalize => quote! {
574 use unicode_normalization::UnicodeNormalization;
575 let #value = &#value.nfc().collect::<String>();
576 },
577 StringValidator::NormalizeNFC => quote! {
578 use unicode_normalization::UnicodeNormalization;
579 let #value = &#value.nfc().collect::<String>();
580 },
581 StringValidator::NormalizeNFCPreformatted => quote! {
582 use unicode_normalization::{UnicodeNormalization, is_nfc};
583 if !is_nfc(&#value) {
584 return Err(serde::de::Error::custom("value must be NFC normalized"));
585 }
586 },
587 StringValidator::NormalizeNFD => quote! {
588 use unicode_normalization::UnicodeNormalization;
589 let #value = &#value.nfd().collect::<String>();
590 },
591 StringValidator::NormalizeNFDPreformatted => quote! {
592 use unicode_normalization::{UnicodeNormalization, is_nfd};
593 if !is_nfd(&#value) {
594 return Err(serde::de::Error::custom("value must be NFD normalized"));
595 }
596 },
597 StringValidator::NormalizeNFKC => quote! {
598 use unicode_normalization::UnicodeNormalization;
599 let #value = &#value.nfkc().collect::<String>();
600 },
601 StringValidator::NormalizeNFKCPreformatted => quote! {
602 use unicode_normalization::{UnicodeNormalization, is_nfkc};
603 if !is_nfkc(&#value) {
604 return Err(serde::de::Error::custom("value must be NFKC normalized"));
605 }
606 },
607 StringValidator::NormalizeNFKD => quote! {
608 use unicode_normalization::UnicodeNormalization;
609 let #value = &#value.nfkd().collect::<String>();
610 },
611 StringValidator::NormalizeNFKDPreformatted => quote! {
612 use unicode_normalization::{UnicodeNormalization, is_nfkd};
613 if !is_nfkd(&#value) {
614 return Err(serde::de::Error::custom("value must be NFKD normalized"));
615 }
616 },
617 StringValidator::Numeric => quote! {
618 if #value.parse::<f64>().is_err() {
619 return Err(serde::de::Error::custom("value must be numeric"));
620 }
621 },
622 StringValidator::NumericParse => quote! {
623 let #value = &#value.parse::<f64>()
624 .map_err(|_| serde::de::Error::custom("invalid numeric value"))?;
625 },
626 StringValidator::Regex => quote! {
627 },
630 StringValidator::Semver => quote! {
631 if semver::Version::parse(&#value).is_err() {
632 return Err(serde::de::Error::custom("invalid semantic version"));
633 }
634 },
635 StringValidator::Trim => quote! {
636 let #value = &#value.trim().to_string();
637 },
638 StringValidator::TrimPreformatted => quote! {
639 if &#value != &#value.trim() {
640 return Err(serde::de::Error::custom("value must be trimmed"));
641 }
642 },
643 StringValidator::Upper => quote! {
644 let #value = &#value.to_uppercase();
645 },
646 StringValidator::UpperPreformatted => quote! {
647 if #value.chars().any(|c| c.is_alphabetic() && !c.is_uppercase()) {
648 return Err(serde::de::Error::custom("value must be uppercase"));
649 }
650 },
651 StringValidator::Url => quote! {
652 if url::Url::parse(&#value).is_err() {
653 return Err(serde::de::Error::custom("invalid URL"));
654 }
655 },
656 StringValidator::UrlParse => quote! {
657 let #value = url::Url::parse(&#value)
658 .map_err(|_| serde::de::Error::custom("invalid URL"))?;
659 },
660 StringValidator::Uuid => quote! {
661 if uuid::Uuid::parse_str(&#value).is_err() {
662 return Err(serde::de::Error::custom("invalid UUID"));
663 }
664 },
665 StringValidator::UuidV1 => quote! {
666 let uuid = uuid::Uuid::parse_str(&#value)
667 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
668 if uuid.get_version() != Some(uuid::Version::Mac) {
669 return Err(serde::de::Error::custom("UUID must be version 1"));
670 }
671 },
672 StringValidator::UuidV2 => quote! {
673 let uuid = uuid::Uuid::parse_str(&#value)
674 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
675 if uuid.get_version() != Some(uuid::Version::Dce) {
676 return Err(serde::de::Error::custom("UUID must be version 2"));
677 }
678 },
679 StringValidator::UuidV3 => quote! {
680 let uuid = uuid::Uuid::parse_str(&#value)
681 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
682 if uuid.get_version() != Some(uuid::Version::Md5) {
683 return Err(serde::de::Error::custom("UUID must be version 3"));
684 }
685 },
686 StringValidator::UuidV4 => quote! {
687 let uuid = uuid::Uuid::parse_str(&#value)
688 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
689 if uuid.get_version() != Some(uuid::Version::Random) {
690 return Err(serde::de::Error::custom("UUID must be version 4"));
691 }
692 },
693 StringValidator::UuidV5 => quote! {
694 let uuid = uuid::Uuid::parse_str(&#value)
695 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
696 if uuid.get_version() != Some(uuid::Version::Sha1) {
697 return Err(serde::de::Error::custom("UUID must be version 5"));
698 }
699 },
700 StringValidator::UuidV6 => quote! {
701 let uuid = uuid::Uuid::parse_str(&#value)
702 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
703 if uuid.get_version() != Some(uuid::Version::SortMac) {
704 return Err(serde::de::Error::custom("UUID must be version 6"));
705 }
706 },
707 StringValidator::UuidV7 => quote! {
708 let uuid = uuid::Uuid::parse_str(&#value)
709 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
710 if uuid.get_version() != Some(uuid::Version::SortRand) {
711 return Err(serde::de::Error::custom("UUID must be version 7"));
712 }
713 },
714 StringValidator::UuidV8 => quote! {
715 let uuid = uuid::Uuid::parse_str(&#value)
716 .map_err(|_| serde::de::Error::custom("invalid UUID"))?;
717 if uuid.get_version() != Some(uuid::Version::Custom) {
718 return Err(serde::de::Error::custom("UUID must be version 8"));
719 }
720 },
721 StringValidator::Literal(literal) => {
722 quote! {
723 if #value != #literal {
724 return Err(serde::de::Error::custom(format!("value must be exactly '{}'", #literal)));
725 }
726 }
727 }
728 StringValidator::StringEmbedded(_embedded) => quote! {
729 },
731 StringValidator::RegexLiteral(format_variant) => {
732 let format_regex_string: String =
734 format_variant.to_owned().into_regex().to_string();
735 quote! {
736 {
737 static RE: once_cell::sync::Lazy<regex::Regex> = once_cell::sync::Lazy::new(|| {
738 regex::Regex::new(#format_regex_string).expect("Invalid regex pattern")
739 });
740
741 if !RE.is_match(&#value) {
742 return Err(serde::de::Error::custom("value does not match pattern"));
743 }
744 }
745 }
746 }
747 StringValidator::Length(len_str) => {
748 quote! {
749 let expected_len: usize = #len_str.parse()
750 .map_err(|_| serde::de::Error::custom("invalid length specification"))?;
751 if #value.len() != expected_len {
752 return Err(serde::de::Error::custom(format!("value must be exactly {} characters", expected_len)));
753 }
754 }
755 }
756 StringValidator::MinLength(min_len) => {
757 quote! {
758 if #value.len() < #min_len {
759 return Err(serde::de::Error::custom(format!("value must be at least {} characters", #min_len)));
760 }
761 }
762 }
763 StringValidator::MaxLength(max_len) => {
764 quote! {
765 if #value.len() > #max_len {
766 return Err(serde::de::Error::custom(format!("value must be at most {} characters", #max_len)));
767 }
768 }
769 }
770 StringValidator::NonEmpty => quote! {
771 if #value.is_empty() {
772 return Err(serde::de::Error::custom("value cannot be empty"));
773 }
774 },
775 StringValidator::StartsWith(prefix) => {
776 quote! {
777 if !#value.starts_with(#prefix) {
778 return Err(serde::de::Error::custom(format!("value must start with '{}'", #prefix)));
779 }
780 }
781 }
782 StringValidator::EndsWith(suffix) => {
783 quote! {
784 if !#value.ends_with(#suffix) {
785 return Err(serde::de::Error::custom(format!("value must end with '{}'", #suffix)));
786 }
787 }
788 }
789 StringValidator::Includes(substring) => {
790 quote! {
791 if !#value.contains(#substring) {
792 return Err(serde::de::Error::custom(format!("value must contain '{}'", #substring)));
793 }
794 }
795 }
796 StringValidator::Trimmed => quote! {
797 if #value != #value.trim() {
798 return Err(serde::de::Error::custom("value must not have leading or trailing whitespace"));
799 }
800 },
801 StringValidator::Lowercased => quote! {
802 if #value.chars().any(|c| c.is_alphabetic() && !c.is_lowercase()) {
803 return Err(serde::de::Error::custom("value must be entirely lowercase"));
804 }
805 },
806 StringValidator::Uppercased => quote! {
807 if #value.chars().any(|c| c.is_alphabetic() && !c.is_uppercase()) {
808 return Err(serde::de::Error::custom("value must be entirely uppercase"));
809 }
810 },
811 StringValidator::Capitalized => quote! {
812 let mut chars = #value.chars();
813 match chars.next() {
814 Some(first) if !first.is_uppercase() => {
815 return Err(serde::de::Error::custom("value must be capitalized"));
816 }
817 None => return Err(serde::de::Error::custom("value cannot be empty")),
818 _ => {}
819 }
820 if chars.any(|c| c.is_alphabetic() && !c.is_lowercase()) {
821 return Err(serde::de::Error::custom("value must be capitalized (only first letter uppercase)"));
822 }
823 },
824 StringValidator::Uncapitalized => quote! {
825 let mut chars = #value.chars();
826 match chars.next() {
827 Some(first) if !first.is_lowercase() => {
828 return Err(serde::de::Error::custom("value must be uncapitalized"));
829 }
830 None => return Err(serde::de::Error::custom("value cannot be empty")),
831 _ => {}
832 }
833 },
834 },
835
836 Validator::NumberValidator(number_validator) => match number_validator {
838 NumberValidator::GreaterThan(min) => {
839 let min_val = min.0;
840 quote! {
841 if (#value as f64) <= #min_val {
842 return Err(serde::de::Error::custom(format!("value must be greater than {}", #min_val)));
843 }
844 }
845 }
846 NumberValidator::GreaterThanOrEqualTo(min) => {
847 let min_val = min.0;
848 quote! {
849 if (#value as f64) < #min_val {
850 return Err(serde::de::Error::custom(format!("value must be greater than or equal to {}", #min_val)));
851 }
852 }
853 }
854 NumberValidator::LessThan(max) => {
855 let max_val = max.0;
856 quote! {
857 if (#value as f64) >= #max_val {
858 return Err(serde::de::Error::custom(format!("value must be less than {}", #max_val)));
859 }
860 }
861 }
862 NumberValidator::LessThanOrEqualTo(max) => {
863 let max_val = max.0;
864 quote! {
865 if (#value as f64) > #max_val {
866 return Err(serde::de::Error::custom(format!("value must be less than or equal to {}", #max_val)));
867 }
868 }
869 }
870 NumberValidator::Between(min, max) => {
871 let min_val = min.0;
872 let max_val = max.0;
873 quote! {
874 if (#value as f64) < #min_val || (#value as f64) > #max_val {
875 return Err(serde::de::Error::custom(format!("value must be between {} and {} (inclusive)", #min_val, #max_val)));
876 }
877 }
878 }
879 NumberValidator::Int => quote! {
880 if #value.fract() != 0.0 {
881 return Err(serde::de::Error::custom("value must be an integer"));
882 }
883 },
884 NumberValidator::NonNaN => quote! {
885 if #value.is_nan() {
886 return Err(serde::de::Error::custom("value cannot be NaN"));
887 }
888 },
889 NumberValidator::Positive => quote! {
890 if (#value as f64) <= 0.0 {
891 return Err(serde::de::Error::custom("value must be positive"));
892 }
893 },
894 NumberValidator::Negative => quote! {
895 if (#value as f64) >= 0.0 {
896 return Err(serde::de::Error::custom("value must be negative"));
897 }
898 },
899 NumberValidator::NonPositive => quote! {
900 if (#value as f64) > 0.0 {
901 return Err(serde::de::Error::custom("value must be non-positive"));
902 }
903 },
904 NumberValidator::NonNegative => quote! {
905 if (#value as f64) < 0.0 {
906 return Err(serde::de::Error::custom("value must be non-negative"));
907 }
908 },
909 NumberValidator::Finite => quote! {
910 if !#value.is_finite() {
911 return Err(serde::de::Error::custom("value must be finite"));
912 }
913 },
914 NumberValidator::MultipleOf(divisor) => {
915 let divisor_val = divisor.0;
916 quote! {
917 if (#value % #divisor_val).abs() > f64::EPSILON {
918 return Err(serde::de::Error::custom(format!("value must be a multiple of {}", #divisor_val)));
919 }
920 }
921 }
922 NumberValidator::Uint8 => quote! {
923 if #value < 0.0 || #value > 255.0 || #value.fract() != 0.0 {
924 return Err(serde::de::Error::custom("value must be an 8-bit unsigned integer (0-255)"));
925 }
926 },
927 },
928
929 Validator::ArrayValidator(array_validator) => match array_validator {
931 ArrayValidator::MinItems(min_count) => {
932 quote! {
933 if #value.len() < #min_count {
934 return Err(serde::de::Error::custom(format!("array must have at least {} items", #min_count)));
935 }
936 }
937 }
938 ArrayValidator::MaxItems(max_count) => {
939 quote! {
940 if #value.len() > #max_count {
941 return Err(serde::de::Error::custom(format!("array must have at most {} items", #max_count)));
942 }
943 }
944 }
945 ArrayValidator::ItemsCount(exact_count) => {
946 quote! {
947 if #value.len() != #exact_count {
948 return Err(serde::de::Error::custom(format!("array must have exactly {} items", #exact_count)));
949 }
950 }
951 }
952 },
953
954 Validator::DateValidator(date_validator) => match date_validator {
956 DateValidator::ValidDate => quote! {
957 },
960 DateValidator::GreaterThanDate(date_str) => {
961 quote! {
962 let compare_date = chrono::NaiveDate::parse_from_str(#date_str, "%Y-%m-%d")
963 .map_err(|_| serde::de::Error::custom("invalid comparison date"))?;
964 if #value <= compare_date {
965 return Err(serde::de::Error::custom(format!("date must be after {}", #date_str)));
966 }
967 }
968 }
969 DateValidator::GreaterThanOrEqualToDate(date_str) => {
970 quote! {
971 let compare_date = chrono::NaiveDate::parse_from_str(#date_str, "%Y-%m-%d")
972 .map_err(|_| serde::de::Error::custom("invalid comparison date"))?;
973 if #value < compare_date {
974 return Err(serde::de::Error::custom(format!("date must be on or after {}", #date_str)));
975 }
976 }
977 }
978 DateValidator::LessThanDate(date_str) => {
979 quote! {
980 let compare_date = chrono::NaiveDate::parse_from_str(#date_str, "%Y-%m-%d")
981 .map_err(|_| serde::de::Error::custom("invalid comparison date"))?;
982 if #value >= compare_date {
983 return Err(serde::de::Error::custom(format!("date must be before {}", #date_str)));
984 }
985 }
986 }
987 DateValidator::LessThanOrEqualToDate(date_str) => {
988 quote! {
989 let compare_date = chrono::NaiveDate::parse_from_str(#date_str, "%Y-%m-%d")
990 .map_err(|_| serde::de::Error::custom("invalid comparison date"))?;
991 if #value > compare_date {
992 return Err(serde::de::Error::custom(format!("date must be on or before {}", #date_str)));
993 }
994 }
995 }
996 DateValidator::BetweenDate(start_str, end_str) => {
997 quote! {
998 let start_date = chrono::NaiveDate::parse_from_str(#start_str, "%Y-%m-%d")
999 .map_err(|_| serde::de::Error::custom("invalid start date"))?;
1000 let end_date = chrono::NaiveDate::parse_from_str(#end_str, "%Y-%m-%d")
1001 .map_err(|_| serde::de::Error::custom("invalid end date"))?;
1002 if #value < start_date || #value > end_date {
1003 return Err(serde::de::Error::custom(format!("date must be between {} and {}", #start_str, #end_str)));
1004 }
1005 }
1006 }
1007 },
1008
1009 Validator::BigIntValidator(bigint_validator) => match bigint_validator {
1011 BigIntValidator::GreaterThanBigInt(value_str) => {
1012 quote! {
1013 use num_bigint::BigInt;
1014 use std::str::FromStr;
1015 let compare_val = BigInt::from_str(#value_str)
1016 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1017 if #value <= compare_val {
1018 return Err(serde::de::Error::custom(format!("value must be greater than {}", #value_str)));
1019 }
1020 }
1021 }
1022 BigIntValidator::GreaterThanOrEqualToBigInt(value_str) => {
1023 quote! {
1024 use num_bigint::BigInt;
1025 use std::str::FromStr;
1026 let compare_val = BigInt::from_str(#value_str)
1027 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1028 if #value < compare_val {
1029 return Err(serde::de::Error::custom(format!("value must be greater than or equal to {}", #value_str)));
1030 }
1031 }
1032 }
1033 BigIntValidator::LessThanBigInt(value_str) => {
1034 quote! {
1035 use num_bigint::BigInt;
1036 use std::str::FromStr;
1037 let compare_val = BigInt::from_str(#value_str)
1038 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1039 if #value >= compare_val {
1040 return Err(serde::de::Error::custom(format!("value must be less than {}", #value_str)));
1041 }
1042 }
1043 }
1044 BigIntValidator::LessThanOrEqualToBigInt(value_str) => {
1045 quote! {
1046 use num_bigint::BigInt;
1047 use std::str::FromStr;
1048 let compare_val = BigInt::from_str(#value_str)
1049 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1050 if #value > compare_val {
1051 return Err(serde::de::Error::custom(format!("value must be less than or equal to {}", #value_str)));
1052 }
1053 }
1054 }
1055 BigIntValidator::BetweenBigInt(start_str, end_str) => {
1056 quote! {
1057 use num_bigint::BigInt;
1058 use std::str::FromStr;
1059 let start_val = BigInt::from_str(#start_str)
1060 .map_err(|_| serde::de::Error::custom("invalid start value"))?;
1061 let end_val = BigInt::from_str(#end_str)
1062 .map_err(|_| serde::de::Error::custom("invalid end value"))?;
1063 if #value < start_val || #value > end_val {
1064 return Err(serde::de::Error::custom(format!("value must be between {} and {}", #start_str, #end_str)));
1065 }
1066 }
1067 }
1068 BigIntValidator::PositiveBigInt => {
1069 quote! {
1070 use num_bigint::BigInt;
1071 use num_traits::Zero;
1072 if #value <= BigInt::zero() {
1073 return Err(serde::de::Error::custom("value must be positive"));
1074 }
1075 }
1076 }
1077 BigIntValidator::NonNegativeBigInt => {
1078 quote! {
1079 use num_bigint::BigInt;
1080 use num_traits::Zero;
1081 if #value < BigInt::zero() {
1082 return Err(serde::de::Error::custom("value must be non-negative"));
1083 }
1084 }
1085 }
1086 BigIntValidator::NegativeBigInt => {
1087 quote! {
1088 use num_bigint::BigInt;
1089 use num_traits::Zero;
1090 if #value >= BigInt::zero() {
1091 return Err(serde::de::Error::custom("value must be negative"));
1092 }
1093 }
1094 }
1095 BigIntValidator::NonPositiveBigInt => {
1096 quote! {
1097 use num_bigint::BigInt;
1098 use num_traits::Zero;
1099 if #value > BigInt::zero() {
1100 return Err(serde::de::Error::custom("value must be non-positive"));
1101 }
1102 }
1103 }
1104 },
1105
1106 Validator::BigDecimalValidator(bigdecimal_validator) => match bigdecimal_validator {
1108 BigDecimalValidator::GreaterThanBigDecimal(value_str) => {
1109 quote! {
1110 use bigdecimal::BigDecimal;
1111 use std::str::FromStr;
1112 let compare_val = BigDecimal::from_str(#value_str)
1113 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1114 if #value <= compare_val {
1115 return Err(serde::de::Error::custom(format!("value must be greater than {}", #value_str)));
1116 }
1117 }
1118 }
1119 BigDecimalValidator::GreaterThanOrEqualToBigDecimal(value_str) => {
1120 quote! {
1121 use bigdecimal::BigDecimal;
1122 use std::str::FromStr;
1123 let compare_val = BigDecimal::from_str(#value_str)
1124 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1125 if #value < compare_val {
1126 return Err(serde::de::Error::custom(format!("value must be greater than or equal to {}", #value_str)));
1127 }
1128 }
1129 }
1130 BigDecimalValidator::LessThanBigDecimal(value_str) => {
1131 quote! {
1132 use bigdecimal::BigDecimal;
1133 use std::str::FromStr;
1134 let compare_val = BigDecimal::from_str(#value_str)
1135 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1136 if #value >= compare_val {
1137 return Err(serde::de::Error::custom(format!("value must be less than {}", #value_str)));
1138 }
1139 }
1140 }
1141 BigDecimalValidator::LessThanOrEqualToBigDecimal(value_str) => {
1142 quote! {
1143 use bigdecimal::BigDecimal;
1144 use std::str::FromStr;
1145 let compare_val = BigDecimal::from_str(#value_str)
1146 .map_err(|_| serde::de::Error::custom("invalid comparison value"))?;
1147 if #value > compare_val {
1148 return Err(serde::de::Error::custom(format!("value must be less than or equal to {}", #value_str)));
1149 }
1150 }
1151 }
1152 BigDecimalValidator::BetweenBigDecimal(start_str, end_str) => {
1153 quote! {
1154 use bigdecimal::BigDecimal;
1155 use std::str::FromStr;
1156 let start_val = BigDecimal::from_str(#start_str)
1157 .map_err(|_| serde::de::Error::custom("invalid start value"))?;
1158 let end_val = BigDecimal::from_str(#end_str)
1159 .map_err(|_| serde::de::Error::custom("invalid end value"))?;
1160 if #value < start_val || #value > end_val {
1161 return Err(serde::de::Error::custom(format!("value must be between {} and {}", #start_str, #end_str)));
1162 }
1163 }
1164 }
1165 BigDecimalValidator::PositiveBigDecimal => {
1166 quote! {
1167 use bigdecimal::{BigDecimal, Zero};
1168 if #value <= BigDecimal::zero() {
1169 return Err(serde::de::Error::custom("value must be positive"));
1170 }
1171 }
1172 }
1173 BigDecimalValidator::NonNegativeBigDecimal => {
1174 quote! {
1175 use bigdecimal::{BigDecimal, Zero};
1176 if #value < BigDecimal::zero() {
1177 return Err(serde::de::Error::custom("value must be non-negative"));
1178 }
1179 }
1180 }
1181 BigDecimalValidator::NegativeBigDecimal => {
1182 quote! {
1183 use bigdecimal::{BigDecimal, Zero};
1184 if #value >= BigDecimal::zero() {
1185 return Err(serde::de::Error::custom("value must be negative"));
1186 }
1187 }
1188 }
1189 BigDecimalValidator::NonPositiveBigDecimal => {
1190 quote! {
1191 use bigdecimal::{BigDecimal, Zero};
1192 if #value > BigDecimal::zero() {
1193 return Err(serde::de::Error::custom("value must be non-positive"));
1194 }
1195 }
1196 }
1197 },
1198
1199 Validator::DurationValidator(duration_validator) => match duration_validator {
1201 DurationValidator::GreaterThanDuration(duration_str) => {
1202 quote! {
1203 let compare_duration = parse_duration(#duration_str)
1204 .map_err(|_| serde::de::Error::custom("invalid comparison duration"))?;
1205 if #value <= compare_duration {
1206 return Err(serde::de::Error::custom(format!("duration must be greater than {}", #duration_str)));
1207 }
1208 }
1209 }
1210 DurationValidator::GreaterThanOrEqualToDuration(duration_str) => {
1211 quote! {
1212 let compare_duration = parse_duration(#duration_str)
1213 .map_err(|_| serde::de::Error::custom("invalid comparison duration"))?;
1214 if #value < compare_duration {
1215 return Err(serde::de::Error::custom(format!("duration must be greater than or equal to {}", #duration_str)));
1216 }
1217 }
1218 }
1219 DurationValidator::LessThanDuration(duration_str) => {
1220 quote! {
1221 let compare_duration = parse_duration(#duration_str)
1222 .map_err(|_| serde::de::Error::custom("invalid comparison duration"))?;
1223 if #value >= compare_duration {
1224 return Err(serde::de::Error::custom(format!("duration must be less than {}", #duration_str)));
1225 }
1226 }
1227 }
1228 DurationValidator::LessThanOrEqualToDuration(duration_str) => {
1229 quote! {
1230 let compare_duration = parse_duration(#duration_str)
1231 .map_err(|_| serde::de::Error::custom("invalid comparison duration"))?;
1232 if #value > compare_duration {
1233 return Err(serde::de::Error::custom(format!("duration must be less than or equal to {}", #duration_str)));
1234 }
1235 }
1236 }
1237 DurationValidator::BetweenDuration(start_str, end_str) => {
1238 quote! {
1239 let start_duration = parse_duration(#start_str)
1240 .map_err(|_| serde::de::Error::custom("invalid start duration"))?;
1241 let end_duration = parse_duration(#end_str)
1242 .map_err(|_| serde::de::Error::custom("invalid end duration"))?;
1243 if #value < start_duration || #value > end_duration {
1244 return Err(serde::de::Error::custom(format!("duration must be between {} and {}", #start_str, #end_str)));
1245 }
1246 }
1247 }
1248 },
1249 }
1250 }
1251}
1252
1253impl ToTokens for Validator {
1254 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1255 let variant_tokens = match self {
1256 Validator::StringValidator(v) => {
1257 quote! { ::evenframe::validator::Validator::StringValidator(#v) }
1258 }
1259 Validator::NumberValidator(v) => {
1260 quote! { ::evenframe::validator::Validator::NumberValidator(#v) }
1261 }
1262 Validator::ArrayValidator(v) => {
1263 quote! { ::evenframe::validator::Validator::ArrayValidator(#v) }
1264 }
1265 Validator::DateValidator(v) => {
1266 quote! { ::evenframe::validator::Validator::DateValidator(#v) }
1267 }
1268 Validator::BigIntValidator(v) => {
1269 quote! { ::evenframe::validator::Validator::BigIntValidator(#v) }
1270 }
1271 Validator::BigDecimalValidator(v) => {
1272 quote! { ::evenframe::validator::Validator::BigDecimalValidator(#v) }
1273 }
1274 Validator::DurationValidator(v) => {
1275 quote! { ::evenframe::validator::Validator::DurationValidator(#v) }
1276 }
1277 };
1278 tokens.extend(variant_tokens);
1279 }
1280}
1281
1282impl ToTokens for StringValidator {
1283 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1284 let variant_tokens = match self {
1285 StringValidator::String => {
1286 quote! { ::evenframe::validator::StringValidator::String }
1287 }
1288 StringValidator::Alpha => {
1289 quote! { ::evenframe::validator::StringValidator::Alpha }
1290 }
1291 StringValidator::Alphanumeric => {
1292 quote! { ::evenframe::validator::StringValidator::Alphanumeric }
1293 }
1294 StringValidator::Base64 => {
1295 quote! { ::evenframe::validator::StringValidator::Base64 }
1296 }
1297 StringValidator::Base64Url => {
1298 quote! { ::evenframe::validator::StringValidator::Base64Url }
1299 }
1300 StringValidator::Capitalize => {
1301 quote! { ::evenframe::validator::StringValidator::Capitalize }
1302 }
1303 StringValidator::CapitalizePreformatted => {
1304 quote! { ::evenframe::validator::StringValidator::CapitalizePreformatted }
1305 }
1306 StringValidator::CreditCard => {
1307 quote! { ::evenframe::validator::StringValidator::CreditCard }
1308 }
1309 StringValidator::Date => {
1310 quote! { ::evenframe::validator::StringValidator::Date }
1311 }
1312 StringValidator::DateEpoch => {
1313 quote! { ::evenframe::validator::StringValidator::DateEpoch }
1314 }
1315 StringValidator::DateEpochParse => {
1316 quote! { ::evenframe::validator::StringValidator::DateEpochParse }
1317 }
1318 StringValidator::DateIso => {
1319 quote! { ::evenframe::validator::StringValidator::DateIso }
1320 }
1321 StringValidator::DateIsoParse => {
1322 quote! { ::evenframe::validator::StringValidator::DateIsoParse }
1323 }
1324 StringValidator::DateParse => {
1325 quote! { ::evenframe::validator::StringValidator::DateParse }
1326 }
1327 StringValidator::Digits => {
1328 quote! { ::evenframe::validator::StringValidator::Digits }
1329 }
1330 StringValidator::Email => {
1331 quote! { ::evenframe::validator::StringValidator::Email }
1332 }
1333 StringValidator::Hex => {
1334 quote! { ::evenframe::validator::StringValidator::Hex }
1335 }
1336 StringValidator::Integer => {
1337 quote! { ::evenframe::validator::StringValidator::Integer }
1338 }
1339 StringValidator::IntegerParse => {
1340 quote! { ::evenframe::validator::StringValidator::IntegerParse }
1341 }
1342 StringValidator::Ip => quote! { ::evenframe::validator::StringValidator::Ip },
1343 StringValidator::IpV4 => {
1344 quote! { ::evenframe::validator::StringValidator::IpV4 }
1345 }
1346 StringValidator::IpV6 => {
1347 quote! { ::evenframe::validator::StringValidator::IpV6 }
1348 }
1349 StringValidator::Json => {
1350 quote! { ::evenframe::validator::StringValidator::Json }
1351 }
1352 StringValidator::JsonParse => {
1353 quote! { ::evenframe::validator::StringValidator::JsonParse }
1354 }
1355 StringValidator::Lower => {
1356 quote! { ::evenframe::validator::StringValidator::Lower }
1357 }
1358 StringValidator::LowerPreformatted => {
1359 quote! { ::evenframe::validator::StringValidator::LowerPreformatted }
1360 }
1361 StringValidator::Normalize => {
1362 quote! { ::evenframe::validator::StringValidator::Normalize }
1363 }
1364 StringValidator::NormalizeNFC => {
1365 quote! { ::evenframe::validator::StringValidator::NormalizeNFC }
1366 }
1367 StringValidator::NormalizeNFCPreformatted => {
1368 quote! { ::evenframe::validator::StringValidator::NormalizeNFCPreformatted }
1369 }
1370 StringValidator::NormalizeNFD => {
1371 quote! { ::evenframe::validator::StringValidator::NormalizeNFD }
1372 }
1373 StringValidator::NormalizeNFDPreformatted => {
1374 quote! { ::evenframe::validator::StringValidator::NormalizeNFDPreformatted }
1375 }
1376 StringValidator::NormalizeNFKC => {
1377 quote! { ::evenframe::validator::StringValidator::NormalizeNFKC }
1378 }
1379 StringValidator::NormalizeNFKCPreformatted => {
1380 quote! { ::evenframe::validator::StringValidator::NormalizeNFKCPreformatted }
1381 }
1382 StringValidator::NormalizeNFKD => {
1383 quote! { ::evenframe::validator::StringValidator::NormalizeNFKD }
1384 }
1385 StringValidator::NormalizeNFKDPreformatted => {
1386 quote! { ::evenframe::validator::StringValidator::NormalizeNFKDPreformatted }
1387 }
1388 StringValidator::Numeric => {
1389 quote! { ::evenframe::validator::StringValidator::Numeric }
1390 }
1391 StringValidator::NumericParse => {
1392 quote! { ::evenframe::validator::StringValidator::NumericParse }
1393 }
1394 StringValidator::Regex => {
1395 quote! { ::evenframe::validator::StringValidator::Regex }
1396 }
1397 StringValidator::Semver => {
1398 quote! { ::evenframe::validator::StringValidator::Semver }
1399 }
1400 StringValidator::Trim => {
1401 quote! { ::evenframe::validator::StringValidator::Trim }
1402 }
1403 StringValidator::TrimPreformatted => {
1404 quote! { ::evenframe::validator::StringValidator::TrimPreformatted }
1405 }
1406 StringValidator::Upper => {
1407 quote! { ::evenframe::validator::StringValidator::Upper }
1408 }
1409 StringValidator::UpperPreformatted => {
1410 quote! { ::evenframe::validator::StringValidator::UpperPreformatted }
1411 }
1412 StringValidator::Url => {
1413 quote! { ::evenframe::validator::StringValidator::Url }
1414 }
1415 StringValidator::UrlParse => {
1416 quote! { ::evenframe::validator::StringValidator::UrlParse }
1417 }
1418 StringValidator::Uuid => {
1419 quote! { ::evenframe::validator::StringValidator::Uuid }
1420 }
1421 StringValidator::UuidV1 => {
1422 quote! { ::evenframe::validator::StringValidator::UuidV1 }
1423 }
1424 StringValidator::UuidV2 => {
1425 quote! { ::evenframe::validator::StringValidator::UuidV2 }
1426 }
1427 StringValidator::UuidV3 => {
1428 quote! { ::evenframe::validator::StringValidator::UuidV3 }
1429 }
1430 StringValidator::UuidV4 => {
1431 quote! { ::evenframe::validator::StringValidator::UuidV4 }
1432 }
1433 StringValidator::UuidV5 => {
1434 quote! { ::evenframe::validator::StringValidator::UuidV5 }
1435 }
1436 StringValidator::UuidV6 => {
1437 quote! { ::evenframe::validator::StringValidator::UuidV6 }
1438 }
1439 StringValidator::UuidV7 => {
1440 quote! { ::evenframe::validator::StringValidator::UuidV7 }
1441 }
1442 StringValidator::UuidV8 => {
1443 quote! { ::evenframe::validator::StringValidator::UuidV8 }
1444 }
1445 StringValidator::Literal(s) => {
1446 quote! { ::evenframe::validator::StringValidator::Literal(#s.to_string()) }
1447 }
1448 StringValidator::StringEmbedded(s) => {
1449 quote! { ::evenframe::validator::StringValidator::StringEmbedded(#s.to_string()) }
1450 }
1451 StringValidator::RegexLiteral(f) => {
1452 quote! { ::evenframe::validator::StringValidator::RegexLiteral(#f) }
1453 }
1454 StringValidator::Length(s) => {
1455 quote! { ::evenframe::validator::StringValidator::Length(#s.to_string()) }
1456 }
1457 StringValidator::MinLength(n) => {
1458 quote! { ::evenframe::validator::StringValidator::MinLength(#n) }
1459 }
1460 StringValidator::MaxLength(n) => {
1461 quote! { ::evenframe::validator::StringValidator::MaxLength(#n) }
1462 }
1463 StringValidator::NonEmpty => {
1464 quote! { ::evenframe::validator::StringValidator::NonEmpty }
1465 }
1466 StringValidator::StartsWith(s) => {
1467 quote! { ::evenframe::validator::StringValidator::StartsWith(#s.to_string()) }
1468 }
1469 StringValidator::EndsWith(s) => {
1470 quote! { ::evenframe::validator::StringValidator::EndsWith(#s.to_string()) }
1471 }
1472 StringValidator::Includes(s) => {
1473 quote! { ::evenframe::validator::StringValidator::Includes(#s.to_string()) }
1474 }
1475 StringValidator::Trimmed => {
1476 quote! { ::evenframe::validator::StringValidator::Trimmed }
1477 }
1478 StringValidator::Lowercased => {
1479 quote! { ::evenframe::validator::StringValidator::Lowercased }
1480 }
1481 StringValidator::Uppercased => {
1482 quote! { ::evenframe::validator::StringValidator::Uppercased }
1483 }
1484 StringValidator::Capitalized => {
1485 quote! { ::evenframe::validator::StringValidator::Capitalized }
1486 }
1487 StringValidator::Uncapitalized => {
1488 quote! { ::evenframe::validator::StringValidator::Uncapitalized }
1489 }
1490 };
1491 tokens.extend(variant_tokens);
1492 }
1493}
1494
1495impl ToTokens for NumberValidator {
1496 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1497 let variant_tokens = match self {
1498 NumberValidator::GreaterThan(v) => {
1499 let f = v.0;
1500 quote! { ::evenframe::validator::NumberValidator::GreaterThan(::ordered_float::OrderedFloat(#f)) }
1501 }
1502 NumberValidator::GreaterThanOrEqualTo(v) => {
1503 let f = v.0;
1504 quote! { ::evenframe::validator::NumberValidator::GreaterThanOrEqualTo(::ordered_float::OrderedFloat(#f)) }
1505 }
1506 NumberValidator::LessThan(v) => {
1507 let f = v.0;
1508 quote! { ::evenframe::validator::NumberValidator::LessThan(::ordered_float::OrderedFloat(#f)) }
1509 }
1510 NumberValidator::LessThanOrEqualTo(v) => {
1511 let f = v.0;
1512 quote! { ::evenframe::validator::NumberValidator::LessThanOrEqualTo(::ordered_float::OrderedFloat(#f)) }
1513 }
1514 NumberValidator::Between(start, end) => {
1515 let s = start.0;
1516 let e = end.0;
1517 quote! { ::evenframe::validator::NumberValidator::Between(::ordered_float::OrderedFloat(#s), ::ordered_float::OrderedFloat(#e)) }
1518 }
1519 NumberValidator::Int => {
1520 quote! { ::evenframe::validator::NumberValidator::Int }
1521 }
1522 NumberValidator::NonNaN => {
1523 quote! { ::evenframe::validator::NumberValidator::NonNaN }
1524 }
1525 NumberValidator::Positive => {
1526 quote! { ::evenframe::validator::NumberValidator::Positive }
1527 }
1528 NumberValidator::Negative => {
1529 quote! { ::evenframe::validator::NumberValidator::Negative }
1530 }
1531 NumberValidator::NonPositive => {
1532 quote! { ::evenframe::validator::NumberValidator::NonPositive }
1533 }
1534 NumberValidator::NonNegative => {
1535 quote! { ::evenframe::validator::NumberValidator::NonNegative }
1536 }
1537 NumberValidator::Finite => {
1538 quote! { ::evenframe::validator::NumberValidator::Finite }
1539 }
1540 NumberValidator::MultipleOf(v) => {
1541 let f = v.0;
1542 quote! { ::evenframe::validator::NumberValidator::MultipleOf(::ordered_float::OrderedFloat(#f)) }
1543 }
1544 NumberValidator::Uint8 => {
1545 quote! { ::evenframe::validator::NumberValidator::Uint8 }
1546 }
1547 };
1548 tokens.extend(variant_tokens);
1549 }
1550}
1551
1552impl ToTokens for ArrayValidator {
1553 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1554 let variant_tokens = match self {
1555 ArrayValidator::MinItems(n) => {
1556 quote! { ::evenframe::validator::ArrayValidator::MinItems(#n) }
1557 }
1558 ArrayValidator::MaxItems(n) => {
1559 quote! { ::evenframe::validator::ArrayValidator::MaxItems(#n) }
1560 }
1561 ArrayValidator::ItemsCount(n) => {
1562 quote! { ::evenframe::validator::ArrayValidator::ItemsCount(#n) }
1563 }
1564 };
1565 tokens.extend(variant_tokens);
1566 }
1567}
1568
1569impl ToTokens for DateValidator {
1570 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1571 let variant_tokens = match self {
1572 DateValidator::ValidDate => {
1573 quote! { ::evenframe::validator::DateValidator::ValidDate }
1574 }
1575 DateValidator::GreaterThanDate(s) => {
1576 quote! { ::evenframe::validator::DateValidator::GreaterThanDate(#s.to_string()) }
1577 }
1578 DateValidator::GreaterThanOrEqualToDate(s) => {
1579 quote! { ::evenframe::validator::DateValidator::GreaterThanOrEqualToDate(#s.to_string()) }
1580 }
1581 DateValidator::LessThanDate(s) => {
1582 quote! { ::evenframe::validator::DateValidator::LessThanDate(#s.to_string()) }
1583 }
1584 DateValidator::LessThanOrEqualToDate(s) => {
1585 quote! { ::evenframe::validator::DateValidator::LessThanOrEqualToDate(#s.to_string()) }
1586 }
1587 DateValidator::BetweenDate(start, end) => {
1588 quote! { ::evenframe::validator::DateValidator::BetweenDate(#start.to_string(), #end.to_string()) }
1589 }
1590 };
1591 tokens.extend(variant_tokens);
1592 }
1593}
1594
1595impl ToTokens for BigIntValidator {
1596 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1597 let variant_tokens = match self {
1598 BigIntValidator::GreaterThanBigInt(s) => {
1599 quote! { ::evenframe::validator::BigIntValidator::GreaterThanBigInt(#s.to_string()) }
1600 }
1601 BigIntValidator::GreaterThanOrEqualToBigInt(s) => {
1602 quote! { ::evenframe::validator::BigIntValidator::GreaterThanOrEqualToBigInt(#s.to_string()) }
1603 }
1604 BigIntValidator::LessThanBigInt(s) => {
1605 quote! { ::evenframe::validator::BigIntValidator::LessThanBigInt(#s.to_string()) }
1606 }
1607 BigIntValidator::LessThanOrEqualToBigInt(s) => {
1608 quote! { ::evenframe::validator::BigIntValidator::LessThanOrEqualToBigInt(#s.to_string()) }
1609 }
1610 BigIntValidator::BetweenBigInt(start, end) => {
1611 quote! { ::evenframe::validator::BigIntValidator::BetweenBigInt(#start.to_string(), #end.to_string()) }
1612 }
1613 BigIntValidator::PositiveBigInt => {
1614 quote! { ::evenframe::validator::BigIntValidator::PositiveBigInt }
1615 }
1616 BigIntValidator::NegativeBigInt => {
1617 quote! { ::evenframe::validator::BigIntValidator::NegativeBigInt }
1618 }
1619 BigIntValidator::NonPositiveBigInt => {
1620 quote! { ::evenframe::validator::BigIntValidator::NonPositiveBigInt }
1621 }
1622 BigIntValidator::NonNegativeBigInt => {
1623 quote! { ::evenframe::validator::BigIntValidator::NonNegativeBigInt }
1624 }
1625 };
1626 tokens.extend(variant_tokens);
1627 }
1628}
1629
1630impl ToTokens for BigDecimalValidator {
1631 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1632 let variant_tokens = match self {
1633 BigDecimalValidator::GreaterThanBigDecimal(s) => {
1634 quote! { ::evenframe::validator::BigDecimalValidator::GreaterThanBigDecimal(#s.to_string()) }
1635 }
1636 BigDecimalValidator::GreaterThanOrEqualToBigDecimal(s) => {
1637 quote! { ::evenframe::validator::BigDecimalValidator::GreaterThanOrEqualToBigDecimal(#s.to_string()) }
1638 }
1639 BigDecimalValidator::LessThanBigDecimal(s) => {
1640 quote! { ::evenframe::validator::BigDecimalValidator::LessThanBigDecimal(#s.to_string()) }
1641 }
1642 BigDecimalValidator::LessThanOrEqualToBigDecimal(s) => {
1643 quote! { ::evenframe::validator::BigDecimalValidator::LessThanOrEqualToBigDecimal(#s.to_string()) }
1644 }
1645 BigDecimalValidator::BetweenBigDecimal(start, end) => {
1646 quote! { ::evenframe::validator::BigDecimalValidator::BetweenBigDecimal(#start.to_string(), #end.to_string()) }
1647 }
1648 BigDecimalValidator::PositiveBigDecimal => {
1649 quote! { ::evenframe::validator::BigDecimalValidator::PositiveBigDecimal }
1650 }
1651 BigDecimalValidator::NegativeBigDecimal => {
1652 quote! { ::evenframe::validator::BigDecimalValidator::NegativeBigDecimal }
1653 }
1654 BigDecimalValidator::NonPositiveBigDecimal => {
1655 quote! { ::evenframe::validator::BigDecimalValidator::NonPositiveBigDecimal }
1656 }
1657 BigDecimalValidator::NonNegativeBigDecimal => {
1658 quote! { ::evenframe::validator::BigDecimalValidator::NonNegativeBigDecimal }
1659 }
1660 };
1661 tokens.extend(variant_tokens);
1662 }
1663}
1664
1665impl ToTokens for DurationValidator {
1666 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1667 let variant_tokens = match self {
1668 DurationValidator::GreaterThanDuration(s) => {
1669 quote! { ::evenframe::validator::DurationValidator::GreaterThanDuration(#s.to_string()) }
1670 }
1671 DurationValidator::GreaterThanOrEqualToDuration(s) => {
1672 quote! { ::evenframe::validator::DurationValidator::GreaterThanOrEqualToDuration(#s.to_string()) }
1673 }
1674 DurationValidator::LessThanDuration(s) => {
1675 quote! { ::evenframe::validator::DurationValidator::LessThanDuration(#s.to_string()) }
1676 }
1677 DurationValidator::LessThanOrEqualToDuration(s) => {
1678 quote! { ::evenframe::validator::DurationValidator::LessThanOrEqualToDuration(#s.to_string()) }
1679 }
1680 DurationValidator::BetweenDuration(start, end) => {
1681 quote! { ::evenframe::validator::DurationValidator::BetweenDuration(#start.to_string(), #end.to_string()) }
1682 }
1683 };
1684 tokens.extend(variant_tokens);
1685 }
1686}
1687
1688#[cfg(test)]
1689mod tests {
1690 use super::*;
1691 use ordered_float::OrderedFloat;
1692
1693 #[test]
1696 fn test_validator_from_string_validator() {
1697 let sv = StringValidator::Email;
1698 let v: Validator = sv.into();
1699 assert!(matches!(
1700 v,
1701 Validator::StringValidator(StringValidator::Email)
1702 ));
1703 }
1704
1705 #[test]
1706 fn test_validator_from_number_validator() {
1707 let nv = NumberValidator::Positive;
1708 let v: Validator = nv.into();
1709 assert!(matches!(
1710 v,
1711 Validator::NumberValidator(NumberValidator::Positive)
1712 ));
1713 }
1714
1715 #[test]
1716 fn test_validator_from_array_validator() {
1717 let av = ArrayValidator::MinItems(5);
1718 let v: Validator = av.into();
1719 assert!(matches!(
1720 v,
1721 Validator::ArrayValidator(ArrayValidator::MinItems(5))
1722 ));
1723 }
1724
1725 #[test]
1726 fn test_validator_from_date_validator() {
1727 let dv = DateValidator::ValidDate;
1728 let v: Validator = dv.into();
1729 assert!(matches!(
1730 v,
1731 Validator::DateValidator(DateValidator::ValidDate)
1732 ));
1733 }
1734
1735 #[test]
1736 fn test_validator_from_bigint_validator() {
1737 let bv = BigIntValidator::PositiveBigInt;
1738 let v: Validator = bv.into();
1739 assert!(matches!(
1740 v,
1741 Validator::BigIntValidator(BigIntValidator::PositiveBigInt)
1742 ));
1743 }
1744
1745 #[test]
1746 fn test_validator_from_bigdecimal_validator() {
1747 let bv = BigDecimalValidator::PositiveBigDecimal;
1748 let v: Validator = bv.into();
1749 assert!(matches!(
1750 v,
1751 Validator::BigDecimalValidator(BigDecimalValidator::PositiveBigDecimal)
1752 ));
1753 }
1754
1755 #[test]
1756 fn test_validator_from_duration_validator() {
1757 let dv = DurationValidator::GreaterThanDuration("1h".to_string());
1758 let v: Validator = dv.into();
1759 assert!(matches!(
1760 v,
1761 Validator::DurationValidator(DurationValidator::GreaterThanDuration(_))
1762 ));
1763 }
1764
1765 #[test]
1768 fn test_string_validator_equality() {
1769 assert_eq!(StringValidator::Email, StringValidator::Email);
1770 assert_ne!(StringValidator::Email, StringValidator::Url);
1771 }
1772
1773 #[test]
1774 fn test_string_validator_with_parameters() {
1775 let v1 = StringValidator::MinLength(5);
1776 let v2 = StringValidator::MinLength(5);
1777 let v3 = StringValidator::MinLength(10);
1778
1779 assert_eq!(v1, v2);
1780 assert_ne!(v1, v3);
1781 }
1782
1783 #[test]
1784 fn test_string_validator_literal() {
1785 let v = StringValidator::Literal("hello".to_string());
1786 assert!(matches!(v, StringValidator::Literal(s) if s == "hello"));
1787 }
1788
1789 #[test]
1790 fn test_string_validator_starts_with() {
1791 let v = StringValidator::StartsWith("prefix".to_string());
1792 assert!(matches!(v, StringValidator::StartsWith(s) if s == "prefix"));
1793 }
1794
1795 #[test]
1796 fn test_string_validator_ends_with() {
1797 let v = StringValidator::EndsWith("suffix".to_string());
1798 assert!(matches!(v, StringValidator::EndsWith(s) if s == "suffix"));
1799 }
1800
1801 #[test]
1802 fn test_string_validator_includes() {
1803 let v = StringValidator::Includes("substring".to_string());
1804 assert!(matches!(v, StringValidator::Includes(s) if s == "substring"));
1805 }
1806
1807 #[test]
1808 fn test_string_validator_hash() {
1809 use std::collections::HashSet;
1810 let mut set = HashSet::new();
1811 set.insert(StringValidator::Email);
1812 set.insert(StringValidator::Url);
1813 set.insert(StringValidator::Email); assert_eq!(set.len(), 2);
1815 }
1816
1817 #[test]
1818 fn test_string_validator_clone() {
1819 let v = StringValidator::MinLength(10);
1820 let cloned = v.clone();
1821 assert_eq!(v, cloned);
1822 }
1823
1824 #[test]
1827 fn test_number_validator_greater_than() {
1828 let v = NumberValidator::GreaterThan(OrderedFloat(5.0));
1829 assert!(matches!(v, NumberValidator::GreaterThan(OrderedFloat(x)) if x == 5.0));
1830 }
1831
1832 #[test]
1833 fn test_number_validator_less_than() {
1834 let v = NumberValidator::LessThan(OrderedFloat(10.0));
1835 assert!(matches!(v, NumberValidator::LessThan(OrderedFloat(x)) if x == 10.0));
1836 }
1837
1838 #[test]
1839 fn test_number_validator_between() {
1840 let v = NumberValidator::Between(OrderedFloat(1.0), OrderedFloat(10.0));
1841 assert!(
1842 matches!(v, NumberValidator::Between(OrderedFloat(a), OrderedFloat(b)) if a == 1.0 && b == 10.0)
1843 );
1844 }
1845
1846 #[test]
1847 fn test_number_validator_multiple_of() {
1848 let v = NumberValidator::MultipleOf(OrderedFloat(3.0));
1849 assert!(matches!(v, NumberValidator::MultipleOf(OrderedFloat(x)) if x == 3.0));
1850 }
1851
1852 #[test]
1853 fn test_number_validator_equality() {
1854 assert_eq!(NumberValidator::Positive, NumberValidator::Positive);
1855 assert_ne!(NumberValidator::Positive, NumberValidator::Negative);
1856 }
1857
1858 #[test]
1859 fn test_number_validator_int() {
1860 let v = NumberValidator::Int;
1861 assert!(matches!(v, NumberValidator::Int));
1862 }
1863
1864 #[test]
1865 fn test_number_validator_finite() {
1866 let v = NumberValidator::Finite;
1867 assert!(matches!(v, NumberValidator::Finite));
1868 }
1869
1870 #[test]
1871 fn test_number_validator_uint8() {
1872 let v = NumberValidator::Uint8;
1873 assert!(matches!(v, NumberValidator::Uint8));
1874 }
1875
1876 #[test]
1879 fn test_array_validator_min_items() {
1880 let v = ArrayValidator::MinItems(3);
1881 assert!(matches!(v, ArrayValidator::MinItems(3)));
1882 }
1883
1884 #[test]
1885 fn test_array_validator_max_items() {
1886 let v = ArrayValidator::MaxItems(10);
1887 assert!(matches!(v, ArrayValidator::MaxItems(10)));
1888 }
1889
1890 #[test]
1891 fn test_array_validator_items_count() {
1892 let v = ArrayValidator::ItemsCount(5);
1893 assert!(matches!(v, ArrayValidator::ItemsCount(5)));
1894 }
1895
1896 #[test]
1897 fn test_array_validator_equality() {
1898 assert_eq!(ArrayValidator::MinItems(5), ArrayValidator::MinItems(5));
1899 assert_ne!(ArrayValidator::MinItems(5), ArrayValidator::MinItems(10));
1900 assert_ne!(ArrayValidator::MinItems(5), ArrayValidator::MaxItems(5));
1901 }
1902
1903 #[test]
1906 fn test_date_validator_valid_date() {
1907 let v = DateValidator::ValidDate;
1908 assert!(matches!(v, DateValidator::ValidDate));
1909 }
1910
1911 #[test]
1912 fn test_date_validator_greater_than() {
1913 let v = DateValidator::GreaterThanDate("2024-01-01".to_string());
1914 assert!(matches!(v, DateValidator::GreaterThanDate(s) if s == "2024-01-01"));
1915 }
1916
1917 #[test]
1918 fn test_date_validator_between() {
1919 let v = DateValidator::BetweenDate("2024-01-01".to_string(), "2024-12-31".to_string());
1920 assert!(
1921 matches!(v, DateValidator::BetweenDate(start, end) if start == "2024-01-01" && end == "2024-12-31")
1922 );
1923 }
1924
1925 #[test]
1928 fn test_bigint_validator_greater_than() {
1929 let v = BigIntValidator::GreaterThanBigInt("1000000000000".to_string());
1930 assert!(matches!(v, BigIntValidator::GreaterThanBigInt(s) if s == "1000000000000"));
1931 }
1932
1933 #[test]
1934 fn test_bigint_validator_positive() {
1935 let v = BigIntValidator::PositiveBigInt;
1936 assert!(matches!(v, BigIntValidator::PositiveBigInt));
1937 }
1938
1939 #[test]
1940 fn test_bigint_validator_between() {
1941 let v = BigIntValidator::BetweenBigInt("0".to_string(), "100".to_string());
1942 assert!(
1943 matches!(v, BigIntValidator::BetweenBigInt(start, end) if start == "0" && end == "100")
1944 );
1945 }
1946
1947 #[test]
1950 fn test_bigdecimal_validator_greater_than() {
1951 let v = BigDecimalValidator::GreaterThanBigDecimal("0.001".to_string());
1952 assert!(matches!(v, BigDecimalValidator::GreaterThanBigDecimal(s) if s == "0.001"));
1953 }
1954
1955 #[test]
1956 fn test_bigdecimal_validator_positive() {
1957 let v = BigDecimalValidator::PositiveBigDecimal;
1958 assert!(matches!(v, BigDecimalValidator::PositiveBigDecimal));
1959 }
1960
1961 #[test]
1964 fn test_duration_validator_greater_than() {
1965 let v = DurationValidator::GreaterThanDuration("1h".to_string());
1966 assert!(matches!(v, DurationValidator::GreaterThanDuration(s) if s == "1h"));
1967 }
1968
1969 #[test]
1970 fn test_duration_validator_between() {
1971 let v = DurationValidator::BetweenDuration("1m".to_string(), "1h".to_string());
1972 assert!(
1973 matches!(v, DurationValidator::BetweenDuration(start, end) if start == "1m" && end == "1h")
1974 );
1975 }
1976
1977 #[test]
1980 fn test_validator_serialize_deserialize() {
1981 let v = Validator::StringValidator(StringValidator::Email);
1982 let json = serde_json::to_string(&v).unwrap();
1983 let deserialized: Validator = serde_json::from_str(&json).unwrap();
1984 assert_eq!(v, deserialized);
1985 }
1986
1987 #[test]
1988 fn test_string_validator_serialize_deserialize() {
1989 let v = StringValidator::MinLength(10);
1990 let json = serde_json::to_string(&v).unwrap();
1991 let deserialized: StringValidator = serde_json::from_str(&json).unwrap();
1992 assert_eq!(v, deserialized);
1993 }
1994
1995 #[test]
1996 fn test_number_validator_serialize_deserialize() {
1997 let v = NumberValidator::GreaterThan(OrderedFloat(5.5));
1998 let json = serde_json::to_string(&v).unwrap();
1999 let deserialized: NumberValidator = serde_json::from_str(&json).unwrap();
2000 assert_eq!(v, deserialized);
2001 }
2002
2003 #[test]
2004 fn test_array_validator_serialize_deserialize() {
2005 let v = ArrayValidator::MinItems(5);
2006 let json = serde_json::to_string(&v).unwrap();
2007 let deserialized: ArrayValidator = serde_json::from_str(&json).unwrap();
2008 assert_eq!(v, deserialized);
2009 }
2010
2011 #[test]
2014 fn test_validator_to_tokens_not_empty() {
2015 let v = Validator::StringValidator(StringValidator::Email);
2016 let tokens = v.to_token_stream();
2017 assert!(!tokens.is_empty());
2018 }
2019
2020 #[test]
2021 fn test_string_validator_to_tokens() {
2022 let v = StringValidator::Alpha;
2023 let tokens = v.to_token_stream();
2024 let token_string = tokens.to_string();
2025 assert!(token_string.contains("Alpha"));
2026 }
2027
2028 #[test]
2029 fn test_number_validator_to_tokens() {
2030 let v = NumberValidator::Positive;
2031 let tokens = v.to_token_stream();
2032 let token_string = tokens.to_string();
2033 assert!(token_string.contains("Positive"));
2034 }
2035
2036 #[test]
2037 fn test_array_validator_to_tokens() {
2038 let v = ArrayValidator::MaxItems(10);
2039 let tokens = v.to_token_stream();
2040 let token_string = tokens.to_string();
2041 assert!(token_string.contains("MaxItems"));
2042 }
2043
2044 #[test]
2045 fn test_date_validator_to_tokens() {
2046 let v = DateValidator::ValidDate;
2047 let tokens = v.to_token_stream();
2048 let token_string = tokens.to_string();
2049 assert!(token_string.contains("ValidDate"));
2050 }
2051
2052 #[test]
2053 fn test_bigint_validator_to_tokens() {
2054 let v = BigIntValidator::PositiveBigInt;
2055 let tokens = v.to_token_stream();
2056 let token_string = tokens.to_string();
2057 assert!(token_string.contains("PositiveBigInt"));
2058 }
2059
2060 #[test]
2061 fn test_bigdecimal_validator_to_tokens() {
2062 let v = BigDecimalValidator::NegativeBigDecimal;
2063 let tokens = v.to_token_stream();
2064 let token_string = tokens.to_string();
2065 assert!(token_string.contains("NegativeBigDecimal"));
2066 }
2067
2068 #[test]
2069 fn test_duration_validator_to_tokens() {
2070 let v = DurationValidator::LessThanDuration("2h".to_string());
2071 let tokens = v.to_token_stream();
2072 let token_string = tokens.to_string();
2073 assert!(token_string.contains("LessThanDuration"));
2074 }
2075
2076 #[test]
2079 fn test_get_validation_logic_tokens_alpha() {
2080 let v = Validator::StringValidator(StringValidator::Alpha);
2081 let tokens = v.get_validation_logic_tokens("value");
2082 let token_string = tokens.to_string();
2083 assert!(token_string.contains("alphabetic"));
2084 }
2085
2086 #[test]
2087 fn test_get_validation_logic_tokens_email() {
2088 let v = Validator::StringValidator(StringValidator::Email);
2089 let tokens = v.get_validation_logic_tokens("email");
2090 let token_string = tokens.to_string();
2091 assert!(token_string.contains("email"));
2092 }
2093
2094 #[test]
2095 fn test_get_validation_logic_tokens_min_length() {
2096 let v = Validator::StringValidator(StringValidator::MinLength(5));
2097 let tokens = v.get_validation_logic_tokens("text");
2098 let token_string = tokens.to_string();
2099 assert!(token_string.contains("len"));
2100 }
2101
2102 #[test]
2103 fn test_get_validation_logic_tokens_positive_number() {
2104 let v = Validator::NumberValidator(NumberValidator::Positive);
2105 let tokens = v.get_validation_logic_tokens("num");
2106 let token_string = tokens.to_string();
2107 assert!(token_string.contains("positive"));
2108 }
2109
2110 #[test]
2111 fn test_get_validation_logic_tokens_array_min_items() {
2112 let v = Validator::ArrayValidator(ArrayValidator::MinItems(3));
2113 let tokens = v.get_validation_logic_tokens("arr");
2114 let token_string = tokens.to_string();
2115 assert!(token_string.contains("len"));
2116 }
2117
2118 #[test]
2119 fn test_get_validation_logic_tokens_uuid() {
2120 let v = Validator::StringValidator(StringValidator::Uuid);
2121 let tokens = v.get_validation_logic_tokens("id");
2122 let token_string = tokens.to_string();
2123 assert!(token_string.contains("uuid"));
2124 }
2125
2126 #[test]
2129 fn test_validator_debug() {
2130 let v = Validator::StringValidator(StringValidator::Email);
2131 let debug_str = format!("{:?}", v);
2132 assert!(debug_str.contains("Email"));
2133 }
2134
2135 #[test]
2136 fn test_string_validator_debug() {
2137 let v = StringValidator::Url;
2138 let debug_str = format!("{:?}", v);
2139 assert!(debug_str.contains("Url"));
2140 }
2141
2142 #[test]
2143 fn test_number_validator_debug() {
2144 let v = NumberValidator::Between(OrderedFloat(1.0), OrderedFloat(10.0));
2145 let debug_str = format!("{:?}", v);
2146 assert!(debug_str.contains("Between"));
2147 }
2148
2149 #[test]
2152 fn test_validator_hash() {
2153 use std::collections::HashSet;
2154 let mut set = HashSet::new();
2155 set.insert(Validator::StringValidator(StringValidator::Email));
2156 set.insert(Validator::StringValidator(StringValidator::Url));
2157 set.insert(Validator::NumberValidator(NumberValidator::Positive));
2158 assert_eq!(set.len(), 3);
2159 }
2160
2161 #[test]
2164 fn test_string_validator_empty_literal() {
2165 let v = StringValidator::Literal("".to_string());
2166 assert!(matches!(v, StringValidator::Literal(s) if s.is_empty()));
2167 }
2168
2169 #[test]
2170 fn test_string_validator_zero_length() {
2171 let v = StringValidator::MinLength(0);
2172 assert!(matches!(v, StringValidator::MinLength(0)));
2173 }
2174
2175 #[test]
2176 fn test_number_validator_zero() {
2177 let v = NumberValidator::GreaterThan(OrderedFloat(0.0));
2178 assert!(matches!(v, NumberValidator::GreaterThan(OrderedFloat(x)) if x == 0.0));
2179 }
2180
2181 #[test]
2182 fn test_number_validator_negative() {
2183 let v = NumberValidator::LessThan(OrderedFloat(-5.0));
2184 assert!(matches!(v, NumberValidator::LessThan(OrderedFloat(x)) if x == -5.0));
2185 }
2186
2187 #[test]
2188 fn test_array_validator_zero_items() {
2189 let v = ArrayValidator::MinItems(0);
2190 assert!(matches!(v, ArrayValidator::MinItems(0)));
2191 }
2192}