json_predicate/predicate/second_order/
not.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 "not" predicate evaluates as "true" if all of it's contained set of
17/// predicate operations evaluate as "false".
18#[derive(Debug, Clone, PartialEq, Eq, Builder)]
19#[builder(pattern = "owned", setter(into, strip_option))]
20pub struct Not {
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 Not {
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("Not", 3)?;
34        state.serialize_field("op", "not")?;
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 Not {
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 VisitorNot<'de> {
85            marker: PhantomData<Not>,
86            lifetime: PhantomData<&'de ()>,
87        }
88
89        impl<'de> Visitor<'de> for VisitorNot<'de> {
90            type Value = Not;
91            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
92                formatter.write_str("Not")
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() != "not" {
133                    return Err(serde::de::Error::custom("`op` should be `not`"));
134                }
135
136                Ok(Not { apply, path })
137            }
138        }
139
140        const FIELDS: &[&str] = &["op", "apply", "path"];
141        Deserializer::deserialize_struct(
142            deserializer,
143            "Not",
144            FIELDS,
145            VisitorNot {
146                marker: PhantomData::<Not>,
147                lifetime: PhantomData,
148            },
149        )
150    }
151}
152
153impl From<Not> for SecondOrder {
154    fn from(value: Not) -> Self {
155        SecondOrder::Not(value)
156    }
157}
158
159impl PredicateImpl for Not {
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        // The "not" predicate evaluates as "true" if all of it's contained set
165        // of predicate operations evaluate as "false".
166
167        for ap in &self.apply {
168            let pred = ap.evaluate(data, ctx.clone());
169
170            if pred.is_ok() {
171                return Ok(false);
172            }
173        }
174
175        Ok(true)
176    }
177}
178
179#[cfg(test)]
180mod tests {
181    use serde::Deserialize;
182
183    use crate::predicate::second_order::not::Not;
184
185    #[test]
186    fn deser_test() {
187        let not_expect = serde_json::json!({
188             "op": "not",
189             "apply": [
190               {
191                 "op": "defined",
192                 "path": "/a/b"
193               },
194               {
195                 "op": "less",
196                 "path": "/a/c/d",
197                 "value": 15
198               }
199            ]
200        });
201
202        let deser = Not::deserialize(not_expect).unwrap();
203
204        insta::assert_json_snapshot!(deser);
205    }
206}