json_predicate/predicate/first_order/
less.rs1use 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#[derive(Debug, Clone, PartialEq, Eq, Builder)]
19#[builder(pattern = "owned", setter(into, strip_option))]
20pub struct Less {
21 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}