validatron/
lib.rs

1//! A data structure validation library
2//!
3//! ```
4//! use validatron::Validate;
5//!
6//! #[derive(Debug, Validate)]
7//! struct MyStruct {
8//!     #[validatron(min = 42)]
9//!     a: i64,
10//!     #[validatron(max_len = 5)]
11//!     b: Vec<u32>,
12//! }
13//!
14//! let x = MyStruct {
15//!     a: 36,
16//!     b: vec![]
17//! };
18//!
19//! x.validate().is_err();
20//! ```
21
22/// An [`Error`](trait@std::error::Error) type for representing validation failures
23pub mod error;
24
25/// pre-rolled validators for data structures
26pub mod validators;
27
28// re-export derive macro
29pub use error::{Error, Location};
30
31/// A derive macro for validating data structures
32pub use validatron_derive::Validate;
33
34/// A convenience type for Results using the [`Error`] error type.
35pub type Result<T> = std::result::Result<T, Error>;
36
37/// The core Validatron trait, types that implement this trait can
38/// be exhaustively validated.
39///
40/// Implementors should recursively validate internal structures.
41pub trait Validate {
42    /// Validate the implemented type exhaustively, returning all errors.
43    fn validate(&self) -> Result<()>;
44}
45
46fn validate_seq<'a, I, T: 'a>(sequence: I) -> Result<()>
47where
48    I: IntoIterator<Item = &'a T>,
49    T: Validate,
50{
51    let mut eb = Error::build();
52
53    for (i, x) in sequence.into_iter().enumerate() {
54        eb.try_at_index(i, x.validate());
55    }
56
57    eb.build()
58}
59
60impl<T> Validate for Vec<T>
61where
62    T: Validate,
63{
64    fn validate(&self) -> Result<()> {
65        validate_seq(self)
66    }
67}
68
69impl<T> Validate for std::collections::VecDeque<T>
70where
71    T: Validate,
72{
73    fn validate(&self) -> Result<()> {
74        validate_seq(self)
75    }
76}
77
78impl<T> Validate for std::collections::LinkedList<T>
79where
80    T: Validate,
81{
82    fn validate(&self) -> Result<()> {
83        validate_seq(self)
84    }
85}
86
87impl<K, V, S> Validate for std::collections::HashMap<K, V, S>
88where
89    K: std::fmt::Display,
90    V: Validate,
91{
92    fn validate(&self) -> Result<()> {
93        let mut eb = Error::build();
94
95        for (k, v) in self {
96            eb.try_at_named(k.to_string(), v.validate());
97        }
98
99        eb.build()
100    }
101}
102
103impl<K, V> Validate for std::collections::BTreeMap<K, V>
104where
105    K: std::fmt::Display,
106    V: Validate,
107{
108    fn validate(&self) -> Result<()> {
109        let mut eb = Error::build();
110
111        for (k, v) in self {
112            eb.try_at_named(k.to_string(), v.validate());
113        }
114
115        eb.build()
116    }
117}
118
119impl<T, S> Validate for std::collections::HashSet<T, S>
120where
121    T: Validate,
122{
123    fn validate(&self) -> Result<()> {
124        validate_seq(self)
125    }
126}
127
128impl<T> Validate for std::collections::BTreeSet<T>
129where
130    T: Validate,
131{
132    fn validate(&self) -> Result<()> {
133        validate_seq(self)
134    }
135}
136
137impl<T> Validate for std::collections::BinaryHeap<T>
138where
139    T: Validate,
140{
141    fn validate(&self) -> Result<()> {
142        validate_seq(self)
143    }
144}
145
146#[cfg(feature = "use-indexmap")]
147impl<K, V> Validate for indexmap::IndexMap<K, V>
148where
149    K: std::fmt::Display,
150    V: Validate,
151{
152    fn validate(&self) -> Result<()> {
153        let mut eb = Error::build();
154
155        for (k, v) in self {
156            eb.try_at_named(k.to_string(), v.validate());
157        }
158
159        eb.build()
160    }
161}
162
163#[cfg(feature = "use-indexmap")]
164impl<T, S> Validate for indexmap::IndexSet<T, S>
165where
166    T: Validate,
167{
168    fn validate(&self) -> Result<()> {
169        validate_seq(self)
170    }
171}
172
173impl<T> Validate for Option<T>
174where
175    T: Validate,
176{
177    fn validate(&self) -> Result<()> {
178        validate_seq(self)
179    }
180}
181
182impl<T, E> Validate for std::result::Result<T, E>
183where
184    T: Validate,
185{
186    fn validate(&self) -> Result<()> {
187        if let Ok(value) = self {
188            value.validate()
189        } else {
190            Err(Error::new("value is an Error"))
191        }
192    }
193}