1use std::convert::Infallible;
2
3use crate::helpers::{create_array, push_item_to_array};
4use crate::merge::merge;
5#[cfg(feature = "regex1")]
6use lazy_static::lazy_static;
7use percent_encoding::percent_decode;
8#[cfg(feature = "regex1")]
9use regex::Regex;
10use serde_json::{Map, Number, Value};
11use thiserror::Error;
12
13#[cfg(feature = "regex1")]
14lazy_static! {
15 static ref PARENT_REGEX: Regex = Regex::new(r"^([^\]\[]+)").unwrap();
16 static ref CHILD_REGEX: Regex = Regex::new(r"(\[[^\]\[]*\])").unwrap();
17}
18
19type Object = Map<String, Value>;
20
21#[derive(Debug, Error)]
22pub enum ParseError {
23 #[error("Failed to decode: {0}")]
24 DecodingError(String),
25 #[error("Other")]
26 Other,
27}
28
29pub type ParseResult<T> = Result<T, ParseError>;
30
31pub fn decode_component(source: &str) -> Result<String, String> {
32 let result = percent_decode(source.as_bytes())
33 .decode_utf8_lossy()
34 .to_string();
35 Ok(result)
36}
37
38fn parse_pair(part: &str) -> (&str, Option<&str>) {
39 let separator = part
40 .find("]=")
41 .map(|pos| pos + 1)
42 .or_else(|| part.find('='));
43 match separator {
44 None => (part, None),
45 Some(pos) => {
46 let key = &part[..pos];
47 let val = &part[(pos + 1)..];
48 (key, Some(val))
49 }
50 }
51}
52
53fn parse_pairs(body: &str) -> Vec<(&str, Option<&str>)> {
54 let mut pairs = vec![];
55 for part in body.split('&') {
56 pairs.push(parse_pair(part));
57 }
58 pairs
59}
60
61#[cfg(feature = "regex1")]
62fn parse_key(key: &str) -> ParseResult<Vec<String>> {
63 let mut keys: Vec<String> = vec![];
64
65 if let Some(captures) = PARENT_REGEX.captures(key) {
66 match decode_component(captures.get(1).unwrap().as_str()) {
67 Ok(decoded_key) => keys.push(decoded_key),
68 Err(err_msg) => return Err(ParseError::DecodingError(err_msg)),
69 }
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::DecodingError(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() => match decode_component(parent) {
88 Ok(decoded_key) => keys.push(decoded_key),
89 Err(err_msg) => return Err(ParseError::DecodingError(err_msg)),
90 },
91 _ => (),
92 }
93
94 let mut prev_bracket = None;
95 for (idx, ch) in key.char_indices() {
96 match ch {
97 '[' => prev_bracket = Some(idx),
98 ']' => {
99 if let Some(prev_idx) = prev_bracket {
100 prev_bracket = None;
101 let child = &key[prev_idx..=idx];
102 match decode_component(child) {
103 Ok(decoded_key) => keys.push(decoded_key),
104 Err(err_msg) => {
105 return Err(ParseError {
106 kind: ParseErrorKind::DecodingError,
107 message: err_msg,
108 })
109 }
110 }
111 }
112 }
113 _ => (),
114 }
115 }
116
117 Ok(keys)
118}
119
120fn cleanup_key(key: &str) -> &str {
121 if key.starts_with('[') && key.ends_with(']') {
122 &key[1..(key.len() - 1)]
123 } else {
124 key
125 }
126}
127
128fn create_idx_merger(idx: u64, obj: Value) -> Value {
129 let mut tree = Object::new();
130 tree.insert("__idx".to_string(), Value::Number(Number::from(idx)));
131 tree.insert("__object".to_string(), obj);
132 Value::Object(tree)
133}
134
135fn create_object_with_key(key: String, obj: Value) -> Value {
136 let mut tree = Object::new();
137 tree.insert(key, obj);
138 Value::Object(tree)
139}
140
141fn apply_object(keys: &[String], val: Value) -> Value {
142 if !keys.is_empty() {
143 let key = keys.get(0).unwrap();
144 if key == "[]" {
145 let mut new_array = create_array();
146 let item = apply_object(&keys[1..], val);
147 push_item_to_array(&mut new_array, item);
148 new_array
149 } else {
150 let key = cleanup_key(key);
151 let array_index = key.parse();
152
153 match array_index {
154 Ok(idx) => {
155 let result = apply_object(&keys[1..], val);
156 create_idx_merger(idx, result)
157 }
158 Err(_) => create_object_with_key(key.to_string(), apply_object(&keys[1..], val)),
159 }
160 }
161 } else {
162 val
163 }
164}
165
166pub fn parse(params: &str) -> ParseResult<Value> {
167 let tree = Object::new();
168 let mut obj = Value::Object(tree);
169 let decoded_params = match decode_component(¶ms.replace('+', " ")) {
170 Ok(val) => val,
171 Err(err) => return Err(ParseError::DecodingError(err)),
172 };
173 let pairs = parse_pairs(&decoded_params);
174 for &(key, value) in pairs.iter() {
175 let parse_key_res = parse_key(key)?;
176 let key_chain = &parse_key_res[0..];
177 let decoded_value = match value {
178 None => Value::default(),
179 Some(val) => match decode_component(val) {
180 Ok(v) => {
181 let n = v.parse::<i64>();
182 let f = v.parse::<f64>();
183 let b = v.parse::<bool>();
184 let null = Ok::<_, Infallible>(v == "null");
185 match (n, f, b, null) {
186 (Ok(n), _, _, _) => Value::Number(Number::from(n)),
187 (_, Ok(f), _, _) => Value::Number(Number::from_f64(f).unwrap()),
188 (_, _, Ok(b), _) => Value::Bool(b),
189 (_, _, _, Ok(true)) => Value::Null,
190 _ => Value::String(v),
191 }
192 }
193 Err(err) => return Err(ParseError::DecodingError(err)),
194 },
195 };
196 let partial = apply_object(key_chain, decoded_value);
197 merge(&mut obj, &partial);
198 }
199
200 Ok(obj)
201}
202
203#[cfg(test)]
204mod tests {
205 use super::{parse, parse_pair};
206 use serde_json::{json, to_string, Value};
207
208 fn eq_str(value: Value, string: &str) {
209 assert_eq!(&to_string(&value).unwrap(), string)
210 }
211
212 #[test]
213 fn test_parse_pair() {
214 assert_eq!(parse_pair("foo=1"), ("foo", Some("1")));
215 assert_eq!(parse_pair("empty="), ("empty", Some("")));
216 assert_eq!(parse_pair("noval"), ("noval", None));
217 }
218
219 #[test]
220 fn it_parses_simple_string() {
221 eq_str(parse("0=foo").unwrap(), r#"{"0":"foo"}"#);
222 eq_str(parse("a[<=>]==23").unwrap(), r#"{"a":{"<=>":"=23"}}"#);
223 eq_str(
224 parse(" foo = bar = baz ").unwrap(),
225 r#"{" foo ":" bar = baz "}"#,
226 );
227 }
228
229 #[test]
230 fn it_parses_nested_string() {
231 eq_str(
232 parse("a[b][c][d][e][f][g][h]=i").unwrap(),
233 r#"{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":"i"}}}}}}}}"#,
234 );
235 }
236
237 #[test]
238 fn it_parses_simple_array() {
239 eq_str(
240 parse("a=b&a=c&a=d&a=e").unwrap(),
241 r#"{"a":["b","c","d","e"]}"#,
242 );
243 }
244
245 #[test]
246 fn it_parses_explicit_array() {
247 eq_str(
248 parse("a[]=b&a[]=c&a[]=d").unwrap(),
249 r#"{"a":["b","c","d"]}"#,
250 );
251 }
252
253 #[test]
254 fn it_parses_nested_array() {
255 eq_str(
256 parse("a[b][]=c&a[b][]=d").unwrap(),
257 r#"{"a":{"b":["c","d"]}}"#,
258 );
259 }
260
261 #[test]
262 fn it_allows_to_specify_array_indexes() {
263 eq_str(
264 parse("a[0][]=c&a[1][]=d").unwrap(),
265 r#"{"a":[["c"],["d"]]}"#,
266 );
267 }
268
269 #[test]
270 fn it_transforms_arrays_to_object() {
271 eq_str(
272 parse("foo[0]=bar&foo[bad]=baz").unwrap(),
273 r#"{"foo":{"0":"bar","bad":"baz"}}"#,
274 );
275
276 eq_str(
277 parse("foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb").unwrap(),
278 r#"{"foo":[{"a":"a","b":"b"},{"a":"aa","b":"bb"}]}"#,
279 );
280 }
281
282 #[test]
283 fn it_transforms_standalone_keys() {
284 eq_str(parse("foo=bar&baz").unwrap(), r#"{"baz":null,"foo":"bar"}"#);
285 }
286
287 #[test]
288 fn it_doesnt_produce_empty_keys() {
289 assert_eq!(parse("_r=1&").unwrap(), json!({"_r": 1}));
290 }
291
292 #[test]
293 fn it_supports_encoded_strings() {
294 eq_str(parse("a[b%20c]=c%20d").unwrap(), r#"{"a":{"b c":"c d"}}"#);
295 }
296
297 #[test]
298 fn it_parses_explicit_encoded_array() {
299 eq_str(
300 parse("a%5B%5D=b&a%5B%5D=c&a%5B%5D=d").unwrap(),
301 r#"{"a":["b","c","d"]}"#,
302 );
303 }
304 #[test]
305 fn it_parses_plus_sign() {
306 eq_str(parse("a=b%20c+d%2B").unwrap(), r#"{"a":"b c d+"}"#);
307 }
308
309 #[test]
310 fn it_parses_numbers() {
311 assert_eq!(parse("a=1").unwrap(), json!({"a": 1}));
312 assert_eq!(parse("a=1.1").unwrap(), json!({"a": 1.1}));
313 assert_eq!(parse("a=1.1e1").unwrap(), json!({"a": 11.0}));
314 assert_eq!(parse("a=1.1e-1").unwrap(), json!({"a": 0.11}));
315 }
316
317 #[test]
318 fn it_parses_booleans() {
319 assert_eq!(parse("a=true").unwrap(), json!({"a": true}));
320 assert_eq!(parse("a=false").unwrap(), json!({"a": false}));
321 }
322
323 #[test]
324 fn it_parses_null() {
325 assert_eq!(parse("a=null").unwrap(), json!({ "a": null }));
326 }
327
328 #[test]
329 fn it_parses_empty_string() {
330 assert_eq!(parse("a=").unwrap(), json!({ "a": "" }));
331 }
332
333 #[test]
334 fn it_parses_array_integer() {
335 assert_eq!(parse("a[]=1&a[]=2").unwrap(), json!({ "a": [1, 2] }));
336 }
337
338 #[test]
339 fn it_parses_nested_array_integer() {
340 assert_eq!(
341 parse("a[b]=null&a[b]=2").unwrap(),
342 json!({ "a": {"b": [null, 2] }})
343 );
344
345 assert_eq!(
346 parse("a[b]=1&a[b]=2").unwrap(),
347 json!({ "a": {"b": [1, 2] }})
348 );
349 }
350}