ron_parser/
lib.rs

1#![deny(clippy::unwrap_used)]
2
3mod string;
4use nom::{combinator::fail, error::ErrorKind, multi::separated_list1};
5use std::{borrow::Cow, collections::HashMap};
6use wasm_bindgen::prelude::*;
7
8use nom::{
9    branch::alt,
10    bytes::complete::{escaped, tag, take_while},
11    character::complete::{char, digit1, one_of},
12    combinator::{cut, map, opt, value},
13    error::{context, ContextError, FromExternalError, ParseError},
14    multi::separated_list0,
15    number::complete::double,
16    sequence::{delimited, preceded, separated_pair, terminated},
17    AsChar, IResult, InputTakeAtPosition, Parser,
18};
19
20///
21/// [`DataModel`] is used to perform ron object conversion it is the intermediate representation
22/// for the parser.
23///
24#[derive(Clone, Debug, PartialEq, serde::Serialize)]
25#[serde(untagged)]
26pub enum DataModel<'a> {
27    Null,                                 // ✅
28    Boolean(bool),                        // ✅
29    Float(f64),                           // ✅
30    String(Cow<'a, str>),                 // ✅
31    Map(HashMap<&'a str, DataModel<'a>>), // ✅
32    Vec(Vec<DataModel<'a>>),              // ✅
33}
34
35impl<'a, T: 'a + Into<Cow<'a, str>>> From<T> for DataModel<'a> {
36    fn from(value: T) -> Self {
37        DataModel::String(value.into())
38    }
39}
40
41impl<'a> std::hash::Hash for DataModel<'a>
42where
43    HashMap<&'a str, DataModel<'a>>: std::hash::Hash,
44{
45    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
46        match self {
47            DataModel::Null => 0_u8.hash(state),
48            DataModel::Boolean(data) => data.hash(state),
49            DataModel::Float(_data) => {}
50            DataModel::String(data) => data.hash(state),
51            DataModel::Map(data) => data.hash(state),
52            DataModel::Vec(data) => data.hash(state),
53        }
54    }
55}
56
57fn spacer<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
58    let chars = " \t\r\n";
59
60    take_while(move |c| chars.contains(c))(i)
61}
62
63pub fn char_checker<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E>
64where
65    <&'a str as nom::InputTakeAtPosition>::Item: nom::AsChar,
66{
67    input.split_at_position1_complete(
68        |item| !(item.is_alphanum() || item == '_'),
69        nom::error::ErrorKind::AlphaNumeric,
70    )
71}
72
73pub fn num_checker<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E>
74where
75    <&'a str as nom::InputTakeAtPosition>::Item: nom::AsChar,
76{
77    input.split_at_position1_complete(
78        |item| !(item.is_ascii_digit() || item == '.'),
79        nom::error::ErrorKind::AlphaNumeric,
80    )
81}
82
83fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
84    escaped(char_checker, '\\', one_of("\"n\\"))(i)
85}
86
87fn parse_bool<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, bool, E> {
88    let parse_true = value(true, tag("true"));
89    let parse_false = value(false, tag("false"));
90
91    alt((parse_true, parse_false)).parse(i)
92}
93
94fn parse_null<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, (), E> {
95    value((), tag("None")).parse(input)
96}
97
98fn parse_string<'a, E: ParseError<&'a str> + ContextError<&'a str> + std::fmt::Debug>(
99    input: &'a str,
100) -> IResult<&'a str, &'a str, E> {
101    context(
102        "string",
103        preceded(char('\"'), cut(terminated(parse_str, char('\"')))),
104    )(input)
105}
106
107#[allow(dead_code)]
108fn parse_integer<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, isize, E> {
109    let (number, data) = opt(char('-'))(input)?;
110    digit1(number).and_then(|(rest, doq)| match (doq.parse::<isize>(), data.is_some()) {
111        (Ok(x), _) => Ok((rest, x)),
112        (Result::Err(_), true) => Err(nom::Err::Failure(E::from_error_kind(
113            input,
114            nom::error::ErrorKind::Fail,
115        ))),
116        (Result::Err(_), false) => Err(nom::Err::Error(E::from_error_kind(
117            input,
118            nom::error::ErrorKind::Fail,
119        ))),
120    })
121}
122
123fn parse_datetime<
124    'a,
125    E: ParseError<&'a str>
126        + ContextError<&'a str>
127        + FromExternalError<&'a str, std::num::ParseIntError>
128        + std::fmt::Debug,
129>(
130    i: &'a str,
131) -> IResult<&'a str, String, E> {
132    context(
133        "datetime",
134        map(
135            separated_pair(
136                separated_list1(tag("-"), num_checker),
137                tag(" "),
138                separated_list1(tag(":"), num_checker),
139            ),
140            |x| {
141                println!("datetime: {:#?}", x);
142                let mut string = String::new();
143                string.push_str(&x.0.join("-"));
144                string.push(' ');
145                string.push_str(&x.1.join(":"));
146                string
147            },
148        ),
149    )
150    .parse(i)
151}
152
153fn parse_float<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, f64, E> {
154    let data = double(input);
155    // let data = map_opt(num_checker, |value| { // This is a optional rudimentary float parser
156    //     eprintln!("parsing: {}", value);
157    //     value.parse::<f64>().ok()
158    // })
159    // .parse(input);
160
161    match data {
162        Ok((rest, _)) if rest.starts_with('*') => fail(input),
163        _ => data,
164    }
165}
166
167fn parse_array<
168    'a,
169    E: ParseError<&'a str>
170        + ContextError<&'a str>
171        + FromExternalError<&'a str, std::num::ParseIntError>
172        + std::fmt::Debug,
173>(
174    input: &'a str,
175) -> IResult<&'a str, Vec<DataModel<'a>>, E> {
176    context(
177        "array",
178        preceded(
179            char('['),
180            cut(terminated(
181                separated_list0(preceded(spacer, char(',')), data_model),
182                preceded(spacer, char(']')),
183            )),
184        ),
185    )
186    .parse(input)
187}
188
189fn parse_array_tuple<
190    'a,
191    E: ParseError<&'a str>
192        + ContextError<&'a str>
193        + FromExternalError<&'a str, std::num::ParseIntError>
194        + std::fmt::Debug,
195>(
196    input: &'a str,
197) -> IResult<&'a str, Vec<DataModel<'a>>, E> {
198    context(
199        "tuple",
200        preceded(
201            char('('),
202            cut(terminated(
203                separated_list0(preceded(spacer, char(',')), data_model),
204                preceded(spacer, char(')')),
205            )),
206        ),
207    )
208    .parse(input)
209}
210
211fn parse_key_value_hash<
212    'a,
213    E: ParseError<&'a str>
214        + ContextError<&'a str>
215        + FromExternalError<&'a str, std::num::ParseIntError>
216        + std::fmt::Debug,
217>(
218    i: &'a str,
219) -> IResult<&'a str, (&'a str, DataModel<'a>), E> {
220    separated_pair(
221        preceded(spacer, parse_string),
222        cut(preceded(spacer, char(':'))),
223        preceded(spacer, data_model),
224    )
225    .parse(i)
226}
227
228fn parse_key_value_struct<
229    'a,
230    E: ParseError<&'a str>
231        + ContextError<&'a str>
232        + FromExternalError<&'a str, std::num::ParseIntError>
233        + std::fmt::Debug,
234>(
235    i: &'a str,
236) -> IResult<&'a str, (&'a str, DataModel<'a>), E> {
237    separated_pair(
238        preceded(spacer, parse_str.or(parse_string)),
239        cut(preceded(spacer, char(':'))),
240        preceded(spacer, data_model),
241    )
242    .parse(i)
243}
244
245fn parse_hash<
246    'a,
247    E: ParseError<&'a str>
248        + ContextError<&'a str>
249        + FromExternalError<&'a str, std::num::ParseIntError>
250        + std::fmt::Debug,
251>(
252    input: &'a str,
253) -> IResult<&'a str, HashMap<&'a str, DataModel<'a>>, E> {
254    context(
255        "map",
256        preceded(
257            char('{'),
258            cut(terminated(
259                map(
260                    separated_list0(preceded(spacer, char(',')), parse_key_value_hash),
261                    |tuple_vec| tuple_vec.into_iter().collect(),
262                ),
263                preceded(spacer, char('}')),
264            )),
265        ),
266    )(input)
267}
268
269fn parse_hash_unticked<
270    'a,
271    E: ParseError<&'a str>
272        + ContextError<&'a str>
273        + FromExternalError<&'a str, std::num::ParseIntError>
274        + std::fmt::Debug,
275>(
276    input: &'a str,
277) -> IResult<&'a str, HashMap<&'a str, DataModel<'a>>, E> {
278    context(
279        "struct map",
280        preceded(
281            spacer,
282            preceded(
283                char('{'),
284                cut(terminated(
285                    map(
286                        separated_list0(preceded(spacer, char(',')), parse_key_value_struct),
287                        |tuple_vec| tuple_vec.into_iter().collect(),
288                    ),
289                    preceded(spacer, char('}')),
290                )),
291            ),
292        ),
293    )(input)
294}
295
296fn parse_struct<
297    'a,
298    E: ParseError<&'a str>
299        + ContextError<&'a str>
300        + FromExternalError<&'a str, std::num::ParseIntError>
301        + std::fmt::Debug,
302>(
303    input: &'a str,
304) -> IResult<&'a str, HashMap<&'a str, DataModel<'a>>, E> {
305    let value = context(
306        "struct",
307        separated_pair(parse_str, spacer, parse_hash_unticked),
308    )(input);
309
310    let value = value?;
311
312    Ok((value.0, value.1 .1))
313}
314
315fn parse_tuple_var<
316    'a,
317    E: ParseError<&'a str>
318        + ContextError<&'a str>
319        + FromExternalError<&'a str, std::num::ParseIntError>
320        + std::fmt::Debug,
321>(
322    input: &'a str,
323) -> IResult<&'a str, DataModel<'a>, E> {
324    context(
325        "option",
326        preceded(
327            preceded(parse_str, char('(')),
328            cut(terminated(data_model, char(')'))),
329        ),
330    )(input)
331}
332
333pub fn char_checker_wc<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E>
334where
335    <&'a str as nom::InputTakeAtPosition>::Item: nom::AsChar,
336{
337    input.split_at_position1_complete(
338        |item| item == ',' || item == '}' || item == ')' || item == ']',
339        nom::error::ErrorKind::AlphaNumeric,
340    )
341}
342
343pub fn everything_none_space<'a, E: ParseError<&'a str>>(
344    input: &'a str,
345) -> IResult<&'a str, &'a str, E>
346where
347    <&'a str as nom::InputTakeAtPosition>::Item: nom::AsChar,
348{
349    input.split_at_position1_complete(|item| item == ' ', nom::error::ErrorKind::AlphaNumeric)
350}
351
352fn parse_wildcard<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
353    // escaped(char_checker_wc, '\\', one_of("\"n\\"))(i)
354    alt((
355        map(masked_data, |_| "*** masked ***"),
356        escaped(char_checker_wc, '\\', one_of("\"n\\")),
357    ))(i)
358}
359
360fn masked_data<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
361    delimited(tag("*** "), everything_none_space, tag(" ***"))(i)
362}
363
364///
365/// Parse string into [`DataModel`] using this function.
366///
367pub fn data_model<
368    'a,
369    E: ParseError<&'a str>
370        + ContextError<&'a str>
371        + FromExternalError<&'a str, std::num::ParseIntError>
372        + std::fmt::Debug,
373>(
374    i: &'a str,
375) -> IResult<&'a str, DataModel<'a>, E> {
376    preceded(
377        spacer,
378        alt((
379            map(parse_null, |_| DataModel::Null),
380            map(parse_bool, DataModel::Boolean),
381            map(parse_datetime, Into::into),
382            map(parse_float, DataModel::Float),
383            map(string::parse_string, Into::into),
384            map(parse_array_tuple, DataModel::Vec),
385            map(parse_array, DataModel::Vec),
386            map(parse_hash, DataModel::Map),
387            map(parse_tuple_var, |x| x),
388            map(parse_struct, DataModel::Map),
389            map(parse_wildcard, Into::into),
390        )),
391    )
392    .parse(i)
393}
394
395///
396/// Function exposed as `wasm` function in js `parse`. Allowing use to extend the functionality and
397/// usage for web
398///
399#[wasm_bindgen(js_name=parse)]
400pub fn my_parse(val: String) -> String {
401    serde_json::to_string(
402        &root::<(&str, ErrorKind)>(&val)
403            .expect("Failed to parse the ron object")
404            .1,
405    )
406    .expect("Failed to serialize to json")
407}
408
409///
410/// The entrypoint to the crate this is internally calling [`data_model`] with a relaxed
411/// constraints of space padding on the start and the end
412///
413pub fn root<
414    'a,
415    E: ParseError<&'a str>
416        + ContextError<&'a str>
417        + FromExternalError<&'a str, std::num::ParseIntError>
418        + std::fmt::Debug,
419>(
420    i: &'a str,
421) -> IResult<&'a str, DataModel<'a>, E> {
422    delimited(spacer, data_model, opt(spacer)).parse(i)
423}
424
425#[cfg(test)]
426mod tests {
427    #![allow(clippy::unwrap_used)]
428    #![allow(dead_code)]
429
430    use nom::error::ErrorKind;
431
432    use crate::*;
433
434    #[derive(Debug)]
435    struct Everything {
436        integer: i32,
437        uint: u32,
438        float: f64,
439        string: String,
440        vector_int: Vec<i32>,
441        vector_str: Vec<String>,
442        hashmap: HashMap<String, i32>,
443        nested: Bob,
444        custom_hidden: Hidden,
445        enumer1: Boat,
446        enumer2: Boat,
447        enumer3: Option<Boat>,
448        enumer4: Boat,
449        tutu: (i32, f64),
450        nothing: Option<()>,
451        boolean: bool,
452    }
453
454    #[derive(Debug)]
455    enum Boat {
456        JustOne(i32),
457        AnCouple((i32, String)),
458        JustStruct { names: Vec<String>, age: i32 },
459        Unit,
460    }
461
462    #[derive(Debug)]
463    struct Bob {
464        inner_int: f32,
465        inner_string: String,
466    }
467
468    struct Hidden;
469
470    impl std::fmt::Debug for Hidden {
471        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
472            f.write_str("*** hidden ***")
473        }
474    }
475
476    fn generate_data() -> Everything {
477        Everything {
478            uint: 321,
479            integer: -123,
480            float: 123.456,
481            string: "Bob said, \"Hello!\"".to_owned(),
482            vector_int: vec![12, 45, 56, -1, -3],
483            vector_str: vec![
484                "Alice".to_string(),
485                "Venus".to_string(),
486                "Karter".to_string(),
487            ],
488            hashmap: [
489                ("Draco".to_string(), 123),
490                ("Harry".to_string(), -123),
491                ("Ron".to_string(), 0),
492            ]
493            .into_iter()
494            .collect(),
495            nested: Bob {
496                inner_int: -50.0,
497                inner_string: "Sharel".to_string(),
498            },
499            custom_hidden: Hidden,
500            enumer1: Boat::JustOne(1024),
501            enumer2: Boat::AnCouple((512, "Freak".to_string())),
502            enumer3: Some(Boat::JustStruct {
503                names: vec!["Tricky".to_string(), "Hacky".to_string()],
504                age: -256,
505            }),
506            enumer4: Boat::Unit,
507            tutu: (12, -12.5),
508            nothing: None,
509            boolean: false,
510        }
511    }
512
513    #[test]
514    #[ignore]
515    fn test_generate() {
516        panic!("{:?}", generate_data())
517    }
518
519    #[test]
520    #[ignore]
521    fn debug_test() {
522        let data = "!13113431";
523        let (x, y) = parse_integer::<()>(data).unwrap();
524        panic!("{:#?}", (x, y))
525    }
526
527    #[test]
528    fn test_null() {
529        let data = "None";
530        let _value = parse_null::<(&str, ErrorKind)>(data).unwrap();
531    }
532
533    #[test]
534    #[should_panic]
535    fn test_not_null() {
536        let data = "123";
537        let _value = parse_null::<(&str, ErrorKind)>(data).unwrap();
538    }
539
540    #[test]
541    fn test_boolean() {
542        let data = "true";
543        let value = parse_bool::<(&str, ErrorKind)>(data).unwrap();
544        assert!(value.1, "residue: {}", value.0)
545    }
546
547    #[test]
548    #[should_panic]
549    fn test_not_bool() {
550        let data = "123";
551        let _value = parse_bool::<(&str, ErrorKind)>(data).unwrap();
552    }
553
554    #[test]
555    fn test_string() {
556        let data = r#""true""#;
557        let value = string::parse_string::<(&str, ErrorKind)>(data).unwrap();
558        assert_eq!(value.1, "true", "residue: {}", value.0)
559    }
560
561    #[test]
562    #[should_panic]
563    fn test_not_string() {
564        let data = "true";
565        let _value = string::parse_string::<(&str, ErrorKind)>(data).unwrap();
566    }
567
568    #[test]
569    fn test_float() {
570        let data = r#"123.35"#;
571        let value = double::<_, (&str, ErrorKind)>(data).unwrap();
572        assert_eq!(value.1, 123.35, "residue: {}", value.0)
573    }
574
575    #[test]
576    #[should_panic]
577    fn test_not_float() {
578        let data = r#""213""#;
579        let _value = double::<_, (&str, ErrorKind)>(data).unwrap();
580    }
581
582    #[test]
583    fn test_integer() {
584        let data = r#"123"#;
585        let value = parse_integer::<(&str, ErrorKind)>(data).unwrap();
586        assert_eq!(value.1, 123, "residue: {}", value.0)
587    }
588
589    #[test]
590    #[should_panic]
591    fn test_not_integer() {
592        let data = r#""213""#;
593        let _value = parse_integer::<(&str, ErrorKind)>(data).unwrap();
594    }
595
596    #[test]
597    fn test_array() {
598        let data = "[ \"12\", 2.3]";
599
600        let value = parse_array::<(&str, ErrorKind)>(data).unwrap();
601        assert_eq!(
602            value.1,
603            vec![DataModel::String("12".into()), DataModel::Float(2.3)],
604            "residue: {}",
605            value.0
606        )
607    }
608
609    #[test]
610    #[should_panic]
611    fn test_not_array() {
612        let data = "[ \"12\"; 23]";
613        let value = parse_array::<(&str, ErrorKind)>(data).unwrap();
614        assert_eq!(
615            value.1,
616            vec![DataModel::String("12".into()), DataModel::Float(23.0)],
617            "residue: {}",
618            value.0
619        )
620    }
621
622    #[test]
623    fn test_array_tuple() {
624        let data = "(\"12\",23)";
625        let value = parse_array_tuple::<(&str, ErrorKind)>(data).unwrap();
626        assert_eq!(
627            value.1,
628            vec![DataModel::String("12".into()), DataModel::Float(23.0)],
629            "residue: {}",
630            value.0
631        )
632    }
633
634    #[test]
635    #[should_panic]
636    fn test_not_array_tuple() {
637        let data = "( \"12\"; 23)";
638        let value = parse_array_tuple::<(&str, ErrorKind)>(data).unwrap();
639        assert_eq!(
640            value.1,
641            vec![DataModel::String("12".into()), DataModel::Float(23.0)],
642            "residue: {}",
643            value.0
644        )
645    }
646
647    #[test]
648    fn test_hash() {
649        let data = r#"{ "inner": "data", "outer": 123 }"#;
650        let value = parse_hash::<(&str, ErrorKind)>(data).unwrap();
651        assert_eq!(
652            value.1,
653            [
654                ("inner", DataModel::String("data".into())),
655                ("outer", DataModel::Float(123.0))
656            ]
657            .into_iter()
658            .collect(),
659            "residue: {}",
660            value.0
661        )
662    }
663
664    #[test]
665    #[should_panic]
666    fn test_not_hash() {
667        let data = r#"{ inner: "data", outer: 123, value: {} }"#;
668        let value = parse_hash::<(&str, ErrorKind)>(data).unwrap();
669        assert_eq!(
670            value.1,
671            [
672                ("inner", DataModel::String("data".into())),
673                ("outer", DataModel::Float(123.0))
674            ]
675            .into_iter()
676            .collect(),
677            "residue: {}",
678            value.0
679        )
680    }
681
682    #[test]
683    fn test_struct() {
684        let data = r#"Yager { inner: "data", outer: 123 }"#;
685        let value = parse_struct::<(&str, ErrorKind)>(data).unwrap();
686        assert_eq!(
687            value.1,
688            [
689                ("inner", DataModel::String("data".into())),
690                ("outer", DataModel::Float(123.0))
691            ]
692            .into_iter()
693            .collect(),
694            "residue: {}",
695            value.0
696        )
697    }
698
699    #[test]
700    #[should_panic]
701    fn test_not_struct() {
702        let data = r#"Insider( inner: "data", outer: 123, value: {} )"#;
703        let value = parse_struct::<(&str, ErrorKind)>(data).unwrap();
704        assert_eq!(
705            value.1,
706            [
707                ("inner", DataModel::String("data".into())),
708                ("outer", DataModel::Float(123.0))
709            ]
710            .into_iter()
711            .collect(),
712            "residue: {}",
713            value.0
714        )
715    }
716
717    #[test]
718    fn test_array_tuple_var() {
719        let data = "Data((\"12\",23))";
720        let value = parse_tuple_var::<(&str, ErrorKind)>(data).unwrap();
721        assert_eq!(
722            value.1,
723            DataModel::Vec(vec![DataModel::String("12".into()), DataModel::Float(23.0)]),
724            "residue: {}",
725            value.0
726        )
727    }
728
729    #[test]
730    #[should_panic]
731    fn test_not_array_tuple_var() {
732        let data = "Data( \"12\", 23)";
733        let value = parse_tuple_var::<(&str, ErrorKind)>(data).unwrap();
734        assert_eq!(
735            value.1,
736            DataModel::Vec(vec![DataModel::String("12".into()), DataModel::Float(23.0)]),
737            "residue: {}",
738            value.0
739        )
740    }
741
742    #[test]
743    fn test_bob() {
744        let bob = Bob {
745            inner_int: 123.0,
746            inner_string: "data".to_string(),
747        };
748
749        let val = format!("{:?}", bob);
750
751        let a_val1 = "{\"inner_string\":\"data\",\"inner_int\":123.0}";
752        let a_val2 = "{\"inner_int\":123.0,\"inner_string\":\"data\"}";
753        let value = serde_json::to_string(&root::<(&str, ErrorKind)>(&val).unwrap().1).unwrap();
754
755        assert!(value == a_val1 || value == a_val2);
756    }
757
758    #[test]
759    #[ignore = "It's panicable"]
760    fn test_try_all() {
761        let data = generate_data();
762        let data = format!("{:?}", data);
763
764        let data_model = root::<(&str, ErrorKind)>(&data).unwrap().1;
765
766        panic!("{:?}", data_model);
767    }
768
769    #[derive(Debug)]
770    struct A {
771        data: String,
772        value: Ba,
773    }
774    #[derive(Debug)]
775    struct Ba {
776        item: i32,
777    }
778
779    #[test]
780    fn test_xyz() {
781        let data = A {
782            data: "123".to_string(),
783            value: Ba { item: 123 },
784        };
785        let data = format!("{:?}", data);
786        let data_model = root::<(&str, ErrorKind)>(&data).unwrap().1;
787        let value = serde_json::to_string(&data_model).unwrap();
788
789        let a_val2 = "{\"value\":{\"item\":123.0},\"data\":\"123\"}";
790        let a_val1 = "{\"data\":\"123\",\"value\":{\"item\":123.0}}";
791        assert!(value == a_val1 || value == a_val2)
792    }
793
794    #[test]
795    fn test_me_10000() {
796        let data1 = r#"Dalton { name: ""#;
797        let data2 = r#"" }"#;
798        let heavy_data = String::from("A").repeat(1000);
799        let composite_data = {
800            let mut output = String::new();
801            output.push_str(data1);
802            output.push_str(&heavy_data);
803            output.push_str(data2);
804            output
805        };
806        let parsed = root::<(&str, ErrorKind)>(&composite_data).unwrap().1;
807        let expected = DataModel::Map([("name", DataModel::String(heavy_data.into()))].into());
808        println!("{:#?}", parsed);
809        assert_eq!(parsed, expected)
810    }
811
812    #[test]
813    #[ignore = "It's panicable"]
814    fn test_payment_request() {
815        let data = r#"PaymentsRequest { payment_id: None, merchant_id: None, amount: Some(Value(6500)), routing: None, connector: None, currency: Some(USD), capture_method: Some(Automatic), amount_to_capture: None, capture_on: None, confirm: Some(false), customer: None, customer_id: Some("hyperswitch111"), email: Some(Email(*********@gmail.com)), name: None, phone: None, phone_country_code: None, off_session: None, description: Some("Hello this is description"), return_url: None, setup_future_usage: None, authentication_type: Some(ThreeDs), payment_method_data: None, payment_method: None, payment_token: None, card_cvc: None, shipping: Some(Address { address: Some(AddressDetails { city: Some("Banglore"), country: Some(US), line1: Some(*** alloc::string::String ***), line2: Some(*** alloc::string::String ***), line3: Some(*** alloc::string::String ***), zip: Some(*** alloc::string::String ***), state: Some(*** alloc::string::String ***), first_name: Some(*** alloc::string::String ***), last_name: None }), phone: Some(PhoneDetails { number: Some(*** alloc::string::String ***), country_code: Some("+1") }) }), billing: Some(Address { address: Some(AddressDetails { city: Some("San Fransico"), country: Some(AT), line1: Some(*** alloc::string::String ***), line2: Some(*** alloc::string::String ***), line3: Some(*** alloc::string::String ***), zip: Some(*** alloc::string::String ***), state: Some(*** alloc::string::String ***), first_name: Some(*** alloc::string::String ***), last_name: Some(*** alloc::string::String ***) }), phone: Some(PhoneDetails { number: Some(*** alloc::string::String ***), country_code: Some("+91") }) }), statement_descriptor_name: None, statement_descriptor_suffix: None, metadata: Some(Metadata { order_details: Some(OrderDetails { product_name: "gillete razor", quantity: 1 }), order_category: None, redirect_response: None, allowed_payment_method_types: None }), order_details: None, client_secret: None, mandate_data: None, mandate_id: None, browser_info: None, payment_experience: None, payment_method_type: None, business_country: Some(US), business_label: Some("default"), merchant_connector_details: None, allowed_payment_method_types: None, business_sub_label: None, manual_retry: false, udf: None }"#;
816
817        let data_model = root::<(&str, ErrorKind)>(data).unwrap().1;
818
819        panic!("{:?}", data_model);
820    }
821
822    #[test]
823    fn test_parse_datetime() {
824        let datetime = "2023-06-06 12:30:30.351996";
825        let parse = parse_datetime::<(&str, ErrorKind)>(datetime).unwrap();
826        assert_eq!(parse.1, "2023-06-06 12:30:30.351996")
827    }
828
829    #[test]
830    fn test_parse_date_response() {
831        let data = "PaymentsResponse { created: Some(2023-06-06 12:30:30.351996)}";
832        let parse = root::<(&str, ErrorKind)>(data).unwrap().1;
833        assert_eq!(
834            parse,
835            DataModel::Map(
836                [(
837                    "created",
838                    DataModel::String("2023-06-06 12:30:30.351996".into())
839                )]
840                .into()
841            )
842        )
843    }
844
845    #[test]
846    #[ignore = "It's panicable"]
847    fn regression_test_1() {
848        let data = r#"PaymentsRequest { payment_id: Some(PaymentIntentId("pay_nLjAOteAucUEv29qLv01")), merchant_id: None, amount: None, routing: None, connector: None, currency: None, capture_method: None, amount_to_capture: None, capture_on: None, confirm: Some(true), customer: None, customer_id: None, email: None, name: None, phone: None, phone_country_code: None, off_session: None, description: None, return_url: Some(Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("app.hyperswitch.io")), port: None, path: "/home", query: None, fragment: None }), setup_future_usage: None, authentication_type: None, payment_method_data: Some(Card(Card { card_number: CardNumber(424242**********), card_exp_month: *** alloc::string::String ***, card_exp_year: *** alloc::string::String ***, card_holder_name: *** alloc::string::String ***, card_cvc: *** alloc::string::String ***, card_issuer: Some(""), card_network: Some(Visa) })), payment_method: Some(Card), payment_token: None, card_cvc: None, shipping: None, billing: None, statement_descriptor_name: None, statement_descriptor_suffix: None, metadata: None, order_details: None, client_secret: Some("pay_nLjAOteAucUEv29qLv01_secret_9M2BQVnMPskkdYGitWNJ"), mandate_data: None, mandate_id: None, browser_info: Some(Object {"color_depth": Number(30), "java_enabled": Bool(true), "java_script_enabled": Bool(true), "language": String("en-GB"), "screen_height": Number(1117), "screen_width": Number(1728), "time_zone": Number(-330), "ip_address": String("65.1.52.128"), "accept_header": String("text\\/html,application\\/xhtml+xml,application\\/xml;q=0.9,image\\/webp,image\\/apng,*\\/*;q=0.8"), "user_agent": String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")}), payment_experience: None, payment_method_type: None, business_country: None, business_label: None, merchant_connector_details: None, allowed_payment_method_types: None, business_sub_label: None, manual_retry: false, udf: None }"#;
849
850        let parse = root::<(&str, ErrorKind)>(data).unwrap().1;
851        panic!("{:#?}", parse);
852    }
853
854    #[test]
855    fn test_empty_brackets() {
856        let data = "PaymentsRequest { payment_methods: [] }";
857        let parse = root::<(&str, ErrorKind)>(data).unwrap().1;
858        assert_eq!(
859            parse,
860            DataModel::Map([("payment_methods", DataModel::Vec(vec![]))].into())
861        )
862    }
863}