jsonpath_rust/query/
state.rs

1use crate::query::queryable::Queryable;
2use crate::query::QueryPath;
3use std::fmt::{Display, Formatter};
4
5/// Represents the state of a query, including the current data and the root object.
6/// It is used to track the progress of a query as it traverses through the data structure.
7#[derive(Debug, Clone, PartialEq)]
8pub struct State<'a, T: Queryable> {
9    pub data: Data<'a, T>,
10    pub root: &'a T,
11}
12
13impl<'a, T: Queryable> Display for State<'a, T> {
14    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15        write!(f, "{}", self.data)
16    }
17}
18
19impl<'a, T: Queryable> From<&'a T> for State<'a, T> {
20    fn from(root: &'a T) -> Self {
21        State::root(root)
22    }
23}
24
25impl<'a, T: Queryable> State<'a, T> {
26    pub fn bool(b: bool, root: &T) -> State<T> {
27        State::data(root, Data::Value(b.into()))
28    }
29
30    pub fn i64(i: i64, root: &T) -> State<T> {
31        State::data(root, Data::Value(i.into()))
32    }
33    pub fn str(v: &str, root: &'a T) -> State<'a, T> {
34        State::data(root, Data::Value(v.into()))
35    }
36
37    pub fn shift_to_root(self) -> State<'a, T> {
38        State::root(self.root)
39    }
40
41    pub fn root(root: &'a T) -> Self {
42        State {
43            root,
44            data: Data::new_ref(Pointer::new(root, "$".to_string())),
45        }
46    }
47
48    pub fn nothing(root: &'a T) -> Self {
49        State {
50            root,
51            data: Data::Nothing,
52        }
53    }
54
55    pub fn data(root: &'a T, data: Data<'a, T>) -> Self {
56        State { root, data }
57    }
58
59    pub fn ok_ref(self) -> Option<Vec<Pointer<'a, T>>> {
60        self.data.ok_ref()
61    }
62
63    pub fn ok_val(self) -> Option<T> {
64        match self.data {
65            Data::Value(v) => Some(v),
66            _ => None,
67        }
68    }
69
70    pub fn is_nothing(&self) -> bool {
71        matches!(&self.data, Data::Nothing)
72    }
73
74    pub fn reduce(self, other: State<'a, T>) -> State<'a, T> {
75        State {
76            root: self.root,
77            data: self.data.reduce(other.data),
78        }
79    }
80    pub fn flat_map<F>(self, f: F) -> State<'a, T>
81    where
82        F: Fn(Pointer<'a, T>) -> Data<'a, T>,
83    {
84        State {
85            root: self.root,
86            data: self.data.flat_map(f),
87        }
88    }
89}
90
91/// Represents the data that is being processed in the query.
92/// It can be a reference to a single object, a collection of references,
93#[derive(Debug, Clone, PartialEq)]
94pub enum Data<'a, T: Queryable> {
95    Ref(Pointer<'a, T>),
96    Refs(Vec<Pointer<'a, T>>),
97    Value(T),
98    Nothing,
99}
100
101impl<'a, T: Queryable> Display for Data<'a, T> {
102    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
103        match self {
104            Data::Ref(p) => write!(f, "&{}", p),
105            Data::Refs(p) => write!(
106                f,
107                "{}",
108                p.iter()
109                    .map(|ptr| ptr.to_string())
110                    .collect::<Vec<_>>()
111                    .join("; ")
112            ),
113            Data::Value(v) => write!(f, "{:?}", v),
114            Data::Nothing => write!(f, "Nothing"),
115        }
116    }
117}
118
119impl<'a, T: Queryable> Default for Data<'a, T> {
120    fn default() -> Self {
121        Data::Nothing
122    }
123}
124
125impl<'a, T: Queryable> Data<'a, T> {
126    pub fn reduce(self, other: Data<'a, T>) -> Data<'a, T> {
127        match (self, other) {
128            (Data::Ref(data), Data::Ref(data2)) => Data::Refs(vec![data, data2]),
129            (Data::Ref(data), Data::Refs(data_vec)) => {
130                Data::Refs(vec![data].into_iter().chain(data_vec).collect())
131            }
132            (Data::Refs(data_vec), Data::Ref(data)) => {
133                Data::Refs(data_vec.into_iter().chain(vec![data]).collect())
134            }
135            (Data::Refs(data_vec), Data::Refs(data_vec2)) => {
136                Data::Refs(data_vec.into_iter().chain(data_vec2).collect())
137            }
138            (d @ (Data::Ref(_) | Data::Refs(..)), Data::Nothing) => d,
139            (Data::Nothing, d @ (Data::Ref(_) | Data::Refs(..))) => d,
140            _ => Data::Nothing,
141        }
142    }
143
144    pub fn flat_map<F>(self, f: F) -> Data<'a, T>
145    where
146        F: Fn(Pointer<'a, T>) -> Data<'a, T>,
147    {
148        match self {
149            Data::Ref(data) => f(data),
150            Data::Refs(data_vec) => Data::Refs(
151                data_vec
152                    .into_iter()
153                    .flat_map(|data| match f(data) {
154                        Data::Ref(data) => vec![data],
155                        Data::Refs(data_vec) => data_vec,
156                        _ => vec![],
157                    })
158                    .collect::<Vec<_>>(),
159            ),
160            _ => Data::Nothing,
161        }
162    }
163
164    /// Returns the inner value if it is a single reference.
165    /// If it is a collection of references, it returns the first one.
166    /// If it is a value, it returns None.
167    pub fn ok_ref(self) -> Option<Vec<Pointer<'a, T>>> {
168        match self {
169            Data::Ref(data) => Some(vec![data]),
170            Data::Refs(data) => Some(data),
171            _ => None,
172        }
173    }
174
175    /// Returns the inner value if it is a single value.
176    /// If it is a reference or a collection of references, it returns None.
177    pub fn ok_val(self) -> Option<T> {
178        match self {
179            Data::Value(v) => Some(v),
180            _ => None,
181        }
182    }
183
184    pub fn new_ref(data: Pointer<'a, T>) -> Data<'a, T> {
185        Data::Ref(data)
186    }
187
188    pub fn new_refs(data: Vec<Pointer<'a, T>>) -> Data<'a, T> {
189        Data::Refs(data)
190    }
191}
192
193/// Represents a pointer to a specific location in the data structure.
194/// It contains a reference to the data and a path that indicates the location of the data in the structure.
195#[derive(Debug, Clone, PartialEq)]
196pub(crate) struct Pointer<'a, T: Queryable> {
197    pub inner: &'a T,
198    pub path: QueryPath,
199}
200
201impl<'a, T: Queryable> Display for Pointer<'a, T> {
202    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203        write!(f, "{:?}='{}'", self.inner, self.path)
204    }
205}
206
207impl<'a, T: Queryable> Pointer<'a, T> {
208    pub fn new(inner: &'a T, path: QueryPath) -> Self {
209        Pointer { inner, path }
210    }
211
212    pub fn key(inner: &'a T, path: QueryPath, key: &str) -> Self {
213        let path = if key.starts_with("'") && key.ends_with("'") {
214            format!("{}[{}]", path, key)
215        } else {
216            format!("{}['{}']", path, key)
217        };
218
219        Pointer { inner, path }
220    }
221    pub fn idx(inner: &'a T, path: QueryPath, index: usize) -> Self {
222        Pointer {
223            inner,
224            path: format!("{}[{}]", path, index),
225        }
226    }
227
228    pub fn empty(inner: &'a T) -> Self {
229        Pointer {
230            inner,
231            path: String::new(),
232        }
233    }
234
235    pub fn is_internal(&self) -> bool {
236        self.path.is_empty()
237    }
238}