Skip to main content

json_bourne/
macros.rs

1//! `from_json!` — declarative macro that emits a struct or enum together
2//! with its [`FromJson`] impl.
3//!
4//! This is the zero-dep alternative to a `#[derive(FromJson)]` proc
5//! macro. The crate's core promise is no external deps; a proc-macro
6//! crate would need `proc-macro2` / `quote` / `syn`. `macro_rules!`
7//! lives inside `json-bourne` itself, so the dep graph stays empty.
8//!
9//! # Usage
10//!
11//! ```
12//! use json_bourne::{from_json, parse_str};
13//!
14//! from_json! {
15//!     #[derive(Debug, PartialEq)]
16//!     struct User<'input> {
17//!         id: u64,
18//!         name: &'input str,
19//!         active: bool,
20//!         nickname: Option<&'input str>,
21//!     }
22//! }
23//!
24//! let u: User<'_> = parse_str(r#"{"id":1,"name":"a","active":true}"#).unwrap();
25//! assert_eq!(u.nickname, None);
26//! ```
27//!
28//! # Strategy notes for maintainers
29//!
30//! `macro_rules!` has two traps that shape the design here:
31//!
32//! 1. **`:ty` capture is opaque downstream.** Once a type is captured
33//!    via a `:ty` fragment specifier, splicing it into another macro's
34//!    `tt`-pattern does not re-tokenize it — it remains a single
35//!    opaque "type token" that downstream literal patterns like
36//!    `Option<...>` cannot peek inside. So Option-vs-required
37//!    detection must happen *during the same walk* where the type's
38//!    individual tokens are still visible.
39//!
40//! 2. **Greedy `$($t:tt)+` swallows commas.** A naive
41//!    `$fname:ident : $($fty:tt)+ , $($rest:tt)*` pattern doesn't
42//!    work because `$($fty:tt)+` greedily eats commas it could match
43//!    against `,`. The reliable workaround is a *tt-muncher*: walk
44//!    one token at a time, accumulate into a "current type"
45//!    accumulator until a `,` literal is hit, then commit and recurse.
46//!
47//! The body-walking macro below is one tt-muncher per field that
48//! emits all three things (slot decl, key dispatch arm, final
49//! assignment) at once, so each field is touched only once and the
50//! type tokens are pattern-matchable for Option detection at every
51//! step.
52
53/// Emit a struct or enum together with its [`FromJson`](crate::FromJson) impl.
54///
55/// See the module-level docs for the supported shapes and limitations.
56#[macro_export]
57macro_rules! from_json {
58    // -----------------------------------------------------------------
59    // Lenient named-field struct (deny_unknown_fields = false), no generics.
60    //
61    // The container attribute must appear *first* among the outer
62    // attrs. macro_rules! cannot pattern-match attrs after the fact
63    // (each arm is a fixed prefix), so the literal placement matters.
64    // -----------------------------------------------------------------
65    (
66        #[bourne(deny_unknown_fields = false)]
67        $(#[$attr:meta])*
68        $vis:vis struct $name:ident { $($body:tt)* }
69    ) => {
70        $crate::__from_json_emit_struct_def!(
71            attrs: { $(#[$attr])* },
72            vis: $vis,
73            name: $name,
74            generics_def: (),
75            body: ($($body)*)
76        );
77
78        impl<'input> $crate::FromJson<'input> for $name {
79            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
80                $crate::__from_json_named_body!(__lex, (Self), lenient, $($body)*)
81            }
82        }
83    };
84
85    // Lenient + one lifetime.
86    (
87        #[bourne(deny_unknown_fields = false)]
88        $(#[$attr:meta])*
89        $vis:vis struct $name:ident < $lt:lifetime $(,)? > { $($body:tt)* }
90    ) => {
91        $crate::__from_json_emit_struct_def!(
92            attrs: { $(#[$attr])* },
93            vis: $vis,
94            name: $name,
95            generics_def: (<$lt>),
96            body: ($($body)*)
97        );
98
99        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
100            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
101                $crate::__from_json_named_body!(__lex, (Self), lenient, $($body)*)
102            }
103        }
104    };
105
106    // -----------------------------------------------------------------
107    // Named-field struct, no generics.
108    // -----------------------------------------------------------------
109    (
110        $(#[$attr:meta])*
111        $vis:vis struct $name:ident { $($body:tt)* }
112    ) => {
113        $crate::__from_json_emit_struct_def!(
114            attrs: { $(#[$attr])* },
115            vis: $vis,
116            name: $name,
117            generics_def: (),
118            body: ($($body)*)
119        );
120
121        impl<'input> $crate::FromJson<'input> for $name {
122            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
123                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
124            }
125        }
126    };
127
128    // -----------------------------------------------------------------
129    // Named-field struct with one lifetime.
130    // -----------------------------------------------------------------
131    (
132        $(#[$attr:meta])*
133        $vis:vis struct $name:ident < $lt:lifetime $(,)? > { $($body:tt)* }
134    ) => {
135        $crate::__from_json_emit_struct_def!(
136            attrs: { $(#[$attr])* },
137            vis: $vis,
138            name: $name,
139            generics_def: (<$lt>),
140            body: ($($body)*)
141        );
142
143        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
144            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
145                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
146            }
147        }
148    };
149
150    // -----------------------------------------------------------------
151    // Named-field struct with lifetime + one type param (bounded or not).
152    // -----------------------------------------------------------------
153    (
154        $(#[$attr:meta])*
155        $vis:vis struct $name:ident < $lt:lifetime, $tp:ident $(: $($tb:tt)+)? $(,)? > { $($body:tt)* }
156    ) => {
157        $crate::__from_json_emit_struct_def!(
158            attrs: { $(#[$attr])* },
159            vis: $vis,
160            name: $name,
161            generics_def: (<$lt, $tp $(: $($tb)+)?>),
162            body: ($($body)*)
163        );
164
165        impl<$lt, $tp> $crate::FromJson<$lt> for $name<$lt, $tp>
166        where
167            $tp: $crate::FromJson<$lt> $($(+ $tb)+)?,
168        {
169            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
170                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
171            }
172        }
173    };
174
175    // -----------------------------------------------------------------
176    // Named-field struct with one type param (no lifetime).
177    // -----------------------------------------------------------------
178    (
179        $(#[$attr:meta])*
180        $vis:vis struct $name:ident < $tp:ident $(: $($tb:tt)+)? $(,)? > { $($body:tt)* }
181    ) => {
182        $crate::__from_json_emit_struct_def!(
183            attrs: { $(#[$attr])* },
184            vis: $vis,
185            name: $name,
186            generics_def: (<$tp $(: $($tb)+)?>),
187            body: ($($body)*)
188        );
189
190        impl<'input, $tp> $crate::FromJson<'input> for $name<$tp>
191        where
192            $tp: $crate::FromJson<'input> $($(+ $tb)+)?,
193        {
194            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
195                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
196            }
197        }
198    };
199
200    // -----------------------------------------------------------------
201    // Tuple struct, no generics, newtype (single field).
202    //
203    // Parses a *bare* JSON value of the inner type (matches serde's
204    // `#[serde(transparent)]` default for newtypes).
205    // -----------------------------------------------------------------
206    (
207        $(#[$attr:meta])*
208        $vis:vis struct $name:ident ( $fty:ty $(,)? ) ;
209    ) => {
210        $(#[$attr])*
211        $vis struct $name($fty);
212
213        impl<'input> $crate::FromJson<'input> for $name {
214            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
215                ::core::result::Result::Ok(Self(
216                    <$fty as $crate::FromJson<'_>>::from_lex(__lex)?,
217                ))
218            }
219        }
220    };
221
222    // -----------------------------------------------------------------
223    // Tuple struct with one lifetime, newtype.
224    //
225    // The lifetime threads through into the inner type's borrow chain
226    // (e.g. `BorrowedTag<'input>(&'input str)`).
227    // -----------------------------------------------------------------
228    (
229        $(#[$attr:meta])*
230        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty:ty $(,)? ) ;
231    ) => {
232        $(#[$attr])*
233        $vis struct $name<$lt>($fty);
234
235        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
236            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
237                ::core::result::Result::Ok(Self(
238                    <$fty as $crate::FromJson<$lt>>::from_lex(__lex)?,
239                ))
240            }
241        }
242    };
243
244    // -----------------------------------------------------------------
245    // Tuple struct, multi-field. No generics.
246    //
247    // Parses a JSON array of exactly N elements, where N is the number
248    // of declared fields. The element-walker emits per-element reads
249    // separated by `array_continue` checks; the closing-bracket check
250    // after the last element rejects "array too long" inputs.
251    // -----------------------------------------------------------------
252    (
253        $(#[$attr:meta])*
254        $vis:vis struct $name:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
255    ) => {
256        $(#[$attr])*
257        $vis struct $name($fty1, $($ftyn),+);
258
259        impl<'input> $crate::FromJson<'input> for $name {
260            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
261                if __lex.array_start()? {
262                    return ::core::result::Result::Err(
263                        $crate::Error::new($crate::ErrorKind::TypeMismatch, __lex.position()),
264                    );
265                }
266                let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex(__lex)?;
267                $crate::__from_json_tuple_walk!(
268                    lex: __lex,
269                    self_ctor: (Self),
270                    accum: [ __elem_0 ],
271                    remaining: [ $(($ftyn))+ ]
272                )
273            }
274        }
275    };
276
277    // Tuple struct, multi-field, with one lifetime.
278    (
279        $(#[$attr:meta])*
280        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
281    ) => {
282        $(#[$attr])*
283        $vis struct $name<$lt>($fty1, $($ftyn),+);
284
285        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
286            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
287                if __lex.array_start()? {
288                    return ::core::result::Result::Err(
289                        $crate::Error::new($crate::ErrorKind::TypeMismatch, __lex.position()),
290                    );
291                }
292                let __elem_0 = <$fty1 as $crate::FromJson<$lt>>::from_lex(__lex)?;
293                $crate::__from_json_tuple_walk!(
294                    lex: __lex,
295                    self_ctor: (Self),
296                    accum: [ __elem_0 ],
297                    remaining: [ $(($ftyn))+ ]
298                )
299            }
300        }
301    };
302
303    // -----------------------------------------------------------------
304    // Untagged enum, no generics.
305    //
306    // Container attribute `#[bourne(untagged)]` parses by trial: each
307    // variant is attempted in declaration order; the first one that
308    // parses successfully wins. On failure the lexer is restored to
309    // the value's start before the next attempt.
310    //
311    // JSON shapes per variant:
312    //   - Unit `Foo`            → JSON `null`
313    //   - Newtype `Foo(T)`      → bare `T`
314    //   - Tuple `Foo(T, U)`     → `[T, U]`
315    //   - Struct `Foo {a, b}`   → `{"a": ..., "b": ...}`
316    //
317    // Order matters: variants overlapping in shape (e.g. two newtype
318    // variants where both inner types accept the same JSON) resolve
319    // to the first one declared.
320    // -----------------------------------------------------------------
321    (
322        #[bourne(untagged)]
323        $(#[$attr:meta])*
324        $vis:vis enum $name:ident { $($variants:tt)* }
325    ) => {
326        $crate::__from_json_emit_enum_def!(
327            attrs: { $(#[$attr])* },
328            vis: $vis,
329            name: $name,
330            generics_def: (),
331            variants_input: ($($variants)*)
332        );
333
334        impl<'input> $crate::FromJson<'input> for $name {
335            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
336                $crate::__from_json_untagged_dispatch!(__lex, $name, ($($variants)*))
337            }
338        }
339    };
340
341    // Untagged enum, one lifetime.
342    (
343        #[bourne(untagged)]
344        $(#[$attr:meta])*
345        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
346    ) => {
347        $crate::__from_json_emit_enum_def!(
348            attrs: { $(#[$attr])* },
349            vis: $vis,
350            name: $name,
351            generics_def: (<$lt>),
352            variants_input: ($($variants)*)
353        );
354
355        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
356            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
357                $crate::__from_json_untagged_dispatch!(__lex, $name, ($($variants)*))
358            }
359        }
360    };
361
362    // -----------------------------------------------------------------
363    // Adjacently-tagged enum, no generics.
364    //
365    // Container attribute `#[bourne(tag = "t", content = "c")]` puts
366    // the discriminator and payload in two sibling fields:
367    //
368    //   {"t": "Foo", "c": <payload>}
369    //   {"t": "Bar"}                  // unit — content absent
370    //
371    // Field order is not significant. All variant shapes are
372    // supported (unit, newtype, tuple, struct), unlike the
373    // internally-tagged case.
374    // -----------------------------------------------------------------
375    (
376        #[bourne(tag = $tag:literal, content = $content:literal)]
377        $(#[$attr:meta])*
378        $vis:vis enum $name:ident { $($variants:tt)* }
379    ) => {
380        $crate::__from_json_emit_enum_def!(
381            attrs: { $(#[$attr])* },
382            vis: $vis,
383            name: $name,
384            generics_def: (),
385            variants_input: ($($variants)*)
386        );
387
388        impl<'input> $crate::FromJson<'input> for $name {
389            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
390                $crate::__from_json_adjacently_tagged_dispatch!(
391                    __lex, $name, $tag, $content, ($($variants)*)
392                )
393            }
394        }
395    };
396
397    // Adjacently-tagged enum, one lifetime.
398    (
399        #[bourne(tag = $tag:literal, content = $content:literal)]
400        $(#[$attr:meta])*
401        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
402    ) => {
403        $crate::__from_json_emit_enum_def!(
404            attrs: { $(#[$attr])* },
405            vis: $vis,
406            name: $name,
407            generics_def: (<$lt>),
408            variants_input: ($($variants)*)
409        );
410
411        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
412            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
413                $crate::__from_json_adjacently_tagged_dispatch!(
414                    __lex, $name, $tag, $content, ($($variants)*)
415                )
416            }
417        }
418    };
419
420    // -----------------------------------------------------------------
421    // Internally-tagged enum, no generics.
422    //
423    // Container attribute `#[bourne(tag = "type")]` makes the variant
424    // discriminator a sibling field of the variant's own fields:
425    //
426    //   {"type": "Foo", "a": 1, "b": 2}   // → Foo { a: 1, b: 2 }
427    //   {"type": "Bar"}                    // → Bar (unit)
428    //
429    // Container attribute must appear *first* among outer attrs (same
430    // rule as `deny_unknown_fields = false`): macro_rules! arms match
431    // a fixed prefix.
432    //
433    // Supported variant shapes: unit and struct-variant only. Newtype
434    // and tuple variants do not have a coherent internally-tagged
435    // representation (the discriminator would have to live inside the
436    // newtype payload, which conflicts with the payload's own shape);
437    // serde rejects them too.
438    // -----------------------------------------------------------------
439    (
440        #[bourne(tag = $tag:literal)]
441        $(#[$attr:meta])*
442        $vis:vis enum $name:ident { $($variants:tt)* }
443    ) => {
444        $crate::__from_json_emit_enum_def!(
445            attrs: { $(#[$attr])* },
446            vis: $vis,
447            name: $name,
448            generics_def: (),
449            variants_input: ($($variants)*)
450        );
451
452        impl<'input> $crate::FromJson<'input> for $name {
453            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
454                $crate::__from_json_internally_tagged_dispatch!(
455                    __lex, $name, $tag, ($($variants)*)
456                )
457            }
458        }
459    };
460
461    // Internally-tagged enum, one lifetime.
462    (
463        #[bourne(tag = $tag:literal)]
464        $(#[$attr:meta])*
465        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
466    ) => {
467        $crate::__from_json_emit_enum_def!(
468            attrs: { $(#[$attr])* },
469            vis: $vis,
470            name: $name,
471            generics_def: (<$lt>),
472            variants_input: ($($variants)*)
473        );
474
475        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
476            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
477                $crate::__from_json_internally_tagged_dispatch!(
478                    __lex, $name, $tag, ($($variants)*)
479                )
480            }
481        }
482    };
483
484    // -----------------------------------------------------------------
485    // Externally-tagged enum, no generics.
486    //
487    // JSON shape per variant:
488    //   - Unit `Foo`             → string `"Foo"`
489    //   - Newtype `Foo(T)`       → object `{"Foo": <T>}`
490    //   - Tuple `Foo(T, U)`      → object `{"Foo": [<T>, <U>]}`
491    //   - Struct `Foo {a, b}`    → object `{"Foo": {"a": …, "b": …}}`
492    //
493    // Variant-level `#[bourne(rename = "...")]` retags the variant.
494    // -----------------------------------------------------------------
495    (
496        $(#[$attr:meta])*
497        $vis:vis enum $name:ident { $($variants:tt)* }
498    ) => {
499        $crate::__from_json_emit_enum_def!(
500            attrs: { $(#[$attr])* },
501            vis: $vis,
502            name: $name,
503            generics_def: (),
504            variants_input: ($($variants)*)
505        );
506
507        impl<'input> $crate::FromJson<'input> for $name {
508            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
509                $crate::__from_json_enum_dispatch!(__lex, $name, ($($variants)*))
510            }
511        }
512    };
513
514    // Externally-tagged enum, one lifetime.
515    (
516        $(#[$attr:meta])*
517        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
518    ) => {
519        $crate::__from_json_emit_enum_def!(
520            attrs: { $(#[$attr])* },
521            vis: $vis,
522            name: $name,
523            generics_def: (<$lt>),
524            variants_input: ($($variants)*)
525        );
526
527        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
528            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
529                $crate::__from_json_enum_dispatch!(__lex, $name, ($($variants)*))
530            }
531        }
532    };
533}
534
535// ============================================================================
536// Struct-definition emitter (with field-attribute strip).
537//
538// Walks the body tt-stream and produces a clean struct definition
539// where `#[bourne(...)]` attrs have been removed but every other attr
540// (including `#[doc = "..."]`, user-written `#[allow(...)]`, etc.) is
541// preserved on the field. The impl walker downstream re-walks the
542// same body to extract the bourne-attr metadata for slot decls,
543// dispatch arms, and final assignments.
544//
545// Two walks over the same body is wasteful in macro-expansion terms
546// but simpler than threading both outputs through one combined
547// walker. The body is bounded by the user's struct definition, so
548// the constant factor is small.
549//
550// State:
551//   - kept: the stripped body emitted so far
552//   - cur:  per-field accumulator for "attrs we'll keep on this field"
553//   - input: remaining tokens
554// ============================================================================
555
556#[doc(hidden)]
557#[macro_export]
558macro_rules! __from_json_emit_struct_def {
559    (
560        attrs: { $(#[$attr:meta])* },
561        vis: $vis:vis,
562        name: $name:ident,
563        generics_def: (),
564        body: ($($body:tt)*)
565    ) => {
566        $crate::__from_json_strip_walk!(
567            done: {
568                attrs: { $(#[$attr])* },
569                vis: $vis,
570                name: $name,
571                generics: ()
572            },
573            kept: { },
574            cur: [],
575            input: ($($body)*)
576        );
577    };
578    (
579        attrs: { $(#[$attr:meta])* },
580        vis: $vis:vis,
581        name: $name:ident,
582        generics_def: (<$lt:lifetime>),
583        body: ($($body:tt)*)
584    ) => {
585        $crate::__from_json_strip_walk!(
586            done: {
587                attrs: { $(#[$attr])* },
588                vis: $vis,
589                name: $name,
590                generics: (<$lt>)
591            },
592            kept: { },
593            cur: [],
594            input: ($($body)*)
595        );
596    };
597    (
598        attrs: { $(#[$attr:meta])* },
599        vis: $vis:vis,
600        name: $name:ident,
601        generics_def: (<$tp:ident $(: $($tb:tt)+)?>),
602        body: ($($body:tt)*)
603    ) => {
604        $crate::__from_json_strip_walk!(
605            done: {
606                attrs: { $(#[$attr])* },
607                vis: $vis,
608                name: $name,
609                generics: (<$tp $(: $($tb)+)?>)
610            },
611            kept: { },
612            cur: [],
613            input: ($($body)*)
614        );
615    };
616    (
617        attrs: { $(#[$attr:meta])* },
618        vis: $vis:vis,
619        name: $name:ident,
620        generics_def: (<$lt:lifetime, $tp:ident $(: $($tb:tt)+)?>),
621        body: ($($body:tt)*)
622    ) => {
623        $crate::__from_json_strip_walk!(
624            done: {
625                attrs: { $(#[$attr])* },
626                vis: $vis,
627                name: $name,
628                generics: (<$lt, $tp $(: $($tb)+)?>)
629            },
630            kept: { },
631            cur: [],
632            input: ($($body)*)
633        );
634    };
635}
636
637// Strip-pass walker. Eats tokens from `input`. When it sees a
638// `#[bourne(...)]` group, drops it. When it sees any other `#[...]`
639// group, appends it to `cur` (per-field). When it reaches the field
640// name + colon + type tokens up to a comma, commits `cur + field` to
641// `kept` and starts the next field.
642//
643// At end-of-input, splices `kept` into the struct definition.
644#[doc(hidden)]
645#[macro_export]
646macro_rules! __from_json_strip_walk {
647    // Done: emit the struct.
648    (
649        done: {
650            attrs: { $(#[$outer:meta])* },
651            vis: $vis:vis,
652            name: $name:ident,
653            generics: ()
654        },
655        kept: { $($kept:tt)* },
656        cur: [],
657        input: ()
658    ) => {
659        $(#[$outer])*
660        $vis struct $name { $($kept)* }
661    };
662    (
663        done: {
664            attrs: { $(#[$outer:meta])* },
665            vis: $vis:vis,
666            name: $name:ident,
667            generics: ($($g:tt)+)
668        },
669        kept: { $($kept:tt)* },
670        cur: [],
671        input: ()
672    ) => {
673        $(#[$outer])*
674        $vis struct $name $($g)+ { $($kept)* }
675    };
676
677    // bourne(rename = "x") attribute: drop it.
678    (
679        done: $done:tt,
680        kept: { $($kept:tt)* },
681        cur: [ $($cur:tt)* ],
682        input: ( #[bourne(rename = $_lit:literal)] $($rest:tt)* )
683    ) => {
684        $crate::__from_json_strip_walk!(
685            done: $done,
686            kept: { $($kept)* },
687            cur: [ $($cur)* ],
688            input: ($($rest)*)
689        );
690    };
691    // bourne(default) attribute: drop it.
692    (
693        done: $done:tt,
694        kept: { $($kept:tt)* },
695        cur: [ $($cur:tt)* ],
696        input: ( #[bourne(default)] $($rest:tt)* )
697    ) => {
698        $crate::__from_json_strip_walk!(
699            done: $done,
700            kept: { $($kept)* },
701            cur: [ $($cur)* ],
702            input: ($($rest)*)
703        );
704    };
705    // bourne(default = "fn") attribute: drop it.
706    (
707        done: $done:tt,
708        kept: { $($kept:tt)* },
709        cur: [ $($cur:tt)* ],
710        input: ( #[bourne(default = $_path:literal)] $($rest:tt)* )
711    ) => {
712        $crate::__from_json_strip_walk!(
713            done: $done,
714            kept: { $($kept)* },
715            cur: [ $($cur)* ],
716            input: ($($rest)*)
717        );
718    };
719    // bourne(skip) attribute: drop it.
720    (
721        done: $done:tt,
722        kept: { $($kept:tt)* },
723        cur: [ $($cur:tt)* ],
724        input: ( #[bourne(skip)] $($rest:tt)* )
725    ) => {
726        $crate::__from_json_strip_walk!(
727            done: $done,
728            kept: { $($kept)* },
729            cur: [ $($cur)* ],
730            input: ($($rest)*)
731        );
732    };
733    // bourne(skip_if_none) attribute: drop it. Ser-side only, no-op
734    // for parsing (the field is just an Option<T> that defaults to
735    // None when absent), but the attr has to be strippable so the
736    // emitted struct def doesn't carry it.
737    (
738        done: $done:tt,
739        kept: { $($kept:tt)* },
740        cur: [ $($cur:tt)* ],
741        input: ( #[bourne(skip_if_none)] $($rest:tt)* )
742    ) => {
743        $crate::__from_json_strip_walk!(
744            done: $done,
745            kept: { $($kept)* },
746            cur: [ $($cur)* ],
747            input: ($($rest)*)
748        );
749    };
750    // bourne(rename = "x", default) compound: drop it.
751    (
752        done: $done:tt,
753        kept: { $($kept:tt)* },
754        cur: [ $($cur:tt)* ],
755        input: ( #[bourne(rename = $_lit:literal, default)] $($rest:tt)* )
756    ) => {
757        $crate::__from_json_strip_walk!(
758            done: $done,
759            kept: { $($kept)* },
760            cur: [ $($cur)* ],
761            input: ($($rest)*)
762        );
763    };
764    // Any other `#[...]` attribute: keep it on `cur`.
765    (
766        done: $done:tt,
767        kept: { $($kept:tt)* },
768        cur: [ $($cur:tt)* ],
769        input: ( #[$other:meta] $($rest:tt)* )
770    ) => {
771        $crate::__from_json_strip_walk!(
772            done: $done,
773            kept: { $($kept)* },
774            cur: [ $($cur)* #[$other] ],
775            input: ($($rest)*)
776        );
777    };
778
779    // Field with vis + name + colon + type ending at `,`.
780    // Use `:ty` here (the *struct definition* is a context where
781    // collapsed type tokens are fine — we re-emit them verbatim).
782    (
783        done: $done:tt,
784        kept: { $($kept:tt)* },
785        cur: [ $($cur:tt)* ],
786        input: ( $fvis:vis $fname:ident : $fty:ty , $($rest:tt)* )
787    ) => {
788        $crate::__from_json_strip_walk!(
789            done: $done,
790            kept: {
791                $($kept)*
792                $($cur)* $fvis $fname: $fty,
793            },
794            cur: [],
795            input: ($($rest)*)
796        );
797    };
798    // Last field, no trailing comma.
799    (
800        done: $done:tt,
801        kept: { $($kept:tt)* },
802        cur: [ $($cur:tt)* ],
803        input: ( $fvis:vis $fname:ident : $fty:ty )
804    ) => {
805        $crate::__from_json_strip_walk!(
806            done: $done,
807            kept: {
808                $($kept)*
809                $($cur)* $fvis $fname: $fty,
810            },
811            cur: [],
812            input: ()
813        );
814    };
815}
816
817// ============================================================================
818// Enum-definition emitter (with variant-attribute strip).
819//
820// Walks the variant list and produces a clean enum definition where
821// `#[bourne(rename = "...")]` attrs have been removed but every other
822// attr is preserved. Same two-walk approach as the named-struct
823// strip pass.
824// ============================================================================
825
826#[doc(hidden)]
827#[macro_export]
828macro_rules! __from_json_emit_enum_def {
829    (
830        attrs: { $(#[$attr:meta])* },
831        vis: $vis:vis,
832        name: $name:ident,
833        generics_def: (),
834        variants_input: ($($variants:tt)*)
835    ) => {
836        $crate::__from_json_enum_strip!(
837            done: {
838                attrs: { $(#[$attr])* },
839                vis: $vis,
840                name: $name,
841                generics: ()
842            },
843            kept: { },
844            cur: [],
845            input: ($($variants)*)
846        );
847    };
848    (
849        attrs: { $(#[$attr:meta])* },
850        vis: $vis:vis,
851        name: $name:ident,
852        generics_def: (<$lt:lifetime>),
853        variants_input: ($($variants:tt)*)
854    ) => {
855        $crate::__from_json_enum_strip!(
856            done: {
857                attrs: { $(#[$attr])* },
858                vis: $vis,
859                name: $name,
860                generics: (<$lt>)
861            },
862            kept: { },
863            cur: [],
864            input: ($($variants)*)
865        );
866    };
867}
868
869// Strip-pass walker for enums. State:
870//   - kept: stripped variants emitted so far
871//   - cur: per-variant accumulator for kept attrs
872//   - input: remaining tokens
873//
874// Variant body recognition:
875//   - `(types)` (paren group) — tuple/newtype variant
876//   - `{fields}` (brace group) — struct variant
877//   - neither — unit variant
878//
879// macro_rules! groups parens and braces as single tt items, so we
880// can match the body shape via separate arms.
881#[doc(hidden)]
882#[macro_export]
883macro_rules! __from_json_enum_strip {
884    // Done.
885    (
886        done: {
887            attrs: { $(#[$outer:meta])* },
888            vis: $vis:vis,
889            name: $name:ident,
890            generics: ()
891        },
892        kept: { $($kept:tt)* },
893        cur: [],
894        input: ()
895    ) => {
896        $(#[$outer])*
897        $vis enum $name { $($kept)* }
898    };
899    (
900        done: {
901            attrs: { $(#[$outer:meta])* },
902            vis: $vis:vis,
903            name: $name:ident,
904            generics: ($($g:tt)+)
905        },
906        kept: { $($kept:tt)* },
907        cur: [],
908        input: ()
909    ) => {
910        $(#[$outer])*
911        $vis enum $name $($g)+ { $($kept)* }
912    };
913
914    // bourne(rename = "x") on the next variant: drop it.
915    (
916        done: $done:tt,
917        kept: { $($kept:tt)* },
918        cur: [ $($cur:tt)* ],
919        input: ( #[bourne(rename = $_lit:literal)] $($rest:tt)* )
920    ) => {
921        $crate::__from_json_enum_strip!(
922            done: $done,
923            kept: { $($kept)* },
924            cur: [ $($cur)* ],
925            input: ($($rest)*)
926        );
927    };
928    // Other attribute: keep on cur.
929    (
930        done: $done:tt,
931        kept: { $($kept:tt)* },
932        cur: [ $($cur:tt)* ],
933        input: ( #[$other:meta] $($rest:tt)* )
934    ) => {
935        $crate::__from_json_enum_strip!(
936            done: $done,
937            kept: { $($kept)* },
938            cur: [ $($cur)* #[$other] ],
939            input: ($($rest)*)
940        );
941    };
942
943    // Unit variant followed by `,`.
944    (
945        done: $done:tt,
946        kept: { $($kept:tt)* },
947        cur: [ $($cur:tt)* ],
948        input: ( $vname:ident , $($rest:tt)* )
949    ) => {
950        $crate::__from_json_enum_strip!(
951            done: $done,
952            kept: { $($kept)* $($cur)* $vname, },
953            cur: [],
954            input: ($($rest)*)
955        );
956    };
957    // Unit variant, last (no trailing comma).
958    (
959        done: $done:tt,
960        kept: { $($kept:tt)* },
961        cur: [ $($cur:tt)* ],
962        input: ( $vname:ident )
963    ) => {
964        $crate::__from_json_enum_strip!(
965            done: $done,
966            kept: { $($kept)* $($cur)* $vname, },
967            cur: [],
968            input: ()
969        );
970    };
971
972    // Tuple/newtype variant (parenthesized body) with trailing `,`.
973    (
974        done: $done:tt,
975        kept: { $($kept:tt)* },
976        cur: [ $($cur:tt)* ],
977        input: ( $vname:ident ( $($body:tt)* ) , $($rest:tt)* )
978    ) => {
979        $crate::__from_json_enum_strip!(
980            done: $done,
981            kept: { $($kept)* $($cur)* $vname($($body)*), },
982            cur: [],
983            input: ($($rest)*)
984        );
985    };
986    // Tuple/newtype variant, last.
987    (
988        done: $done:tt,
989        kept: { $($kept:tt)* },
990        cur: [ $($cur:tt)* ],
991        input: ( $vname:ident ( $($body:tt)* ) )
992    ) => {
993        $crate::__from_json_enum_strip!(
994            done: $done,
995            kept: { $($kept)* $($cur)* $vname($($body)*), },
996            cur: [],
997            input: ()
998        );
999    };
1000
1001    // Struct variant (brace body) with trailing `,`.
1002    //
1003    // The body may contain `#[bourne(...)]` field attrs that must
1004    // also be stripped; route the body through the named-struct
1005    // strip walker by pre-emitting it here as opaque tokens, since
1006    // bourne attrs on inner fields are forbidden inside enum struct
1007    // variants for v1 (the proc-macro version's design supported
1008    // them but `macro_rules!` recursion with a separate output sink
1009    // for the body would balloon the macro size; v1 punts).
1010    (
1011        done: $done:tt,
1012        kept: { $($kept:tt)* },
1013        cur: [ $($cur:tt)* ],
1014        input: ( $vname:ident { $($body:tt)* } , $($rest:tt)* )
1015    ) => {
1016        $crate::__from_json_enum_strip!(
1017            done: $done,
1018            kept: { $($kept)* $($cur)* $vname { $($body)* }, },
1019            cur: [],
1020            input: ($($rest)*)
1021        );
1022    };
1023    // Struct variant, last.
1024    (
1025        done: $done:tt,
1026        kept: { $($kept:tt)* },
1027        cur: [ $($cur:tt)* ],
1028        input: ( $vname:ident { $($body:tt)* } )
1029    ) => {
1030        $crate::__from_json_enum_strip!(
1031            done: $done,
1032            kept: { $($kept)* $($cur)* $vname { $($body)* }, },
1033            cur: [],
1034            input: ()
1035        );
1036    };
1037}
1038
1039// ============================================================================
1040// Enum dispatch (impl side).
1041//
1042// Walks the variant list once to build:
1043//   - unit_arms: match arms for the JSON-string ValueKind
1044//   - tagged_arms: match arms for the JSON-object ValueKind
1045//
1046// At end-of-input, splices both into a `match peek_value_kind` block
1047// with a `_ => TypeMismatch` catchall.
1048// ============================================================================
1049
1050#[doc(hidden)]
1051#[macro_export]
1052macro_rules! __from_json_enum_dispatch {
1053    ($lex:ident, $name:ident, ($($variants:tt)*)) => {
1054        $crate::__from_json_enum_walk!(
1055            lex: $lex,
1056            name: $name,
1057            unit_arms: { },
1058            tagged_arms: { },
1059            cur_rename: (),
1060            has_tagged: (),
1061            input: ($($variants)*)
1062        )
1063    };
1064}
1065
1066#[doc(hidden)]
1067#[macro_export]
1068macro_rules! __from_json_enum_walk {
1069    // Done — all-unit enum: skip the Object dispatch entirely (it
1070    // would be empty and would generate `unreachable_code` warnings).
1071    (
1072        lex: $lex:ident,
1073        name: $name:ident,
1074        unit_arms: { $($unit:tt)* },
1075        tagged_arms: { },
1076        cur_rename: (),
1077        has_tagged: (),
1078        input: ()
1079    ) => {
1080        match $lex.peek_value_kind()? {
1081            $crate::ValueKind::String => {
1082                let __tag = $lex.parse_str_value()?;
1083                match __tag {
1084                    $($unit)*
1085                    _ => ::core::result::Result::Err(
1086                        $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1087                    ),
1088                }
1089            }
1090            _ => ::core::result::Result::Err(
1091                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
1092            ),
1093        }
1094    };
1095
1096    // Done — has at least one tagged variant: full String + Object dispatch.
1097    (
1098        lex: $lex:ident,
1099        name: $name:ident,
1100        unit_arms: { $($unit:tt)* },
1101        tagged_arms: { $($tagged:tt)* },
1102        cur_rename: (),
1103        has_tagged: ($_h:tt $($_hrest:tt)*),
1104        input: ()
1105    ) => {
1106        match $lex.peek_value_kind()? {
1107            $crate::ValueKind::String => {
1108                let __tag = $lex.parse_str_value()?;
1109                match __tag {
1110                    $($unit)*
1111                    _ => ::core::result::Result::Err(
1112                        $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1113                    ),
1114                }
1115            }
1116            $crate::ValueKind::Object => {
1117                $lex.object_start()?;
1118                let __key_js = $lex.object_first_key_lex()?.ok_or_else(|| {
1119                    $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position())
1120                })?;
1121                let __key_cow = $crate::key_to_cow(__key_js, $lex)?;
1122                let __value = match __key_cow.as_ref() {
1123                    $($tagged)*
1124                    _ => return ::core::result::Result::Err(
1125                        $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1126                    ),
1127                };
1128                if $lex.object_next_key_lex()?.is_some() {
1129                    return ::core::result::Result::Err(
1130                        $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1131                    );
1132                }
1133                ::core::result::Result::Ok(__value)
1134            }
1135            _ => ::core::result::Result::Err(
1136                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
1137            ),
1138        }
1139    };
1140
1141    // bourne(rename = "x") on the next variant.
1142    (
1143        lex: $lex:ident,
1144        name: $name:ident,
1145        unit_arms: $u:tt,
1146        tagged_arms: $t:tt,
1147        cur_rename: (),
1148        has_tagged: ($($h:tt)*),
1149        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
1150    ) => {
1151        $crate::__from_json_enum_walk!(
1152            lex: $lex,
1153            name: $name,
1154            unit_arms: $u,
1155            tagged_arms: $t,
1156            cur_rename: ($renamed),
1157            has_tagged: ($($h)*),
1158            input: ($($rest)*)
1159        )
1160    };
1161
1162    // Skip other attributes on the variant.
1163    (
1164        lex: $lex:ident,
1165        name: $name:ident,
1166        unit_arms: $u:tt,
1167        tagged_arms: $t:tt,
1168        cur_rename: ($($rename:tt)?),
1169        has_tagged: ($($h:tt)*),
1170        input: ( #[$_other:meta] $($rest:tt)* )
1171    ) => {
1172        $crate::__from_json_enum_walk!(
1173            lex: $lex,
1174            name: $name,
1175            unit_arms: $u,
1176            tagged_arms: $t,
1177            cur_rename: ($($rename)?),
1178            has_tagged: ($($h)*),
1179            input: ($($rest)*)
1180        )
1181    };
1182
1183    // Unit variant followed by `,`.
1184    (
1185        lex: $lex:ident,
1186        name: $name:ident,
1187        unit_arms: { $($u:tt)* },
1188        tagged_arms: $t:tt,
1189        cur_rename: ($($rename:tt)?),
1190        has_tagged: ($($h:tt)*),
1191        input: ( $vname:ident , $($rest:tt)* )
1192    ) => {
1193        $crate::__from_json_enum_walk!(
1194            lex: $lex,
1195            name: $name,
1196            unit_arms: {
1197                $($u)*
1198                $crate::__from_json_field_key!($vname, ($($rename)?))
1199                    => ::core::result::Result::Ok($name::$vname),
1200            },
1201            tagged_arms: $t,
1202            cur_rename: (),
1203            has_tagged: ($($h)*),
1204            input: ($($rest)*)
1205        )
1206    };
1207    // Unit variant, last.
1208    (
1209        lex: $lex:ident,
1210        name: $name:ident,
1211        unit_arms: { $($u:tt)* },
1212        tagged_arms: $t:tt,
1213        cur_rename: ($($rename:tt)?),
1214        has_tagged: ($($h:tt)*),
1215        input: ( $vname:ident )
1216    ) => {
1217        $crate::__from_json_enum_walk!(
1218            lex: $lex,
1219            name: $name,
1220            unit_arms: {
1221                $($u)*
1222                $crate::__from_json_field_key!($vname, ($($rename)?))
1223                    => ::core::result::Result::Ok($name::$vname),
1224            },
1225            tagged_arms: $t,
1226            cur_rename: (),
1227            has_tagged: ($($h)*),
1228            input: ()
1229        )
1230    };
1231
1232    // Newtype variant (single-element tuple).
1233    (
1234        lex: $lex:ident,
1235        name: $name:ident,
1236        unit_arms: $u:tt,
1237        tagged_arms: { $($t:tt)* },
1238        cur_rename: ($($rename:tt)?),
1239        has_tagged: ($($h:tt)*),
1240        input: ( $vname:ident ( $fty:ty $(,)? ) , $($rest:tt)* )
1241    ) => {
1242        $crate::__from_json_enum_walk!(
1243            lex: $lex,
1244            name: $name,
1245            unit_arms: $u,
1246            tagged_arms: {
1247                $($t)*
1248                $crate::__from_json_field_key!($vname, ($($rename)?)) => $name::$vname(
1249                    <$fty as $crate::FromJson<'_>>::from_lex($lex)?,
1250                ),
1251            },
1252            cur_rename: (),
1253            has_tagged: ($($h)* ()),
1254            input: ($($rest)*)
1255        )
1256    };
1257    (
1258        lex: $lex:ident,
1259        name: $name:ident,
1260        unit_arms: $u:tt,
1261        tagged_arms: { $($t:tt)* },
1262        cur_rename: ($($rename:tt)?),
1263        has_tagged: ($($h:tt)*),
1264        input: ( $vname:ident ( $fty:ty $(,)? ) )
1265    ) => {
1266        $crate::__from_json_enum_walk!(
1267            lex: $lex,
1268            name: $name,
1269            unit_arms: $u,
1270            tagged_arms: {
1271                $($t)*
1272                $crate::__from_json_field_key!($vname, ($($rename)?)) => $name::$vname(
1273                    <$fty as $crate::FromJson<'_>>::from_lex($lex)?,
1274                ),
1275            },
1276            cur_rename: (),
1277            has_tagged: ($($h)* ()),
1278            input: ()
1279        )
1280    };
1281
1282    // Multi-field tuple variant.
1283    (
1284        lex: $lex:ident,
1285        name: $name:ident,
1286        unit_arms: $u:tt,
1287        tagged_arms: { $($t:tt)* },
1288        cur_rename: ($($rename:tt)?),
1289        has_tagged: ($($h:tt)*),
1290        input: ( $vname:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) , $($rest:tt)* )
1291    ) => {
1292        $crate::__from_json_enum_walk!(
1293            lex: $lex,
1294            name: $name,
1295            unit_arms: $u,
1296            tagged_arms: {
1297                $($t)*
1298                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1299                    if $lex.array_start()? {
1300                        return ::core::result::Result::Err(
1301                            $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
1302                        );
1303                    }
1304                    let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex($lex)?;
1305                    $crate::__from_json_tuple_walk!(
1306                        lex: $lex,
1307                        self_ctor: ($name::$vname),
1308                        accum: [ __elem_0 ],
1309                        remaining: [ $(($ftyn))+ ]
1310                    )?
1311                },
1312            },
1313            cur_rename: (),
1314            has_tagged: ($($h)* ()),
1315            input: ($($rest)*)
1316        )
1317    };
1318    (
1319        lex: $lex:ident,
1320        name: $name:ident,
1321        unit_arms: $u:tt,
1322        tagged_arms: { $($t:tt)* },
1323        cur_rename: ($($rename:tt)?),
1324        has_tagged: ($($h:tt)*),
1325        input: ( $vname:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) )
1326    ) => {
1327        $crate::__from_json_enum_walk!(
1328            lex: $lex,
1329            name: $name,
1330            unit_arms: $u,
1331            tagged_arms: {
1332                $($t)*
1333                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1334                    if $lex.array_start()? {
1335                        return ::core::result::Result::Err(
1336                            $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
1337                        );
1338                    }
1339                    let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex($lex)?;
1340                    $crate::__from_json_tuple_walk!(
1341                        lex: $lex,
1342                        self_ctor: ($name::$vname),
1343                        accum: [ __elem_0 ],
1344                        remaining: [ $(($ftyn))+ ]
1345                    )?
1346                },
1347            },
1348            cur_rename: (),
1349            has_tagged: ($($h)* ()),
1350            input: ()
1351        )
1352    };
1353
1354    // Struct variant.
1355    (
1356        lex: $lex:ident,
1357        name: $name:ident,
1358        unit_arms: $u:tt,
1359        tagged_arms: { $($t:tt)* },
1360        cur_rename: ($($rename:tt)?),
1361        has_tagged: ($($h:tt)*),
1362        input: ( $vname:ident { $($body:tt)* } , $($rest:tt)* )
1363    ) => {
1364        $crate::__from_json_enum_walk!(
1365            lex: $lex,
1366            name: $name,
1367            unit_arms: $u,
1368            tagged_arms: {
1369                $($t)*
1370                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1371                    $crate::__from_json_named_body!(
1372                        $lex,
1373                        ($name::$vname),
1374                        strict,
1375                        $($body)*
1376                    )?
1377                },
1378            },
1379            cur_rename: (),
1380            has_tagged: ($($h)* ()),
1381            input: ($($rest)*)
1382        )
1383    };
1384    (
1385        lex: $lex:ident,
1386        name: $name:ident,
1387        unit_arms: $u:tt,
1388        tagged_arms: { $($t:tt)* },
1389        cur_rename: ($($rename:tt)?),
1390        has_tagged: ($($h:tt)*),
1391        input: ( $vname:ident { $($body:tt)* } )
1392    ) => {
1393        $crate::__from_json_enum_walk!(
1394            lex: $lex,
1395            name: $name,
1396            unit_arms: $u,
1397            tagged_arms: {
1398                $($t)*
1399                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1400                    $crate::__from_json_named_body!(
1401                        $lex,
1402                        ($name::$vname),
1403                        strict,
1404                        $($body)*
1405                    )?
1406                },
1407            },
1408            cur_rename: (),
1409            has_tagged: ($($h)* ()),
1410            input: ()
1411        )
1412    };
1413}
1414
1415// ============================================================================
1416// Internally-tagged enum dispatch.
1417//
1418// Strategy: open the object, snapshot the lexer right after `{`, walk
1419// keys until we find the tag (parsing+restoring per non-tag value),
1420// read the tag's string value, then restore the snapshot and re-enter
1421// the variant's named-body parser with a "skip this one key by name"
1422// hint so the tag itself is consumed without complaint.
1423//
1424// The "find tag" pass parses non-tag values via `skip_value`, which is
1425// O(value-size) — for typical `{"type": "...", ...payload...}` shapes
1426// where the tag is the first key, that's a no-op and the second pass
1427// reads each value once. Worst case (tag is the last key) we read the
1428// payload twice. That trade is the cost of avoiding a Value DOM here.
1429//
1430// State accumulators:
1431//   - unit_arms:   match arms keyed on tag string → `Ok(Variant)`
1432//   - struct_arms: match arms keyed on tag string → struct-variant body
1433//                  parser invocation (with tag-skip)
1434// ============================================================================
1435
1436#[doc(hidden)]
1437#[macro_export]
1438macro_rules! __from_json_internally_tagged_dispatch {
1439    ($lex:ident, $name:ident, $tag:literal, ($($variants:tt)*)) => {{
1440        // Snapshot the cursor before consuming `{` so the second pass
1441        // (variant body) can call `object_start()` again from a clean
1442        // state — restoring puts us back to "expect a JSON value at
1443        // the cursor" which is exactly what the variant body assumes.
1444        let __cp = $lex.checkpoint();
1445        $lex.object_start()?;
1446
1447        // Find-tag pass. The tag value is borrowed from the input
1448        // slice; restoring the lexer's cursor does not invalidate
1449        // borrows into the input (only `offset` and stack depth move,
1450        // the slice itself is unchanged).
1451        //
1452        // Limitation: the tag value goes through `parse_str_value`,
1453        // which rejects backslash escapes. A tag like `"Foo"`
1454        // therefore won't match the variant name `Foo`. This matches
1455        // the existing struct-field-name dispatch behavior; both are
1456        // raised together if/when we gain a `Cow<str>` decode path
1457        // here.
1458        let mut __maybe_key = $lex.object_first_key_lex()?;
1459        let __tag_value: &str = loop {
1460            let Some(__key_js) = __maybe_key else {
1461                return ::core::result::Result::Err(
1462                    $crate::Error::new($crate::ErrorKind::MissingField, $lex.position()),
1463                );
1464            };
1465            let __key_cow = $crate::key_to_cow(__key_js, $lex)?;
1466            if __key_cow.as_ref() == $tag {
1467                break $lex.parse_str_value()?;
1468            }
1469            $lex.skip_value()?;
1470            __maybe_key = $lex.object_next_key_lex()?;
1471        };
1472
1473        // Restore and dispatch on the tag.
1474        $lex.restore(__cp);
1475        $crate::__from_json_internally_tagged_walk!(
1476            lex: $lex,
1477            name: $name,
1478            tag_key: $tag,
1479            tag_value: (__tag_value),
1480            unit_arms: { },
1481            struct_arms: { },
1482            cur_rename: (),
1483            input: ($($variants)*)
1484        )
1485    }};
1486}
1487
1488#[doc(hidden)]
1489#[macro_export]
1490macro_rules! __from_json_internally_tagged_walk {
1491    // Done: emit the dispatch.
1492    (
1493        lex: $lex:ident,
1494        name: $name:ident,
1495        tag_key: $tag:literal,
1496        tag_value: ($tagval:ident),
1497        unit_arms: { $($u:tt)* },
1498        struct_arms: { $($s:tt)* },
1499        cur_rename: (),
1500        input: ()
1501    ) => {
1502        match $tagval {
1503            $($u)*
1504            $($s)*
1505            _ => ::core::result::Result::Err(
1506                $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1507            ),
1508        }
1509    };
1510
1511    // bourne(rename = "x") on the next variant.
1512    (
1513        lex: $lex:ident,
1514        name: $name:ident,
1515        tag_key: $tag:literal,
1516        tag_value: ($tagval:ident),
1517        unit_arms: $u:tt,
1518        struct_arms: $s:tt,
1519        cur_rename: (),
1520        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
1521    ) => {
1522        $crate::__from_json_internally_tagged_walk!(
1523            lex: $lex,
1524            name: $name,
1525            tag_key: $tag,
1526            tag_value: ($tagval),
1527            unit_arms: $u,
1528            struct_arms: $s,
1529            cur_rename: ($renamed),
1530            input: ($($rest)*)
1531        )
1532    };
1533
1534    // Skip other variant attributes.
1535    (
1536        lex: $lex:ident,
1537        name: $name:ident,
1538        tag_key: $tag:literal,
1539        tag_value: ($tagval:ident),
1540        unit_arms: $u:tt,
1541        struct_arms: $s:tt,
1542        cur_rename: ($($rename:tt)?),
1543        input: ( #[$_other:meta] $($rest:tt)* )
1544    ) => {
1545        $crate::__from_json_internally_tagged_walk!(
1546            lex: $lex,
1547            name: $name,
1548            tag_key: $tag,
1549            tag_value: ($tagval),
1550            unit_arms: $u,
1551            struct_arms: $s,
1552            cur_rename: ($($rename)?),
1553            input: ($($rest)*)
1554        )
1555    };
1556
1557    // Reject newtype variant.
1558    (
1559        lex: $lex:ident,
1560        name: $name:ident,
1561        tag_key: $tag:literal,
1562        tag_value: ($tagval:ident),
1563        unit_arms: $u:tt,
1564        struct_arms: $s:tt,
1565        cur_rename: ($($rename:tt)?),
1566        input: ( $vname:ident ( $($_body:tt)* ) $($rest:tt)* )
1567    ) => {
1568        ::core::compile_error!(
1569            "from_json! macro: internally-tagged enums (#[bourne(tag = \"...\")]) \
1570             do not support newtype or tuple variants. Only unit and struct variants \
1571             are allowed; the tag must be a sibling field of the variant's own \
1572             fields, which is not representable for a non-object payload."
1573        );
1574    };
1575
1576    // Unit variant followed by `,`.
1577    (
1578        lex: $lex:ident,
1579        name: $name:ident,
1580        tag_key: $tag:literal,
1581        tag_value: ($tagval:ident),
1582        unit_arms: { $($u:tt)* },
1583        struct_arms: $s:tt,
1584        cur_rename: ($($rename:tt)?),
1585        input: ( $vname:ident , $($rest:tt)* )
1586    ) => {
1587        $crate::__from_json_internally_tagged_walk!(
1588            lex: $lex,
1589            name: $name,
1590            tag_key: $tag,
1591            tag_value: ($tagval),
1592            unit_arms: {
1593                $($u)*
1594                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1595                    $crate::__from_json_internally_tagged_unit_body!($lex, $tag);
1596                    ::core::result::Result::Ok($name::$vname)
1597                },
1598            },
1599            struct_arms: $s,
1600            cur_rename: (),
1601            input: ($($rest)*)
1602        )
1603    };
1604    // Unit variant, last.
1605    (
1606        lex: $lex:ident,
1607        name: $name:ident,
1608        tag_key: $tag:literal,
1609        tag_value: ($tagval:ident),
1610        unit_arms: { $($u:tt)* },
1611        struct_arms: $s:tt,
1612        cur_rename: ($($rename:tt)?),
1613        input: ( $vname:ident )
1614    ) => {
1615        $crate::__from_json_internally_tagged_walk!(
1616            lex: $lex,
1617            name: $name,
1618            tag_key: $tag,
1619            tag_value: ($tagval),
1620            unit_arms: {
1621                $($u)*
1622                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1623                    $crate::__from_json_internally_tagged_unit_body!($lex, $tag);
1624                    ::core::result::Result::Ok($name::$vname)
1625                },
1626            },
1627            struct_arms: $s,
1628            cur_rename: (),
1629            input: ()
1630        )
1631    };
1632
1633    // Struct variant with trailing comma.
1634    (
1635        lex: $lex:ident,
1636        name: $name:ident,
1637        tag_key: $tag:literal,
1638        tag_value: ($tagval:ident),
1639        unit_arms: $u:tt,
1640        struct_arms: { $($s:tt)* },
1641        cur_rename: ($($rename:tt)?),
1642        input: ( $vname:ident { $($body:tt)* } , $($rest:tt)* )
1643    ) => {
1644        $crate::__from_json_internally_tagged_walk!(
1645            lex: $lex,
1646            name: $name,
1647            tag_key: $tag,
1648            tag_value: ($tagval),
1649            unit_arms: $u,
1650            struct_arms: {
1651                $($s)*
1652                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1653                    $crate::__from_json_named_body_skip_one!(
1654                        $lex,
1655                        ($name::$vname),
1656                        $tag,
1657                        $($body)*
1658                    )
1659                },
1660            },
1661            cur_rename: (),
1662            input: ($($rest)*)
1663        )
1664    };
1665    // Struct variant, last.
1666    (
1667        lex: $lex:ident,
1668        name: $name:ident,
1669        tag_key: $tag:literal,
1670        tag_value: ($tagval:ident),
1671        unit_arms: $u:tt,
1672        struct_arms: { $($s:tt)* },
1673        cur_rename: ($($rename:tt)?),
1674        input: ( $vname:ident { $($body:tt)* } )
1675    ) => {
1676        $crate::__from_json_internally_tagged_walk!(
1677            lex: $lex,
1678            name: $name,
1679            tag_key: $tag,
1680            tag_value: ($tagval),
1681            unit_arms: $u,
1682            struct_arms: {
1683                $($s)*
1684                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1685                    $crate::__from_json_named_body_skip_one!(
1686                        $lex,
1687                        ($name::$vname),
1688                        $tag,
1689                        $($body)*
1690                    )
1691                },
1692            },
1693            cur_rename: (),
1694            input: ()
1695        )
1696    };
1697}
1698
1699// Body-walk variant of __from_json_named_body that treats one specific
1700// key (`$skip_key`) as the tag-and-skip-it case rather than as
1701// "unknown". All other keys behave strict. Reuses the existing
1702// `__from_json_walk!` engine via a new `unknown:` mode value
1703// `tag_skip(...)`.
1704#[doc(hidden)]
1705#[macro_export]
1706macro_rules! __from_json_named_body_skip_one {
1707    ($lex:ident, ($($self_ctor:tt)+), $skip_key:literal, $($body:tt)*) => {
1708        $crate::__from_json_walk!(
1709            lex: $lex,
1710            ctor: ($($self_ctor)+),
1711            unknown: (tag_skip $skip_key),
1712            decls: { },
1713            arms: { },
1714            assigns: { },
1715            ftokens: [],
1716            cur_name: (),
1717            cur_rename: (),
1718            cur_default: (),
1719            input: ($($body)*)
1720        )
1721    };
1722}
1723
1724// Body for a unit variant in internally-tagged mode: the only other
1725// keys allowed are the tag itself (already validated). Any other key
1726// is `UnknownField`. The variant has been selected by the caller; we
1727// just need to drain the remaining keys.
1728#[doc(hidden)]
1729#[macro_export]
1730macro_rules! __from_json_internally_tagged_unit_body {
1731    ($lex:ident, $tag:literal) => {{
1732        $lex.object_start()?;
1733        let mut __maybe_key = $lex.object_first_key_lex()?;
1734        while let ::core::option::Option::Some(__key_js) = __maybe_key {
1735            let __key_cow = $crate::key_to_cow(__key_js, $lex)?;
1736            if __key_cow.as_ref() == $tag {
1737                $lex.skip_value()?;
1738            } else {
1739                return ::core::result::Result::Err($crate::Error::new(
1740                    $crate::ErrorKind::UnknownField,
1741                    $lex.position(),
1742                ));
1743            }
1744            __maybe_key = $lex.object_next_key_lex()?;
1745        }
1746    }};
1747}
1748
1749// ============================================================================
1750// Adjacently-tagged enum dispatch.
1751//
1752// Walk the object once, capturing:
1753//   - the tag string (borrowed from input — survives `restore` since
1754//     restore only moves the cursor, not the input slice itself)
1755//   - a checkpoint pointing at the content value (if a `content` key
1756//     is encountered), which we use to seek back for the variant body
1757//
1758// After the object closes, dispatch on the tag. Unit-variant arms
1759// reject any captured content; non-unit arms require it. The restore-
1760// to-content step puts the lexer back into "expecting one JSON value"
1761// state for the variant payload.
1762// ============================================================================
1763
1764#[doc(hidden)]
1765#[macro_export]
1766macro_rules! __from_json_adjacently_tagged_dispatch {
1767    ($lex:ident, $name:ident, $tag:literal, $content:literal, ($($variants:tt)*)) => {{
1768        $lex.object_start()?;
1769
1770        let mut __tag_value: ::core::option::Option<&str> = ::core::option::Option::None;
1771        let mut __content_cp: ::core::option::Option<$crate::Checkpoint> =
1772            ::core::option::Option::None;
1773
1774        let mut __maybe_key = $lex.object_first_key_lex()?;
1775        while let ::core::option::Option::Some(__key_js) = __maybe_key {
1776            let __key_cow = $crate::key_to_cow(__key_js, $lex)?;
1777            if __key_cow.as_ref() == $tag {
1778                if __tag_value.is_some() {
1779                    return ::core::result::Result::Err(
1780                        $crate::Error::new($crate::ErrorKind::DuplicateKey, $lex.position()),
1781                    );
1782                }
1783                __tag_value = ::core::option::Option::Some($lex.parse_str_value()?);
1784            } else if __key_cow.as_ref() == $content {
1785                if __content_cp.is_some() {
1786                    return ::core::result::Result::Err(
1787                        $crate::Error::new($crate::ErrorKind::DuplicateKey, $lex.position()),
1788                    );
1789                }
1790                __content_cp = ::core::option::Option::Some($lex.checkpoint());
1791                $lex.skip_value()?;
1792            } else {
1793                return ::core::result::Result::Err(
1794                    $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1795                );
1796            }
1797            __maybe_key = $lex.object_next_key_lex()?;
1798        }
1799
1800        let __tag = __tag_value.ok_or_else(|| {
1801            $crate::Error::new($crate::ErrorKind::MissingField, $lex.position())
1802        })?;
1803
1804        // Snapshot the post-object cursor (with depth back to 0). After
1805        // restoring inward to the content checkpoint and parsing the
1806        // payload, we restore here so the outer parser sees the lexer
1807        // at end-of-object and `finish()` accepts the input.
1808        let __post_cp = $lex.checkpoint();
1809
1810        let __value = $crate::__from_json_adjacently_tagged_walk!(
1811            lex: $lex,
1812            name: $name,
1813            tag_key: $tag,
1814            content_key: $content,
1815            tag_value: (__tag),
1816            content_cp: (__content_cp),
1817            arms: { },
1818            cur_rename: (),
1819            input: ($($variants)*)
1820        )?;
1821        $lex.restore(__post_cp);
1822        ::core::result::Result::Ok(__value)
1823    }};
1824}
1825
1826#[doc(hidden)]
1827#[macro_export]
1828macro_rules! __from_json_adjacently_tagged_walk {
1829    // Done — emit the dispatch.
1830    (
1831        lex: $lex:ident,
1832        name: $name:ident,
1833        tag_key: $tag:literal,
1834        content_key: $content:literal,
1835        tag_value: ($tagval:ident),
1836        content_cp: ($cp:ident),
1837        arms: { $($a:tt)* },
1838        cur_rename: (),
1839        input: ()
1840    ) => {
1841        match $tagval {
1842            $($a)*
1843            _ => ::core::result::Result::Err(
1844                $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1845            ),
1846        }
1847    };
1848
1849    // bourne(rename = "x") on the next variant.
1850    (
1851        lex: $lex:ident,
1852        name: $name:ident,
1853        tag_key: $tag:literal,
1854        content_key: $content:literal,
1855        tag_value: ($tagval:ident),
1856        content_cp: ($cp:ident),
1857        arms: $a:tt,
1858        cur_rename: (),
1859        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
1860    ) => {
1861        $crate::__from_json_adjacently_tagged_walk!(
1862            lex: $lex,
1863            name: $name,
1864            tag_key: $tag,
1865            content_key: $content,
1866            tag_value: ($tagval),
1867            content_cp: ($cp),
1868            arms: $a,
1869            cur_rename: ($renamed),
1870            input: ($($rest)*)
1871        )
1872    };
1873
1874    // Skip other variant attributes.
1875    (
1876        lex: $lex:ident,
1877        name: $name:ident,
1878        tag_key: $tag:literal,
1879        content_key: $content:literal,
1880        tag_value: ($tagval:ident),
1881        content_cp: ($cp:ident),
1882        arms: $a:tt,
1883        cur_rename: ($($rename:tt)?),
1884        input: ( #[$_other:meta] $($rest:tt)* )
1885    ) => {
1886        $crate::__from_json_adjacently_tagged_walk!(
1887            lex: $lex,
1888            name: $name,
1889            tag_key: $tag,
1890            content_key: $content,
1891            tag_value: ($tagval),
1892            content_cp: ($cp),
1893            arms: $a,
1894            cur_rename: ($($rename)?),
1895            input: ($($rest)*)
1896        )
1897    };
1898
1899    // Unit variant — content must NOT be present.
1900    (
1901        lex: $lex:ident,
1902        name: $name:ident,
1903        tag_key: $tag:literal,
1904        content_key: $content:literal,
1905        tag_value: ($tagval:ident),
1906        content_cp: ($cp:ident),
1907        arms: { $($a:tt)* },
1908        cur_rename: ($($rename:tt)?),
1909        input: ( $vname:ident $(, $($rest:tt)*)? )
1910    ) => {
1911        $crate::__from_json_adjacently_tagged_walk!(
1912            lex: $lex,
1913            name: $name,
1914            tag_key: $tag,
1915            content_key: $content,
1916            tag_value: ($tagval),
1917            content_cp: ($cp),
1918            arms: {
1919                $($a)*
1920                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1921                    if $cp.is_some() {
1922                        ::core::result::Result::Err(
1923                            $crate::Error::new($crate::ErrorKind::UnknownField, $lex.position()),
1924                        )
1925                    } else {
1926                        ::core::result::Result::Ok($name::$vname)
1927                    }
1928                },
1929            },
1930            cur_rename: (),
1931            input: ($($($rest)*)?)
1932        )
1933    };
1934
1935    // Newtype variant — content required, parsed bare.
1936    (
1937        lex: $lex:ident,
1938        name: $name:ident,
1939        tag_key: $tag:literal,
1940        content_key: $content:literal,
1941        tag_value: ($tagval:ident),
1942        content_cp: ($cp:ident),
1943        arms: { $($a:tt)* },
1944        cur_rename: ($($rename:tt)?),
1945        input: ( $vname:ident ( $fty:ty $(,)? ) $(, $($rest:tt)*)? )
1946    ) => {
1947        $crate::__from_json_adjacently_tagged_walk!(
1948            lex: $lex,
1949            name: $name,
1950            tag_key: $tag,
1951            content_key: $content,
1952            tag_value: ($tagval),
1953            content_cp: ($cp),
1954            arms: {
1955                $($a)*
1956                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1957                    match $cp {
1958                        ::core::option::Option::Some(__c) => {
1959                            $lex.restore(__c);
1960                            ::core::result::Result::Ok($name::$vname(
1961                                <$fty as $crate::FromJson<'_>>::from_lex($lex)?,
1962                            ))
1963                        }
1964                        ::core::option::Option::None => ::core::result::Result::Err(
1965                            $crate::Error::new($crate::ErrorKind::MissingField, $lex.position()),
1966                        ),
1967                    }
1968                },
1969            },
1970            cur_rename: (),
1971            input: ($($($rest)*)?)
1972        )
1973    };
1974
1975    // Multi-field tuple variant — content required, parsed as array.
1976    (
1977        lex: $lex:ident,
1978        name: $name:ident,
1979        tag_key: $tag:literal,
1980        content_key: $content:literal,
1981        tag_value: ($tagval:ident),
1982        content_cp: ($cp:ident),
1983        arms: { $($a:tt)* },
1984        cur_rename: ($($rename:tt)?),
1985        input: ( $vname:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) $(, $($rest:tt)*)? )
1986    ) => {
1987        $crate::__from_json_adjacently_tagged_walk!(
1988            lex: $lex,
1989            name: $name,
1990            tag_key: $tag,
1991            content_key: $content,
1992            tag_value: ($tagval),
1993            content_cp: ($cp),
1994            arms: {
1995                $($a)*
1996                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
1997                    match $cp {
1998                        ::core::option::Option::Some(__c) => {
1999                            $lex.restore(__c);
2000                            if $lex.array_start()? {
2001                                return ::core::result::Result::Err(
2002                                    $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2003                                );
2004                            }
2005                            let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex($lex)?;
2006                            $crate::__from_json_tuple_walk!(
2007                                lex: $lex,
2008                                self_ctor: ($name::$vname),
2009                                accum: [ __elem_0 ],
2010                                remaining: [ $(($ftyn))+ ]
2011                            )
2012                        }
2013                        ::core::option::Option::None => ::core::result::Result::Err(
2014                            $crate::Error::new($crate::ErrorKind::MissingField, $lex.position()),
2015                        ),
2016                    }
2017                },
2018            },
2019            cur_rename: (),
2020            input: ($($($rest)*)?)
2021        )
2022    };
2023
2024    // Struct variant — content required, parsed as nested object.
2025    (
2026        lex: $lex:ident,
2027        name: $name:ident,
2028        tag_key: $tag:literal,
2029        content_key: $content:literal,
2030        tag_value: ($tagval:ident),
2031        content_cp: ($cp:ident),
2032        arms: { $($a:tt)* },
2033        cur_rename: ($($rename:tt)?),
2034        input: ( $vname:ident { $($body:tt)* } $(, $($rest:tt)*)? )
2035    ) => {
2036        $crate::__from_json_adjacently_tagged_walk!(
2037            lex: $lex,
2038            name: $name,
2039            tag_key: $tag,
2040            content_key: $content,
2041            tag_value: ($tagval),
2042            content_cp: ($cp),
2043            arms: {
2044                $($a)*
2045                $crate::__from_json_field_key!($vname, ($($rename)?)) => {
2046                    match $cp {
2047                        ::core::option::Option::Some(__c) => {
2048                            $lex.restore(__c);
2049                            $crate::__from_json_named_body!(
2050                                $lex,
2051                                ($name::$vname),
2052                                strict,
2053                                $($body)*
2054                            )
2055                        }
2056                        ::core::option::Option::None => ::core::result::Result::Err(
2057                            $crate::Error::new($crate::ErrorKind::MissingField, $lex.position()),
2058                        ),
2059                    }
2060                },
2061            },
2062            cur_rename: (),
2063            input: ($($($rest)*)?)
2064        )
2065    };
2066}
2067
2068// ============================================================================
2069// Untagged enum dispatch.
2070//
2071// Take a checkpoint at the value's start, then for each variant:
2072//   1. Restore (no-op on first try).
2073//   2. Run a `(|| { ... })()` closure that parses the variant's JSON
2074//      shape and constructs the variant.
2075//   3. On `Ok`, return.
2076//   4. On `Err`, fall through to the next variant.
2077//
2078// If all variants fail, return a generic TypeMismatch error pointing
2079// at the value's start. We cannot return all candidate errors without
2080// allocating; this matches serde's untagged behavior.
2081// ============================================================================
2082
2083#[doc(hidden)]
2084#[macro_export]
2085macro_rules! __from_json_untagged_dispatch {
2086    ($lex:ident, $name:ident, ($($variants:tt)*)) => {{
2087        let __cp = $lex.checkpoint();
2088        $crate::__from_json_untagged_walk!(
2089            lex: $lex,
2090            name: $name,
2091            cp: (__cp),
2092            cur_rename: (),
2093            input: ($($variants)*)
2094        )
2095    }};
2096}
2097
2098#[doc(hidden)]
2099#[macro_export]
2100macro_rules! __from_json_untagged_walk {
2101    // Done — all variants tried, return generic error.
2102    (
2103        lex: $lex:ident,
2104        name: $name:ident,
2105        cp: ($cp:ident),
2106        cur_rename: (),
2107        input: ()
2108    ) => {
2109        ::core::result::Result::Err(
2110            $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2111        )
2112    };
2113
2114    // Skip rename attribute — irrelevant to untagged (no tag string).
2115    (
2116        lex: $lex:ident,
2117        name: $name:ident,
2118        cp: ($cp:ident),
2119        cur_rename: (),
2120        input: ( #[bourne(rename = $_renamed:literal)] $($rest:tt)* )
2121    ) => {
2122        $crate::__from_json_untagged_walk!(
2123            lex: $lex,
2124            name: $name,
2125            cp: ($cp),
2126            cur_rename: (),
2127            input: ($($rest)*)
2128        )
2129    };
2130
2131    // Skip other variant attributes.
2132    (
2133        lex: $lex:ident,
2134        name: $name:ident,
2135        cp: ($cp:ident),
2136        cur_rename: (),
2137        input: ( #[$_other:meta] $($rest:tt)* )
2138    ) => {
2139        $crate::__from_json_untagged_walk!(
2140            lex: $lex,
2141            name: $name,
2142            cp: ($cp),
2143            cur_rename: (),
2144            input: ($($rest)*)
2145        )
2146    };
2147
2148    // Unit variant — JSON null.
2149    (
2150        lex: $lex:ident,
2151        name: $name:ident,
2152        cp: ($cp:ident),
2153        cur_rename: (),
2154        input: ( $vname:ident $(, $($rest:tt)*)? )
2155    ) => {{
2156        $lex.restore($cp);
2157        let __try: ::core::result::Result<$name, $crate::Error> = (|| {
2158            <() as $crate::FromJson<'_>>::from_lex($lex)?;
2159            ::core::result::Result::Ok($name::$vname)
2160        })();
2161        if let ::core::result::Result::Ok(__v) = __try {
2162            ::core::result::Result::Ok(__v)
2163        } else {
2164            $crate::__from_json_untagged_walk!(
2165                lex: $lex,
2166                name: $name,
2167                cp: ($cp),
2168                cur_rename: (),
2169                input: ($($($rest)*)?)
2170            )
2171        }
2172    }};
2173
2174    // Newtype variant — bare inner value.
2175    (
2176        lex: $lex:ident,
2177        name: $name:ident,
2178        cp: ($cp:ident),
2179        cur_rename: (),
2180        input: ( $vname:ident ( $fty:ty $(,)? ) $(, $($rest:tt)*)? )
2181    ) => {{
2182        $lex.restore($cp);
2183        let __try: ::core::result::Result<$name, $crate::Error> = (|| {
2184            ::core::result::Result::Ok($name::$vname(
2185                <$fty as $crate::FromJson<'_>>::from_lex($lex)?,
2186            ))
2187        })();
2188        if let ::core::result::Result::Ok(__v) = __try {
2189            ::core::result::Result::Ok(__v)
2190        } else {
2191            $crate::__from_json_untagged_walk!(
2192                lex: $lex,
2193                name: $name,
2194                cp: ($cp),
2195                cur_rename: (),
2196                input: ($($($rest)*)?)
2197            )
2198        }
2199    }};
2200
2201    // Multi-field tuple variant — JSON array.
2202    (
2203        lex: $lex:ident,
2204        name: $name:ident,
2205        cp: ($cp:ident),
2206        cur_rename: (),
2207        input: ( $vname:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) $(, $($rest:tt)*)? )
2208    ) => {{
2209        $lex.restore($cp);
2210        let __try: ::core::result::Result<$name, $crate::Error> = (|| {
2211            if $lex.array_start()? {
2212                return ::core::result::Result::Err(
2213                    $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2214                );
2215            }
2216            let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex($lex)?;
2217            $crate::__from_json_tuple_walk!(
2218                lex: $lex,
2219                self_ctor: ($name::$vname),
2220                accum: [ __elem_0 ],
2221                remaining: [ $(($ftyn))+ ]
2222            )
2223        })();
2224        if let ::core::result::Result::Ok(__v) = __try {
2225            ::core::result::Result::Ok(__v)
2226        } else {
2227            $crate::__from_json_untagged_walk!(
2228                lex: $lex,
2229                name: $name,
2230                cp: ($cp),
2231                cur_rename: (),
2232                input: ($($($rest)*)?)
2233            )
2234        }
2235    }};
2236
2237    // Struct variant — JSON object.
2238    (
2239        lex: $lex:ident,
2240        name: $name:ident,
2241        cp: ($cp:ident),
2242        cur_rename: (),
2243        input: ( $vname:ident { $($body:tt)* } $(, $($rest:tt)*)? )
2244    ) => {{
2245        $lex.restore($cp);
2246        let __try: ::core::result::Result<$name, $crate::Error> = (|| {
2247            $crate::__from_json_named_body!(
2248                $lex,
2249                ($name::$vname),
2250                strict,
2251                $($body)*
2252            )
2253        })();
2254        if let ::core::result::Result::Ok(__v) = __try {
2255            ::core::result::Result::Ok(__v)
2256        } else {
2257            $crate::__from_json_untagged_walk!(
2258                lex: $lex,
2259                name: $name,
2260                cp: ($cp),
2261                cur_rename: (),
2262                input: ($($($rest)*)?)
2263            )
2264        }
2265    }};
2266}
2267
2268// ============================================================================
2269// Tuple struct element walker.
2270//
2271// State: `accum` holds the names of elements read so far; `remaining`
2272// holds the types still to read. Each step consumes one type from
2273// `remaining`, emits a `array_continue == false` check, reads the
2274// element via FromJson, and recurses. When `remaining` is empty,
2275// emits the closing `array_continue == true` check and constructs.
2276//
2277// The element naming is positional: `__elem_0`, `__elem_1`, ... up to
2278// `__elem_7`. Tuple structs of more than 8 fields are vanishingly rare
2279// in real code; we cap at 8 because each new ident has to be hand-
2280// minted in this macro (no concat_idents! on stable). If users hit the
2281// cap, they can hand-write the FromJson impl.
2282// ============================================================================
2283
2284#[doc(hidden)]
2285#[macro_export]
2286macro_rules! __from_json_tuple_walk {
2287    // Done — emit the closing check and the constructor.
2288    (
2289        lex: $lex:ident,
2290        self_ctor: ($($ctor:tt)+),
2291        accum: [ $($prev:ident),+ ],
2292        remaining: []
2293    ) => {{
2294        if !$lex.array_continue(b']')? {
2295            return ::core::result::Result::Err(
2296                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2297            );
2298        }
2299        ::core::result::Result::Ok($($ctor)+($($prev),+))
2300    }};
2301
2302    // Read next element. Position-based naming via inner sub-arms.
2303    (lex: $lex:ident, self_ctor: ($($ctor:tt)+), accum: [ $a:ident ], remaining: [ ($fty:ty) $($rest:tt)* ]) => {{
2304        if $lex.array_continue(b']')? {
2305            return ::core::result::Result::Err(
2306                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2307            );
2308        }
2309        let __elem_1 = <$fty as $crate::FromJson<'_>>::from_lex($lex)?;
2310        $crate::__from_json_tuple_walk!(
2311            lex: $lex, self_ctor: ($($ctor)+), accum: [ $a, __elem_1 ], remaining: [ $($rest)* ]
2312        )
2313    }};
2314    (lex: $lex:ident, self_ctor: ($($ctor:tt)+), accum: [ $a:ident, $b:ident ], remaining: [ ($fty:ty) $($rest:tt)* ]) => {{
2315        if $lex.array_continue(b']')? {
2316            return ::core::result::Result::Err(
2317                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2318            );
2319        }
2320        let __elem_2 = <$fty as $crate::FromJson<'_>>::from_lex($lex)?;
2321        $crate::__from_json_tuple_walk!(
2322            lex: $lex, self_ctor: ($($ctor)+), accum: [ $a, $b, __elem_2 ], remaining: [ $($rest)* ]
2323        )
2324    }};
2325    (lex: $lex:ident, self_ctor: ($($ctor:tt)+), accum: [ $a:ident, $b:ident, $c:ident ], remaining: [ ($fty:ty) $($rest:tt)* ]) => {{
2326        if $lex.array_continue(b']')? {
2327            return ::core::result::Result::Err(
2328                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2329            );
2330        }
2331        let __elem_3 = <$fty as $crate::FromJson<'_>>::from_lex($lex)?;
2332        $crate::__from_json_tuple_walk!(
2333            lex: $lex, self_ctor: ($($ctor)+), accum: [ $a, $b, $c, __elem_3 ], remaining: [ $($rest)* ]
2334        )
2335    }};
2336    (lex: $lex:ident, self_ctor: ($($ctor:tt)+), accum: [ $a:ident, $b:ident, $c:ident, $d:ident ], remaining: [ ($fty:ty) $($rest:tt)* ]) => {{
2337        if $lex.array_continue(b']')? {
2338            return ::core::result::Result::Err(
2339                $crate::Error::new($crate::ErrorKind::TypeMismatch, $lex.position()),
2340            );
2341        }
2342        let __elem_4 = <$fty as $crate::FromJson<'_>>::from_lex($lex)?;
2343        $crate::__from_json_tuple_walk!(
2344            lex: $lex, self_ctor: ($($ctor)+), accum: [ $a, $b, $c, $d, __elem_4 ], remaining: [ $($rest)* ]
2345        )
2346    }};
2347}
2348
2349// ============================================================================
2350// __from_json_named_body!($lex, $self_ctor, $($body:tt)*)
2351//
2352// Top-level body emitter. Drives a tt-walker that accumulates three
2353// parallel token streams as it consumes the field list:
2354//
2355//   - decls: per-field slot decls
2356//   - arms:  per-field key-dispatch arms
2357//   - assigns: per-field final assignments
2358//
2359// When the input is exhausted, the three streams are spliced into
2360// the surrounding `object_start` / `while object_next_key` / `Self {}`
2361// scaffold.
2362// ============================================================================
2363
2364#[doc(hidden)]
2365#[macro_export]
2366macro_rules! __from_json_named_body {
2367    // Strict (default): unknown key → UnknownField error.
2368    ($lex:ident, ($($self_ctor:tt)+), strict, $($body:tt)*) => {
2369        $crate::__from_json_walk!(
2370            lex: $lex,
2371            ctor: ($($self_ctor)+),
2372            unknown: strict,
2373            decls: { },
2374            arms: { },
2375            assigns: { },
2376            ftokens: [],
2377            cur_name: (),
2378            cur_rename: (),
2379            cur_default: (),
2380            input: ($($body)*)
2381        )
2382    };
2383    // Lenient: unknown key → lex.skip_value()?.
2384    ($lex:ident, ($($self_ctor:tt)+), lenient, $($body:tt)*) => {
2385        $crate::__from_json_walk!(
2386            lex: $lex,
2387            ctor: ($($self_ctor)+),
2388            unknown: lenient,
2389            decls: { },
2390            arms: { },
2391            assigns: { },
2392            ftokens: [],
2393            cur_name: (),
2394            cur_rename: (),
2395            cur_default: (),
2396            input: ($($body)*)
2397        )
2398    };
2399}
2400
2401// ============================================================================
2402// The tt-muncher.
2403//
2404// The state machine has these moving parts:
2405//
2406//   - `decls`, `arms`, `assigns`: append-only token lists, the three
2407//     parallel streams that get spliced into the final body.
2408//   - `ftokens`: per-field accumulator of "type tokens seen so far for
2409//     the current field." Cleared after each field commits.
2410//   - `cur_name`: the name of the field currently being collected.
2411//     Set when we consume `name :`, cleared when we commit.
2412//   - `input`: remaining tokens to consume from the user's body.
2413//
2414// Phases:
2415//   1. Empty input + empty cur_name → emit the body block.
2416//   2. We just read a field name and `:`; absorb tokens into ftokens
2417//      until we see `,` (commit) or input ends (commit final field).
2418//   3. After a comma, ftokens is empty and cur_name is empty; we expect
2419//      the next token to be a field name → goto phase 2.
2420//
2421// The arms below pattern-match the head of `input` to figure out which
2422// phase we're in.
2423// ============================================================================
2424
2425#[doc(hidden)]
2426#[macro_export]
2427macro_rules! __from_json_walk {
2428    // ---------- Phase 1: terminal — input exhausted, no in-flight field. ----------
2429    (
2430        lex: $lex:ident,
2431        ctor: ($($self_ctor:tt)+),
2432        unknown: $u:tt,
2433        decls: { $($decls:tt)* },
2434        arms: { $($arms:tt)* },
2435        assigns: { $($assigns:tt)* },
2436        ftokens: [],
2437        cur_name: (),
2438        cur_rename: (),
2439        cur_default: (),
2440        input: ()
2441    ) => {{
2442        $lex.object_start()?;
2443        $($decls)*
2444        let mut __maybe_key = $lex.object_first_key_lex()?;
2445        while let ::core::option::Option::Some(__key_js) = __maybe_key {
2446            let __key_cow = $crate::key_to_cow(__key_js, $lex)?;
2447            match __key_cow.as_ref() {
2448                $($arms)*
2449                _ => {
2450                    $crate::__from_json_unknown_arm!($u, $lex, __key_cow);
2451                }
2452            }
2453            __maybe_key = $lex.object_next_key_lex()?;
2454        }
2455        ::core::result::Result::Ok($($self_ctor)+ { $($assigns)* })
2456    }};
2457
2458    // ---------- Phase 1b-skip: terminal commit for #[bourne(skip)] field. ----------
2459    //
2460    // Skipped fields contribute nothing to `decls` or `arms`; the
2461    // assignment is `Default::default()`. The only thing we still
2462    // consume is the field's type tokens (kept on the struct def by
2463    // the strip walker, but here we just discard them).
2464    (
2465        lex: $lex:ident,
2466        ctor: ($($self_ctor:tt)+),
2467        unknown: $u:tt,
2468        decls: { $($decls:tt)* },
2469        arms: { $($arms:tt)* },
2470        assigns: { $($assigns:tt)* },
2471        ftokens: [ $($fty:tt)+ ],
2472        cur_name: ($fname:ident),
2473        cur_rename: ($($rename:tt)?),
2474        cur_default: (skip),
2475        input: ()
2476    ) => {
2477        $crate::__from_json_walk!(
2478            lex: $lex,
2479            ctor: ($($self_ctor)+),
2480            unknown: $u,
2481            decls: { $($decls)* },
2482            arms: { $($arms)* },
2483            assigns: {
2484                $($assigns)*
2485                $fname: <$($fty)+ as ::core::default::Default>::default(),
2486            },
2487            ftokens: [],
2488            cur_name: (),
2489            cur_rename: (),
2490            cur_default: (),
2491            input: ()
2492        )
2493    };
2494
2495    // ---------- Phase 1b: terminal — last field, no trailing comma. ----------
2496    (
2497        lex: $lex:ident,
2498        ctor: ($($self_ctor:tt)+),
2499        unknown: $u:tt,
2500        decls: { $($decls:tt)* },
2501        arms: { $($arms:tt)* },
2502        assigns: { $($assigns:tt)* },
2503        ftokens: [ $($fty:tt)+ ],
2504        cur_name: ($fname:ident),
2505        cur_rename: ($($rename:tt)?),
2506        cur_default: ($($default:tt)?),
2507        input: ()
2508    ) => {
2509        $crate::__from_json_walk!(
2510            lex: $lex,
2511            ctor: ($($self_ctor)+),
2512            unknown: $u,
2513            decls: {
2514                $($decls)*
2515                let mut $fname: ::core::option::Option<$($fty)+> = ::core::option::Option::None;
2516            },
2517            arms: {
2518                $($arms)*
2519                $crate::__from_json_field_key!($fname, ($($rename)?)) => {
2520                    if $fname.is_some() {
2521                        return ::core::result::Result::Err(
2522                            $crate::Error::new($crate::ErrorKind::DuplicateKey, $lex.position()),
2523                        );
2524                    }
2525                    $fname = ::core::option::Option::Some(
2526                        $crate::__from_json_acquire!($lex, $($fty)+)
2527                    );
2528                }
2529            },
2530            assigns: {
2531                $($assigns)*
2532                $fname: $crate::__from_json_finalize_with_default!(
2533                    $lex, $fname, ($($default)?), $($fty)+
2534                ),
2535            },
2536            ftokens: [],
2537            cur_name: (),
2538            cur_rename: (),
2539            cur_default: (),
2540            input: ()
2541        )
2542    };
2543
2544    // ---------- bourne(rename = "x") attribute on the next field. ----------
2545    (
2546        lex: $lex:ident,
2547        ctor: ($($self_ctor:tt)+),
2548        unknown: $u:tt,
2549        decls: $decls:tt,
2550        arms: $arms:tt,
2551        assigns: $assigns:tt,
2552        ftokens: [],
2553        cur_name: (),
2554        cur_rename: (),
2555        cur_default: ($($default:tt)?),
2556        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
2557    ) => {
2558        $crate::__from_json_walk!(
2559            lex: $lex,
2560            ctor: ($($self_ctor)+),
2561            unknown: $u,
2562            decls: $decls,
2563            arms: $arms,
2564            assigns: $assigns,
2565            ftokens: [],
2566            cur_name: (),
2567            cur_rename: ($renamed),
2568            cur_default: ($($default)?),
2569            input: ($($rest)*)
2570        )
2571    };
2572
2573    // ---------- bourne(skip) attribute on the next field. ----------
2574    //
2575    // A skipped field is never read from JSON. The slot decl and key
2576    // dispatch arm are omitted entirely; the final assignment uses
2577    // `Default::default()`. This is encoded as a third value on the
2578    // `cur_default` slot — `(skip)` — which the dedicated commit arms
2579    // below match before the regular `(trait_default)` / `()` arms.
2580    (
2581        lex: $lex:ident,
2582        ctor: ($($self_ctor:tt)+),
2583        unknown: $u:tt,
2584        decls: $decls:tt,
2585        arms: $arms:tt,
2586        assigns: $assigns:tt,
2587        ftokens: [],
2588        cur_name: (),
2589        cur_rename: ($($rename:tt)?),
2590        cur_default: (),
2591        input: ( #[bourne(skip)] $($rest:tt)* )
2592    ) => {
2593        $crate::__from_json_walk!(
2594            lex: $lex,
2595            ctor: ($($self_ctor)+),
2596            unknown: $u,
2597            decls: $decls,
2598            arms: $arms,
2599            assigns: $assigns,
2600            ftokens: [],
2601            cur_name: (),
2602            cur_rename: ($($rename)?),
2603            cur_default: (skip),
2604            input: ($($rest)*)
2605        )
2606    };
2607
2608    // ---------- bourne(default) attribute on the next field. ----------
2609    (
2610        lex: $lex:ident,
2611        ctor: ($($self_ctor:tt)+),
2612        unknown: $u:tt,
2613        decls: $decls:tt,
2614        arms: $arms:tt,
2615        assigns: $assigns:tt,
2616        ftokens: [],
2617        cur_name: (),
2618        cur_rename: ($($rename:tt)?),
2619        cur_default: (),
2620        input: ( #[bourne(default)] $($rest:tt)* )
2621    ) => {
2622        $crate::__from_json_walk!(
2623            lex: $lex,
2624            ctor: ($($self_ctor)+),
2625            unknown: $u,
2626            decls: $decls,
2627            arms: $arms,
2628            assigns: $assigns,
2629            ftokens: [],
2630            cur_name: (),
2631            cur_rename: ($($rename)?),
2632            cur_default: (trait_default),
2633            input: ($($rest)*)
2634        )
2635    };
2636
2637    // ---------- bourne(skip_if_none) attribute on the next field. ----------
2638    //
2639    // Pure ser-side metadata. For parsing, this is a no-op: the
2640    // field is an Option<T> whose missing-key case already produces
2641    // `None`, so we just drop the attr and continue.
2642    (
2643        lex: $lex:ident,
2644        ctor: ($($self_ctor:tt)+),
2645        unknown: $u:tt,
2646        decls: $decls:tt,
2647        arms: $arms:tt,
2648        assigns: $assigns:tt,
2649        ftokens: [],
2650        cur_name: (),
2651        cur_rename: ($($rename:tt)?),
2652        cur_default: ($($default:tt)?),
2653        input: ( #[bourne(skip_if_none)] $($rest:tt)* )
2654    ) => {
2655        $crate::__from_json_walk!(
2656            lex: $lex,
2657            ctor: ($($self_ctor)+),
2658            unknown: $u,
2659            decls: $decls,
2660            arms: $arms,
2661            assigns: $assigns,
2662            ftokens: [],
2663            cur_name: (),
2664            cur_rename: ($($rename)?),
2665            cur_default: ($($default)?),
2666            input: ($($rest)*)
2667        )
2668    };
2669
2670    // ---------- bourne(rename = "x", default) compound attribute. ----------
2671    (
2672        lex: $lex:ident,
2673        ctor: ($($self_ctor:tt)+),
2674        unknown: $u:tt,
2675        decls: $decls:tt,
2676        arms: $arms:tt,
2677        assigns: $assigns:tt,
2678        ftokens: [],
2679        cur_name: (),
2680        cur_rename: (),
2681        cur_default: (),
2682        input: ( #[bourne(rename = $renamed:literal, default)] $($rest:tt)* )
2683    ) => {
2684        $crate::__from_json_walk!(
2685            lex: $lex,
2686            ctor: ($($self_ctor)+),
2687            unknown: $u,
2688            decls: $decls,
2689            arms: $arms,
2690            assigns: $assigns,
2691            ftokens: [],
2692            cur_name: (),
2693            cur_rename: ($renamed),
2694            cur_default: (trait_default),
2695            input: ($($rest)*)
2696        )
2697    };
2698
2699    // ---------- bourne(default = "fn") rejected with a compile_error!. ----------
2700    (
2701        lex: $lex:ident,
2702        ctor: ($($self_ctor:tt)+),
2703        unknown: $u:tt,
2704        decls: $decls:tt,
2705        arms: $arms:tt,
2706        assigns: $assigns:tt,
2707        ftokens: [],
2708        cur_name: (),
2709        cur_rename: ($($rename:tt)?),
2710        cur_default: (),
2711        input: ( #[bourne(default = $_path:literal)] $($rest:tt)* )
2712    ) => {
2713        ::core::compile_error!(
2714            "from_json! macro: `#[bourne(default = \"path\")]` is not supported. \
2715             Use bare `#[bourne(default)]` (which calls Default::default()) and implement Default \
2716             for the field type, or hand-write the FromJson impl. macro_rules! cannot resolve a \
2717             string literal to a function path."
2718        );
2719    };
2720
2721    // ---------- Other `#[...]` attributes: drop them on the impl side. ----------
2722    // The strip-pass walker preserves them on the struct definition;
2723    // the impl doesn't need them.
2724    (
2725        lex: $lex:ident,
2726        ctor: ($($self_ctor:tt)+),
2727        unknown: $u:tt,
2728        decls: $decls:tt,
2729        arms: $arms:tt,
2730        assigns: $assigns:tt,
2731        ftokens: [],
2732        cur_name: (),
2733        cur_rename: ($($rename:tt)?),
2734        cur_default: ($($default:tt)?),
2735        input: ( #[$_other:meta] $($rest:tt)* )
2736    ) => {
2737        $crate::__from_json_walk!(
2738            lex: $lex,
2739            ctor: ($($self_ctor)+),
2740            unknown: $u,
2741            decls: $decls,
2742            arms: $arms,
2743            assigns: $assigns,
2744            ftokens: [],
2745            cur_name: (),
2746            cur_rename: ($($rename)?),
2747            cur_default: ($($default)?),
2748            input: ($($rest)*)
2749        )
2750    };
2751
2752    // ---------- Phase 3: start a new field. ----------
2753    (
2754        lex: $lex:ident,
2755        ctor: ($($self_ctor:tt)+),
2756        unknown: $u:tt,
2757        decls: $decls:tt,
2758        arms: $arms:tt,
2759        assigns: $assigns:tt,
2760        ftokens: [],
2761        cur_name: (),
2762        cur_rename: ($($rename:tt)?),
2763        cur_default: ($($default:tt)?),
2764        input: ($_fvis:vis $fname:ident : $($rest:tt)*)
2765    ) => {
2766        $crate::__from_json_walk!(
2767            lex: $lex,
2768            ctor: ($($self_ctor)+),
2769            unknown: $u,
2770            decls: $decls,
2771            arms: $arms,
2772            assigns: $assigns,
2773            ftokens: [],
2774            cur_name: ($fname),
2775            cur_rename: ($($rename)?),
2776            cur_default: ($($default)?),
2777            input: ($($rest)*)
2778        )
2779    };
2780
2781    // ---------- Phase 2-skip: commit on `,` for #[bourne(skip)] field. ----------
2782    (
2783        lex: $lex:ident,
2784        ctor: ($($self_ctor:tt)+),
2785        unknown: $u:tt,
2786        decls: { $($decls:tt)* },
2787        arms: { $($arms:tt)* },
2788        assigns: { $($assigns:tt)* },
2789        ftokens: [ $($fty:tt)+ ],
2790        cur_name: ($fname:ident),
2791        cur_rename: ($($rename:tt)?),
2792        cur_default: (skip),
2793        input: ( , $($rest:tt)* )
2794    ) => {
2795        $crate::__from_json_walk!(
2796            lex: $lex,
2797            ctor: ($($self_ctor)+),
2798            unknown: $u,
2799            decls: { $($decls)* },
2800            arms: { $($arms)* },
2801            assigns: {
2802                $($assigns)*
2803                $fname: <$($fty)+ as ::core::default::Default>::default(),
2804            },
2805            ftokens: [],
2806            cur_name: (),
2807            cur_rename: (),
2808            cur_default: (),
2809            input: ($($rest)*)
2810        )
2811    };
2812
2813    // ---------- Phase 2: commit on `,`. ----------
2814    (
2815        lex: $lex:ident,
2816        ctor: ($($self_ctor:tt)+),
2817        unknown: $u:tt,
2818        decls: { $($decls:tt)* },
2819        arms: { $($arms:tt)* },
2820        assigns: { $($assigns:tt)* },
2821        ftokens: [ $($fty:tt)+ ],
2822        cur_name: ($fname:ident),
2823        cur_rename: ($($rename:tt)?),
2824        cur_default: ($($default:tt)?),
2825        input: ( , $($rest:tt)* )
2826    ) => {
2827        $crate::__from_json_walk!(
2828            lex: $lex,
2829            ctor: ($($self_ctor)+),
2830            unknown: $u,
2831            decls: {
2832                $($decls)*
2833                let mut $fname: ::core::option::Option<$($fty)+> = ::core::option::Option::None;
2834            },
2835            arms: {
2836                $($arms)*
2837                $crate::__from_json_field_key!($fname, ($($rename)?)) => {
2838                    if $fname.is_some() {
2839                        return ::core::result::Result::Err(
2840                            $crate::Error::new($crate::ErrorKind::DuplicateKey, $lex.position()),
2841                        );
2842                    }
2843                    $fname = ::core::option::Option::Some(
2844                        $crate::__from_json_acquire!($lex, $($fty)+)
2845                    );
2846                }
2847            },
2848            assigns: {
2849                $($assigns)*
2850                $fname: $crate::__from_json_finalize_with_default!(
2851                    $lex, $fname, ($($default)?), $($fty)+
2852                ),
2853            },
2854            ftokens: [],
2855            cur_name: (),
2856            cur_rename: (),
2857            cur_default: (),
2858            input: ($($rest)*)
2859        )
2860    };
2861
2862    // ---------- Phase 2: absorb one type token. ----------
2863    (
2864        lex: $lex:ident,
2865        ctor: ($($self_ctor:tt)+),
2866        unknown: $u:tt,
2867        decls: $decls:tt,
2868        arms: $arms:tt,
2869        assigns: $assigns:tt,
2870        ftokens: [ $($fty:tt)* ],
2871        cur_name: ($fname:ident),
2872        cur_rename: ($($rename:tt)?),
2873        cur_default: ($($default:tt)?),
2874        input: ( $head:tt $($rest:tt)* )
2875    ) => {
2876        $crate::__from_json_walk!(
2877            lex: $lex,
2878            ctor: ($($self_ctor)+),
2879            unknown: $u,
2880            decls: $decls,
2881            arms: $arms,
2882            assigns: $assigns,
2883            ftokens: [ $($fty)* $head ],
2884            cur_name: ($fname),
2885            cur_rename: ($($rename)?),
2886            cur_default: ($($default)?),
2887            input: ($($rest)*)
2888        )
2889    };
2890}
2891
2892// ============================================================================
2893// Strict vs. lenient unknown-key handling.
2894//
2895// `strict`  → raise `UnknownField` on the first unknown key.
2896// `lenient` → call `lex.skip_value()` to advance past the unknown
2897//             value (including nested arrays/objects) and continue.
2898// ============================================================================
2899
2900#[doc(hidden)]
2901#[macro_export]
2902macro_rules! __from_json_unknown_arm {
2903    (strict, $lex:ident, $key:ident) => {
2904        return ::core::result::Result::Err($crate::Error::new(
2905            $crate::ErrorKind::UnknownField,
2906            $lex.position(),
2907        ));
2908    };
2909    (lenient, $lex:ident, $key:ident) => {
2910        $lex.skip_value()?;
2911    };
2912    // Used by internally-tagged enum struct-variant bodies. The tag
2913    // key (`$skip_key`) was already consumed during the find-tag pass
2914    // before restore; on the second pass we encounter it again as a
2915    // sibling field and must skip it. Any *other* unknown key remains
2916    // a hard error.
2917    //
2918    // Wrapped in parens at the call site (`unknown: (tag_skip "x")`)
2919    // so the engine's `unknown: $u:tt` matcher captures the whole
2920    // mode token as a single tt.
2921    //
2922    // `$key` is the local Cow<str> bound by the body walker; passing
2923    // it explicitly avoids the macro_rules hygiene issue that would
2924    // otherwise mangle the binding when this arm expands.
2925    ((tag_skip $skip_key:literal), $lex:ident, $key:ident) => {
2926        if $key.as_ref() == $skip_key {
2927            $lex.skip_value()?;
2928        } else {
2929            return ::core::result::Result::Err($crate::Error::new(
2930                $crate::ErrorKind::UnknownField,
2931                $lex.position(),
2932            ));
2933        }
2934    };
2935}
2936
2937// ============================================================================
2938// Per-field key resolution: rename if set, else stringified field name.
2939// ============================================================================
2940
2941#[doc(hidden)]
2942#[macro_export]
2943macro_rules! __from_json_field_key {
2944    ($fname:ident, ($renamed:literal)) => {
2945        $renamed
2946    };
2947    ($fname:ident, ()) => {
2948        ::core::stringify!($fname)
2949    };
2950}
2951
2952// ============================================================================
2953// Final-value with optional default. The 3-arg form (no default) calls
2954// the existing __from_json_finalize. The 4-arg form (with default)
2955// emits `slot.unwrap_or_else(|| <T as Default>::default())`.
2956// ============================================================================
2957
2958#[doc(hidden)]
2959#[macro_export]
2960macro_rules! __from_json_finalize_with_default {
2961    // No default → existing path (Option-collapse or MissingField).
2962    ($lex:ident, $fname:ident, (), $($fty:tt)+) => {
2963        $crate::__from_json_finalize!($lex, $fname, $($fty)+)
2964    };
2965    // Bare `#[bourne(default)]` → trait Default.
2966    ($lex:ident, $fname:ident, (trait_default), $($fty:tt)+) => {
2967        $fname.unwrap_or_else(|| <$($fty)+ as ::core::default::Default>::default())
2968    };
2969}
2970
2971// ============================================================================
2972// Per-field acquire — emits the right call for the field type.
2973//
2974// Takes the type as raw `tt`-tokens (from the `ftokens` accumulator),
2975// so leading-token literal matchers like `& str` work.
2976//
2977// Recognized fast paths:
2978//   - &str, &'lt str: parse_str_value()
2979//   - i8/i16/i32/i64/isize: parse_i64_value() + try_from
2980//   - u8/u16/u32/u64/usize: parse_i64_value() + try_from
2981//   - everything else: <$ty as FromJson<'_>>::from_lex
2982// ============================================================================
2983
2984#[doc(hidden)]
2985#[macro_export]
2986macro_rules! __from_json_acquire {
2987    ($lex:ident, & str) => { $lex.parse_str_value()? };
2988    ($lex:ident, & $lt:lifetime str) => { $lex.parse_str_value()? };
2989
2990    ($lex:ident, i8) => {
2991        <i8>::try_from($lex.parse_i64_value()?).map_err(|_| {
2992            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
2993        })?
2994    };
2995    ($lex:ident, i16) => {
2996        <i16>::try_from($lex.parse_i64_value()?).map_err(|_| {
2997            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
2998        })?
2999    };
3000    ($lex:ident, i32) => {
3001        <i32>::try_from($lex.parse_i64_value()?).map_err(|_| {
3002            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3003        })?
3004    };
3005    ($lex:ident, i64) => {
3006        $lex.parse_i64_value()?
3007    };
3008    ($lex:ident, isize) => {
3009        <isize>::try_from($lex.parse_i64_value()?).map_err(|_| {
3010            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3011        })?
3012    };
3013
3014    ($lex:ident, u8) => {
3015        <u8>::try_from($lex.parse_i64_value()?).map_err(|_| {
3016            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3017        })?
3018    };
3019    ($lex:ident, u16) => {
3020        <u16>::try_from($lex.parse_i64_value()?).map_err(|_| {
3021            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3022        })?
3023    };
3024    ($lex:ident, u32) => {
3025        <u32>::try_from($lex.parse_i64_value()?).map_err(|_| {
3026            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3027        })?
3028    };
3029    ($lex:ident, u64) => {
3030        <u64>::try_from($lex.parse_i64_value()?).map_err(|_| {
3031            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3032        })?
3033    };
3034    ($lex:ident, usize) => {
3035        <usize>::try_from($lex.parse_i64_value()?).map_err(|_| {
3036            $crate::Error::new($crate::ErrorKind::NumberOutOfRange, $lex.position())
3037        })?
3038    };
3039
3040    ($lex:ident, $($ty:tt)+) => {
3041        <$($ty)+ as $crate::FromJson<'_>>::from_lex($lex)?
3042    };
3043}
3044
3045// ============================================================================
3046// Final-value dispatch.
3047//
3048// `Option<...>` collapses missing-key → None (the slot's outer-None,
3049// before unwrap, becomes inner None). Required fields raise
3050// MissingField if the slot was never set.
3051//
3052// The Option matcher receives the raw type tokens from ftokens, so
3053// the leading `Option` ident is visible literally.
3054// ============================================================================
3055
3056// Two-step dispatch to avoid the `Option<...>` greedy-matcher
3057// ambiguity. The outer macro tags the field's leading token as either
3058// "Option" (for direct match on the literal ident) or "Other"
3059// (catchall), then the inner macro picks the right finalize
3060// expression. This avoids relying on `Option<$($_inner:tt)*>`, which
3061// is locally ambiguous against the catchall arm because `$_inner`
3062// has no fixed delimiter at its tail (`>` is just punctuation, not
3063// a token-tree boundary).
3064#[doc(hidden)]
3065#[macro_export]
3066macro_rules! __from_json_finalize {
3067    ($lex:ident, $fname:ident, Option < $($rest:tt)*) => {
3068        $crate::__from_json_finalize_option!($lex, $fname)
3069    };
3070    ($lex:ident, $fname:ident, $($fty:tt)+) => {
3071        $crate::__from_json_finalize_required!($lex, $fname)
3072    };
3073}
3074
3075#[doc(hidden)]
3076#[macro_export]
3077macro_rules! __from_json_finalize_option {
3078    ($lex:ident, $fname:ident) => {
3079        $fname.unwrap_or(::core::option::Option::None)
3080    };
3081}
3082
3083#[doc(hidden)]
3084#[macro_export]
3085macro_rules! __from_json_finalize_required {
3086    ($lex:ident, $fname:ident) => {
3087        $fname
3088            .ok_or_else(|| $crate::Error::new($crate::ErrorKind::MissingField, $lex.position()))?
3089    };
3090}
3091
3092// ============================================================================
3093// `to_json!` — declarative macro that emits a struct or enum together
3094// with its [`ToJson`] impl.
3095//
3096// Mirror image of `from_json!`. The two are independent: emitting both
3097// from the same source today would re-emit the type, which Rust
3098// disallows. Users who want round-trip macros either (a) define the
3099// type with `from_json!` and hand-write the `ToJson` impl, or
3100// (b) define with `to_json!` and hand-write `FromJson` — until a
3101// future combined macro lands.
3102//
3103// Field/variant attributes recognized:
3104//   - #[bourne(rename = "key")]     — emit that key instead of the field name
3105//   - #[bourne(skip)]               — omit the field from output
3106//   - #[bourne(skip_if_none)]       — omit Option<T> field when None
3107//   - #[bourne(default)]            — no-op on serialize (silently ignored)
3108//
3109// Container attributes recognized: same set as `from_json!`
3110// (deny_unknown_fields, untagged, tag, tag+content) — all are no-ops
3111// on serialize except the tagged-enum forms, which dictate variant
3112// encoding shape.
3113//
3114// Implementation strategy mirrors `from_json!`: tt-munch the body
3115// per field, accumulating a `emit:` token stream that splices into
3116// the impl body. The per-field state tracks (rename, skip,
3117// skip_if_none).
3118// ============================================================================
3119
3120/// Emit a struct or enum together with its [`crate::ToJson`] impl.
3121///
3122/// See the [`from_json!`](crate::from_json) docs for shape coverage —
3123/// the two macros support the same set of containers and attributes.
3124#[macro_export]
3125macro_rules! to_json {
3126    // -----------------------------------------------------------------
3127    // Named-field struct, no generics.
3128    // -----------------------------------------------------------------
3129    (
3130        $(#[$attr:meta])*
3131        $vis:vis struct $name:ident { $($body:tt)* }
3132    ) => {
3133        $crate::__to_json_emit_struct_def!(
3134            attrs: { $(#[$attr])* },
3135            vis: $vis,
3136            name: $name,
3137            generics_def: (),
3138            body: ($($body)*)
3139        );
3140
3141        impl $crate::ToJson for $name {
3142            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3143                &self,
3144                __w: &mut __W,
3145            ) -> ::core::result::Result<(), __W::Error> {
3146                $crate::__to_json_named_body!(self, __w, $($body)*)
3147            }
3148        }
3149    };
3150
3151    // -----------------------------------------------------------------
3152    // Named-field struct, one lifetime.
3153    // -----------------------------------------------------------------
3154    (
3155        $(#[$attr:meta])*
3156        $vis:vis struct $name:ident < $lt:lifetime $(,)? > { $($body:tt)* }
3157    ) => {
3158        $crate::__to_json_emit_struct_def!(
3159            attrs: { $(#[$attr])* },
3160            vis: $vis,
3161            name: $name,
3162            generics_def: (<$lt>),
3163            body: ($($body)*)
3164        );
3165
3166        impl<$lt> $crate::ToJson for $name<$lt> {
3167            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3168                &self,
3169                __w: &mut __W,
3170            ) -> ::core::result::Result<(), __W::Error> {
3171                $crate::__to_json_named_body!(self, __w, $($body)*)
3172            }
3173        }
3174    };
3175
3176    // -----------------------------------------------------------------
3177    // Tuple struct, no generics, newtype (single field).
3178    //
3179    // Mirror of `from_json!`'s `#[serde(transparent)]`-style newtype:
3180    // serialize as a bare JSON value of the inner type, no wrapping.
3181    // -----------------------------------------------------------------
3182    (
3183        $(#[$attr:meta])*
3184        $vis:vis struct $name:ident ( $fty:ty $(,)? ) ;
3185    ) => {
3186        $(#[$attr])*
3187        $vis struct $name($fty);
3188
3189        impl $crate::ToJson for $name {
3190            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3191                &self,
3192                __w: &mut __W,
3193            ) -> ::core::result::Result<(), __W::Error> {
3194                $crate::ToJson::write_json(&self.0, __w)
3195            }
3196        }
3197    };
3198
3199    // Tuple struct with one lifetime, newtype.
3200    (
3201        $(#[$attr:meta])*
3202        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty:ty $(,)? ) ;
3203    ) => {
3204        $(#[$attr])*
3205        $vis struct $name<$lt>($fty);
3206
3207        impl<$lt> $crate::ToJson for $name<$lt> {
3208            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3209                &self,
3210                __w: &mut __W,
3211            ) -> ::core::result::Result<(), __W::Error> {
3212                $crate::ToJson::write_json(&self.0, __w)
3213            }
3214        }
3215    };
3216
3217    // -----------------------------------------------------------------
3218    // Tuple struct, multi-field. No generics.
3219    //
3220    // Serializes as a JSON array of N elements, mirroring the
3221    // FromJson side. The body emits each `self.idx.write_json(w)?`
3222    // separated by commas.
3223    // -----------------------------------------------------------------
3224    (
3225        $(#[$attr:meta])*
3226        $vis:vis struct $name:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
3227    ) => {
3228        $(#[$attr])*
3229        $vis struct $name($fty1, $($ftyn),+);
3230
3231        impl $crate::ToJson for $name {
3232            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3233                &self,
3234                __w: &mut __W,
3235            ) -> ::core::result::Result<(), __W::Error> {
3236                __w.write_raw_bytes(b"[")?;
3237                $crate::ToJson::write_json(&self.0, __w)?;
3238                $crate::__to_json_tuple_walk!(
3239                    self_ref: self,
3240                    sink: __w,
3241                    idx: 1,
3242                    remaining: [ $(($ftyn))+ ]
3243                );
3244                __w.write_raw_bytes(b"]")?;
3245                ::core::result::Result::Ok(())
3246            }
3247        }
3248    };
3249
3250    // Tuple struct, multi-field, with one lifetime.
3251    (
3252        $(#[$attr:meta])*
3253        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
3254    ) => {
3255        $(#[$attr])*
3256        $vis struct $name<$lt>($fty1, $($ftyn),+);
3257
3258        impl<$lt> $crate::ToJson for $name<$lt> {
3259            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3260                &self,
3261                __w: &mut __W,
3262            ) -> ::core::result::Result<(), __W::Error> {
3263                __w.write_raw_bytes(b"[")?;
3264                $crate::ToJson::write_json(&self.0, __w)?;
3265                $crate::__to_json_tuple_walk!(
3266                    self_ref: self,
3267                    sink: __w,
3268                    idx: 1,
3269                    remaining: [ $(($ftyn))+ ]
3270                );
3271                __w.write_raw_bytes(b"]")?;
3272                ::core::result::Result::Ok(())
3273            }
3274        }
3275    };
3276
3277    // -----------------------------------------------------------------
3278    // Untagged enum, no generics.
3279    //
3280    //   #[bourne(untagged)]
3281    //   enum E { Foo, Bar(T), Baz(T,U), Qux { x: T } }
3282    //
3283    // emits the variant's payload bare:
3284    //   Foo  → null
3285    //   Bar  → <T>
3286    //   Baz  → [T, U]
3287    //   Qux  → {"x": T}
3288    //
3289    // The parse side disambiguates by trial; the ser side just
3290    // matches on `self` and writes the raw shape.
3291    // -----------------------------------------------------------------
3292    (
3293        #[bourne(untagged)]
3294        $(#[$attr:meta])*
3295        $vis:vis enum $name:ident { $($variants:tt)* }
3296    ) => {
3297        $crate::__from_json_emit_enum_def!(
3298            attrs: { $(#[$attr])* },
3299            vis: $vis,
3300            name: $name,
3301            generics_def: (),
3302            variants_input: ($($variants)*)
3303        );
3304
3305        impl $crate::ToJson for $name {
3306            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3307                &self,
3308                __w: &mut __W,
3309            ) -> ::core::result::Result<(), __W::Error> {
3310                let __this: &Self = self;
3311                $crate::__to_json_untagged_walk!(
3312                    receiver: __this,
3313                    sink: __w,
3314                    name: $name,
3315                    arms: { },
3316                    input: ($($variants)*)
3317                )
3318            }
3319        }
3320    };
3321
3322    (
3323        #[bourne(untagged)]
3324        $(#[$attr:meta])*
3325        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
3326    ) => {
3327        $crate::__from_json_emit_enum_def!(
3328            attrs: { $(#[$attr])* },
3329            vis: $vis,
3330            name: $name,
3331            generics_def: (<$lt>),
3332            variants_input: ($($variants)*)
3333        );
3334
3335        impl<$lt> $crate::ToJson for $name<$lt> {
3336            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3337                &self,
3338                __w: &mut __W,
3339            ) -> ::core::result::Result<(), __W::Error> {
3340                let __this: &Self = self;
3341                $crate::__to_json_untagged_walk!(
3342                    receiver: __this,
3343                    sink: __w,
3344                    name: $name,
3345                    arms: { },
3346                    input: ($($variants)*)
3347                )
3348            }
3349        }
3350    };
3351
3352    // -----------------------------------------------------------------
3353    // Internally-tagged enum, no generics.
3354    //
3355    //   #[bourne(tag = "type")]
3356    //   enum E { Foo, Bar { x: u32 } }
3357    //
3358    // emits { "type": "Foo" } / { "type": "Bar", "x": 42 }.
3359    //
3360    // Only unit + struct variants. Newtype / tuple variants reject at
3361    // parse time too — they have no coherent internally-tagged shape.
3362    // -----------------------------------------------------------------
3363    (
3364        #[bourne(tag = $tag:literal)]
3365        $(#[$attr:meta])*
3366        $vis:vis enum $name:ident { $($variants:tt)* }
3367    ) => {
3368        $crate::__from_json_emit_enum_def!(
3369            attrs: { $(#[$attr])* },
3370            vis: $vis,
3371            name: $name,
3372            generics_def: (),
3373            variants_input: ($($variants)*)
3374        );
3375
3376        impl $crate::ToJson for $name {
3377            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3378                &self,
3379                __w: &mut __W,
3380            ) -> ::core::result::Result<(), __W::Error> {
3381                let __this: &Self = self;
3382                $crate::__to_json_internal_walk!(
3383                    receiver: __this,
3384                    sink: __w,
3385                    name: $name,
3386                    tag: $tag,
3387                    arms: { },
3388                    cur_rename: (),
3389                    input: ($($variants)*)
3390                )
3391            }
3392        }
3393    };
3394
3395    (
3396        #[bourne(tag = $tag:literal)]
3397        $(#[$attr:meta])*
3398        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
3399    ) => {
3400        $crate::__from_json_emit_enum_def!(
3401            attrs: { $(#[$attr])* },
3402            vis: $vis,
3403            name: $name,
3404            generics_def: (<$lt>),
3405            variants_input: ($($variants)*)
3406        );
3407
3408        impl<$lt> $crate::ToJson for $name<$lt> {
3409            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3410                &self,
3411                __w: &mut __W,
3412            ) -> ::core::result::Result<(), __W::Error> {
3413                let __this: &Self = self;
3414                $crate::__to_json_internal_walk!(
3415                    receiver: __this,
3416                    sink: __w,
3417                    name: $name,
3418                    tag: $tag,
3419                    arms: { },
3420                    cur_rename: (),
3421                    input: ($($variants)*)
3422                )
3423            }
3424        }
3425    };
3426
3427    // -----------------------------------------------------------------
3428    // Adjacently-tagged enum, no generics.
3429    //
3430    //   #[bourne(tag = "t", content = "c")]
3431    //   enum E { Foo, Bar(u32), Baz(u32, u32), Qux { x: u32 } }
3432    //
3433    // emits:
3434    //   Foo  → {"t":"Foo"}
3435    //   Bar  → {"t":"Bar","c":42}
3436    //   Baz  → {"t":"Baz","c":[1,2]}
3437    //   Qux  → {"t":"Qux","c":{"x":1}}
3438    // -----------------------------------------------------------------
3439    (
3440        #[bourne(tag = $tag:literal, content = $content:literal)]
3441        $(#[$attr:meta])*
3442        $vis:vis enum $name:ident { $($variants:tt)* }
3443    ) => {
3444        $crate::__from_json_emit_enum_def!(
3445            attrs: { $(#[$attr])* },
3446            vis: $vis,
3447            name: $name,
3448            generics_def: (),
3449            variants_input: ($($variants)*)
3450        );
3451
3452        impl $crate::ToJson for $name {
3453            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3454                &self,
3455                __w: &mut __W,
3456            ) -> ::core::result::Result<(), __W::Error> {
3457                let __this: &Self = self;
3458                $crate::__to_json_adjacent_walk!(
3459                    receiver: __this,
3460                    sink: __w,
3461                    name: $name,
3462                    tag: $tag,
3463                    content: $content,
3464                    arms: { },
3465                    cur_rename: (),
3466                    input: ($($variants)*)
3467                )
3468            }
3469        }
3470    };
3471
3472    (
3473        #[bourne(tag = $tag:literal, content = $content:literal)]
3474        $(#[$attr:meta])*
3475        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
3476    ) => {
3477        $crate::__from_json_emit_enum_def!(
3478            attrs: { $(#[$attr])* },
3479            vis: $vis,
3480            name: $name,
3481            generics_def: (<$lt>),
3482            variants_input: ($($variants)*)
3483        );
3484
3485        impl<$lt> $crate::ToJson for $name<$lt> {
3486            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3487                &self,
3488                __w: &mut __W,
3489            ) -> ::core::result::Result<(), __W::Error> {
3490                let __this: &Self = self;
3491                $crate::__to_json_adjacent_walk!(
3492                    receiver: __this,
3493                    sink: __w,
3494                    name: $name,
3495                    tag: $tag,
3496                    content: $content,
3497                    arms: { },
3498                    cur_rename: (),
3499                    input: ($($variants)*)
3500                )
3501            }
3502        }
3503    };
3504
3505    // -----------------------------------------------------------------
3506    // Externally-tagged enum, no generics. (Default — no container attr.)
3507    //
3508    // Variant shapes:
3509    //   - Unit `Foo`            → string `"Foo"`
3510    //   - Newtype `Foo(T)`      → object `{"Foo": <T>}`
3511    //   - Tuple `Foo(T, U)`     → object `{"Foo": [<T>, <U>]}`
3512    //   - Struct `Foo {a, b}`   → object `{"Foo": {"a": ..., "b": ...}}`
3513    //
3514    // Variant-level `#[bourne(rename = "...")]` retags.
3515    // -----------------------------------------------------------------
3516    (
3517        $(#[$attr:meta])*
3518        $vis:vis enum $name:ident { $($variants:tt)* }
3519    ) => {
3520        $crate::__from_json_emit_enum_def!(
3521            attrs: { $(#[$attr])* },
3522            vis: $vis,
3523            name: $name,
3524            generics_def: (),
3525            variants_input: ($($variants)*)
3526        );
3527
3528        impl $crate::ToJson for $name {
3529            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3530                &self,
3531                __w: &mut __W,
3532            ) -> ::core::result::Result<(), __W::Error> {
3533                let __this: &Self = self;
3534                $crate::__to_json_enum_walk!(
3535                    receiver: __this,
3536                    sink: __w,
3537                    name: $name,
3538                    arms: { },
3539                    cur_rename: (),
3540                    input: ($($variants)*)
3541                )
3542            }
3543        }
3544    };
3545
3546    // Externally-tagged enum, one lifetime.
3547    (
3548        $(#[$attr:meta])*
3549        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
3550    ) => {
3551        $crate::__from_json_emit_enum_def!(
3552            attrs: { $(#[$attr])* },
3553            vis: $vis,
3554            name: $name,
3555            generics_def: (<$lt>),
3556            variants_input: ($($variants)*)
3557        );
3558
3559        impl<$lt> $crate::ToJson for $name<$lt> {
3560            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
3561                &self,
3562                __w: &mut __W,
3563            ) -> ::core::result::Result<(), __W::Error> {
3564                let __this: &Self = self;
3565                $crate::__to_json_enum_walk!(
3566                    receiver: __this,
3567                    sink: __w,
3568                    name: $name,
3569                    arms: { },
3570                    cur_rename: (),
3571                    input: ($($variants)*)
3572                )
3573            }
3574        }
3575    };
3576}
3577
3578// ============================================================================
3579// Externally-tagged enum walker.
3580//
3581// Emits one match arm per variant. Output is a stream of arms that
3582// gets spliced into a `match self { … }` at the call site.
3583//
3584// State:
3585//   - `arms`: append-only stream of match arms emitted so far.
3586//   - `cur_rename`: per-variant rename (if any). Cleared after commit.
3587// ============================================================================
3588
3589#[doc(hidden)]
3590#[macro_export]
3591macro_rules! __to_json_enum_walk {
3592    // ---------- Terminal: splice arms into a match. ----------
3593    //
3594    // macro_rules! cannot expand into match arms standalone — it must
3595    // produce the entire match expression. The `receiver:` slot is
3596    // an ident the call site bound to `&Self` (avoids the `self`
3597    // hygiene pitfall — `self` in a macro body resolves as a module
3598    // path, not the method's parameter).
3599    //
3600    // `match *receiver { … }` would auto-deref but then the variant
3601    // patterns would need `ref __inner` to keep bindings borrowed;
3602    // matching `match receiver { &Variant(...) => … }` keeps the
3603    // bindings borrowed without `ref`. The `&` prefix on each pattern
3604    // below is what makes `__inner: &T` instead of `T`.
3605    (
3606        receiver: $r:ident,
3607        sink: $w:ident,
3608        name: $name:ident,
3609        arms: { $($arms:tt)* },
3610        cur_rename: (),
3611        input: ()
3612    ) => {
3613        match $r {
3614            $($arms)*
3615        }
3616    };
3617
3618    // ---------- bourne(rename = "x") on the next variant. ----------
3619    (
3620        receiver: $r:ident,
3621        sink: $w:ident,
3622        name: $name:ident,
3623        arms: $arms:tt,
3624        cur_rename: (),
3625        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
3626    ) => {
3627        $crate::__to_json_enum_walk!(
3628            receiver: $r,
3629            sink: $w,
3630            name: $name,
3631            arms: $arms,
3632            cur_rename: ($renamed),
3633            input: ($($rest)*)
3634        )
3635    };
3636
3637    // ---------- Skip other attributes on the variant. ----------
3638    (
3639        receiver: $r:ident,
3640        sink: $w:ident,
3641        name: $name:ident,
3642        arms: $arms:tt,
3643        cur_rename: ($($rename:tt)?),
3644        input: ( #[$_other:meta] $($rest:tt)* )
3645    ) => {
3646        $crate::__to_json_enum_walk!(
3647            receiver: $r,
3648            sink: $w,
3649            name: $name,
3650            arms: $arms,
3651            cur_rename: ($($rename)?),
3652            input: ($($rest)*)
3653        )
3654    };
3655
3656    // ---------- Unit variant: `VariantName,` or terminal `VariantName`. ----------
3657    (
3658        receiver: $r:ident,
3659        sink: $w:ident,
3660        name: $name:ident,
3661        arms: { $($arms:tt)* },
3662        cur_rename: ($($rename:tt)?),
3663        input: ( $vname:ident , $($rest:tt)* )
3664    ) => {
3665        $crate::__to_json_enum_walk!(
3666            receiver: $r,
3667            sink: $w,
3668            name: $name,
3669            arms: {
3670                $($arms)*
3671                &$name::$vname => {
3672                    $w.write_raw_bytes(b"\"")?;
3673                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3674                    $w.write_raw_bytes(b"\"")?;
3675                    ::core::result::Result::Ok(())
3676                }
3677            },
3678            cur_rename: (),
3679            input: ($($rest)*)
3680        )
3681    };
3682    (
3683        receiver: $r:ident,
3684        sink: $w:ident,
3685        name: $name:ident,
3686        arms: { $($arms:tt)* },
3687        cur_rename: ($($rename:tt)?),
3688        input: ( $vname:ident )
3689    ) => {
3690        $crate::__to_json_enum_walk!(
3691            receiver: $r,
3692            sink: $w,
3693            name: $name,
3694            arms: {
3695                $($arms)*
3696                &$name::$vname => {
3697                    $w.write_raw_bytes(b"\"")?;
3698                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3699                    $w.write_raw_bytes(b"\"")?;
3700                    ::core::result::Result::Ok(())
3701                }
3702            },
3703            cur_rename: (),
3704            input: ()
3705        )
3706    };
3707
3708    // ---------- Newtype variant: `VariantName(T),`. ----------
3709    //
3710    // `&Self::Variant(ref __inner)` binds `__inner: &T` without
3711    // moving out — works for both Copy and non-Copy inner types.
3712    (
3713        receiver: $r:ident,
3714        sink: $w:ident,
3715        name: $name:ident,
3716        arms: { $($arms:tt)* },
3717        cur_rename: ($($rename:tt)?),
3718        input: ( $vname:ident ( $_fty:ty $(,)? ) $(, $($rest:tt)*)? )
3719    ) => {
3720        $crate::__to_json_enum_walk!(
3721            receiver: $r,
3722            sink: $w,
3723            name: $name,
3724            arms: {
3725                $($arms)*
3726                &$name::$vname(ref __inner) => {
3727                    $w.write_raw_bytes(b"{")?;
3728                    $w.write_escaped_str($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3729                    $w.write_raw_bytes(b":")?;
3730                    $crate::ToJson::write_json(__inner, $w)?;
3731                    $w.write_raw_bytes(b"}")?;
3732                    ::core::result::Result::Ok(())
3733                }
3734            },
3735            cur_rename: (),
3736            input: ( $($($rest)*)? )
3737        )
3738    };
3739
3740    // ---------- Tuple variant (2 fields): `VariantName(A, B),`. ----------
3741    (
3742        receiver: $r:ident,
3743        sink: $w:ident,
3744        name: $name:ident,
3745        arms: { $($arms:tt)* },
3746        cur_rename: ($($rename:tt)?),
3747        input: ( $vname:ident ( $_a:ty, $_b:ty $(,)? ) $(, $($rest:tt)*)? )
3748    ) => {
3749        $crate::__to_json_enum_walk!(
3750            receiver: $r,
3751            sink: $w,
3752            name: $name,
3753            arms: {
3754                $($arms)*
3755                &$name::$vname(ref __a, ref __b) => {
3756                    $w.write_raw_bytes(b"{")?;
3757                    $w.write_escaped_str($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3758                    $w.write_raw_bytes(b":[")?;
3759                    $crate::ToJson::write_json(__a, $w)?;
3760                    $w.write_raw_bytes(b",")?;
3761                    $crate::ToJson::write_json(__b, $w)?;
3762                    $w.write_raw_bytes(b"]}")?;
3763                    ::core::result::Result::Ok(())
3764                }
3765            },
3766            cur_rename: (),
3767            input: ( $($($rest)*)? )
3768        )
3769    };
3770
3771    // ---------- Tuple variant (3 fields). ----------
3772    (
3773        receiver: $r:ident,
3774        sink: $w:ident,
3775        name: $name:ident,
3776        arms: { $($arms:tt)* },
3777        cur_rename: ($($rename:tt)?),
3778        input: ( $vname:ident ( $_a:ty, $_b:ty, $_c:ty $(,)? ) $(, $($rest:tt)*)? )
3779    ) => {
3780        $crate::__to_json_enum_walk!(
3781            receiver: $r,
3782            sink: $w,
3783            name: $name,
3784            arms: {
3785                $($arms)*
3786                &$name::$vname(ref __a, ref __b, ref __c) => {
3787                    $w.write_raw_bytes(b"{")?;
3788                    $w.write_escaped_str($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3789                    $w.write_raw_bytes(b":[")?;
3790                    $crate::ToJson::write_json(__a, $w)?;
3791                    $w.write_raw_bytes(b",")?;
3792                    $crate::ToJson::write_json(__b, $w)?;
3793                    $w.write_raw_bytes(b",")?;
3794                    $crate::ToJson::write_json(__c, $w)?;
3795                    $w.write_raw_bytes(b"]}")?;
3796                    ::core::result::Result::Ok(())
3797                }
3798            },
3799            cur_rename: (),
3800            input: ( $($($rest)*)? )
3801        )
3802    };
3803
3804    // ---------- Struct variant: `VariantName { a: A, b: B },`. ----------
3805    (
3806        receiver: $r:ident,
3807        sink: $w:ident,
3808        name: $name:ident,
3809        arms: { $($arms:tt)* },
3810        cur_rename: ($($rename:tt)?),
3811        input: ( $vname:ident { $($fname:ident : $_fty:ty),+ $(,)? } $(, $($rest:tt)*)? )
3812    ) => {
3813        $crate::__to_json_enum_walk!(
3814            receiver: $r,
3815            sink: $w,
3816            name: $name,
3817            arms: {
3818                $($arms)*
3819                &$name::$vname { $(ref $fname),+ } => {
3820                    $w.write_raw_bytes(b"{")?;
3821                    $w.write_escaped_str($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3822                    $w.write_raw_bytes(b":{")?;
3823                    let mut __first: bool = true;
3824                    $(
3825                        if !__first { $w.write_raw_bytes(b",")?; }
3826                        $w.write_raw_bytes(
3827                            ::core::concat!("\"", ::core::stringify!($fname), "\":").as_bytes()
3828                        )?;
3829                        $crate::ToJson::write_json($fname, $w)?;
3830                        __first = false;
3831                    )+
3832                    $w.write_raw_bytes(b"}}")?;
3833                    ::core::result::Result::Ok(())
3834                }
3835            },
3836            cur_rename: (),
3837            input: ( $($($rest)*)? )
3838        )
3839    };
3840}
3841
3842// ============================================================================
3843// Internally-tagged enum walker.
3844//
3845// Each variant is encoded as a single object whose first key is the
3846// configured tag literal carrying the variant name (or rename), and
3847// whose remaining keys are the variant's struct fields. Unit variants
3848// produce just the tag entry.
3849//
3850// Newtype / tuple variants are unsupported (mirror from_json! — they
3851// have no coherent internally-tagged shape). The macro is silently
3852// silent if you try to use one; it just won't match any arm and
3853// you'll get a compilation error pointing at the variant. That's
3854// the same failure mode as the parse side.
3855// ============================================================================
3856
3857#[doc(hidden)]
3858#[macro_export]
3859macro_rules! __to_json_internal_walk {
3860    // Terminal: splice arms into a match.
3861    (
3862        receiver: $r:ident,
3863        sink: $w:ident,
3864        name: $name:ident,
3865        tag: $tag:literal,
3866        arms: { $($arms:tt)* },
3867        cur_rename: (),
3868        input: ()
3869    ) => {
3870        match $r {
3871            $($arms)*
3872        }
3873    };
3874
3875    // bourne(rename = "x") on the next variant.
3876    (
3877        receiver: $r:ident,
3878        sink: $w:ident,
3879        name: $name:ident,
3880        tag: $tag:literal,
3881        arms: $arms:tt,
3882        cur_rename: (),
3883        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
3884    ) => {
3885        $crate::__to_json_internal_walk!(
3886            receiver: $r,
3887            sink: $w,
3888            name: $name,
3889            tag: $tag,
3890            arms: $arms,
3891            cur_rename: ($renamed),
3892            input: ($($rest)*)
3893        )
3894    };
3895
3896    // Skip other attributes.
3897    (
3898        receiver: $r:ident,
3899        sink: $w:ident,
3900        name: $name:ident,
3901        tag: $tag:literal,
3902        arms: $arms:tt,
3903        cur_rename: ($($rename:tt)?),
3904        input: ( #[$_other:meta] $($rest:tt)* )
3905    ) => {
3906        $crate::__to_json_internal_walk!(
3907            receiver: $r,
3908            sink: $w,
3909            name: $name,
3910            tag: $tag,
3911            arms: $arms,
3912            cur_rename: ($($rename)?),
3913            input: ($($rest)*)
3914        )
3915    };
3916
3917    // Unit variant: `{"tag":"VariantName"}`.
3918    (
3919        receiver: $r:ident,
3920        sink: $w:ident,
3921        name: $name:ident,
3922        tag: $tag:literal,
3923        arms: { $($arms:tt)* },
3924        cur_rename: ($($rename:tt)?),
3925        input: ( $vname:ident , $($rest:tt)* )
3926    ) => {
3927        $crate::__to_json_internal_walk!(
3928            receiver: $r,
3929            sink: $w,
3930            name: $name,
3931            tag: $tag,
3932            arms: {
3933                $($arms)*
3934                &$name::$vname => {
3935                    $w.write_raw_bytes(b"{")?;
3936                    $w.write_escaped_str($tag)?;
3937                    $w.write_raw_bytes(b":\"")?;
3938                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3939                    $w.write_raw_bytes(b"\"}")?;
3940                    ::core::result::Result::Ok(())
3941                }
3942            },
3943            cur_rename: (),
3944            input: ($($rest)*)
3945        )
3946    };
3947    (
3948        receiver: $r:ident,
3949        sink: $w:ident,
3950        name: $name:ident,
3951        tag: $tag:literal,
3952        arms: { $($arms:tt)* },
3953        cur_rename: ($($rename:tt)?),
3954        input: ( $vname:ident )
3955    ) => {
3956        $crate::__to_json_internal_walk!(
3957            receiver: $r,
3958            sink: $w,
3959            name: $name,
3960            tag: $tag,
3961            arms: {
3962                $($arms)*
3963                &$name::$vname => {
3964                    $w.write_raw_bytes(b"{")?;
3965                    $w.write_escaped_str($tag)?;
3966                    $w.write_raw_bytes(b":\"")?;
3967                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3968                    $w.write_raw_bytes(b"\"}")?;
3969                    ::core::result::Result::Ok(())
3970                }
3971            },
3972            cur_rename: (),
3973            input: ()
3974        )
3975    };
3976
3977    // Struct variant: `{"tag":"VariantName","field1":..,"field2":..}`.
3978    (
3979        receiver: $r:ident,
3980        sink: $w:ident,
3981        name: $name:ident,
3982        tag: $tag:literal,
3983        arms: { $($arms:tt)* },
3984        cur_rename: ($($rename:tt)?),
3985        input: ( $vname:ident { $($fname:ident : $_fty:ty),+ $(,)? } $(, $($rest:tt)*)? )
3986    ) => {
3987        $crate::__to_json_internal_walk!(
3988            receiver: $r,
3989            sink: $w,
3990            name: $name,
3991            tag: $tag,
3992            arms: {
3993                $($arms)*
3994                &$name::$vname { $(ref $fname),+ } => {
3995                    $w.write_raw_bytes(b"{")?;
3996                    $w.write_escaped_str($tag)?;
3997                    $w.write_raw_bytes(b":\"")?;
3998                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
3999                    $w.write_raw_bytes(b"\"")?;
4000                    $(
4001                        $w.write_raw_bytes(
4002                            ::core::concat!(",\"", ::core::stringify!($fname), "\":").as_bytes()
4003                        )?;
4004                        $crate::ToJson::write_json($fname, $w)?;
4005                    )+
4006                    $w.write_raw_bytes(b"}")?;
4007                    ::core::result::Result::Ok(())
4008                }
4009            },
4010            cur_rename: (),
4011            input: ( $($($rest)*)? )
4012        )
4013    };
4014}
4015
4016// ============================================================================
4017// Adjacently-tagged enum walker.
4018//
4019// Each variant emits {"tag":"Name","content":<payload>}. Unit
4020// variants omit the content key entirely (mirror the parse side).
4021// All four variant shapes are supported.
4022// ============================================================================
4023
4024#[doc(hidden)]
4025#[macro_export]
4026macro_rules! __to_json_adjacent_walk {
4027    // Terminal.
4028    (
4029        receiver: $r:ident,
4030        sink: $w:ident,
4031        name: $name:ident,
4032        tag: $tag:literal,
4033        content: $content:literal,
4034        arms: { $($arms:tt)* },
4035        cur_rename: (),
4036        input: ()
4037    ) => {
4038        match $r {
4039            $($arms)*
4040        }
4041    };
4042
4043    // bourne(rename = "x").
4044    (
4045        receiver: $r:ident,
4046        sink: $w:ident,
4047        name: $name:ident,
4048        tag: $tag:literal,
4049        content: $content:literal,
4050        arms: $arms:tt,
4051        cur_rename: (),
4052        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
4053    ) => {
4054        $crate::__to_json_adjacent_walk!(
4055            receiver: $r,
4056            sink: $w,
4057            name: $name,
4058            tag: $tag,
4059            content: $content,
4060            arms: $arms,
4061            cur_rename: ($renamed),
4062            input: ($($rest)*)
4063        )
4064    };
4065
4066    // Skip other attributes.
4067    (
4068        receiver: $r:ident,
4069        sink: $w:ident,
4070        name: $name:ident,
4071        tag: $tag:literal,
4072        content: $content:literal,
4073        arms: $arms:tt,
4074        cur_rename: ($($rename:tt)?),
4075        input: ( #[$_other:meta] $($rest:tt)* )
4076    ) => {
4077        $crate::__to_json_adjacent_walk!(
4078            receiver: $r,
4079            sink: $w,
4080            name: $name,
4081            tag: $tag,
4082            content: $content,
4083            arms: $arms,
4084            cur_rename: ($($rename)?),
4085            input: ($($rest)*)
4086        )
4087    };
4088
4089    // Unit variant: `{"tag":"Name"}` — no content key.
4090    (
4091        receiver: $r:ident,
4092        sink: $w:ident,
4093        name: $name:ident,
4094        tag: $tag:literal,
4095        content: $content:literal,
4096        arms: { $($arms:tt)* },
4097        cur_rename: ($($rename:tt)?),
4098        input: ( $vname:ident , $($rest:tt)* )
4099    ) => {
4100        $crate::__to_json_adjacent_walk!(
4101            receiver: $r,
4102            sink: $w,
4103            name: $name,
4104            tag: $tag,
4105            content: $content,
4106            arms: {
4107                $($arms)*
4108                &$name::$vname => {
4109                    $w.write_raw_bytes(b"{")?;
4110                    $w.write_escaped_str($tag)?;
4111                    $w.write_raw_bytes(b":\"")?;
4112                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4113                    $w.write_raw_bytes(b"\"}")?;
4114                    ::core::result::Result::Ok(())
4115                }
4116            },
4117            cur_rename: (),
4118            input: ($($rest)*)
4119        )
4120    };
4121    (
4122        receiver: $r:ident,
4123        sink: $w:ident,
4124        name: $name:ident,
4125        tag: $tag:literal,
4126        content: $content:literal,
4127        arms: { $($arms:tt)* },
4128        cur_rename: ($($rename:tt)?),
4129        input: ( $vname:ident )
4130    ) => {
4131        $crate::__to_json_adjacent_walk!(
4132            receiver: $r,
4133            sink: $w,
4134            name: $name,
4135            tag: $tag,
4136            content: $content,
4137            arms: {
4138                $($arms)*
4139                &$name::$vname => {
4140                    $w.write_raw_bytes(b"{")?;
4141                    $w.write_escaped_str($tag)?;
4142                    $w.write_raw_bytes(b":\"")?;
4143                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4144                    $w.write_raw_bytes(b"\"}")?;
4145                    ::core::result::Result::Ok(())
4146                }
4147            },
4148            cur_rename: (),
4149            input: ()
4150        )
4151    };
4152
4153    // Newtype variant: `{"tag":"Name","content":<inner>}`.
4154    (
4155        receiver: $r:ident,
4156        sink: $w:ident,
4157        name: $name:ident,
4158        tag: $tag:literal,
4159        content: $content:literal,
4160        arms: { $($arms:tt)* },
4161        cur_rename: ($($rename:tt)?),
4162        input: ( $vname:ident ( $_fty:ty $(,)? ) $(, $($rest:tt)*)? )
4163    ) => {
4164        $crate::__to_json_adjacent_walk!(
4165            receiver: $r,
4166            sink: $w,
4167            name: $name,
4168            tag: $tag,
4169            content: $content,
4170            arms: {
4171                $($arms)*
4172                &$name::$vname(ref __inner) => {
4173                    $w.write_raw_bytes(b"{")?;
4174                    $w.write_escaped_str($tag)?;
4175                    $w.write_raw_bytes(b":\"")?;
4176                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4177                    $w.write_raw_bytes(b"\",")?;
4178                    $w.write_escaped_str($content)?;
4179                    $w.write_raw_bytes(b":")?;
4180                    $crate::ToJson::write_json(__inner, $w)?;
4181                    $w.write_raw_bytes(b"}")?;
4182                    ::core::result::Result::Ok(())
4183                }
4184            },
4185            cur_rename: (),
4186            input: ( $($($rest)*)? )
4187        )
4188    };
4189
4190    // Tuple variant (2 fields): content is a JSON array.
4191    (
4192        receiver: $r:ident,
4193        sink: $w:ident,
4194        name: $name:ident,
4195        tag: $tag:literal,
4196        content: $content:literal,
4197        arms: { $($arms:tt)* },
4198        cur_rename: ($($rename:tt)?),
4199        input: ( $vname:ident ( $_a:ty, $_b:ty $(,)? ) $(, $($rest:tt)*)? )
4200    ) => {
4201        $crate::__to_json_adjacent_walk!(
4202            receiver: $r,
4203            sink: $w,
4204            name: $name,
4205            tag: $tag,
4206            content: $content,
4207            arms: {
4208                $($arms)*
4209                &$name::$vname(ref __a, ref __b) => {
4210                    $w.write_raw_bytes(b"{")?;
4211                    $w.write_escaped_str($tag)?;
4212                    $w.write_raw_bytes(b":\"")?;
4213                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4214                    $w.write_raw_bytes(b"\",")?;
4215                    $w.write_escaped_str($content)?;
4216                    $w.write_raw_bytes(b":[")?;
4217                    $crate::ToJson::write_json(__a, $w)?;
4218                    $w.write_raw_bytes(b",")?;
4219                    $crate::ToJson::write_json(__b, $w)?;
4220                    $w.write_raw_bytes(b"]}")?;
4221                    ::core::result::Result::Ok(())
4222                }
4223            },
4224            cur_rename: (),
4225            input: ( $($($rest)*)? )
4226        )
4227    };
4228
4229    // Tuple variant (3 fields).
4230    (
4231        receiver: $r:ident,
4232        sink: $w:ident,
4233        name: $name:ident,
4234        tag: $tag:literal,
4235        content: $content:literal,
4236        arms: { $($arms:tt)* },
4237        cur_rename: ($($rename:tt)?),
4238        input: ( $vname:ident ( $_a:ty, $_b:ty, $_c:ty $(,)? ) $(, $($rest:tt)*)? )
4239    ) => {
4240        $crate::__to_json_adjacent_walk!(
4241            receiver: $r,
4242            sink: $w,
4243            name: $name,
4244            tag: $tag,
4245            content: $content,
4246            arms: {
4247                $($arms)*
4248                &$name::$vname(ref __a, ref __b, ref __c) => {
4249                    $w.write_raw_bytes(b"{")?;
4250                    $w.write_escaped_str($tag)?;
4251                    $w.write_raw_bytes(b":\"")?;
4252                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4253                    $w.write_raw_bytes(b"\",")?;
4254                    $w.write_escaped_str($content)?;
4255                    $w.write_raw_bytes(b":[")?;
4256                    $crate::ToJson::write_json(__a, $w)?;
4257                    $w.write_raw_bytes(b",")?;
4258                    $crate::ToJson::write_json(__b, $w)?;
4259                    $w.write_raw_bytes(b",")?;
4260                    $crate::ToJson::write_json(__c, $w)?;
4261                    $w.write_raw_bytes(b"]}")?;
4262                    ::core::result::Result::Ok(())
4263                }
4264            },
4265            cur_rename: (),
4266            input: ( $($($rest)*)? )
4267        )
4268    };
4269
4270    // Struct variant: content is a JSON object.
4271    (
4272        receiver: $r:ident,
4273        sink: $w:ident,
4274        name: $name:ident,
4275        tag: $tag:literal,
4276        content: $content:literal,
4277        arms: { $($arms:tt)* },
4278        cur_rename: ($($rename:tt)?),
4279        input: ( $vname:ident { $($fname:ident : $_fty:ty),+ $(,)? } $(, $($rest:tt)*)? )
4280    ) => {
4281        $crate::__to_json_adjacent_walk!(
4282            receiver: $r,
4283            sink: $w,
4284            name: $name,
4285            tag: $tag,
4286            content: $content,
4287            arms: {
4288                $($arms)*
4289                &$name::$vname { $(ref $fname),+ } => {
4290                    $w.write_raw_bytes(b"{")?;
4291                    $w.write_escaped_str($tag)?;
4292                    $w.write_raw_bytes(b":\"")?;
4293                    $w.write_str_raw($crate::__to_json_field_key!($vname, ($($rename)?)))?;
4294                    $w.write_raw_bytes(b"\",")?;
4295                    $w.write_escaped_str($content)?;
4296                    $w.write_raw_bytes(b":{")?;
4297                    let mut __first: bool = true;
4298                    $(
4299                        if !__first { $w.write_raw_bytes(b",")?; }
4300                        $w.write_raw_bytes(
4301                            ::core::concat!("\"", ::core::stringify!($fname), "\":").as_bytes()
4302                        )?;
4303                        $crate::ToJson::write_json($fname, $w)?;
4304                        __first = false;
4305                    )+
4306                    $w.write_raw_bytes(b"}}")?;
4307                    ::core::result::Result::Ok(())
4308                }
4309            },
4310            cur_rename: (),
4311            input: ( $($($rest)*)? )
4312        )
4313    };
4314}
4315
4316// ============================================================================
4317// Untagged enum walker.
4318//
4319// Each variant's payload is written bare with no surrounding tag.
4320// Unit → `null`, newtype → inner, tuple → array, struct → object.
4321// Variant-level rename has no meaning (no tag is emitted), so we
4322// simply ignore it.
4323// ============================================================================
4324
4325#[doc(hidden)]
4326#[macro_export]
4327macro_rules! __to_json_untagged_walk {
4328    // Terminal.
4329    (
4330        receiver: $r:ident,
4331        sink: $w:ident,
4332        name: $name:ident,
4333        arms: { $($arms:tt)* },
4334        input: ()
4335    ) => {
4336        match $r {
4337            $($arms)*
4338        }
4339    };
4340
4341    // Drop attributes — rename has no tag to retag here, ignore quietly.
4342    (
4343        receiver: $r:ident,
4344        sink: $w:ident,
4345        name: $name:ident,
4346        arms: $arms:tt,
4347        input: ( #[$_other:meta] $($rest:tt)* )
4348    ) => {
4349        $crate::__to_json_untagged_walk!(
4350            receiver: $r,
4351            sink: $w,
4352            name: $name,
4353            arms: $arms,
4354            input: ($($rest)*)
4355        )
4356    };
4357
4358    // Unit variant: emit `null`.
4359    (
4360        receiver: $r:ident,
4361        sink: $w:ident,
4362        name: $name:ident,
4363        arms: { $($arms:tt)* },
4364        input: ( $vname:ident , $($rest:tt)* )
4365    ) => {
4366        $crate::__to_json_untagged_walk!(
4367            receiver: $r,
4368            sink: $w,
4369            name: $name,
4370            arms: {
4371                $($arms)*
4372                &$name::$vname => {
4373                    $w.write_raw_bytes(b"null")?;
4374                    ::core::result::Result::Ok(())
4375                }
4376            },
4377            input: ($($rest)*)
4378        )
4379    };
4380    (
4381        receiver: $r:ident,
4382        sink: $w:ident,
4383        name: $name:ident,
4384        arms: { $($arms:tt)* },
4385        input: ( $vname:ident )
4386    ) => {
4387        $crate::__to_json_untagged_walk!(
4388            receiver: $r,
4389            sink: $w,
4390            name: $name,
4391            arms: {
4392                $($arms)*
4393                &$name::$vname => {
4394                    $w.write_raw_bytes(b"null")?;
4395                    ::core::result::Result::Ok(())
4396                }
4397            },
4398            input: ()
4399        )
4400    };
4401
4402    // Newtype variant: emit the inner value bare.
4403    (
4404        receiver: $r:ident,
4405        sink: $w:ident,
4406        name: $name:ident,
4407        arms: { $($arms:tt)* },
4408        input: ( $vname:ident ( $_fty:ty $(,)? ) $(, $($rest:tt)*)? )
4409    ) => {
4410        $crate::__to_json_untagged_walk!(
4411            receiver: $r,
4412            sink: $w,
4413            name: $name,
4414            arms: {
4415                $($arms)*
4416                &$name::$vname(ref __inner) => {
4417                    $crate::ToJson::write_json(__inner, $w)?;
4418                    ::core::result::Result::Ok(())
4419                }
4420            },
4421            input: ( $($($rest)*)? )
4422        )
4423    };
4424
4425    // Tuple variant (2 fields): emit as array.
4426    (
4427        receiver: $r:ident,
4428        sink: $w:ident,
4429        name: $name:ident,
4430        arms: { $($arms:tt)* },
4431        input: ( $vname:ident ( $_a:ty, $_b:ty $(,)? ) $(, $($rest:tt)*)? )
4432    ) => {
4433        $crate::__to_json_untagged_walk!(
4434            receiver: $r,
4435            sink: $w,
4436            name: $name,
4437            arms: {
4438                $($arms)*
4439                &$name::$vname(ref __a, ref __b) => {
4440                    $w.write_raw_bytes(b"[")?;
4441                    $crate::ToJson::write_json(__a, $w)?;
4442                    $w.write_raw_bytes(b",")?;
4443                    $crate::ToJson::write_json(__b, $w)?;
4444                    $w.write_raw_bytes(b"]")?;
4445                    ::core::result::Result::Ok(())
4446                }
4447            },
4448            input: ( $($($rest)*)? )
4449        )
4450    };
4451
4452    // Tuple variant (3 fields).
4453    (
4454        receiver: $r:ident,
4455        sink: $w:ident,
4456        name: $name:ident,
4457        arms: { $($arms:tt)* },
4458        input: ( $vname:ident ( $_a:ty, $_b:ty, $_c:ty $(,)? ) $(, $($rest:tt)*)? )
4459    ) => {
4460        $crate::__to_json_untagged_walk!(
4461            receiver: $r,
4462            sink: $w,
4463            name: $name,
4464            arms: {
4465                $($arms)*
4466                &$name::$vname(ref __a, ref __b, ref __c) => {
4467                    $w.write_raw_bytes(b"[")?;
4468                    $crate::ToJson::write_json(__a, $w)?;
4469                    $w.write_raw_bytes(b",")?;
4470                    $crate::ToJson::write_json(__b, $w)?;
4471                    $w.write_raw_bytes(b",")?;
4472                    $crate::ToJson::write_json(__c, $w)?;
4473                    $w.write_raw_bytes(b"]")?;
4474                    ::core::result::Result::Ok(())
4475                }
4476            },
4477            input: ( $($($rest)*)? )
4478        )
4479    };
4480
4481    // Struct variant: emit as object.
4482    (
4483        receiver: $r:ident,
4484        sink: $w:ident,
4485        name: $name:ident,
4486        arms: { $($arms:tt)* },
4487        input: ( $vname:ident { $($fname:ident : $_fty:ty),+ $(,)? } $(, $($rest:tt)*)? )
4488    ) => {
4489        $crate::__to_json_untagged_walk!(
4490            receiver: $r,
4491            sink: $w,
4492            name: $name,
4493            arms: {
4494                $($arms)*
4495                &$name::$vname { $(ref $fname),+ } => {
4496                    $w.write_raw_bytes(b"{")?;
4497                    let mut __first: bool = true;
4498                    $(
4499                        if !__first { $w.write_raw_bytes(b",")?; }
4500                        $w.write_raw_bytes(
4501                            ::core::concat!("\"", ::core::stringify!($fname), "\":").as_bytes()
4502                        )?;
4503                        $crate::ToJson::write_json($fname, $w)?;
4504                        __first = false;
4505                    )+
4506                    $w.write_raw_bytes(b"}")?;
4507                    ::core::result::Result::Ok(())
4508                }
4509            },
4510            input: ( $($($rest)*)? )
4511        )
4512    };
4513}
4514
4515// ============================================================================
4516// Tuple-walk: emit `, self.IDX.write_json(w)?;` for each remaining
4517// field, incrementing IDX. Mirrors `__from_json_tuple_walk` on the
4518// parse side.
4519//
4520// macro_rules! has no integer arithmetic, so the index has to be a
4521// separate ident at each call site. We emit numeric idents (1, 2, 3,
4522// ...) by hand: the macro takes an explicit `idx:` head and recurses
4523// with the next number. A helper for arities up to 6 is enough for
4524// every shape `from_json!` supports.
4525// ============================================================================
4526
4527#[doc(hidden)]
4528#[macro_export]
4529macro_rules! __to_json_tuple_walk {
4530    // Terminal: nothing left.
4531    (
4532        self_ref: $self:ident,
4533        sink: $w:ident,
4534        idx: $_idx:tt,
4535        remaining: []
4536    ) => {};
4537
4538    // 1 field remaining: emit it at $idx.
4539    (
4540        self_ref: $self:ident,
4541        sink: $w:ident,
4542        idx: 1,
4543        remaining: [ ($_fty:ty) ]
4544    ) => {
4545        $w.write_raw_bytes(b",")?;
4546        $crate::ToJson::write_json(&$self.1, $w)?;
4547    };
4548    (
4549        self_ref: $self:ident,
4550        sink: $w:ident,
4551        idx: 2,
4552        remaining: [ ($_fty:ty) ]
4553    ) => {
4554        $w.write_raw_bytes(b",")?;
4555        $crate::ToJson::write_json(&$self.2, $w)?;
4556    };
4557    (
4558        self_ref: $self:ident,
4559        sink: $w:ident,
4560        idx: 3,
4561        remaining: [ ($_fty:ty) ]
4562    ) => {
4563        $w.write_raw_bytes(b",")?;
4564        $crate::ToJson::write_json(&$self.3, $w)?;
4565    };
4566    (
4567        self_ref: $self:ident,
4568        sink: $w:ident,
4569        idx: 4,
4570        remaining: [ ($_fty:ty) ]
4571    ) => {
4572        $w.write_raw_bytes(b",")?;
4573        $crate::ToJson::write_json(&$self.4, $w)?;
4574    };
4575    (
4576        self_ref: $self:ident,
4577        sink: $w:ident,
4578        idx: 5,
4579        remaining: [ ($_fty:ty) ]
4580    ) => {
4581        $w.write_raw_bytes(b",")?;
4582        $crate::ToJson::write_json(&$self.5, $w)?;
4583    };
4584
4585    // 2+ fields remaining at idx 1: emit and recurse.
4586    (
4587        self_ref: $self:ident,
4588        sink: $w:ident,
4589        idx: 1,
4590        remaining: [ ($_fty:ty) $(($rest:ty))+ ]
4591    ) => {
4592        $w.write_raw_bytes(b",")?;
4593        $crate::ToJson::write_json(&$self.1, $w)?;
4594        $crate::__to_json_tuple_walk!(
4595            self_ref: $self,
4596            sink: $w,
4597            idx: 2,
4598            remaining: [ $(($rest))+ ]
4599        )
4600    };
4601    (
4602        self_ref: $self:ident,
4603        sink: $w:ident,
4604        idx: 2,
4605        remaining: [ ($_fty:ty) $(($rest:ty))+ ]
4606    ) => {
4607        $w.write_raw_bytes(b",")?;
4608        $crate::ToJson::write_json(&$self.2, $w)?;
4609        $crate::__to_json_tuple_walk!(
4610            self_ref: $self,
4611            sink: $w,
4612            idx: 3,
4613            remaining: [ $(($rest))+ ]
4614        )
4615    };
4616    (
4617        self_ref: $self:ident,
4618        sink: $w:ident,
4619        idx: 3,
4620        remaining: [ ($_fty:ty) $(($rest:ty))+ ]
4621    ) => {
4622        $w.write_raw_bytes(b",")?;
4623        $crate::ToJson::write_json(&$self.3, $w)?;
4624        $crate::__to_json_tuple_walk!(
4625            self_ref: $self,
4626            sink: $w,
4627            idx: 4,
4628            remaining: [ $(($rest))+ ]
4629        )
4630    };
4631    (
4632        self_ref: $self:ident,
4633        sink: $w:ident,
4634        idx: 4,
4635        remaining: [ ($_fty:ty) $(($rest:ty))+ ]
4636    ) => {
4637        $w.write_raw_bytes(b",")?;
4638        $crate::ToJson::write_json(&$self.4, $w)?;
4639        $crate::__to_json_tuple_walk!(
4640            self_ref: $self,
4641            sink: $w,
4642            idx: 5,
4643            remaining: [ $(($rest))+ ]
4644        )
4645    };
4646}
4647
4648// ============================================================================
4649// Struct-definition emitter for `to_json!`.
4650//
4651// Identical structure to `__from_json_emit_struct_def` — strips
4652// `#[bourne(...)]` field attrs and re-emits the clean type. The
4653// attribute strip walker is shared via `__from_json_strip_walk` since
4654// the strip rules are the same (rename, skip, default, skip_if_none
4655// all get dropped from the emitted def).
4656//
4657// `skip_if_none` is new on the ser side; we add a strip arm for it
4658// inside `__from_json_strip_walk` further down.
4659// ============================================================================
4660
4661#[doc(hidden)]
4662#[macro_export]
4663macro_rules! __to_json_emit_struct_def {
4664    (
4665        attrs: { $(#[$attr:meta])* },
4666        vis: $vis:vis,
4667        name: $name:ident,
4668        generics_def: $gen:tt,
4669        body: ($($body:tt)*)
4670    ) => {
4671        // Reuse the from_json strip walker. The output is identical:
4672        // a clean struct def with bourne-attrs stripped and every
4673        // other attr (incl. user-written ones) preserved.
4674        $crate::__from_json_emit_struct_def!(
4675            attrs: { $(#[$attr])* },
4676            vis: $vis,
4677            name: $name,
4678            generics_def: $gen,
4679            body: ($($body)*)
4680        );
4681    };
4682}
4683
4684// ============================================================================
4685// `__to_json_named_body` — emits the struct-impl body.
4686//
4687// The body shape:
4688//
4689//   __w.write_byte(b'{')?;
4690//   let mut __first: bool = true;
4691//   <per-field emit>
4692//   __w.write_byte(b'}')?;
4693//   ::core::result::Result::Ok(())
4694//
4695// Per-field emit (no skip_if_none):
4696//
4697//   if !__first { __w.write_byte(b',')?; }
4698//   __w.write_escaped_str("key")?;
4699//   __w.write_byte(b':')?;
4700//   $crate::ToJson::write_json(&self.fname, __w)?;
4701//   __first = false;
4702//
4703// Per-field emit (skip_if_none, only valid on Option<T>):
4704//
4705//   if let ::core::option::Option::Some(ref __v) = self.fname {
4706//       if !__first { __w.write_byte(b',')?; }
4707//       __w.write_escaped_str("key")?;
4708//       __w.write_byte(b':')?;
4709//       $crate::ToJson::write_json(__v, __w)?;
4710//       __first = false;
4711//   }
4712//
4713// `__first` carries the "have we emitted any field yet" state, which
4714// is the cleanest way to handle dynamically-skipped fields. Constant
4715// folding will eliminate the `if !__first` branch in the first
4716// iteration; the rest is one cmp+branch per field, dwarfed by the
4717// actual ToJson::write_json call.
4718// ============================================================================
4719
4720#[doc(hidden)]
4721#[macro_export]
4722macro_rules! __to_json_named_body {
4723    ($self:ident, $w:ident, $($body:tt)*) => {{
4724        $w.write_raw_bytes(b"{")?;
4725        // `__first` exists only for the dynamic-comma path: as soon as
4726        // a `skip_if_none` field is encountered, comma placement
4727        // becomes runtime-dependent and subsequent fields consult this
4728        // flag. Pure-plain structs never read or write it (the walker
4729        // emits static `,"key":` literals via `concat!`), so the
4730        // `#[allow(unused)]` suppresses a "let assigned never read"
4731        // warning for that common case.
4732        #[allow(unused_assignments, unused_mut, unused_variables)]
4733        let mut __first: bool = true;
4734        $crate::__to_json_named_walk!(
4735            self_ref: $self,
4736            sink: $w,
4737            first: __first,
4738            emit: { },
4739            cur_rename: (),
4740            cur_skip: (),
4741            cur_skip_if_none: (),
4742            cur_name: (),
4743            ftokens: [],
4744            static_first: (yes),
4745            input: ($($body)*)
4746        );
4747        $w.write_raw_bytes(b"}")?;
4748        ::core::result::Result::Ok(())
4749    }};
4750}
4751
4752// ============================================================================
4753// The tt-muncher for named-struct fields.
4754//
4755// Mirrors `__from_json_walk`'s state machine but with simpler
4756// per-field state. The four named buckets:
4757//
4758//   - `emit`: append-only stream of per-field emit blocks.
4759//   - `cur_rename`, `cur_skip`, `cur_skip_if_none`: per-field
4760//     attribute state. Cleared after each commit.
4761//   - `cur_name`, `ftokens`: per-field name + type accumulator. Type
4762//     tokens are not used to emit anything (the impl just calls
4763//     `ToJson::write_json` on the value, which is type-erased through
4764//     trait dispatch), but we still consume them to advance the input
4765//     correctly.
4766// ============================================================================
4767
4768#[doc(hidden)]
4769#[macro_export]
4770macro_rules! __to_json_named_walk {
4771    // ---------- Phase 1: terminal — input exhausted, no in-flight field. ----------
4772    (
4773        self_ref: $self:ident,
4774        sink: $w:ident,
4775        first: $first:ident,
4776        emit: { $($emit:tt)* },
4777        cur_rename: (),
4778        cur_skip: (),
4779        cur_skip_if_none: (),
4780        cur_name: (),
4781        ftokens: [],
4782        static_first: ($($_sf:tt)?),
4783        input: ()
4784    ) => {
4785        $($emit)*
4786    };
4787
4788    // ---------- Phase 1b-skip: terminal commit for #[bourne(skip)]. ----------
4789    //
4790    // Skipped fields contribute nothing to `emit`. Type tokens are
4791    // discarded. `static_first` is preserved unchanged — a skipped
4792    // field neither emits punctuation nor changes the leading-comma
4793    // posture of the next field.
4794    (
4795        self_ref: $self:ident,
4796        sink: $w:ident,
4797        first: $first:ident,
4798        emit: { $($emit:tt)* },
4799        cur_rename: ($($_rn:tt)?),
4800        cur_skip: (skip),
4801        cur_skip_if_none: ($($_si:tt)?),
4802        cur_name: ($fname:ident),
4803        ftokens: [ $($_ft:tt)+ ],
4804        input: ()
4805    ) => {
4806        $crate::__to_json_named_walk!(
4807            self_ref: $self,
4808            sink: $w,
4809            first: $first,
4810            emit: { $($emit)* },
4811            cur_rename: (),
4812            cur_skip: (),
4813            cur_skip_if_none: (),
4814            cur_name: (),
4815            ftokens: [],
4816            static_first: (no),  // doesn't matter — input exhausted
4817            input: ()
4818        )
4819    };
4820
4821    // ---------- Phase 1c: terminal — last field, skip_if_none variant. ----------
4822    //
4823    // skip_if_none always emits a runtime conditional regardless of
4824    // `static_first`. Two flavors:
4825    //   - `static_first: (yes)`: this is the *only* field, so
4826    //     unconditionally elide the leading comma (the `if !$first`
4827    //     branch is dead — `__first` is still `true`).
4828    //   - `static_first: (no | maybe)`: prior fields may or may not
4829    //     have committed. If `(no)`, a prior plain field always
4830    //     committed and we always need the comma. If `(maybe)`, fall
4831    //     back to the runtime flag.
4832    (
4833        self_ref: $self:ident,
4834        sink: $w:ident,
4835        first: $first:ident,
4836        emit: { $($emit:tt)* },
4837        cur_rename: ($($rename:tt)?),
4838        cur_skip: (),
4839        cur_skip_if_none: (yes),
4840        cur_name: ($fname:ident),
4841        ftokens: [ $($_ft:tt)+ ],
4842        input: ()
4843    ) => {
4844        $crate::__to_json_named_walk!(
4845            self_ref: $self,
4846            sink: $w,
4847            first: $first,
4848            emit: {
4849                $($emit)*
4850                if let ::core::option::Option::Some(ref __v) = $self.$fname {
4851                    if !$first { $w.write_raw_bytes(b",")?; }
4852                    $w.write_escaped_str(
4853                        $crate::__to_json_field_key!($fname, ($($rename)?))
4854                    )?;
4855                    $w.write_raw_bytes(b":")?;
4856                    $crate::ToJson::write_json(__v, $w)?;
4857                    $first = false;
4858                }
4859            },
4860            cur_rename: (),
4861            cur_skip: (),
4862            cur_skip_if_none: (),
4863            cur_name: (),
4864            ftokens: [],
4865            static_first: (no),
4866            input: ()
4867        )
4868    };
4869
4870    // ---------- Phase 1d: terminal — last field, plain, no rename, static-known. ----------
4871    //
4872    // Fast path: no rename means the key is `stringify!($fname)`,
4873    // which is guaranteed to be a Rust ident — no escape-needing
4874    // bytes. Fuse `,"key":` (or `"key":` if first) into a single
4875    // `concat!()` literal and emit via `write_raw_bytes` (one
4876    // `extend_from_slice` on `ByteSink`).
4877    (
4878        self_ref: $self:ident,
4879        sink: $w:ident,
4880        first: $first:ident,
4881        emit: { $($emit:tt)* },
4882        cur_rename: (),
4883        cur_skip: (),
4884        cur_skip_if_none: (),
4885        cur_name: ($fname:ident),
4886        ftokens: [ $($_ft:tt)+ ],
4887        static_first: (yes),
4888        input: ()
4889    ) => {
4890        $crate::__to_json_named_walk!(
4891            self_ref: $self,
4892            sink: $w,
4893            first: $first,
4894            emit: {
4895                $($emit)*
4896                $w.write_raw_bytes(
4897                    ::core::concat!("\"", ::core::stringify!($fname), "\":").as_bytes()
4898                )?;
4899                $crate::ToJson::write_json(&$self.$fname, $w)?;
4900            },
4901            cur_rename: (),
4902            cur_skip: (),
4903            cur_skip_if_none: (),
4904            cur_name: (),
4905            ftokens: [],
4906            static_first: (no),
4907            input: ()
4908        )
4909    };
4910    (
4911        self_ref: $self:ident,
4912        sink: $w:ident,
4913        first: $first:ident,
4914        emit: { $($emit:tt)* },
4915        cur_rename: (),
4916        cur_skip: (),
4917        cur_skip_if_none: (),
4918        cur_name: ($fname:ident),
4919        ftokens: [ $($_ft:tt)+ ],
4920        static_first: (no),
4921        input: ()
4922    ) => {
4923        $crate::__to_json_named_walk!(
4924            self_ref: $self,
4925            sink: $w,
4926            first: $first,
4927            emit: {
4928                $($emit)*
4929                $w.write_raw_bytes(
4930                    ::core::concat!(",\"", ::core::stringify!($fname), "\":").as_bytes()
4931                )?;
4932                $crate::ToJson::write_json(&$self.$fname, $w)?;
4933            },
4934            cur_rename: (),
4935            cur_skip: (),
4936            cur_skip_if_none: (),
4937            cur_name: (),
4938            ftokens: [],
4939            static_first: (no),
4940            input: ()
4941        )
4942    };
4943
4944    // ---------- Phase 1d: terminal — last field, plain, dynamic comma. ----------
4945    //
4946    // Slow path. Either:
4947    //   - the field is renamed (we keep `write_escaped_str` because
4948    //     the rename literal is user-controlled and may legitimately
4949    //     contain bytes that need escaping), or
4950    //   - a prior `skip_if_none` made comma placement runtime-
4951    //     dependent (`static_first: (maybe)`).
4952    (
4953        self_ref: $self:ident,
4954        sink: $w:ident,
4955        first: $first:ident,
4956        emit: { $($emit:tt)* },
4957        cur_rename: ($($rename:tt)?),
4958        cur_skip: (),
4959        cur_skip_if_none: (),
4960        cur_name: ($fname:ident),
4961        ftokens: [ $($_ft:tt)+ ],
4962        static_first: ($($_sf:tt)?),
4963        input: ()
4964    ) => {
4965        $crate::__to_json_named_walk!(
4966            self_ref: $self,
4967            sink: $w,
4968            first: $first,
4969            emit: {
4970                $($emit)*
4971                if !$first { $w.write_raw_bytes(b",")?; }
4972                $w.write_escaped_str(
4973                    $crate::__to_json_field_key!($fname, ($($rename)?))
4974                )?;
4975                $w.write_raw_bytes(b":")?;
4976                $crate::ToJson::write_json(&$self.$fname, $w)?;
4977                $first = false;
4978            },
4979            cur_rename: (),
4980            cur_skip: (),
4981            cur_skip_if_none: (),
4982            cur_name: (),
4983            ftokens: [],
4984            static_first: (maybe),
4985            input: ()
4986        )
4987    };
4988
4989    // ---------- bourne(rename = "x") on the next field. ----------
4990    (
4991        self_ref: $self:ident,
4992        sink: $w:ident,
4993        first: $first:ident,
4994        emit: $emit:tt,
4995        cur_rename: (),
4996        cur_skip: ($($skip:tt)?),
4997        cur_skip_if_none: ($($sin:tt)?),
4998        cur_name: (),
4999        ftokens: [],
5000        static_first: ($($sf:tt)?),
5001        input: ( #[bourne(rename = $renamed:literal)] $($rest:tt)* )
5002    ) => {
5003        $crate::__to_json_named_walk!(
5004            self_ref: $self,
5005            sink: $w,
5006            first: $first,
5007            emit: $emit,
5008            cur_rename: ($renamed),
5009            cur_skip: ($($skip)?),
5010            cur_skip_if_none: ($($sin)?),
5011            cur_name: (),
5012            ftokens: [],
5013            static_first: ($($sf)?),
5014            input: ($($rest)*)
5015        )
5016    };
5017
5018    // ---------- bourne(skip) on the next field. ----------
5019    (
5020        self_ref: $self:ident,
5021        sink: $w:ident,
5022        first: $first:ident,
5023        emit: $emit:tt,
5024        cur_rename: ($($rename:tt)?),
5025        cur_skip: (),
5026        cur_skip_if_none: ($($sin:tt)?),
5027        cur_name: (),
5028        ftokens: [],
5029        static_first: ($($sf:tt)?),
5030        input: ( #[bourne(skip)] $($rest:tt)* )
5031    ) => {
5032        $crate::__to_json_named_walk!(
5033            self_ref: $self,
5034            sink: $w,
5035            first: $first,
5036            emit: $emit,
5037            cur_rename: ($($rename)?),
5038            cur_skip: (skip),
5039            cur_skip_if_none: ($($sin)?),
5040            cur_name: (),
5041            ftokens: [],
5042            static_first: ($($sf)?),
5043            input: ($($rest)*)
5044        )
5045    };
5046
5047    // ---------- bourne(skip_if_none) on the next field. ----------
5048    (
5049        self_ref: $self:ident,
5050        sink: $w:ident,
5051        first: $first:ident,
5052        emit: $emit:tt,
5053        cur_rename: ($($rename:tt)?),
5054        cur_skip: ($($skip:tt)?),
5055        cur_skip_if_none: (),
5056        cur_name: (),
5057        ftokens: [],
5058        static_first: ($($sf:tt)?),
5059        input: ( #[bourne(skip_if_none)] $($rest:tt)* )
5060    ) => {
5061        $crate::__to_json_named_walk!(
5062            self_ref: $self,
5063            sink: $w,
5064            first: $first,
5065            emit: $emit,
5066            cur_rename: ($($rename)?),
5067            cur_skip: ($($skip)?),
5068            cur_skip_if_none: (yes),
5069            cur_name: (),
5070            ftokens: [],
5071            static_first: ($($sf)?),
5072            input: ($($rest)*)
5073        )
5074    };
5075
5076    // ---------- bourne(default) on the next field — no-op for ser. ----------
5077    (
5078        self_ref: $self:ident,
5079        sink: $w:ident,
5080        first: $first:ident,
5081        emit: $emit:tt,
5082        cur_rename: ($($rename:tt)?),
5083        cur_skip: ($($skip:tt)?),
5084        cur_skip_if_none: ($($sin:tt)?),
5085        cur_name: (),
5086        ftokens: [],
5087        static_first: ($($sf:tt)?),
5088        input: ( #[bourne(default)] $($rest:tt)* )
5089    ) => {
5090        $crate::__to_json_named_walk!(
5091            self_ref: $self,
5092            sink: $w,
5093            first: $first,
5094            emit: $emit,
5095            cur_rename: ($($rename)?),
5096            cur_skip: ($($skip)?),
5097            cur_skip_if_none: ($($sin)?),
5098            cur_name: (),
5099            ftokens: [],
5100            static_first: ($($sf)?),
5101            input: ($($rest)*)
5102        )
5103    };
5104
5105    // ---------- compound: rename + default ----------
5106    (
5107        self_ref: $self:ident,
5108        sink: $w:ident,
5109        first: $first:ident,
5110        emit: $emit:tt,
5111        cur_rename: (),
5112        cur_skip: ($($skip:tt)?),
5113        cur_skip_if_none: ($($sin:tt)?),
5114        cur_name: (),
5115        ftokens: [],
5116        static_first: ($($sf:tt)?),
5117        input: ( #[bourne(rename = $renamed:literal, default)] $($rest:tt)* )
5118    ) => {
5119        $crate::__to_json_named_walk!(
5120            self_ref: $self,
5121            sink: $w,
5122            first: $first,
5123            emit: $emit,
5124            cur_rename: ($renamed),
5125            cur_skip: ($($skip)?),
5126            cur_skip_if_none: ($($sin)?),
5127            cur_name: (),
5128            ftokens: [],
5129            static_first: ($($sf)?),
5130            input: ($($rest)*)
5131        )
5132    };
5133
5134    // ---------- Phase 2 entry: read field name. ----------
5135    (
5136        self_ref: $self:ident,
5137        sink: $w:ident,
5138        first: $first:ident,
5139        emit: $emit:tt,
5140        cur_rename: ($($rename:tt)?),
5141        cur_skip: ($($skip:tt)?),
5142        cur_skip_if_none: ($($sin:tt)?),
5143        cur_name: (),
5144        ftokens: [],
5145        static_first: ($($sf:tt)?),
5146        input: ( $_fvis:vis $fname:ident : $($rest:tt)* )
5147    ) => {
5148        $crate::__to_json_named_walk!(
5149            self_ref: $self,
5150            sink: $w,
5151            first: $first,
5152            emit: $emit,
5153            cur_rename: ($($rename)?),
5154            cur_skip: ($($skip)?),
5155            cur_skip_if_none: ($($sin)?),
5156            cur_name: ($fname),
5157            ftokens: [],
5158            static_first: ($($sf)?),
5159            input: ($($rest)*)
5160        )
5161    };
5162
5163    // ---------- Phase 2: comma commits the in-flight field. ----------
5164    //
5165    // skip variant: drop the field on the floor. `static_first` is
5166    // unchanged — a skipped field neither emits nor changes the
5167    // leading-comma posture of the next field.
5168    (
5169        self_ref: $self:ident,
5170        sink: $w:ident,
5171        first: $first:ident,
5172        emit: $emit:tt,
5173        cur_rename: ($($_rn:tt)?),
5174        cur_skip: (skip),
5175        cur_skip_if_none: ($($_si:tt)?),
5176        cur_name: ($fname:ident),
5177        ftokens: [ $($_ft:tt)+ ],
5178        static_first: ($($sf:tt)?),
5179        input: ( , $($rest:tt)* )
5180    ) => {
5181        $crate::__to_json_named_walk!(
5182            self_ref: $self,
5183            sink: $w,
5184            first: $first,
5185            emit: $emit,
5186            cur_rename: (),
5187            cur_skip: (),
5188            cur_skip_if_none: (),
5189            cur_name: (),
5190            ftokens: [],
5191            static_first: ($($sf)?),
5192            input: ($($rest)*)
5193        )
5194    };
5195
5196    // skip_if_none variant: emit the conditional block. After the
5197    // block, comma posture is runtime-dependent (the field may or may
5198    // not have committed), so transition `static_first` to (maybe).
5199    //
5200    // Two sub-arms specialize the leading-comma computation by current
5201    // `static_first`: (yes) means we're definitely the first emit and
5202    // the comma never fires; (no | maybe) keeps the runtime branch.
5203    (
5204        self_ref: $self:ident,
5205        sink: $w:ident,
5206        first: $first:ident,
5207        emit: { $($emit:tt)* },
5208        cur_rename: ($($rename:tt)?),
5209        cur_skip: (),
5210        cur_skip_if_none: (yes),
5211        cur_name: ($fname:ident),
5212        ftokens: [ $($_ft:tt)+ ],
5213        static_first: (yes),
5214        input: ( , $($rest:tt)* )
5215    ) => {
5216        $crate::__to_json_named_walk!(
5217            self_ref: $self,
5218            sink: $w,
5219            first: $first,
5220            emit: {
5221                $($emit)*
5222                if let ::core::option::Option::Some(ref __v) = $self.$fname {
5223                    $w.write_escaped_str(
5224                        $crate::__to_json_field_key!($fname, ($($rename)?))
5225                    )?;
5226                    $w.write_raw_bytes(b":")?;
5227                    $crate::ToJson::write_json(__v, $w)?;
5228                    $first = false;
5229                }
5230            },
5231            cur_rename: (),
5232            cur_skip: (),
5233            cur_skip_if_none: (),
5234            cur_name: (),
5235            ftokens: [],
5236            static_first: (maybe),
5237            input: ($($rest)*)
5238        )
5239    };
5240    (
5241        self_ref: $self:ident,
5242        sink: $w:ident,
5243        first: $first:ident,
5244        emit: { $($emit:tt)* },
5245        cur_rename: ($($rename:tt)?),
5246        cur_skip: (),
5247        cur_skip_if_none: (yes),
5248        cur_name: ($fname:ident),
5249        ftokens: [ $($_ft:tt)+ ],
5250        static_first: ($($_sf:tt)?),
5251        input: ( , $($rest:tt)* )
5252    ) => {
5253        $crate::__to_json_named_walk!(
5254            self_ref: $self,
5255            sink: $w,
5256            first: $first,
5257            emit: {
5258                $($emit)*
5259                if let ::core::option::Option::Some(ref __v) = $self.$fname {
5260                    if !$first { $w.write_raw_bytes(b",")?; }
5261                    $w.write_escaped_str(
5262                        $crate::__to_json_field_key!($fname, ($($rename)?))
5263                    )?;
5264                    $w.write_raw_bytes(b":")?;
5265                    $crate::ToJson::write_json(__v, $w)?;
5266                    $first = false;
5267                }
5268            },
5269            cur_rename: (),
5270            cur_skip: (),
5271            cur_skip_if_none: (),
5272            cur_name: (),
5273            ftokens: [],
5274            static_first: (maybe),
5275            input: ($($rest)*)
5276        )
5277    };
5278
5279    // plain variant, no rename, static-first: yes.
5280    //
5281    // Fast path. `concat!("\"", stringify!($fname), "\":")` collapses
5282    // to a single &'static byte slice, and the value is the only field
5283    // committed so far so no leading comma. Single `write_raw_bytes`
5284    // (one `extend_from_slice` on `ByteSink`).
5285    //
5286    // `$first = false;` keeps the runtime flag in sync so a later
5287    // skip_if_none or renamed field that falls back to the dynamic
5288    // arm sees the correct posture. The store is hoisted out of any
5289    // loop in the caller and disappears under register allocation.
5290    (
5291        self_ref: $self:ident,
5292        sink: $w:ident,
5293        first: $first:ident,
5294        emit: { $($emit:tt)* },
5295        cur_rename: (),
5296        cur_skip: (),
5297        cur_skip_if_none: (),
5298        cur_name: ($fname:ident),
5299        ftokens: [ $($_ft:tt)+ ],
5300        static_first: (yes),
5301        input: ( , $($rest:tt)* )
5302    ) => {
5303        $crate::__to_json_named_walk!(
5304            self_ref: $self,
5305            sink: $w,
5306            first: $first,
5307            emit: {
5308                $($emit)*
5309                $w.write_raw_bytes(
5310                    ::core::concat!("\"", ::core::stringify!($fname), "\":").as_bytes()
5311                )?;
5312                $crate::ToJson::write_json(&$self.$fname, $w)?;
5313                $first = false;
5314            },
5315            cur_rename: (),
5316            cur_skip: (),
5317            cur_skip_if_none: (),
5318            cur_name: (),
5319            ftokens: [],
5320            static_first: (no),
5321            input: ($($rest)*)
5322        )
5323    };
5324
5325    // plain variant, no rename, static-first: no.
5326    //
5327    // Fast path. The leading comma is also static, so fold it into
5328    // the same byte literal: `,"key":`.
5329    (
5330        self_ref: $self:ident,
5331        sink: $w:ident,
5332        first: $first:ident,
5333        emit: { $($emit:tt)* },
5334        cur_rename: (),
5335        cur_skip: (),
5336        cur_skip_if_none: (),
5337        cur_name: ($fname:ident),
5338        ftokens: [ $($_ft:tt)+ ],
5339        static_first: (no),
5340        input: ( , $($rest:tt)* )
5341    ) => {
5342        $crate::__to_json_named_walk!(
5343            self_ref: $self,
5344            sink: $w,
5345            first: $first,
5346            emit: {
5347                $($emit)*
5348                $w.write_raw_bytes(
5349                    ::core::concat!(",\"", ::core::stringify!($fname), "\":").as_bytes()
5350                )?;
5351                $crate::ToJson::write_json(&$self.$fname, $w)?;
5352            },
5353            cur_rename: (),
5354            cur_skip: (),
5355            cur_skip_if_none: (),
5356            cur_name: (),
5357            ftokens: [],
5358            static_first: (no),
5359            input: ($($rest)*)
5360        )
5361    };
5362
5363    // plain variant, dynamic comma fallback (rename set, OR a prior
5364    // `skip_if_none` made comma posture runtime-dependent).
5365    //
5366    // - Rename: `$renamed` is user-controlled and may contain bytes
5367    //   that need escaping; route through `write_escaped_str`.
5368    // - `static_first: (maybe)`: consult the runtime `__first` flag.
5369    (
5370        self_ref: $self:ident,
5371        sink: $w:ident,
5372        first: $first:ident,
5373        emit: { $($emit:tt)* },
5374        cur_rename: ($($rename:tt)?),
5375        cur_skip: (),
5376        cur_skip_if_none: (),
5377        cur_name: ($fname:ident),
5378        ftokens: [ $($_ft:tt)+ ],
5379        static_first: ($($_sf:tt)?),
5380        input: ( , $($rest:tt)* )
5381    ) => {
5382        $crate::__to_json_named_walk!(
5383            self_ref: $self,
5384            sink: $w,
5385            first: $first,
5386            emit: {
5387                $($emit)*
5388                if !$first { $w.write_raw_bytes(b",")?; }
5389                $w.write_escaped_str(
5390                    $crate::__to_json_field_key!($fname, ($($rename)?))
5391                )?;
5392                $w.write_raw_bytes(b":")?;
5393                $crate::ToJson::write_json(&$self.$fname, $w)?;
5394                $first = false;
5395            },
5396            cur_rename: (),
5397            cur_skip: (),
5398            cur_skip_if_none: (),
5399            cur_name: (),
5400            ftokens: [],
5401            static_first: (maybe),
5402            input: ($($rest)*)
5403        )
5404    };
5405
5406    // ---------- Phase 2: type-token accumulator. ----------
5407    //
5408    // Walk the field's type one token at a time. Each token gets
5409    // pushed onto `ftokens`. We never inspect ftokens — type info is
5410    // carried by `&self.fname` at runtime — but we still need to
5411    // consume each token to keep the input cursor advancing.
5412    (
5413        self_ref: $self:ident,
5414        sink: $w:ident,
5415        first: $first:ident,
5416        emit: $emit:tt,
5417        cur_rename: ($($rename:tt)?),
5418        cur_skip: ($($skip:tt)?),
5419        cur_skip_if_none: ($($sin:tt)?),
5420        cur_name: ($fname:ident),
5421        ftokens: [ $($ftokens:tt)* ],
5422        static_first: ($($sf:tt)?),
5423        input: ( $tok:tt $($rest:tt)* )
5424    ) => {
5425        $crate::__to_json_named_walk!(
5426            self_ref: $self,
5427            sink: $w,
5428            first: $first,
5429            emit: $emit,
5430            cur_rename: ($($rename)?),
5431            cur_skip: ($($skip)?),
5432            cur_skip_if_none: ($($sin)?),
5433            cur_name: ($fname),
5434            ftokens: [ $($ftokens)* $tok ],
5435            static_first: ($($sf)?),
5436            input: ($($rest)*)
5437        )
5438    };
5439}
5440
5441// ============================================================================
5442// Field-key resolver: rename overrides the ident's stringified form.
5443// Mirrors `__from_json_field_key`.
5444// ============================================================================
5445
5446#[doc(hidden)]
5447#[macro_export]
5448macro_rules! __to_json_field_key {
5449    ($fname:ident, ($renamed:literal)) => {
5450        $renamed
5451    };
5452    ($fname:ident, ()) => {
5453        ::core::stringify!($fname)
5454    };
5455}
5456
5457// ============================================================================
5458// `json!` — combined macro that emits the type definition once and
5459// generates both `FromJson` and `ToJson` impls.
5460//
5461// Without this, users who need both traits must choose between
5462// duplicating the struct definition or writing one impl by hand,
5463// because `from_json!` and `to_json!` each emit the type definition
5464// themselves.
5465//
5466// Every arm emits the type via the existing `__from_json_emit_struct_def!`
5467// / `__from_json_emit_enum_def!`, then splices both impl blocks.
5468// ============================================================================
5469
5470/// Emit a struct or enum together with both its [`FromJson`](crate::FromJson)
5471/// and [`ToJson`](crate::ToJson) impls.
5472///
5473/// This is the combined form of [`from_json!`] and [`to_json!`]. Use it
5474/// when a type needs to both parse and serialize — it emits the type
5475/// definition once, avoiding the duplicate-definition error you'd get
5476/// from invoking both single-trait macros on the same type.
5477///
5478/// ```
5479/// use json_bourne::{json, parse_str, to_string};
5480///
5481/// json! {
5482///     #[derive(Debug, PartialEq)]
5483///     struct Point { x: i32, y: i32 }
5484/// }
5485///
5486/// let p: Point = parse_str(r#"{"x":1,"y":2}"#).unwrap();
5487/// assert_eq!(to_string(&p).unwrap(), r#"{"x":1,"y":2}"#);
5488/// ```
5489#[macro_export]
5490macro_rules! json {
5491    // -----------------------------------------------------------------
5492    // Named-field struct, no generics.
5493    // -----------------------------------------------------------------
5494    (
5495        $(#[$attr:meta])*
5496        $vis:vis struct $name:ident { $($body:tt)* }
5497    ) => {
5498        $crate::__from_json_emit_struct_def!(
5499            attrs: { $(#[$attr])* },
5500            vis: $vis,
5501            name: $name,
5502            generics_def: (),
5503            body: ($($body)*)
5504        );
5505
5506        impl<'input> $crate::FromJson<'input> for $name {
5507            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5508                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
5509            }
5510        }
5511
5512        impl $crate::ToJson for $name {
5513            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5514                &self,
5515                __w: &mut __W,
5516            ) -> ::core::result::Result<(), __W::Error> {
5517                $crate::__to_json_named_body!(self, __w, $($body)*)
5518            }
5519        }
5520    };
5521
5522    // -----------------------------------------------------------------
5523    // Named-field struct, one lifetime.
5524    // -----------------------------------------------------------------
5525    (
5526        $(#[$attr:meta])*
5527        $vis:vis struct $name:ident < $lt:lifetime $(,)? > { $($body:tt)* }
5528    ) => {
5529        $crate::__from_json_emit_struct_def!(
5530            attrs: { $(#[$attr])* },
5531            vis: $vis,
5532            name: $name,
5533            generics_def: (<$lt>),
5534            body: ($($body)*)
5535        );
5536
5537        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5538            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5539                $crate::__from_json_named_body!(__lex, (Self), strict, $($body)*)
5540            }
5541        }
5542
5543        impl<$lt> $crate::ToJson for $name<$lt> {
5544            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5545                &self,
5546                __w: &mut __W,
5547            ) -> ::core::result::Result<(), __W::Error> {
5548                $crate::__to_json_named_body!(self, __w, $($body)*)
5549            }
5550        }
5551    };
5552
5553    // -----------------------------------------------------------------
5554    // Tuple struct, newtype, no generics.
5555    // -----------------------------------------------------------------
5556    (
5557        $(#[$attr:meta])*
5558        $vis:vis struct $name:ident ( $fty:ty $(,)? ) ;
5559    ) => {
5560        $(#[$attr])*
5561        $vis struct $name($fty);
5562
5563        impl<'input> $crate::FromJson<'input> for $name {
5564            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5565                ::core::result::Result::Ok(Self(
5566                    <$fty as $crate::FromJson<'_>>::from_lex(__lex)?,
5567                ))
5568            }
5569        }
5570
5571        impl $crate::ToJson for $name {
5572            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5573                &self,
5574                __w: &mut __W,
5575            ) -> ::core::result::Result<(), __W::Error> {
5576                $crate::ToJson::write_json(&self.0, __w)
5577            }
5578        }
5579    };
5580
5581    // -----------------------------------------------------------------
5582    // Tuple struct, newtype, one lifetime.
5583    // -----------------------------------------------------------------
5584    (
5585        $(#[$attr:meta])*
5586        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty:ty $(,)? ) ;
5587    ) => {
5588        $(#[$attr])*
5589        $vis struct $name<$lt>($fty);
5590
5591        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5592            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5593                ::core::result::Result::Ok(Self(
5594                    <$fty as $crate::FromJson<$lt>>::from_lex(__lex)?,
5595                ))
5596            }
5597        }
5598
5599        impl<$lt> $crate::ToJson for $name<$lt> {
5600            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5601                &self,
5602                __w: &mut __W,
5603            ) -> ::core::result::Result<(), __W::Error> {
5604                $crate::ToJson::write_json(&self.0, __w)
5605            }
5606        }
5607    };
5608
5609    // -----------------------------------------------------------------
5610    // Tuple struct, multi-field, no generics.
5611    // -----------------------------------------------------------------
5612    (
5613        $(#[$attr:meta])*
5614        $vis:vis struct $name:ident ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
5615    ) => {
5616        $(#[$attr])*
5617        $vis struct $name($fty1, $($ftyn),+);
5618
5619        impl<'input> $crate::FromJson<'input> for $name {
5620            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5621                if __lex.array_start()? {
5622                    return ::core::result::Result::Err(
5623                        $crate::Error::new($crate::ErrorKind::TypeMismatch, __lex.position()),
5624                    );
5625                }
5626                let __elem_0 = <$fty1 as $crate::FromJson<'_>>::from_lex(__lex)?;
5627                $crate::__from_json_tuple_walk!(
5628                    lex: __lex,
5629                    self_ctor: (Self),
5630                    accum: [ __elem_0 ],
5631                    remaining: [ $(($ftyn))+ ]
5632                )
5633            }
5634        }
5635
5636        impl $crate::ToJson for $name {
5637            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5638                &self,
5639                __w: &mut __W,
5640            ) -> ::core::result::Result<(), __W::Error> {
5641                __w.write_raw_bytes(b"[")?;
5642                $crate::ToJson::write_json(&self.0, __w)?;
5643                $crate::__to_json_tuple_walk!(
5644                    self_ref: self,
5645                    sink: __w,
5646                    idx: 1,
5647                    remaining: [ $(($ftyn))+ ]
5648                );
5649                __w.write_raw_bytes(b"]")?;
5650                ::core::result::Result::Ok(())
5651            }
5652        }
5653    };
5654
5655    // -----------------------------------------------------------------
5656    // Tuple struct, multi-field, one lifetime.
5657    // -----------------------------------------------------------------
5658    (
5659        $(#[$attr:meta])*
5660        $vis:vis struct $name:ident < $lt:lifetime $(,)? > ( $fty1:ty, $($ftyn:ty),+ $(,)? ) ;
5661    ) => {
5662        $(#[$attr])*
5663        $vis struct $name<$lt>($fty1, $($ftyn),+);
5664
5665        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5666            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5667                if __lex.array_start()? {
5668                    return ::core::result::Result::Err(
5669                        $crate::Error::new($crate::ErrorKind::TypeMismatch, __lex.position()),
5670                    );
5671                }
5672                let __elem_0 = <$fty1 as $crate::FromJson<$lt>>::from_lex(__lex)?;
5673                $crate::__from_json_tuple_walk!(
5674                    lex: __lex,
5675                    self_ctor: (Self),
5676                    accum: [ __elem_0 ],
5677                    remaining: [ $(($ftyn))+ ]
5678                )
5679            }
5680        }
5681
5682        impl<$lt> $crate::ToJson for $name<$lt> {
5683            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5684                &self,
5685                __w: &mut __W,
5686            ) -> ::core::result::Result<(), __W::Error> {
5687                __w.write_raw_bytes(b"[")?;
5688                $crate::ToJson::write_json(&self.0, __w)?;
5689                $crate::__to_json_tuple_walk!(
5690                    self_ref: self,
5691                    sink: __w,
5692                    idx: 1,
5693                    remaining: [ $(($ftyn))+ ]
5694                );
5695                __w.write_raw_bytes(b"]")?;
5696                ::core::result::Result::Ok(())
5697            }
5698        }
5699    };
5700
5701    // -----------------------------------------------------------------
5702    // Untagged enum, no generics.
5703    // -----------------------------------------------------------------
5704    (
5705        #[bourne(untagged)]
5706        $(#[$attr:meta])*
5707        $vis:vis enum $name:ident { $($variants:tt)* }
5708    ) => {
5709        $crate::__from_json_emit_enum_def!(
5710            attrs: { $(#[$attr])* },
5711            vis: $vis,
5712            name: $name,
5713            generics_def: (),
5714            variants_input: ($($variants)*)
5715        );
5716
5717        impl<'input> $crate::FromJson<'input> for $name {
5718            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5719                $crate::__from_json_untagged_dispatch!(__lex, $name, ($($variants)*))
5720            }
5721        }
5722
5723        impl $crate::ToJson for $name {
5724            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5725                &self,
5726                __w: &mut __W,
5727            ) -> ::core::result::Result<(), __W::Error> {
5728                let __this: &Self = self;
5729                $crate::__to_json_untagged_walk!(
5730                    receiver: __this,
5731                    sink: __w,
5732                    name: $name,
5733                    arms: { },
5734                    input: ($($variants)*)
5735                )
5736            }
5737        }
5738    };
5739
5740    // Untagged enum, one lifetime.
5741    (
5742        #[bourne(untagged)]
5743        $(#[$attr:meta])*
5744        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
5745    ) => {
5746        $crate::__from_json_emit_enum_def!(
5747            attrs: { $(#[$attr])* },
5748            vis: $vis,
5749            name: $name,
5750            generics_def: (<$lt>),
5751            variants_input: ($($variants)*)
5752        );
5753
5754        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5755            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5756                $crate::__from_json_untagged_dispatch!(__lex, $name, ($($variants)*))
5757            }
5758        }
5759
5760        impl<$lt> $crate::ToJson for $name<$lt> {
5761            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5762                &self,
5763                __w: &mut __W,
5764            ) -> ::core::result::Result<(), __W::Error> {
5765                let __this: &Self = self;
5766                $crate::__to_json_untagged_walk!(
5767                    receiver: __this,
5768                    sink: __w,
5769                    name: $name,
5770                    arms: { },
5771                    input: ($($variants)*)
5772                )
5773            }
5774        }
5775    };
5776
5777    // -----------------------------------------------------------------
5778    // Adjacently-tagged enum, no generics.
5779    // -----------------------------------------------------------------
5780    (
5781        #[bourne(tag = $tag:literal, content = $content:literal)]
5782        $(#[$attr:meta])*
5783        $vis:vis enum $name:ident { $($variants:tt)* }
5784    ) => {
5785        $crate::__from_json_emit_enum_def!(
5786            attrs: { $(#[$attr])* },
5787            vis: $vis,
5788            name: $name,
5789            generics_def: (),
5790            variants_input: ($($variants)*)
5791        );
5792
5793        impl<'input> $crate::FromJson<'input> for $name {
5794            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5795                $crate::__from_json_adjacently_tagged_dispatch!(
5796                    __lex, $name, $tag, $content, ($($variants)*)
5797                )
5798            }
5799        }
5800
5801        impl $crate::ToJson for $name {
5802            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5803                &self,
5804                __w: &mut __W,
5805            ) -> ::core::result::Result<(), __W::Error> {
5806                let __this: &Self = self;
5807                $crate::__to_json_adjacent_walk!(
5808                    receiver: __this,
5809                    sink: __w,
5810                    name: $name,
5811                    tag: $tag,
5812                    content: $content,
5813                    arms: { },
5814                    cur_rename: (),
5815                    input: ($($variants)*)
5816                )
5817            }
5818        }
5819    };
5820
5821    // Adjacently-tagged enum, one lifetime.
5822    (
5823        #[bourne(tag = $tag:literal, content = $content:literal)]
5824        $(#[$attr:meta])*
5825        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
5826    ) => {
5827        $crate::__from_json_emit_enum_def!(
5828            attrs: { $(#[$attr])* },
5829            vis: $vis,
5830            name: $name,
5831            generics_def: (<$lt>),
5832            variants_input: ($($variants)*)
5833        );
5834
5835        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5836            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5837                $crate::__from_json_adjacently_tagged_dispatch!(
5838                    __lex, $name, $tag, $content, ($($variants)*)
5839                )
5840            }
5841        }
5842
5843        impl<$lt> $crate::ToJson for $name<$lt> {
5844            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5845                &self,
5846                __w: &mut __W,
5847            ) -> ::core::result::Result<(), __W::Error> {
5848                let __this: &Self = self;
5849                $crate::__to_json_adjacent_walk!(
5850                    receiver: __this,
5851                    sink: __w,
5852                    name: $name,
5853                    tag: $tag,
5854                    content: $content,
5855                    arms: { },
5856                    cur_rename: (),
5857                    input: ($($variants)*)
5858                )
5859            }
5860        }
5861    };
5862
5863    // -----------------------------------------------------------------
5864    // Internally-tagged enum, no generics.
5865    // -----------------------------------------------------------------
5866    (
5867        #[bourne(tag = $tag:literal)]
5868        $(#[$attr:meta])*
5869        $vis:vis enum $name:ident { $($variants:tt)* }
5870    ) => {
5871        $crate::__from_json_emit_enum_def!(
5872            attrs: { $(#[$attr])* },
5873            vis: $vis,
5874            name: $name,
5875            generics_def: (),
5876            variants_input: ($($variants)*)
5877        );
5878
5879        impl<'input> $crate::FromJson<'input> for $name {
5880            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5881                $crate::__from_json_internally_tagged_dispatch!(
5882                    __lex, $name, $tag, ($($variants)*)
5883                )
5884            }
5885        }
5886
5887        impl $crate::ToJson for $name {
5888            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5889                &self,
5890                __w: &mut __W,
5891            ) -> ::core::result::Result<(), __W::Error> {
5892                let __this: &Self = self;
5893                $crate::__to_json_internal_walk!(
5894                    receiver: __this,
5895                    sink: __w,
5896                    name: $name,
5897                    tag: $tag,
5898                    arms: { },
5899                    cur_rename: (),
5900                    input: ($($variants)*)
5901                )
5902            }
5903        }
5904    };
5905
5906    // Internally-tagged enum, one lifetime.
5907    (
5908        #[bourne(tag = $tag:literal)]
5909        $(#[$attr:meta])*
5910        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
5911    ) => {
5912        $crate::__from_json_emit_enum_def!(
5913            attrs: { $(#[$attr])* },
5914            vis: $vis,
5915            name: $name,
5916            generics_def: (<$lt>),
5917            variants_input: ($($variants)*)
5918        );
5919
5920        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
5921            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
5922                $crate::__from_json_internally_tagged_dispatch!(
5923                    __lex, $name, $tag, ($($variants)*)
5924                )
5925            }
5926        }
5927
5928        impl<$lt> $crate::ToJson for $name<$lt> {
5929            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5930                &self,
5931                __w: &mut __W,
5932            ) -> ::core::result::Result<(), __W::Error> {
5933                let __this: &Self = self;
5934                $crate::__to_json_internal_walk!(
5935                    receiver: __this,
5936                    sink: __w,
5937                    name: $name,
5938                    tag: $tag,
5939                    arms: { },
5940                    cur_rename: (),
5941                    input: ($($variants)*)
5942                )
5943            }
5944        }
5945    };
5946
5947    // -----------------------------------------------------------------
5948    // Externally-tagged enum, no generics.
5949    // -----------------------------------------------------------------
5950    (
5951        $(#[$attr:meta])*
5952        $vis:vis enum $name:ident { $($variants:tt)* }
5953    ) => {
5954        $crate::__from_json_emit_enum_def!(
5955            attrs: { $(#[$attr])* },
5956            vis: $vis,
5957            name: $name,
5958            generics_def: (),
5959            variants_input: ($($variants)*)
5960        );
5961
5962        impl<'input> $crate::FromJson<'input> for $name {
5963            fn from_lex(__lex: &mut $crate::Lexer<'input>) -> ::core::result::Result<Self, $crate::Error> {
5964                $crate::__from_json_enum_dispatch!(__lex, $name, ($($variants)*))
5965            }
5966        }
5967
5968        impl $crate::ToJson for $name {
5969            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
5970                &self,
5971                __w: &mut __W,
5972            ) -> ::core::result::Result<(), __W::Error> {
5973                let __this: &Self = self;
5974                $crate::__to_json_enum_walk!(
5975                    receiver: __this,
5976                    sink: __w,
5977                    name: $name,
5978                    arms: { },
5979                    cur_rename: (),
5980                    input: ($($variants)*)
5981                )
5982            }
5983        }
5984    };
5985
5986    // Externally-tagged enum, one lifetime.
5987    (
5988        $(#[$attr:meta])*
5989        $vis:vis enum $name:ident < $lt:lifetime $(,)? > { $($variants:tt)* }
5990    ) => {
5991        $crate::__from_json_emit_enum_def!(
5992            attrs: { $(#[$attr])* },
5993            vis: $vis,
5994            name: $name,
5995            generics_def: (<$lt>),
5996            variants_input: ($($variants)*)
5997        );
5998
5999        impl<$lt> $crate::FromJson<$lt> for $name<$lt> {
6000            fn from_lex(__lex: &mut $crate::Lexer<$lt>) -> ::core::result::Result<Self, $crate::Error> {
6001                $crate::__from_json_enum_dispatch!(__lex, $name, ($($variants)*))
6002            }
6003        }
6004
6005        impl<$lt> $crate::ToJson for $name<$lt> {
6006            fn write_json<__W: $crate::JsonWrite + ?::core::marker::Sized>(
6007                &self,
6008                __w: &mut __W,
6009            ) -> ::core::result::Result<(), __W::Error> {
6010                let __this: &Self = self;
6011                $crate::__to_json_enum_walk!(
6012                    receiver: __this,
6013                    sink: __w,
6014                    name: $name,
6015                    arms: { },
6016                    cur_rename: (),
6017                    input: ($($variants)*)
6018                )
6019            }
6020        }
6021    };
6022}