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#[derive(Clone, Debug, PartialEq, serde::Serialize)]
25#[serde(untagged)]
26pub enum DataModel<'a> {
27 Null, Boolean(bool), Float(f64), String(Cow<'a, str>), Map(HashMap<&'a str, DataModel<'a>>), Vec(Vec<DataModel<'a>>), }
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 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 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
364pub 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#[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
409pub 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}