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}