1pub use serde::de::{Deserialize, IntoDeserializer};
2
3use crate::value::{Array, Table, Value};
4
5#[macro_export]
28macro_rules! toml {
29 ($($toml:tt)+) => {{
30 let table = $crate::value::Table::new();
31 let mut root = $crate::Value::Table(table);
32 $crate::toml_internal!(@toplevel root [] $($toml)+);
33 match root {
34 $crate::Value::Table(table) => table,
35 _ => unreachable!(),
36 }
37 }};
38}
39
40#[macro_export]
73#[doc(hidden)]
74macro_rules! toml_internal {
75 (@toplevel $root:ident [$($path:tt)*]) => {};
77
78 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = - $v:tt $($rest:tt)*) => {
80 $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = (-$v) $($rest)*);
81 };
82
83 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = + $v:tt $($rest:tt)*) => {
85 $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = ($v) $($rest)*);
86 };
87
88 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
90 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
91 };
92 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
94 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
95 };
96
97 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
99 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
100 };
101 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
103 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
104 };
105
106 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
108 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
109 };
110 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
112 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
113 };
114
115 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
117 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*);
118 };
119 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
121 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
122 };
123
124 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $($rest:tt)*) => {
126 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day) $($rest)*);
127 };
128
129 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
131 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*);
132 };
133
134 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
136 $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec) $($rest)*);
137 };
138
139 (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $v:tt $($rest:tt)*) => {{
142 $crate::macros::insert_toml(
143 &mut $root,
144 &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
145 $crate::toml_internal!(@value $v));
146 $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*);
147 }};
148
149 (@toplevel $root:ident $oldpath:tt [[$($($path:tt)-+).+]] $($rest:tt)*) => {
151 $crate::macros::push_toml(
152 &mut $root,
153 &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+]);
154 $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*);
155 };
156
157 (@toplevel $root:ident $oldpath:tt [$($($path:tt)-+).+] $($rest:tt)*) => {
159 $crate::macros::insert_toml(
160 &mut $root,
161 &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+],
162 $crate::Value::Table($crate::value::Table::new()));
163 $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*);
164 };
165
166 (@topleveldatetime $root:ident [$($path:tt)*] $($($k:tt)-+).+ = ($($datetime:tt)+) $($rest:tt)*) => {
168 $crate::macros::insert_toml(
169 &mut $root,
170 &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
171 $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
172 $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*);
173 };
174
175 (@path $ident:ident) => {
177 stringify!($ident)
178 };
179
180 (@path $quoted:tt) => {
183 $quoted
184 };
185
186 (@value { $($inline:tt)* }) => {{
188 let mut table = $crate::Value::Table($crate::value::Table::new());
189 $crate::toml_internal!(@trailingcomma (@table table) $($inline)*);
190 table
191 }};
192
193 (@value [ $($inline:tt)* ]) => {{
195 let mut array = $crate::value::Array::new();
196 $crate::toml_internal!(@trailingcomma (@array array) $($inline)*);
197 $crate::Value::Array(array)
198 }};
199
200 (@value (-nan)) => {
201 $crate::Value::Float(-::std::f64::NAN)
202 };
203
204 (@value (nan)) => {
205 $crate::Value::Float(::std::f64::NAN)
206 };
207
208 (@value nan) => {
209 $crate::Value::Float(::std::f64::NAN)
210 };
211
212 (@value (-inf)) => {
213 $crate::Value::Float(::std::f64::NEG_INFINITY)
214 };
215
216 (@value (inf)) => {
217 $crate::Value::Float(::std::f64::INFINITY)
218 };
219
220 (@value inf) => {
221 $crate::Value::Float(::std::f64::INFINITY)
222 };
223
224 (@value $v:tt) => {{
226 let de = $crate::macros::IntoDeserializer::<$crate::de::Error>::into_deserializer($v);
228 <$crate::Value as $crate::macros::Deserialize>::deserialize(de).unwrap()
229 }};
230
231 (@table $root:ident) => {};
233
234 (@table $root:ident $($($k:tt)-+).+ = - $v:tt , $($rest:tt)*) => {
236 $crate::toml_internal!(@table $root $($($k)-+).+ = (-$v) , $($rest)*);
237 };
238
239 (@table $root:ident $($($k:tt)-+).+ = + $v:tt , $($rest:tt)*) => {
241 $crate::toml_internal!(@table $root $($($k)-+).+ = ($v) , $($rest)*);
242 };
243
244 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
246 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
247 };
248 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
250 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
251 };
252
253 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
255 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
256 };
257 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
259 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
260 };
261
262 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
264 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
265 };
266 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
268 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
269 };
270
271 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
273 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*);
274 };
275 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
277 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
278 };
279
280 (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => {
282 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day) $($rest)*);
283 };
284
285 (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
287 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*);
288 };
289
290 (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
292 $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec) $($rest)*);
293 };
294
295 (@table $root:ident $($($k:tt)-+).+ = $v:tt , $($rest:tt)*) => {
297 $crate::macros::insert_toml(
298 &mut $root,
299 &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
300 $crate::toml_internal!(@value $v));
301 $crate::toml_internal!(@table $root $($rest)*);
302 };
303
304 (@tabledatetime $root:ident $($($k:tt)-+).+ = ($($datetime:tt)*) $($rest:tt)*) => {
306 $crate::macros::insert_toml(
307 &mut $root,
308 &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
309 $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
310 $crate::toml_internal!(@table $root $($rest)*);
311 };
312
313 (@array $root:ident) => {};
315
316 (@array $root:ident - $v:tt , $($rest:tt)*) => {
318 $crate::toml_internal!(@array $root (-$v) , $($rest)*);
319 };
320
321 (@array $root:ident + $v:tt , $($rest:tt)*) => {
323 $crate::toml_internal!(@array $root ($v) , $($rest)*);
324 };
325
326 (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
328 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
329 };
330 (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
332 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
333 };
334
335 (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
337 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
338 };
339 (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
341 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
342 };
343
344 (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
346 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
347 };
348 (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
350 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
351 };
352
353 (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
355 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec) $($rest)*);
356 };
357 (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
359 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
360 };
361
362 (@array $root:ident $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => {
364 $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day) $($rest)*);
365 };
366
367 (@array $root:ident $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
369 $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec . $frac) $($rest)*);
370 };
371
372 (@array $root:ident $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
374 $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec) $($rest)*);
375 };
376
377 (@array $root:ident $v:tt , $($rest:tt)*) => {
379 $root.push($crate::toml_internal!(@value $v));
380 $crate::toml_internal!(@array $root $($rest)*);
381 };
382
383 (@arraydatetime $root:ident ($($datetime:tt)*) $($rest:tt)*) => {
385 $root.push($crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
386 $crate::toml_internal!(@array $root $($rest)*);
387 };
388
389 (@trailingcomma ($($args:tt)*)) => {
391 $crate::toml_internal!($($args)*);
392 };
393
394 (@trailingcomma ($($args:tt)*) ,) => {
396 $crate::toml_internal!($($args)* ,);
397 };
398
399 (@trailingcomma ($($args:tt)*) $last:tt) => {
401 $crate::toml_internal!($($args)* $last ,);
402 };
403
404 (@trailingcomma ($($args:tt)*) $first:tt $($rest:tt)+) => {
406 $crate::toml_internal!(@trailingcomma ($($args)* $first) $($rest)+);
407 };
408}
409
410pub fn insert_toml(root: &mut Value, path: &[&str], value: Value) {
413 *traverse(root, path) = value;
414}
415
416pub fn push_toml(root: &mut Value, path: &[&str]) {
419 let target = traverse(root, path);
420 if !target.is_array() {
421 *target = Value::Array(Array::new());
422 }
423 target
424 .as_array_mut()
425 .unwrap()
426 .push(Value::Table(Table::new()));
427}
428
429fn traverse<'a>(root: &'a mut Value, path: &[&str]) -> &'a mut Value {
430 let mut cur = root;
431 for &key in path {
432 let cur1 = cur;
434
435 let cur2 = if cur1.is_array() {
440 cur1.as_array_mut().unwrap().last_mut().unwrap()
441 } else {
442 cur1
443 };
444
445 if !cur2.is_table() {
447 *cur2 = Value::Table(Table::new());
448 }
449
450 if !cur2.as_table().unwrap().contains_key(key) {
451 let empty = Value::Table(Table::new());
453 cur2.as_table_mut().unwrap().insert(key.to_owned(), empty);
454 }
455
456 cur = cur2.as_table_mut().unwrap().get_mut(key).unwrap();
458 }
459 cur
460}