1pub use serde::de::{Deserialize, IntoDeserializer};
2
3use crate::value::{Array, Table, Value};
4
5#[macro_export]
23macro_rules! toml {
24    ($($toml:tt)+) => {{
25        let table = $crate::value::Table::new();
26        let mut root = $crate::Value::Table(table);
27        $crate::toml_internal!(@toplevel root [] $($toml)+);
28        match root {
29            $crate::Value::Table(table) => table,
30            _ => unreachable!(),
31        }
32    }};
33}
34
35#[macro_export]
68#[doc(hidden)]
69macro_rules! toml_internal {
70    (@toplevel $root:ident [$($path:tt)*]) => {};
72
73    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = - $v:tt $($rest:tt)*) => {
75        $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = (-$v) $($rest)*);
76    };
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)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
85        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
86    };
87    (@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)*) => {
89        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
90    };
91
92    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => {
94        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
95    };
96    (@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)*) => {
98        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
99    };
100
101    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
103        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
104    };
105    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
107        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
108    };
109
110    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
112        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*);
113    };
114    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
116        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
117    };
118
119    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $($rest:tt)*) => {
121        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day) $($rest)*);
122    };
123
124    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => {
126        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*);
127    };
128
129    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => {
131        $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec) $($rest)*);
132    };
133
134    (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $v:tt $($rest:tt)*) => {{
137        $crate::macros::insert_toml(
138            &mut $root,
139            &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
140            $crate::toml_internal!(@value $v));
141        $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*);
142    }};
143
144    (@toplevel $root:ident $oldpath:tt [[$($($path:tt)-+).+]] $($rest:tt)*) => {
146        $crate::macros::push_toml(
147            &mut $root,
148            &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+]);
149        $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*);
150    };
151
152    (@toplevel $root:ident $oldpath:tt [$($($path:tt)-+).+] $($rest:tt)*) => {
154        $crate::macros::insert_toml(
155            &mut $root,
156            &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+],
157            $crate::Value::Table($crate::value::Table::new()));
158        $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*);
159    };
160
161    (@topleveldatetime $root:ident [$($path:tt)*] $($($k:tt)-+).+ = ($($datetime:tt)+) $($rest:tt)*) => {
163        $crate::macros::insert_toml(
164            &mut $root,
165            &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
166            $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
167        $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*);
168    };
169
170    (@path $ident:ident) => {
172        stringify!($ident)
173    };
174
175    (@path $quoted:tt) => {
178        $quoted
179    };
180
181    (@value { $($inline:tt)* }) => {{
183        let mut table = $crate::Value::Table($crate::value::Table::new());
184        $crate::toml_internal!(@trailingcomma (@table table) $($inline)*);
185        table
186    }};
187
188    (@value [ $($inline:tt)* ]) => {{
190        let mut array = $crate::value::Array::new();
191        $crate::toml_internal!(@trailingcomma (@array array) $($inline)*);
192        $crate::Value::Array(array)
193    }};
194
195    (@value (-nan)) => {
196        $crate::Value::Float(::std::f64::NAN.copysign(-1.0))
197    };
198
199    (@value (nan)) => {
200        $crate::Value::Float(::std::f64::NAN.copysign(1.0))
201    };
202
203    (@value nan) => {
204        $crate::Value::Float(::std::f64::NAN.copysign(1.0))
205    };
206
207    (@value (-inf)) => {
208        $crate::Value::Float(::std::f64::NEG_INFINITY)
209    };
210
211    (@value (inf)) => {
212        $crate::Value::Float(::std::f64::INFINITY)
213    };
214
215    (@value inf) => {
216        $crate::Value::Float(::std::f64::INFINITY)
217    };
218
219    (@value $v:tt) => {{
221        let de = $crate::macros::IntoDeserializer::<$crate::de::Error>::into_deserializer($v);
223        <$crate::Value as $crate::macros::Deserialize>::deserialize(de).unwrap()
224    }};
225
226    (@table $root:ident) => {};
228
229    (@table $root:ident $($($k:tt)-+).+ = - $v:tt , $($rest:tt)*) => {
231        $crate::toml_internal!(@table $root $($($k)-+).+ = (-$v) , $($rest)*);
232    };
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)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
241        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
242    };
243    (@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)*) => {
245        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
246    };
247
248    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
250        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
251    };
252    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
254        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
255    };
256
257    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
259        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
260    };
261    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
263        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
264    };
265
266    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
268        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*);
269    };
270    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
272        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
273    };
274
275    (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => {
277        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day) $($rest)*);
278    };
279
280    (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
282        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*);
283    };
284
285    (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
287        $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec) $($rest)*);
288    };
289
290    (@table $root:ident $($($k:tt)-+).+ = $v:tt , $($rest:tt)*) => {
292        $crate::macros::insert_toml(
293            &mut $root,
294            &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
295            $crate::toml_internal!(@value $v));
296        $crate::toml_internal!(@table $root $($rest)*);
297    };
298
299    (@tabledatetime $root:ident $($($k:tt)-+).+ = ($($datetime:tt)*) $($rest:tt)*) => {
301        $crate::macros::insert_toml(
302            &mut $root,
303            &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+],
304            $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
305        $crate::toml_internal!(@table $root $($rest)*);
306    };
307
308    (@array $root:ident) => {};
310
311    (@array $root:ident - $v:tt , $($rest:tt)*) => {
313        $crate::toml_internal!(@array $root (-$v) , $($rest)*);
314    };
315
316    (@array $root:ident + $v:tt , $($rest:tt)*) => {
318        $crate::toml_internal!(@array $root ($v) , $($rest)*);
319    };
320
321    (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
323        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
324    };
325    (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
327        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*);
328    };
329
330    (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
332        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*);
333    };
334    (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => {
336        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*);
337    };
338
339    (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
341        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*);
342    };
343    (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
345        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*);
346    };
347
348    (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
350        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec) $($rest)*);
351    };
352    (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
354        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec) $($rest)*);
355    };
356
357    (@array $root:ident $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => {
359        $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day) $($rest)*);
360    };
361
362    (@array $root:ident $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => {
364        $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec . $frac) $($rest)*);
365    };
366
367    (@array $root:ident $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => {
369        $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec) $($rest)*);
370    };
371
372    (@array $root:ident $v:tt , $($rest:tt)*) => {
374        $root.push($crate::toml_internal!(@value $v));
375        $crate::toml_internal!(@array $root $($rest)*);
376    };
377
378    (@arraydatetime $root:ident ($($datetime:tt)*) $($rest:tt)*) => {
380        $root.push($crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap()));
381        $crate::toml_internal!(@array $root $($rest)*);
382    };
383
384    (@trailingcomma ($($args:tt)*)) => {
386        $crate::toml_internal!($($args)*);
387    };
388
389    (@trailingcomma ($($args:tt)*) ,) => {
391        $crate::toml_internal!($($args)* ,);
392    };
393
394    (@trailingcomma ($($args:tt)*) $last:tt) => {
396        $crate::toml_internal!($($args)* $last ,);
397    };
398
399    (@trailingcomma ($($args:tt)*) $first:tt $($rest:tt)+) => {
401        $crate::toml_internal!(@trailingcomma ($($args)* $first) $($rest)+);
402    };
403}
404
405pub fn insert_toml(root: &mut Value, path: &[&str], value: Value) {
408    *traverse(root, path) = value;
409}
410
411pub fn push_toml(root: &mut Value, path: &[&str]) {
414    let target = traverse(root, path);
415    if !target.is_array() {
416        *target = Value::Array(Array::new());
417    }
418    target
419        .as_array_mut()
420        .unwrap()
421        .push(Value::Table(Table::new()));
422}
423
424fn traverse<'a>(root: &'a mut Value, path: &[&str]) -> &'a mut Value {
425    let mut cur = root;
426    for &key in path {
427        let cur1 = cur;
429
430        let cur2 = if cur1.is_array() {
435            cur1.as_array_mut().unwrap().last_mut().unwrap()
436        } else {
437            cur1
438        };
439
440        if !cur2.is_table() {
442            *cur2 = Value::Table(Table::new());
443        }
444
445        if !cur2.as_table().unwrap().contains_key(key) {
446            let empty = Value::Table(Table::new());
448            cur2.as_table_mut().unwrap().insert(key.to_owned(), empty);
449        }
450
451        cur = cur2.as_table_mut().unwrap().get_mut(key).unwrap();
453    }
454    cur
455}