Skip to main content

evenframe_core/
validator.rs

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/// Describes various string validation and transformation _requirements.
22#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
23pub enum StringValidator {
24    /// A string
25    String,
26
27    /// Only letters
28    Alpha,
29
30    /// Only letters and digits 0-9
31    Alphanumeric,
32
33    /// Base64-encoded
34    Base64,
35
36    /// Base64url-encoded
37    Base64Url,
38
39    /// A morph from a string to capitalized
40    Capitalize,
41
42    /// Capitalized
43    CapitalizePreformatted,
44
45    /// A credit card number and a credit card number
46    CreditCard,
47
48    /// A string and a parsable date
49    Date,
50
51    /// An integer string representing a safe Unix timestamp
52    DateEpoch,
53
54    /// A morph from an integer string representing a safe Unix timestamp to a Date
55    DateEpochParse,
56
57    /// An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) date
58    DateIso,
59
60    /// A morph from an ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) date to a Date
61    DateIsoParse,
62
63    /// A morph from a string and a parsable date to a Date
64    DateParse,
65
66    /// Only digits 0-9
67    Digits,
68
69    /// An email address
70    Email,
71
72    /// Hex characters only
73    Hex,
74
75    /// A well-formed integer string
76    Integer,
77
78    /// A morph from a well-formed integer string to an integer
79    IntegerParse,
80
81    /// An IP address
82    Ip,
83
84    /// An IPv4 address
85    IpV4,
86
87    /// An IPv6 address
88    IpV6,
89
90    /// A JSON string
91    Json,
92
93    /// Safe JSON string parser
94    JsonParse,
95
96    /// A morph from a string to only lowercase letters
97    Lower,
98
99    /// Only lowercase letters
100    LowerPreformatted,
101
102    /// A morph from a string to NFC-normalized unicode
103    Normalize,
104
105    /// A morph from a string to NFC-normalized unicode
106    NormalizeNFC,
107
108    /// NFC-normalized unicode
109    NormalizeNFCPreformatted,
110
111    /// A morph from a string to NFD-normalized unicode
112    NormalizeNFD,
113
114    /// NFD-normalized unicode
115    NormalizeNFDPreformatted,
116
117    /// A morph from a string to NFKC-normalized unicode
118    NormalizeNFKC,
119
120    /// NFKC-normalized unicode
121    NormalizeNFKCPreformatted,
122
123    /// A morph from a string to NFKD-normalized unicode
124    NormalizeNFKD,
125
126    /// NFKD-normalized unicode
127    NormalizeNFKDPreformatted,
128
129    /// A well-formed numeric string
130    Numeric,
131
132    /// A morph from a well-formed numeric string to a number
133    NumericParse,
134
135    /// A string and a regex pattern
136    Regex,
137
138    /// A semantic version (see https://semver.org/)
139    Semver,
140
141    /// A morph from a string to trimmed
142    Trim,
143
144    /// Trimmed
145    TrimPreformatted,
146
147    /// A morph from a string to only uppercase letters
148    Upper,
149
150    /// Only uppercase letters
151    UpperPreformatted,
152
153    /// A string and a URL string
154    Url,
155
156    /// A morph from a string and a URL string to a URL instance
157    UrlParse,
158
159    /// A UUID
160    Uuid,
161
162    /// A UUIDv1
163    UuidV1,
164
165    /// A UUIDv2
166    UuidV2,
167
168    /// A UUIDv3
169    UuidV3,
170
171    /// A UUIDv4
172    UuidV4,
173
174    /// A UUIDv5
175    UuidV5,
176
177    /// A UUIDv6
178    UuidV6,
179
180    /// A UUIDv7
181    UuidV7,
182
183    /// A UUIDv8
184    UuidV8,
185
186    Literal(String),
187
188    StringEmbedded(String),
189
190    RegexLiteral(Format),
191
192    Length(String),
193
194    /// Minimum length of a string
195    MinLength(usize),
196
197    /// Maximum length of a string  
198    MaxLength(usize),
199
200    /// Non-empty string (equivalent to MinLength(1))
201    NonEmpty,
202
203    /// String starts with a specific prefix
204    StartsWith(String),
205
206    /// String ends with a specific suffix
207    EndsWith(String),
208
209    /// String includes a specific substring
210    Includes(String),
211
212    /// String has no leading or trailing whitespace (validation only)
213    Trimmed,
214
215    /// String is entirely lowercase (validation only)
216    Lowercased,
217
218    /// String is entirely uppercase (validation only)
219    Uppercased,
220
221    /// String is capitalized (validation only)
222    Capitalized,
223
224    /// String is uncapitalized (validation only)
225    Uncapitalized,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
229pub enum NumberValidator {
230    /// Number greater than a value
231    GreaterThan(OrderedFloat<f64>),
232
233    /// Number greater than or equal to a value
234    GreaterThanOrEqualTo(OrderedFloat<f64>),
235
236    /// Number less than a value
237    LessThan(OrderedFloat<f64>),
238
239    /// Number less than or equal to a value  
240    LessThanOrEqualTo(OrderedFloat<f64>),
241
242    /// Number between two values (inclusive)
243    Between(OrderedFloat<f64>, OrderedFloat<f64>),
244
245    /// Must be an integer
246    Int,
247
248    /// Must not be NaN
249    NonNaN,
250
251    /// Must be a finite number (not NaN, +Infinity, -Infinity)
252    Finite,
253
254    /// Must be positive (> 0)
255    Positive,
256
257    /// Must be non-negative (>= 0)
258    NonNegative,
259
260    /// Must be negative (< 0)
261    Negative,
262
263    /// Must be non-positive (<= 0)
264    NonPositive,
265
266    /// Must be evenly divisible by a value
267    MultipleOf(OrderedFloat<f64>),
268
269    /// 8-bit unsigned integer (0 to 255)
270    Uint8,
271}
272
273/// Describes array validation filters
274#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
275pub enum ArrayValidator {
276    /// Minimum number of items in the array
277    MinItems(usize),
278
279    /// Maximum number of items in the array
280    MaxItems(usize),
281
282    /// Exact number of items in the array
283    ItemsCount(usize),
284}
285
286/// Describes date validation filters
287#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
288pub enum DateValidator {
289    /// Must be a valid date (not Invalid Date)
290    ValidDate,
291
292    /// Date greater than a specific date
293    GreaterThanDate(String),
294
295    /// Date greater than or equal to a specific date
296    GreaterThanOrEqualToDate(String),
297
298    /// Date less than a specific date
299    LessThanDate(String),
300
301    /// Date less than or equal to a specific date
302    LessThanOrEqualToDate(String),
303
304    /// Date between two dates (inclusive)
305    BetweenDate(String, String),
306}
307
308/// Describes BigInt validation filters
309#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
310pub enum BigIntValidator {
311    /// BigInt greater than a value
312    GreaterThanBigInt(String),
313
314    /// BigInt greater than or equal to a value
315    GreaterThanOrEqualToBigInt(String),
316
317    /// BigInt less than a value
318    LessThanBigInt(String),
319
320    /// BigInt less than or equal to a value
321    LessThanOrEqualToBigInt(String),
322
323    /// BigInt between two values (inclusive)
324    BetweenBigInt(String, String),
325
326    /// Must be positive (> 0n)
327    PositiveBigInt,
328
329    /// Must be non-negative (>= 0n)
330    NonNegativeBigInt,
331
332    /// Must be negative (< 0n)
333    NegativeBigInt,
334
335    /// Must be non-positive (<= 0n)
336    NonPositiveBigInt,
337}
338
339/// Describes BigDecimal validation filters
340#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
341pub enum BigDecimalValidator {
342    /// BigDecimal greater than a value
343    GreaterThanBigDecimal(String),
344
345    /// BigDecimal greater than or equal to a value
346    GreaterThanOrEqualToBigDecimal(String),
347
348    /// BigDecimal less than a value
349    LessThanBigDecimal(String),
350
351    /// BigDecimal less than or equal to a value
352    LessThanOrEqualToBigDecimal(String),
353
354    /// BigDecimal between two values (inclusive)
355    BetweenBigDecimal(String, String),
356
357    /// Must be positive (> 0)
358    PositiveBigDecimal,
359
360    /// Must be non-negative (>= 0)
361    NonNegativeBigDecimal,
362
363    /// Must be negative (< 0)
364    NegativeBigDecimal,
365
366    /// Must be non-positive (<= 0)
367    NonPositiveBigDecimal,
368}
369
370/// Describes Duration validation filters
371#[derive(Debug, Clone, PartialEq, Eq, Hash, TryFromExpr, Serialize, Deserialize)]
372pub enum DurationValidator {
373    /// Duration greater than a value
374    GreaterThanDuration(String),
375
376    /// Duration greater than or equal to a value
377    GreaterThanOrEqualToDuration(String),
378
379    /// Duration less than a value
380    LessThanDuration(String),
381
382    /// Duration less than or equal to a value
383    LessThanOrEqualToDuration(String),
384
385    /// Duration between two values (inclusive)
386    BetweenDuration(String, String),
387}
388
389impl Validator {
390    /// Generates validation logic tokens for each validator variant
391    /// Returns TokenStream that can be used in proc macros to generate validation code
392    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            // String Validators
399            Validator::StringValidator(string_validator) => match string_validator {
400                StringValidator::String => quote! {
401                    // No validation needed - any string is valid
402                },
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                    // This is a transformation, not validation
427                    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                    // Luhn algorithm validation
451                    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                    // Basic date validation - actual implementation would depend on date library
479                    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                    // Transform epoch to date
490                    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                    // Generic date parsing - implementation would depend on format
506                    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                    // Basic email validation
516                    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                    // Note: Regex pattern would need to be provided separately
628                    // This is a placeholder
629                },
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                    // String embedded validation would be handled by external logic
730                },
731                StringValidator::RegexLiteral(format_variant) => {
732                    // have to make it a string because Regex does not have ToTokens
733                    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            // Number Validators
837            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            // Array Validators
930            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            // Date Validators
955            Validator::DateValidator(date_validator) => match date_validator {
956                DateValidator::ValidDate => quote! {
957                    // Assumes value is already parsed as a date type
958                    // Validation would depend on the date library being used
959                },
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            // BigInt Validators
1010            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            // BigDecimal Validators
1107            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            // Duration Validators
1200            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    // ==================== Validator Enum Tests ====================
1694
1695    #[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    // ==================== StringValidator Tests ====================
1766
1767    #[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); // duplicate
1814        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    // ==================== NumberValidator Tests ====================
1825
1826    #[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    // ==================== ArrayValidator Tests ====================
1877
1878    #[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    // ==================== DateValidator Tests ====================
1904
1905    #[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    // ==================== BigIntValidator Tests ====================
1926
1927    #[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    // ==================== BigDecimalValidator Tests ====================
1948
1949    #[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    // ==================== DurationValidator Tests ====================
1962
1963    #[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    // ==================== Serialization Tests ====================
1978
1979    #[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    // ==================== ToTokens Tests ====================
2012
2013    #[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    // ==================== get_validation_logic_tokens Tests ====================
2077
2078    #[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    // ==================== Debug Tests ====================
2127
2128    #[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    // ==================== Hash Tests ====================
2150
2151    #[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    // ==================== Edge Cases ====================
2162
2163    #[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}