access_json/
query_parser.rs1use crate::query::QueryElement;
2
3pub(crate) fn parse_query(input: &str) -> Result<Vec<QueryElement>, QueryParseErr> {
4 let mut output = Vec::new();
5 let mut parser = Parser::from(input);
6 while let Some(it) = parser.next()? {
7 output.push(it);
8 }
9 Ok(output)
10}
11
12#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
16pub enum QueryParseErr {
17 BadCharacter(usize),
19 MissingField,
21 MissingNumber(usize),
23 BadArray(usize),
25 BadField(usize),
27 UnexpectedEOF(char),
29 Unexpected(usize, char),
31 BadIndex(usize, String),
33}
34
35impl std::fmt::Display for QueryParseErr {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{:?}", self)
38 }
39}
40
41impl std::error::Error for QueryParseErr {}
42
43struct Parser {
44 data: Vec<char>,
45 position: usize,
46}
47
48impl From<&str> for Parser {
49 fn from(input: &str) -> Parser {
50 Parser {
51 data: input.chars().collect(),
52 position: 0,
53 }
54 }
55}
56
57impl Parser {
58 fn peek(&self) -> Option<char> {
59 self.data.get(self.position).cloned()
60 }
61 fn advance(&mut self) -> Option<char> {
62 let found = self.peek();
63 self.position += 1;
64 found
65 }
66 fn consume(&mut self, expected: char) -> Result<(), QueryParseErr> {
67 match self.advance() {
68 None => Err(QueryParseErr::UnexpectedEOF(expected)),
69 Some(actual) => {
70 if actual == expected {
71 Ok(())
72 } else {
73 Err(QueryParseErr::Unexpected(self.position - 1, expected))
74 }
75 }
76 }
77 }
78 fn read_array(&mut self) -> Result<QueryElement, QueryParseErr> {
79 self.consume('[')?;
80 let mut digits = String::new();
81 let start = self.position;
82
83 while let Some(ch) = self.advance() {
84 if ch == ']' {
85 break;
86 } else if ch.is_digit(10) {
87 digits.push(ch);
88 } else {
89 return Err(QueryParseErr::BadArray(self.position - 1));
90 }
91 }
92
93 if digits.is_empty() {
94 Err(QueryParseErr::MissingNumber(start))
95 } else {
96 let num = digits
97 .parse::<usize>()
98 .map_err(|e| QueryParseErr::BadIndex(start, e.to_string()))?;
99 Ok(QueryElement::ArrayItem(num))
100 }
101 }
102 fn read_field(&mut self) -> Result<QueryElement, QueryParseErr> {
103 self.consume('.')?;
104 let mut id = String::new();
105 while let Some(ch) = self.peek() {
106 if ch == '.' || ch == '[' {
107 break;
108 } else if ch.is_whitespace() {
109 return Err(QueryParseErr::BadField(self.position - 1));
110 }
111 self.consume(ch)?;
112 id.push(ch);
113 }
114 if id.is_empty() {
115 Err(QueryParseErr::MissingField)
116 } else {
117 Ok(QueryElement::Field(id))
118 }
119 }
120 fn next(&mut self) -> Result<Option<QueryElement>, QueryParseErr> {
121 if let Some(ch) = self.peek() {
122 Ok(Some(if ch == '[' {
123 self.read_array()?
124 } else if ch == '.' {
125 self.read_field()?
126 } else {
127 return Err(QueryParseErr::BadCharacter(self.position));
128 }))
129 } else {
130 Ok(None)
131 }
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::parse_query;
138 use super::QueryParseErr;
139 use crate::query::QueryElement as Q;
140
141 #[test]
142 fn test_dots_happy() {
143 assert_eq!(
144 parse_query(".a.b.c").unwrap(),
145 vec![Q::field("a"), Q::field("b"), Q::field("c")]
146 )
147 }
148
149 #[test]
150 fn test_array_happy() {
151 assert_eq!(
152 parse_query("[0][7]").unwrap(),
153 vec![Q::array_item(0), Q::array_item(7)]
154 )
155 }
156
157 #[test]
158 fn test_parse_mixed() {
159 assert_eq!(
160 parse_query(".a.b[7].c.e[5]").unwrap(),
161 vec![
162 Q::field("a"),
163 Q::field("b"),
164 Q::array_item(7),
165 Q::field("c"),
166 Q::field("e"),
167 Q::array_item(5)
168 ]
169 )
170 }
171
172 #[test]
173 fn test_missing_field() {
174 assert_eq!(
175 parse_query(".a.b.").unwrap_err(),
176 QueryParseErr::MissingField
177 );
178 }
179
180 #[test]
181 fn test_bad_numbers() {
182 assert_eq!(
183 parse_query("[0][]").unwrap_err(),
184 QueryParseErr::MissingNumber(4)
185 )
186 }
187
188 #[test]
189 fn test_array_not_closed() {
190 assert_eq!(
191 parse_query("[").unwrap_err(),
192 QueryParseErr::MissingNumber(1)
193 )
194 }
195}