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}