1use crate::parser::errors::JsonPathError;
2use crate::parser::Parsed;
3use std::fmt::{Display, Formatter};
4
5#[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#[derive(Debug, Clone, PartialEq)]
31pub enum Segment {
32 Descendant(Box<Segment>),
34 Selector(Selector),
36 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) => write!(f, "..{}", s),
50 Segment::Selector(selector) => write!(f, "{}", selector),
51 Segment::Selectors(selectors) => write!(
52 f,
53 "{}",
54 selectors.iter().map(|s| s.to_string()).collect::<String>()
55 ),
56 }
57 }
58}
59#[derive(Debug, Clone, PartialEq)]
61pub enum Selector {
62 Name(String),
64 Wildcard,
66 Index(i64),
68 Slice(Option<i64>, Option<i64>, Option<i64>),
70 Filter(Filter),
72}
73
74pub fn slice_from((start, end, step): (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) => write!(f, "{}", name),
82 Selector::Wildcard => write!(f, "*"),
83 Selector::Index(index) => write!(f, "{}", index),
84 Selector::Slice(start, end, step) => write!(
85 f,
86 "{}:{}:{}",
87 start.unwrap_or(0),
88 end.unwrap_or(0),
89 step.unwrap_or(1)
90 ),
91 Selector::Filter(filter) => write!(f, "[?{}]", filter),
92 }
93 }
94}
95#[derive(Debug, Clone, PartialEq)]
97pub enum Filter {
98 Or(Vec<Filter>),
100 And(Vec<Filter>),
102 Atom(FilterAtom),
104}
105
106impl Display for Filter {
107 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
108 let items_to_str = |items: &Vec<Filter>, sep: &str| {
109 items
110 .iter()
111 .map(|f| f.to_string())
112 .collect::<Vec<_>>()
113 .join(sep)
114 };
115
116 match self {
117 Filter::Or(filters) => write!(f, "{}", items_to_str(filters, " || ")),
118 Filter::And(filters) => write!(f, "{}", items_to_str(filters, " && ")),
119 Filter::Atom(atom) => write!(f, "{}", atom),
120 }
121 }
122}
123
124#[derive(Debug, Clone, PartialEq)]
126pub enum FilterAtom {
127 Filter { expr: Box<Filter>, not: bool },
129 Test { expr: Box<Test>, not: bool },
131 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, not } => {
159 if *not {
160 write!(f, "!{}", expr)
161 } else {
162 write!(f, "{}", expr)
163 }
164 }
165 FilterAtom::Test { expr, not } => {
166 if *not {
167 write!(f, "!{}", expr)
168 } else {
169 write!(f, "{}", expr)
170 }
171 }
172 FilterAtom::Comparison(cmp) => write!(f, "{}", cmp),
173 }
174 }
175}
176#[derive(Debug, Clone, PartialEq)]
178pub enum Comparison {
179 Eq(Comparable, Comparable),
181 Ne(Comparable, Comparable),
183 Gt(Comparable, Comparable),
185 Gte(Comparable, Comparable),
187 Lt(Comparable, Comparable),
189 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, right) => write!(f, "{} == {}", left, right),
225 Comparison::Ne(left, right) => write!(f, "{} != {}", left, right),
226 Comparison::Gt(left, right) => write!(f, "{} > {}", left, right),
227 Comparison::Gte(left, right) => write!(f, "{} >= {}", left, right),
228 Comparison::Lt(left, right) => write!(f, "{} < {}", left, right),
229 Comparison::Lte(left, right) => write!(f, "{} <= {}", left, right),
230 }
231 }
232}
233
234#[derive(Debug, Clone, PartialEq)]
236pub enum Comparable {
237 Literal(Literal),
239 Function(TestFunction),
241 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) => write!(f, "{}", literal),
249 Comparable::Function(func) => write!(f, "{}", func),
250 Comparable::SingularQuery(query) => write!(f, "{}", query),
251 }
252 }
253}
254
255#[derive(Debug, Clone, PartialEq)]
257pub enum SingularQuery {
258 Current(Vec<SingularQuerySegment>),
260 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) => write!(
268 f,
269 "@.{}",
270 segments.iter().map(|s| s.to_string()).collect::<String>()
271 ),
272 SingularQuery::Root(segments) => write!(
273 f,
274 "$.{}",
275 segments.iter().map(|s| s.to_string()).collect::<String>()
276 ),
277 }
278 }
279}
280
281#[derive(Debug, Clone, PartialEq)]
283pub enum SingularQuerySegment {
284 Index(i64),
286 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) => write!(f, "{}", index),
294 SingularQuerySegment::Name(name) => write!(f, "{}", name),
295 }
296 }
297}
298
299#[derive(Debug, Clone, PartialEq)]
301pub enum Test {
302 RelQuery(Vec<Segment>),
304 AbsQuery(JpQuery),
306 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) => 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) => write!(
331 f,
332 "{}",
333 segments.iter().map(|s| s.to_string()).collect::<String>()
334 ),
335 Test::AbsQuery(query) => write!(f, "{}", query),
336 Test::Function(func) => write!(f, "{}", func),
337 }
338 }
339}
340
341#[derive(Debug, Clone, PartialEq)]
343pub enum TestFunction {
344 Custom(String, Vec<FnArg>),
346 Length(Box<FnArg>),
348 Value(FnArg),
350 Count(FnArg),
352 Search(FnArg, FnArg),
354 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, args) => write!(
414 f,
415 "{}({})",
416 name,
417 args.iter().map(|a| a.to_string()).collect::<String>()
418 ),
419 TestFunction::Length(arg) => write!(f, "length({})", arg),
420 TestFunction::Value(arg) => write!(f, "value({})", arg),
421 TestFunction::Count(arg) => write!(f, "count({})", arg),
422 TestFunction::Search(arg1, arg2) => write!(f, "search({}, {})", arg1, arg2),
423 TestFunction::Match(arg1, arg2) => write!(f, "match({}, {})", arg1, arg2),
424 }
425 }
426}
427
428#[derive(Debug, Clone, PartialEq)]
430pub enum FnArg {
431 Literal(Literal),
433 Test(Box<Test>),
435 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) => write!(f, "{}", literal),
452 FnArg::Test(test) => write!(f, "{}", test),
453 FnArg::Filter(filter) => write!(f, "{}", filter),
454 }
455 }
456}
457
458#[derive(Debug, Clone, PartialEq)]
460pub enum Literal {
461 Int(i64),
463 Float(f64),
465 String(String),
467 Bool(bool),
469 Null,
471}
472
473impl Display for Literal {
474 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475 match self {
476 Literal::Int(val) => write!(f, "{}", val),
477 Literal::Float(val) => write!(f, "{}", val),
478 Literal::String(val) => write!(f, "\"{}\"", val),
479 Literal::Bool(val) => write!(f, "{}", val),
480 Literal::Null => write!(f, "null"),
481 }
482 }
483}