1use serde_json::Value;
2
3use crate::path::JsonLike;
4
5use super::errors::JsonPathParserError;
6use super::parse_json_path;
7use std::fmt::{Display, Formatter};
8use std::{convert::TryFrom, str::FromStr};
9
10#[derive(Debug, Clone)]
15pub enum JsonPath<T = Value> {
16 Root,
18 Field(String),
20 Chain(Vec<JsonPath<T>>),
22 Descent(String),
24 DescentW,
26 Index(JsonPathIndex<T>),
28 Current(Box<JsonPath<T>>),
30 Wildcard,
32 Empty,
34 Fn(Function),
36}
37
38impl<T: Display> Display for JsonPath<T> {
39 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 let str = match self {
41 JsonPath::Root => "$".to_string(),
42 JsonPath::Field(e) => format!(".'{}'", e),
43 JsonPath::Chain(elems) => elems.iter().map(ToString::to_string).collect::<String>(),
44 JsonPath::Descent(e) => {
45 format!("..{}", e)
46 }
47 JsonPath::DescentW => "..*".to_string(),
48 JsonPath::Index(e) => e.to_string(),
49 JsonPath::Current(e) => format!("@{}", e),
50 JsonPath::Wildcard => "[*]".to_string(),
51 JsonPath::Empty => "".to_string(),
52 JsonPath::Fn(e) => format!(".{}", e),
53 };
54 write!(f, "{}", str)
55 }
56}
57
58impl<T> TryFrom<&str> for JsonPath<T>
59where
60 T: JsonLike,
61{
62 type Error = JsonPathParserError;
63
64 fn try_from(value: &str) -> Result<Self, Self::Error> {
70 parse_json_path(value)
71 }
72}
73
74impl<T> FromStr for JsonPath<T>
75where
76 T: JsonLike,
77{
78 type Err = JsonPathParserError;
79
80 fn from_str(value: &str) -> Result<Self, Self::Err> {
86 parse_json_path(value)
87 }
88}
89
90#[derive(Debug, PartialEq, Clone)]
91pub enum Function {
92 Length,
94}
95
96impl Display for Function {
97 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
98 let str = match self {
99 Function::Length => "length()".to_string(),
100 };
101 write!(f, "{}", str)
102 }
103}
104
105#[derive(Debug, Clone)]
106pub enum JsonPathIndex<T> {
107 Single(T),
109 UnionIndex(Vec<T>),
111 UnionKeys(Vec<String>),
113 Slice(i32, i32, usize),
115 Filter(FilterExpression<T>),
117}
118
119impl<T: Display> Display for JsonPathIndex<T> {
120 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
121 let str = match self {
122 JsonPathIndex::Single(e) => format!("[{}]", e),
123 JsonPathIndex::UnionIndex(elems) => {
124 format!(
125 "[{}]",
126 elems
127 .iter()
128 .map(ToString::to_string)
129 .collect::<Vec<_>>()
130 .join(",")
131 )
132 }
133 JsonPathIndex::UnionKeys(elems) => {
134 format!(
135 "[{}]",
136 elems
137 .iter()
138 .map(|el| format!("'{}'", el))
139 .collect::<Vec<_>>()
140 .join(",")
141 )
142 }
143 JsonPathIndex::Slice(s, e, st) => {
144 format!("[{}:{}:{}]", s, e, st)
145 }
146 JsonPathIndex::Filter(filter) => format!("[?({})]", filter),
147 };
148 write!(f, "{}", str)
149 }
150}
151
152#[derive(Debug, Clone, PartialEq)]
153pub enum FilterExpression<T> {
154 Atom(Operand<T>, FilterSign, Operand<T>),
156 And(Box<FilterExpression<T>>, Box<FilterExpression<T>>),
158 Or(Box<FilterExpression<T>>, Box<FilterExpression<T>>),
160 Not(Box<FilterExpression<T>>),
162}
163
164impl<T: Display> Display for FilterExpression<T> {
165 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
166 let str = match self {
167 FilterExpression::Atom(left, sign, right) => {
168 format!("{} {} {}", left, sign, right)
169 }
170 FilterExpression::And(left, right) => {
171 format!("{} && {}", left, right)
172 }
173 FilterExpression::Or(left, right) => {
174 format!("{} || {}", left, right)
175 }
176 FilterExpression::Not(expr) => {
177 format!("!{}", expr)
178 }
179 };
180 write!(f, "{}", str)
181 }
182}
183
184impl<T> FilterExpression<T> {
185 pub fn exists(op: Operand<T>) -> Self {
186 FilterExpression::Atom(
187 op,
188 FilterSign::Exists,
189 Operand::Dynamic(Box::new(JsonPath::Empty)),
190 )
191 }
192}
193
194#[derive(Debug, Clone)]
196pub enum Operand<T> {
197 Static(T),
198 Dynamic(Box<JsonPath<T>>),
199}
200
201impl<T: Display> Display for Operand<T> {
202 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203 let str = match self {
204 Operand::Static(e) => e.to_string(),
205 Operand::Dynamic(e) => e.to_string(),
206 };
207 write!(f, "{}", str)
208 }
209}
210
211#[allow(dead_code)]
212impl<T> Operand<T> {
213 pub fn val(v: T) -> Self {
214 Operand::Static(v)
215 }
216}
217
218#[derive(Debug, Clone, PartialEq)]
220pub enum FilterSign {
221 Equal,
222 Unequal,
223 Less,
224 Greater,
225 LeOrEq,
226 GrOrEq,
227 Regex,
228 In,
229 Nin,
230 Size,
231 NoneOf,
232 AnyOf,
233 SubSetOf,
234 Exists,
235}
236
237impl Display for FilterSign {
238 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
239 let str = match self {
240 FilterSign::Equal => "==",
241 FilterSign::Unequal => "!=",
242 FilterSign::Less => "<",
243 FilterSign::Greater => ">",
244 FilterSign::LeOrEq => "<=",
245 FilterSign::GrOrEq => ">=",
246 FilterSign::Regex => "~=",
247 FilterSign::In => "in",
248 FilterSign::Nin => "nin",
249 FilterSign::Size => "size",
250 FilterSign::NoneOf => "noneOf",
251 FilterSign::AnyOf => "anyOf",
252 FilterSign::SubSetOf => "subsetOf",
253 FilterSign::Exists => "exists",
254 };
255 write!(f, "{}", str)
256 }
257}
258
259impl FilterSign {
260 pub fn new(key: &str) -> Self {
261 match key {
262 "==" => FilterSign::Equal,
263 "!=" => FilterSign::Unequal,
264 "<" => FilterSign::Less,
265 ">" => FilterSign::Greater,
266 "<=" => FilterSign::LeOrEq,
267 ">=" => FilterSign::GrOrEq,
268 "~=" => FilterSign::Regex,
269 "in" => FilterSign::In,
270 "nin" => FilterSign::Nin,
271 "size" => FilterSign::Size,
272 "noneOf" => FilterSign::NoneOf,
273 "anyOf" => FilterSign::AnyOf,
274 "subsetOf" => FilterSign::SubSetOf,
275 _ => FilterSign::Exists,
276 }
277 }
278}
279
280impl<T> PartialEq for JsonPath<T>
281where
282 T: PartialEq,
283{
284 fn eq(&self, other: &Self) -> bool {
285 match (self, other) {
286 (JsonPath::Root, JsonPath::Root) => true,
287 (JsonPath::Descent(k1), JsonPath::Descent(k2)) => k1 == k2,
288 (JsonPath::DescentW, JsonPath::DescentW) => true,
289 (JsonPath::Field(k1), JsonPath::Field(k2)) => k1 == k2,
290 (JsonPath::Wildcard, JsonPath::Wildcard) => true,
291 (JsonPath::Empty, JsonPath::Empty) => true,
292 (JsonPath::Current(jp1), JsonPath::Current(jp2)) => jp1 == jp2,
293 (JsonPath::Chain(ch1), JsonPath::Chain(ch2)) => ch1 == ch2,
294 (JsonPath::Index(idx1), JsonPath::Index(idx2)) => idx1 == idx2,
295 (JsonPath::Fn(fn1), JsonPath::Fn(fn2)) => fn2 == fn1,
296 (_, _) => false,
297 }
298 }
299}
300
301impl<T> PartialEq for JsonPathIndex<T>
302where
303 T: PartialEq,
304{
305 fn eq(&self, other: &Self) -> bool {
306 match (self, other) {
307 (JsonPathIndex::Slice(s1, e1, st1), JsonPathIndex::Slice(s2, e2, st2)) => {
308 s1 == s2 && e1 == e2 && st1 == st2
309 }
310 (JsonPathIndex::Single(el1), JsonPathIndex::Single(el2)) => el1 == el2,
311 (JsonPathIndex::UnionIndex(elems1), JsonPathIndex::UnionIndex(elems2)) => {
312 elems1 == elems2
313 }
314 (JsonPathIndex::UnionKeys(elems1), JsonPathIndex::UnionKeys(elems2)) => {
315 elems1 == elems2
316 }
317 (JsonPathIndex::Filter(left), JsonPathIndex::Filter(right)) => left.eq(right),
318 (_, _) => false,
319 }
320 }
321}
322
323impl<T> PartialEq for Operand<T>
324where
325 T: PartialEq,
326{
327 fn eq(&self, other: &Self) -> bool {
328 match (self, other) {
329 (Operand::Static(v1), Operand::Static(v2)) => v1 == v2,
330 (Operand::Dynamic(jp1), Operand::Dynamic(jp2)) => jp1 == jp2,
331 (_, _) => false,
332 }
333 }
334}