simd_json/
macros.rs

1/// Construct a `simd_json::Value` from a JSON literal.
2///
3/// Taken from: <https://github.com/serde-rs/json/blob/5b5f95831d9e0d769367b30b76a686339bffd209/src/macros.rs>
4///
5/// ```edition2018
6/// # use simd_json::json;
7/// #
8/// let value = json!({
9///     "code": 200,
10///     "success": true,
11///     "payload": {
12///         "features": [
13///             "serde",
14///             "json"
15///         ]
16///     }
17/// });
18/// ```
19///
20/// Variables or expressions can be interpolated into the JSON literal. Any type
21/// interpolated into an array element or object value must implement Serde's
22/// `Serialize` trait, while any type interpolated into a object key must
23/// implement `Into<String>`. If the `Serialize` implementation of the
24/// interpolated type decides to fail, or if the interpolated type contains a
25/// map with non-string keys, the `json!` macro will panic.
26///
27/// ```edition2018
28/// # use simd_json::json;
29/// #
30/// let code = 200;
31/// let features = vec!["serde", "json"];
32///
33/// let value = json!({
34///     "code": code,
35///     "success": code == 200,
36///     "payload": {
37///         features[0]: features[1]
38///     }
39/// });
40/// ```
41///
42/// Trailing commas are allowed inside both arrays and objects.
43///
44/// ```edition2018
45/// # use simd_json::json;
46/// #
47/// let value = json!([
48///     "notice",
49///     "the",
50///     "trailing",
51///     "comma -->",
52/// ]);
53/// ```
54///
55/// It works for both Borrowed and owned values when used with `.into()`
56/// ```edition2018
57/// # use simd_json::{json, OwnedValue, BorrowedValue};
58/// #
59/// let owned_value: OwnedValue = json!({
60///     "code": 200,
61///     "success": true,
62///     "payload": {
63///         "features": [
64///             "serde",
65///             "json"
66///         ]
67///     }
68/// });
69///
70/// let borrowed_value: BorrowedValue = json!({
71///     "code": 200,
72///     "success": true,
73///     "payload": {
74///         "features": [
75///             "serde",
76///             "json"
77///         ]
78///     },
79///     "empty_obj": {},
80///     "empty_array": [],
81/// }).into();
82/// ````
83#[macro_export(local_inner_macros)]
84macro_rules! json {
85    // Hide distracting implementation details from the generated rustdoc.
86    ($($json:tt)+) => {
87        json_internal_owned!($($json)+)
88    };
89}
90
91/// Constructs a `simd_json::Value` from a JSON literal and allows specifying whether it generates
92/// an owned or borrowed variant.
93///
94/// Adapted from: <https://github.com/serde-rs/json/blob/5b5f95831d9e0d769367b30b76a686339bffd209/src/macros.rs>
95///
96/// Create an owned value of the form:
97///
98/// ```edition2018
99/// # use simd_json::{json_typed, OwnedValue};
100/// #
101/// let value: OwnedValue = json_typed!(owned, {
102///     "code": 200,
103///     "success": true,
104///     "payload": {
105///         "features": [
106///             "serde",
107///             "json"
108///         ]
109///     }
110/// });
111/// ```
112///
113/// Create a borrowed value of the form:
114///
115/// ```edition2018
116/// # use simd_json::{json_typed, BorrowedValue};
117/// #
118/// let value: BorrowedValue = json_typed!(borrowed, {
119///     "code": 200,
120///     "success": true,
121///     "payload": {
122///         "features": [
123///             "serde",
124///             "json"
125///         ]
126///     }
127/// });
128/// ```
129///
130/// Variables or expressions can be interpolated into the JSON literal. Any type
131/// interpolated into an array element or object value must implement Serde's
132/// `Serialize` trait, while any type interpolated into a object key must
133/// implement `Into<String>`. If the `Serialize` implementation of the
134/// interpolated type decides to fail, or if the interpolated type contains a
135/// map with non-string keys, the `json!` macro will panic.
136///
137/// ```edition2018
138/// # use simd_json::json_typed;
139/// #
140/// let code = 200;
141/// let features = vec!["serde", "json"];
142///
143/// let value = json_typed!(owned, {
144///     "code": code,
145///     "success": code == 200,
146///     "payload": {
147///         features[0]: features[1]
148///     }
149/// });
150/// ```
151///
152/// Trailing commas are allowed inside both arrays and objects.
153///
154/// ```edition2018
155/// # use simd_json::json_typed;
156/// #
157/// let value = json_typed!(borrowed, [
158///     "notice",
159///     "the",
160///     "trailing",
161///     "comma -->",
162/// ]);
163/// ```
164///
165/// It works for both Borrowed and owned values natively without the
166/// need for calling `into()` unlike the `json!` macro which supports
167/// owned values only.
168///
169/// ```edition2018
170/// # use simd_json::{json_typed, OwnedValue, BorrowedValue};
171/// #
172/// let owned_value: OwnedValue = json_typed!(owned, {
173///     "code": 200,
174///     "success": true,
175///     "payload": {
176///         "features": [
177///             "serde",
178///             "json"
179///         ]
180///     }
181/// });
182///
183/// let borrowed_value: BorrowedValue = json_typed!(borrowed, {
184///     "code": 200,
185///     "success": true,
186///     "payload": {
187///         "features": [
188///             "serde",
189///             "json"
190///         ]
191///     },
192///     "empty_obj": {},
193///     "empty_array": [],
194/// }).into();
195/// ````
196#[macro_export(local_inner_macros)]
197macro_rules! json_typed {
198    (owned, $($json:tt)+) => {
199        json_internal_owned!($($json)+)
200    };
201    (borrowed, $($json:tt)+) => {
202        json_internal_borrowed!($($json)+)
203   };
204
205}
206
207// Rocket relies on this because they export their own `json!` with a different
208// doc comment than ours, and various Rust bugs prevent them from calling our
209// `json!` from their `json!` so they call `json_internal!` directly. Check with
210// @SergioBenitez before making breaking changes to this macro.
211//
212// Changes are fine as long as `json_internal!` does not call any new helper
213// macros and can still be invoked as `json_internal!($($json)+)`.
214#[cfg(feature = "serde_impl")]
215#[macro_export(local_inner_macros)]
216#[doc(hidden)]
217macro_rules! json_internal_owned {
218    //////////////////////////////////////////////////////////////////////////
219    // TT muncher for parsing the inside of an array [...]. Produces a vec![...]
220    // of the elements.
221    //
222    // Must be invoked as: json_internal_owned!(@array [] $($tt)*)
223    //////////////////////////////////////////////////////////////////////////
224
225    // Done with trailing comma.
226    (@array [$($elems:expr,)*]) => {
227        json_internal_vec![$($elems,)*]
228    };
229
230    // Done without trailing comma.
231    (@array [$($elems:expr),*]) => {
232        json_internal_vec![$($elems),*]
233    };
234
235    // Next element is `null`.
236    (@array [$($elems:expr,)*] null $($rest:tt)*) => {
237        json_internal_owned!(@array [$($elems,)* json_internal_owned!(null)] $($rest)*)
238    };
239
240    // Next element is `true`.
241    (@array [$($elems:expr,)*] true $($rest:tt)*) => {
242        json_internal_owned!(@array [$($elems,)* json_internal_owned!(true)] $($rest)*)
243    };
244
245    // Next element is `false`.
246    (@array [$($elems:expr,)*] false $($rest:tt)*) => {
247        json_internal_owned!(@array [$($elems,)* json_internal_owned!(false)] $($rest)*)
248    };
249
250    // Next element is an array.
251    (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
252        json_internal_owned!(@array [$($elems,)* json_internal_owned!([$($array)*])] $($rest)*)
253    };
254
255    // Next element is a map.
256    (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
257        json_internal_owned!(@array [$($elems,)* json_internal_owned!({$($map)*})] $($rest)*)
258    };
259
260    // Next element is an expression followed by comma.
261    (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
262        json_internal_owned!(@array [$($elems,)* json_internal_owned!($next),] $($rest)*)
263    };
264
265    // Last element is an expression with no trailing comma.
266    (@array [$($elems:expr,)*] $last:expr) => {
267        json_internal_owned!(@array [$($elems,)* json_internal_owned!($last)])
268    };
269
270    // Comma after the most recent element.
271    (@array [$($elems:expr),*] , $($rest:tt)*) => {
272        json_internal_owned!(@array [$($elems,)*] $($rest)*)
273    };
274
275    // Unexpected token after most recent element.
276    (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
277        json_unexpected!($unexpected)
278    };
279
280    //////////////////////////////////////////////////////////////////////////
281    // TT muncher for parsing the inside of an object {...}. Each entry is
282    // inserted into the given map variable. Entries are parsed from the TT
283    // and then inserted into a stack of entries to be appended all at once
284    // at the end, allowing us to pre-allocate the map.
285    //
286    // Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
287    //
288    // We require two copies of the input tokens so that we can match on one
289    // copy and trigger errors on the other copy.
290    //////////////////////////////////////////////////////////////////////////
291
292    // Done.
293    (@object $object:ident [@entries] () () ()) => {};
294
295    // Count the number of entries to insert.
296    // Modified version of https://docs.rs/halfbrown/0.1.11/src/halfbrown/macros.rs.html#46-62
297    (@object @count [@entries $(($value:expr => $($key:tt)+))*]) => {
298        <[()]>::len(&[$(json_internal_owned!(@object @count @single ($($key)+))),*])
299    };
300    (@object @count @single ($($key:tt)+)) => {()};
301
302    // Done. Insert all entries from the stack
303    (@object $object:ident [@entries $(($value:expr => $($key:tt)+))*] () () ()) => {
304        let len = json_internal_owned!(@object @count [@entries $(($value => $($key)+))*]);
305        $object = $crate::value::owned::Object::with_capacity_and_hasher(len, $crate::value::ObjectHasher::default());
306        $(
307            #[allow(clippy::let_underscore_drop)]
308            let _: Option<_> = $object.insert(($($key)+).into(), $value);
309        )*
310    };
311
312    // Insert the current entry (followed by trailing comma) into the stack.
313    // Entries are inserted in reverse order, the captured $entries is expanded first,
314    // keeping inserts in the same order that they're defined in the macro.
315    //
316    // We expand the $key _after_ the $value since $key => $value leads to a parsing ambiguity.
317    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
318        json_internal_owned!(@object $object [@entries $($entries)* ($value => $($key)+) ] () ($($rest)*) ($($rest)*));
319    };
320
321    // Insert the last entry (without trailing comma) into the stack.
322    // At this point the recursion is complete and the entries can now be inserted.
323    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr)) => {
324        json_internal_owned!(@object $object [@entries $($entries)* ($value => $($key)+) ] () () ());
325    };
326
327    // Current entry followed by unexpected token.
328    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
329        json_unexpected!($unexpected);
330    };
331
332
333    // Next value is `null`.
334    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
335        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(null)) $($rest)*);
336    };
337
338    // Next value is `true`.
339    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
340        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(true)) $($rest)*);
341    };
342
343    // Next value is `false`.
344    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
345        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(false)) $($rest)*);
346    };
347
348    // Next value is an array.
349    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
350        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!([$($array)*])) $($rest)*);
351    };
352
353    // Next value is a map.
354    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
355        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!({$($map)*})) $($rest)*);
356    };
357
358    // Next value is an expression followed by comma.
359    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
360        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!($value)) , $($rest)*);
361    };
362
363    // Last value is an expression with no trailing comma.
364    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr) $copy:tt) => {
365        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!($value)));
366    };
367
368    // Missing value for last entry. Trigger a reasonable error message.
369    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (:) $copy:tt) => {
370        // "unexpected end of macro invocation"
371        json_internal_owned!();
372    };
373
374    // Missing colon and value for last entry. Trigger a reasonable error
375    // message.
376    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) () $copy:tt) => {
377        // "unexpected end of macro invocation"
378        json_internal_owned!();
379    };
380
381    // Misplaced colon. Trigger a reasonable error message.
382    (@object $object:ident [@entries $($entries:tt)*] () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
383        // Takes no arguments so "no rules expected the token `:`".
384        json_unexpected!($colon);
385    };
386
387    // Found a comma inside a key. Trigger a reasonable error message.
388    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
389        // Takes no arguments so "no rules expected the token `,`".
390        json_unexpected!($comma);
391    };
392
393    // Key is fully parenthesized. This avoids clippy double_parens false
394    // positives because the parenthesization may be necessary here.
395    (@object $object:ident [@entries $($entries:tt)*] () (($key:expr) : $($rest:tt)*) $copy:tt) => {
396        json_internal_owned!(@object $object [@entries $($entries)*] ($key) (: $($rest)*) (: $($rest)*));
397    };
398
399    // Munch a token into the current key.
400    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
401        json_internal_owned!(@object $object [@entries $($entries)*] ($($key)* $tt) ($($rest)*) ($($rest)*));
402    };
403
404    //////////////////////////////////////////////////////////////////////////
405    // The main implementation.
406    //
407    // Must be invoked as: json_internal!($($json)+)
408    //////////////////////////////////////////////////////////////////////////
409
410    (null) => {
411        $crate::value::owned::Value::Static($crate::StaticNode::Null)
412    };
413
414    (true) => {
415        $crate::value::owned::Value::Static($crate::StaticNode::Bool(true))
416    };
417
418    (false) => {
419        $crate::value::owned::Value::Static($crate::StaticNode::Bool(false))
420    };
421
422    ([]) => {
423        $crate::value::owned::Value::Array(Box::new(json_internal_vec![]))
424    };
425
426    ([ $($tt:tt)+ ]) => {
427        $crate::value::owned::Value::Array(Box::new(json_internal_owned!(@array [] $($tt)+)))
428    };
429
430    ({}) => {
431        {
432            use $crate::value::ValueBuilder;
433            $crate::value::owned::Value::object()
434        }
435    };
436
437    ({ $($tt:tt)+ }) => {
438        $crate::value::owned::Value::from({
439            let mut object;
440            json_internal_owned!(@object object [@entries] () ($($tt)+) ($($tt)+));
441            object
442        })
443    };
444
445    // Any Serialize type: numbers, strings, struct literals, variables etc.
446    // Must be below every other rule.
447    ($other:expr) => {
448        $crate::serde::to_owned_value(&$other).expect("serde::to_owned_value")
449    };
450}
451
452#[cfg(not(feature = "serde_impl"))]
453#[macro_export(local_inner_macros)]
454#[doc(hidden)]
455macro_rules! json_internal_owned {
456    //////////////////////////////////////////////////////////////////////////
457    // TT muncher for parsing the inside of an array [...]. Produces a vec![...]
458    // of the elements.
459    //
460    // Must be invoked as: json_internal_owned!(@array [] $($tt)*)
461    //////////////////////////////////////////////////////////////////////////
462
463    // Done with trailing comma.
464    (@array [$($elems:expr,)*]) => {
465        json_internal_vec![$($elems,)*]
466    };
467
468    // Done without trailing comma.
469    (@array [$($elems:expr),*]) => {
470        json_internal_vec![$($elems),*]
471    };
472
473    // Next element is `null`.
474    (@array [$($elems:expr,)*] null $($rest:tt)*) => {
475        json_internal_owned!(@array [$($elems,)* json_internal_owned!(null)] $($rest)*)
476    };
477
478    // Next element is `true`.
479    (@array [$($elems:expr,)*] true $($rest:tt)*) => {
480        json_internal_owned!(@array [$($elems,)* json_internal_owned!(true)] $($rest)*)
481    };
482
483    // Next element is `false`.
484    (@array [$($elems:expr,)*] false $($rest:tt)*) => {
485        json_internal_owned!(@array [$($elems,)* json_internal_owned!(false)] $($rest)*)
486    };
487
488    // Next element is an array.
489    (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
490        json_internal_owned!(@array [$($elems,)* json_internal_owned!([$($array)*])] $($rest)*)
491    };
492
493    // Next element is a map.
494    (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
495        json_internal_owned!(@array [$($elems,)* json_internal_owned!({$($map)*})] $($rest)*)
496    };
497
498    // Next element is an expression followed by comma.
499    (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
500        json_internal_owned!(@array [$($elems,)* json_internal_owned!($next),] $($rest)*)
501    };
502
503    // Last element is an expression with no trailing comma.
504    (@array [$($elems:expr,)*] $last:expr) => {
505        json_internal_owned!(@array [$($elems,)* json_internal_owned!($last)])
506    };
507
508    // Comma after the most recent element.
509    (@array [$($elems:expr),*] , $($rest:tt)*) => {
510        json_internal_owned!(@array [$($elems,)*] $($rest)*)
511    };
512
513    // Unexpected token after most recent element.
514    (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
515        json_unexpected!($unexpected)
516    };
517
518    //////////////////////////////////////////////////////////////////////////
519    // TT muncher for parsing the inside of an object {...}. Each entry is
520    // inserted into the given map variable. Entries are parsed from the TT
521    // and then inserted into a stack of entries to be appended all at once
522    // at the end, allowing us to pre-allocate the map.
523    //
524    // Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
525    //
526    // We require two copies of the input tokens so that we can match on one
527    // copy and trigger errors on the other copy.
528    //////////////////////////////////////////////////////////////////////////
529
530    // Done.
531    (@object $object:ident [@entries] () () ()) => {};
532
533    // Count the number of entries to insert.
534    // Modified version of https://docs.rs/halfbrown/0.1.11/src/halfbrown/macros.rs.html#46-62
535    (@object @count [@entries $(($value:expr => $($key:tt)+))*]) => {
536        <[()]>::len(&[$(json_internal_owned!(@object @count @single ($($key)+))),*])
537    };
538    (@object @count @single ($($key:tt)+)) => {()};
539
540    // Done. Insert all entries from the stack
541    (@object $object:ident [@entries $(($value:expr => $($key:tt)+))*] () () ()) => {
542        let len = json_internal_owned!(@object @count [@entries $(($value => $($key)+))*]);
543        $object = $crate::value::owned::Object::with_capacity_and_hasher(len, $crate::value::ObjectHasher::default());
544        $(
545            #[allow(clippy::let_underscore_drop)]
546            let _: Option<_> = $object.insert(($($key)+).into(), $value);
547        )*
548    };
549
550    // Insert the current entry (followed by trailing comma) into the stack.
551    // Entries are inserted in reverse order, the captured $entries is expanded first,
552    // keeping inserts in the same order that they're defined in the macro.
553    //
554    // We expand the $key _after_ the $value since $key => $value leads to a parsing ambiguity.
555    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
556        json_internal_owned!(@object $object [@entries $($entries)* ($value => $($key)+) ] () ($($rest)*) ($($rest)*));
557    };
558
559    // Insert the last entry (without trailing comma) into the stack.
560    // At this point the recursion is complete and the entries can now be inserted.
561    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr)) => {
562        json_internal_owned!(@object $object [@entries $($entries)* ($value => $($key)+) ] () () ());
563    };
564
565    // Current entry followed by unexpected token.
566    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
567        json_unexpected!($unexpected);
568    };
569
570
571    // Next value is `null`.
572    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
573        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(null)) $($rest)*);
574    };
575
576    // Next value is `true`.
577    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
578        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(true)) $($rest)*);
579    };
580
581    // Next value is `false`.
582    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
583        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!(false)) $($rest)*);
584    };
585
586    // Next value is an array.
587    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
588        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!([$($array)*])) $($rest)*);
589    };
590
591    // Next value is a map.
592    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
593        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!({$($map)*})) $($rest)*);
594    };
595
596    // Next value is an expression followed by comma.
597    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
598        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!($value)) , $($rest)*);
599    };
600
601    // Last value is an expression with no trailing comma.
602    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr) $copy:tt) => {
603        json_internal_owned!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_owned!($value)));
604    };
605
606    // Missing value for last entry. Trigger a reasonable error message.
607    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (:) $copy:tt) => {
608        // "unexpected end of macro invocation"
609        json_internal_owned!();
610    };
611
612    // Missing colon and value for last entry. Trigger a reasonable error
613    // message.
614    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) () $copy:tt) => {
615        // "unexpected end of macro invocation"
616        json_internal_owned!();
617    };
618
619    // Misplaced colon. Trigger a reasonable error message.
620    (@object $object:ident [@entries $($entries:tt)*] () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
621        // Takes no arguments so "no rules expected the token `:`".
622        json_unexpected!($colon);
623    };
624
625    // Found a comma inside a key. Trigger a reasonable error message.
626    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
627        // Takes no arguments so "no rules expected the token `,`".
628        json_unexpected!($comma);
629    };
630
631    // Key is fully parenthesized. This avoids clippy double_parens false
632    // positives because the parenthesization may be necessary here.
633    (@object $object:ident [@entries $($entries:tt)*] () (($key:expr) : $($rest:tt)*) $copy:tt) => {
634        json_internal_owned!(@object $object [@entries $($entries)*] ($key) (: $($rest)*) (: $($rest)*));
635    };
636
637    // Munch a token into the current key.
638    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
639        json_internal_owned!(@object $object [@entries $($entries)*] ($($key)* $tt) ($($rest)*) ($($rest)*));
640    };
641
642    //////////////////////////////////////////////////////////////////////////
643    // The main implementation.
644    //
645    // Must be invoked as: json_internal!($($json)+)
646    //////////////////////////////////////////////////////////////////////////
647
648    (null) => {
649        $crate::value::owned::Value::Static($crate::StaticNode::Null)
650    };
651
652    (true) => {
653        $crate::value::owned::Value::Static($crate::StaticNode::Bool(true))
654    };
655
656    (false) => {
657        $crate::value::owned::Value::Static($crate::StaticNode::Bool(false))
658    };
659
660    ([]) => {
661        $crate::value::owned::Value::Array(Box::new(json_internal_vec![]))
662    };
663
664    ([ $($tt:tt)+ ]) => {
665        $crate::value::owned::Value::Array(Box::new(json_internal_owned!(@array [] $($tt)+)))
666    };
667
668    ({}) => {
669        {
670            use $crate::value::ValueBuilder;
671            $crate::value::owned::Value::object()
672        }
673    };
674
675    ({ $($tt:tt)+ }) => {
676        $crate::value::owned::Value::from({
677            let mut object;
678            json_internal_owned!(@object object [@entries] () ($($tt)+) ($($tt)+));
679            object
680        })
681    };
682
683    // Any Serialize type: numbers, strings, struct literals, variables etc.
684    // Must be below every other rule.
685    ($other:expr) => {
686        $crate::value::owned::Value::from($other)
687    };
688}
689
690// Rocket relies on this because they export their own `json!` with a different
691// doc comment than ours, and various Rust bugs prevent them from calling our
692// `json!` from their `json!` so they call `json_internal!` directly. Check with
693// @SergioBenitez before making breaking changes to this macro.
694//
695// Changes are fine as long as `json_internal!` does not call any new helper
696// macros and can still be invoked as `json_internal!($($json)+)`.
697#[cfg(feature = "serde_impl")]
698#[macro_export(local_inner_macros)]
699#[doc(hidden)]
700macro_rules! json_internal_borrowed {
701    //////////////////////////////////////////////////////////////////////////
702    // TT muncher for parsing the inside of an array [...]. Produces a vec![...]
703    // of the elements.
704    //
705    // Must be invoked as: json_internal_borrowed!(@array [] $($tt)*)
706    //////////////////////////////////////////////////////////////////////////
707
708    // Done with trailing comma.
709    (@array [$($elems:expr,)*]) => {
710        json_internal_vec![$($elems,)*]
711    };
712
713    // Done without trailing comma.
714    (@array [$($elems:expr),*]) => {
715        json_internal_vec![$($elems),*]
716    };
717
718    // Next element is `null`.
719    (@array [$($elems:expr,)*] null $($rest:tt)*) => {
720        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(null)] $($rest)*)
721    };
722
723    // Next element is `true`.
724    (@array [$($elems:expr,)*] true $($rest:tt)*) => {
725        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(true)] $($rest)*)
726    };
727
728    // Next element is `false`.
729    (@array [$($elems:expr,)*] false $($rest:tt)*) => {
730        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(false)] $($rest)*)
731    };
732
733    // Next element is an array.
734    (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
735        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!([$($array)*])] $($rest)*)
736    };
737
738    // Next element is a map.
739    (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
740        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!({$($map)*})] $($rest)*)
741    };
742
743    // Next element is an expression followed by comma.
744    (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
745        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!($next),] $($rest)*)
746    };
747
748    // Last element is an expression with no trailing comma.
749    (@array [$($elems:expr,)*] $last:expr) => {
750        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!($last)])
751    };
752
753    // Comma after the most recent element.
754    (@array [$($elems:expr),*] , $($rest:tt)*) => {
755        json_internal_borrowed!(@array [$($elems,)*] $($rest)*)
756    };
757
758    // Unexpected token after most recent element.
759    (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
760        json_unexpected!($unexpected)
761    };
762
763    //////////////////////////////////////////////////////////////////////////
764    // TT muncher for parsing the inside of an object {...}. Each entry is
765    // inserted into the given map variable. Entries are parsed from the TT
766    // and then inserted into a stack of entries to be appended all at once
767    // at the end, allowing us to pre-allocate the map.
768    //
769    // Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
770    //
771    // We require two copies of the input tokens so that we can match on one
772    // copy and trigger errors on the other copy.
773    //////////////////////////////////////////////////////////////////////////
774
775    // Done.
776    (@object $object:ident [@entries] () () ()) => {};
777
778    // Count the number of entries to insert.
779    // Modified version of https://docs.rs/halfbrown/0.1.11/src/halfbrown/macros.rs.html#46-62
780    (@object @count [@entries $(($value:expr => $($key:tt)+))*]) => {
781        <[()]>::len(&[$(json_internal_borrowed!(@object @count @single ($($key)+))),*])
782    };
783    (@object @count @single ($($key:tt)+)) => {()};
784
785    // Done. Insert all entries from the stack
786    (@object $object:ident [@entries $(($value:expr => $($key:tt)+))*] () () ()) => {
787        let len = json_internal_borrowed!(@object @count [@entries $(($value => $($key)+))*]);
788
789        $object = $crate::value::borrowed::Object::with_capacity_and_hasher(len, $crate::value::ObjectHasher::default());
790        $(
791            #[allow(clippy::let_underscore_drop)]
792            let _:Option<_> = $object.insert(($($key)+).into(), $value);
793        )*
794
795    };
796
797    // Insert the current entry (followed by trailing comma) into the stack.
798    // Entries are inserted in reverse order, the captured $entries is expanded first,
799    // keeping inserts in the same order that they're defined in the macro.
800    //
801    // We expand the $key _after_ the $value since $key => $value leads to a parsing ambiguity.
802    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
803        json_internal_borrowed!(@object $object [@entries $($entries)* ($value => $($key)+) ] () ($($rest)*) ($($rest)*));
804    };
805
806    // Insert the last entry (without trailing comma) into the stack.
807    // At this point the recursion is complete and the entries can now be inserted.
808    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr)) => {
809        json_internal_borrowed!(@object $object [@entries $($entries)* ($value => $($key)+) ] () () ());
810    };
811
812    // Current entry followed by unexpected token.
813    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
814        json_unexpected!($unexpected);
815    };
816
817
818    // Next value is `null`.
819    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
820        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(null)) $($rest)*);
821    };
822
823    // Next value is `true`.
824    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
825        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(true)) $($rest)*);
826    };
827
828    // Next value is `false`.
829    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
830        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(false)) $($rest)*);
831    };
832
833    // Next value is an array.
834    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
835        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!([$($array)*])) $($rest)*);
836    };
837
838    // Next value is a map.
839    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
840        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!({$($map)*})) $($rest)*);
841    };
842
843    // Next value is an expression followed by comma.
844    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
845        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!($value)) , $($rest)*);
846    };
847
848    // Last value is an expression with no trailing comma.
849    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr) $copy:tt) => {
850        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!($value)));
851    };
852
853    // Missing value for last entry. Trigger a reasonable error message.
854    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (:) $copy:tt) => {
855        // "unexpected end of macro invocation"
856        json_internal_borrowed!();
857    };
858
859    // Missing colon and value for last entry. Trigger a reasonable error
860    // message.
861    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) () $copy:tt) => {
862        // "unexpected end of macro invocation"
863        json_internal_borrowed!();
864    };
865
866    // Misplaced colon. Trigger a reasonable error message.
867    (@object $object:ident [@entries $($entries:tt)*] () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
868        // Takes no arguments so "no rules expected the token `:`".
869        json_unexpected!($colon);
870    };
871
872    // Found a comma inside a key. Trigger a reasonable error message.
873    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
874        // Takes no arguments so "no rules expected the token `,`".
875        json_unexpected!($comma);
876    };
877
878    // Key is fully parenthesized. This avoids clippy double_parens false
879    // positives because the parenthesization may be necessary here.
880    (@object $object:ident [@entries $($entries:tt)*] () (($key:expr) : $($rest:tt)*) $copy:tt) => {
881        json_internal_borrowed!(@object $object [@entries $($entries)*] ($key) (: $($rest)*) (: $($rest)*));
882    };
883
884    // Munch a token into the current key.
885    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
886        json_internal_borrowed!(@object $object [@entries $($entries)*] ($($key)* $tt) ($($rest)*) ($($rest)*));
887    };
888
889    //////////////////////////////////////////////////////////////////////////
890    // The main implementation.
891    //
892    // Must be invoked as: json_internal!($($json)+)
893    //////////////////////////////////////////////////////////////////////////
894
895    (null) => {
896        $crate::value::borrowed::Value::Static($crate::StaticNode::Null)
897    };
898
899    (true) => {
900        $crate::value::borrowed::Value::Static($crate::StaticNode::Bool(true))
901    };
902
903    (false) => {
904        $crate::value::borrowed::Value::Static($crate::StaticNode::Bool(false))
905    };
906
907    ([]) => {
908        $crate::value::borrowed::Value::Array(Box::new(json_internal_vec![]))
909    };
910
911    ([ $($tt:tt)+ ]) => {
912        $crate::value::borrowed::Value::Array(Box::new(json_internal_borrowed!(@array [] $($tt)+)))
913    };
914
915    ({}) => {
916        {
917            use $crate::value::ValueBuilder;
918            $crate::value::borrowed::Value::object()
919        }
920    };
921
922    ({ $($tt:tt)+ }) => {
923        $crate::value::borrowed::Value::from({
924            let mut object;
925            json_internal_borrowed!(@object object [@entries] () ($($tt)+) ($($tt)+));
926            object
927        })
928    };
929
930    // Any Serialize type: numbers, strings, struct literals, variables etc.
931    // Must be below every other rule.
932    ($other:expr) => {
933        $crate::serde::to_borrowed_value(&$other).expect("serde::to_borrowed_value")
934    };
935}
936
937#[cfg(not(feature = "serde_impl"))]
938#[macro_export(local_inner_macros)]
939#[doc(hidden)]
940macro_rules! json_internal_borrowed {
941    //////////////////////////////////////////////////////////////////////////
942    // TT muncher for parsing the inside of an array [...]. Produces a vec![...]
943    // of the elements.
944    //
945    // Must be invoked as: json_internal_borrowed!(@array [] $($tt)*)
946    //////////////////////////////////////////////////////////////////////////
947
948    // Done with trailing comma.
949    (@array [$($elems:expr,)*]) => {
950        json_internal_vec![$($elems,)*]
951    };
952
953    // Done without trailing comma.
954    (@array [$($elems:expr),*]) => {
955        json_internal_vec![$($elems),*]
956    };
957
958    // Next element is `null`.
959    (@array [$($elems:expr,)*] null $($rest:tt)*) => {
960        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(null)] $($rest)*)
961    };
962
963    // Next element is `true`.
964    (@array [$($elems:expr,)*] true $($rest:tt)*) => {
965        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(true)] $($rest)*)
966    };
967
968    // Next element is `false`.
969    (@array [$($elems:expr,)*] false $($rest:tt)*) => {
970        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!(false)] $($rest)*)
971    };
972
973    // Next element is an array.
974    (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
975        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!([$($array)*])] $($rest)*)
976    };
977
978    // Next element is a map.
979    (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
980        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!({$($map)*})] $($rest)*)
981    };
982
983    // Next element is an expression followed by comma.
984    (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
985        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!($next),] $($rest)*)
986    };
987
988    // Last element is an expression with no trailing comma.
989    (@array [$($elems:expr,)*] $last:expr) => {
990        json_internal_borrowed!(@array [$($elems,)* json_internal_borrowed!($last)])
991    };
992
993    // Comma after the most recent element.
994    (@array [$($elems:expr),*] , $($rest:tt)*) => {
995        json_internal_borrowed!(@array [$($elems,)*] $($rest)*)
996    };
997
998    // Unexpected token after most recent element.
999    (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
1000        json_unexpected!($unexpected)
1001    };
1002
1003    //////////////////////////////////////////////////////////////////////////
1004    // TT muncher for parsing the inside of an object {...}. Each entry is
1005    // inserted into the given map variable. Entries are parsed from the TT
1006    // and then inserted into a stack of entries to be appended all at once
1007    // at the end, allowing us to pre-allocate the map.
1008    //
1009    // Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
1010    //
1011    // We require two copies of the input tokens so that we can match on one
1012    // copy and trigger errors on the other copy.
1013    //////////////////////////////////////////////////////////////////////////
1014
1015    // Done.
1016    (@object $object:ident [@entries] () () ()) => {};
1017
1018    // Count the number of entries to insert.
1019    // Modified version of https://docs.rs/halfbrown/0.1.11/src/halfbrown/macros.rs.html#46-62
1020    (@object @count [@entries $(($value:expr => $($key:tt)+))*]) => {
1021        <[()]>::len(&[$(json_internal_borrowed!(@object @count @single ($($key)+))),*])
1022    };
1023    (@object @count @single ($($key:tt)+)) => {()};
1024
1025    // Done. Insert all entries from the stack
1026    (@object $object:ident [@entries $(($value:expr => $($key:tt)+))*] () () ()) => {
1027        let len = json_internal_borrowed!(@object @count [@entries $(($value => $($key)+))*]);
1028
1029        $object = $crate::value::borrowed::Object::with_capacity_and_hasher(len, $crate::value::ObjectHasher::default());
1030        $(
1031            #[allow(clippy::let_underscore_drop)]
1032            let _:Option<_> = $object.insert(($($key)+).into(), $value);
1033        )*
1034
1035    };
1036
1037    // Insert the current entry (followed by trailing comma) into the stack.
1038    // Entries are inserted in reverse order, the captured $entries is expanded first,
1039    // keeping inserts in the same order that they're defined in the macro.
1040    //
1041    // We expand the $key _after_ the $value since $key => $value leads to a parsing ambiguity.
1042    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
1043        json_internal_borrowed!(@object $object [@entries $($entries)* ($value => $($key)+) ] () ($($rest)*) ($($rest)*));
1044    };
1045
1046    // Insert the last entry (without trailing comma) into the stack.
1047    // At this point the recursion is complete and the entries can now be inserted.
1048    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr)) => {
1049        json_internal_borrowed!(@object $object [@entries $($entries)* ($value => $($key)+) ] () () ());
1050    };
1051
1052    // Current entry followed by unexpected token.
1053    (@object $object:ident [@entries $($entries:tt)*] [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
1054        json_unexpected!($unexpected);
1055    };
1056
1057
1058    // Next value is `null`.
1059    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
1060        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(null)) $($rest)*);
1061    };
1062
1063    // Next value is `true`.
1064    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
1065        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(true)) $($rest)*);
1066    };
1067
1068    // Next value is `false`.
1069    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
1070        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!(false)) $($rest)*);
1071    };
1072
1073    // Next value is an array.
1074    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
1075        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!([$($array)*])) $($rest)*);
1076    };
1077
1078    // Next value is a map.
1079    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
1080        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!({$($map)*})) $($rest)*);
1081    };
1082
1083    // Next value is an expression followed by comma.
1084    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
1085        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!($value)) , $($rest)*);
1086    };
1087
1088    // Last value is an expression with no trailing comma.
1089    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (: $value:expr) $copy:tt) => {
1090        json_internal_borrowed!(@object $object [@entries $($entries)*] [$($key)+] (json_internal_borrowed!($value)));
1091    };
1092
1093    // Missing value for last entry. Trigger a reasonable error message.
1094    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) (:) $copy:tt) => {
1095        // "unexpected end of macro invocation"
1096        json_internal_borrowed!();
1097    };
1098
1099    // Missing colon and value for last entry. Trigger a reasonable error
1100    // message.
1101    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)+) () $copy:tt) => {
1102        // "unexpected end of macro invocation"
1103        json_internal_borrowed!();
1104    };
1105
1106    // Misplaced colon. Trigger a reasonable error message.
1107    (@object $object:ident [@entries $($entries:tt)*] () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
1108        // Takes no arguments so "no rules expected the token `:`".
1109        json_unexpected!($colon);
1110    };
1111
1112    // Found a comma inside a key. Trigger a reasonable error message.
1113    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
1114        // Takes no arguments so "no rules expected the token `,`".
1115        json_unexpected!($comma);
1116    };
1117
1118    // Key is fully parenthesized. This avoids clippy double_parens false
1119    // positives because the parenthesization may be necessary here.
1120    (@object $object:ident [@entries $($entries:tt)*] () (($key:expr) : $($rest:tt)*) $copy:tt) => {
1121        json_internal_borrowed!(@object $object [@entries $($entries)*] ($key) (: $($rest)*) (: $($rest)*));
1122    };
1123
1124    // Munch a token into the current key.
1125    (@object $object:ident [@entries $($entries:tt)*] ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
1126        json_internal_borrowed!(@object $object [@entries $($entries)*] ($($key)* $tt) ($($rest)*) ($($rest)*));
1127    };
1128
1129    //////////////////////////////////////////////////////////////////////////
1130    // The main implementation.
1131    //
1132    // Must be invoked as: json_internal!($($json)+)
1133    //////////////////////////////////////////////////////////////////////////
1134
1135    (null) => {
1136        $crate::value::borrowed::Value::Static($crate::StaticNode::Null)
1137    };
1138
1139    (true) => {
1140        $crate::value::borrowed::Value::Static($crate::StaticNode::Bool(true))
1141    };
1142
1143    (false) => {
1144        $crate::value::borrowed::Value::Static($crate::StaticNode::Bool(false))
1145    };
1146
1147    ([]) => {
1148        $crate::value::borrowed::Value::Array(Box::new(json_internal_vec![]))
1149    };
1150
1151    ([ $($tt:tt)+ ]) => {
1152        $crate::value::borrowed::Value::Array(Box::new(json_internal_borrowed!(@array [] $($tt)+)))
1153    };
1154
1155    ({}) => {
1156        {
1157            use $crate::value::ValueBuilder;
1158            $crate::value::borrowed::Value::object()
1159        }
1160    };
1161
1162    ({ $($tt:tt)+ }) => {
1163        $crate::value::borrowed::Value::from({
1164            let mut object;
1165            json_internal_borrowed!(@object object [@entries] () ($($tt)+) ($($tt)+));
1166            object
1167        })
1168    };
1169
1170    // Any Serialize type: numbers, strings, struct literals, variables etc.
1171    // Must be below every other rule.
1172    ($other:expr) => {
1173        $crate::value::borrowed::Value::from($other)
1174    };
1175}
1176
1177// The json_internal macro above cannot invoke vec directly because it uses
1178// local_inner_macros. A vec invocation there would resolve to $crate::vec.
1179// Instead invoke vec here outside of local_inner_macros.
1180#[macro_export]
1181#[doc(hidden)]
1182macro_rules! json_internal_vec {
1183    ($($content:tt)*) => {
1184        vec![$($content)*]
1185    };
1186}
1187
1188#[macro_export]
1189#[doc(hidden)]
1190macro_rules! json_unexpected {
1191    () => {};
1192}
1193
1194/// possible compiler hint that a branch is likely
1195#[cfg(feature = "hints")]
1196#[macro_export]
1197macro_rules! likely {
1198    ($e:expr) => {
1199        ::std::intrinsics::likely($e)
1200    };
1201}
1202
1203/// possible compiler hint that a branch is unlikely
1204#[cfg(feature = "hints")]
1205#[macro_export]
1206macro_rules! unlikely {
1207    ($e:expr) => {{
1208        ::std::intrinsics::unlikely($e)
1209    }};
1210}
1211
1212/// possible compiler hint that a branch is likely
1213///
1214/// Technique borrowed from here: <https://github.com/rust-lang/hashbrown/pull/209>
1215#[cfg(not(feature = "hints"))]
1216#[macro_export]
1217macro_rules! likely {
1218    ($e:expr) => {{
1219        #[inline]
1220        #[cold]
1221        fn cold() {}
1222
1223        let cond = $e;
1224
1225        if !cond {
1226            cold();
1227        }
1228
1229        cond
1230    }};
1231}
1232
1233/// possible compiler hint that a branch is unlikely
1234///
1235/// Technique borrowed from here: <https://github.com/rust-lang/hashbrown/pull/209>
1236#[cfg(not(feature = "hints"))]
1237#[macro_export]
1238macro_rules! unlikely {
1239    ($e:expr) => {{
1240        #[inline]
1241        #[cold]
1242        fn cold() {}
1243
1244        let cond = $e;
1245
1246        if cond {
1247            cold();
1248        }
1249
1250        cond
1251    }};
1252}
1253
1254/// static cast to an i8
1255#[macro_export]
1256macro_rules! static_cast_i8 {
1257    ($v:expr) => {
1258        ::std::transmute::<_, i8>($v)
1259    };
1260}
1261
1262/// static cast to an i32
1263#[macro_export]
1264macro_rules! static_cast_i32 {
1265    ($v:expr) => {
1266        ::std::mem::transmute::<u32, i32>($v)
1267    };
1268}
1269
1270/// static cast to an u32
1271#[macro_export]
1272macro_rules! static_cast_u32 {
1273    ($v:expr) => {
1274        ::std::mem::transmute::<_, u32>($v)
1275    };
1276}
1277
1278/// static cast to an i64
1279#[macro_export]
1280macro_rules! static_cast_i64 {
1281    ($v:expr) => {
1282        ::std::mem::transmute::<u64, i64>($v)
1283    };
1284}
1285
1286/// static cast to an i64
1287#[macro_export]
1288macro_rules! static_cast_i128 {
1289    ($v:expr) => {
1290        ::std::mem::transmute::<_, i128>($v)
1291    };
1292}
1293
1294/// static cast to an u64
1295#[macro_export]
1296macro_rules! static_cast_u64 {
1297    ($v:expr) => {
1298        ::std::mem::transmute::<i64, u64>($v)
1299    };
1300}
1301
1302/// Custom `try!` macro that does no `From` conversions
1303///
1304/// FROM serde-json
1305/// We only use our own error type; no need for From conversions provided by the
1306/// standard library's try! macro. This reduces lines of LLVM IR by 4%.
1307#[macro_export]
1308macro_rules! stry {
1309    ($e:expr) => {
1310        match $e {
1311            ::std::result::Result::Ok(val) => val,
1312            ::std::result::Result::Err(err) => return ::std::result::Result::Err(err),
1313        }
1314    };
1315}
1316
1317#[cfg(test)]
1318mod test {
1319    use crate::prelude::*;
1320    use crate::{BorrowedValue, OwnedValue};
1321
1322    #[cfg(feature = "serde_impl")]
1323    fn owned_test_map() -> OwnedValue {
1324        let mut h = crate::owned::Object::with_hasher(crate::ObjectHasher::default());
1325        h.insert("test".into(), 1.into());
1326        OwnedValue::from(h)
1327    }
1328    #[cfg(feature = "serde_impl")]
1329    fn borrowed_test_map() -> BorrowedValue<'static> {
1330        let mut h = crate::borrowed::Object::with_hasher(crate::ObjectHasher::default());
1331        h.insert("test".into(), 1.into());
1332        BorrowedValue::from(h)
1333    }
1334
1335    #[test]
1336    fn array() {
1337        let v: OwnedValue = json!(vec![1]);
1338        assert_eq!(OwnedValue::from(vec![1_u64]), v);
1339        let v: OwnedValue = json!([1]);
1340        assert_eq!(BorrowedValue::from(vec![1_u64]), v);
1341        let v: OwnedValue = json!([]);
1342        assert_eq!(OwnedValue::array(), v);
1343    }
1344
1345    #[cfg(feature = "serde_impl")]
1346    #[test]
1347    fn obj() {
1348        use halfbrown::hashmap;
1349        let o = owned_test_map();
1350        let v: OwnedValue = json!(hashmap! {"test" => 1});
1351        assert_eq!(o, v);
1352        let v: OwnedValue = json!({"test": 1});
1353        assert_eq!(o, v);
1354        let v: OwnedValue = json!({});
1355        assert_eq!(OwnedValue::object(), v);
1356    }
1357
1358    #[test]
1359    fn array_typed_owned() {
1360        let v: OwnedValue = json_typed!(owned, vec![1]);
1361        assert_eq!(OwnedValue::from(vec![1_u64]), v);
1362        let v: OwnedValue = json_typed!(owned, [1]);
1363        assert_eq!(OwnedValue::from(vec![1_u64]), v);
1364        let v: OwnedValue = json_typed!(owned, []);
1365        assert_eq!(OwnedValue::array(), v);
1366    }
1367
1368    #[test]
1369    fn array_typed_borrowed() {
1370        let v: BorrowedValue = json_typed!(borrowed, vec![1]);
1371        assert_eq!(BorrowedValue::from(vec![1_u64]), v);
1372        let v: BorrowedValue = json_typed!(borrowed, [1]);
1373        assert_eq!(BorrowedValue::from(vec![1_u64]), v);
1374        let v: BorrowedValue = json_typed!(borrowed, []);
1375        assert_eq!(BorrowedValue::array(), v);
1376    }
1377    #[cfg(feature = "serde_impl")]
1378    #[test]
1379    fn obj_typed_owned() {
1380        use halfbrown::hashmap;
1381        let v: OwnedValue = json_typed!(owned, hashmap! {"test" => 1});
1382        let o = owned_test_map();
1383        assert_eq!(o, v);
1384        let v: OwnedValue = json_typed!(owned, {"test": 1});
1385        assert_eq!(o, v);
1386        let v: OwnedValue = json_typed!(owned, {});
1387        assert_eq!(OwnedValue::object(), v);
1388    }
1389
1390    #[cfg(feature = "serde_impl")]
1391    #[test]
1392    fn obj_typed_borrowed() {
1393        use halfbrown::hashmap;
1394        let v: BorrowedValue = json_typed!(borrowed, hashmap! {"test" => 1});
1395        let o = borrowed_test_map();
1396        assert_eq!(o, v);
1397        let v: BorrowedValue = json_typed!(borrowed, {"test": 1});
1398        assert_eq!(o, v);
1399        let v: BorrowedValue = json_typed!(borrowed, {});
1400        assert_eq!(BorrowedValue::object(), v);
1401    }
1402}