json_predicate/predicate/first_order/
less.rs

1use derive_builder::Builder;
2use serde_json::{Number, 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;
12
13use super::FirstOrder;
14
15/// The "less" predicate evaluates as true if the referenced element is defined
16/// and specifies a number whose value is less than that specified by the
17/// predicate object's "value" member.
18#[derive(Debug, Clone, PartialEq, Eq, Builder)]
19#[builder(pattern = "owned", setter(into, strip_option))]
20pub struct Less {
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    pub path: Option<JSONPath>,
24    pub value: Number,
25}
26
27impl Serialize for Less {
28    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
29    where
30        S: serde::Serializer,
31    {
32        let mut state = serializer.serialize_struct("Less", 3)?;
33        state.serialize_field("op", "less")?;
34        state.serialize_field("path", &self.path)?;
35        state.serialize_field("value", &self.value)?;
36        state.end()
37    }
38}
39
40impl<'de> Deserialize<'de> for Less {
41    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42    where
43        D: Deserializer<'de>,
44    {
45        #[allow(non_camel_case_types)]
46        enum Field {
47            op,
48            path,
49            value,
50            __ignore,
51        }
52        struct FieldVisitor;
53
54        impl<'de> Visitor<'de> for FieldVisitor {
55            type Value = Field;
56            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
57                formatter.write_str("field identifier")
58            }
59
60            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
61            where
62                E: de::Error,
63            {
64                match value {
65                    "op" => Ok(Field::op),
66                    "path" => Ok(Field::path),
67                    "value" => Ok(Field::value),
68                    _ => Ok(Field::__ignore),
69                }
70            }
71        }
72
73        impl<'de> Deserialize<'de> for Field {
74            #[inline]
75            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
76            where
77                D: Deserializer<'de>,
78            {
79                Deserializer::deserialize_identifier(deserializer, FieldVisitor)
80            }
81        }
82
83        struct VisitorLess<'de> {
84            marker: PhantomData<Less>,
85            lifetime: PhantomData<&'de ()>,
86        }
87
88        impl<'de> Visitor<'de> for VisitorLess<'de> {
89            type Value = Less;
90            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
91                formatter.write_str("Less")
92            }
93
94            #[inline]
95            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
96            where
97                A: MapAccess<'de>,
98            {
99                let mut path: Option<Option<JSONPath>> = None;
100                let mut value: Option<Number> = None;
101                let mut op: Option<String> = None;
102
103                while let Some(key) = MapAccess::next_key::<Field>(&mut map)? {
104                    match key {
105                        Field::op => {
106                            if op.is_some() {
107                                return Err(serde::de::Error::duplicate_field("op"));
108                            }
109                            op = Some(MapAccess::next_value::<String>(&mut map)?);
110                        }
111                        Field::path => {
112                            if path.is_some() {
113                                return Err(serde::de::Error::duplicate_field("path"));
114                            }
115                            path = Some(MapAccess::next_value::<Option<JSONPath>>(&mut map)?);
116                        }
117                        Field::value => {
118                            if value.is_some() {
119                                return Err(serde::de::Error::duplicate_field("value"));
120                            }
121                            value = Some(MapAccess::next_value::<Number>(&mut map)?);
122                        }
123                        Field::__ignore => {}
124                    }
125                }
126
127                let path = path.ok_or(serde::de::Error::missing_field("path"))?;
128                let value = value.ok_or(serde::de::Error::missing_field("value"))?;
129                let op = op.ok_or(serde::de::Error::missing_field("op"))?;
130
131                if op.as_str() != "less" {
132                    return Err(serde::de::Error::custom("`op` should be `less`"));
133                }
134
135                Ok(Less { path, value })
136            }
137        }
138
139        const FIELDS: &[&str] = &["path", "op", "value"];
140        Deserializer::deserialize_struct(
141            deserializer,
142            "Less",
143            FIELDS,
144            VisitorLess {
145                marker: PhantomData::<Less>,
146                lifetime: PhantomData,
147            },
148        )
149    }
150}
151
152impl From<Less> for FirstOrder {
153    fn from(value: Less) -> Self {
154        FirstOrder::Less(value)
155    }
156}
157
158impl PredicateImpl for Less {
159    fn evaluate(&self, data: &Value, ctx: PredicateContext) -> Result<bool, PredicateError> {
160        let path = ctx.final_path(&self.path).unwrap_or(JSONPath::empty());
161        let ptr = path.take();
162
163        let value = &self.value;
164        let context_value = ptr.get(data)?;
165
166        if context_value.is_number() {
167            Ok(context_value.as_f64() < value.as_f64())
168        } else {
169            Ok(false)
170        }
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use serde::Deserialize;
177    use serde_json::Number;
178
179    use crate::{json_path::JSONPath, predicate::first_order::less::Less};
180
181    #[test]
182    fn snapshot_test() {
183        let less_expect = serde_json::json!({
184             "op": "less",
185             "path": "/a/b",
186             "value": 12
187        });
188
189        let less = Less {
190            path: Some(JSONPath::new("/a/b").unwrap()),
191            value: Number::from(12),
192        };
193
194        assert_eq!(serde_json::to_value(less).unwrap(), less_expect);
195    }
196
197    #[test]
198    fn deser_test() {
199        let less_expect = serde_json::json!({
200             "op": "less",
201             "path": "/a/b",
202             "value": 12
203        });
204
205        let less = Less {
206            path: Some(JSONPath::new("/a/b").unwrap()),
207            value: Number::from(12),
208        };
209
210        let deser = Less::deserialize(less_expect).unwrap();
211
212        assert_eq!(less, deser);
213    }
214}