jsonpath_lib/selector/
selector_impl.rs

1use std::collections::HashSet;
2use std::rc::Rc;
3
4use serde_json::{Number, Value};
5use serde_json::map::Entry;
6
7use JsonPathError;
8use paths::{ParserTokenHandler, PathParser, StrRange, tokens::*};
9use super::utils;
10
11use super::terms::*;
12
13#[derive(Debug, Default)]
14pub struct JsonSelector<'a> {
15    parser: Option<Rc<PathParser<'a>>>,
16    value: Option<&'a Value>,
17    tokens: Vec<ParseToken>,
18    current: Option<Vec<&'a Value>>,
19    selectors: Vec<JsonSelector<'a>>,
20    selector_filter: FilterTerms<'a>,
21}
22
23impl<'a> JsonSelector<'a> {
24    pub fn new(parser: PathParser<'a>) -> Self {
25        JsonSelector {
26            parser: Some(Rc::new(parser)),
27            value: None,
28            tokens: Vec::new(),
29            current: None,
30            selectors: Vec::new(),
31            selector_filter: FilterTerms(Vec::new()),
32        }
33    }
34
35    pub fn new_ref(parser: Rc<PathParser<'a>>) -> Self {
36        JsonSelector {
37            parser: Some(parser),
38            value: None,
39            tokens: Vec::new(),
40            current: None,
41            selectors: Vec::new(),
42            selector_filter: FilterTerms(Vec::new()),
43        }
44    }
45
46    pub fn reset_parser(&mut self, parser: PathParser<'a>) -> &mut Self {
47        self.parser = Some(Rc::new(parser));
48        self
49    }
50
51    pub fn reset_parser_ref(&mut self, parser: Rc<PathParser<'a>>) -> &mut Self {
52        self.parser = Some(parser);
53        self
54    }
55
56    pub fn reset_value(&mut self) -> &mut Self {
57        self.current = None;
58        self
59    }
60
61    pub fn value(&mut self, v: &'a Value) -> &mut Self {
62        self.value = Some(v);
63        self
64    }
65
66    fn _select(&mut self) -> Result<(), JsonPathError> {
67        let parser = self.parser.take();
68        if let Some(parser) = parser.as_ref() {
69            let _ = parser.parse(self);
70        }
71        self.parser = parser;
72
73        Ok(())
74    }
75
76    pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
77        self._select()?;
78
79        match &self.current {
80            Some(vec) => {
81                let mut ret = Vec::new();
82                for v in vec {
83                    match T::deserialize(*v) {
84                        Ok(v) => ret.push(v),
85                        Err(e) => return Err(JsonPathError::Serde(e.to_string())),
86                    }
87                }
88                Ok(ret)
89            }
90            _ => Err(JsonPathError::EmptyValue),
91        }
92    }
93
94    pub fn select_as_str(&mut self) -> Result<String, JsonPathError> {
95        self._select()?;
96
97        match &self.current {
98            Some(r) => {
99                Ok(serde_json::to_string(r).map_err(|e| JsonPathError::Serde(e.to_string()))?)
100            }
101            _ => Err(JsonPathError::EmptyValue),
102        }
103    }
104
105    pub fn select(&mut self) -> Result<Vec<&'a Value>, JsonPathError> {
106        self._select()?;
107
108        match &self.current {
109            Some(r) => Ok(r.to_vec()),
110            _ => Err(JsonPathError::EmptyValue),
111        }
112    }
113
114    fn compute_absolute_path_filter<F>(&mut self, token: &ParseToken, parse_value_reader: &F) -> bool
115        where
116            F: Fn(&StrRange) -> &'a str
117    {
118        if !self.selectors.is_empty() {
119            match token {
120                ParseToken::Absolute | ParseToken::Relative | ParseToken::Filter(_) => {
121                    let selector = self.selectors.pop().unwrap();
122
123                    if let Some(current) = &selector.current {
124                        let term = current.into();
125
126                        if let Some(s) = self.selectors.last_mut() {
127                            s.selector_filter.push_term(Some(term));
128                        } else {
129                            self.selector_filter.push_term(Some(term));
130                        }
131                    } else {
132                        unreachable!()
133                    }
134                }
135                _ => {}
136            }
137        }
138
139        if self.selectors.is_empty() {
140            return false;
141        }
142
143        self.selectors.last_mut().unwrap().handle(token, parse_value_reader);
144        true
145    }
146}
147
148impl<'a> JsonSelector<'a> {
149    fn visit_absolute(&mut self) {
150        if self.current.is_some() {
151            if let Some(value) = self.value {
152                let selector = JsonSelector {
153                    parser: None,
154                    value: Some(value),
155                    tokens: Vec::new(),
156                    current: Some(vec![value]),
157                    selectors: Vec::new(),
158                    selector_filter: FilterTerms(Vec::new()),
159                };
160                self.selectors.push(selector);
161            }
162            return;
163        }
164
165        if let Some(v) = &self.value {
166            self.current = Some(vec![v]);
167        }
168    }
169
170    fn visit_relative(&mut self) {
171        if let Some(ParseToken::Array) = self.tokens.last() {
172            let array_token = self.tokens.pop();
173            if let Some(ParseToken::Leaves) = self.tokens.last() {
174                self.tokens.pop();
175                self.current = self.selector_filter.collect_all(self.current.take());
176            }
177            self.tokens.push(array_token.unwrap());
178        }
179        self.selector_filter.new_filter_context();
180    }
181
182    fn visit_array_eof(&mut self) {
183        if self.is_last_before_token_match(ParseToken::Array) {
184            if let Some(Some(e)) = self.selector_filter.pop_term() {
185                if let ExprTerm::String(key) = e {
186                    self.current = self.selector_filter.filter_next_with_str(self.current.take(), key);
187                    self.tokens.pop();
188                    return;
189                }
190
191                self.selector_filter.push_term(Some(e));
192            }
193        }
194
195        if self.is_last_before_token_match(ParseToken::Leaves) {
196            self.tokens.pop();
197            self.tokens.pop();
198            if let Some(Some(e)) = self.selector_filter.pop_term() {
199                let selector_filter_consumed = match e {
200                    ExprTerm::Number(n) => {
201                        self.current = self.selector_filter.collect_all_with_num(self.current.take(), utils::to_f64(&n));
202                        self.selector_filter.pop_term();
203                        true
204                    }
205                    ExprTerm::String(key) => {
206                        self.current = self.selector_filter.collect_all_with_str(self.current.take(), key);
207                        self.selector_filter.pop_term();
208                        true
209                    }
210                    _ => {
211                        self.selector_filter.push_term(Some(e));
212                        false
213                    }
214                };
215
216                if selector_filter_consumed {
217                    return;
218                }
219            }
220        }
221
222        if let Some(Some(e)) = self.selector_filter.pop_term() {
223            match e {
224                ExprTerm::Number(n) => {
225                    self.current = self.selector_filter.collect_next_with_num(self.current.take(), utils::to_f64(&n));
226                }
227                ExprTerm::String(key) => {
228                    self.current = self.selector_filter.collect_next_with_str(self.current.take(), &[key]);
229                }
230                ExprTerm::Json(rel, _, v) => {
231                    if v.is_empty() {
232                        self.current = Some(Vec::new());
233                    } else if let Some(vec) = rel {
234                        self.current = Some(vec);
235                    } else {
236                        self.current = Some(v);
237                    }
238                }
239                ExprTerm::Bool(false) => {
240                    self.current = Some(vec![]);
241                }
242                _ => {}
243            }
244        }
245
246        self.tokens.pop();
247    }
248
249    fn is_last_before_token_match(&mut self, token: ParseToken) -> bool {
250        if self.tokens.len() > 1 {
251            return token == self.tokens[self.tokens.len() - 2];
252        }
253
254        false
255    }
256
257    fn visit_all(&mut self) {
258        if let Some(ParseToken::Array) = self.tokens.last() {
259            self.tokens.pop();
260        }
261
262        match self.tokens.last() {
263            Some(ParseToken::Leaves) => {
264                self.tokens.pop();
265                self.current = self.selector_filter.collect_all(self.current.take());
266            }
267            Some(ParseToken::In) => {
268                self.tokens.pop();
269                self.current = self.selector_filter.collect_next_all(self.current.take());
270            }
271            _ => {
272                self.current = self.selector_filter.collect_next_all(self.current.take());
273            }
274        }
275    }
276
277    fn visit_key(&mut self, key: &'a str) {
278        if let Some(ParseToken::Array) = self.tokens.last() {
279            self.selector_filter.push_term(Some(ExprTerm::String(key)));
280            return;
281        }
282
283        if let Some(t) = self.tokens.pop() {
284            if self.selector_filter.is_term_empty() {
285                match t {
286                    ParseToken::Leaves => {
287                        self.current = self.selector_filter.collect_all_with_str(self.current.take(), key)
288                    }
289                    ParseToken::In => {
290                        self.current = self.selector_filter.collect_next_with_str(self.current.take(), &[key])
291                    }
292                    _ => {}
293                }
294            } else {
295                match t {
296                    ParseToken::Leaves => {
297                        self.current = self.selector_filter.filter_all_with_str(self.current.take(), key);
298                    }
299                    ParseToken::In => {
300                        self.current = self.selector_filter.filter_next_with_str(self.current.take(), key);
301                    }
302                    _ => {}
303                }
304            }
305        }
306    }
307
308    fn visit_keys(&mut self, keys: &[&'a str]) {
309        if !self.selector_filter.is_term_empty() {
310            unimplemented!("keys in filter");
311        }
312
313        if let Some(ParseToken::Array) = self.tokens.pop() {
314            self.current = self.selector_filter.collect_next_with_str(self.current.take(), keys);
315        } else {
316            unreachable!();
317        }
318    }
319
320    fn visit_filter(&mut self, ft: &FilterToken) {
321        let right = match self.selector_filter.pop_term() {
322            Some(Some(right)) => right,
323            Some(None) => ExprTerm::Json(
324                None,
325                None,
326                match &self.current {
327                    Some(current) => current.to_vec(),
328                    _ => unreachable!(),
329                },
330            ),
331            _ => panic!("empty term right"),
332        };
333
334        let mut left = match self.selector_filter.pop_term() {
335            Some(Some(left)) => left,
336            Some(None) => ExprTerm::Json(
337                None,
338                None,
339                match &self.current {
340                    Some(current) => current.to_vec(),
341                    _ => unreachable!(),
342                },
343            ),
344            _ => panic!("empty term left"),
345        };
346
347        let expr = match ft {
348            FilterToken::Equal => left.eq_(right),
349            FilterToken::NotEqual => left.ne_(right),
350            FilterToken::Greater => left.gt(right),
351            FilterToken::GreaterOrEqual => left.ge(right),
352            FilterToken::Little => left.lt(right),
353            FilterToken::LittleOrEqual => left.le(right),
354            FilterToken::And => left.and(right),
355            FilterToken::Or => left.or(right),
356        };
357
358        self.selector_filter.push_term(Some(expr));
359    }
360
361    fn visit_range(&mut self, from: &Option<isize>, to: &Option<isize>, step: &Option<usize>) {
362        if !self.selector_filter.is_term_empty() {
363            unimplemented!("range syntax in filter");
364        }
365
366        if let Some(ParseToken::Array) = self.tokens.pop() {
367            let mut tmp = Vec::new();
368            if let Some(current) = &self.current {
369                for v in current {
370                    if let Value::Array(vec) = v {
371                        let from = if let Some(from) = from {
372                            utils::abs_index(*from, vec.len())
373                        } else {
374                            0
375                        };
376
377                        let to = if let Some(to) = to {
378                            utils::abs_index(*to, vec.len())
379                        } else {
380                            vec.len()
381                        };
382
383                        for i in (from..to).step_by(match step {
384                            Some(step) => *step,
385                            _ => 1,
386                        }) {
387                            if let Some(v) = vec.get(i) {
388                                tmp.push(v);
389                            }
390                        }
391                    }
392                }
393            }
394            self.current = Some(tmp);
395        } else {
396            unreachable!();
397        }
398    }
399
400    fn visit_union(&mut self, indices: &[isize]) {
401        if !self.selector_filter.is_term_empty() {
402            unimplemented!("union syntax in filter");
403        }
404
405        if let Some(ParseToken::Array) = self.tokens.pop() {
406            let mut tmp = Vec::new();
407            if let Some(current) = &self.current {
408                for v in current {
409                    if let Value::Array(vec) = v {
410                        for i in indices {
411                            if let Some(v) = vec.get(utils::abs_index(*i, vec.len())) {
412                                tmp.push(v);
413                            }
414                        }
415                    }
416                }
417            }
418
419            self.current = Some(tmp);
420        } else {
421            unreachable!();
422        }
423    }
424}
425
426impl<'a> ParserTokenHandler<'a> for JsonSelector<'a> {
427    fn handle<F>(&mut self, token: &ParseToken, parse_value_reader: &F)
428        where
429            F: Fn(&StrRange) -> &'a str
430    {
431        debug!("token: {:?}, stack: {:?}", token, self.tokens);
432
433        if self.compute_absolute_path_filter(token, parse_value_reader) {
434            return;
435        }
436
437        match token {
438            ParseToken::Absolute => self.visit_absolute(),
439            ParseToken::Relative => self.visit_relative(),
440            ParseToken::In | ParseToken::Leaves | ParseToken::Array => {
441                self.tokens.push(token.clone());
442            }
443            ParseToken::ArrayEof => self.visit_array_eof(),
444            ParseToken::All => self.visit_all(),
445            ParseToken::Bool(b) => {
446                self.selector_filter.push_term(Some(ExprTerm::Bool(*b)));
447            }
448            ParseToken::Key(s) => {
449                let key = parse_value_reader(s);
450                self.visit_key(key);
451            }
452            ParseToken::Keys(keys) => {
453                let keys: Vec<&str> = keys.iter().map(|s| { parse_value_reader(s) }).collect();
454                self.visit_keys(&keys)
455            }
456            ParseToken::Number(v) => {
457                self.selector_filter.push_term(Some(ExprTerm::Number(Number::from_f64(*v).unwrap())));
458            }
459            ParseToken::Filter(ref ft) => self.visit_filter(ft),
460            ParseToken::Range(from, to, step) => self.visit_range(from, to, step),
461            ParseToken::Union(indices) => self.visit_union(indices),
462            ParseToken::Eof => {
463                debug!("visit_token eof");
464            }
465        }
466    }
467}
468
469#[derive(Default)]
470pub struct JsonSelectorMut<'a> {
471    value: Option<Value>,
472    parser: Option<Rc<PathParser<'a>>>,
473}
474
475impl<'a> JsonSelectorMut<'a> {
476    pub fn new(parser: PathParser<'a>) -> Self {
477        Self::new_ref(Rc::new(parser))
478    }
479
480    pub fn new_ref(parser: Rc<PathParser<'a>>) -> Self {
481        JsonSelectorMut {
482            value: None,
483            parser: Some(parser),
484        }
485    }
486
487    pub fn reset_parser(&mut self, parser: PathParser<'a>) -> &mut Self {
488        self.parser = Some(Rc::new(parser));
489        self
490    }
491
492    pub fn reset_parser_ref(&mut self, parser: Rc<PathParser<'a>>) -> &mut Self {
493        self.parser = Some(parser);
494        self
495    }
496
497    pub fn value(&mut self, value: Value) -> &mut Self {
498        self.value = Some(value);
499        self
500    }
501
502    pub fn take(&mut self) -> Option<Value> {
503        self.value.take()
504    }
505
506    pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> {
507        self.replace_with(&mut |_| Some(Value::Null))
508    }
509
510    pub fn remove(&mut self) -> Result<&mut Self, JsonPathError> {
511        self.replace_with(&mut |_| None)
512    }
513
514    fn select(&self) -> Result<Vec<&Value>, JsonPathError> {
515        let mut selector = JsonSelector::default();
516
517        if let Some(parser) = self.parser.as_ref() {
518            selector.reset_parser_ref(Rc::clone(parser));
519        } else {
520            return Err(JsonPathError::EmptyPath);
521        }
522
523        if let Some(value) = self.value.as_ref() {
524            selector.value(value);
525        } else {
526            return Err(JsonPathError::EmptyValue);
527        }
528
529        selector.select()
530    }
531
532    pub fn replace_with<F>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError>
533        where
534            F: FnMut(Value) -> Option<Value>,
535    {
536        let result = self.select()?;
537        let paths = self.compute_paths(result);
538
539        if let Some(ref mut value) = &mut self.value {
540            for tokens in paths {
541                Self::replace_value(tokens, value, fun);
542            }
543        }
544
545        Ok(self)
546    }
547
548    fn replace_value<F>(mut tokens: Vec<String>, value: &mut Value, fun: &mut F)
549        where
550            F: FnMut(Value) -> Option<Value>
551    {
552        let mut target = value;
553
554        let last_index = tokens.len().saturating_sub(1);
555        for (i, token) in tokens.drain(..).enumerate() {
556            let target_once = target;
557            let is_last = i == last_index;
558            let target_opt = match *target_once {
559                Value::Object(ref mut map) => {
560                    if is_last {
561                        if let Entry::Occupied(mut e) = map.entry(token) {
562                            let v = e.insert(Value::Null);
563                            if let Some(res) = fun(v) {
564                                e.insert(res);
565                            } else {
566                                e.remove();
567                            }
568                        }
569                        return;
570                    }
571                    map.get_mut(&token)
572                }
573                Value::Array(ref mut vec) => {
574                    if let Ok(x) = token.parse::<usize>() {
575                        if is_last {
576                            if x < vec.len() {
577                                let v = std::mem::replace(&mut vec[x], Value::Null);
578                                if let Some(res) = fun(v) {
579                                    vec[x] = res;
580                                } else {
581                                    vec.remove(x);
582                                }
583                            }
584                            return;
585                        }
586                        vec.get_mut(x)
587                    } else {
588                        None
589                    }
590                }
591                _ => None,
592            };
593
594            if let Some(t) = target_opt {
595                target = t;
596            } else {
597                break;
598            }
599        }
600    }
601
602    fn compute_paths(&self, mut result: Vec<&Value>) -> Vec<Vec<String>> {
603        let mut visited = HashSet::new();
604        let mut visited_order = Vec::new();
605
606        if let Some(origin) = &self.value {
607            let mut tokens = Vec::new();
608            Self::walk(
609                origin,
610                &mut result,
611                &mut tokens,
612                &mut visited,
613                &mut visited_order,
614            );
615        }
616
617        visited_order
618    }
619
620    fn walk(
621        origin: &Value,
622        target: &mut Vec<&Value>,
623        tokens: &mut Vec<String>,
624        visited: &mut HashSet<*const Value>,
625        visited_order: &mut Vec<Vec<String>>,
626    ) -> bool {
627        trace!("{:?}, {:?}", target, tokens);
628
629        if target.is_empty() {
630            return true;
631        }
632
633        target.retain(|t| {
634            if std::ptr::eq(origin, *t) {
635                if visited.insert(*t) {
636                    visited_order.push(tokens.to_vec());
637                }
638                false
639            } else {
640                true
641            }
642        });
643
644        match origin {
645            Value::Array(vec) => {
646                for (i, v) in vec.iter().enumerate() {
647                    tokens.push(i.to_string());
648                    if Self::walk(v, target, tokens, visited, visited_order) {
649                        return true;
650                    }
651                    tokens.pop();
652                }
653            }
654            Value::Object(map) => {
655                for (k, v) in map {
656                    tokens.push(k.clone());
657                    if Self::walk(v, target, tokens, visited, visited_order) {
658                        return true;
659                    }
660                    tokens.pop();
661                }
662            }
663            _ => {}
664        }
665
666        false
667    }
668}