Skip to main content

vld/combinators/
intersection.rs

1use serde_json::Value;
2
3use crate::error::VldError;
4use crate::schema::VldSchema;
5
6/// Intersection of two schemas: input must satisfy both.
7///
8/// Both schemas are run on the same input. If both succeed, the output of the
9/// **first** schema is returned. If either fails, all errors are merged.
10///
11/// Created via [`vld::intersection()`](crate::intersection).
12///
13/// # Example
14/// ```ignore
15/// let schema = vld::intersection(
16///     vld::string().min(3),
17///     vld::string().email(),
18/// );
19/// ```
20pub struct ZIntersection<A: VldSchema, B: VldSchema> {
21    first: A,
22    second: B,
23}
24
25impl<A: VldSchema, B: VldSchema> ZIntersection<A, B> {
26    pub fn new(first: A, second: B) -> Self {
27        Self { first, second }
28    }
29
30    /// Access the first schema.
31    pub fn schema_a(&self) -> &A {
32        &self.first
33    }
34    /// Access the second schema.
35    pub fn schema_b(&self) -> &B {
36        &self.second
37    }
38}
39
40impl<A: VldSchema, B: VldSchema> VldSchema for ZIntersection<A, B> {
41    type Output = A::Output;
42
43    fn parse_value(&self, value: &Value) -> Result<A::Output, VldError> {
44        let mut errors = VldError::new();
45
46        let first_result = match self.first.parse_value(value) {
47            Ok(v) => Some(v),
48            Err(e) => {
49                errors = errors.merge(e);
50                None
51            }
52        };
53
54        if let Err(e) = self.second.parse_value(value) {
55            errors = errors.merge(e);
56        }
57
58        if errors.is_empty() {
59            Ok(first_result.unwrap())
60        } else {
61            Err(errors)
62        }
63    }
64}