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 crate::{Error, ErrorKind, JsonStr, Lexer, ValueKind};
352    use alloc::borrow::Cow;
353    use alloc::string::String;
354    use alloc::vec::Vec;
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 {
491            Self::new()
492        }
493        fn try_insert(&mut self, k: K, v: V) -> bool {
494            self.insert(k, v).is_none()
495        }
496    }
497
498    #[cfg(feature = "std")]
499    impl<K, V, S> DupMap<K, V> for std::collections::HashMap<K, V, S>
500    where
501        K: ::core::hash::Hash + Eq,
502        S: ::core::hash::BuildHasher + Default,
503    {
504        fn new_empty() -> Self {
505            Self::with_hasher(S::default())
506        }
507        fn try_insert(&mut self, k: K, v: V) -> bool {
508            self.insert(k, v).is_none()
509        }
510    }
511
512    #[cfg(feature = "indexmap")]
513    impl<K, V, S> DupMap<K, V> for indexmap::IndexMap<K, V, S>
514    where
515        K: ::core::hash::Hash + Eq,
516        S: ::core::hash::BuildHasher + Default,
517    {
518        fn new_empty() -> Self {
519            Self::with_hasher(S::default())
520        }
521        fn try_insert(&mut self, k: K, v: V) -> bool {
522            self.insert(k, v).is_none()
523        }
524    }
525
526    fn parse_map<'input, K, V, M>(lex: &mut Lexer<'input>) -> Result<M, Error>
527    where
528        K: MapKey<'input>,
529        V: FromJson<'input>,
530        M: DupMap<K, V>,
531    {
532        if !matches!(lex.peek_value_kind()?, ValueKind::Object) {
533            return Err(type_error(lex, ErrorKind::TypeMismatch));
534        }
535        lex.object_start()?;
536        let mut out = M::new_empty();
537        let mut maybe_key = lex.object_first_key_lex()?;
538        while let Some(js) = maybe_key {
539            let key_cow = key_to_cow(js, lex)?;
540            let key = K::from_key(key_cow, lex)?;
541            let v = V::from_lex(lex)?;
542            if !out.try_insert(key, v) {
543                return Err(Error::new(ErrorKind::DuplicateKey, lex.position()));
544            }
545            maybe_key = lex.object_next_key_lex()?;
546        }
547        Ok(out)
548    }
549
550    impl<'input, K, V> FromJson<'input> for alloc::collections::BTreeMap<K, V>
551    where
552        K: MapKey<'input> + Ord,
553        V: FromJson<'input>,
554    {
555        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
556            parse_map(lex)
557        }
558    }
559
560    #[cfg(feature = "std")]
561    impl<'input, K, V, S> FromJson<'input> for std::collections::HashMap<K, V, S>
562    where
563        K: MapKey<'input> + ::core::hash::Hash + Eq,
564        V: FromJson<'input>,
565        S: ::core::hash::BuildHasher + Default,
566    {
567        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
568            parse_map(lex)
569        }
570    }
571
572    trait SetInsert<T> {
573        fn new_empty() -> Self;
574        fn push(&mut self, v: T);
575    }
576
577    impl<T: Ord> SetInsert<T> for alloc::collections::BTreeSet<T> {
578        fn new_empty() -> Self {
579            Self::new()
580        }
581        fn push(&mut self, v: T) {
582            self.insert(v);
583        }
584    }
585
586    #[cfg(feature = "std")]
587    impl<T, S> SetInsert<T> for std::collections::HashSet<T, S>
588    where
589        T: ::core::hash::Hash + Eq,
590        S: ::core::hash::BuildHasher + Default,
591    {
592        fn new_empty() -> Self {
593            Self::with_hasher(S::default())
594        }
595        fn push(&mut self, v: T) {
596            self.insert(v);
597        }
598    }
599
600    #[cfg(feature = "indexmap")]
601    impl<T, S> SetInsert<T> for indexmap::IndexSet<T, S>
602    where
603        T: ::core::hash::Hash + Eq,
604        S: ::core::hash::BuildHasher + Default,
605    {
606        fn new_empty() -> Self {
607            Self::with_hasher(S::default())
608        }
609        fn push(&mut self, v: T) {
610            self.insert(v);
611        }
612    }
613
614    fn parse_set<'input, T, C>(lex: &mut Lexer<'input>) -> Result<C, Error>
615    where
616        T: FromJson<'input>,
617        C: SetInsert<T>,
618    {
619        let mut out = C::new_empty();
620        if lex.array_start()? {
621            return Ok(out);
622        }
623        out.push(T::from_lex(lex)?);
624        while !lex.array_continue(b']')? {
625            out.push(T::from_lex(lex)?);
626        }
627        Ok(out)
628    }
629
630    impl<'input, T> FromJson<'input> for alloc::collections::BTreeSet<T>
631    where
632        T: FromJson<'input> + Ord,
633    {
634        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
635            parse_set(lex)
636        }
637    }
638
639    #[cfg(feature = "std")]
640    impl<'input, T, S> FromJson<'input> for std::collections::HashSet<T, S>
641    where
642        T: FromJson<'input> + ::core::hash::Hash + Eq,
643        S: ::core::hash::BuildHasher + Default,
644    {
645        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
646            parse_set(lex)
647        }
648    }
649
650    // -----------------------------------------------------------------
651    // std::time and std::net adapters.
652    //
653    // JSON has no native types for any of these, so we pick a single
654    // convention per type. These are deliberately simple — projects
655    // with bespoke encodings (RFC 3339 timestamps, custom Duration
656    // shapes) should hand-write a wrapper newtype.
657    // -----------------------------------------------------------------
658
659    /// Parse a `Duration` from JSON `Number` (seconds, possibly fractional).
660    /// Negative inputs and non-finite values are rejected. Subsecond
661    /// precision is preserved to nanosecond resolution.
662    ///
663    /// Implementation note: pre-validates the input to a finite,
664    /// non-negative value within `Duration`'s u64-seconds range, then
665    /// delegates to `Duration::from_secs_f64`. The earlier hand-rolled
666    /// `trunc`/`mul`/`round`/`clamp` sequence was ~3.5× slower than
667    /// `from_secs_f64` on profile (the libstd routine inlines a
668    /// branch-light decomposition of the f64 mantissa).
669    #[cfg(feature = "std")]
670    impl<'input> FromJson<'input> for std::time::Duration {
671        #[allow(clippy::cast_precision_loss)]
672        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
673            // Skip the `f64::from_lex` detour: that does a
674            // `peek_value_kind` first, which `parse_f64_value`'s
675            // own type check makes redundant for the Number arm.
676            let secs_f = match lex.peek_value_kind()? {
677                ValueKind::Number => lex.parse_f64_value()?,
678                _ => return Err(type_error(lex, ErrorKind::ExpectedNumber)),
679            };
680            // `Duration::from_secs_f64` panics on these inputs;
681            // convert to typed errors before calling.
682            if !secs_f.is_finite() || secs_f < 0.0 || secs_f >= (u64::MAX as f64) {
683                return Err(type_error(lex, ErrorKind::NumberOutOfRange));
684            }
685            Ok(Self::from_secs_f64(secs_f))
686        }
687
688        /// Fused-pass fast path for `Vec<Duration>`. Mirrors the
689        /// `Vec<f64>` override: `parse_f64_value` directly per
690        /// element, no type-peek detour past the first.
691        #[cfg(feature = "alloc")]
692        #[allow(clippy::cast_precision_loss)]
693        fn vec_from_lex(lex: &mut Lexer<'input>) -> Result<alloc::vec::Vec<Self>, Error> {
694            #[inline]
695            fn convert(lex: &Lexer<'_>, secs_f: f64) -> Result<std::time::Duration, Error> {
696                if !secs_f.is_finite() || secs_f < 0.0 || secs_f >= (u64::MAX as f64) {
697                    return Err(type_error(lex, ErrorKind::NumberOutOfRange));
698                }
699                Ok(std::time::Duration::from_secs_f64(secs_f))
700            }
701            let mut out: alloc::vec::Vec<Self> = alloc::vec::Vec::new();
702            if lex.array_start()? {
703                return Ok(out);
704            }
705            let secs_f = lex.parse_f64_value()?;
706            out.push(convert(lex, secs_f)?);
707            while !lex.array_continue(b']')? {
708                let secs_f = lex.parse_f64_value()?;
709                out.push(convert(lex, secs_f)?);
710            }
711            Ok(out)
712        }
713    }
714
715    /// Parse a `SystemTime` from JSON `Number` (seconds since
716    /// `UNIX_EPOCH`, possibly fractional and possibly negative).
717    /// Mirrors the `Duration` adapter but allows negative values for
718    /// pre-epoch timestamps, which the `SystemTime` arithmetic model
719    /// supports.
720    ///
721    /// Subsecond precision is preserved to nanosecond resolution via
722    /// `Duration::from_secs_f64`.
723    #[cfg(feature = "std")]
724    impl<'input> FromJson<'input> for std::time::SystemTime {
725        #[allow(clippy::cast_precision_loss)]
726        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
727            let secs_f = match lex.peek_value_kind()? {
728                ValueKind::Number => lex.parse_f64_value()?,
729                _ => return Err(type_error(lex, ErrorKind::ExpectedNumber)),
730            };
731            // Reject non-finite inputs and clamp the magnitude to a
732            // range Duration::from_secs_f64 won't panic on.
733            if !secs_f.is_finite() || secs_f.abs() >= (u64::MAX as f64) {
734                return Err(type_error(lex, ErrorKind::NumberOutOfRange));
735            }
736            let abs = std::time::Duration::from_secs_f64(secs_f.abs());
737            let epoch = std::time::UNIX_EPOCH;
738            let st = if secs_f < 0.0 {
739                epoch.checked_sub(abs)
740            } else {
741                epoch.checked_add(abs)
742            };
743            st.ok_or_else(|| type_error(lex, ErrorKind::NumberOutOfRange))
744        }
745    }
746
747    /// Generic adapter for any type whose canonical text form is parseable
748    /// via `FromStr`. Used below for `IpAddr`, `Ipv4Addr`, `Ipv6Addr`,
749    /// `SocketAddr`, and `PathBuf`. Failures map to `TypeMismatch`.
750    #[cfg(feature = "std")]
751    fn parse_from_str<'input, T>(lex: &mut Lexer<'input>) -> Result<T, Error>
752    where
753        T: ::core::str::FromStr,
754    {
755        let cow: Cow<'input, str> = Cow::<'input, str>::from_lex(lex)?;
756        cow.parse::<T>()
757            .map_err(|_| type_error(lex, ErrorKind::TypeMismatch))
758    }
759
760    #[cfg(feature = "std")]
761    impl<'input> FromJson<'input> for std::net::IpAddr {
762        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
763            parse_from_str(lex)
764        }
765    }
766
767    #[cfg(feature = "std")]
768    impl<'input> FromJson<'input> for std::net::Ipv4Addr {
769        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
770            parse_from_str(lex)
771        }
772    }
773
774    #[cfg(feature = "std")]
775    impl<'input> FromJson<'input> for std::net::Ipv6Addr {
776        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
777            parse_from_str(lex)
778        }
779    }
780
781    #[cfg(feature = "std")]
782    impl<'input> FromJson<'input> for std::net::SocketAddr {
783        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
784            parse_from_str(lex)
785        }
786    }
787
788    /// `PathBuf::from` is infallible on every byte sequence that round-
789    /// trips through UTF-8, so this never fails after string decode.
790    /// Use `parse_from_str` anyway for symmetry with the other adapters.
791    #[cfg(feature = "std")]
792    impl<'input> FromJson<'input> for std::path::PathBuf {
793        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
794            let s: String = String::from_lex(lex)?;
795            Ok(Self::from(s))
796        }
797    }
798
799    /// Transparent wrapper: parses an inner `T` and boxes it. The JSON
800    /// shape is identical to `T`'s — there is no JSON construct that
801    /// "owns" a value the way a `Box` does, and serde's convention is
802    /// the same.
803    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::boxed::Box<T> {
804        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
805            T::from_lex(lex).map(Self::new)
806        }
807    }
808
809    /// Transparent wrapper, same as `Box<T>`. `Rc` is single-threaded;
810    /// users that need cross-thread sharing should use `Arc<T>` instead.
811    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::rc::Rc<T> {
812        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
813            T::from_lex(lex).map(Self::new)
814        }
815    }
816
817    /// Transparent wrapper. `Arc` requires `target_has_atomic = "ptr"`
818    /// transitively via `alloc::sync`; we don't gate it explicitly because
819    /// `json-bourne`'s supported targets all have it.
820    impl<'input, T: FromJson<'input>> FromJson<'input> for alloc::sync::Arc<T> {
821        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
822            T::from_lex(lex).map(Self::new)
823        }
824    }
825
826    /// Returns `Some(c)` iff `s` consists of exactly one Unicode scalar.
827    #[inline]
828    fn single_char(s: &str) -> Option<char> {
829        let mut it = s.chars();
830        let c = it.next()?;
831        if it.next().is_some() {
832            return None;
833        }
834        Some(c)
835    }
836
837    /// Owned-`String` decode given a `JsonStr`. Branches on `has_escapes`:
838    /// the no-escape path borrows the validated bytes and copies into a
839    /// fresh `String`; the escape path goes through `decode_owned`.
840    #[inline]
841    fn decode_string(js: JsonStr, lex: &Lexer<'_>) -> Result<String, Error> {
842        if let Some(borrowed) = js.as_str(lex.input()) {
843            return Ok(String::from(borrowed));
844        }
845        decode_owned(js, lex)
846    }
847
848    /// Shared owned-decode path for `String` and `Cow::Owned`. Pulled out
849    /// so the two impls cannot drift on capacity hint, error mapping, or
850    /// the (subtle) raw-bytes-missing case.
851    fn decode_owned(s: JsonStr, lex: &Lexer<'_>) -> Result<String, Error> {
852        // Capacity hint is the raw byte length: the decoded form is never
853        // longer than the encoded form (every escape sequence produces at
854        // most as many UTF-8 bytes as it occupies on the wire).
855        let raw = s
856            .raw_bytes(lex.input())
857            .ok_or_else(|| Error::new(ErrorKind::InvalidEscape, lex.position()))?;
858        let mut out = String::with_capacity(raw.len());
859        decode_escapes(raw, &mut out).map_err(|kind| Error::new(kind, lex.position()))?;
860        Ok(out)
861    }
862
863    impl<'input, T: FromJson<'input>> FromJson<'input> for Vec<T> {
864        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
865            T::vec_from_lex(lex)
866        }
867    }
868
869    /// SIMD-accelerated single-byte search for `\\` inside a slice.
870    /// Returns the offset of the first backslash, or `None` if none.
871    ///
872    /// Why this exists: the literal-byte run inside `decode_escapes` is
873    /// the inner loop on strings with sparse escapes (~1 escape per 50
874    /// bytes is typical for production payloads). On profile, the scalar
875    /// `while i < n && bytes[i] != b'\\'` walk was 64% of `decode_owned`'s
876    /// time. SSE2's `_mm_cmpeq_epi8` + `_mm_movemask_epi8` walks 16 bytes
877    /// per iteration with the same correctness; on `x86_64` the gain is
878    /// ~10x for long literal runs.
879    ///
880    /// Same `unsafe_code` justification as the parent function: SSE2
881    /// is part of the `x86_64` ABI baseline, the `target_feature` arm
882    /// is statically enabled on `x86_64`, and the unsafe is mechanical
883    /// (intrinsics carry unsafe by signature, not by memory-safety).
884    #[allow(unsafe_code)]
885    #[inline]
886    fn find_backslash(bytes: &[u8]) -> Option<usize> {
887        // Two distinct cfg-gated function bodies — splitting them into
888        // separate items per arch avoids a `return` inside one cfg
889        // branch (which clippy flags as `needless_return`) while
890        // keeping each arm a single expression. The `bourne_no_simd`
891        // cfg disables the SIMD path (used by miri).
892        #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
893        {
894            find_backslash_sse2(bytes)
895        }
896        #[cfg(not(all(target_arch = "x86_64", not(bourne_no_simd))))]
897        {
898            bytes.iter().position(|&b| b == b'\\')
899        }
900    }
901
902    #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
903    #[allow(unsafe_code, clippy::cast_possible_wrap, clippy::cast_sign_loss)]
904    #[inline]
905    fn find_backslash_sse2(bytes: &[u8]) -> Option<usize> {
906        use core::arch::x86_64::{
907            _mm_cmpeq_epi8, _mm_loadu_si128, _mm_movemask_epi8, _mm_set1_epi8,
908        };
909
910        let n = bytes.len();
911        let mut i = 0;
912        // SAFETY: SSE2 is part of the x86_64 ABI baseline; rustc's default
913        // target features include `+sse2`, so the intrinsics are statically
914        // available. `_mm_loadu_si128` is documented as accepting unaligned
915        // addresses, and the bounds check `i + 16 <= n` ensures the load
916        // stays inside `bytes`.
917        unsafe {
918            let backslash = _mm_set1_epi8(b'\\' as i8);
919            while i + 16 <= n {
920                let chunk = _mm_loadu_si128(bytes.as_ptr().add(i).cast());
921                let m = _mm_cmpeq_epi8(chunk, backslash);
922                let bits = _mm_movemask_epi8(m) as u32;
923                if bits != 0 {
924                    return Some(i + bits.trailing_zeros() as usize);
925                }
926                i += 16;
927            }
928        }
929        // Tail: scalar walk for the final <16 bytes.
930        bytes[i..]
931            .iter()
932            .position(|&b| b == b'\\')
933            .map(|off| i + off)
934    }
935
936    /// Decode a JSON string body into `dst`, expanding escape sequences.
937    ///
938    /// `raw` is the bytes between (but not including) the surrounding `"`s,
939    /// produced by [`Lexer::read_string_no_validate`]. This function is
940    /// the *only* validator on that path: it covers every escape sequence
941    /// (each escape is inspected to dispatch into the right branch), every
942    /// hex digit (via `parse_hex4`), and every surrogate pairing — so the
943    /// lexer can skip the redundant `validate_escapes` walk.
944    ///
945    /// Output is always valid UTF-8: the non-escape bytes are validated by
946    /// the lexer's inline UTF-8 walk, and `\u`-derived bytes come from
947    /// `encode_utf8` on a checked `char`.
948    ///
949    /// # Safety justification for the `unsafe` block
950    ///
951    /// The literal-byte path uses `core::str::from_utf8_unchecked`. The
952    /// invariant: every byte in `raw` reached this function via the lexer,
953    /// which validates UTF-8 inline against the RFC 3629 byte ranges as it
954    /// scans (see `Parser::consume_utf8_multibyte` and `scan_ascii_string_run`
955    /// in the lexer). The bytes between escapes are therefore valid
956    /// UTF-8 by construction — re-validating them in safe code is the
957    /// `from_utf8` re-walk that perf showed at ~12% of total time (the
958    /// audit on 2026-05-19 measured the safe variant at 1.68× slower,
959    /// pushing json-bourne below `serde_json` on the escape-heavy workload).
960    /// `json-bourne`'s `unsafe_code = "deny"` lint is overridden for this one
961    /// function with `#[allow]`, mirroring the same localized exception
962    /// the lexer makes at the equivalent site.
963    ///
964    /// The outer loop dispatches between literal-byte runs and escape
965    /// sequences. Escape decoding is delegated to `decode_simple_escape`
966    /// (the 8 single-byte arms) and `decode_unicode_escape` (the `\u`
967    /// branch including surrogate-pair logic) so this fn stays inside
968    /// the project's cyclomatic-complexity budget.
969    #[allow(unsafe_code)]
970    fn decode_escapes(raw: &[u8], dst: &mut String) -> Result<(), ErrorKind> {
971        let mut i = 0;
972        while i < raw.len() {
973            if raw[i] != b'\\' {
974                // Literal byte run: find the next `\` (or end) and append the
975                // whole stretch in one push. This is the hot path for strings
976                // with sparse escapes (most production payloads).
977                //
978                // Use SIMD scan when available — the scalar walk that used
979                // to live here was 64% of total decode time on profile.
980                let start = i;
981                i = find_backslash(&raw[i..]).map_or(raw.len(), |off| i + off);
982                // SAFETY: see the function-level comment. The lexer
983                // validated these bytes as UTF-8 inline.
984                let chunk = unsafe { core::str::from_utf8_unchecked(&raw[start..i]) };
985                dst.push_str(chunk);
986                continue;
987            }
988            // At a backslash. Need at least one more byte.
989            i += 1;
990            if i >= raw.len() {
991                return Err(ErrorKind::InvalidEscape);
992            }
993            if raw[i] == b'u' {
994                i = decode_unicode_escape(raw, i, dst)?;
995            } else {
996                dst.push(decode_simple_escape(raw[i])?);
997            }
998            i += 1;
999        }
1000        Ok(())
1001    }
1002
1003    /// Decode a single non-`u` JSON escape byte to its char. The 8
1004    /// match arms (`"`, `\\`, `/`, `b`, `f`, `n`, `r`, `t`) plus the
1005    /// catch-all error arm live here so `decode_escapes` doesn't carry
1006    /// their cyclomatic complexity.
1007    #[inline]
1008    const fn decode_simple_escape(b: u8) -> Result<char, ErrorKind> {
1009        Ok(match b {
1010            b'"' => '"',
1011            b'\\' => '\\',
1012            b'/' => '/',
1013            b'b' => '\u{0008}',
1014            b'f' => '\u{000C}',
1015            b'n' => '\n',
1016            b'r' => '\r',
1017            b't' => '\t',
1018            _ => return Err(ErrorKind::InvalidEscape),
1019        })
1020    }
1021
1022    /// Decode `\uXXXX` (and optionally a surrogate-pair `\uYYYY`) into
1023    /// a char, push it to `dst`, and return the new index of the last
1024    /// byte consumed inside `raw`. `i` points at the `u` of the first
1025    /// escape. Returns the index of the last hex digit (the caller
1026    /// bumps by 1 to move past it).
1027    fn decode_unicode_escape(raw: &[u8], i: usize, dst: &mut String) -> Result<usize, ErrorKind> {
1028        if i + 5 > raw.len() {
1029            return Err(ErrorKind::InvalidUnicodeEscape);
1030        }
1031        let cp = parse_hex4(&raw[i + 1..i + 5])?;
1032        // After the four hex digits, the consumed-up-to index is i + 4.
1033        let new_i = i + 4;
1034        if (0xD800..=0xDBFF).contains(&cp) {
1035            return decode_surrogate_pair(raw, new_i, cp, dst);
1036        }
1037        if (0xDC00..=0xDFFF).contains(&cp) {
1038            return Err(ErrorKind::UnpairedSurrogate);
1039        }
1040        // BMP scalar — char::from_u32 always succeeds for values
1041        // outside the surrogate range.
1042        let ch = char::from_u32(cp).ok_or(ErrorKind::InvalidUnicodeEscape)?;
1043        dst.push(ch);
1044        Ok(new_i)
1045    }
1046
1047    /// Combine a high surrogate at position `i` with the low surrogate
1048    /// at `i+3..i+7`. Caller has validated the high half is in
1049    /// 0xD800..=0xDBFF. Returns the index of the last hex digit of the
1050    /// low half so the outer loop can resume.
1051    fn decode_surrogate_pair(
1052        raw: &[u8],
1053        i: usize,
1054        cp: u32,
1055        dst: &mut String,
1056    ) -> Result<usize, ErrorKind> {
1057        if i + 7 > raw.len() || raw[i + 1] != b'\\' || raw[i + 2] != b'u' {
1058            return Err(ErrorKind::UnpairedSurrogate);
1059        }
1060        let low = parse_hex4(&raw[i + 3..i + 7])?;
1061        if !(0xDC00..=0xDFFF).contains(&low) {
1062            return Err(ErrorKind::UnpairedSurrogate);
1063        }
1064        let high_off = cp - 0xD800;
1065        let low_off = low - 0xDC00;
1066        let scalar = 0x1_0000 + (high_off << 10) + low_off;
1067        let ch = char::from_u32(scalar).ok_or(ErrorKind::InvalidUnicodeEscape)?;
1068        dst.push(ch);
1069        Ok(i + 6) // skip `\uXXXX`
1070    }
1071
1072    /// Same digit-walk as the lexer's `parse_hex4`. Duplicated here
1073    /// rather than re-exporting because it is a four-line helper and
1074    /// keeping it private avoids widening the public API.
1075    fn parse_hex4(bytes: &[u8]) -> Result<u32, ErrorKind> {
1076        let mut v: u32 = 0;
1077        for &b in bytes {
1078            let d = match b {
1079                b'0'..=b'9' => b - b'0',
1080                b'a'..=b'f' => b - b'a' + 10,
1081                b'A'..=b'F' => b - b'A' + 10,
1082                _ => return Err(ErrorKind::InvalidUnicodeEscape),
1083            };
1084            v = (v << 4) | u32::from(d);
1085        }
1086        Ok(v)
1087    }
1088
1089    // Ensure JsonStr stays imported even if a future refactor drops the
1090    // direct reference. The trait impl above uses it transitively.
1091    #[allow(dead_code)]
1092    type _UseJsonStr = JsonStr;
1093
1094    // -----------------------------------------------------------------
1095    // IndexMap / IndexSet (optional `indexmap` feature).
1096    //
1097    // Mirror image of the BTreeMap / HashMap impls. The novel property
1098    // here is *insertion-order preservation*: the parsed map iterates
1099    // in the order keys appeared in the JSON input, which downstream
1100    // consumers depend on for stable output (canonical JSON, log
1101    // round-trips, golden-file tests).
1102    // -----------------------------------------------------------------
1103
1104    #[cfg(feature = "indexmap")]
1105    impl<'input, K, V, S> FromJson<'input> for indexmap::IndexMap<K, V, S>
1106    where
1107        K: MapKey<'input> + ::core::hash::Hash + Eq,
1108        V: FromJson<'input>,
1109        S: ::core::hash::BuildHasher + Default,
1110    {
1111        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
1112            parse_map(lex)
1113        }
1114    }
1115
1116    #[cfg(feature = "indexmap")]
1117    impl<'input, T, S> FromJson<'input> for indexmap::IndexSet<T, S>
1118    where
1119        T: FromJson<'input> + ::core::hash::Hash + Eq,
1120        S: ::core::hash::BuildHasher + Default,
1121    {
1122        fn from_lex(lex: &mut Lexer<'input>) -> Result<Self, Error> {
1123            parse_set(lex)
1124        }
1125    }
1126}