| 1 | pub use serde::de::{Deserialize, IntoDeserializer}; | 
| 2 |  | 
|---|
| 3 | use crate::value::{Array, Table, Value}; | 
|---|
| 4 |  | 
|---|
| 5 | /// Construct a [`toml::Value`] from TOML syntax. | 
|---|
| 6 | /// | 
|---|
| 7 | /// [`toml::Value`]: value/enum.Value.html | 
|---|
| 8 | /// | 
|---|
| 9 | /// ```rust | 
|---|
| 10 | /// let cargo_toml = toml::toml! { | 
|---|
| 11 | ///     [package] | 
|---|
| 12 | ///     name = "toml" | 
|---|
| 13 | ///     version = "0.4.5" | 
|---|
| 14 | ///     authors = [ "Alex Crichton <alex@alexcrichton.com>"] | 
|---|
| 15 | /// | 
|---|
| 16 | ///     [badges] | 
|---|
| 17 | ///     travis-ci = { repository = "alexcrichton/toml-rs"} | 
|---|
| 18 | /// | 
|---|
| 19 | ///     [dependencies] | 
|---|
| 20 | ///     serde = "1.0" | 
|---|
| 21 | /// | 
|---|
| 22 | ///     [dev-dependencies] | 
|---|
| 23 | ///     serde_derive = "1.0" | 
|---|
| 24 | ///     serde_json = "1.0" | 
|---|
| 25 | /// }; | 
|---|
| 26 | /// | 
|---|
| 27 | /// println!( "{:#?}", cargo_toml); | 
|---|
| 28 | /// ``` | 
|---|
| 29 | #[ macro_export] | 
|---|
| 30 | macro_rules! toml { | 
|---|
| 31 | ($($toml:tt)+) => {{ | 
|---|
| 32 | let table = $crate::value::Table::new(); | 
|---|
| 33 | let mut root = $crate::Value::Table(table); | 
|---|
| 34 | $crate::toml_internal!(@toplevel root [] $($toml)+); | 
|---|
| 35 | root | 
|---|
| 36 | }}; | 
|---|
| 37 | } | 
|---|
| 38 |  | 
|---|
| 39 | // TT-muncher to parse TOML syntax into a toml::Value. | 
|---|
| 40 | // | 
|---|
| 41 | //    @toplevel -- Parse tokens outside of an inline table or inline array. In | 
|---|
| 42 | //                 this state, `[table headers]` and `[[array headers]]` are | 
|---|
| 43 | //                 allowed and `key = value` pairs are not separated by commas. | 
|---|
| 44 | // | 
|---|
| 45 | //    @topleveldatetime -- Helper to parse a Datetime from string and insert it | 
|---|
| 46 | //                 into a table, continuing in the @toplevel state. | 
|---|
| 47 | // | 
|---|
| 48 | //    @path -- Turn a path segment into a string. Segments that look like idents | 
|---|
| 49 | //                 are stringified, while quoted segments like `"cfg(windows)"` | 
|---|
| 50 | //                 are not. | 
|---|
| 51 | // | 
|---|
| 52 | //    @value -- Parse the value part of a `key = value` pair, which may be a | 
|---|
| 53 | //                 primitive or inline table or inline array. | 
|---|
| 54 | // | 
|---|
| 55 | //    @table -- Parse the contents of an inline table, returning them as a | 
|---|
| 56 | //                 toml::Value::Table. | 
|---|
| 57 | // | 
|---|
| 58 | //    @tabledatetime -- Helper to parse a Datetime from string and insert it | 
|---|
| 59 | //                 into a table, continuing in the @table state. | 
|---|
| 60 | // | 
|---|
| 61 | //    @array -- Parse the contents of an inline array, returning them as a | 
|---|
| 62 | //                 toml::Value::Array. | 
|---|
| 63 | // | 
|---|
| 64 | //    @arraydatetime -- Helper to parse a Datetime from string and push it into | 
|---|
| 65 | //                 an array, continuing in the @array state. | 
|---|
| 66 | // | 
|---|
| 67 | //    @trailingcomma -- Helper to append a comma to a sequence of tokens if the | 
|---|
| 68 | //                 sequence is non-empty and does not already end in a trailing | 
|---|
| 69 | //                 comma. | 
|---|
| 70 | // | 
|---|
| 71 | #[ macro_export] | 
|---|
| 72 | #[ doc(hidden)] | 
|---|
| 73 | macro_rules! toml_internal { | 
|---|
| 74 | // Base case, no elements remaining. | 
|---|
| 75 | (@toplevel $root:ident [$($path:tt)*]) => {}; | 
|---|
| 76 |  | 
|---|
| 77 | // Parse negative number `key = -value`. | 
|---|
| 78 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = - $v:tt $($rest:tt)*) => { | 
|---|
| 79 | $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = (-$v) $($rest)*); | 
|---|
| 80 | }; | 
|---|
| 81 |  | 
|---|
| 82 | // Parse positive number `key = +value`. | 
|---|
| 83 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = + $v:tt $($rest:tt)*) => { | 
|---|
| 84 | $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = ($v) $($rest)*); | 
|---|
| 85 | }; | 
|---|
| 86 |  | 
|---|
| 87 | // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. | 
|---|
| 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)*) => { | 
|---|
| 89 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 90 | }; | 
|---|
| 91 | // Space instead of T. | 
|---|
| 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)*) => { | 
|---|
| 93 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 94 | }; | 
|---|
| 95 |  | 
|---|
| 96 | // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. | 
|---|
| 97 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { | 
|---|
| 98 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 99 | }; | 
|---|
| 100 | // Space instead of T. | 
|---|
| 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)*) => { | 
|---|
| 102 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 103 | }; | 
|---|
| 104 |  | 
|---|
| 105 | // Parse local datetime `key = 1979-05-27T00:32:00.999999`. | 
|---|
| 106 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { | 
|---|
| 107 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); | 
|---|
| 108 | }; | 
|---|
| 109 | // Space instead of T. | 
|---|
| 110 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { | 
|---|
| 111 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 112 | }; | 
|---|
| 113 |  | 
|---|
| 114 | // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. | 
|---|
| 115 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt $($rest:tt)*) => { | 
|---|
| 116 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); | 
|---|
| 117 | }; | 
|---|
| 118 | // Space instead of T. | 
|---|
| 119 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { | 
|---|
| 120 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); | 
|---|
| 121 | }; | 
|---|
| 122 |  | 
|---|
| 123 | // Parse local date `key = 1979-05-27`. | 
|---|
| 124 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $($rest:tt)*) => { | 
|---|
| 125 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); | 
|---|
| 126 | }; | 
|---|
| 127 |  | 
|---|
| 128 | // Parse local time `key = 00:32:00.999999`. | 
|---|
| 129 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { | 
|---|
| 130 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 131 | }; | 
|---|
| 132 |  | 
|---|
| 133 | // Parse local time `key = 07:32:00`. | 
|---|
| 134 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { | 
|---|
| 135 | $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); | 
|---|
| 136 | }; | 
|---|
| 137 |  | 
|---|
| 138 | // Parse any other `key = value` including string, inline array, inline | 
|---|
| 139 | // table, number, and boolean. | 
|---|
| 140 | (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $v:tt $($rest:tt)*) => {{ | 
|---|
| 141 | $crate::macros::insert_toml( | 
|---|
| 142 | &mut $root, | 
|---|
| 143 | &[$($path)* $(&concat!($( "-", $crate::toml_internal!(@path $k),)+)[1..], )+], | 
|---|
| 144 | $crate::toml_internal!(@value $v)); | 
|---|
| 145 | $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); | 
|---|
| 146 | }}; | 
|---|
| 147 |  | 
|---|
| 148 | // Parse array header `[[bin]]`. | 
|---|
| 149 | (@toplevel $root:ident $oldpath:tt [[$($($path:tt)-+).+]] $($rest:tt)*) => { | 
|---|
| 150 | $crate::macros::push_toml( | 
|---|
| 151 | &mut $root, | 
|---|
| 152 | &[$(&concat!($( "-", $crate::toml_internal!(@path $path),)+)[1..],)+]); | 
|---|
| 153 | $crate::toml_internal!(@toplevel $root [$(&concat!($( "-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); | 
|---|
| 154 | }; | 
|---|
| 155 |  | 
|---|
| 156 | // Parse table header `[patch.crates-io]`. | 
|---|
| 157 | (@toplevel $root:ident $oldpath:tt [$($($path:tt)-+).+] $($rest:tt)*) => { | 
|---|
| 158 | $crate::macros::insert_toml( | 
|---|
| 159 | &mut $root, | 
|---|
| 160 | &[$(&concat!($( "-", $crate::toml_internal!(@path $path),)+)[1..],)+], | 
|---|
| 161 | $crate::Value::Table($crate::value::Table::new())); | 
|---|
| 162 | $crate::toml_internal!(@toplevel $root [$(&concat!($( "-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); | 
|---|
| 163 | }; | 
|---|
| 164 |  | 
|---|
| 165 | // Parse datetime from string and insert into table. | 
|---|
| 166 | (@topleveldatetime $root:ident [$($path:tt)*] $($($k:tt)-+).+ = ($($datetime:tt)+) $($rest:tt)*) => { | 
|---|
| 167 | $crate::macros::insert_toml( | 
|---|
| 168 | &mut $root, | 
|---|
| 169 | &[$($path)* $(&concat!($( "-", $crate::toml_internal!(@path $k),)+)[1..], )+], | 
|---|
| 170 | $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); | 
|---|
| 171 | $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); | 
|---|
| 172 | }; | 
|---|
| 173 |  | 
|---|
| 174 | // Turn a path segment into a string. | 
|---|
| 175 | (@path $ident:ident) => { | 
|---|
| 176 | stringify!($ident) | 
|---|
| 177 | }; | 
|---|
| 178 |  | 
|---|
| 179 | // For a path segment that is not an ident, expect that it is already a | 
|---|
| 180 | // quoted string, like in `[target."cfg(windows)".dependencies]`. | 
|---|
| 181 | (@path $quoted:tt) => { | 
|---|
| 182 | $quoted | 
|---|
| 183 | }; | 
|---|
| 184 |  | 
|---|
| 185 | // Construct a Value from an inline table. | 
|---|
| 186 | (@value { $($inline:tt)* }) => {{ | 
|---|
| 187 | let mut table = $crate::Value::Table($crate::value::Table::new()); | 
|---|
| 188 | $crate::toml_internal!(@trailingcomma (@table table) $($inline)*); | 
|---|
| 189 | table | 
|---|
| 190 | }}; | 
|---|
| 191 |  | 
|---|
| 192 | // Construct a Value from an inline array. | 
|---|
| 193 | (@value [ $($inline:tt)* ]) => {{ | 
|---|
| 194 | let mut array = $crate::value::Array::new(); | 
|---|
| 195 | $crate::toml_internal!(@trailingcomma (@array array) $($inline)*); | 
|---|
| 196 | $crate::Value::Array(array) | 
|---|
| 197 | }}; | 
|---|
| 198 |  | 
|---|
| 199 | (@value (-nan)) => { | 
|---|
| 200 | $crate::Value::Float(-::std::f64::NAN) | 
|---|
| 201 | }; | 
|---|
| 202 |  | 
|---|
| 203 | (@value (nan)) => { | 
|---|
| 204 | $crate::Value::Float(::std::f64::NAN) | 
|---|
| 205 | }; | 
|---|
| 206 |  | 
|---|
| 207 | (@value nan) => { | 
|---|
| 208 | $crate::Value::Float(::std::f64::NAN) | 
|---|
| 209 | }; | 
|---|
| 210 |  | 
|---|
| 211 | (@value (-inf)) => { | 
|---|
| 212 | $crate::Value::Float(::std::f64::NEG_INFINITY) | 
|---|
| 213 | }; | 
|---|
| 214 |  | 
|---|
| 215 | (@value (inf)) => { | 
|---|
| 216 | $crate::Value::Float(::std::f64::INFINITY) | 
|---|
| 217 | }; | 
|---|
| 218 |  | 
|---|
| 219 | (@value inf) => { | 
|---|
| 220 | $crate::Value::Float(::std::f64::INFINITY) | 
|---|
| 221 | }; | 
|---|
| 222 |  | 
|---|
| 223 | // Construct a Value from any other type, probably string or boolean or number. | 
|---|
| 224 | (@value $v:tt) => {{ | 
|---|
| 225 | // TODO: Implement this with something like serde_json::to_value instead. | 
|---|
| 226 | let de = $crate::macros::IntoDeserializer::<$crate::de::Error>::into_deserializer($v); | 
|---|
| 227 | <$crate::Value as $crate::macros::Deserialize>::deserialize(de).unwrap() | 
|---|
| 228 | }}; | 
|---|
| 229 |  | 
|---|
| 230 | // Base case of inline table. | 
|---|
| 231 | (@table $root:ident) => {}; | 
|---|
| 232 |  | 
|---|
| 233 | // Parse negative number `key = -value`. | 
|---|
| 234 | (@table $root:ident $($($k:tt)-+).+ = - $v:tt , $($rest:tt)*) => { | 
|---|
| 235 | $crate::toml_internal!(@table $root $($($k)-+).+ = (-$v) , $($rest)*); | 
|---|
| 236 | }; | 
|---|
| 237 |  | 
|---|
| 238 | // Parse positive number `key = +value`. | 
|---|
| 239 | (@table $root:ident $($($k:tt)-+).+ = + $v:tt , $($rest:tt)*) => { | 
|---|
| 240 | $crate::toml_internal!(@table $root $($($k)-+).+ = ($v) , $($rest)*); | 
|---|
| 241 | }; | 
|---|
| 242 |  | 
|---|
| 243 | // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. | 
|---|
| 244 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 245 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 246 | }; | 
|---|
| 247 | // Space instead of T. | 
|---|
| 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)*) => { | 
|---|
| 249 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 250 | }; | 
|---|
| 251 |  | 
|---|
| 252 | // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. | 
|---|
| 253 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 254 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 255 | }; | 
|---|
| 256 | // Space instead of T. | 
|---|
| 257 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 258 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 259 | }; | 
|---|
| 260 |  | 
|---|
| 261 | // Parse local datetime `key = 1979-05-27T00:32:00.999999`. | 
|---|
| 262 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 263 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); | 
|---|
| 264 | }; | 
|---|
| 265 | // Space instead of T. | 
|---|
| 266 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 267 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 268 | }; | 
|---|
| 269 |  | 
|---|
| 270 | // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. | 
|---|
| 271 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 272 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); | 
|---|
| 273 | }; | 
|---|
| 274 | // Space instead of T. | 
|---|
| 275 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 276 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); | 
|---|
| 277 | }; | 
|---|
| 278 |  | 
|---|
| 279 | // Parse local date `key = 1979-05-27`. | 
|---|
| 280 | (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { | 
|---|
| 281 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); | 
|---|
| 282 | }; | 
|---|
| 283 |  | 
|---|
| 284 | // Parse local time `key = 00:32:00.999999`. | 
|---|
| 285 | (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 286 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 287 | }; | 
|---|
| 288 |  | 
|---|
| 289 | // Parse local time `key = 07:32:00`. | 
|---|
| 290 | (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 291 | $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); | 
|---|
| 292 | }; | 
|---|
| 293 |  | 
|---|
| 294 | // Parse any other type, probably string or boolean or number. | 
|---|
| 295 | (@table $root:ident $($($k:tt)-+).+ = $v:tt , $($rest:tt)*) => { | 
|---|
| 296 | $crate::macros::insert_toml( | 
|---|
| 297 | &mut $root, | 
|---|
| 298 | &[$(&concat!($( "-", $crate::toml_internal!(@path $k),)+)[1..], )+], | 
|---|
| 299 | $crate::toml_internal!(@value $v)); | 
|---|
| 300 | $crate::toml_internal!(@table $root $($rest)*); | 
|---|
| 301 | }; | 
|---|
| 302 |  | 
|---|
| 303 | // Parse a Datetime from string and continue in @table state. | 
|---|
| 304 | (@tabledatetime $root:ident $($($k:tt)-+).+ = ($($datetime:tt)*) $($rest:tt)*) => { | 
|---|
| 305 | $crate::macros::insert_toml( | 
|---|
| 306 | &mut $root, | 
|---|
| 307 | &[$(&concat!($( "-", $crate::toml_internal!(@path $k),)+)[1..], )+], | 
|---|
| 308 | $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); | 
|---|
| 309 | $crate::toml_internal!(@table $root $($rest)*); | 
|---|
| 310 | }; | 
|---|
| 311 |  | 
|---|
| 312 | // Base case of inline array. | 
|---|
| 313 | (@array $root:ident) => {}; | 
|---|
| 314 |  | 
|---|
| 315 | // Parse negative number `-value`. | 
|---|
| 316 | (@array $root:ident - $v:tt , $($rest:tt)*) => { | 
|---|
| 317 | $crate::toml_internal!(@array $root (-$v) , $($rest)*); | 
|---|
| 318 | }; | 
|---|
| 319 |  | 
|---|
| 320 | // Parse positive number `+value`. | 
|---|
| 321 | (@array $root:ident + $v:tt , $($rest:tt)*) => { | 
|---|
| 322 | $crate::toml_internal!(@array $root ($v) , $($rest)*); | 
|---|
| 323 | }; | 
|---|
| 324 |  | 
|---|
| 325 | // Parse offset datetime `1979-05-27T00:32:00.999999-07:00`. | 
|---|
| 326 | (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 327 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 328 | }; | 
|---|
| 329 | // Space instead of T. | 
|---|
| 330 | (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 331 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); | 
|---|
| 332 | }; | 
|---|
| 333 |  | 
|---|
| 334 | // Parse offset datetime `1979-05-27T00:32:00-07:00`. | 
|---|
| 335 | (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 336 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 337 | }; | 
|---|
| 338 | // Space instead of T. | 
|---|
| 339 | (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { | 
|---|
| 340 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); | 
|---|
| 341 | }; | 
|---|
| 342 |  | 
|---|
| 343 | // Parse local datetime `1979-05-27T00:32:00.999999`. | 
|---|
| 344 | (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 345 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); | 
|---|
| 346 | }; | 
|---|
| 347 | // Space instead of T. | 
|---|
| 348 | (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 349 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 350 | }; | 
|---|
| 351 |  | 
|---|
| 352 | // Parse offset datetime `1979-05-27T07:32:00Z` and local datetime `1979-05-27T07:32:00`. | 
|---|
| 353 | (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 354 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec) $($rest)*); | 
|---|
| 355 | }; | 
|---|
| 356 | // Space instead of T. | 
|---|
| 357 | (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 358 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); | 
|---|
| 359 | }; | 
|---|
| 360 |  | 
|---|
| 361 | // Parse local date `1979-05-27`. | 
|---|
| 362 | (@array $root:ident $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { | 
|---|
| 363 | $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day) $($rest)*); | 
|---|
| 364 | }; | 
|---|
| 365 |  | 
|---|
| 366 | // Parse local time `00:32:00.999999`. | 
|---|
| 367 | (@array $root:ident $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { | 
|---|
| 368 | $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec . $frac) $($rest)*); | 
|---|
| 369 | }; | 
|---|
| 370 |  | 
|---|
| 371 | // Parse local time `07:32:00`. | 
|---|
| 372 | (@array $root:ident $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { | 
|---|
| 373 | $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec) $($rest)*); | 
|---|
| 374 | }; | 
|---|
| 375 |  | 
|---|
| 376 | // Parse any other type, probably string or boolean or number. | 
|---|
| 377 | (@array $root:ident $v:tt , $($rest:tt)*) => { | 
|---|
| 378 | $root.push($crate::toml_internal!(@value $v)); | 
|---|
| 379 | $crate::toml_internal!(@array $root $($rest)*); | 
|---|
| 380 | }; | 
|---|
| 381 |  | 
|---|
| 382 | // Parse a Datetime from string and continue in @array state. | 
|---|
| 383 | (@arraydatetime $root:ident ($($datetime:tt)*) $($rest:tt)*) => { | 
|---|
| 384 | $root.push($crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); | 
|---|
| 385 | $crate::toml_internal!(@array $root $($rest)*); | 
|---|
| 386 | }; | 
|---|
| 387 |  | 
|---|
| 388 | // No trailing comma required if the tokens are empty. | 
|---|
| 389 | (@trailingcomma ($($args:tt)*)) => { | 
|---|
| 390 | $crate::toml_internal!($($args)*); | 
|---|
| 391 | }; | 
|---|
| 392 |  | 
|---|
| 393 | // Tokens end with a trailing comma, do not append another one. | 
|---|
| 394 | (@trailingcomma ($($args:tt)*) ,) => { | 
|---|
| 395 | $crate::toml_internal!($($args)* ,); | 
|---|
| 396 | }; | 
|---|
| 397 |  | 
|---|
| 398 | // Tokens end with something other than comma, append a trailing comma. | 
|---|
| 399 | (@trailingcomma ($($args:tt)*) $last:tt) => { | 
|---|
| 400 | $crate::toml_internal!($($args)* $last ,); | 
|---|
| 401 | }; | 
|---|
| 402 |  | 
|---|
| 403 | // Not yet at the last token. | 
|---|
| 404 | (@trailingcomma ($($args:tt)*) $first:tt $($rest:tt)+) => { | 
|---|
| 405 | $crate::toml_internal!(@trailingcomma ($($args)* $first) $($rest)+); | 
|---|
| 406 | }; | 
|---|
| 407 | } | 
|---|
| 408 |  | 
|---|
| 409 | // Called when parsing a `key = value` pair. | 
|---|
| 410 | // Inserts an entry into the table at the given path. | 
|---|
| 411 | pub fn insert_toml(root: &mut Value, path: &[&str], value: Value) { | 
|---|
| 412 | *traverse(root, path) = value; | 
|---|
| 413 | } | 
|---|
| 414 |  | 
|---|
| 415 | // Called when parsing an `[[array header]]`. | 
|---|
| 416 | // Pushes an empty table onto the array at the given path. | 
|---|
| 417 | pub fn push_toml(root: &mut Value, path: &[&str]) { | 
|---|
| 418 | let target: &mut Value = traverse(root, path); | 
|---|
| 419 | if !target.is_array() { | 
|---|
| 420 | *target = Value::Array(Array::new()); | 
|---|
| 421 | } | 
|---|
| 422 | target&mut Vec | 
|---|
| 423 | .as_array_mut() | 
|---|
| 424 | .unwrap() | 
|---|
| 425 | .push(Value::Table(Table::new())); | 
|---|
| 426 | } | 
|---|
| 427 |  | 
|---|
| 428 | fn traverse<'a>(root: &'a mut Value, path: &[&str]) -> &'a mut Value { | 
|---|
| 429 | let mut cur = root; | 
|---|
| 430 | for &key in path { | 
|---|
| 431 | // Lexical lifetimes :D | 
|---|
| 432 | let cur1 = cur; | 
|---|
| 433 |  | 
|---|
| 434 | // From the TOML spec: | 
|---|
| 435 | // | 
|---|
| 436 | // > Each double-bracketed sub-table will belong to the most recently | 
|---|
| 437 | // > defined table element above it. | 
|---|
| 438 | let cur2 = if cur1.is_array() { | 
|---|
| 439 | cur1.as_array_mut().unwrap().last_mut().unwrap() | 
|---|
| 440 | } else { | 
|---|
| 441 | cur1 | 
|---|
| 442 | }; | 
|---|
| 443 |  | 
|---|
| 444 | // We are about to index into this value, so it better be a table. | 
|---|
| 445 | if !cur2.is_table() { | 
|---|
| 446 | *cur2 = Value::Table(Table::new()); | 
|---|
| 447 | } | 
|---|
| 448 |  | 
|---|
| 449 | if !cur2.as_table().unwrap().contains_key(key) { | 
|---|
| 450 | // Insert an empty table for the next loop iteration to point to. | 
|---|
| 451 | let empty = Value::Table(Table::new()); | 
|---|
| 452 | cur2.as_table_mut().unwrap().insert(key.to_owned(), empty); | 
|---|
| 453 | } | 
|---|
| 454 |  | 
|---|
| 455 | // Step into the current table. | 
|---|
| 456 | cur = cur2.as_table_mut().unwrap().get_mut(key).unwrap(); | 
|---|
| 457 | } | 
|---|
| 458 | cur | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|