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