Skip to main content

json_bourne/
de.rs

1//! Type-driven deserialization.
2//!
3//! The [`FromJson`] trait is the heart of `json-bourne`. Each type knows how to
4//! parse itself from JSON given direct access to the [`Lexer`].
5//!
6//! Why a lexer instead of an event stream? Typed parsing already enforces
7//! the JSON grammar by virtue of which method gets called when — `Vec<T>`
8//! knows it's parsing an array, a struct knows it's parsing an object. The
9//! streaming `Event` API has to thread a state machine through every value
10//! to enforce the same grammar; for typed consumers that dispatch is pure
11//! overhead. By driving the lexer directly we skip the state machine.
12//!
13//! Inside `Vec<T>::from_lex` the loop is roughly:
14//!
15//! ```ignore
16//! lex.array_start()?;          // consume `[`
17//! loop {
18//!     out.push(T::from_lex(lex)?);
19//!     if lex.array_continue(b']')? { break; }
20//! }
21//! ```
22//!
23//! Each element costs exactly one `T::from_lex` plus one `array_continue`
24//! — no per-element `next_event`, no `match self.state`.
25
26use crate::{Error, ErrorKind, Event, JsonNum, Lexer, Parser, ValueKind};
27
28/// Parse a value of type `T` from a slice of JSON bytes.
29pub fn parse<'input, T: FromJson<'input>>(input: &'input [u8]) -> Result<T, Error> {
30    let mut p: Parser<'input> = Parser::new(input);
31    let lex = p.lexer();
32    let value = T::from_lex(lex)?;
33    lex.finish()?;
34    Ok(value)
35}
36
37/// Parse from a `&str`.
38pub fn parse_str<'input, T: FromJson<'input>>(input: &'input str) -> Result<T, Error> {
39    parse(input.as_bytes())
40}
41
42/// Types that know how to deserialize themselves from JSON via a [`Lexer`].
43///
44/// The `'input` lifetime is the lifetime of the input bytes. Implementors
45/// that borrow from input (e.g. `&'input str`) tie their output to `'input`;
46/// owned implementors (e.g. `String`) leave `'input` unused.
47pub trait FromJson<'input>: Sized {
48    /// Parse one value of `Self` from the lexer's current position.
49    ///
50    /// Whitespace before the value is consumed by the lexer's value-reading
51    /// methods, so impls do not need to skip whitespace themselves.
52    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error>;
53
54    /// Optional fast path for `Vec<Self>`. The default implementation drives
55    /// `from_lex` once per element. Types where the per-element streaming
56    /// detour is pure overhead (the integer types, `&str`) override this to
57    /// lex-and-parse directly.
58    #[cfg(feature = "alloc")]
59    #[doc(hidden)]
60    fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
61        let mut out = alloc::vec::Vec::new();
62        if lex.array_start()? {
63            return Ok(out);
64        }
65        out.push(Self::from_lex(lex)?);
66        while !lex.array_continue(b']')? {
67            out.push(Self::from_lex(lex)?);
68        }
69        Ok(out)
70    }
71}
72
73// ---------------------------------------------------------------------------
74// Primitive impls
75// ---------------------------------------------------------------------------
76
77#[inline]
78const fn type_error(lex: &Lexer<'_>, kind: ErrorKind) -> Error {
79    Error::new(kind, lex.position())
80}
81
82impl<'input> FromJson<'input> for bool {
83    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
84        match lex.read_value()? {
85            Event::Bool(b) => Ok(b),
86            _ => Err(type_error(lex, ErrorKind::ExpectedBool)),
87        }
88    }
89}
90
91impl<'input> FromJson<'input> for () {
92    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
93        match lex.read_value()? {
94            Event::Null => Ok(()),
95            _ => Err(type_error(lex, ErrorKind::ExpectedNull)),
96        }
97    }
98}
99
100impl<'input> FromJson<'input> for &'input str {
101    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
102        // The fast path: skip Event entirely.
103        match lex.peek_value_kind()? {
104            ValueKind::String => lex.parse_str_value(),
105            _ => Err(type_error(lex, ErrorKind::ExpectedString)),
106        }
107    }
108
109    /// Fused-pass fast path for `Vec<&str>`. Falls back to the streaming
110    /// path for the first element only so an immediate `]` (empty array)
111    /// is handled cleanly.
112    #[cfg(feature = "alloc")]
113    fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
114        let mut out: alloc::vec::Vec<&'input str> = alloc::vec::Vec::new();
115        if lex.array_start()? {
116            return Ok(out);
117        }
118        out.push(lex.parse_str_value()?);
119        while !lex.array_continue(b']')? {
120            out.push(lex.parse_str_value()?);
121        }
122        Ok(out)
123    }
124}
125
126macro_rules! impl_int {
127    ($($t:ty => $accessor:ident),* $(,)?) => {
128        $(
129            impl<'input> FromJson<'input> for $t {
130                fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
131                    match lex.peek_value_kind()? {
132                        ValueKind::Number => {
133                            let n: JsonNum = lex.read_number()?;
134                            let big = n.$accessor(lex.input())
135                                .map_err(|kind| Error::new(kind, lex.position()))?;
136                            <$t>::try_from(big).map_err(|_| {
137                                Error::new(ErrorKind::NumberOutOfRange, lex.position())
138                            })
139                        }
140                        _ => Err(type_error(lex, ErrorKind::ExpectedNumber)),
141                    }
142                }
143
144                /// Fused-pass fast path: skip `JsonNum` entirely.
145                #[cfg(feature = "alloc")]
146                fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
147                    let mut out: alloc::vec::Vec<Self> = alloc::vec::Vec::new();
148                    if lex.array_start()? {
149                        return Ok(out);
150                    }
151                    let v = lex.parse_i64_value()?;
152                    out.push(<$t>::try_from(v).map_err(|_| {
153                        Error::new(ErrorKind::NumberOutOfRange, lex.position())
154                    })?);
155                    while !lex.array_continue(b']')? {
156                        let v = lex.parse_i64_value()?;
157                        out.push(<$t>::try_from(v).map_err(|_| {
158                            Error::new(ErrorKind::NumberOutOfRange, lex.position())
159                        })?);
160                    }
161                    Ok(out)
162                }
163            }
164        )*
165    };
166}
167
168impl_int!(i8 => as_i64, i16 => as_i64, i32 => as_i64, i64 => as_i64, isize => as_i64);
169impl_int!(u8 => as_u64, u16 => as_u64, u32 => as_u64, u64 => as_u64, usize => as_u64);
170
171// 128-bit ints — fused lex + decode via `parse_i128_value` /
172// `parse_u128_value`. The earlier path went through `JsonNum::as_*128`
173// which delegated to `str::parse::<i128>`; perf showed that taking 60%
174// of the `Vec<i128>` workload because `str::parse` uses checked
175// arithmetic on every digit. The bespoke parser skips overflow checks
176// for the first 38 digits (which always fit a `u128`).
177macro_rules! impl_int_wide {
178    ($($t:ty => $parse_fn:ident),* $(,)?) => {
179        $(
180            impl<'input> FromJson<'input> for $t {
181                fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
182                    match lex.peek_value_kind()? {
183                        ValueKind::Number => lex.$parse_fn(),
184                        _ => Err(type_error(lex, ErrorKind::ExpectedNumber)),
185                    }
186                }
187
188                /// Fused-pass fast path for `Vec<Self>`: skip the
189                /// per-element peek-and-dispatch.
190                #[cfg(feature = "alloc")]
191                fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
192                    let mut out: alloc::vec::Vec<Self> = alloc::vec::Vec::new();
193                    if lex.array_start()? {
194                        return Ok(out);
195                    }
196                    out.push(lex.$parse_fn()?);
197                    while !lex.array_continue(b']')? {
198                        out.push(lex.$parse_fn()?);
199                    }
200                    Ok(out)
201                }
202            }
203        )*
204    };
205}
206
207impl_int_wide!(i128 => parse_i128_value, u128 => parse_u128_value);
208
209impl<'input> FromJson<'input> for f64 {
210    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
211        match lex.peek_value_kind()? {
212            ValueKind::Number => lex.parse_f64_value(),
213            _ => Err(type_error(lex, ErrorKind::ExpectedNumber)),
214        }
215    }
216
217    /// Fused-pass fast path for `Vec<f64>`: skip `JsonNum` and the
218    /// type-peek per element. The `array_continue` polarity is the
219    /// same shape the integer impls use.
220    #[cfg(feature = "alloc")]
221    fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
222        let mut out: alloc::vec::Vec<Self> = alloc::vec::Vec::new();
223        if lex.array_start()? {
224            return Ok(out);
225        }
226        out.push(lex.parse_f64_value()?);
227        while !lex.array_continue(b']')? {
228            out.push(lex.parse_f64_value()?);
229        }
230        Ok(out)
231    }
232}
233
234impl<'input> FromJson<'input> for f32 {
235    /// Reject literals whose magnitude can't fit `f32` instead of
236    /// silently coercing to `±inf`. Subnormals and finite-but-imprecise
237    /// values still narrow as a normal cast (the JSON spec doesn't
238    /// promise lossless f32 round-trip; libstd's `f64 as f32` rounds
239    /// to the nearest representable value).
240    #[allow(clippy::cast_possible_truncation)]
241    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
242        let v = f64::from_lex(lex)?;
243        let narrowed = v as Self;
244        if narrowed.is_finite() {
245            Ok(narrowed)
246        } else {
247            Err(Error::new(ErrorKind::NumberOutOfRange, lex.position()))
248        }
249    }
250}
251
252// ---------------------------------------------------------------------------
253// Composite impls
254// ---------------------------------------------------------------------------
255
256impl<'input, T: FromJson<'input>> FromJson<'input> for Option<T> {
257    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
258        match lex.peek_value_kind()? {
259            ValueKind::Null => {
260                let _ = lex.read_value()?;
261                Ok(None)
262            }
263            _ => Ok(Some(T::from_lex(lex)?)),
264        }
265    }
266}
267
268impl<'input, T: FromJson<'input>, const N: usize> FromJson<'input> for [T; N] {
269    fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
270        let mut slots: [Option<T>; N] = core::array::from_fn(|_| None);
271
272        let empty = lex.array_start()?;
273        if empty {
274            if N == 0 {
275                return Ok(core::array::from_fn(|i| {
276                    slots[i].take().expect("slot filled")
277                }));
278            }
279            return Err(type_error(lex, ErrorKind::TypeMismatch));
280        }
281
282        for (i, slot) in slots.iter_mut().enumerate() {
283            *slot = Some(T::from_lex(lex)?);
284            let closed = lex.array_continue(b']')?;
285            if closed {
286                if i + 1 == N {
287                    return Ok(core::array::from_fn(|i| {
288                        slots[i].take().expect("slot filled")
289                    }));
290                }
291                return Err(type_error(lex, ErrorKind::TypeMismatch));
292            }
293        }
294        // Filled all N slots without seeing `]` after the last one: too long.
295        Err(type_error(lex, ErrorKind::TypeMismatch))
296    }
297}
298
299// Tuples — keep small and explicit.
300//
301// The macro generates a fixed-arity walk: for `(A, B, C)` we parse A, then
302// require `,`; parse B, then require `,`; parse C, then require `]`.
303// `array_continue` returns true when it consumed `]` and false when it
304// consumed `,`, which is exactly the polarity we need for the last vs
305// non-last branch.
306macro_rules! impl_tuple {
307    ($last:tt: $LAST:ident $(, $idx:tt: $T:ident)*) => {
308        impl<'input, $LAST: FromJson<'input> $(, $T: FromJson<'input>)*>
309            FromJson<'input> for ($LAST, $($T,)*)
310        {
311            #[allow(non_snake_case)]
312            fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
313                if lex.array_start()? {
314                    return Err(type_error(lex, ErrorKind::TypeMismatch));
315                }
316                let $LAST = <$LAST>::from_lex(lex)?;
317                $(
318                    if lex.array_continue(b']')? {
319                        return Err(type_error(lex, ErrorKind::TypeMismatch));
320                    }
321                    let $T = <$T>::from_lex(lex)?;
322                )*
323                if !lex.array_continue(b']')? {
324                    return Err(type_error(lex, ErrorKind::TypeMismatch));
325                }
326                let _ = ($last $(, $idx)*); // silence unused-tt warnings
327                Ok(($LAST, $($T,)*))
328            }
329        }
330    };
331}
332
333impl_tuple!(0: A);
334impl_tuple!(0: A, 1: B);
335impl_tuple!(0: A, 1: B, 2: C);
336impl_tuple!(0: A, 1: B, 2: C, 3: D);
337impl_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
338impl_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
339
340// ---------------------------------------------------------------------------
341// alloc-gated impls
342// ---------------------------------------------------------------------------
343
344#[cfg(feature = "alloc")]
345pub use alloc_impls::{MapKey, key_to_cow};
346
347#[cfg(feature = "alloc")]
348mod alloc_impls {
349    extern crate alloc;
350    use super::{FromJson, type_error};
351    use alloc::borrow::Cow;
352    use alloc::string::String;
353    use alloc::vec::Vec;
354    use crate::{Error, ErrorKind, JsonStr, Lexer, ValueKind};
355
356    impl<'input> FromJson<'input> for String {
357        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
358            match lex.peek_value_kind()? {
359                ValueKind::String => {
360                    // Drive the lexer directly with the no-validate variant.
361                    // The decoder below performs the same validation walk
362                    // as part of decoding, so paying validate_escapes here
363                    // (the lexer's default) would be a redundant pass over
364                    // every escaped string. perf showed this redundant
365                    // pass at 42% of total time on Vec<String> with escapes.
366                    let js = lex.read_string_no_validate()?;
367                    decode_string(js, lex)
368                }
369                _ => Err(type_error(lex, ErrorKind::ExpectedString)),
370            }
371        }
372    }
373
374    /// Borrow-when-you-can, allocate-when-you-must. The right default for
375    /// most string fields: ~95% of production JSON has no escapes, so this
376    /// avoids the per-element allocation that `String` pays. When escapes
377    /// are present the cost is identical to `String`.
378    impl<'input> FromJson<'input> for Cow<'input, str> {
379        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
380            match lex.peek_value_kind()? {
381                ValueKind::String => {
382                    let js = lex.read_string_no_validate()?;
383                    if let Some(borrowed) = js.as_str(lex.input()) {
384                        return Ok(Cow::Borrowed(borrowed));
385                    }
386                    Ok(Cow::Owned(decode_owned(js, lex)?))
387                }
388                _ => Err(type_error(lex, ErrorKind::ExpectedString)),
389            }
390        }
391    }
392
393    /// JSON has no `char` type — pick "string of exactly one Unicode
394    /// scalar value" as the convention. Empty strings, multi-character
395    /// strings, and strings whose decoded form is not exactly one
396    /// scalar all reject. Escapes are honored (e.g. `"\n"`, `"é"`).
397    impl<'input> FromJson<'input> for char {
398        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
399            match lex.peek_value_kind()? {
400                ValueKind::String => {
401                    let js = lex.read_string_no_validate()?;
402                    // Borrow path: no escapes — read the validated UTF-8
403                    // directly and require exactly one scalar.
404                    if let Some(borrowed) = js.as_str(lex.input()) {
405                        return single_char(borrowed)
406                            .ok_or_else(|| type_error(lex, ErrorKind::TypeMismatch));
407                    }
408                    // Escape path: decode into a small scratch buffer.
409                    // Most escape sequences produce ≤4 UTF-8 bytes, so a
410                    // small allocation is fine; we still error if the
411                    // decoded content isn't exactly one scalar.
412                    let decoded = decode_owned(js, lex)?;
413                    single_char(&decoded).ok_or_else(|| type_error(lex, ErrorKind::TypeMismatch))
414                }
415                _ => Err(type_error(lex, ErrorKind::ExpectedString)),
416            }
417        }
418    }
419
420    // -----------------------------------------------------------------
421    // Map and set collections.
422    //
423    // JSON object keys are always strings; the lexer's `_lex`-suffixed
424    // key methods surface them as `JsonStr` so callers can decode
425    // escapes when present. `key_to_cow` below borrows when escape-free
426    // and decodes otherwise — yielding `Cow<'input, str>`. The MapKey
427    // adapter then converts that into the user's chosen K. Supported
428    // keys: String, Cow<'input, str>, and (escape-free only)
429    // &'input str.
430    //
431    // `BTreeMap`/`BTreeSet` are alloc-gated (live in `alloc`).
432    // `HashMap`/`HashSet` are std-gated (live in `std`).
433    // -----------------------------------------------------------------
434
435    /// Materialize an object key from a [`JsonStr`] span. Borrows when the
436    /// key is escape-free; decodes into an owned `String` otherwise.
437    pub fn key_to_cow<'input>(js: JsonStr, lex: &Lexer<'input>) -> Result<Cow<'input, str>, Error> {
438        if let Some(borrowed) = js.as_str(lex.input()) {
439            return Ok(Cow::Borrowed(borrowed));
440        }
441        Ok(Cow::Owned(decode_owned(js, lex)?))
442    }
443
444    /// Internal adapter from a decoded JSON key to the user's key type.
445    ///
446    /// Sealed by the limited set of impls we provide; users who need a
447    /// custom key type should hand-write the `FromJson` impl for the map
448    /// or wrap the key in a newtype.
449    ///
450    /// Returns `Result` because not every adapter is total — `&'input str`
451    /// keys can only borrow, so escaped keys reject with `InvalidEscape`.
452    pub trait MapKey<'input>: Sized {
453        fn from_key(key: Cow<'input, str>, lex: &Lexer<'input>) -> Result<Self, Error>;
454    }
455
456    impl<'input> MapKey<'input> for String {
457        #[inline]
458        fn from_key(key: Cow<'input, str>, _lex: &Lexer<'input>) -> Result<Self, Error> {
459            Ok(key.into_owned())
460        }
461    }
462
463    impl<'input> MapKey<'input> for Cow<'input, str> {
464        #[inline]
465        fn from_key(key: Self, _lex: &Lexer<'input>) -> Result<Self, Error> {
466            Ok(key)
467        }
468    }
469
470    impl<'input> MapKey<'input> for &'input str {
471        /// Borrowing `&'input str` keys cannot represent escape-bearing
472        /// keys, since the decoded form lives in a fresh allocation
473        /// outside the input. Reject those at runtime; callers that
474        /// expect escapes should use `Cow<'input, str>` or `String`.
475        #[inline]
476        fn from_key(key: Cow<'input, str>, lex: &Lexer<'input>) -> Result<Self, Error> {
477            match key {
478                Cow::Borrowed(s) => Ok(s),
479                Cow::Owned(_) => Err(type_error(lex, ErrorKind::InvalidEscape)),
480            }
481        }
482    }
483
484    trait DupMap<K, V> {
485        fn new_empty() -> Self;
486        fn try_insert(&mut self, k: K, v: V) -> bool;
487    }
488
489    impl<K: Ord, V> DupMap<K, V> for alloc::collections::BTreeMap<K, V> {
490        fn new_empty() -> Self { Self::new() }
491        fn try_insert(&mut self, k: K, v: V) -> bool { self.insert(k, v).is_none() }
492    }
493
494    #[cfg(feature = "std")]
495    impl<K, V, S> DupMap<K, V> for std::collections::HashMap<K, V, S>
496    where
497        K: ::core::hash::Hash + Eq,
498        S: ::core::hash::BuildHasher + Default,
499    {
500        fn new_empty() -> Self { Self::with_hasher(S::default()) }
501        fn try_insert(&mut self, k: K, v: V) -> bool { self.insert(k, v).is_none() }
502    }
503
504    #[cfg(feature = "indexmap")]
505    impl<K, V, S> DupMap<K, V> for indexmap::IndexMap<K, V, S>
506    where
507        K: ::core::hash::Hash + Eq,
508        S: ::core::hash::BuildHasher + Default,
509    {
510        fn new_empty() -> Self { Self::with_hasher(S::default()) }
511        fn try_insert(&mut self, k: K, v: V) -> bool { self.insert(k, v).is_none() }
512    }
513
514    fn parse_map<'input, K, V, M>(lex: &mut Lexer<'input>) -> Result<M, Error>
515    where
516        K: MapKey<'input>,
517        V: FromJson<'input>,
518        M: DupMap<K, V>,
519    {
520        if !matches!(lex.peek_value_kind()?, ValueKind::Object) {
521            return Err(type_error(lex, ErrorKind::TypeMismatch));
522        }
523        lex.object_start()?;
524        let mut out = M::new_empty();
525        let mut maybe_key = lex.object_first_key_lex()?;
526        while let Some(js) = maybe_key {
527            let key_cow = key_to_cow(js, lex)?;
528            let key = K::from_key(key_cow, lex)?;
529            let v = V::from_lex(lex)?;
530            if !out.try_insert(key, v) {
531                return Err(Error::new(ErrorKind::DuplicateKey, lex.position()));
532            }
533            maybe_key = lex.object_next_key_lex()?;
534        }
535        Ok(out)
536    }
537
538    impl<'input, K, V> FromJson<'input> for alloc::collections::BTreeMap<K, V>
539    where
540        K: MapKey<'input> + Ord,
541        V: FromJson<'input>,
542    {
543        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
544            parse_map(lex)
545        }
546    }
547
548    #[cfg(feature = "std")]
549    impl<'input, K, V, S> FromJson<'input> for std::collections::HashMap<K, V, S>
550    where
551        K: MapKey<'input> + ::core::hash::Hash + Eq,
552        V: FromJson<'input>,
553        S: ::core::hash::BuildHasher + Default,
554    {
555        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
556            parse_map(lex)
557        }
558    }
559
560    trait SetInsert<T> {
561        fn new_empty() -> Self;
562        fn push(&mut self, v: T);
563    }
564
565    impl<T: Ord> SetInsert<T> for alloc::collections::BTreeSet<T> {
566        fn new_empty() -> Self { Self::new() }
567        fn push(&mut self, v: T) { self.insert(v); }
568    }
569
570    #[cfg(feature = "std")]
571    impl<T, S> SetInsert<T> for std::collections::HashSet<T, S>
572    where
573        T: ::core::hash::Hash + Eq,
574        S: ::core::hash::BuildHasher + Default,
575    {
576        fn new_empty() -> Self { Self::with_hasher(S::default()) }
577        fn push(&mut self, v: T) { self.insert(v); }
578    }
579
580    #[cfg(feature = "indexmap")]
581    impl<T, S> SetInsert<T> for indexmap::IndexSet<T, S>
582    where
583        T: ::core::hash::Hash + Eq,
584        S: ::core::hash::BuildHasher + Default,
585    {
586        fn new_empty() -> Self { Self::with_hasher(S::default()) }
587        fn push(&mut self, v: T) { self.insert(v); }
588    }
589
590    fn parse_set<'input, T, C>(lex: &mut Lexer<'input>) -> Result<C, Error>
591    where
592        T: FromJson<'input>,
593        C: SetInsert<T>,
594    {
595        let mut out = C::new_empty();
596        if lex.array_start()? {
597            return Ok(out);
598        }
599        out.push(T::from_lex(lex)?);
600        while !lex.array_continue(b']')? {
601            out.push(T::from_lex(lex)?);
602        }
603        Ok(out)
604    }
605
606    impl<'input, T> FromJson<'input> for alloc::collections::BTreeSet<T>
607    where
608        T: FromJson<'input> + Ord,
609    {
610        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
611            parse_set(lex)
612        }
613    }
614
615    #[cfg(feature = "std")]
616    impl<'input, T, S> FromJson<'input> for std::collections::HashSet<T, S>
617    where
618        T: FromJson<'input> + ::core::hash::Hash + Eq,
619        S: ::core::hash::BuildHasher + Default,
620    {
621        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
622            parse_set(lex)
623        }
624    }
625
626    // -----------------------------------------------------------------
627    // std::time and std::net adapters.
628    //
629    // JSON has no native types for any of these, so we pick a single
630    // convention per type. These are deliberately simple — projects
631    // with bespoke encodings (RFC 3339 timestamps, custom Duration
632    // shapes) should hand-write a wrapper newtype.
633    // -----------------------------------------------------------------
634
635    /// Parse a `Duration` from JSON `Number` (seconds, possibly fractional).
636    /// Negative inputs and non-finite values are rejected. Subsecond
637    /// precision is preserved to nanosecond resolution.
638    ///
639    /// Implementation note: pre-validates the input to a finite,
640    /// non-negative value within `Duration`'s u64-seconds range, then
641    /// delegates to `Duration::from_secs_f64`. The earlier hand-rolled
642    /// `trunc`/`mul`/`round`/`clamp` sequence was ~3.5× slower than
643    /// `from_secs_f64` on profile (the libstd routine inlines a
644    /// branch-light decomposition of the f64 mantissa).
645    #[cfg(feature = "std")]
646    impl<'input> FromJson<'input> for std::time::Duration {
647        #[allow(clippy::cast_precision_loss)]
648        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
649            // Skip the `f64::from_lex` detour: that does a
650            // `peek_value_kind` first, which `parse_f64_value`'s
651            // own type check makes redundant for the Number arm.
652            let secs_f = match lex.peek_value_kind()? {
653                ValueKind::Number => lex.parse_f64_value()?,
654                _ => return Err(type_error(lex, ErrorKind::ExpectedNumber)),
655            };
656            // `Duration::from_secs_f64` panics on these inputs;
657            // convert to typed errors before calling.
658            if !secs_f.is_finite() || secs_f < 0.0 || secs_f >= (u64::MAX as f64) {
659                return Err(type_error(lex, ErrorKind::NumberOutOfRange));
660            }
661            Ok(Self::from_secs_f64(secs_f))
662        }
663
664        /// Fused-pass fast path for `Vec<Duration>`. Mirrors the
665        /// `Vec<f64>` override: `parse_f64_value` directly per
666        /// element, no type-peek detour past the first.
667        #[cfg(feature = "alloc")]
668        #[allow(clippy::cast_precision_loss)]
669        fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
670            #[inline]
671            fn convert(lex: &Lexer<'_>, secs_f: f64) -> Result<std::time::Duration, Error> {
672                if !secs_f.is_finite() || secs_f < 0.0 || secs_f >= (u64::MAX as f64) {
673                    return Err(type_error(lex, ErrorKind::NumberOutOfRange));
674                }
675                Ok(std::time::Duration::from_secs_f64(secs_f))
676            }
677            let mut out: alloc::vec::Vec<Self> = alloc::vec::Vec::new();
678            if lex.array_start()? {
679                return Ok(out);
680            }
681            let secs_f = lex.parse_f64_value()?;
682            out.push(convert(lex, secs_f)?);
683            while !lex.array_continue(b']')? {
684                let secs_f = lex.parse_f64_value()?;
685                out.push(convert(lex, secs_f)?);
686            }
687            Ok(out)
688        }
689    }
690
691    /// Parse a `SystemTime` from JSON `Number` (seconds since
692    /// `UNIX_EPOCH`, possibly fractional and possibly negative).
693    /// Mirrors the `Duration` adapter but allows negative values for
694    /// pre-epoch timestamps, which the `SystemTime` arithmetic model
695    /// supports.
696    ///
697    /// Subsecond precision is preserved to nanosecond resolution via
698    /// `Duration::from_secs_f64`.
699    #[cfg(feature = "std")]
700    impl<'input> FromJson<'input> for std::time::SystemTime {
701        #[allow(clippy::cast_precision_loss)]
702        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
703            let secs_f = match lex.peek_value_kind()? {
704                ValueKind::Number => lex.parse_f64_value()?,
705                _ => return Err(type_error(lex, ErrorKind::ExpectedNumber)),
706            };
707            // Reject non-finite inputs and clamp the magnitude to a
708            // range Duration::from_secs_f64 won't panic on.
709            if !secs_f.is_finite() || secs_f.abs() >= (u64::MAX as f64) {
710                return Err(type_error(lex, ErrorKind::NumberOutOfRange));
711            }
712            let abs = std::time::Duration::from_secs_f64(secs_f.abs());
713            let epoch = std::time::UNIX_EPOCH;
714            let st = if secs_f < 0.0 {
715                epoch.checked_sub(abs)
716            } else {
717                epoch.checked_add(abs)
718            };
719            st.ok_or_else(|| type_error(lex, ErrorKind::NumberOutOfRange))
720        }
721    }
722
723    /// Generic adapter for any type whose canonical text form is parseable
724    /// via `FromStr`. Used below for `IpAddr`, `Ipv4Addr`, `Ipv6Addr`,
725    /// `SocketAddr`, and `PathBuf`. Failures map to `TypeMismatch`.
726    #[cfg(feature = "std")]
727    fn parse_from_str<'input, T>(lex: &mut Lexer<'input>) -> Result<T, Error>
728    where
729        T: ::core::str::FromStr,
730    {
731        let cow: Cow<'input, str> = Cow::<'input, str>::from_lex(lex)?;
732        cow.parse::<T>()
733            .map_err(|_| type_error(lex, ErrorKind::TypeMismatch))
734    }
735
736    #[cfg(feature = "std")]
737    impl<'input> FromJson<'input> for std::net::IpAddr {
738        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
739            parse_from_str(lex)
740        }
741    }
742
743    #[cfg(feature = "std")]
744    impl<'input> FromJson<'input> for std::net::Ipv4Addr {
745        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
746            parse_from_str(lex)
747        }
748    }
749
750    #[cfg(feature = "std")]
751    impl<'input> FromJson<'input> for std::net::Ipv6Addr {
752        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
753            parse_from_str(lex)
754        }
755    }
756
757    #[cfg(feature = "std")]
758    impl<'input> FromJson<'input> for std::net::SocketAddr {
759        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
760            parse_from_str(lex)
761        }
762    }
763
764    /// `PathBuf::from` is infallible on every byte sequence that round-
765    /// trips through UTF-8, so this never fails after string decode.
766    /// Use `parse_from_str` anyway for symmetry with the other adapters.
767    #[cfg(feature = "std")]
768    impl<'input> FromJson<'input> for std::path::PathBuf {
769        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
770            let s: String = String::from_lex(lex)?;
771            Ok(Self::from(s))
772        }
773    }
774
775    /// Transparent wrapper: parses an inner `T` and boxes it. The JSON
776    /// shape is identical to `T`'s — there is no JSON construct that
777    /// "owns" a value the way a `Box` does, and serde's convention is
778    /// the same.
779    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::boxed::Box<T> {
780        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
781            T::from_lex(lex).map(Self::new)
782        }
783    }
784
785    /// Transparent wrapper, same as `Box<T>`. `Rc` is single-threaded;
786    /// users that need cross-thread sharing should use `Arc<T>` instead.
787    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::rc::Rc<T> {
788        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
789            T::from_lex(lex).map(Self::new)
790        }
791    }
792
793    /// Transparent wrapper. `Arc` requires `target_has_atomic = "ptr"`
794    /// transitively via `alloc::sync`; we don't gate it explicitly because
795    /// `json-bourne`'s supported targets all have it.
796    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::sync::Arc<T> {
797        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
798            T::from_lex(lex).map(Self::new)
799        }
800    }
801
802    /// Returns `Some(c)` iff `s` consists of exactly one Unicode scalar.
803    #[inline]
804    fn single_char(s: &str) -> Option<char> {
805        let mut it = s.chars();
806        let c = it.next()?;
807        if it.next().is_some() {
808            return None;
809        }
810        Some(c)
811    }
812
813    /// Owned-`String` decode given a `JsonStr`. Branches on `has_escapes`:
814    /// the no-escape path borrows the validated bytes and copies into a
815    /// fresh `String`; the escape path goes through `decode_owned`.
816    #[inline]
817    fn decode_string(js: JsonStr, lex: &Lexer<'_>) -> Result<String, Error> {
818        if let Some(borrowed) = js.as_str(lex.input()) {
819            return Ok(String::from(borrowed));
820        }
821        decode_owned(js, lex)
822    }
823
824    /// Shared owned-decode path for `String` and `Cow::Owned`. Pulled out
825    /// so the two impls cannot drift on capacity hint, error mapping, or
826    /// the (subtle) raw-bytes-missing case.
827    fn decode_owned(s: JsonStr, lex: &Lexer<'_>) -> Result<String, Error> {
828        // Capacity hint is the raw byte length: the decoded form is never
829        // longer than the encoded form (every escape sequence produces at
830        // most as many UTF-8 bytes as it occupies on the wire).
831        let raw = s
832            .raw_bytes(lex.input())
833            .ok_or_else(|| Error::new(ErrorKind::InvalidEscape, lex.position()))?;
834        let mut out = String::with_capacity(raw.len());
835        decode_escapes(raw, &mut out).map_err(|kind| Error::new(kind, lex.position()))?;
836        Ok(out)
837    }
838
839    impl<'input, T: FromJson<'input>> FromJson<'input> for Vec<T> {
840        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
841            T::vec_from_lex(lex)
842        }
843    }
844
845    /// SIMD-accelerated single-byte search for `\\` inside a slice.
846    /// Returns the offset of the first backslash, or `None` if none.
847    ///
848    /// Why this exists: the literal-byte run inside `decode_escapes` is
849    /// the inner loop on strings with sparse escapes (~1 escape per 50
850    /// bytes is typical for production payloads). On profile, the scalar
851    /// `while i < n && bytes[i] != b'\\'` walk was 64% of `decode_owned`'s
852    /// time. SSE2's `_mm_cmpeq_epi8` + `_mm_movemask_epi8` walks 16 bytes
853    /// per iteration with the same correctness; on `x86_64` the gain is
854    /// ~10x for long literal runs.
855    ///
856    /// Same `unsafe_code` justification as the parent function: SSE2
857    /// is part of the `x86_64` ABI baseline, the `target_feature` arm
858    /// is statically enabled on `x86_64`, and the unsafe is mechanical
859    /// (intrinsics carry unsafe by signature, not by memory-safety).
860    #[allow(unsafe_code)]
861    #[inline]
862    fn find_backslash(bytes: &[u8]) -> Option<usize> {
863        // Two distinct cfg-gated function bodies — splitting them into
864        // separate items per arch avoids a `return` inside one cfg
865        // branch (which clippy flags as `needless_return`) while
866        // keeping each arm a single expression. The `bourne_no_simd`
867        // cfg disables the SIMD path (used by miri).
868        #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
869        {
870            find_backslash_sse2(bytes)
871        }
872        #[cfg(not(all(target_arch = "x86_64", not(bourne_no_simd))))]
873        {
874            bytes.iter().position(|&b| b == b'\\')
875        }
876    }
877
878    #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
879    #[allow(unsafe_code, clippy::cast_possible_wrap, clippy::cast_sign_loss)]
880    #[inline]
881    fn find_backslash_sse2(bytes: &[u8]) -> Option<usize> {
882        use core::arch::x86_64::{
883            _mm_cmpeq_epi8, _mm_loadu_si128, _mm_movemask_epi8, _mm_set1_epi8,
884        };
885
886        let n = bytes.len();
887        let mut i = 0;
888        // SAFETY: SSE2 is part of the x86_64 ABI baseline; rustc's default
889        // target features include `+sse2`, so the intrinsics are statically
890        // available. `_mm_loadu_si128` is documented as accepting unaligned
891        // addresses, and the bounds check `i + 16 <= n` ensures the load
892        // stays inside `bytes`.
893        unsafe {
894            let backslash = _mm_set1_epi8(b'\\' as i8);
895            while i + 16 <= n {
896                let chunk = _mm_loadu_si128(bytes.as_ptr().add(i).cast());
897                let m = _mm_cmpeq_epi8(chunk, backslash);
898                let bits = _mm_movemask_epi8(m) as u32;
899                if bits != 0 {
900                    return Some(i + bits.trailing_zeros() as usize);
901                }
902                i += 16;
903            }
904        }
905        // Tail: scalar walk for the final <16 bytes.
906        bytes[i..]
907            .iter()
908            .position(|&b| b == b'\\')
909            .map(|off| i + off)
910    }
911
912    /// Decode a JSON string body into `dst`, expanding escape sequences.
913    ///
914    /// `raw` is the bytes between (but not including) the surrounding `"`s,
915    /// produced by [`Lexer::read_string_no_validate`]. This function is
916    /// the *only* validator on that path: it covers every escape sequence
917    /// (each escape is inspected to dispatch into the right branch), every
918    /// hex digit (via `parse_hex4`), and every surrogate pairing — so the
919    /// lexer can skip the redundant `validate_escapes` walk.
920    ///
921    /// Output is always valid UTF-8: the non-escape bytes are validated by
922    /// the lexer's inline UTF-8 walk, and `\u`-derived bytes come from
923    /// `encode_utf8` on a checked `char`.
924    ///
925    /// # Safety justification for the `unsafe` block
926    ///
927    /// The literal-byte path uses `core::str::from_utf8_unchecked`. The
928    /// invariant: every byte in `raw` reached this function via the lexer,
929    /// which validates UTF-8 inline against the RFC 3629 byte ranges as it
930    /// scans (see `Parser::consume_utf8_multibyte` and `scan_ascii_string_run`
931    /// in the lexer). The bytes between escapes are therefore valid
932    /// UTF-8 by construction — re-validating them in safe code is the
933    /// `from_utf8` re-walk that perf showed at ~12% of total time (the
934    /// audit on 2026-05-19 measured the safe variant at 1.68× slower,
935    /// pushing json-bourne below `serde_json` on the escape-heavy workload).
936    /// `json-bourne`'s `unsafe_code = "deny"` lint is overridden for this one
937    /// function with `#[allow]`, mirroring the same localized exception
938    /// the lexer makes at the equivalent site.
939    ///
940    /// The outer loop dispatches between literal-byte runs and escape
941    /// sequences. Escape decoding is delegated to `decode_simple_escape`
942    /// (the 8 single-byte arms) and `decode_unicode_escape` (the `\u`
943    /// branch including surrogate-pair logic) so this fn stays inside
944    /// the project's cyclomatic-complexity budget.
945    #[allow(unsafe_code)]
946    fn decode_escapes(raw: &[u8], dst: &mut String) -> Result<(), ErrorKind> {
947        let mut i = 0;
948        while i < raw.len() {
949            if raw[i] != b'\\' {
950                // Literal byte run: find the next `\` (or end) and append the
951                // whole stretch in one push. This is the hot path for strings
952                // with sparse escapes (most production payloads).
953                //
954                // Use SIMD scan when available — the scalar walk that used
955                // to live here was 64% of total decode time on profile.
956                let start = i;
957                i = find_backslash(&raw[i..]).map_or(raw.len(), |off| i + off);
958                // SAFETY: see the function-level comment. The lexer
959                // validated these bytes as UTF-8 inline.
960                let chunk = unsafe { core::str::from_utf8_unchecked(&raw[start..i]) };
961                dst.push_str(chunk);
962                continue;
963            }
964            // At a backslash. Need at least one more byte.
965            i += 1;
966            if i >= raw.len() {
967                return Err(ErrorKind::InvalidEscape);
968            }
969            if raw[i] == b'u' {
970                i = decode_unicode_escape(raw, i, dst)?;
971            } else {
972                dst.push(decode_simple_escape(raw[i])?);
973            }
974            i += 1;
975        }
976        Ok(())
977    }
978
979    /// Decode a single non-`u` JSON escape byte to its char. The 8
980    /// match arms (`"`, `\\`, `/`, `b`, `f`, `n`, `r`, `t`) plus the
981    /// catch-all error arm live here so `decode_escapes` doesn't carry
982    /// their cyclomatic complexity.
983    #[inline]
984    const fn decode_simple_escape(b: u8) -> Result<char, ErrorKind> {
985        Ok(match b {
986            b'"' => '"',
987            b'\\' => '\\',
988            b'/' => '/',
989            b'b' => '\u{0008}',
990            b'f' => '\u{000C}',
991            b'n' => '\n',
992            b'r' => '\r',
993            b't' => '\t',
994            _ => return Err(ErrorKind::InvalidEscape),
995        })
996    }
997
998    /// Decode `\uXXXX` (and optionally a surrogate-pair `\uYYYY`) into
999    /// a char, push it to `dst`, and return the new index of the last
1000    /// byte consumed inside `raw`. `i` points at the `u` of the first
1001    /// escape. Returns the index of the last hex digit (the caller
1002    /// bumps by 1 to move past it).
1003    fn decode_unicode_escape(raw: &[u8], i: usize, dst: &mut String) -> Result<usize, ErrorKind> {
1004        if i + 5 > raw.len() {
1005            return Err(ErrorKind::InvalidUnicodeEscape);
1006        }
1007        let cp = parse_hex4(&raw[i + 1..i + 5])?;
1008        // After the four hex digits, the consumed-up-to index is i + 4.
1009        let new_i = i + 4;
1010        if (0xD800..=0xDBFF).contains(&cp) {
1011            return decode_surrogate_pair(raw, new_i, cp, dst);
1012        }
1013        if (0xDC00..=0xDFFF).contains(&cp) {
1014            return Err(ErrorKind::UnpairedSurrogate);
1015        }
1016        // BMP scalar — char::from_u32 always succeeds for values
1017        // outside the surrogate range.
1018        let ch = char::from_u32(cp).ok_or(ErrorKind::InvalidUnicodeEscape)?;
1019        dst.push(ch);
1020        Ok(new_i)
1021    }
1022
1023    /// Combine a high surrogate at position `i` with the low surrogate
1024    /// at `i+3..i+7`. Caller has validated the high half is in
1025    /// 0xD800..=0xDBFF. Returns the index of the last hex digit of the
1026    /// low half so the outer loop can resume.
1027    fn decode_surrogate_pair(
1028        raw: &[u8],
1029        i: usize,
1030        cp: u32,
1031        dst: &mut String,
1032    ) -> Result<usize, ErrorKind> {
1033        if i + 7 > raw.len() || raw[i + 1] != b'\\' || raw[i + 2] != b'u' {
1034            return Err(ErrorKind::UnpairedSurrogate);
1035        }
1036        let low = parse_hex4(&raw[i + 3..i + 7])?;
1037        if !(0xDC00..=0xDFFF).contains(&low) {
1038            return Err(ErrorKind::UnpairedSurrogate);
1039        }
1040        let high_off = cp - 0xD800;
1041        let low_off = low - 0xDC00;
1042        let scalar = 0x1_0000 + (high_off << 10) + low_off;
1043        let ch = char::from_u32(scalar).ok_or(ErrorKind::InvalidUnicodeEscape)?;
1044        dst.push(ch);
1045        Ok(i + 6) // skip `\uXXXX`
1046    }
1047
1048    /// Same digit-walk as the lexer's `parse_hex4`. Duplicated here
1049    /// rather than re-exporting because it is a four-line helper and
1050    /// keeping it private avoids widening the public API.
1051    fn parse_hex4(bytes: &[u8]) -> Result<u32, ErrorKind> {
1052        let mut v: u32 = 0;
1053        for &b in bytes {
1054            let d = match b {
1055                b'0'..=b'9' => b - b'0',
1056                b'a'..=b'f' => b - b'a' + 10,
1057                b'A'..=b'F' => b - b'A' + 10,
1058                _ => return Err(ErrorKind::InvalidUnicodeEscape),
1059            };
1060            v = (v << 4) | u32::from(d);
1061        }
1062        Ok(v)
1063    }
1064
1065    // Ensure JsonStr stays imported even if a future refactor drops the
1066    // direct reference. The trait impl above uses it transitively.
1067    #[allow(dead_code)]
1068    type _UseJsonStr = JsonStr;
1069
1070    // -----------------------------------------------------------------
1071    // IndexMap / IndexSet (optional `indexmap` feature).
1072    //
1073    // Mirror image of the BTreeMap / HashMap impls. The novel property
1074    // here is *insertion-order preservation*: the parsed map iterates
1075    // in the order keys appeared in the JSON input, which downstream
1076    // consumers depend on for stable output (canonical JSON, log
1077    // round-trips, golden-file tests).
1078    // -----------------------------------------------------------------
1079
1080    #[cfg(feature = "indexmap")]
1081    impl<'input, K, V, S> FromJson<'input> for indexmap::IndexMap<K, V, S>
1082    where
1083        K: MapKey<'input> + ::core::hash::Hash + Eq,
1084        V: FromJson<'input>,
1085        S: ::core::hash::BuildHasher + Default,
1086    {
1087        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
1088            parse_map(lex)
1089        }
1090    }
1091
1092    #[cfg(feature = "indexmap")]
1093    impl<'input, T, S> FromJson<'input> for indexmap::IndexSet<T, S>
1094    where
1095        T: FromJson<'input> + ::core::hash::Hash + Eq,
1096        S: ::core::hash::BuildHasher + Default,
1097    {
1098        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
1099            parse_set(lex)
1100        }
1101    }
1102}