1use crate::parser::model::Selector;
2use crate::query::queryable::Queryable;
3use crate::query::state::{Data, Pointer, State};
4use crate::query::Query;
5use std::cmp::{max, min};
6
7impl Query for Selector {
8 fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
9 match self {
10 Selector::Name(key) => step.flat_map(|d| process_key(d, key)),
11 Selector::Index(idx) => step.flat_map(|d| process_index(d, idx)),
12 Selector::Wildcard => step.flat_map(process_wildcard),
13 Selector::Slice(start, end, sl_step) => {
14 step.flat_map(|d| process_slice(d, start, end, sl_step))
15 }
16 Selector::Filter(f) => f.process(step),
17 }
18 }
19}
20
21fn process_wildcard<T: Queryable>(
22 Pointer {
23 inner: pointer,
24 path,
25 }: Pointer<T>,
26) -> Data<T> {
27 if let Some(array) = pointer.as_array() {
28 if array.is_empty() {
29 Data::Nothing
30 } else {
31 Data::new_refs(
32 array
33 .iter()
34 .enumerate()
35 .map(|(i, elem)| Pointer::idx(elem, path.clone(), i))
36 .collect(),
37 )
38 }
39 } else if let Some(object) = pointer.as_object() {
40 if object.is_empty() {
41 Data::Nothing
42 } else {
43 Data::new_refs(
44 object
45 .into_iter()
46 .map(|(key, value)| Pointer::key(value, path.clone(), key))
47 .collect(),
48 )
49 }
50 } else {
51 Data::Nothing
52 }
53}
54
55fn process_slice<'a, T: Queryable>(
56 Pointer { inner, path }: Pointer<'a, T>,
57 start: &Option<i64>,
58 end: &Option<i64>,
59 step: &Option<i64>,
60) -> Data<'a, T> {
61 let extract_elems = |elements: &'a Vec<T>| -> Vec<(&'a T, usize)> {
62 let len = elements.len() as i64;
63 let norm = |i: i64| {
64 if i >= 0 {
65 i
66 } else {
67 len + i
68 }
69 };
70
71 match step.unwrap_or(1) {
72 e if e > 0 => {
73 let n_start = norm(start.unwrap_or(0));
74 let n_end = norm(end.unwrap_or(len));
75 let lower = min(max(n_start, 0), len);
76 let upper = min(max(n_end, 0), len);
77
78 let mut idx = lower;
79 let mut res = vec![];
80 while idx < upper {
81 let i = idx as usize;
82 if let Some(elem) = elements.get(i) {
83 res.push((elem, i));
84 }
85 idx += e;
86 }
87 res
88 }
89 e if e < 0 => {
90 let n_start = norm(start.unwrap_or(len - 1));
91 let n_end = norm(end.unwrap_or(-len - 1));
92 let lower = min(max(n_end, -1), len - 1);
93 let upper = min(max(n_start, -1), len - 1);
94 let mut idx = upper;
95 let mut res = vec![];
96 while lower < idx {
97 let i = idx as usize;
98 if let Some(elem) = elements.get(i) {
99 res.push((elem, i));
100 }
101 idx += e;
102 }
103 res
104 }
105 _ => vec![],
106 }
107 };
108
109 let elems_to_step = |v: Vec<(&'a T, usize)>| {
110 Data::new_refs(
111 v.into_iter()
112 .map(|(elem, i)| Pointer::idx(elem, path.clone(), i))
113 .collect(),
114 )
115 };
116
117 inner
118 .as_array()
119 .map(extract_elems)
120 .map(elems_to_step)
121 .unwrap_or_default()
122}
123
124fn normalize_json_key(input: &str) -> String {
129 let mut result = String::with_capacity(input.len());
130 let mut chars = input.chars().peekable();
131
132 while let Some(c) = chars.next() {
133 if c == '\\' {
134 if let Some(&next) = chars.peek() {
135 match next {
136 '\\' => {
137 result.push('\\');
138 chars.next(); }
140 '/' => {
141 result.push('/');
142 chars.next(); }
144 '\'' => {
145 result.push('\\');
146 result.push('\'');
147 chars.next(); }
149 '"' => {
150 result.push('\\');
151 result.push('"');
152 chars.next(); }
154 'b' | 'f' | 'n' | 'r' | 't' | 'u' => {
155 result.push('\\');
157 result.push(next);
158 chars.next();
159 }
160 _ => {
161 result.push('\\');
163 }
164 }
165 } else {
166 result.push('\\');
168 }
169 } else {
170 result.push(c);
171 }
172 }
173 result
174}
175
176pub fn process_key<'a, T: Queryable>(
177 Pointer { inner, path }: Pointer<'a, T>,
178 key: &str,
179) -> Data<'a, T> {
180 inner
181 .get(normalize_json_key(key).as_str())
182 .map(|v| Data::new_ref(Pointer::key(v, path, key)))
183 .unwrap_or_default()
184}
185
186pub fn process_index<'a, T: Queryable>(
187 Pointer { inner, path }: Pointer<'a, T>,
188 idx: &i64,
189) -> Data<'a, T> {
190 inner
191 .as_array()
192 .map(|array| {
193 if *idx >= 0 {
194 if *idx >= array.len() as i64 {
195 Data::Nothing
196 } else {
197 let i = *idx as usize;
198 Data::new_ref(Pointer::idx(&array[i], path, i))
199 }
200 } else {
201 let abs_idx = idx.abs() as usize;
202 if abs_idx > array.len() {
203 Data::Nothing
204 } else {
205 let i = array.len() - abs_idx;
206 Data::new_ref(Pointer::idx(&array[i], path, i))
207 }
208 }
209 })
210 .unwrap_or_default()
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216 use crate::parser::model::Segment;
217 use crate::query::{js_path, Queried};
218 use serde_json::json;
219 use std::vec;
220 #[test]
221 fn test_process_empty_key() {
222 let value = json!({" ": "value"});
223 let segment = Segment::Selector(Selector::Name(" ".to_string()));
224
225 let step = segment.process(State::root(&value));
226
227 assert_eq!(
228 step.ok_ref(),
229 Some(vec![Pointer::new(&json!("value"), "$[' ']".to_string())])
230 );
231 }
232 #[test]
233 fn test_process_key() {
234 let value = json!({"key": "value"});
235 let segment = Segment::Selector(Selector::Name("key".to_string()));
236
237 let step = segment.process(State::root(&value));
238
239 assert_eq!(
240 step.ok_ref(),
241 Some(vec![Pointer::new(&json!("value"), "$['key']".to_string())])
242 );
243 }
244
245 #[test]
246 fn test_process_key_failed() {
247 let value = json!({"key": "value"});
248 let segment = Segment::Selector(Selector::Name("key2".to_string()));
249 let step = segment.process(State::root(&value));
250
251 assert_eq!(step, State::nothing(&value));
252 }
253
254 #[test]
255 fn test_process_index() {
256 let value = json!([1, 2, 3]);
257 let segment = Segment::Selector(Selector::Index(1));
258 let step = segment.process(State::root(&value));
259
260 assert_eq!(
261 step.ok_ref(),
262 Some(vec![Pointer::new(&json!(2), "$[1]".to_string())])
263 );
264 }
265
266 #[test]
267 fn test_process_index_failed() {
268 let value = json!([1, 2, 3]);
269 let segment = Segment::Selector(Selector::Index(3));
270 let step = segment.process(State::root(&value));
271
272 assert_eq!(step, State::nothing(&value));
273 }
274
275 #[test]
276 fn test_process_slice1() {
277 let value = json!([1, 2, 3, 4, 5]);
278 let segment = Segment::Selector(Selector::Slice(Some(1), Some(4), Some(1)));
279 let step = segment.process(State::root(&value));
280
281 assert_eq!(
282 step.ok_ref(),
283 Some(vec![
284 Pointer::new(&json!(2), "$[1]".to_string()),
285 Pointer::new(&json!(3), "$[2]".to_string()),
286 Pointer::new(&json!(4), "$[3]".to_string())
287 ])
288 );
289 }
290
291 #[test]
292 fn test_process_slice2() {
293 let value = json!([1, 2, 3, 4, 5]);
294 let segment = Segment::Selector(Selector::Slice(Some(2), Some(0), Some(-1)));
295 let step = segment.process(State::root(&value));
296
297 assert_eq!(
298 step.ok_ref(),
299 Some(vec![
300 Pointer::new(&json!(3), "$[2]".to_string()),
301 Pointer::new(&json!(2), "$[1]".to_string()),
302 ])
303 );
304 }
305
306 #[test]
307 fn test_process_slice3() {
308 let value = json!([1, 2, 3, 4, 5]);
309 let segment = Segment::Selector(Selector::Slice(Some(0), Some(5), Some(2)));
310 let step = segment.process(State::root(&value));
311
312 assert_eq!(
313 step.ok_ref(),
314 Some(vec![
315 Pointer::new(&json!(1), "$[0]".to_string()),
316 Pointer::new(&json!(3), "$[2]".to_string()),
317 Pointer::new(&json!(5), "$[4]".to_string())
318 ])
319 );
320 }
321
322 #[test]
323 fn test_process_slice_failed() {
324 let value = json!([1, 2, 3, 4, 5]);
325 let segment = Segment::Selector(Selector::Slice(Some(0), Some(5), Some(0)));
326 let step = segment.process(State::root(&value));
327
328 assert_eq!(step.ok_ref(), Some(vec![]));
329 }
330
331 #[test]
332 fn test_process_wildcard() {
333 let value = json!({"key": "value", "key2": "value2"});
334 let segment = Segment::Selector(Selector::Wildcard);
335 let step = segment.process(State::root(&value));
336
337 assert_eq!(
338 step.ok_ref(),
339 Some(vec![
340 Pointer::new(&json!("value"), "$['key']".to_string()),
341 Pointer::new(&json!("value2"), "$['key2']".to_string())
342 ])
343 );
344 }
345
346 #[test]
347 fn test_process_wildcard_array() {
348 let value = json!([1, 2, 3]);
349 let segment = Segment::Selector(Selector::Wildcard);
350 let step = segment.process(State::root(&value));
351
352 assert_eq!(
353 step.ok_ref(),
354 Some(vec![
355 Pointer::new(&json!(1), "$[0]".to_string()),
356 Pointer::new(&json!(2), "$[1]".to_string()),
357 Pointer::new(&json!(3), "$[2]".to_string())
358 ])
359 );
360 }
361
362 #[test]
363 fn test_process_wildcard_failed() {
364 let value = json!(1);
365 let segment = Segment::Selector(Selector::Wildcard);
366 let step = segment.process(State::root(&value));
367
368 assert_eq!(step, State::nothing(&value));
369 }
370
371 #[test]
372 fn multi_selector() -> Queried<()> {
373 let json = json!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
374
375 let vec = js_path("$['a',1]", &json)?;
376
377 assert_eq!(vec, vec![(&json!(1), "$[1]".to_string()).into(),]);
378
379 Ok(())
380 }
381 #[test]
382 fn multi_selector_space() -> Queried<()> {
383 let json = json!({
384 "a": "ab",
385 "b": "bc"
386 });
387
388 let vec = js_path("$['a',\r'b']", &json)?;
389
390 assert_eq!(
391 vec,
392 vec![
393 (&json!("ab"), "$['a']".to_string()).into(),
394 (&json!("bc"), "$['b']".to_string()).into(),
395 ]
396 );
397
398 Ok(())
399 }
400}