json_predicate/predicate/second_order/
or.rs

1use derive_builder::Builder;
2use serde_json::Value;
3use std::marker::PhantomData;
4
5use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
6use serde::{ser::SerializeStruct, Serialize};
7
8use crate::json_path::JSONPath;
9use crate::predicate::context::PredicateContext;
10use crate::predicate::error::PredicateError;
11use crate::predicate::PredicateImpl;
12use crate::Predicate;
13
14use super::SecondOrder;
15
16/// The "or" predicate evaluates as "true" if at least one of it's contained
17/// set of predicate operations evaluate as "true".
18#[derive(Debug, Clone, PartialEq, Eq, Builder)]
19#[builder(pattern = "owned", setter(into, strip_option))]
20pub struct Or {
21    /// Must be a [JSON Pointer](https://tools.ietf.org/html/rfc6901)
22    /// If the "path" member is not specified within the predicate object, it's value is assumed to be an empty string.
23    #[builder(default)]
24    pub path: Option<JSONPath>,
25    pub apply: Vec<Predicate>,
26}
27
28impl Serialize for Or {
29    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
30    where
31        S: serde::Serializer,
32    {
33        let mut state = serializer.serialize_struct("Or", 3)?;
34        state.serialize_field("op", "or")?;
35        state.serialize_field("path", &self.path)?;
36        state.serialize_field("apply", &self.apply)?;
37        state.end()
38    }
39}
40
41impl<'de> Deserialize<'de> for Or {
42    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
43    where
44        D: Deserializer<'de>,
45    {
46        #[allow(non_camel_case_types)]
47        enum Field {
48            op,
49            path,
50            apply,
51            __ignore,
52        }
53        struct FieldVisitor;
54
55        impl<'de> Visitor<'de> for FieldVisitor {
56            type Value = Field;
57            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
58                formatter.write_str("field identifier")
59            }
60
61            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
62            where
63                E: de::Error,
64            {
65                match value {
66                    "op" => Ok(Field::op),
67                    "apply" => Ok(Field::apply),
68                    "path" => Ok(Field::path),
69                    _ => Ok(Field::__ignore),
70                }
71            }
72        }
73
74        impl<'de> Deserialize<'de> for Field {
75            #[inline]
76            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
77            where
78                D: Deserializer<'de>,
79            {
80                Deserializer::deserialize_identifier(deserializer, FieldVisitor)
81            }
82        }
83
84        struct VisitorOr<'de> {
85            marker: PhantomData<Or>,
86            lifetime: PhantomData<&'de ()>,
87        }
88
89        impl<'de> Visitor<'de> for VisitorOr<'de> {
90            type Value = Or;
91            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
92                formatter.write_str("Or")
93            }
94
95            #[inline]
96            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
97            where
98                A: MapAccess<'de>,
99            {
100                let mut path: Option<Option<JSONPath>> = None;
101                let mut apply: Option<Vec<Predicate>> = None;
102                let mut op: Option<String> = None;
103
104                while let Some(key) = MapAccess::next_key::<Field>(&mut map)? {
105                    match key {
106                        Field::op => {
107                            if op.is_some() {
108                                return Err(serde::de::Error::duplicate_field("op"));
109                            }
110                            op = Some(MapAccess::next_value::<String>(&mut map)?);
111                        }
112                        Field::path => {
113                            if path.is_some() {
114                                return Err(serde::de::Error::duplicate_field("path"));
115                            }
116                            path = Some(MapAccess::next_value::<Option<JSONPath>>(&mut map)?);
117                        }
118                        Field::apply => {
119                            if apply.is_some() {
120                                return Err(serde::de::Error::duplicate_field("value"));
121                            }
122                            apply = Some(MapAccess::next_value::<Vec<Predicate>>(&mut map)?);
123                        }
124                        Field::__ignore => {}
125                    }
126                }
127
128                let path = path.flatten();
129                let apply = apply.ok_or(serde::de::Error::missing_field("apply"))?;
130                let op = op.ok_or(serde::de::Error::missing_field("op"))?;
131
132                if op.as_str() != "or" {
133                    return Err(serde::de::Error::custom("`op` should be `or`"));
134                }
135
136                Ok(Or { apply, path })
137            }
138        }
139
140        const FIELDS: &[&str] = &["op", "apply", "path"];
141        Deserializer::deserialize_struct(
142            deserializer,
143            "Or",
144            FIELDS,
145            VisitorOr {
146                marker: PhantomData::<Or>,
147                lifetime: PhantomData,
148            },
149        )
150    }
151}
152
153impl From<Or> for SecondOrder {
154    fn from(value: Or) -> Self {
155        SecondOrder::Or(value)
156    }
157}
158
159impl PredicateImpl for Or {
160    fn evaluate(&self, data: &Value, ctx: PredicateContext) -> Result<bool, PredicateError> {
161        let path = ctx.final_path(&self.path);
162        let ctx = PredicateContext::from(path);
163
164        let mut acc = true;
165
166        for ap in &self.apply {
167            let pred = ap.evaluate(data, ctx.clone());
168
169            if pred.is_ok() {
170                return Ok(true);
171            } else {
172                acc = false;
173            }
174        }
175
176        Ok(acc)
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use serde::Deserialize;
183
184    use crate::predicate::second_order::or::Or;
185
186    #[test]
187    fn deser_test() {
188        let or_expect = serde_json::json!({
189             "op": "or",
190             "apply": [
191               {
192                 "op": "defined",
193                 "path": "/a/b"
194               },
195               {
196                 "op": "less",
197                 "path": "/a/c/d",
198                 "value": 15
199               }
200            ]
201        });
202
203        let deser = Or::deserialize(or_expect).unwrap();
204
205        insta::assert_json_snapshot!(deser);
206    }
207}