jsonpath_rust/parser/
model.rs

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/// The basic structures for parsing json paths.
11/// The common logic of the structures pursues to correspond the internal parsing structure.
12///
13/// usually it's created by using [`FromStr`] or [`TryFrom<&str>`]
14#[derive(Debug, Clone)]
15pub enum JsonPath<T = Value> {
16    /// The $ operator
17    Root,
18    /// Field represents key
19    Field(String),
20    /// The whole chain of the path.
21    Chain(Vec<JsonPath<T>>),
22    /// The .. operator
23    Descent(String),
24    /// The ..* operator
25    DescentW,
26    /// The indexes for array
27    Index(JsonPathIndex<T>),
28    /// The @ operator
29    Current(Box<JsonPath<T>>),
30    /// The * operator
31    Wildcard,
32    /// The item uses to define the unresolved state
33    Empty,
34    /// Functions that can calculate some expressions
35    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    /// Parses a string into a [JsonPath].
65    ///
66    /// # Errors
67    ///
68    /// Returns a variant of [JsonPathParserError] if the parsing operation failed.
69    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    /// Parses a string into a [JsonPath].
81    ///
82    /// # Errors
83    ///
84    /// Returns a variant of [JsonPathParserError] if the parsing operation failed.
85    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()
93    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    /// A single element in array
108    Single(T),
109    /// Union represents a several indexes
110    UnionIndex(Vec<T>),
111    /// Union represents a several keys
112    UnionKeys(Vec<String>),
113    /// DEfault slice where the items are start/end/step respectively
114    Slice(i32, i32, usize),
115    /// Filter ?()
116    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    /// a single expression like a > 2
155    Atom(Operand<T>, FilterSign, Operand<T>),
156    /// and with &&
157    And(Box<FilterExpression<T>>, Box<FilterExpression<T>>),
158    /// or with ||
159    Or(Box<FilterExpression<T>>, Box<FilterExpression<T>>),
160    /// not with !
161    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/// Operand for filtering expressions
195#[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/// The operators for filtering functions
219#[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}