1 use serde::Deserialize;
2 
3 #[derive(Debug, Deserialize, PartialEq)]
4 struct OuterStruct {
5     inner: TheEnum,
6 }
7 
8 #[derive(Debug, Deserialize, PartialEq)]
9 enum TheEnum {
10     Plain,
11     Tuple(i64, bool),
12     NewType(String),
13     Struct { value: i64 },
14 }
15 
16 #[derive(Debug, Deserialize, PartialEq)]
17 struct Val {
18     val: TheEnum,
19 }
20 
21 #[derive(Debug, Deserialize, PartialEq)]
22 struct Multi {
23     enums: Vec<TheEnum>,
24 }
25 
value_from_str<T>(s: &'_ str) -> Result<T, toml::de::Error> where T: serde::de::DeserializeOwned,26 fn value_from_str<T>(s: &'_ str) -> Result<T, toml::de::Error>
27 where
28     T: serde::de::DeserializeOwned,
29 {
30     T::deserialize(toml::de::ValueDeserializer::new(s))
31 }
32 
33 #[test]
invalid_variant_returns_error_with_good_message_string()34 fn invalid_variant_returns_error_with_good_message_string() {
35     let error = value_from_str::<TheEnum>("\"NonExistent\"").unwrap_err();
36     snapbox::assert_eq(
37         r#"unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct`
38 "#,
39         error.to_string(),
40     );
41 
42     let error = toml::from_str::<Val>("val = \"NonExistent\"").unwrap_err();
43     snapbox::assert_eq(
44         r#"TOML parse error at line 1, column 7
45   |
46 1 | val = "NonExistent"
47   |       ^^^^^^^^^^^^^
48 unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct`
49 "#,
50         error.to_string(),
51     );
52 }
53 
54 #[test]
invalid_variant_returns_error_with_good_message_inline_table()55 fn invalid_variant_returns_error_with_good_message_inline_table() {
56     let error = value_from_str::<TheEnum>("{ NonExistent = {} }").unwrap_err();
57     snapbox::assert_eq(
58         r#"unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct`
59 "#,
60         error.to_string(),
61     );
62 
63     let error = toml::from_str::<Val>("val = { NonExistent = {} }").unwrap_err();
64     snapbox::assert_eq(
65         r#"TOML parse error at line 1, column 9
66   |
67 1 | val = { NonExistent = {} }
68   |         ^^^^^^^^^^^
69 unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct`
70 "#,
71         error.to_string(),
72     );
73 }
74 
75 #[test]
extra_field_returns_expected_empty_table_error()76 fn extra_field_returns_expected_empty_table_error() {
77     let error = value_from_str::<TheEnum>("{ Plain = { extra_field = 404 } }").unwrap_err();
78     snapbox::assert_eq(
79         r#"expected empty table
80 "#,
81         error.to_string(),
82     );
83 
84     let error = toml::from_str::<Val>("val = { Plain = { extra_field = 404 } }").unwrap_err();
85     snapbox::assert_eq(
86         r#"TOML parse error at line 1, column 17
87   |
88 1 | val = { Plain = { extra_field = 404 } }
89   |                 ^^^^^^^^^^^^^^^^^^^^^
90 expected empty table
91 "#,
92         error.to_string(),
93     );
94 }
95 
96 #[test]
extra_field_returns_expected_empty_table_error_struct_variant()97 fn extra_field_returns_expected_empty_table_error_struct_variant() {
98     let error = value_from_str::<TheEnum>("{ Struct = { value = 123, extra_0 = 0, extra_1 = 1 } }")
99         .unwrap_err();
100 
101     snapbox::assert_eq(
102         r#"unexpected keys in table: extra_0, extra_1, available keys: value
103 "#,
104         error.to_string(),
105     );
106 
107     let error =
108         toml::from_str::<Val>("val = { Struct = { value = 123, extra_0 = 0, extra_1 = 1 } }")
109             .unwrap_err();
110 
111     snapbox::assert_eq(
112         r#"TOML parse error at line 1, column 33
113   |
114 1 | val = { Struct = { value = 123, extra_0 = 0, extra_1 = 1 } }
115   |                                 ^^^^^^^
116 unexpected keys in table: extra_0, extra_1, available keys: value
117 "#,
118         error.to_string(),
119     );
120 }
121 
122 mod enum_unit {
123     use super::*;
124 
125     #[test]
from_str()126     fn from_str() {
127         assert_eq!(TheEnum::Plain, value_from_str("\"Plain\"").unwrap());
128 
129         assert_eq!(
130             Val {
131                 val: TheEnum::Plain
132             },
133             toml::from_str("val = \"Plain\"").unwrap()
134         );
135     }
136 
137     #[test]
from_inline_table()138     fn from_inline_table() {
139         assert_eq!(TheEnum::Plain, value_from_str("{ Plain = {} }").unwrap());
140         assert_eq!(
141             Val {
142                 val: TheEnum::Plain
143             },
144             toml::from_str("val = { Plain = {} }").unwrap()
145         );
146     }
147 
148     #[test]
from_std_table()149     fn from_std_table() {
150         assert_eq!(TheEnum::Plain, toml::from_str("[Plain]\n").unwrap());
151     }
152 }
153 
154 mod enum_tuple {
155     use super::*;
156 
157     #[test]
from_inline_table()158     fn from_inline_table() {
159         assert_eq!(
160             TheEnum::Tuple(-123, true),
161             value_from_str("{ Tuple = { 0 = -123, 1 = true } }").unwrap()
162         );
163         assert_eq!(
164             Val {
165                 val: TheEnum::Tuple(-123, true)
166             },
167             toml::from_str("val = { Tuple = { 0 = -123, 1 = true } }").unwrap()
168         );
169     }
170 
171     #[test]
from_std_table()172     fn from_std_table() {
173         assert_eq!(
174             TheEnum::Tuple(-123, true),
175             toml::from_str(
176                 r#"[Tuple]
177                 0 = -123
178                 1 = true
179                 "#
180             )
181             .unwrap()
182         );
183     }
184 }
185 
186 mod enum_newtype {
187     use super::*;
188 
189     #[test]
from_inline_table()190     fn from_inline_table() {
191         assert_eq!(
192             TheEnum::NewType("value".to_string()),
193             value_from_str(r#"{ NewType = "value" }"#).unwrap()
194         );
195         assert_eq!(
196             Val {
197                 val: TheEnum::NewType("value".to_string()),
198             },
199             toml::from_str(r#"val = { NewType = "value" }"#).unwrap()
200         );
201     }
202 
203     #[test]
from_std_table()204     fn from_std_table() {
205         assert_eq!(
206             TheEnum::NewType("value".to_string()),
207             toml::from_str(r#"NewType = "value""#).unwrap()
208         );
209         assert_eq!(
210             Val {
211                 val: TheEnum::NewType("value".to_string()),
212             },
213             toml::from_str(
214                 r#"[val]
215                 NewType = "value"
216                 "#
217             )
218             .unwrap()
219         );
220     }
221 }
222 
223 mod enum_struct {
224     use super::*;
225 
226     #[test]
from_inline_table()227     fn from_inline_table() {
228         assert_eq!(
229             TheEnum::Struct { value: -123 },
230             value_from_str("{ Struct = { value = -123 } }").unwrap()
231         );
232         assert_eq!(
233             Val {
234                 val: TheEnum::Struct { value: -123 }
235             },
236             toml::from_str("val = { Struct = { value = -123 } }").unwrap()
237         );
238     }
239 
240     #[test]
from_std_table()241     fn from_std_table() {
242         assert_eq!(
243             TheEnum::Struct { value: -123 },
244             toml::from_str(
245                 r#"[Struct]
246                 value = -123
247                 "#
248             )
249             .unwrap()
250         );
251     }
252 
253     #[test]
from_nested_std_table()254     fn from_nested_std_table() {
255         assert_eq!(
256             OuterStruct {
257                 inner: TheEnum::Struct { value: -123 }
258             },
259             toml::from_str(
260                 r#"[inner.Struct]
261                 value = -123
262                 "#
263             )
264             .unwrap()
265         );
266     }
267 }
268 
269 mod enum_array {
270     use super::*;
271 
272     #[test]
from_inline_tables()273     fn from_inline_tables() {
274         let toml_str = r#"
275             enums = [
276                 { Plain = {} },
277                 { Tuple = { 0 = -123, 1 = true } },
278                 { NewType = "value" },
279                 { Struct = { value = -123 } }
280             ]"#;
281         assert_eq!(
282             Multi {
283                 enums: vec![
284                     TheEnum::Plain,
285                     TheEnum::Tuple(-123, true),
286                     TheEnum::NewType("value".to_string()),
287                     TheEnum::Struct { value: -123 },
288                 ]
289             },
290             toml::from_str(toml_str).unwrap()
291         );
292     }
293 
294     #[test]
from_std_table()295     fn from_std_table() {
296         let toml_str = r#"[[enums]]
297             Plain = {}
298 
299             [[enums]]
300             Tuple = { 0 = -123, 1 = true }
301 
302             [[enums]]
303             NewType = "value"
304 
305             [[enums]]
306             Struct = { value = -123 }
307             "#;
308         assert_eq!(
309             Multi {
310                 enums: vec![
311                     TheEnum::Plain,
312                     TheEnum::Tuple(-123, true),
313                     TheEnum::NewType("value".to_string()),
314                     TheEnum::Struct { value: -123 },
315                 ]
316             },
317             toml::from_str(toml_str).unwrap()
318         );
319     }
320 }
321