1#![doc=include_str!("../README.md")]
2mod errors;
3pub use errors::{Accumulator, Error, Failure, Result};
4pub mod synch;
5pub use synch::{Validate, ValidateContext};
6mod wrapper;
7pub use wrapper::Valid;
8pub mod asynch;
9
10#[cfg(test)]
11mod tests {
12 use crate::synch::Validate;
13
14 use super::*;
15
16 struct A {
17 avalue: u8,
18 b: B,
19 }
20
21 impl Validate for A {
22 fn validate_inner(&self, accum: &mut errors::Accumulator) -> usize {
23 let orig = accum.len();
24 if self.avalue % 2 != 0 {
25 accum.add_failure("value is odd".into(), &["avalue".into()]);
26 }
27
28 accum.prefix.push("b".into());
29 self.b.validate_inner(accum);
30 accum.prefix.pop();
31
32 accum.len() - orig
33 }
34 }
35
36 struct B {
37 bvalue: u8,
38 cs: Vec<C>,
39 }
40
41 impl Validate for B {
42 fn validate_inner(&self, accum: &mut errors::Accumulator) -> usize {
43 let orig_len = accum.len();
44 if self.bvalue % 2 != 0 {
45 accum.add_failure("value is odd".into(), &["bvalue".into()]);
46 }
47
48 accum.prefix.push("cs".into());
49 accum.validate_iter(&self.cs);
50 accum.prefix.pop();
51
52 accum.len() - orig_len
53 }
54 }
55
56 struct C {
57 cvalue: u8,
58 }
59
60 impl Validate for C {
61 fn validate_inner(&self, accum: &mut errors::Accumulator) -> usize {
62 let orig_len = accum.len();
63 if self.cvalue % 2 != 0 {
64 accum.add_failure("value is odd".into(), &["cvalue".into()]);
65 }
66 accum.len() - orig_len
67 }
68 }
69
70 #[test]
71 fn valid() {
72 let valid = A {
73 avalue: 0,
74 b: B {
75 bvalue: 0,
76 cs: vec![C { cvalue: 0 }],
77 },
78 };
79 assert!(valid.validate().is_ok());
80 }
81
82 #[test]
83 fn invalid() {
84 let valid = A {
85 avalue: 1,
86 b: B {
87 bvalue: 1,
88 cs: vec![C { cvalue: 1 }, C { cvalue: 1 }],
89 },
90 };
91 let err = valid.validate().unwrap_err();
92 println!("{err}");
93 }
94}