Skip to main content

rusdantic_core/rules/
mod.rs

1//! Built-in validation rules for Rusdantic.
2//!
3//! Each rule module provides a validation function that the derive macro's
4//! generated code calls at runtime. All functions follow a consistent pattern:
5//! they take the value to validate, constraint parameters, the field path,
6//! and a mutable reference to a `ValidationErrors` collection.
7//!
8//! This design allows error accumulation (collect-all) rather than
9//! fail-fast behavior.
10
11pub mod contains;
12pub mod email;
13pub mod length;
14pub mod pattern;
15pub mod range;
16pub mod required;
17pub mod url;
18
19// Re-export all validation functions at the rules module level
20// so generated code can use `::rusdantic_core::rules::validate_length(...)`.
21pub use contains::validate_contains;
22pub use email::validate_email;
23pub use length::validate_length;
24pub use pattern::validate_pattern;
25pub use range::validate_range;
26pub use required::validate_required;
27pub use url::validate_url;
28
29/// Trait for types that have a measurable length.
30/// Used by the length validator to work with both strings and collections.
31pub trait HasLength {
32    /// Return the length of this value (character count for strings,
33    /// element count for collections).
34    fn rusdantic_length(&self) -> usize;
35
36    /// Return the unit name for error messages ("characters" for strings,
37    /// "items" for collections).
38    fn rusdantic_length_unit(&self) -> &'static str {
39        "items"
40    }
41}
42
43impl HasLength for String {
44    fn rusdantic_length(&self) -> usize {
45        self.chars().count()
46    }
47
48    fn rusdantic_length_unit(&self) -> &'static str {
49        "characters"
50    }
51}
52
53impl HasLength for &str {
54    fn rusdantic_length(&self) -> usize {
55        self.chars().count()
56    }
57
58    fn rusdantic_length_unit(&self) -> &'static str {
59        "characters"
60    }
61}
62
63impl<T> HasLength for Vec<T> {
64    fn rusdantic_length(&self) -> usize {
65        self.len()
66    }
67}
68
69impl<T: std::hash::Hash + Eq> HasLength for std::collections::HashSet<T> {
70    fn rusdantic_length(&self) -> usize {
71        self.len()
72    }
73}
74
75impl<T: Ord> HasLength for std::collections::BTreeSet<T> {
76    fn rusdantic_length(&self) -> usize {
77        self.len()
78    }
79}
80
81impl<K: std::hash::Hash + Eq, V> HasLength for std::collections::HashMap<K, V> {
82    fn rusdantic_length(&self) -> usize {
83        self.len()
84    }
85}
86
87impl<K: Ord, V> HasLength for std::collections::BTreeMap<K, V> {
88    fn rusdantic_length(&self) -> usize {
89        self.len()
90    }
91}
92
93impl<T> HasLength for std::collections::VecDeque<T> {
94    fn rusdantic_length(&self) -> usize {
95        self.len()
96    }
97}
98
99impl<T> HasLength for std::collections::LinkedList<T> {
100    fn rusdantic_length(&self) -> usize {
101        self.len()
102    }
103}
104
105/// Trait for types that can be checked against a string pattern.
106/// Used by email, url, pattern, and contains validators.
107pub trait AsStr {
108    /// Return this value as a string slice for pattern matching.
109    fn as_str_ref(&self) -> &str;
110}
111
112impl AsStr for String {
113    fn as_str_ref(&self) -> &str {
114        self.as_str()
115    }
116}
117
118impl AsStr for &str {
119    fn as_str_ref(&self) -> &str {
120        self
121    }
122}
123
124impl AsStr for std::borrow::Cow<'_, str> {
125    fn as_str_ref(&self) -> &str {
126        self.as_ref()
127    }
128}