queryst/
parser.rs

1#[cfg(feature = "regex1")]
2use regex::Regex;
3use serde_json::{Value, Map, Number};
4use percent_encoding::percent_decode;
5
6use crate::merge::merge;
7use crate::helpers::{create_array, push_item_to_array};
8
9#[cfg(feature = "regex1")]
10lazy_static! {
11    static ref PARENT_REGEX: Regex = Regex::new(r"^([^\]\[]+)").unwrap();
12    static ref CHILD_REGEX: Regex = Regex::new(r"(\[[^\]\[]*\])").unwrap();
13}
14
15type Object = Map<String, Value>;
16
17#[derive(Debug)]
18#[allow(missing_copy_implementations)]
19pub enum ParseErrorKind {
20    DecodingError,
21    Other
22}
23
24#[derive(Debug)]
25pub struct ParseError {
26    pub kind: ParseErrorKind,
27    pub message: String
28}
29
30pub type ParseResult<T> = Result<T,ParseError>;
31
32pub fn decode_component(source: &str) -> Result<String,String> {
33    let result = percent_decode(source.as_bytes()).decode_utf8_lossy().to_string();
34    Ok(result)
35}
36
37fn parse_pair(part: &str) -> (&str, Option<&str>) {
38    let separator = part.find("]=").map(|pos| pos+1)
39                        .or_else(|| part.find('='));
40    match separator {
41        None => (part, None),
42        Some(pos) => {
43            let key = &part[..pos];
44            let val = &part[(pos + 1)..];
45            (key, Some(val))
46        }
47    }
48}
49
50fn parse_pairs(body: &str) -> Vec<(&str, Option<&str>)> {
51    let mut pairs = vec![];
52    for part in body.split('&') {
53        pairs.push(parse_pair(part));
54    }
55    pairs
56}
57
58#[cfg(feature = "regex1")]
59fn parse_key(key: &str) -> ParseResult<Vec<String>> {
60    let mut keys: Vec<String> = vec![];
61
62    match PARENT_REGEX.captures(key) {
63        Some(captures) => {
64            match decode_component(captures.get(1).unwrap().as_str()) {
65                Ok(decoded_key) => keys.push(decoded_key),
66                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
67            }
68        }
69        None => ()
70    };
71
72    for captures in CHILD_REGEX.captures_iter(key) {
73        match decode_component(captures.get(1).unwrap().as_str()) {
74            Ok(decoded_key) => keys.push(decoded_key),
75            Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
76        }
77    }
78
79    Ok(keys)
80}
81
82#[cfg(not(feature = "regex1"))]
83fn parse_key(key: &str) -> ParseResult<Vec<String>> {
84    let mut keys: Vec<String> = vec![];
85
86    match key.split(|c| c=='[' || c==']').next() {
87        Some(parent) if !parent.is_empty() =>  {
88            match decode_component(parent) {
89                Ok(decoded_key) => keys.push(decoded_key),
90                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
91            }
92        }
93        _ => ()
94    }
95
96    let mut prev_bracket = None;
97    for (idx, ch) in key.char_indices() {
98        match ch {
99            '[' => prev_bracket = Some(idx),
100            ']' => {
101                if let Some(prev_idx) = prev_bracket {
102                    prev_bracket = None;
103                    let child = &key[prev_idx..=idx];
104                    match decode_component(child) {
105                        Ok(decoded_key) => keys.push(decoded_key),
106                        Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
107                    }
108                }
109            }
110            _ => (),
111        }
112    }
113
114    Ok(keys)
115}
116
117
118fn cleanup_key(key: &str) -> &str {
119    if key.starts_with('[') && key.ends_with(']') {
120        &key[1..(key.len()-1)]
121    } else {
122        key
123    }
124}
125
126fn create_idx_merger(idx: u64, obj: Value) -> Value {
127    let mut tree = Object::new();
128    tree.insert("__idx".to_string(), Value::Number(Number::from(idx)));
129    tree.insert("__object".to_string(), obj);
130    Value::Object(tree)
131}
132
133fn create_object_with_key(key: String, obj: Value) -> Value {
134    let mut tree = Object::new();
135    tree.insert(key, obj);
136    Value::Object(tree)
137}
138
139fn apply_object(keys: &[String], val: Value) -> Value {
140
141    if !keys.is_empty() {
142        let key = keys.get(0).unwrap();
143        if key == "[]" {
144            let mut new_array = create_array();
145            let item = apply_object(&keys[1..], val);
146            push_item_to_array(&mut new_array, item);
147            new_array
148        } else {
149            let key = cleanup_key(key);
150            let array_index = key.parse();
151
152            match array_index {
153                Ok(idx) => {
154                    let result = apply_object(&keys[1..], val);
155                    
156                    create_idx_merger(idx, result)
157                },
158                Err(_) => {
159                    create_object_with_key(key.to_string(), apply_object(&keys[1..], val))
160                }
161            }
162        }
163
164    } else {
165        val
166    }
167}
168
169pub fn parse(params: &str) -> ParseResult<Value> {
170    let tree = Object::new();
171    let mut obj = Value::Object(tree);
172    let decoded_params = match decode_component(&params.replace('+', " ")) {
173        Ok(val) => val,
174        Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
175    };
176    let pairs = parse_pairs(&decoded_params);
177    for &(key, value) in pairs.iter() {
178        let parse_key_res = parse_key(key)?;
179        let key_chain = &parse_key_res[0..];
180        let decoded_value = match value {
181            None => Value::default(),
182            Some(val) => match decode_component(val) {
183                Ok(decoded_value) => Value::String(decoded_value),
184                Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
185            }
186        };
187        let partial = apply_object(key_chain, decoded_value);
188        merge(&mut obj, &partial);
189    }
190
191    Ok(obj)
192}
193
194#[cfg(test)]
195mod tests {
196    use crate::parse;
197    use super::parse_pair;
198    use serde_json::{Value, to_string};
199
200    fn eq_str(value: Value, string: &str) {
201        assert_eq!(&to_string(&value).unwrap(), string)
202    }
203
204    #[test]
205    fn test_parse_pair() {
206        assert_eq!(parse_pair("foo=1"), ("foo", Some("1")));
207        assert_eq!(parse_pair("empty="), ("empty", Some("")));
208        assert_eq!(parse_pair("noval"), ("noval", None));
209    }
210
211    #[test]
212    fn it_parses_simple_string() {
213        eq_str(parse("0=foo").unwrap(), r#"{"0":"foo"}"#);
214        eq_str(parse("a[<=>]==23").unwrap(), r#"{"a":{"<=>":"=23"}}"#);
215        eq_str(parse(" foo = bar = baz ").unwrap(), r#"{" foo ":" bar = baz "}"#);
216    }
217
218    #[test]
219    fn it_parses_nested_string() {
220        eq_str(parse("a[b][c][d][e][f][g][h]=i").unwrap(),
221            r#"{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":"i"}}}}}}}}"#);
222    }
223
224    #[test]
225    fn it_parses_simple_array() {
226        eq_str(parse("a=b&a=c&a=d&a=e").unwrap(),
227            r#"{"a":["b","c","d","e"]}"#);
228    }
229
230    #[test]
231    fn it_parses_explicit_array() {
232        eq_str(parse("a[]=b&a[]=c&a[]=d").unwrap(),
233            r#"{"a":["b","c","d"]}"#);
234    }
235
236    #[test]
237    fn it_parses_nested_array() {
238        eq_str(parse("a[b][]=c&a[b][]=d").unwrap(),
239            r#"{"a":{"b":["c","d"]}}"#);
240    }
241
242    #[test]
243    fn it_allows_to_specify_array_indexes() {
244        eq_str(parse("a[0][]=c&a[1][]=d").unwrap(),
245            r#"{"a":[["c"],["d"]]}"#);
246    }
247
248    #[test]
249    fn it_transforms_arrays_to_object() {
250        eq_str(parse("foo[0]=bar&foo[bad]=baz").unwrap(),
251            r#"{"foo":{"0":"bar","bad":"baz"}}"#);
252
253        eq_str(parse("foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb").unwrap(),
254            r#"{"foo":[{"a":"a","b":"b"},{"a":"aa","b":"bb"}]}"#);
255    }
256
257    #[test]
258    fn it_transforms_standalone_keys() {
259        eq_str(parse("foo=bar&baz").unwrap(),
260            r#"{"baz":null,"foo":"bar"}"#);
261    }
262
263    #[test]
264    fn it_doesnt_produce_empty_keys() {
265        eq_str(parse("_r=1&").unwrap(),
266            r#"{"_r":"1"}"#);
267    }
268
269    #[test]
270    fn it_supports_encoded_strings() {
271        eq_str(parse("a[b%20c]=c%20d").unwrap(),
272            r#"{"a":{"b c":"c d"}}"#);
273    }
274
275    #[test]
276    fn it_parses_explicit_encoded_array() {
277        eq_str(parse("a%5B%5D=b&a%5B%5D=c&a%5B%5D=d").unwrap(),
278            r#"{"a":["b","c","d"]}"#);
279    }
280    #[test]
281    fn it_parses_plus_sign() {
282        eq_str(parse("a=b%20c+d%2B").unwrap(), r#"{"a":"b c d+"}"#);
283     }
284}