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