1#[macro_export]
41macro_rules! value {
42 (@array [$($elems:expr,)*]) => {
51 vec![$($elems,)*]
52 };
53
54 (@array [$($elems:expr),*]) => {
56 vec![$($elems),*]
57 };
58
59 (@array [$($elems:expr,)*] nil $($rest:tt)*) => {
61 $crate::value!(@array [$($elems,)* $crate::value!(nil)] $($rest)*)
62 };
63
64 (@array [$($elems:expr,)*] true $($rest:tt)*) => {
66 $crate::value!(@array [$($elems,)* $crate::value!(true)] $($rest)*)
67 };
68
69 (@array [$($elems:expr,)*] false $($rest:tt)*) => {
71 $crate::value!(@array [$($elems,)* $crate::value!(false)] $($rest)*)
72 };
73
74 (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
76 $crate::value!(@array [$($elems,)* $crate::value!([$($array)*])] $($rest)*)
77 };
78
79 (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
81 $crate::value!(@array [$($elems,)* $crate::value!({$($map)*})] $($rest)*)
82 };
83
84 (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
86 $crate::value!(@array [$($elems,)* $crate::value!($next),] $($rest)*)
87 };
88
89 (@array [$($elems:expr,)*] $last:expr) => {
91 $crate::value!(@array [$($elems,)* $crate::value!($last)])
92 };
93
94 (@array [$($elems:expr),*] , $($rest:tt)*) => {
96 $crate::value!(@array [$($elems,)*] $($rest)*)
97 };
98
99 (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
101 $crate::value_unexpected!($unexpected)
102 };
103
104 (@map $map:ident () () ()) => {};
116
117 (@map $map:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
119 let _ = $map.insert(($($key)+).into(), $value);
120 $crate::value!(@map $map () ($($rest)*) ($($rest)*));
121 };
122
123 (@map $map:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
125 $crate::value_unexpected!($unexpected);
126 };
127
128 (@map $map:ident [$($key:tt)+] ($value:expr)) => {
130 let _ = $map.insert(($($key)+).into(), $value);
131 };
132
133 (@map $map:ident ($($key:tt)+) (: nil $($rest:tt)*) $copy:tt) => {
135 $crate::value!(@map $map [$($key)+] ($crate::value!(nil)) $($rest)*);
136 };
137
138 (@map $map:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
140 $crate::value!(@map $map [$($key)+] ($crate::value!(true)) $($rest)*);
141 };
142
143 (@map $map:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
145 $crate::value!(@map $map [$($key)+] ($crate::value!(false)) $($rest)*);
146 };
147
148 (@map $map:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
150 $crate::value!(@map $map [$($key)+] ($crate::value!([$($array)*])) $($rest)*);
151 };
152
153 (@map $map:ident ($($key:tt)+) (: {$($inner:tt)*} $($rest:tt)*) $copy:tt) => {
155 $crate::value!(@map $map [$($key)+] ($crate::value!({$($inner)*})) $($rest)*);
156 };
157
158 (@map $map:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
160 $crate::value!(@map $map [$($key)+] ($crate::value!($value)) , $($rest)*);
161 };
162
163 (@map $map:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
165 $crate::value!(@map $map [$($key)+] ($crate::value!($value)));
166 };
167
168 (@map $map:ident ($($key:tt)+) (:) $copy:tt) => {
170 $crate::value!();
172 };
173
174 (@map $map:ident ($($key:tt)+) () $copy:tt) => {
177 $crate::value!();
179 };
180
181 (@map $map:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
183 $crate::value_unexpected!($colon);
185 };
186
187 (@map $map:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
189 $crate::value_unexpected!($comma);
191 };
192
193 (@map $map:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
196 $crate::value!(@map $map ($key) (: $($rest)*) (: $($rest)*));
197 };
198
199 (@map $map:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
201 $crate::value_expect_expr_comma!($($unexpected)+);
202 };
203
204 (@map $map:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
206 $crate::value!(@map $map ($($key)* $tt) ($($rest)*) ($($rest)*));
207 };
208
209 (nil) => {
216 $crate::Value::Nil
217 };
218
219 (true) => {
220 $crate::Value::Bool(true)
221 };
222
223 (false) => {
224 $crate::Value::Bool(false)
225 };
226
227 ([]) => {
228 $crate::Value::Array(vec![])
229 };
230
231 ([ $($tt:tt)+ ]) => {
232 $crate::Value::Array($crate::value!(@array [] $($tt)+))
233 };
234
235 ({}) => {
236 $crate::Value::Map($crate::__private::IndexMap::new())
237 };
238
239 ({ $($tt:tt)+ }) => {
240 $crate::Value::Map({
241 let mut map: $crate::__private::IndexMap<String, $crate::Value> = $crate::__private::IndexMap::new();
242 $crate::value!(@map map () ($($tt)+) ($($tt)+));
243 map
244 })
245 };
246
247 ($other:expr) => {
250 $crate::Value::from($other)
251 };
252}
253
254#[macro_export]
255#[doc(hidden)]
256macro_rules! value_unexpected {
257 () => {};
258}
259
260#[macro_export]
261#[doc(hidden)]
262macro_rules! value_expect_expr_comma {
263 ($e:expr , $($tt:tt)*) => {};
264}
265
266#[cfg(test)]
267mod tests {
268 use crate::Value;
269 use indexmap::IndexMap;
270
271 #[test]
272 fn test_value_macro_boolean() {
273 let true_val = value!(true);
274 assert_eq!(true_val, Value::Bool(true));
275
276 let false_val = value!(false);
277 assert_eq!(false_val, Value::Bool(false));
278 }
279
280 #[test]
281 fn test_value_macro_string() {
282 let string_val = value!("foo");
283 assert_eq!(string_val, Value::String("foo".to_string()));
284
285 let empty_string = value!("");
286 assert_eq!(empty_string, Value::String("".to_string()));
287 }
288
289 #[test]
290 fn test_value_macro_nil() {
291 let nil_val = value!(nil);
292 assert_eq!(nil_val, Value::Nil);
293 }
294
295 #[test]
296 fn test_value_macro_numeric() {
297 let integer_val = value!(42);
298 assert_eq!(integer_val, Value::Number(42));
299
300 let float_val = value!(3.14);
301 assert_eq!(float_val, Value::Float(3.14));
302
303 let negative_val = value!(-10.5);
304 assert_eq!(negative_val, Value::Float(-10.5));
305 }
306
307 #[test]
308 fn test_value_macro_array() {
309 let empty_array = value!([]);
310 assert_eq!(empty_array, Value::Array(vec![]));
311
312 let simple_array = value!([1, 2, 3]);
313 assert_eq!(
314 simple_array,
315 Value::Array(vec![
316 Value::Number(1),
317 Value::Number(2),
318 Value::Number(3),
319 ])
320 );
321
322 let mixed_array = value!([true, "hello", nil, 42.5]);
323 assert_eq!(
324 mixed_array,
325 Value::Array(vec![
326 Value::Bool(true),
327 Value::String("hello".to_string()),
328 Value::Nil,
329 Value::Float(42.5),
330 ])
331 );
332
333 let nested_array = value!([[1, 2], ["a", "b"]]);
334 assert_eq!(
335 nested_array,
336 Value::Array(vec![
337 Value::Array(vec![Value::Number(1), Value::Number(2)]),
338 Value::Array(vec![
339 Value::String("a".to_string()),
340 Value::String("b".to_string()),
341 ]),
342 ])
343 );
344 }
345
346 #[test]
347 fn test_value_macro_map() {
348 let empty_map = value!({});
349 assert_eq!(empty_map, Value::Map(IndexMap::new()));
350
351 let simple_map = value!({
352 "key1": "value1",
353 "key2": 42,
354 });
355 let expected_simple_map = Value::from_iter([
356 ("key1", Value::from("value1")),
357 ("key2", Value::from(42)),
358 ]);
359 assert_eq!(simple_map, expected_simple_map);
360
361 let complex_map = value!({
362 "boolean": true,
363 "string": "hello",
364 "nil": nil,
365 "number": 3.14,
366 "array": [1, 2, 3],
367 "nested_map": {
368 "inner_key": "inner_value",
369 },
370 });
371 let expected_complex_map = Value::from_iter([
372 ("boolean", Value::Bool(true)),
373 ("string", Value::String("hello".to_string())),
374 ("nil", Value::Nil),
375 ("number", Value::Float(3.14)),
376 ("array", Value::from(vec![
377 Value::Number(1),
378 Value::Number(2),
379 Value::Number(3),
380 ])),
381 ("nested_map", Value::from_iter([
382 ("inner_key", Value::String("inner_value".to_string()))
383 ])),
384 ]);
385 assert_eq!(complex_map, expected_complex_map);
386 }
387
388 #[test]
389 fn test_interpolation() {
390 let bool_var = true;
391 let string_var = "hello".to_string();
392 let int_var = 42;
393 let float_var = 3.14;
394 let nil_var = Value::Nil;
395 let array_var = vec![1, 2, 3];
396 let map_var: IndexMap<String, Value> = IndexMap::from([
397 ("key".to_string(), Value::String("value".to_string())),
398 ]);
399
400 let interpolated_value = value!({
401 "bool": bool_var,
402 "string": string_var,
403 "int": int_var,
404 "float": float_var,
405 "nil": nil_var,
406 "array": array_var,
407 "map": map_var,
408 });
409 let expected_value = Value::from_iter([
410 ("bool", Value::from(true)),
411 ("string", Value::from("hello")),
412 ("int", Value::from(42)),
413 ("float", Value::from(3.14)),
414 ("nil", Value::Nil),
415 ("array", Value::from(vec![
416 Value::from(1),
417 Value::from(2),
418 Value::from(3),
419 ])),
420 ("map", Value::from_iter([
421 ("key", Value::from("value")),
422 ])),
423 ]);
424 assert_eq!(interpolated_value, expected_value);
425 }
426}