forked from RedisJSON/RedisJSON
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnodevisitor.rs
89 lines (79 loc) · 2.83 KB
/
nodevisitor.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use jsonpath_lib::parser::{NodeVisitor, ParseToken};
use jsonpath_lib::Parser;
use std::fmt::Display;
use std::fmt::Formatter;
pub enum StaticPathElement {
ArrayIndex(f64),
ObjectKey(String),
Root,
}
impl Display for StaticPathElement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
use StaticPathElement::*;
match self {
ArrayIndex(num) => write!(f, "[{}]", num),
ObjectKey(key) => write!(f, "[\"{}\"]", key),
Root => write!(f, "$"),
}
}
}
#[derive(Debug, PartialEq)]
pub enum VisitStatus {
NotValid,
PartialValid,
Valid,
}
pub struct StaticPathParser {
pub valid: VisitStatus,
last_token: Option<ParseToken>,
pub static_path_elements: Vec<StaticPathElement>,
}
impl StaticPathParser {
///
/// Checks if path is static & valid
///
pub fn check(input: &str) -> Result<Self, String> {
let node = Parser::compile(input)?;
let mut visitor = StaticPathParser {
valid: VisitStatus::PartialValid,
last_token: None,
static_path_elements: vec![],
};
visitor.visit(&node);
Ok(visitor)
}
}
impl NodeVisitor for StaticPathParser {
fn visit_token(&mut self, token: &ParseToken) {
if self.valid != VisitStatus::NotValid {
//eprintln!("visit token: {:?} -> {:?}", self.last_token, token);
self.valid = match (&self.last_token, token) {
(None, ParseToken::Absolute) => {
self.static_path_elements.push(StaticPathElement::Root);
VisitStatus::Valid
}
(Some(ParseToken::Absolute), ParseToken::In)
| (Some(ParseToken::Absolute), ParseToken::Array)
| (Some(ParseToken::Array), ParseToken::Key(_))
| (Some(ParseToken::Key(_)), ParseToken::In)
| (Some(ParseToken::Key(_)), ParseToken::Array)
| (Some(ParseToken::ArrayEof), ParseToken::Array)
| (Some(ParseToken::Array), ParseToken::Number(_))
| (Some(ParseToken::ArrayEof), ParseToken::In) => VisitStatus::PartialValid,
(Some(ParseToken::Number(num)), ParseToken::ArrayEof) => {
self.static_path_elements
.push(StaticPathElement::ArrayIndex(*num));
VisitStatus::Valid
}
(Some(ParseToken::In), ParseToken::Key(key))
| (Some(ParseToken::Key(key)), ParseToken::ArrayEof) => {
self.static_path_elements
.push(StaticPathElement::ObjectKey(key.clone()));
VisitStatus::Valid
}
_ => VisitStatus::NotValid,
};
self.last_token = Some(token.clone());
}
}
}