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