json_predicate/predicate/first_order/
in.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 In {
24 pub path: Option<JSONPath>,
27 #[builder(default)]
28 pub ignore_case: bool,
29 pub value: Vec<serde_json::Value>,
30}
31
32impl Serialize for In {
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("In", 3)?;
38 if self.ignore_case {
39 state.serialize_field("op", "in-")?;
40 } else {
41 state.serialize_field("op", "in")?;
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 In {
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 VisitorIn<'de> {
93 marker: PhantomData<In>,
94 lifetime: PhantomData<&'de ()>,
95 }
96
97 impl<'de> Visitor<'de> for VisitorIn<'de> {
98 type Value = In;
99 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
100 formatter.write_str("In")
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<Vec<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 =
131 Some(MapAccess::next_value::<Vec<serde_json::Value>>(&mut map)?);
132 }
133 Field::__ignore => {}
134 }
135 }
136
137 let path = path.ok_or(serde::de::Error::missing_field("path"))?;
138 let value = value.ok_or(serde::de::Error::missing_field("value"))?;
139 let op = op.ok_or(serde::de::Error::missing_field("op"))?;
140
141 let ignore_case = match op.as_str() {
142 "in" => false,
143 "in-" => true,
144 _ => {
145 return Err(serde::de::Error::custom(
146 "`op` should be either `in` or `in-`",
147 ));
148 }
149 };
150
151 Ok(In {
152 path,
153 ignore_case,
154 value,
155 })
156 }
157 }
158
159 const FIELDS: &[&str] = &["path", "op", "value"];
160 Deserializer::deserialize_struct(
161 deserializer,
162 "In",
163 FIELDS,
164 VisitorIn {
165 marker: PhantomData::<In>,
166 lifetime: PhantomData,
167 },
168 )
169 }
170}
171
172impl From<In> for FirstOrder {
173 fn from(value: In) -> Self {
174 FirstOrder::In(value)
175 }
176}
177
178impl PredicateImpl for In {
179 fn evaluate(&self, data: &Value, ctx: PredicateContext) -> Result<bool, PredicateError> {
180 let path = ctx.final_path(&self.path).unwrap_or(JSONPath::empty());
181 let ptr = path.take();
182
183 let value = &self.value;
184 let context_value = ptr.get(data)?;
185
186 let result = if self.ignore_case {
187 let context_value = context_value.to_string().to_lowercase();
188 value
189 .iter()
190 .find(|x| x.to_string().to_lowercase() == context_value)
191 } else {
192 value.iter().find(|x| *x == context_value)
193 };
194 Ok(result.is_some())
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use serde::Deserialize;
201
202 use crate::{json_path::JSONPath, predicate::first_order::r#in::In};
203
204 #[test]
205 fn snapshot_test() {
206 let end_expect = serde_json::json!({
207 "op": "in",
208 "path": "/a/b",
209 "value": ["a"],
210 });
211
212 let end = In {
213 path: Some(JSONPath::new("/a/b").unwrap()),
214 ignore_case: false,
215 value: vec![serde_json::Value::String("a".to_string())],
216 };
217
218 assert_eq!(serde_json::to_value(end).unwrap(), end_expect);
219 }
220
221 #[test]
222 fn deser_test() {
223 let end_expect = serde_json::json!({
224 "op": "in",
225 "path": "/a/b",
226 "value": ["a"],
227 });
228
229 let end = In {
230 path: Some(JSONPath::new("/a/b").unwrap()),
231 ignore_case: false,
232 value: vec![serde_json::Value::String("a".to_string())],
233 };
234
235 let deser = In::deserialize(end_expect).unwrap();
236
237 assert_eq!(end, deser);
238 }
239}