1#[doc(hidden)]
222pub use toml_example_derive::TomlExample;
223pub mod traits;
224pub use traits::*;
225
226#[cfg(test)]
227mod tests {
228 use crate as toml_example;
229 use serde_derive::Deserialize;
230 use std::collections::HashMap;
231 use toml_example::TomlExample;
232
233 #[test]
234 fn basic() {
235 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
236 #[allow(dead_code)]
237 struct Config {
238 a: usize,
240 b: String,
242 }
243 assert_eq!(
244 Config::toml_example(),
245 r#"# Config.a should be a number
246a = 0
247
248# Config.b should be a string
249b = ""
250
251"#
252 );
253 assert_eq!(
254 toml::from_str::<Config>(&Config::toml_example()).unwrap(),
255 Config::default()
256 );
257 let mut tmp_file = std::env::temp_dir();
258 tmp_file.push("config.toml");
259 Config::to_toml_example(&tmp_file.as_path().to_str().unwrap()).unwrap();
260 assert_eq!(
261 std::fs::read_to_string(tmp_file).unwrap(),
262 r#"# Config.a should be a number
263a = 0
264
265# Config.b should be a string
266b = ""
267
268"#
269 );
270 }
271
272 #[test]
273 fn hinden_doc() {
274 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
275 #[allow(dead_code)]
276 struct Config {
277 a: usize,
280
281 b: String,
284 }
285 assert_eq!(
286 Config::toml_example(),
287 r#"# Config.a should be a number
288a = 0
289
290# Config.b should be a string
291b = ""
292
293"#
294 );
295 }
296
297 #[test]
298 fn option() {
299 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
300 #[allow(dead_code)]
301 struct Config {
302 a: Option<usize>,
304 b: Option<String>,
306 }
307 assert_eq!(
308 Config::toml_example(),
309 r#"# Config.a is an optional number
310# a = 0
311
312# Config.b is an optional string
313# b = ""
314
315"#
316 );
317 assert_eq!(
318 toml::from_str::<Config>(&Config::toml_example()).unwrap(),
319 Config::default()
320 )
321 }
322
323 #[test]
324 fn vec() {
325 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
326 #[allow(dead_code)]
327 struct Config {
328 a: Vec<usize>,
330 b: Vec<String>,
332 c: Vec<Option<usize>>,
334 d: Option<Vec<usize>>,
336 }
337 assert_eq!(
338 Config::toml_example(),
339 r#"# Config.a is a list of number
340a = [ 0, ]
341
342# Config.b is a list of string
343b = [ "", ]
344
345# Config.c
346c = [ 0, ]
347
348# Config.d
349# d = [ 0, ]
350
351"#
352 );
353 assert!(toml::from_str::<Config>(&Config::toml_example()).is_ok())
354 }
355
356 #[test]
357 fn hashset_btreeset() {
358 use std::collections::{BTreeSet, HashSet};
359
360 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
361 #[allow(dead_code)]
362 struct Config {
363 a: HashSet<String>,
365 b: BTreeSet<usize>,
367 c: Option<HashSet<String>>,
369 }
370 assert_eq!(
371 Config::toml_example(),
372 r#"# Config.a is a set of string
373a = [ "", ]
374
375# Config.b is a set of number
376b = [ 0, ]
377
378# Config.c is optional
379# c = [ "", ]
380
381"#
382 );
383 assert!(toml::from_str::<Config>(&Config::toml_example()).is_ok())
384 }
385
386 #[test]
387 fn struct_doc() {
388 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
391 #[allow(dead_code)]
392 struct Config {
393 a: usize,
396 }
397 assert_eq!(
398 Config::toml_example(),
399 r#"# Config is to arrange something or change the controls on a computer or other device
400# so that it can be used in a particular way
401# Config.a should be a number
402# the number should be greater or equal zero
403a = 0
404
405"#
406 );
407 assert_eq!(
408 toml::from_str::<Config>(&Config::toml_example()).unwrap(),
409 Config::default()
410 )
411 }
412
413 #[test]
414 fn serde_default() {
415 fn default_a() -> usize {
416 7
417 }
418 fn default_b() -> String {
419 "default".into()
420 }
421 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
422 #[allow(dead_code)]
423 struct Config {
424 #[serde(default = "default_a")]
426 a: usize,
427 #[serde(default = "default_b")]
429 b: String,
430 #[serde(default)]
432 c: usize,
433 #[serde(default)]
435 d: String,
436 #[serde(default)]
437 e: Option<usize>,
438 }
439 assert_eq!(
440 Config::toml_example(),
441 r#"# Config.a should be a number
442a = 7
443
444# Config.b should be a string
445b = "default"
446
447# Config.c should be a number
448c = 0
449
450# Config.d should be a string
451d = ""
452
453# e = 0
454
455"#
456 );
457 }
458
459 #[test]
460 fn toml_example_default() {
461 fn default_str() -> String {
462 "seven".into()
463 }
464 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
465 #[allow(dead_code)]
466 struct Config {
467 #[toml_example(default = 7)]
469 a: usize,
470 #[toml_example(default = "default")]
472 #[serde(default = "default_str")]
473 b: String,
474 #[serde(default = "default_str")]
475 #[toml_example(default = "default")]
476 c: String,
477 #[toml_example(default = [ "default", ])]
478 e: Vec<String>,
479 #[toml_example(
480 default = "super looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string"
481 )]
482 f: String,
483 #[toml_example(default = [ "super looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string",
484 "second",
485 "third",
486 ])]
487 g: Vec<String>,
488 #[toml_example(default = "#FAFAFA")]
490 color: String,
491 }
492 assert_eq!(
493 Config::toml_example(),
494 r##"# Config.a should be a number
495a = 7
496
497# Config.b should be a string
498b = "seven"
499
500c = "default"
501
502e = ["default",]
503
504f = "super looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string"
505
506g = ["super looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string",
507"second", "third",]
508
509# Config.color should be a hex color code
510color = "#FAFAFA"
511
512"##
513 );
514 }
515
516 #[test]
517 fn struct_serde_default() {
518 #[derive(TomlExample, Deserialize, PartialEq)]
519 #[serde(default)]
520 struct Foo {
521 bar: String,
522 #[serde(default)]
523 x: usize,
524 }
525 impl Default for Foo {
526 fn default() -> Self {
527 Foo {
528 bar: String::from("hello world"),
529 x: 12,
530 }
531 }
532 }
533 assert_eq!(
534 Foo::toml_example(),
535 r##"bar = "hello world"
536
537x = 0
538
539"##
540 );
541 }
542
543 #[test]
544 fn struct_serde_default_fn() {
545 #[derive(TomlExample, Deserialize, PartialEq)]
546 #[serde(default = "default")]
547 struct Foo {
548 bar: String,
549 #[toml_example(default = "field override")]
550 baz: String,
551 }
552 fn default() -> Foo {
553 Foo {
554 bar: String::from("hello world"),
555 baz: String::from("custom default"),
556 }
557 }
558 assert_eq!(
559 Foo::toml_example(),
560 r##"bar = "hello world"
561
562baz = "field override"
563
564"##
565 );
566 }
567
568 #[test]
569 fn struct_toml_example_default() {
570 #[derive(TomlExample, Deserialize, PartialEq)]
571 #[toml_example(default)]
572 struct Foo {
573 #[serde(default = "paru")]
574 yay: &'static str,
575 aur_is_useful: bool,
576 }
577 impl Default for Foo {
578 fn default() -> Self {
579 Foo {
580 yay: "yay!",
581 aur_is_useful: true,
582 }
583 }
584 }
585 fn paru() -> &'static str {
586 "no, paru!"
587 }
588 assert_eq!(
589 Foo::toml_example(),
590 r##"yay = "no, paru!"
591
592aur_is_useful = true
593
594"##
595 );
596 }
597
598 #[test]
599 fn no_nesting() {
600 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
602 #[allow(dead_code)]
603 struct Inner {
604 a: usize,
606 }
607 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
608 #[allow(dead_code)]
609 struct Outer {
610 inner: Inner,
612 }
613 assert_eq!(
614 Outer::toml_example(),
615 r#"# Outer.inner is a complex struct
616inner = ""
617
618"#
619 );
620 }
621
622 #[test]
623 fn nesting() {
624 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
626 #[allow(dead_code)]
627 struct Inner {
628 a: usize,
630 }
631 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
632 #[allow(dead_code)]
633 struct Outer {
634 #[toml_example(nesting)]
636 inner: Inner,
637 }
638 assert_eq!(
639 Outer::toml_example(),
640 r#"# Outer.inner is a complex struct
641# Inner is a config live in Outer
642[inner]
643# Inner.a should be a number
644a = 0
645
646"#
647 );
648 assert_eq!(
649 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
650 Outer::default()
651 );
652 }
653
654 #[test]
655 fn nesting_by_section() {
656 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
658 #[allow(dead_code)]
659 struct Inner {
660 a: usize,
662 }
663 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
664 #[allow(dead_code)]
665 struct Outer {
666 #[toml_example(nesting = section)]
668 inner: Inner,
669 }
670 assert_eq!(
671 Outer::toml_example(),
672 r#"# Outer.inner is a complex struct
673# Inner is a config live in Outer
674[inner]
675# Inner.a should be a number
676a = 0
677
678"#
679 );
680 assert_eq!(
681 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
682 Outer::default()
683 );
684 }
685
686 #[test]
687 fn nesting_by_prefix() {
688 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
690 #[allow(dead_code)]
691 struct Inner {
692 a: usize,
694 }
695 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
696 #[allow(dead_code)]
697 struct Outer {
698 #[toml_example(nesting = prefix)]
700 inner: Inner,
701 }
702 assert_eq!(
703 Outer::toml_example(),
704 r#"# Outer.inner is a complex struct
705# Inner is a config live in Outer
706# Inner.a should be a number
707inner.a = 0
708
709"#
710 );
711 assert_eq!(
712 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
713 Outer::default()
714 );
715 }
716
717 #[test]
718 fn nesting_vector() {
719 #[derive(TomlExample, Deserialize)]
721 #[allow(dead_code)]
722 struct Service {
723 port: usize,
725 }
726 #[derive(TomlExample, Deserialize)]
727 #[allow(dead_code)]
728 struct Node {
729 #[toml_example(nesting)]
731 services: Vec<Service>,
732 }
733 assert_eq!(
734 Node::toml_example(),
735 r#"# Services are running in the node
736# Service with specific port
737[[services]]
738# port should be a number
739port = 0
740
741"#
742 );
743 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
744 }
745
746 #[test]
747 fn nesting_hashmap() {
748 #[derive(TomlExample, Deserialize)]
750 #[allow(dead_code)]
751 struct Service {
752 port: usize,
754 }
755 #[derive(TomlExample, Deserialize)]
756 #[allow(dead_code)]
757 struct Node {
758 #[toml_example(nesting)]
760 services: HashMap<String, Service>,
761 }
762 assert_eq!(
763 Node::toml_example(),
764 r#"# Services are running in the node
765# Service with specific port
766[services.example]
767# port should be a number
768port = 0
769
770"#
771 );
772 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
773 }
774
775 #[test]
776 fn optional_nesting() {
777 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
779 #[allow(dead_code)]
780 struct Inner {
781 a: usize,
783 }
784 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
785 #[allow(dead_code)]
786 struct Outer {
787 #[toml_example(nesting)]
789 inner: Option<Inner>,
790 }
791 assert_eq!(
792 Outer::toml_example(),
793 r#"# Outer.inner is a complex struct
794# Inner is a config live in Outer
795# [inner]
796# Inner.a should be a number
797# a = 0
798
799"#
800 );
801 assert_eq!(
802 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
803 Outer::default()
804 );
805 }
806
807 #[test]
808 fn optional_nesting_by_section() {
809 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
811 #[allow(dead_code)]
812 struct Inner {
813 a: usize,
815 }
816 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
817 #[allow(dead_code)]
818 struct Outer {
819 #[toml_example(nesting = section)]
821 inner: Option<Inner>,
822 }
823 assert_eq!(
824 Outer::toml_example(),
825 r#"# Outer.inner is a complex struct
826# Inner is a config live in Outer
827# [inner]
828# Inner.a should be a number
829# a = 0
830
831"#
832 );
833 assert_eq!(
834 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
835 Outer::default()
836 );
837 }
838
839 #[test]
840 fn optional_nesting_by_prefix() {
841 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
843 #[allow(dead_code)]
844 struct Inner {
845 a: usize,
847 }
848 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
849 #[allow(dead_code)]
850 struct Outer {
851 #[toml_example(nesting = prefix)]
853 inner: Option<Inner>,
854 }
855 assert_eq!(
856 Outer::toml_example(),
857 r#"# Outer.inner is a complex struct
858# Inner is a config live in Outer
859# Inner.a should be a number
860# inner.a = 0
861
862"#
863 );
864 assert_eq!(
865 toml::from_str::<Outer>(&Outer::toml_example()).unwrap(),
866 Outer::default()
867 );
868 }
869
870 #[test]
871 fn optional_nesting_vector() {
872 #[derive(TomlExample, Deserialize)]
874 #[allow(dead_code)]
875 struct Service {
876 port: usize,
878 }
879 #[derive(TomlExample, Deserialize)]
880 #[allow(dead_code)]
881 struct Node {
882 #[toml_example(nesting)]
884 services: Option<Vec<Service>>,
885 }
886 assert_eq!(
887 Node::toml_example(),
888 r#"# Services are running in the node
889# Service with specific port
890# [[services]]
891# port should be a number
892# port = 0
893
894"#
895 );
896 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
897 }
898
899 #[test]
900 fn optional_nesting_hashmap() {
901 #[derive(TomlExample, Deserialize)]
903 #[allow(dead_code)]
904 struct Service {
905 port: usize,
907 }
908 #[derive(TomlExample, Deserialize)]
909 #[allow(dead_code)]
910 struct Node {
911 #[toml_example(nesting)]
913 services: Option<HashMap<String, Service>>,
914 }
915 assert_eq!(
916 Node::toml_example(),
917 r#"# Services are running in the node
918# Service with specific port
919# [services.example]
920# port should be a number
921# port = 0
922
923"#
924 );
925 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
926 }
927
928 #[test]
929 fn nesting_hashmap_with_default_name() {
930 #[derive(TomlExample, Deserialize)]
932 #[allow(dead_code)]
933 struct Service {
934 #[toml_example(default = 80)]
936 port: usize,
937 }
938 #[derive(TomlExample, Deserialize)]
939 #[allow(dead_code)]
940 struct Node {
941 #[toml_example(nesting)]
943 #[toml_example(default = http)]
944 services: HashMap<String, Service>,
945 }
946 assert_eq!(
947 Node::toml_example(),
948 r#"# Services are running in the node
949# Service with specific port
950[services.http]
951# port should be a number
952port = 80
953
954"#
955 );
956 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
957 }
958
959 #[test]
960 fn nesting_hashmap_with_dash_name() {
961 #[derive(TomlExample, Deserialize)]
963 #[allow(dead_code)]
964 struct Service {
965 #[toml_example(default = 80)]
967 port: usize,
968 }
969 #[derive(TomlExample, Deserialize)]
970 #[allow(dead_code)]
971 struct Node {
972 #[toml_example(nesting)]
974 #[toml_example(default = http.01)]
975 services: HashMap<String, Service>,
976 }
977 assert_eq!(
978 Node::toml_example(),
979 r#"# Services are running in the node
980# Service with specific port
981[services.http-01]
982# port should be a number
983port = 80
984
985"#
986 );
987 assert!(toml::from_str::<Node>(&Node::toml_example()).is_ok());
988 }
989
990 #[test]
991 fn recursive_nesting() {
992 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
993 struct Outer {
994 #[toml_example(nesting)]
995 _middle: Middle,
996 }
997 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
998 struct Middle {
999 #[toml_example(nesting)]
1000 _inner: Inner,
1001 }
1002 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
1003 struct Inner {
1004 _value: usize,
1005 }
1006 let example = Outer::toml_example();
1007 assert_eq!(toml::from_str::<Outer>(&example).unwrap(), Outer::default());
1008 assert_eq!(
1009 example,
1010 r#"[_middle]
1011[_middle._inner]
1012_value = 0
1013
1014"#
1015 );
1016 }
1017
1018 #[test]
1019 fn recursive_nesting_and_flatten() {
1020 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
1021 struct Outer {
1022 #[toml_example(nesting)]
1023 middle: Middle,
1024 #[toml_example(default = false)]
1025 flag: bool,
1027 }
1028 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
1029 struct Middle {
1030 #[serde(flatten)]
1031 #[toml_example(nesting)]
1032 inner: Inner,
1034 }
1035 #[derive(TomlExample, Default, Debug, Deserialize, PartialEq)]
1036 struct Inner {
1037 #[toml_example(nesting)]
1038 extra: Extra,
1040 value: usize,
1042 }
1043 #[derive(TomlExample, Debug, Deserialize, PartialEq)]
1044 #[toml_example(default)]
1045 struct Extra {
1046 name: String,
1047 }
1048 impl Default for Extra {
1049 fn default() -> Self {
1050 Self {
1051 name: String::from("ferris"),
1052 }
1053 }
1054 }
1055 let example = Outer::toml_example();
1056 assert_eq!(toml::from_str::<Outer>(&example).unwrap(), Outer::default());
1057 assert_eq!(
1058 example,
1059 r#"# Some toggle
1060flag = false
1061
1062[middle]
1063# Values of [Inner] are flattened into [Middle]
1064# `value` is defined below `extra`, but shown above
1065value = 0
1066
1067# [Extra] is flattened into [Middle]
1068[middle.extra]
1069name = "ferris"
1070
1071"#
1072 );
1073 }
1074
1075 #[test]
1076 fn require() {
1077 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
1078 #[allow(dead_code)]
1079 struct Config {
1080 #[toml_example(require)]
1082 a: Option<usize>,
1083 #[toml_example(require)]
1085 b: Option<String>,
1086 #[toml_example(require)]
1087 #[toml_example(default = "third")]
1088 c: Option<String>,
1089 }
1090 assert_eq!(
1091 Config::toml_example(),
1092 r#"# Config.a is an optional number
1093a = 0
1094
1095# Config.b is an optional string
1096b = ""
1097
1098c = "third"
1099
1100"#
1101 );
1102 }
1103
1104 #[test]
1105 fn skip() {
1106 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
1107 #[allow(dead_code)]
1108 struct Config {
1109 a: usize,
1111 #[toml_example(skip)]
1112 b: usize,
1113 #[serde(skip)]
1114 c: usize,
1115 #[serde(skip_deserializing)]
1116 d: usize,
1117 }
1118 assert_eq!(
1119 Config::toml_example(),
1120 r#"# Config.a is a number
1121a = 0
1122
1123"#
1124 );
1125 }
1126
1127 #[test]
1128 fn is_enum() {
1129 fn b() -> AB {
1130 AB::B
1131 }
1132 #[derive(TomlExample, Deserialize, Default, PartialEq, Debug)]
1133 #[allow(dead_code)]
1134 struct Config {
1135 #[toml_example(enum, default)]
1137 ab: AB,
1138 #[toml_example(is_enum)]
1140 #[serde(default)]
1141 ab2: AB,
1142 #[toml_example(is_enum)]
1144 #[serde(default = "b")]
1145 ab3: AB,
1146 }
1147 #[derive(Debug, Default, Deserialize, PartialEq)]
1148 enum AB {
1149 #[default]
1150 A,
1151 B,
1152 }
1153 assert_eq!(
1154 Config::toml_example(),
1155 r#"# Config.ab is an enum
1156ab = "A"
1157
1158# Config.ab2 is an enum too
1159ab2 = "A"
1160
1161# Config.ab3 is an enum as well
1162ab3 = "B"
1163
1164"#
1165 );
1166 }
1167
1168 #[test]
1169 fn flatten() {
1170 #[derive(TomlExample)]
1171 struct ItemWrapper {
1172 #[toml_example(flatten, nesting)]
1173 _item: Item,
1174 }
1175 #[derive(TomlExample)]
1176 struct Item {
1177 _value: String,
1178 }
1179 assert_eq!(ItemWrapper::toml_example(), Item::toml_example());
1180 }
1181
1182 #[test]
1183 fn flatten_order() {
1184 #[derive(TomlExample)]
1185 struct Outer {
1186 #[toml_example(nesting)]
1187 _nested: Item,
1188 #[toml_example(flatten, nesting)]
1189 _flattened: Item,
1190 }
1191 #[derive(TomlExample)]
1192 struct Item {
1193 _value: String,
1194 }
1195 assert_eq!(
1196 Outer::toml_example(),
1197 r#"_value = ""
1198
1199[_nested]
1200_value = ""
1201
1202"#
1203 );
1204 }
1205
1206 #[test]
1207 fn multi_attr_escaping() {
1208 #[derive(TomlExample, Deserialize, PartialEq)]
1209 struct ConfigWrapper {
1210 #[toml_example(default = ["hello", "{nice :)\""], require)]
1211 vec: Option<Vec<String>>,
1212
1213 #[toml_example(require, default = ["\"\\\n}])", "super (fancy\\! :-) )"])]
1214 list: Option<[String; 2]>,
1215 }
1216
1217 assert_eq!(
1218 ConfigWrapper::toml_example(),
1219 r#"vec = ["hello", "{nice :)\""]
1220
1221list = ["\"\\\n}])", "super (fancy\\! :-) )"]
1222
1223"#
1224 );
1225 }
1226
1227 #[test]
1228 fn r_sharp_field() {
1229 #[derive(TomlExample)]
1230 #[allow(dead_code)]
1231 struct Config {
1232 r#type: usize,
1234 }
1235 assert_eq!(
1236 Config::toml_example(),
1237 r#"# Config.type is a number
1238type = 0
1239
1240"#
1241 );
1242 }
1243
1244 #[test]
1245 fn non_nesting_field_should_be_first() {
1246 #[derive(TomlExample)]
1247 #[allow(dead_code)]
1248 struct Foo {
1249 a: String,
1250 }
1251
1252 #[derive(TomlExample)]
1253 #[allow(dead_code)]
1254 struct Bar {
1255 #[toml_example(nesting)]
1256 foo: Foo,
1257 b: String,
1258 }
1259
1260 assert_eq!(
1261 Bar::toml_example(),
1262 r#"b = ""
1263
1264[foo]
1265a = ""
1266
1267"#
1268 );
1269 }
1270
1271 #[test]
1272 fn rename() {
1273 use serde::Serialize;
1274
1275 #[derive(Deserialize, Serialize, TomlExample)]
1276 struct Config {
1277 #[serde(rename = "bb")]
1278 b: usize,
1279 }
1280 assert_eq!(
1281 Config::toml_example(),
1282 r#"bb = 0
1283
1284"#
1285 );
1286 }
1287
1288 #[test]
1289 fn rename_all() {
1290 use serde::Serialize;
1291
1292 #[derive(Deserialize, Serialize, TomlExample)]
1293 #[serde(rename_all = "kebab-case")]
1294 struct Config {
1295 a_a: usize,
1296 }
1297 assert_eq!(
1298 Config::toml_example(),
1299 r#"a-a = 0
1300
1301"#
1302 );
1303 }
1304
1305 #[test]
1306 fn hashset_and_struct() {
1307 use std::collections::HashMap;
1308
1309 #[derive(TomlExample)]
1310 #[allow(dead_code)]
1311 struct Foo {
1312 a: String,
1313 }
1314
1315 #[derive(TomlExample)]
1316 #[allow(dead_code)]
1317 struct Bar {
1318 #[toml_example(nesting)]
1320 default: Foo,
1321
1322 #[toml_example(nesting)]
1324 instance: HashMap<String, Foo>,
1325 }
1326
1327 assert_eq!(
1328 Bar::toml_example(),
1329 r#"# Default instances doc
1330[default]
1331a = ""
1332
1333# Instances doc
1334[instance.example]
1335a = ""
1336
1337"#
1338 );
1339 }
1340
1341 #[test]
1342 fn optional_long_vector_field() {
1343 #[derive(TomlExample)]
1344 #[allow(dead_code)]
1345 struct Foo {
1346 #[toml_example(default = ["a", "b", "c"])]
1348 array_value_example: Option<Vec<String>>,
1349
1350 #[toml_example(default = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1352 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1353 "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
1354 "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
1355 ])]
1356 array_long_value_example: Option<Vec<String>>,
1357
1358 #[toml_example(default = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"])]
1360 array_long_value_no_space_example: Option<Vec<String>>,
1361 }
1362 assert_eq!(
1363 Foo::toml_example(),
1364 r#"# Option<Vec<String>>, with small default values
1365# array_value_example = ["a", "b", "c"]
1366
1367# Option<Vec<String>>, with long default values
1368# array_long_value_example = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1369# "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1370# "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
1371# "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"]
1372
1373# Option<Vec<String>>, with a long default value but no space after comma
1374# array_long_value_no_space_example = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"]
1375
1376"#
1377 );
1378 }
1379}