queryst_prime/
parser.rs

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