• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::collections::BTreeMap;
2 
3 use serde::Deserialize;
4 use serde::Deserializer;
5 use serde::Serialize;
6 use snapbox::assert_data_eq;
7 use snapbox::prelude::*;
8 use snapbox::str;
9 use toml::map::Map;
10 use toml::Table;
11 use toml::Value;
12 
13 macro_rules! t {
14     ($e:expr) => {
15         match $e {
16             Ok(t) => t,
17             Err(e) => panic!("{} failed with {}", stringify!($e), e),
18         }
19     };
20 }
21 
22 macro_rules! equivalent {
23     ($literal:expr, $toml:expr,) => {{
24         let toml = $toml;
25         let literal = $literal;
26 
27         // Through a string equivalent
28         println!("to_string");
29         assert_data_eq!(
30             t!(toml::to_string(&toml)),
31             t!(toml::to_string(&literal)).raw()
32         );
33         println!("literal, from_str(toml)");
34         assert_eq!(literal, t!(toml::from_str(&t!(toml::to_string(&toml)))));
35         println!("toml, from_str(literal)");
36         assert_eq!(toml, t!(toml::from_str(&t!(toml::to_string(&literal)))));
37 
38         // In/out of Value is equivalent
39         println!("Table::try_from(literal)");
40         assert_eq!(toml, t!(Table::try_from(literal.clone())));
41         println!("Value::try_from(literal)");
42         assert_eq!(
43             Value::Table(toml.clone()),
44             t!(Value::try_from(literal.clone()))
45         );
46         println!("toml.try_into()");
47         assert_eq!(literal, t!(toml.clone().try_into()));
48         println!("Value::Table(toml).try_into()");
49         assert_eq!(literal, t!(Value::Table(toml.clone()).try_into()));
50     }};
51 }
52 
53 macro_rules! error {
54     ($ty:ty, $toml:expr, $msg_parse:expr, $msg_decode:expr) => {{
55         println!("attempting parsing");
56         match toml::from_str::<$ty>(&$toml.to_string()) {
57             Ok(_) => panic!("successful"),
58             Err(e) => assert_data_eq!(e.to_string(), $msg_parse.raw()),
59         }
60 
61         println!("attempting toml decoding");
62         match $toml.try_into::<$ty>() {
63             Ok(_) => panic!("successful"),
64             Err(e) => assert_data_eq!(e.to_string(), $msg_decode.raw()),
65         }
66     }};
67 }
68 
69 macro_rules! map( ($($k:ident: $v:expr),*) => ({
70     let mut _m = Map::new();
71     $(_m.insert(stringify!($k).to_owned(), t!(Value::try_from($v)));)*
72     _m
73 }) );
74 
75 #[test]
smoke()76 fn smoke() {
77     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
78     struct Foo {
79         a: isize,
80     }
81 
82     equivalent!(Foo { a: 2 }, map! { a: Value::Integer(2) },);
83 }
84 
85 #[test]
smoke_hyphen()86 fn smoke_hyphen() {
87     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
88     struct Foo {
89         a_b: isize,
90     }
91 
92     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
93     struct Foo2 {
94         #[serde(rename = "a-b")]
95         a_b: isize,
96     }
97 
98     equivalent! {
99         Foo { a_b: 2 },
100         map! { a_b: Value::Integer(2)},
101     }
102 
103     let mut m = Map::new();
104     m.insert("a-b".to_owned(), Value::Integer(2));
105     equivalent! {
106         Foo2 { a_b: 2 },
107         m,
108     }
109 }
110 
111 #[test]
nested()112 fn nested() {
113     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
114     struct Foo {
115         a: isize,
116         b: Bar,
117     }
118     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
119     struct Bar {
120         a: String,
121     }
122 
123     equivalent! {
124         Foo { a: 2, b: Bar { a: "test".to_owned() } },
125         map! {
126             a: Value::Integer(2),
127             b: map! {
128                 a: Value::String("test".to_owned())
129             }
130         },
131     }
132 }
133 
134 #[test]
application_decode_error()135 fn application_decode_error() {
136     #[derive(PartialEq, Debug)]
137     struct Range10(usize);
138     impl<'de> Deserialize<'de> for Range10 {
139         fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Range10, D::Error> {
140             let x: usize = Deserialize::deserialize(d)?;
141             if x > 10 {
142                 Err(serde::de::Error::custom("more than 10"))
143             } else {
144                 Ok(Range10(x))
145             }
146         }
147     }
148     let d_good = Value::Integer(5);
149     let d_bad1 = Value::String("not an isize".to_owned());
150     let d_bad2 = Value::Integer(11);
151 
152     assert_eq!(Range10(5), d_good.try_into().unwrap());
153 
154     let err1: Result<Range10, _> = d_bad1.try_into();
155     assert!(err1.is_err());
156     let err2: Result<Range10, _> = d_bad2.try_into();
157     assert!(err2.is_err());
158 }
159 
160 #[test]
array()161 fn array() {
162     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
163     struct Foo {
164         a: Vec<isize>,
165     }
166 
167     equivalent! {
168         Foo { a: vec![1, 2, 3, 4] },
169         map! {
170             a: Value::Array(vec![
171                 Value::Integer(1),
172                 Value::Integer(2),
173                 Value::Integer(3),
174                 Value::Integer(4)
175             ])
176         },
177     };
178 }
179 
180 #[test]
inner_structs_with_options()181 fn inner_structs_with_options() {
182     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
183     struct Foo {
184         a: Option<Box<Foo>>,
185         b: Bar,
186     }
187     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
188     struct Bar {
189         a: String,
190         b: f64,
191     }
192 
193     equivalent! {
194         Foo {
195             a: Some(Box::new(Foo {
196                 a: None,
197                 b: Bar { a: "foo".to_owned(), b: 4.5 },
198             })),
199             b: Bar { a: "bar".to_owned(), b: 1.0 },
200         },
201         map! {
202             a: map! {
203                 b: map! {
204                     a: Value::String("foo".to_owned()),
205                     b: Value::Float(4.5)
206                 }
207             },
208             b: map! {
209                 a: Value::String("bar".to_owned()),
210                 b: Value::Float(1.0)
211             }
212         },
213     }
214 }
215 
216 #[test]
217 #[cfg(feature = "preserve_order")]
hashmap()218 fn hashmap() {
219     use std::collections::HashSet;
220 
221     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
222     struct Foo {
223         set: HashSet<char>,
224         map: BTreeMap<String, isize>,
225     }
226 
227     equivalent! {
228         Foo {
229             set: {
230                 let mut s = HashSet::new();
231                 s.insert('a');
232                 s
233             },
234             map: {
235                 let mut m = BTreeMap::new();
236                 m.insert("bar".to_owned(), 4);
237                 m.insert("foo".to_owned(), 10);
238                 m
239             }
240         },
241         map! {
242             set: Value::Array(vec![Value::String("a".to_owned())]),
243             map: map! {
244                 bar: Value::Integer(4),
245                 foo: Value::Integer(10)
246             }
247         },
248     }
249 }
250 
251 #[test]
table_array()252 fn table_array() {
253     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
254     struct Foo {
255         a: Vec<Bar>,
256     }
257     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
258     struct Bar {
259         a: isize,
260     }
261 
262     equivalent! {
263         Foo { a: vec![Bar { a: 1 }, Bar { a: 2 }] },
264         map! {
265             a: Value::Array(vec![
266                 Value::Table(map!{ a: Value::Integer(1) }),
267                 Value::Table(map!{ a: Value::Integer(2) }),
268             ])
269         },
270     }
271 }
272 
273 #[test]
type_errors()274 fn type_errors() {
275     #[derive(Deserialize)]
276     #[allow(dead_code)]
277     struct Foo {
278         bar: isize,
279     }
280 
281     #[derive(Deserialize)]
282     #[allow(dead_code)]
283     struct Bar {
284         foo: Foo,
285     }
286 
287     error! {
288         Foo,
289         map! {
290             bar: Value::String("a".to_owned())
291         },
292         str![[r#"
293 TOML parse error at line 1, column 7
294   |
295 1 | bar = "a"
296   |       ^^^
297 invalid type: string "a", expected isize
298 
299 "#]],
300         str![[r#"
301 invalid type: string "a", expected isize
302 in `bar`
303 
304 "#]]
305     }
306 
307     error! {
308         Bar,
309         map! {
310             foo: map! {
311                 bar: Value::String("a".to_owned())
312             }
313         },
314         str![[r#"
315 TOML parse error at line 2, column 7
316   |
317 2 | bar = "a"
318   |       ^^^
319 invalid type: string "a", expected isize
320 
321 "#]],
322         str![[r#"
323 invalid type: string "a", expected isize
324 in `foo.bar`
325 
326 "#]]
327     }
328 }
329 
330 #[test]
missing_errors()331 fn missing_errors() {
332     #[derive(Serialize, Deserialize, PartialEq, Debug)]
333     struct Foo {
334         bar: isize,
335     }
336 
337     error! {
338         Foo,
339         map! { },
340         str![[r#"
341 TOML parse error at line 1, column 1
342   |
343 1 |
344   | ^
345 missing field `bar`
346 
347 "#]],
348         str![[r#"
349 missing field `bar`
350 
351 "#]]
352     }
353 }
354 
355 #[test]
parse_enum()356 fn parse_enum() {
357     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
358     struct Foo {
359         a: E,
360     }
361     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
362     #[serde(untagged)]
363     enum E {
364         Bar(isize),
365         Baz(String),
366         Last(Foo2),
367     }
368     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
369     struct Foo2 {
370         test: String,
371     }
372 
373     equivalent! {
374         Foo { a: E::Bar(10) },
375         map! { a: Value::Integer(10) },
376     }
377 
378     equivalent! {
379         Foo { a: E::Baz("foo".to_owned()) },
380         map! { a: Value::String("foo".to_owned()) },
381     }
382 
383     equivalent! {
384         Foo { a: E::Last(Foo2 { test: "test".to_owned() }) },
385         map! { a: map! { test: Value::String("test".to_owned()) } },
386     }
387 }
388 
389 #[test]
parse_enum_string()390 fn parse_enum_string() {
391     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
392     struct Foo {
393         a: Sort,
394     }
395 
396     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
397     #[serde(rename_all = "lowercase")]
398     enum Sort {
399         Asc,
400         Desc,
401     }
402 
403     equivalent! {
404         Foo { a: Sort::Desc },
405         map! { a: Value::String("desc".to_owned()) },
406     }
407 }
408 
409 #[test]
parse_tuple_variant()410 fn parse_tuple_variant() {
411     #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
412     struct Document {
413         inner: Vec<Enum>,
414     }
415 
416     #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
417     enum Enum {
418         Int(i32, i32),
419         String(String, String),
420     }
421 
422     let input = Document {
423         inner: vec![
424             Enum::Int(1, 1),
425             Enum::String("2".to_owned(), "2".to_owned()),
426         ],
427     };
428     let raw = toml::to_string(&input).unwrap();
429     assert_data_eq!(
430         raw,
431         str![[r#"
432 [[inner]]
433 Int = [1, 1]
434 
435 [[inner]]
436 String = ["2", "2"]
437 
438 "#]]
439         .raw()
440     );
441 
442     equivalent! {
443         Document {
444             inner: vec![
445                 Enum::Int(1, 1),
446                 Enum::String("2".to_owned(), "2".to_owned()),
447             ],
448         },
449         map! {
450             inner: vec![
451                 map! { Int: [1, 1] },
452                 map! { String: ["2".to_owned(), "2".to_owned()] },
453             ]
454         },
455     }
456 }
457 
458 #[test]
parse_struct_variant()459 fn parse_struct_variant() {
460     #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
461     struct Document {
462         inner: Vec<Enum>,
463     }
464 
465     #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
466     enum Enum {
467         Int { first: i32, second: i32 },
468         String { first: String, second: String },
469     }
470 
471     let input = Document {
472         inner: vec![
473             Enum::Int {
474                 first: 1,
475                 second: 1,
476             },
477             Enum::String {
478                 first: "2".to_owned(),
479                 second: "2".to_owned(),
480             },
481         ],
482     };
483     let raw = toml::to_string(&input).unwrap();
484     assert_data_eq!(
485         raw,
486         str![[r#"
487 [[inner]]
488 
489 [inner.Int]
490 first = 1
491 second = 1
492 
493 [[inner]]
494 
495 [inner.String]
496 first = "2"
497 second = "2"
498 
499 "#]]
500         .raw()
501     );
502 
503     equivalent! {
504         Document {
505             inner: vec![
506                 Enum::Int { first: 1, second: 1 },
507                 Enum::String { first: "2".to_owned(), second: "2".to_owned() },
508             ],
509         },
510         map! {
511             inner: vec![
512                 map! { Int: map! { first: 1, second: 1 } },
513                 map! { String: map! { first: "2".to_owned(), second: "2".to_owned() } },
514             ]
515         },
516     }
517 }
518 
519 #[test]
520 #[cfg(feature = "preserve_order")]
map_key_unit_variants()521 fn map_key_unit_variants() {
522     #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, PartialOrd, Ord)]
523     enum Sort {
524         #[serde(rename = "ascending")]
525         Asc,
526         Desc,
527     }
528 
529     let mut map = BTreeMap::new();
530     map.insert(Sort::Asc, 1);
531     map.insert(Sort::Desc, 2);
532 
533     equivalent! {
534         map,
535         map! { ascending: Value::Integer(1), Desc: Value::Integer(2) },
536     }
537 }
538 
539 // #[test]
540 // fn unused_fields() {
541 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
542 //     struct Foo { a: isize }
543 //
544 //     let v = Foo { a: 2 };
545 //     let mut d = Decoder::new(Table(map! {
546 //         a, Integer(2),
547 //         b, Integer(5)
548 //     }));
549 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
550 //
551 //     assert_eq!(d.toml, Some(Table(map! {
552 //         b, Integer(5)
553 //     })));
554 // }
555 //
556 // #[test]
557 // fn unused_fields2() {
558 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
559 //     struct Foo { a: Bar }
560 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
561 //     struct Bar { a: isize }
562 //
563 //     let v = Foo { a: Bar { a: 2 } };
564 //     let mut d = Decoder::new(Table(map! {
565 //         a, Table(map! {
566 //             a, Integer(2),
567 //             b, Integer(5)
568 //         })
569 //     }));
570 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
571 //
572 //     assert_eq!(d.toml, Some(Table(map! {
573 //         a, Table(map! {
574 //             b, Integer(5)
575 //         })
576 //     })));
577 // }
578 //
579 // #[test]
580 // fn unused_fields3() {
581 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
582 //     struct Foo { a: Bar }
583 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
584 //     struct Bar { a: isize }
585 //
586 //     let v = Foo { a: Bar { a: 2 } };
587 //     let mut d = Decoder::new(Table(map! {
588 //         a, Table(map! {
589 //             a, Integer(2)
590 //         })
591 //     }));
592 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
593 //
594 //     assert_eq!(d.toml, None);
595 // }
596 //
597 // #[test]
598 // fn unused_fields4() {
599 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
600 //     struct Foo { a: BTreeMap<String, String> }
601 //
602 //     let v = Foo { a: map! { a, "foo".to_owned() } };
603 //     let mut d = Decoder::new(Table(map! {
604 //         a, Table(map! {
605 //             a, Value::String("foo".to_owned())
606 //         })
607 //     }));
608 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
609 //
610 //     assert_eq!(d.toml, None);
611 // }
612 //
613 // #[test]
614 // fn unused_fields5() {
615 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
616 //     struct Foo { a: Vec<String> }
617 //
618 //     let v = Foo { a: vec!["a".to_owned()] };
619 //     let mut d = Decoder::new(Table(map! {
620 //         a, Array(vec![Value::String("a".to_owned())])
621 //     }));
622 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
623 //
624 //     assert_eq!(d.toml, None);
625 // }
626 //
627 // #[test]
628 // fn unused_fields6() {
629 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
630 //     struct Foo { a: Option<Vec<String>> }
631 //
632 //     let v = Foo { a: Some(vec![]) };
633 //     let mut d = Decoder::new(Table(map! {
634 //         a, Array(vec![])
635 //     }));
636 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
637 //
638 //     assert_eq!(d.toml, None);
639 // }
640 //
641 // #[test]
642 // fn unused_fields7() {
643 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
644 //     struct Foo { a: Vec<Bar> }
645 //     #[derive(Serialize, Deserialize, PartialEq, Debug)]
646 //     struct Bar { a: isize }
647 //
648 //     let v = Foo { a: vec![Bar { a: 1 }] };
649 //     let mut d = Decoder::new(Table(map! {
650 //         a, Array(vec![Table(map! {
651 //             a, Integer(1),
652 //             b, Integer(2)
653 //         })])
654 //     }));
655 //     assert_eq!(v, t!(Deserialize::deserialize(&mut d)));
656 //
657 //     assert_eq!(d.toml, Some(Table(map! {
658 //         a, Array(vec![Table(map! {
659 //             b, Integer(2)
660 //         })])
661 //     })));
662 // }
663 
664 #[test]
empty_arrays()665 fn empty_arrays() {
666     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
667     struct Foo {
668         a: Vec<Bar>,
669     }
670     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
671     struct Bar;
672 
673     equivalent! {
674         Foo { a: vec![] },
675         map! {a: Value::Array(Vec::new())},
676     }
677 }
678 
679 #[test]
empty_arrays2()680 fn empty_arrays2() {
681     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
682     struct Foo {
683         a: Option<Vec<Bar>>,
684     }
685     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
686     struct Bar;
687 
688     equivalent! {
689         Foo { a: None },
690         map! {},
691     }
692 
693     equivalent! {
694         Foo { a: Some(vec![]) },
695         map! { a: Value::Array(vec![]) },
696     }
697 }
698 
699 #[test]
extra_keys()700 fn extra_keys() {
701     #[derive(Serialize, Deserialize)]
702     struct Foo {
703         a: isize,
704     }
705 
706     let toml = map! { a: Value::Integer(2), b: Value::Integer(2) };
707     assert!(toml.clone().try_into::<Foo>().is_ok());
708     assert!(toml::from_str::<Foo>(&toml.to_string()).is_ok());
709 }
710 
711 #[test]
newtypes()712 fn newtypes() {
713     #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
714     struct A {
715         b: B,
716     }
717 
718     #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
719     struct B(u32);
720 
721     equivalent! {
722         A { b: B(2) },
723         map! { b: Value::Integer(2) },
724     }
725 }
726 
727 #[test]
newtypes2()728 fn newtypes2() {
729     #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
730     struct A {
731         b: B,
732     }
733 
734     #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
735     struct B(Option<C>);
736 
737     #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
738     struct C {
739         x: u32,
740         y: u32,
741         z: u32,
742     }
743 
744     equivalent! {
745         A { b: B(Some(C { x: 0, y: 1, z: 2 })) },
746         map! {
747             b: map! {
748                 x: Value::Integer(0),
749                 y: Value::Integer(1),
750                 z: Value::Integer(2)
751             }
752         },
753     }
754 }
755 
756 #[test]
newtype_variant()757 fn newtype_variant() {
758     #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
759     struct Struct {
760         field: Enum,
761     }
762 
763     #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
764     enum Enum {
765         Variant(u8),
766     }
767 
768     equivalent! {
769         Struct { field: Enum::Variant(21) },
770         map! {
771             field: map! {
772                 Variant: Value::Integer(21)
773             }
774         },
775     }
776 }
777 
778 #[test]
newtype_key()779 fn newtype_key() {
780     #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Serialize, Deserialize)]
781     struct NewType(String);
782 
783     type CustomKeyMap = BTreeMap<NewType, u32>;
784 
785     equivalent! {
786         [
787             (NewType("x".to_owned()), 1),
788             (NewType("y".to_owned()), 2),
789         ].into_iter().collect::<CustomKeyMap>(),
790         map! {
791             x: Value::Integer(1),
792             y: Value::Integer(2)
793         },
794     }
795 }
796 
797 #[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
798 struct CanBeEmpty {
799     a: Option<String>,
800     b: Option<String>,
801 }
802 
803 #[test]
table_structs_empty()804 fn table_structs_empty() {
805     let text = "[bar]\n\n[baz]\n\n[bazv]\na = \"foo\"\n\n[foo]\n";
806     let value: BTreeMap<String, CanBeEmpty> = toml::from_str(text).unwrap();
807     let mut expected: BTreeMap<String, CanBeEmpty> = BTreeMap::new();
808     expected.insert("bar".to_owned(), CanBeEmpty::default());
809     expected.insert("baz".to_owned(), CanBeEmpty::default());
810     expected.insert(
811         "bazv".to_owned(),
812         CanBeEmpty {
813             a: Some("foo".to_owned()),
814             b: None,
815         },
816     );
817     expected.insert("foo".to_owned(), CanBeEmpty::default());
818     assert_eq!(value, expected);
819     assert_data_eq!(toml::to_string(&value).unwrap(), text.raw());
820 }
821 
822 #[test]
fixed_size_array()823 fn fixed_size_array() {
824     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
825     struct Entity {
826         pos: [i32; 2],
827     }
828 
829     equivalent! {
830         Entity { pos: [1, 2] },
831         map! {
832             pos: Value::Array(vec![
833                 Value::Integer(1),
834                 Value::Integer(2),
835             ])
836         },
837     }
838 }
839 
840 #[test]
homogeneous_tuple()841 fn homogeneous_tuple() {
842     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
843     struct Collection {
844         elems: (i64, i64, i64),
845     }
846 
847     equivalent! {
848         Collection { elems: (0, 1, 2) },
849         map! {
850             elems: Value::Array(vec![
851                 Value::Integer(0),
852                 Value::Integer(1),
853                 Value::Integer(2),
854             ])
855         },
856     }
857 }
858 
859 #[test]
homogeneous_tuple_struct()860 fn homogeneous_tuple_struct() {
861     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
862     struct Object(Vec<String>, Vec<String>, Vec<String>);
863 
864     equivalent! {
865         map! {
866             obj: Object(vec!["foo".to_owned()], vec![], vec!["bar".to_owned(), "baz".to_owned()])
867         },
868         map! {
869             obj: Value::Array(vec![
870                 Value::Array(vec![
871                     Value::String("foo".to_owned()),
872                 ]),
873                 Value::Array(vec![]),
874                 Value::Array(vec![
875                     Value::String("bar".to_owned()),
876                     Value::String("baz".to_owned()),
877                 ]),
878             ])
879         },
880     }
881 }
882 
883 #[test]
json_interoperability()884 fn json_interoperability() {
885     #[derive(Serialize, Deserialize)]
886     struct Foo {
887         any: Value,
888     }
889 
890     let _foo: Foo = serde_json::from_str(
891         r#"
892         {"any":1}
893     "#,
894     )
895     .unwrap();
896 }
897 
898 #[test]
error_includes_key()899 fn error_includes_key() {
900     #[derive(Debug, Serialize, Deserialize)]
901     struct Package {
902         name: String,
903         version: String,
904         authors: Vec<String>,
905         profile: Profile,
906     }
907 
908     #[derive(Debug, Serialize, Deserialize)]
909     struct Profile {
910         dev: Dev,
911     }
912 
913     #[derive(Debug, Serialize, Deserialize)]
914     struct Dev {
915         debug: U32OrBool,
916     }
917 
918     #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
919     #[serde(untagged, expecting = "expected a boolean or an integer")]
920     pub(crate) enum U32OrBool {
921         U32(u32),
922         Bool(bool),
923     }
924 
925     let res: Result<Package, _> = toml::from_str(
926         r#"
927 [package]
928 name = "foo"
929 version = "0.0.0"
930 authors = []
931 
932 [profile.dev]
933 debug = 'a'
934 "#,
935     );
936     let err = res.unwrap_err();
937     assert_data_eq!(
938         err.to_string(),
939         str![[r#"
940 TOML parse error at line 8, column 9
941   |
942 8 | debug = 'a'
943   |         ^^^
944 expected a boolean or an integer
945 
946 "#]]
947     );
948 
949     let res: Result<Package, _> = toml::from_str(
950         r#"
951 [package]
952 name = "foo"
953 version = "0.0.0"
954 authors = []
955 
956 [profile]
957 dev = { debug = 'a' }
958 "#,
959     );
960     let err = res.unwrap_err();
961     assert_data_eq!(
962         err.to_string(),
963         str![[r#"
964 TOML parse error at line 8, column 17
965   |
966 8 | dev = { debug = 'a' }
967   |                 ^^^
968 expected a boolean or an integer
969 
970 "#]]
971     );
972 }
973 
974 #[test]
newline_key_value()975 fn newline_key_value() {
976     #[derive(Debug, Serialize, Deserialize)]
977     struct Package {
978         name: String,
979     }
980 
981     let package = Package {
982         name: "foo".to_owned(),
983     };
984     let raw = toml::to_string_pretty(&package).unwrap();
985     assert_data_eq!(
986         raw,
987         str![[r#"
988 name = "foo"
989 
990 "#]]
991     );
992 }
993 
994 #[test]
newline_table()995 fn newline_table() {
996     #[derive(Debug, Serialize, Deserialize)]
997     struct Manifest {
998         package: Package,
999     }
1000 
1001     #[derive(Debug, Serialize, Deserialize)]
1002     struct Package {
1003         name: String,
1004     }
1005 
1006     let package = Manifest {
1007         package: Package {
1008             name: "foo".to_owned(),
1009         },
1010     };
1011     let raw = toml::to_string_pretty(&package).unwrap();
1012     assert_data_eq!(
1013         raw,
1014         str![[r#"
1015 [package]
1016 name = "foo"
1017 
1018 "#]]
1019     );
1020 }
1021 
1022 #[test]
newline_dotted_table()1023 fn newline_dotted_table() {
1024     #[derive(Debug, Serialize, Deserialize)]
1025     struct Manifest {
1026         profile: Profile,
1027     }
1028 
1029     #[derive(Debug, Serialize, Deserialize)]
1030     struct Profile {
1031         dev: Dev,
1032     }
1033 
1034     #[derive(Debug, Serialize, Deserialize)]
1035     struct Dev {
1036         debug: U32OrBool,
1037     }
1038 
1039     #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
1040     #[serde(untagged, expecting = "expected a boolean or an integer")]
1041     pub(crate) enum U32OrBool {
1042         U32(u32),
1043         Bool(bool),
1044     }
1045 
1046     let package = Manifest {
1047         profile: Profile {
1048             dev: Dev {
1049                 debug: U32OrBool::Bool(true),
1050             },
1051         },
1052     };
1053     let raw = toml::to_string_pretty(&package).unwrap();
1054     assert_data_eq!(
1055         raw,
1056         str![[r#"
1057 [profile.dev]
1058 debug = true
1059 
1060 "#]]
1061     );
1062 }
1063 
1064 #[test]
newline_mixed_tables()1065 fn newline_mixed_tables() {
1066     #[derive(Debug, Serialize, Deserialize)]
1067     struct Manifest {
1068         cargo_features: Vec<String>,
1069         package: Package,
1070         profile: Profile,
1071     }
1072 
1073     #[derive(Debug, Serialize, Deserialize)]
1074     struct Package {
1075         name: String,
1076         version: String,
1077         authors: Vec<String>,
1078     }
1079 
1080     #[derive(Debug, Serialize, Deserialize)]
1081     struct Profile {
1082         dev: Dev,
1083     }
1084 
1085     #[derive(Debug, Serialize, Deserialize)]
1086     struct Dev {
1087         debug: U32OrBool,
1088     }
1089 
1090     #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
1091     #[serde(untagged, expecting = "expected a boolean or an integer")]
1092     pub(crate) enum U32OrBool {
1093         U32(u32),
1094         Bool(bool),
1095     }
1096 
1097     let package = Manifest {
1098         cargo_features: vec![],
1099         package: Package {
1100             name: "foo".to_owned(),
1101             version: "1.0.0".to_owned(),
1102             authors: vec![],
1103         },
1104         profile: Profile {
1105             dev: Dev {
1106                 debug: U32OrBool::Bool(true),
1107             },
1108         },
1109     };
1110     let raw = toml::to_string_pretty(&package).unwrap();
1111     assert_data_eq!(
1112         raw,
1113         str![[r#"
1114 cargo_features = []
1115 
1116 [package]
1117 name = "foo"
1118 version = "1.0.0"
1119 authors = []
1120 
1121 [profile.dev]
1122 debug = true
1123 
1124 "#]]
1125     );
1126 }
1127 
1128 #[test]
integer_min()1129 fn integer_min() {
1130     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
1131     struct Foo {
1132         a_b: i64,
1133     }
1134 
1135     equivalent! {
1136         Foo { a_b: i64::MIN },
1137         map! { a_b: Value::Integer(i64::MIN) },
1138     }
1139 }
1140 
1141 #[test]
integer_too_big()1142 fn integer_too_big() {
1143     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
1144     struct Foo {
1145         a_b: u64,
1146     }
1147 
1148     let native = Foo { a_b: u64::MAX };
1149     let err = Table::try_from(native.clone()).unwrap_err();
1150     assert_data_eq!(err.to_string(), str!["u64 value was too large"].raw());
1151     let err = toml::to_string(&native).unwrap_err();
1152     assert_data_eq!(
1153         err.to_string(),
1154         str!["out-of-range value for u64 type"].raw()
1155     );
1156 }
1157 
1158 #[test]
integer_max()1159 fn integer_max() {
1160     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
1161     struct Foo {
1162         a_b: i64,
1163     }
1164 
1165     equivalent! {
1166         Foo { a_b: i64::MAX },
1167         map! { a_b: Value::Integer(i64::MAX) },
1168     }
1169 }
1170 
1171 #[test]
float_min()1172 fn float_min() {
1173     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
1174     struct Foo {
1175         a_b: f64,
1176     }
1177 
1178     equivalent! {
1179         Foo { a_b: f64::MIN },
1180         map! { a_b: Value::Float(f64::MIN) },
1181     }
1182 }
1183 
1184 #[test]
float_max()1185 fn float_max() {
1186     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
1187     struct Foo {
1188         a_b: f64,
1189     }
1190 
1191     equivalent! {
1192         Foo { a_b: f64::MAX },
1193         map! { a_b: Value::Float(f64::MAX) },
1194     }
1195 }
1196 
1197 #[test]
unsupported_root_type()1198 fn unsupported_root_type() {
1199     let native = "value";
1200     let err = toml::to_string_pretty(&native).unwrap_err();
1201     assert_data_eq!(err.to_string(), str!["unsupported rust type"].raw());
1202 }
1203 
1204 #[test]
unsupported_nested_type()1205 fn unsupported_nested_type() {
1206     #[derive(Debug, Serialize, Deserialize)]
1207     struct Foo {
1208         unused: (),
1209     }
1210 
1211     let native = Foo { unused: () };
1212     let err = toml::to_string_pretty(&native).unwrap_err();
1213     assert_data_eq!(err.to_string(), str!["unsupported unit type"].raw());
1214 }
1215 
1216 #[test]
table_type_enum_regression_issue_388()1217 fn table_type_enum_regression_issue_388() {
1218     #[derive(Deserialize)]
1219     struct DataFile {
1220         #[allow(dead_code)]
1221         data: Compare,
1222     }
1223 
1224     #[derive(Deserialize)]
1225     #[allow(dead_code)]
1226     enum Compare {
1227         Gt(u32),
1228     }
1229 
1230     let dotted_table = r#"
1231         data.Gt = 5
1232         "#;
1233     assert!(toml::from_str::<DataFile>(dotted_table).is_ok());
1234 
1235     let inline_table = r#"
1236         data = { Gt = 5 }
1237         "#;
1238     assert!(toml::from_str::<DataFile>(inline_table).is_ok());
1239 }
1240 
1241 #[test]
serialize_datetime_issue_333()1242 fn serialize_datetime_issue_333() {
1243     use toml::{to_string, value::Date, value::Datetime};
1244 
1245     #[derive(Serialize)]
1246     struct Struct {
1247         date: Datetime,
1248     }
1249 
1250     let toml = to_string(&Struct {
1251         date: Datetime {
1252             date: Some(Date {
1253                 year: 2022,
1254                 month: 1,
1255                 day: 1,
1256             }),
1257             time: None,
1258             offset: None,
1259         },
1260     })
1261     .unwrap();
1262     assert_eq!(toml, "date = 2022-01-01\n");
1263 }
1264 
1265 #[test]
datetime_offset_issue_496()1266 fn datetime_offset_issue_496() {
1267     let original = "value = 1911-01-01T10:11:12-00:36\n";
1268     let toml = original.parse::<Table>().unwrap();
1269     let output = toml.to_string();
1270     assert_data_eq!(output, original.raw());
1271 }
1272 
1273 #[test]
serialize_date()1274 fn serialize_date() {
1275     use toml::value::Date;
1276 
1277     #[derive(Serialize)]
1278     struct Document {
1279         date: Date,
1280     }
1281 
1282     let input = Document {
1283         date: Date {
1284             year: 2024,
1285             month: 1,
1286             day: 1,
1287         },
1288     };
1289     let raw = toml::to_string(&input).unwrap();
1290     assert_data_eq!(
1291         raw,
1292         str![[r#"
1293 date = 2024-01-01
1294 
1295 "#]]
1296         .raw()
1297     );
1298 }
1299 
1300 #[test]
serialize_time()1301 fn serialize_time() {
1302     use toml::value::Time;
1303 
1304     #[derive(Serialize)]
1305     struct Document {
1306         date: Time,
1307     }
1308 
1309     let input = Document {
1310         date: Time {
1311             hour: 5,
1312             minute: 0,
1313             second: 0,
1314             nanosecond: 0,
1315         },
1316     };
1317     let raw = toml::to_string(&input).unwrap();
1318     assert_data_eq!(
1319         raw,
1320         str![[r#"
1321 date = 05:00:00
1322 
1323 "#]]
1324         .raw()
1325     );
1326 }
1327 
1328 #[test]
deserialize_date()1329 fn deserialize_date() {
1330     use toml::value::Date;
1331 
1332     #[derive(Debug, Deserialize)]
1333     struct Document {
1334         date: Date,
1335     }
1336 
1337     let document: Document = toml::from_str("date = 2024-01-01").unwrap();
1338     assert_eq!(
1339         document.date,
1340         Date {
1341             year: 2024,
1342             month: 1,
1343             day: 1
1344         }
1345     );
1346 
1347     let err = toml::from_str::<Document>("date = 2024-01-01T05:00:00").unwrap_err();
1348     assert_data_eq!(
1349         err.message(),
1350         str!["invalid type: local datetime, expected local date"]
1351     );
1352 }
1353 
1354 #[test]
deserialize_time()1355 fn deserialize_time() {
1356     use toml::value::Time;
1357 
1358     #[derive(Debug, Deserialize)]
1359     struct Document {
1360         time: Time,
1361     }
1362 
1363     let document: Document = toml::from_str("time = 05:00:00").unwrap();
1364     assert_eq!(
1365         document.time,
1366         Time {
1367             hour: 5,
1368             minute: 0,
1369             second: 0,
1370             nanosecond: 0,
1371         }
1372     );
1373 
1374     let err = toml::from_str::<Document>("time = 2024-01-01T05:00:00").unwrap_err();
1375     assert_data_eq!(
1376         err.message(),
1377         str!["invalid type: local datetime, expected local time"]
1378     );
1379 }
1380 
1381 #[test]
serialize_array_with_none_value()1382 fn serialize_array_with_none_value() {
1383     #[derive(Serialize)]
1384     struct Document {
1385         values: Vec<Option<usize>>,
1386     }
1387 
1388     let input = Document {
1389         values: vec![Some(1), Some(2), Some(3)],
1390     };
1391     let raw = toml::to_string(&input).unwrap();
1392     assert_data_eq!(
1393         raw,
1394         str![[r#"
1395 values = [1, 2, 3]
1396 
1397 "#]]
1398         .raw()
1399     );
1400 
1401     let input = Document {
1402         values: vec![Some(1), None, Some(3)],
1403     };
1404     let err = toml::to_string(&input).unwrap_err();
1405     assert_data_eq!(err.to_string(), str!["unsupported None value"].raw());
1406 }
1407 
1408 #[test]
serialize_array_with_optional_struct_field()1409 fn serialize_array_with_optional_struct_field() {
1410     #[derive(Debug, Deserialize, Serialize)]
1411     struct Document {
1412         values: Vec<OptionalField>,
1413     }
1414 
1415     #[derive(Debug, Deserialize, Serialize)]
1416     struct OptionalField {
1417         x: u8,
1418         y: Option<u8>,
1419     }
1420 
1421     let input = Document {
1422         values: vec![
1423             OptionalField { x: 0, y: Some(4) },
1424             OptionalField { x: 2, y: Some(5) },
1425             OptionalField { x: 3, y: Some(7) },
1426         ],
1427     };
1428     let raw = toml::to_string(&input).unwrap();
1429     assert_data_eq!(
1430         raw,
1431         str![[r#"
1432 [[values]]
1433 x = 0
1434 y = 4
1435 
1436 [[values]]
1437 x = 2
1438 y = 5
1439 
1440 [[values]]
1441 x = 3
1442 y = 7
1443 
1444 "#]]
1445         .raw()
1446     );
1447 
1448     let input = Document {
1449         values: vec![
1450             OptionalField { x: 0, y: Some(4) },
1451             OptionalField { x: 2, y: None },
1452             OptionalField { x: 3, y: Some(7) },
1453         ],
1454     };
1455     let raw = toml::to_string(&input).unwrap();
1456     assert_data_eq!(
1457         raw,
1458         str![[r#"
1459 [[values]]
1460 x = 0
1461 y = 4
1462 
1463 [[values]]
1464 x = 2
1465 
1466 [[values]]
1467 x = 3
1468 y = 7
1469 
1470 "#]]
1471         .raw()
1472     );
1473 }
1474 
1475 #[test]
serialize_array_with_enum_of_optional_struct_field()1476 fn serialize_array_with_enum_of_optional_struct_field() {
1477     #[derive(Debug, Deserialize, Serialize)]
1478     struct Document {
1479         values: Vec<Choice>,
1480     }
1481 
1482     #[derive(Debug, Deserialize, Serialize)]
1483     enum Choice {
1484         Optional(OptionalField),
1485         Empty,
1486     }
1487 
1488     #[derive(Debug, Deserialize, Serialize)]
1489     struct OptionalField {
1490         x: u8,
1491         y: Option<u8>,
1492     }
1493 
1494     let input = Document {
1495         values: vec![
1496             Choice::Optional(OptionalField { x: 0, y: Some(4) }),
1497             Choice::Empty,
1498             Choice::Optional(OptionalField { x: 2, y: Some(5) }),
1499             Choice::Optional(OptionalField { x: 3, y: Some(7) }),
1500         ],
1501     };
1502     let raw = toml::to_string(&input).unwrap();
1503     assert_data_eq!(raw, str![[r#"
1504 values = [{ Optional = { x = 0, y = 4 } }, "Empty", { Optional = { x = 2, y = 5 } }, { Optional = { x = 3, y = 7 } }]
1505 
1506 "#]].raw());
1507 
1508     let input = Document {
1509         values: vec![
1510             Choice::Optional(OptionalField { x: 0, y: Some(4) }),
1511             Choice::Empty,
1512             Choice::Optional(OptionalField { x: 2, y: None }),
1513             Choice::Optional(OptionalField { x: 3, y: Some(7) }),
1514         ],
1515     };
1516     let raw = toml::to_string(&input).unwrap();
1517     assert_data_eq!(raw, str![[r#"
1518 values = [{ Optional = { x = 0, y = 4 } }, "Empty", { Optional = { x = 2 } }, { Optional = { x = 3, y = 7 } }]
1519 
1520 "#]].raw());
1521 }
1522 
1523 #[test]
span_for_sequence_as_map()1524 fn span_for_sequence_as_map() {
1525     #[allow(dead_code)]
1526     #[derive(Deserialize)]
1527     struct Manifest {
1528         package: Package,
1529         bench: Vec<Bench>,
1530     }
1531 
1532     #[derive(Deserialize)]
1533     struct Package {}
1534 
1535     #[derive(Deserialize)]
1536     struct Bench {}
1537 
1538     let raw = r#"
1539 [package]
1540 name = "foo"
1541 version = "0.1.0"
1542 edition = "2021"
1543 [[bench.foo]]
1544 "#;
1545     let err = match toml::from_str::<Manifest>(raw) {
1546         Ok(_) => panic!("should fail"),
1547         Err(err) => err,
1548     };
1549     assert_eq!(err.span(), Some(61..66));
1550 }
1551