1use crate::parser::errors::JsonPathError;
2use crate::parser::Parsed;
3use std::fmt::{Display, Formatter};
4
5/// Represents a JSONPath query with a list of segments.
6#[derive(Debug, Clone, PartialEq)]
7pub struct JpQuery {
8 pub segments: Vec<Segment>,
9}
10
11impl JpQuery {
12 pub fn new(segments: Vec<Segment>) -> Self {
13 JpQuery { segments }
14 }
15}
16
17impl Display for JpQuery {
18 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
19 write!(
20 f,
21 "${}",
22 self.segments
23 .iter()
24 .map(|s| s.to_string())
25 .collect::<String>()
26 )
27 }
28}
29/// Enum representing different types of segments in a JSONPath query.
30#[derive(Debug, Clone, PartialEq)]
31pub enum Segment {
32 /// Represents a descendant segment.
33 Descendant(Box<Segment>),
34 /// Represents a selector segment.
35 Selector(Selector),
36 /// Represents multiple selectors.
37 Selectors(Vec<Selector>),
38}
39
40impl Segment {
41 pub fn name(name: &str) -> Self {
42 Segment::Selector(Selector::Name(name.to_string()))
43 }
44}
45
46impl Display for Segment {
47 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48 match self {
49 Segment::Descendant(s: &Box) => write!(f, "..{}", s),
50 Segment::Selector(selector: &Selector) => write!(f, "{}", selector),
51 Segment::Selectors(selectors: &Vec) => write!(
52 f,
53 "{}",
54 selectors.iter().map(|s| s.to_string()).collect::<String>()
55 ),
56 }
57 }
58}
59/// Enum representing different types of selectors in a JSONPath query.
60#[derive(Debug, Clone, PartialEq)]
61pub enum Selector {
62 /// Represents a name selector.
63 Name(String),
64 /// Represents a wildcard selector.
65 Wildcard,
66 /// Represents an index selector.
67 Index(i64),
68 /// Represents a slice selector.
69 Slice(Option<i64>, Option<i64>, Option<i64>),
70 /// Represents a filter selector.
71 Filter(Filter),
72}
73
74pub fn slice_from((start: Option, end: Option, step: Option): (Option<i64>, Option<i64>, Option<i64>)) -> Selector {
75 Selector::Slice(start, end, step)
76}
77
78impl Display for Selector {
79 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
80 match self {
81 Selector::Name(name: &String) => write!(f, "{}", name),
82 Selector::Wildcard => write!(f, "*"),
83 Selector::Index(index: &i64) => write!(f, "{}", index),
84 Selector::Slice(start: &Option, end: &Option, step: &Option) => write!(
85 f,
86 "{}:{}:{}",
87 start.unwrap_or(0),
88 end.unwrap_or(0),
89 step.unwrap_or(1)
90 ),
91 Selector::Filter(filter: &Filter) => write!(f, "[?{}]", filter),
92 }
93 }
94}
95/// Enum representing different types of filters in a JSONPath query.
96#[derive(Debug, Clone, PartialEq)]
97pub enum Filter {
98 /// Represents a logical OR filter.
99 Or(Vec<Filter>),
100 /// Represents a logical AND filter.
101 And(Vec<Filter>),
102 /// Represents an atomic filter.
103 Atom(FilterAtom),
104}
105
106impl Display for Filter {
107 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
108 let items_to_str: impl Fn(&Vec, &str) -> … = |items: &Vec<Filter>, sep: &str| {
109 itemsVec
110 .iter()
111 .map(|f: &Filter| f.to_string())
112 .collect::<Vec<_>>()
113 .join(sep)
114 };
115
116 match self {
117 Filter::Or(filters: &Vec) => write!(f, "{}", items_to_str(filters, " || ")),
118 Filter::And(filters: &Vec) => write!(f, "{}", items_to_str(filters, " && ")),
119 Filter::Atom(atom: &FilterAtom) => write!(f, "{}", atom),
120 }
121 }
122}
123
124/// Enum representing different types of atomic filters in a JSONPath query.
125#[derive(Debug, Clone, PartialEq)]
126pub enum FilterAtom {
127 /// Represents a nested filter with an optional NOT flag.
128 Filter { expr: Box<Filter>, not: bool },
129 /// Represents a test filter with an optional NOT flag.
130 Test { expr: Box<Test>, not: bool },
131 /// Represents a comparison filter.
132 Comparison(Box<Comparison>),
133}
134
135impl FilterAtom {
136 pub fn filter(expr: Filter, not: bool) -> Self {
137 FilterAtom::Filter {
138 expr: Box::new(expr),
139 not,
140 }
141 }
142
143 pub fn test(expr: Test, not: bool) -> Self {
144 FilterAtom::Test {
145 expr: Box::new(expr),
146 not,
147 }
148 }
149
150 pub fn cmp(cmp: Box<Comparison>) -> Self {
151 FilterAtom::Comparison(cmp)
152 }
153}
154
155impl Display for FilterAtom {
156 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
157 match self {
158 FilterAtom::Filter { expr: &Box, not: &bool } => {
159 if *not {
160 write!(f, "!{}", expr)
161 } else {
162 write!(f, "{}", expr)
163 }
164 }
165 FilterAtom::Test { expr: &Box, not: &bool } => {
166 if *not {
167 write!(f, "!{}", expr)
168 } else {
169 write!(f, "{}", expr)
170 }
171 }
172 FilterAtom::Comparison(cmp: &Box) => write!(f, "{}", cmp),
173 }
174 }
175}
176/// Enum representing different types of comparisons in a JSONPath query.
177#[derive(Debug, Clone, PartialEq)]
178pub enum Comparison {
179 /// Represents an equality comparison.
180 Eq(Comparable, Comparable),
181 /// Represents a non-equality comparison.
182 Ne(Comparable, Comparable),
183 /// Represents a greater-than comparison.
184 Gt(Comparable, Comparable),
185 /// Represents a greater-than-or-equal-to comparison.
186 Gte(Comparable, Comparable),
187 /// Represents a less-than comparison.
188 Lt(Comparable, Comparable),
189 /// Represents a less-than-or-equal-to comparison.
190 Lte(Comparable, Comparable),
191}
192
193impl Comparison {
194 pub fn try_new(op: &str, left: Comparable, right: Comparable) -> Parsed<Self> {
195 match op {
196 "==" => Ok(Comparison::Eq(left, right)),
197 "!=" => Ok(Comparison::Ne(left, right)),
198 ">" => Ok(Comparison::Gt(left, right)),
199 ">=" => Ok(Comparison::Gte(left, right)),
200 "<" => Ok(Comparison::Lt(left, right)),
201 "<=" => Ok(Comparison::Lte(left, right)),
202 _ => Err(JsonPathError::InvalidJsonPath(format!(
203 "Invalid comparison operator: {}",
204 op
205 ))),
206 }
207 }
208
209 pub fn vals(&self) -> (&Comparable, &Comparable) {
210 match self {
211 Comparison::Eq(left, right) => (left, right),
212 Comparison::Ne(left, right) => (left, right),
213 Comparison::Gt(left, right) => (left, right),
214 Comparison::Gte(left, right) => (left, right),
215 Comparison::Lt(left, right) => (left, right),
216 Comparison::Lte(left, right) => (left, right),
217 }
218 }
219}
220
221impl Display for Comparison {
222 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
223 match self {
224 Comparison::Eq(left: &Comparable, right: &Comparable) => write!(f, "{} == {}", left, right),
225 Comparison::Ne(left: &Comparable, right: &Comparable) => write!(f, "{} != {}", left, right),
226 Comparison::Gt(left: &Comparable, right: &Comparable) => write!(f, "{} > {}", left, right),
227 Comparison::Gte(left: &Comparable, right: &Comparable) => write!(f, "{} >= {}", left, right),
228 Comparison::Lt(left: &Comparable, right: &Comparable) => write!(f, "{} < {}", left, right),
229 Comparison::Lte(left: &Comparable, right: &Comparable) => write!(f, "{} <= {}", left, right),
230 }
231 }
232}
233
234/// Enum representing different types of comparable values in a JSONPath query.
235#[derive(Debug, Clone, PartialEq)]
236pub enum Comparable {
237 /// Represents a literal value.
238 Literal(Literal),
239 /// Represents a function.
240 Function(TestFunction),
241 /// Represents a singular query.
242 SingularQuery(SingularQuery),
243}
244
245impl Display for Comparable {
246 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
247 match self {
248 Comparable::Literal(literal: &Literal) => write!(f, "{}", literal),
249 Comparable::Function(func: &TestFunction) => write!(f, "{}", func),
250 Comparable::SingularQuery(query: &SingularQuery) => write!(f, "{}", query),
251 }
252 }
253}
254
255/// Enum representing different types of singular queries in a JSONPath query.
256#[derive(Debug, Clone, PartialEq)]
257pub enum SingularQuery {
258 /// Represents a current node query.
259 Current(Vec<SingularQuerySegment>),
260 /// Represents a root node query.
261 Root(Vec<SingularQuerySegment>),
262}
263
264impl Display for SingularQuery {
265 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
266 match self {
267 SingularQuery::Current(segments: &Vec) => write!(
268 f,
269 "@.{}",
270 segments.iter().map(|s| s.to_string()).collect::<String>()
271 ),
272 SingularQuery::Root(segments: &Vec) => write!(
273 f,
274 "$.{}",
275 segments.iter().map(|s| s.to_string()).collect::<String>()
276 ),
277 }
278 }
279}
280
281/// Enum representing different types of singular query segments in a JSONPath query.
282#[derive(Debug, Clone, PartialEq)]
283pub enum SingularQuerySegment {
284 /// Represents an index segment.
285 Index(i64),
286 /// Represents a name segment.
287 Name(String),
288}
289
290impl Display for SingularQuerySegment {
291 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
292 match self {
293 SingularQuerySegment::Index(index: &i64) => write!(f, "{}", index),
294 SingularQuerySegment::Name(name: &String) => write!(f, "{}", name),
295 }
296 }
297}
298
299/// Enum representing different types of tests in a JSONPath query.
300#[derive(Debug, Clone, PartialEq)]
301pub enum Test {
302 /// Represents a relative query.
303 RelQuery(Vec<Segment>),
304 /// Represents an absolute query.
305 AbsQuery(JpQuery),
306 /// Represents a function test.
307 Function(Box<TestFunction>),
308}
309
310impl Test {
311 pub fn is_res_bool(&self) -> bool {
312 match self {
313 Test::RelQuery(_) => false,
314 Test::AbsQuery(_) => false,
315 Test::Function(func: &Box) => match **func {
316 TestFunction::Length(_) => false,
317 TestFunction::Value(_) => false,
318 TestFunction::Count(_) => false,
319 TestFunction::Custom(_, _) => true,
320 TestFunction::Search(_, _) => true,
321 TestFunction::Match(_, _) => true,
322 },
323 }
324 }
325}
326
327impl Display for Test {
328 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
329 match self {
330 Test::RelQuery(segments: &Vec) => write!(
331 f,
332 "{}",
333 segments.iter().map(|s| s.to_string()).collect::<String>()
334 ),
335 Test::AbsQuery(query: &JpQuery) => write!(f, "{}", query),
336 Test::Function(func: &Box) => write!(f, "{}", func),
337 }
338 }
339}
340
341/// Enum representing different types of test functions in a JSONPath query.
342#[derive(Debug, Clone, PartialEq)]
343pub enum TestFunction {
344 /// Represents a custom function.
345 Custom(String, Vec<FnArg>),
346 /// Represents a length function.
347 Length(Box<FnArg>),
348 /// Represents a value function.
349 Value(FnArg),
350 /// Represents a count function.
351 Count(FnArg),
352 /// Represents a search function.
353 Search(FnArg, FnArg),
354 /// Represents a match function.
355 Match(FnArg, FnArg),
356}
357
358impl TestFunction {
359 pub fn try_new(name: &str, args: Vec<FnArg>) -> Parsed<Self> {
360 fn with_node_type_validation<'a>(
361 a: &'a FnArg,
362 name: &str,
363 ) -> Result<&'a FnArg, JsonPathError> {
364 if a.is_lit() {
365 Err(JsonPathError::InvalidJsonPath(format!(
366 "Invalid argument for the function `{}`: expected a node, got a literal",
367 name
368 )))
369 } else if a.is_filter() {
370 Err(JsonPathError::InvalidJsonPath(format!(
371 "Invalid argument for the function `{}`: expected a node, got a filter",
372 name
373 )))
374 } else {
375 Ok(a)
376 }
377 }
378
379 match (name, args.as_slice()) {
380 ("length", [a]) => Ok(TestFunction::Length(Box::new(a.clone()))),
381 ("value", [a]) => Ok(TestFunction::Value(a.clone())),
382 ("count", [a]) => Ok(TestFunction::Count(
383 with_node_type_validation(a, name)?.clone(),
384 )),
385 ("search", [a, b]) => Ok(TestFunction::Search(a.clone(), b.clone())),
386 ("match", [a, b]) => Ok(TestFunction::Match(a.clone(), b.clone())),
387 ("length" | "value" | "count" | "match" | "search", args) => {
388 Err(JsonPathError::InvalidJsonPath(format!(
389 "Invalid number of arguments for the function `{}`: got {}",
390 name,
391 args.len()
392 )))
393 }
394 (custom, _) => Ok(TestFunction::Custom(custom.to_string(), args)),
395 }
396 }
397
398 pub fn is_comparable(&self) -> bool {
399 match self {
400 TestFunction::Length(_) => true,
401 TestFunction::Value(_) => true,
402 TestFunction::Count(_) => true,
403 TestFunction::Custom(_, _) => false,
404 TestFunction::Search(_, _) => false,
405 TestFunction::Match(_, _) => false,
406 }
407 }
408}
409
410impl Display for TestFunction {
411 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
412 match self {
413 TestFunction::Custom(name: &String, args: &Vec) => write!(
414 f,
415 "{}({})",
416 name,
417 args.iter().map(|a| a.to_string()).collect::<String>()
418 ),
419 TestFunction::Length(arg: &Box) => write!(f, "length({})", arg),
420 TestFunction::Value(arg: &FnArg) => write!(f, "value({})", arg),
421 TestFunction::Count(arg: &FnArg) => write!(f, "count({})", arg),
422 TestFunction::Search(arg1: &FnArg, arg2: &FnArg) => write!(f, "search({}, {})", arg1, arg2),
423 TestFunction::Match(arg1: &FnArg, arg2: &FnArg) => write!(f, "match({}, {})", arg1, arg2),
424 }
425 }
426}
427
428/// Enum representing different types of function arguments in a JSONPath query.
429#[derive(Debug, Clone, PartialEq)]
430pub enum FnArg {
431 /// Represents a literal argument.
432 Literal(Literal),
433 /// Represents a test argument.
434 Test(Box<Test>),
435 /// Represents a filter argument.
436 Filter(Filter),
437}
438
439impl FnArg {
440 pub fn is_lit(&self) -> bool {
441 matches!(self, FnArg::Literal(_))
442 }
443 pub fn is_filter(&self) -> bool {
444 matches!(self, FnArg::Filter(_))
445 }
446}
447
448impl Display for FnArg {
449 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
450 match self {
451 FnArg::Literal(literal: &Literal) => write!(f, "{}", literal),
452 FnArg::Test(test: &Box) => write!(f, "{}", test),
453 FnArg::Filter(filter: &Filter) => write!(f, "{}", filter),
454 }
455 }
456}
457
458/// Enum representing different types of literal values in a JSONPath query.
459#[derive(Debug, Clone, PartialEq)]
460pub enum Literal {
461 /// Represents an integer literal.
462 Int(i64),
463 /// Represents a floating-point literal.
464 Float(f64),
465 /// Represents a string literal.
466 String(String),
467 /// Represents a boolean literal.
468 Bool(bool),
469 /// Represents a null literal.
470 Null,
471}
472
473impl Display for Literal {
474 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475 match self {
476 Literal::Int(val: &i64) => write!(f, "{}", val),
477 Literal::Float(val: &f64) => write!(f, "{}", val),
478 Literal::String(val: &String) => write!(f, "\"{}\"", val),
479 Literal::Bool(val: &bool) => write!(f, "{}", val),
480 Literal::Null => write!(f, "null"),
481 }
482 }
483}
484