facet_json/
deserialize.rs

1//! Recursive descent JSON deserializer using facet-reflect.
2
3use alloc::borrow::Cow;
4use alloc::format;
5use alloc::string::{String, ToString};
6use alloc::vec::Vec;
7use core::fmt::{self, Display};
8use core::ptr;
9
10use alloc::collections::{BTreeMap, BTreeSet};
11
12use facet_core::{
13    Characteristic, Def, Facet, KnownPointer, NumericType, PrimitiveType, ScalarType, SequenceType,
14    Shape, ShapeLayout, StructKind, Type, UserType,
15};
16use facet_reflect::{Partial, ReflectError, is_spanned_shape};
17use facet_solver::{FieldInfo, PathSegment, Schema, Solver, VariantsByFormat, specificity_score};
18
19use crate::RawJson;
20use crate::adapter::{AdapterError, AdapterErrorKind, SliceAdapter, SpannedAdapterToken, Token};
21use crate::scanner::ScanErrorKind;
22use facet_reflect::Span;
23
24/// Find the best matching field name from a list of expected fields.
25/// Returns Some(suggestion) if a match with similarity >= 0.6 is found.
26fn find_similar_field<'a>(unknown: &str, expected: &[&'a str]) -> Option<&'a str> {
27    let mut best_match: Option<(&'a str, f64)> = None;
28
29    for &candidate in expected {
30        let similarity = strsim::jaro_winkler(unknown, candidate);
31        if similarity >= 0.6 && best_match.is_none_or(|(_, best_sim)| similarity > best_sim) {
32            best_match = Some((candidate, similarity));
33        }
34    }
35
36    best_match.map(|(name, _)| name)
37}
38
39// ============================================================================
40// Error Types
41// ============================================================================
42
43/// Error type for JSON deserialization.
44#[derive(Debug)]
45pub struct JsonError {
46    /// The specific kind of error
47    pub kind: JsonErrorKind,
48    /// Source span where the error occurred
49    pub span: Option<Span>,
50    /// The source input (for diagnostics)
51    pub source_code: Option<String>,
52}
53
54impl Display for JsonError {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        write!(f, "{}", self.kind)
57    }
58}
59
60impl std::error::Error for JsonError {}
61
62impl miette::Diagnostic for JsonError {
63    fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
64        Some(Box::new(self.kind.code()))
65    }
66
67    fn source_code(&self) -> Option<&dyn miette::SourceCode> {
68        self.source_code
69            .as_ref()
70            .map(|s| s as &dyn miette::SourceCode)
71    }
72
73    fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
74        // Handle MissingField with multiple spans
75        if let JsonErrorKind::MissingField {
76            field,
77            object_start,
78            object_end,
79        } = &self.kind
80        {
81            let mut labels = Vec::new();
82            if let Some(start) = object_start {
83                labels.push(miette::LabeledSpan::new(
84                    Some("object started here".into()),
85                    start.offset,
86                    start.len,
87                ));
88            }
89            if let Some(end) = object_end {
90                labels.push(miette::LabeledSpan::new(
91                    Some(format!("object ended without field `{field}`")),
92                    end.offset,
93                    end.len,
94                ));
95            }
96            if labels.is_empty() {
97                return None;
98            }
99            return Some(Box::new(labels.into_iter()));
100        }
101
102        // Default: single span with label
103        let span = self.span?;
104        Some(Box::new(core::iter::once(miette::LabeledSpan::new(
105            Some(self.kind.label()),
106            span.offset,
107            span.len,
108        ))))
109    }
110}
111
112impl JsonError {
113    /// Create a new error with span information
114    pub fn new(kind: JsonErrorKind, span: Span) -> Self {
115        JsonError {
116            kind,
117            span: Some(span),
118            source_code: None,
119        }
120    }
121
122    /// Create an error without span information
123    pub fn without_span(kind: JsonErrorKind) -> Self {
124        JsonError {
125            kind,
126            span: None,
127            source_code: None,
128        }
129    }
130
131    /// Attach source code for rich diagnostics
132    pub fn with_source(mut self, source: &str) -> Self {
133        self.source_code = Some(source.to_string());
134        self
135    }
136}
137
138#[inline(never)]
139#[cold]
140fn attach_source_cold(mut err: JsonError, source: Option<&str>) -> JsonError {
141    if let Some(src) = source {
142        err.source_code = Some(src.to_string());
143    }
144    err
145}
146
147/// Specific error kinds for JSON deserialization
148#[derive(Debug)]
149pub enum JsonErrorKind {
150    /// Scanner/adapter error
151    Scan(ScanErrorKind),
152    /// Scanner error with type context (what type was being parsed)
153    ScanWithContext {
154        /// The underlying scan error
155        error: ScanErrorKind,
156        /// The type that was being parsed
157        expected_type: &'static str,
158    },
159    /// Unexpected token
160    UnexpectedToken {
161        /// The token that was found
162        got: String,
163        /// What was expected instead
164        expected: &'static str,
165    },
166    /// Unexpected end of input
167    UnexpectedEof {
168        /// What was expected before EOF
169        expected: &'static str,
170    },
171    /// Type mismatch
172    TypeMismatch {
173        /// The expected type
174        expected: &'static str,
175        /// The actual type found
176        got: &'static str,
177    },
178    /// Unknown field in struct
179    UnknownField {
180        /// The unknown field name
181        field: String,
182        /// List of valid field names
183        expected: Vec<&'static str>,
184        /// Suggested field name (if similar to an expected field)
185        suggestion: Option<&'static str>,
186    },
187    /// Missing required field
188    MissingField {
189        /// The name of the missing field
190        field: &'static str,
191        /// Span of the object start (opening brace)
192        object_start: Option<Span>,
193        /// Span of the object end (closing brace)
194        object_end: Option<Span>,
195    },
196    /// Invalid value for type
197    InvalidValue {
198        /// Description of why the value is invalid
199        message: String,
200    },
201    /// Reflection error from facet-reflect
202    Reflect(ReflectError),
203    /// Number out of range
204    NumberOutOfRange {
205        /// The numeric value that was out of range
206        value: String,
207        /// The target type that couldn't hold the value
208        target_type: &'static str,
209    },
210    /// Duplicate key in object
211    DuplicateKey {
212        /// The key that appeared more than once
213        key: String,
214    },
215    /// Invalid UTF-8 in string
216    InvalidUtf8,
217    /// Solver error (for flattened types)
218    Solver(String),
219    /// I/O error (for streaming deserialization)
220    Io(String),
221}
222
223impl Display for JsonErrorKind {
224    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225        match self {
226            JsonErrorKind::Scan(e) => write!(f, "{e:?}"),
227            JsonErrorKind::ScanWithContext {
228                error,
229                expected_type,
230            } => {
231                write!(f, "{error:?} (while parsing {expected_type})")
232            }
233            JsonErrorKind::UnexpectedToken { got, expected } => {
234                write!(f, "unexpected token: got {got}, expected {expected}")
235            }
236            JsonErrorKind::UnexpectedEof { expected } => {
237                write!(f, "unexpected end of input, expected {expected}")
238            }
239            JsonErrorKind::TypeMismatch { expected, got } => {
240                write!(f, "type mismatch: expected {expected}, got {got}")
241            }
242            JsonErrorKind::UnknownField {
243                field,
244                expected,
245                suggestion,
246            } => {
247                write!(f, "unknown field `{field}`, expected one of: {expected:?}")?;
248                if let Some(suggested) = suggestion {
249                    write!(f, " (did you mean `{suggested}`?)")?;
250                }
251                Ok(())
252            }
253            JsonErrorKind::MissingField { field, .. } => {
254                write!(f, "missing required field `{field}`")
255            }
256            JsonErrorKind::InvalidValue { message } => {
257                write!(f, "invalid value: {message}")
258            }
259            JsonErrorKind::Reflect(e) => write!(f, "reflection error: {e}"),
260            JsonErrorKind::NumberOutOfRange { value, target_type } => {
261                write!(f, "number `{value}` out of range for {target_type}")
262            }
263            JsonErrorKind::DuplicateKey { key } => {
264                write!(f, "duplicate key `{key}`")
265            }
266            JsonErrorKind::InvalidUtf8 => write!(f, "invalid UTF-8 sequence"),
267            JsonErrorKind::Solver(msg) => write!(f, "solver error: {msg}"),
268            JsonErrorKind::Io(msg) => write!(f, "I/O error: {msg}"),
269        }
270    }
271}
272
273impl JsonErrorKind {
274    /// Get an error code for this kind of error.
275    pub fn code(&self) -> &'static str {
276        match self {
277            JsonErrorKind::Scan(_) => "json::scan",
278            JsonErrorKind::ScanWithContext { .. } => "json::scan",
279            JsonErrorKind::UnexpectedToken { .. } => "json::unexpected_token",
280            JsonErrorKind::UnexpectedEof { .. } => "json::unexpected_eof",
281            JsonErrorKind::TypeMismatch { .. } => "json::type_mismatch",
282            JsonErrorKind::UnknownField { .. } => "json::unknown_field",
283            JsonErrorKind::MissingField { .. } => "json::missing_field",
284            JsonErrorKind::InvalidValue { .. } => "json::invalid_value",
285            JsonErrorKind::Reflect(_) => "json::reflect",
286            JsonErrorKind::NumberOutOfRange { .. } => "json::number_out_of_range",
287            JsonErrorKind::DuplicateKey { .. } => "json::duplicate_key",
288            JsonErrorKind::InvalidUtf8 => "json::invalid_utf8",
289            JsonErrorKind::Solver(_) => "json::solver",
290            JsonErrorKind::Io(_) => "json::io",
291        }
292    }
293
294    /// Get a label describing where/what the error points to.
295    pub fn label(&self) -> String {
296        match self {
297            JsonErrorKind::Scan(e) => match e {
298                ScanErrorKind::UnexpectedChar(c) => format!("unexpected '{c}'"),
299                ScanErrorKind::UnexpectedEof(ctx) => format!("unexpected end of input {ctx}"),
300                ScanErrorKind::InvalidUtf8 => "invalid UTF-8 here".into(),
301            },
302            JsonErrorKind::ScanWithContext {
303                error,
304                expected_type,
305            } => match error {
306                ScanErrorKind::UnexpectedChar(c) => {
307                    format!("unexpected '{c}', expected {expected_type}")
308                }
309                ScanErrorKind::UnexpectedEof(_) => {
310                    format!("unexpected end of input, expected {expected_type}")
311                }
312                ScanErrorKind::InvalidUtf8 => "invalid UTF-8 here".into(),
313            },
314            JsonErrorKind::UnexpectedToken { got, expected } => {
315                format!("expected {expected}, got '{got}'")
316            }
317            JsonErrorKind::UnexpectedEof { expected } => format!("expected {expected}"),
318            JsonErrorKind::TypeMismatch { expected, got } => {
319                format!("expected {expected}, got {got}")
320            }
321            JsonErrorKind::UnknownField {
322                field, suggestion, ..
323            } => {
324                if let Some(suggested) = suggestion {
325                    format!("unknown field '{field}' - did you mean '{suggested}'?")
326                } else {
327                    format!("unknown field '{field}'")
328                }
329            }
330            JsonErrorKind::MissingField { field, .. } => format!("missing field '{field}'"),
331            JsonErrorKind::InvalidValue { .. } => "invalid value".into(),
332            JsonErrorKind::Reflect(_) => "reflection error".into(),
333            JsonErrorKind::NumberOutOfRange { target_type, .. } => {
334                format!("out of range for {target_type}")
335            }
336            JsonErrorKind::DuplicateKey { key } => format!("duplicate key '{key}'"),
337            JsonErrorKind::InvalidUtf8 => "invalid UTF-8".into(),
338            JsonErrorKind::Solver(_) => "solver error".into(),
339            JsonErrorKind::Io(_) => "I/O error".into(),
340        }
341    }
342}
343
344impl From<AdapterError> for JsonError {
345    fn from(err: AdapterError) -> Self {
346        let kind = match err.kind {
347            AdapterErrorKind::Scan(scan_err) => JsonErrorKind::Scan(scan_err),
348            AdapterErrorKind::NeedMore => JsonErrorKind::UnexpectedEof {
349                expected: "more data",
350            },
351        };
352        JsonError {
353            kind,
354            span: Some(err.span),
355            source_code: None,
356        }
357    }
358}
359
360impl From<ReflectError> for JsonError {
361    fn from(err: ReflectError) -> Self {
362        JsonError {
363            kind: JsonErrorKind::Reflect(err),
364            span: None,
365            source_code: None,
366        }
367    }
368}
369
370/// Result type for JSON deserialization
371pub type Result<T> = core::result::Result<T, JsonError>;
372
373// ============================================================================
374// Deserializer
375// ============================================================================
376
377use crate::adapter::TokenSource;
378
379/// JSON deserializer using recursive descent.
380///
381/// Generic over a token source `A` which must implement `TokenSource<'input>`.
382/// The const generic `BORROW` controls whether string data can be borrowed:
383/// - `BORROW=true`: strings without escapes are borrowed from input (for slice-based parsing)
384/// - `BORROW=false`: all strings are owned (for streaming or owned output)
385///
386/// For slice-based parsing, use `SliceAdapter<'input, BORROW>`.
387/// For streaming parsing, use `StreamingAdapter` with `BORROW=false`.
388pub struct JsonDeserializer<'input, const BORROW: bool, A: TokenSource<'input>> {
389    adapter: A,
390    /// Peeked token (for lookahead)
391    peeked: Option<SpannedAdapterToken<'input>>,
392}
393
394impl<'input> JsonDeserializer<'input, true, SliceAdapter<'input, true>> {
395    /// Create a new deserializer for the given input.
396    /// Strings without escapes will be borrowed from input.
397    pub fn new(input: &'input [u8]) -> Self {
398        JsonDeserializer {
399            adapter: SliceAdapter::new(input),
400            peeked: None,
401        }
402    }
403}
404
405impl<'input> JsonDeserializer<'input, false, SliceAdapter<'input, false>> {
406    /// Create a new deserializer that produces owned strings.
407    /// Use this when deserializing into owned types from temporary buffers.
408    pub fn new_owned(input: &'input [u8]) -> Self {
409        JsonDeserializer {
410            adapter: SliceAdapter::new(input),
411            peeked: None,
412        }
413    }
414}
415
416impl<'input, const BORROW: bool, A: TokenSource<'input>> JsonDeserializer<'input, BORROW, A> {
417    /// Create a deserializer from an existing adapter.
418    pub fn from_adapter(adapter: A) -> Self {
419        JsonDeserializer {
420            adapter,
421            peeked: None,
422        }
423    }
424
425    /// Peek at the next token without consuming it.
426    fn peek(&mut self) -> Result<&SpannedAdapterToken<'input>> {
427        if self.peeked.is_none() {
428            self.peeked = Some(self.adapter.next_token()?);
429        }
430        Ok(self.peeked.as_ref().unwrap())
431    }
432
433    /// Consume and return the next token.
434    fn next(&mut self) -> Result<SpannedAdapterToken<'input>> {
435        if let Some(token) = self.peeked.take() {
436            Ok(token)
437        } else {
438            Ok(self.adapter.next_token()?)
439        }
440    }
441
442    /// Consume the next token with type context for better error messages.
443    fn next_expecting(
444        &mut self,
445        expected_type: &'static str,
446    ) -> Result<SpannedAdapterToken<'input>> {
447        match self.next() {
448            Ok(token) => Ok(token),
449            Err(e) => {
450                // If it's a plain scan error, wrap it with context
451                if let JsonErrorKind::Scan(scan_err) = e.kind {
452                    Err(JsonError {
453                        kind: JsonErrorKind::ScanWithContext {
454                            error: scan_err,
455                            expected_type,
456                        },
457                        span: e.span,
458                        source_code: e.source_code,
459                    })
460                } else {
461                    Err(e)
462                }
463            }
464        }
465    }
466
467    /// Expect a specific token, consuming it.
468    #[allow(dead_code)]
469    fn expect(&mut self, _expected: &'static str) -> Result<SpannedAdapterToken<'input>> {
470        let token = self.next()?;
471        // For now, just return the token - caller validates
472        Ok(token)
473    }
474
475    /// Skip a JSON value (for unknown fields).
476    fn skip_value(&mut self) -> Result<Span> {
477        let token = self.next()?;
478        let start_span = token.span;
479
480        match token.token {
481            Token::ObjectStart => {
482                // Skip object
483                let mut depth = 1;
484                while depth > 0 {
485                    let t = self.next()?;
486                    match t.token {
487                        Token::ObjectStart => depth += 1,
488                        Token::ObjectEnd => depth -= 1,
489                        _ => {}
490                    }
491                }
492                Ok(start_span)
493            }
494            Token::ArrayStart => {
495                // Skip array
496                let mut depth = 1;
497                while depth > 0 {
498                    let t = self.next()?;
499                    match t.token {
500                        Token::ArrayStart => depth += 1,
501                        Token::ArrayEnd => depth -= 1,
502                        _ => {}
503                    }
504                }
505                Ok(start_span)
506            }
507            Token::String(_)
508            | Token::F64(_)
509            | Token::I64(_)
510            | Token::U64(_)
511            | Token::U128(_)
512            | Token::I128(_)
513            | Token::True
514            | Token::False
515            | Token::Null => Ok(start_span),
516            _ => Err(JsonError::new(
517                JsonErrorKind::UnexpectedToken {
518                    got: format!("{:?}", token.token),
519                    expected: "value",
520                },
521                token.span,
522            )),
523        }
524    }
525
526    /// Capture a raw JSON value as a string slice.
527    ///
528    /// This skips the value while tracking its full span, then returns
529    /// the raw JSON text.
530    ///
531    /// Note: This requires the adapter to provide input bytes (slice-based parsing).
532    /// For streaming adapters, this will return an error.
533    fn capture_raw_value(&mut self) -> Result<&'input str> {
534        // Check if we have access to input bytes
535        let input = self.adapter.input_bytes().ok_or_else(|| {
536            JsonError::without_span(JsonErrorKind::InvalidValue {
537                message: "RawJson capture is not supported in streaming mode".into(),
538            })
539        })?;
540
541        let token = self.next()?;
542        let start_offset = token.span.offset;
543
544        let end_offset = match token.token {
545            Token::ObjectStart => {
546                // Capture object
547                let mut depth = 1;
548                let mut last_span = token.span;
549                while depth > 0 {
550                    let t = self.next()?;
551                    last_span = t.span;
552                    match t.token {
553                        Token::ObjectStart => depth += 1,
554                        Token::ObjectEnd => depth -= 1,
555                        _ => {}
556                    }
557                }
558                last_span.offset + last_span.len
559            }
560            Token::ArrayStart => {
561                // Capture array
562                let mut depth = 1;
563                let mut last_span = token.span;
564                while depth > 0 {
565                    let t = self.next()?;
566                    last_span = t.span;
567                    match t.token {
568                        Token::ArrayStart => depth += 1,
569                        Token::ArrayEnd => depth -= 1,
570                        _ => {}
571                    }
572                }
573                last_span.offset + last_span.len
574            }
575            Token::String(_)
576            | Token::F64(_)
577            | Token::I64(_)
578            | Token::U64(_)
579            | Token::U128(_)
580            | Token::I128(_)
581            | Token::True
582            | Token::False
583            | Token::Null => token.span.offset + token.span.len,
584            _ => {
585                return Err(JsonError::new(
586                    JsonErrorKind::UnexpectedToken {
587                        got: format!("{:?}", token.token),
588                        expected: "value",
589                    },
590                    token.span,
591                ));
592            }
593        };
594
595        // Extract the raw bytes and convert to str
596        let raw_bytes = &input[start_offset..end_offset];
597        core::str::from_utf8(raw_bytes).map_err(|e| {
598            JsonError::without_span(JsonErrorKind::InvalidValue {
599                message: format!("invalid UTF-8 in raw JSON: {e}"),
600            })
601        })
602    }
603
604    /// Check if a struct has any flattened fields.
605    fn has_flatten_fields(struct_def: &facet_core::StructType) -> bool {
606        struct_def.fields.iter().any(|f| f.is_flattened())
607    }
608
609    /// Main deserialization entry point - deserialize into a Partial.
610    pub fn deserialize_into(
611        &mut self,
612        mut wip: Partial<'input, BORROW>,
613    ) -> Result<Partial<'input, BORROW>> {
614        let shape = wip.shape();
615        log::trace!(
616            "deserialize_into: shape={}, def={:?}",
617            shape.type_identifier,
618            std::mem::discriminant(&shape.def)
619        );
620
621        // Check for Spanned<T> wrapper first
622        if is_spanned_shape(shape) {
623            return self.deserialize_spanned(wip);
624        }
625
626        // Check for RawJson - capture raw bytes without parsing
627        if shape == RawJson::SHAPE {
628            let raw = self.capture_raw_value()?;
629            wip = wip.set(RawJson::new(raw))?;
630            return Ok(wip);
631        }
632
633        // Check for container-level proxy (applies to values inside Vec<T>, Option<T>, etc.)
634        #[cfg(feature = "alloc")]
635        {
636            let (wip_returned, has_proxy) = wip.begin_custom_deserialization_from_shape()?;
637            wip = wip_returned;
638            if has_proxy {
639                log::trace!(
640                    "deserialize_into: using container-level proxy for {}",
641                    shape.type_identifier
642                );
643                wip = self.deserialize_into(wip)?;
644                return wip.end().map_err(Into::into);
645            }
646        }
647
648        // Check Def first for Option (which is also a Type::User::Enum)
649        // Must come before the inner check since Option also has .inner() set
650        let is_option = matches!(&shape.def, Def::Option(_));
651        log::trace!("deserialize_into: is_option={is_option}");
652        if is_option {
653            return self.deserialize_option(wip);
654        }
655
656        // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
657        // These types need to build through a different type
658        if shape.builder_shape.is_some() {
659            wip = wip.begin_inner()?;
660            // Check if field has custom deserialization
661            if wip
662                .parent_field()
663                .and_then(|field| field.proxy_convert_in_fn())
664                .is_some()
665            {
666                wip = wip.begin_custom_deserialization()?;
667                wip = self.deserialize_into(wip)?;
668                wip = wip.end()?;
669            } else {
670                wip = self.deserialize_into(wip)?;
671            }
672            wip = wip.end()?;
673            return Ok(wip);
674        }
675
676        // Priority 2: Check for smart pointers (Box, Arc, Rc) before other Defs
677        if matches!(&shape.def, Def::Pointer(_)) {
678            return self.deserialize_pointer(wip);
679        }
680
681        // Priority 3: Check for .inner (transparent wrappers like NonZero)
682        // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
683        if shape.inner.is_some()
684            && !matches!(
685                &shape.def,
686                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
687            )
688        {
689            wip = wip.begin_inner()?;
690            wip = self.deserialize_into(wip)?;
691            wip = wip.end()?;
692            return Ok(wip);
693        }
694
695        // Priority 4: Check the Type - structs and enums are identified by Type, not Def
696        match &shape.ty {
697            Type::User(UserType::Struct(struct_def)) => {
698                // Tuples and tuple structs both deserialize from JSON arrays.
699                if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
700                    return self.deserialize_tuple(wip);
701                }
702                return self.deserialize_struct(wip);
703            }
704            Type::User(UserType::Enum(_)) => return self.deserialize_enum(wip),
705            _ => {}
706        }
707
708        // Priority 5: Check Def for containers and special types
709        match &shape.def {
710            Def::Scalar => self.deserialize_scalar(wip),
711            Def::List(_) => self.deserialize_list(wip),
712            Def::Map(_) => self.deserialize_map(wip),
713            Def::Array(_) => self.deserialize_array(wip),
714            Def::Set(_) => self.deserialize_set(wip),
715            Def::DynamicValue(_) => self.deserialize_dynamic_value(wip),
716            _ => Err(JsonError::without_span(JsonErrorKind::InvalidValue {
717                message: format!("unsupported shape def: {:?}", shape.def),
718            })),
719        }
720    }
721
722    /// Deserialize into a type with span metadata (like `Spanned<T>`).
723    ///
724    /// This handles structs that have:
725    /// - One or more non-metadata fields (the actual values to deserialize)
726    /// - A field with `#[facet(metadata = span)]` to store source location
727    fn deserialize_spanned(
728        &mut self,
729        mut wip: Partial<'input, BORROW>,
730    ) -> Result<Partial<'input, BORROW>> {
731        log::trace!("deserialize_spanned");
732
733        let shape = wip.shape();
734
735        // Find the span metadata field and non-metadata fields
736        let Type::User(UserType::Struct(struct_def)) = &shape.ty else {
737            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
738                message: format!(
739                    "expected struct with span metadata, found {}",
740                    shape.type_identifier
741                ),
742            }));
743        };
744
745        let span_field = struct_def
746            .fields
747            .iter()
748            .find(|f| f.metadata_kind() == Some("span"))
749            .ok_or_else(|| {
750                JsonError::without_span(JsonErrorKind::InvalidValue {
751                    message: format!(
752                        "expected struct with span metadata field, found {}",
753                        shape.type_identifier
754                    ),
755                })
756            })?;
757
758        let value_fields: Vec<_> = struct_def
759            .fields
760            .iter()
761            .filter(|f| !f.is_metadata())
762            .collect();
763
764        // Peek to get the span of the value we're about to parse
765        let value_span = self.peek()?.span;
766
767        // Deserialize all non-metadata fields
768        // For the common case (Spanned<T> with a single "value" field), this is just one field
769        for field in value_fields {
770            wip = wip.begin_field(field.name)?;
771            wip = self.deserialize_into(wip)?;
772            wip = wip.end()?;
773        }
774
775        // Set the span metadata field
776        // The span field should be of type Span with offset and len
777        wip = wip.begin_field(span_field.name)?;
778        wip = wip.set_field("offset", value_span.offset)?;
779        wip = wip.set_field("len", value_span.len)?;
780        wip = wip.end()?;
781
782        Ok(wip)
783    }
784
785    /// Deserialize a scalar value.
786    fn deserialize_scalar(
787        &mut self,
788        mut wip: Partial<'input, BORROW>,
789    ) -> Result<Partial<'input, BORROW>> {
790        let expected_type = wip.shape().type_identifier;
791        let token = self.next_expecting(expected_type)?;
792        log::trace!("deserialize_scalar: token={:?}", token.token);
793
794        match token.token {
795            Token::String(s) => {
796                // Try parse_from_str first if the type supports it (e.g., chrono types)
797                if wip.shape().vtable.has_parse() {
798                    wip = wip.parse_from_str(&s)?;
799                } else if wip.shape().type_identifier == "Cow" {
800                    // Zero-copy Cow<str>: preserve borrowed/owned status
801                    wip = wip.set(s)?;
802                } else {
803                    wip = wip.set(s.into_owned())?;
804                }
805            }
806            Token::True => {
807                wip = wip.set(true)?;
808            }
809            Token::False => {
810                wip = wip.set(false)?;
811            }
812            Token::Null => {
813                // For scalars, null typically means default
814                wip = wip.set_default()?;
815            }
816            Token::F64(n) => {
817                wip = self.set_number_f64(wip, n, token.span)?;
818            }
819            Token::I64(n) => {
820                wip = self.set_number_i64(wip, n, token.span)?;
821            }
822            Token::U64(n) => {
823                wip = self.set_number_u64(wip, n, token.span)?;
824            }
825            Token::I128(n) => {
826                wip = self.set_number_i128(wip, n, token.span)?;
827            }
828            Token::U128(n) => {
829                wip = self.set_number_u128(wip, n, token.span)?;
830            }
831            _ => {
832                return Err(JsonError::new(
833                    JsonErrorKind::UnexpectedToken {
834                        got: format!("{:?}", token.token),
835                        expected: "scalar value",
836                    },
837                    token.span,
838                ));
839            }
840        }
841        Ok(wip)
842    }
843
844    /// Deserialize any JSON value into a DynamicValue type.
845    ///
846    /// This handles all JSON value types: null, bool, number, string, array, and object.
847    fn deserialize_dynamic_value(
848        &mut self,
849        mut wip: Partial<'input, BORROW>,
850    ) -> Result<Partial<'input, BORROW>> {
851        let token = self.peek()?;
852        log::trace!("deserialize_dynamic_value: token={:?}", token.token);
853
854        match token.token {
855            Token::Null => {
856                self.next()?; // consume the token
857                wip = wip.set_default()?;
858            }
859            Token::True => {
860                self.next()?;
861                wip = wip.set(true)?;
862            }
863            Token::False => {
864                self.next()?;
865                wip = wip.set(false)?;
866            }
867            Token::I64(n) => {
868                self.next()?;
869                wip = wip.set(n)?;
870            }
871            Token::U64(n) => {
872                self.next()?;
873                // Store as i64 if it fits, otherwise as u64
874                if n <= i64::MAX as u64 {
875                    wip = wip.set(n as i64)?;
876                } else {
877                    wip = wip.set(n)?;
878                }
879            }
880            Token::F64(n) => {
881                self.next()?;
882                wip = wip.set(n)?;
883            }
884            Token::I128(n) => {
885                self.next()?;
886                // Try to fit in i64
887                if let Ok(n) = i64::try_from(n) {
888                    wip = wip.set(n)?;
889                } else {
890                    return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
891                        message: format!("i128 value {n} doesn't fit in dynamic value"),
892                    }));
893                }
894            }
895            Token::U128(n) => {
896                self.next()?;
897                // Try to fit in i64 or u64
898                if let Ok(n) = i64::try_from(n) {
899                    wip = wip.set(n)?;
900                } else if let Ok(n) = u64::try_from(n) {
901                    wip = wip.set(n)?;
902                } else {
903                    return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
904                        message: format!("u128 value {n} doesn't fit in dynamic value"),
905                    }));
906                }
907            }
908            Token::String(ref _s) => {
909                // Consume token and get owned string
910                let token = self.next()?;
911                if let Token::String(s) = token.token {
912                    wip = wip.set(s.into_owned())?;
913                }
914            }
915            Token::ArrayStart => {
916                self.next()?; // consume '['
917                wip = wip.begin_list()?;
918
919                loop {
920                    let token = self.peek()?;
921                    if matches!(token.token, Token::ArrayEnd) {
922                        self.next()?;
923                        break;
924                    }
925
926                    wip = wip.begin_list_item()?;
927                    wip = self.deserialize_dynamic_value(wip)?;
928                    wip = wip.end()?;
929
930                    let next = self.peek()?;
931                    if matches!(next.token, Token::Comma) {
932                        self.next()?;
933                    }
934                }
935            }
936            Token::ObjectStart => {
937                self.next()?; // consume '{'
938                wip = wip.begin_map()?; // Initialize as object
939
940                loop {
941                    let token = self.peek()?;
942                    if matches!(token.token, Token::ObjectEnd) {
943                        self.next()?;
944                        break;
945                    }
946
947                    // Parse key (must be a string)
948                    let key_token = self.next()?;
949                    let key = match key_token.token {
950                        Token::String(s) => s.into_owned(),
951                        _ => {
952                            return Err(JsonError::new(
953                                JsonErrorKind::UnexpectedToken {
954                                    got: format!("{:?}", key_token.token),
955                                    expected: "string key",
956                                },
957                                key_token.span,
958                            ));
959                        }
960                    };
961
962                    // Expect colon
963                    let colon = self.next()?;
964                    if !matches!(colon.token, Token::Colon) {
965                        return Err(JsonError::new(
966                            JsonErrorKind::UnexpectedToken {
967                                got: format!("{:?}", colon.token),
968                                expected: "':'",
969                            },
970                            colon.span,
971                        ));
972                    }
973
974                    // Start object entry and deserialize value
975                    wip = wip.begin_object_entry(&key)?;
976                    wip = self.deserialize_dynamic_value(wip)?;
977                    wip = wip.end()?;
978
979                    // Check for comma or end
980                    let next = self.peek()?;
981                    if matches!(next.token, Token::Comma) {
982                        self.next()?;
983                    }
984                }
985            }
986            _ => {
987                return Err(JsonError::new(
988                    JsonErrorKind::UnexpectedToken {
989                        got: format!("{:?}", token.token),
990                        expected: "any JSON value",
991                    },
992                    token.span,
993                ));
994            }
995        }
996        Ok(wip)
997    }
998
999    /// Set a string value, handling `&str`, `Cow<str>`, and `String` appropriately.
1000    fn set_string_value(
1001        &mut self,
1002        mut wip: Partial<'input, BORROW>,
1003        s: Cow<'input, str>,
1004    ) -> Result<Partial<'input, BORROW>> {
1005        let shape = wip.shape();
1006
1007        // Check if target is &str (shared reference to str)
1008        if let Def::Pointer(ptr_def) = shape.def
1009            && matches!(ptr_def.known, Some(KnownPointer::SharedReference))
1010            && ptr_def
1011                .pointee()
1012                .is_some_and(|p| p.type_identifier == "str")
1013        {
1014            // In owned mode, we cannot borrow from input at all
1015            if !BORROW {
1016                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
1017                    message: "cannot deserialize into &str when borrowing is disabled - use String or Cow<str> instead".into(),
1018                }));
1019            }
1020            match s {
1021                Cow::Borrowed(borrowed) => {
1022                    wip = wip.set(borrowed)?;
1023                    return Ok(wip);
1024                }
1025                Cow::Owned(_) => {
1026                    return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
1027                        message: "cannot borrow &str from JSON string containing escape sequences - use String instead".into(),
1028                    }));
1029                }
1030            }
1031        }
1032
1033        // Check if target is Cow<str>
1034        if let Def::Pointer(ptr_def) = shape.def
1035            && matches!(ptr_def.known, Some(KnownPointer::Cow))
1036            && ptr_def
1037                .pointee()
1038                .is_some_and(|p| p.type_identifier == "str")
1039        {
1040            wip = wip.set(s)?;
1041            return Ok(wip);
1042        }
1043
1044        // Default: convert to owned String
1045        wip = wip.set(s.into_owned())?;
1046        Ok(wip)
1047    }
1048
1049    /// Set a numeric value, handling type conversions.
1050    fn set_number_f64(
1051        &mut self,
1052        mut wip: Partial<'input, BORROW>,
1053        n: f64,
1054        span: Span,
1055    ) -> Result<Partial<'input, BORROW>> {
1056        let shape = wip.shape();
1057        let ty = match &shape.ty {
1058            Type::Primitive(PrimitiveType::Numeric(ty)) => ty,
1059            _ => {
1060                return Err(JsonError::new(
1061                    JsonErrorKind::TypeMismatch {
1062                        expected: shape.type_identifier,
1063                        got: "number",
1064                    },
1065                    span,
1066                ));
1067            }
1068        };
1069
1070        match ty {
1071            NumericType::Float => {
1072                let size = match shape.layout {
1073                    ShapeLayout::Sized(layout) => layout.size(),
1074                    _ => {
1075                        return Err(JsonError::new(
1076                            JsonErrorKind::InvalidValue {
1077                                message: "unsized float".into(),
1078                            },
1079                            span,
1080                        ));
1081                    }
1082                };
1083                match size {
1084                    4 => {
1085                        wip = wip.set(n as f32)?;
1086                    }
1087                    8 => {
1088                        wip = wip.set(n)?;
1089                    }
1090                    _ => {
1091                        return Err(JsonError::new(
1092                            JsonErrorKind::InvalidValue {
1093                                message: format!("unexpected float size: {size}"),
1094                            },
1095                            span,
1096                        ));
1097                    }
1098                }
1099            }
1100            NumericType::Integer { signed } => {
1101                // Try to convert float to integer
1102                if n.fract() != 0.0 {
1103                    return Err(JsonError::new(
1104                        JsonErrorKind::TypeMismatch {
1105                            expected: shape.type_identifier,
1106                            got: "float with fractional part",
1107                        },
1108                        span,
1109                    ));
1110                }
1111                if *signed {
1112                    wip = self.set_number_i64(wip, n as i64, span)?;
1113                } else {
1114                    wip = self.set_number_u64(wip, n as u64, span)?;
1115                }
1116            }
1117        }
1118        Ok(wip)
1119    }
1120
1121    fn set_number_i64(
1122        &mut self,
1123        mut wip: Partial<'input, BORROW>,
1124        n: i64,
1125        span: Span,
1126    ) -> Result<Partial<'input, BORROW>> {
1127        let shape = wip.shape();
1128        let size = match shape.layout {
1129            ShapeLayout::Sized(layout) => layout.size(),
1130            _ => {
1131                return Err(JsonError::new(
1132                    JsonErrorKind::InvalidValue {
1133                        message: "unsized integer".into(),
1134                    },
1135                    span,
1136                ));
1137            }
1138        };
1139
1140        // Check type and convert
1141        match &shape.ty {
1142            Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: true })) => {
1143                match size {
1144                    1 => {
1145                        let v = i8::try_from(n).map_err(|_| {
1146                            JsonError::new(
1147                                JsonErrorKind::NumberOutOfRange {
1148                                    value: n.to_string(),
1149                                    target_type: "i8",
1150                                },
1151                                span,
1152                            )
1153                        })?;
1154                        wip = wip.set(v)?;
1155                    }
1156                    2 => {
1157                        let v = i16::try_from(n).map_err(|_| {
1158                            JsonError::new(
1159                                JsonErrorKind::NumberOutOfRange {
1160                                    value: n.to_string(),
1161                                    target_type: "i16",
1162                                },
1163                                span,
1164                            )
1165                        })?;
1166                        wip = wip.set(v)?;
1167                    }
1168                    4 => {
1169                        let v = i32::try_from(n).map_err(|_| {
1170                            JsonError::new(
1171                                JsonErrorKind::NumberOutOfRange {
1172                                    value: n.to_string(),
1173                                    target_type: "i32",
1174                                },
1175                                span,
1176                            )
1177                        })?;
1178                        wip = wip.set(v)?;
1179                    }
1180                    8 => {
1181                        // Check if the target is isize (which has size 8 on 64-bit)
1182                        if shape.scalar_type() == Some(ScalarType::ISize) {
1183                            let v = isize::try_from(n).map_err(|_| {
1184                                JsonError::new(
1185                                    JsonErrorKind::NumberOutOfRange {
1186                                        value: n.to_string(),
1187                                        target_type: "isize",
1188                                    },
1189                                    span,
1190                                )
1191                            })?;
1192                            wip = wip.set(v)?;
1193                        } else {
1194                            wip = wip.set(n)?;
1195                        }
1196                    }
1197                    16 => {
1198                        wip = wip.set(n as i128)?;
1199                    }
1200                    _ => {
1201                        // Handle isize on 32-bit platforms (size 4)
1202                        if shape.scalar_type() == Some(ScalarType::ISize) {
1203                            let v = isize::try_from(n).map_err(|_| {
1204                                JsonError::new(
1205                                    JsonErrorKind::NumberOutOfRange {
1206                                        value: n.to_string(),
1207                                        target_type: "isize",
1208                                    },
1209                                    span,
1210                                )
1211                            })?;
1212                            wip = wip.set(v)?;
1213                        } else {
1214                            return Err(JsonError::new(
1215                                JsonErrorKind::InvalidValue {
1216                                    message: format!("unexpected integer size: {size}"),
1217                                },
1218                                span,
1219                            ));
1220                        }
1221                    }
1222                }
1223            }
1224            Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: false })) => {
1225                if n < 0 {
1226                    return Err(JsonError::new(
1227                        JsonErrorKind::NumberOutOfRange {
1228                            value: n.to_string(),
1229                            target_type: shape.type_identifier,
1230                        },
1231                        span,
1232                    ));
1233                }
1234                wip = self.set_number_u64(wip, n as u64, span)?;
1235            }
1236            Type::Primitive(PrimitiveType::Numeric(NumericType::Float)) => match size {
1237                4 => {
1238                    wip = wip.set(n as f32)?;
1239                }
1240                8 => {
1241                    wip = wip.set(n as f64)?;
1242                }
1243                _ => {
1244                    return Err(JsonError::new(
1245                        JsonErrorKind::InvalidValue {
1246                            message: format!("unexpected float size: {size}"),
1247                        },
1248                        span,
1249                    ));
1250                }
1251            },
1252            _ => {
1253                return Err(JsonError::new(
1254                    JsonErrorKind::TypeMismatch {
1255                        expected: shape.type_identifier,
1256                        got: "integer",
1257                    },
1258                    span,
1259                ));
1260            }
1261        }
1262        Ok(wip)
1263    }
1264
1265    fn set_number_u64(
1266        &mut self,
1267        mut wip: Partial<'input, BORROW>,
1268        n: u64,
1269        span: Span,
1270    ) -> Result<Partial<'input, BORROW>> {
1271        let shape = wip.shape();
1272        let size = match shape.layout {
1273            ShapeLayout::Sized(layout) => layout.size(),
1274            _ => {
1275                return Err(JsonError::new(
1276                    JsonErrorKind::InvalidValue {
1277                        message: "unsized integer".into(),
1278                    },
1279                    span,
1280                ));
1281            }
1282        };
1283
1284        match &shape.ty {
1285            Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: false })) => {
1286                match size {
1287                    1 => {
1288                        let v = u8::try_from(n).map_err(|_| {
1289                            JsonError::new(
1290                                JsonErrorKind::NumberOutOfRange {
1291                                    value: n.to_string(),
1292                                    target_type: "u8",
1293                                },
1294                                span,
1295                            )
1296                        })?;
1297                        wip = wip.set(v)?;
1298                    }
1299                    2 => {
1300                        let v = u16::try_from(n).map_err(|_| {
1301                            JsonError::new(
1302                                JsonErrorKind::NumberOutOfRange {
1303                                    value: n.to_string(),
1304                                    target_type: "u16",
1305                                },
1306                                span,
1307                            )
1308                        })?;
1309                        wip = wip.set(v)?;
1310                    }
1311                    4 => {
1312                        let v = u32::try_from(n).map_err(|_| {
1313                            JsonError::new(
1314                                JsonErrorKind::NumberOutOfRange {
1315                                    value: n.to_string(),
1316                                    target_type: "u32",
1317                                },
1318                                span,
1319                            )
1320                        })?;
1321                        wip = wip.set(v)?;
1322                    }
1323                    8 => {
1324                        // Check if the target is usize (which has size 8 on 64-bit)
1325                        if shape.scalar_type() == Some(ScalarType::USize) {
1326                            let v = usize::try_from(n).map_err(|_| {
1327                                JsonError::new(
1328                                    JsonErrorKind::NumberOutOfRange {
1329                                        value: n.to_string(),
1330                                        target_type: "usize",
1331                                    },
1332                                    span,
1333                                )
1334                            })?;
1335                            wip = wip.set(v)?;
1336                        } else {
1337                            wip = wip.set(n)?;
1338                        }
1339                    }
1340                    16 => {
1341                        wip = wip.set(n as u128)?;
1342                    }
1343                    _ => {
1344                        // Handle usize on 32-bit platforms (size 4)
1345                        if shape.scalar_type() == Some(ScalarType::USize) {
1346                            let v = usize::try_from(n).map_err(|_| {
1347                                JsonError::new(
1348                                    JsonErrorKind::NumberOutOfRange {
1349                                        value: n.to_string(),
1350                                        target_type: "usize",
1351                                    },
1352                                    span,
1353                                )
1354                            })?;
1355                            wip = wip.set(v)?;
1356                        } else {
1357                            return Err(JsonError::new(
1358                                JsonErrorKind::InvalidValue {
1359                                    message: format!("unexpected integer size: {size}"),
1360                                },
1361                                span,
1362                            ));
1363                        }
1364                    }
1365                }
1366            }
1367            Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: true })) => {
1368                // Convert unsigned to signed if it fits
1369                wip = self.set_number_i64(wip, n as i64, span)?;
1370            }
1371            Type::Primitive(PrimitiveType::Numeric(NumericType::Float)) => match size {
1372                4 => {
1373                    wip = wip.set(n as f32)?;
1374                }
1375                8 => {
1376                    wip = wip.set(n as f64)?;
1377                }
1378                _ => {
1379                    return Err(JsonError::new(
1380                        JsonErrorKind::InvalidValue {
1381                            message: format!("unexpected float size: {size}"),
1382                        },
1383                        span,
1384                    ));
1385                }
1386            },
1387            _ => {
1388                return Err(JsonError::new(
1389                    JsonErrorKind::TypeMismatch {
1390                        expected: shape.type_identifier,
1391                        got: "unsigned integer",
1392                    },
1393                    span,
1394                ));
1395            }
1396        }
1397        Ok(wip)
1398    }
1399
1400    fn set_number_i128(
1401        &mut self,
1402        mut wip: Partial<'input, BORROW>,
1403        n: i128,
1404        span: Span,
1405    ) -> Result<Partial<'input, BORROW>> {
1406        let shape = wip.shape();
1407        let size = match shape.layout {
1408            ShapeLayout::Sized(layout) => layout.size(),
1409            _ => {
1410                return Err(JsonError::new(
1411                    JsonErrorKind::InvalidValue {
1412                        message: "unsized integer".into(),
1413                    },
1414                    span,
1415                ));
1416            }
1417        };
1418
1419        if size == 16 {
1420            wip = wip.set(n)?;
1421        } else {
1422            // Try to fit in smaller type
1423            if let Ok(n64) = i64::try_from(n) {
1424                wip = self.set_number_i64(wip, n64, span)?;
1425            } else {
1426                return Err(JsonError::new(
1427                    JsonErrorKind::NumberOutOfRange {
1428                        value: n.to_string(),
1429                        target_type: shape.type_identifier,
1430                    },
1431                    span,
1432                ));
1433            }
1434        }
1435        Ok(wip)
1436    }
1437
1438    fn set_number_u128(
1439        &mut self,
1440        mut wip: Partial<'input, BORROW>,
1441        n: u128,
1442        span: Span,
1443    ) -> Result<Partial<'input, BORROW>> {
1444        let shape = wip.shape();
1445        let size = match shape.layout {
1446            ShapeLayout::Sized(layout) => layout.size(),
1447            _ => {
1448                return Err(JsonError::new(
1449                    JsonErrorKind::InvalidValue {
1450                        message: "unsized integer".into(),
1451                    },
1452                    span,
1453                ));
1454            }
1455        };
1456
1457        if size == 16 {
1458            wip = wip.set(n)?;
1459        } else {
1460            // Try to fit in smaller type
1461            if let Ok(n64) = u64::try_from(n) {
1462                wip = self.set_number_u64(wip, n64, span)?;
1463            } else {
1464                return Err(JsonError::new(
1465                    JsonErrorKind::NumberOutOfRange {
1466                        value: n.to_string(),
1467                        target_type: shape.type_identifier,
1468                    },
1469                    span,
1470                ));
1471            }
1472        }
1473        Ok(wip)
1474    }
1475
1476    /// Deserialize a struct from a JSON object.
1477    fn deserialize_struct(
1478        &mut self,
1479        wip: Partial<'input, BORROW>,
1480    ) -> Result<Partial<'input, BORROW>> {
1481        log::trace!("deserialize_struct: {}", wip.shape().type_identifier);
1482
1483        // Get struct fields to check for flatten
1484        let struct_def = match &wip.shape().ty {
1485            Type::User(UserType::Struct(s)) => s,
1486            _ => {
1487                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
1488                    message: "expected struct type".into(),
1489                }));
1490            }
1491        };
1492
1493        // Check if this struct has any flattened fields - if so, use the solver
1494        if Self::has_flatten_fields(struct_def) {
1495            return self.deserialize_struct_with_flatten(wip);
1496        }
1497
1498        // Simple path: no flattened fields
1499        self.deserialize_struct_simple(wip)
1500    }
1501
1502    /// Deserialize a struct without flattened fields (simple case).
1503    fn deserialize_struct_simple(
1504        &mut self,
1505        mut wip: Partial<'input, BORROW>,
1506    ) -> Result<Partial<'input, BORROW>> {
1507        // Expect opening brace and track its span
1508        let open_token = self.next()?;
1509        let object_start_span = match open_token.token {
1510            Token::ObjectStart => open_token.span,
1511            _ => {
1512                return Err(JsonError::new(
1513                    JsonErrorKind::UnexpectedToken {
1514                        got: format!("{:?}", open_token.token),
1515                        expected: "'{'",
1516                    },
1517                    open_token.span,
1518                ));
1519            }
1520        };
1521
1522        // Get struct fields
1523        let struct_def = match &wip.shape().ty {
1524            Type::User(UserType::Struct(s)) => s,
1525            _ => {
1526                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
1527                    message: "expected struct type".into(),
1528                }));
1529            }
1530        };
1531
1532        // Track which fields have been set
1533        let num_fields = struct_def.fields.len();
1534        let mut fields_set = alloc::vec![false; num_fields];
1535
1536        // Track the end of the object for error reporting
1537        #[allow(unused_assignments)]
1538        let mut object_end_span: Option<Span> = None;
1539
1540        // Check if the struct has a default attribute (all missing fields use defaults)
1541        let struct_has_default = wip.shape().has_default_attr();
1542        // Check if the struct denies unknown fields
1543        let deny_unknown_fields = wip.shape().has_deny_unknown_fields_attr();
1544
1545        // Parse fields until closing brace
1546        loop {
1547            let token = self.peek()?;
1548            match &token.token {
1549                Token::ObjectEnd => {
1550                    let close_token = self.next()?; // consume the brace
1551                    object_end_span = Some(close_token.span);
1552                    break;
1553                }
1554                Token::String(_) => {
1555                    // Parse field name
1556                    let key_token = self.next()?;
1557                    let key = match key_token.token {
1558                        Token::String(s) => s,
1559                        _ => unreachable!(),
1560                    };
1561                    let _key_span = key_token.span;
1562
1563                    // Expect colon
1564                    let colon = self.next()?;
1565                    if !matches!(colon.token, Token::Colon) {
1566                        return Err(JsonError::new(
1567                            JsonErrorKind::UnexpectedToken {
1568                                got: format!("{:?}", colon.token),
1569                                expected: "':'",
1570                            },
1571                            colon.span,
1572                        ));
1573                    }
1574
1575                    // Find the field by name and index
1576                    let field_info = struct_def
1577                        .fields
1578                        .iter()
1579                        .enumerate()
1580                        .find(|(_, f)| f.name == key.as_ref());
1581
1582                    if let Some((idx, field)) = field_info {
1583                        wip = wip.begin_field(field.name)?;
1584                        // Check if field has custom deserialization
1585                        if field.proxy_convert_in_fn().is_some() {
1586                            wip = wip.begin_custom_deserialization()?;
1587                            wip = self.deserialize_into(wip)?;
1588                            wip = wip.end()?; // Calls deserialize_with function
1589                        } else {
1590                            wip = self.deserialize_into(wip)?;
1591                        }
1592                        wip = wip.end()?;
1593                        fields_set[idx] = true;
1594                    } else {
1595                        // Unknown field
1596                        if deny_unknown_fields {
1597                            let expected_fields: Vec<&'static str> =
1598                                struct_def.fields.iter().map(|f| f.name).collect();
1599                            let suggestion = find_similar_field(&key, &expected_fields);
1600                            return Err(JsonError::new(
1601                                JsonErrorKind::UnknownField {
1602                                    field: key.into_owned(),
1603                                    expected: expected_fields,
1604                                    suggestion,
1605                                },
1606                                _key_span,
1607                            ));
1608                        }
1609                        log::trace!("skipping unknown field: {key}");
1610                        self.skip_value()?;
1611                    }
1612
1613                    // Check for comma or end
1614                    let next = self.peek()?;
1615                    if matches!(next.token, Token::Comma) {
1616                        self.next()?; // consume comma
1617                    }
1618                }
1619                _ => {
1620                    let span = token.span;
1621                    return Err(JsonError::new(
1622                        JsonErrorKind::UnexpectedToken {
1623                            got: format!("{:?}", token.token),
1624                            expected: "field name or '}'",
1625                        },
1626                        span,
1627                    ));
1628                }
1629            }
1630        }
1631
1632        // Apply defaults for missing fields and detect required but missing fields
1633        for (idx, field) in struct_def.fields.iter().enumerate() {
1634            if fields_set[idx] {
1635                continue; // Field was already set from JSON
1636            }
1637
1638            // Check if the field has a default available:
1639            // 1. Field has #[facet(default)] or #[facet(default = expr)]
1640            // 2. Struct has #[facet(default)] and field type implements Default
1641            let field_has_default = field.has_default();
1642            let field_type_has_default = field.shape().is(Characteristic::Default);
1643            let field_is_option = matches!(field.shape().def, Def::Option(_));
1644
1645            if field_has_default {
1646                // Use set_nth_field_to_default which handles both default_fn and Default impl
1647                wip = wip.set_nth_field_to_default(idx)?;
1648            } else if struct_has_default && field_type_has_default {
1649                // Struct-level #[facet(default)] - use the field type's Default
1650                wip = wip.set_nth_field_to_default(idx)?;
1651            } else if field_is_option {
1652                // Option<T> fields should default to None even without struct-level defaults
1653                wip = wip.begin_field(field.name)?;
1654                wip = wip.set_default()?;
1655                wip = wip.end()?;
1656            } else {
1657                // Required field is missing - raise our own error with spans
1658                return Err(JsonError {
1659                    kind: JsonErrorKind::MissingField {
1660                        field: field.name,
1661                        object_start: Some(object_start_span),
1662                        object_end: object_end_span,
1663                    },
1664                    span: None, // We use custom labels instead
1665                    source_code: None,
1666                });
1667            }
1668        }
1669
1670        Ok(wip)
1671    }
1672
1673    /// Deserialize a struct with flattened fields using facet-solver.
1674    ///
1675    /// This uses a two-pass approach:
1676    /// 1. Peek mode: Scan all keys, feed to solver, record value positions
1677    /// 2. Deserialize: Use the resolved Configuration to deserialize with proper path handling
1678    fn deserialize_struct_with_flatten(
1679        &mut self,
1680        mut wip: Partial<'input, BORROW>,
1681    ) -> Result<Partial<'input, BORROW>> {
1682        log::trace!(
1683            "deserialize_struct_with_flatten: {wip}",
1684            wip = wip.shape().type_identifier
1685        );
1686
1687        // Build the schema for this type with auto-detection of enum representations
1688        // This respects #[facet(tag = "...", content = "...")] and #[facet(untagged)] attributes
1689        let schema = Schema::build_auto(wip.shape()).map_err(|e| {
1690            JsonError::without_span(JsonErrorKind::Solver(format!(
1691                "failed to build schema: {e}"
1692            )))
1693        })?;
1694
1695        // Create the solver
1696        let mut solver = Solver::new(&schema);
1697
1698        // Track where values start so we can re-read them in pass 2
1699        let mut field_positions: Vec<(Cow<'input, str>, usize)> = Vec::new();
1700
1701        // Expect opening brace
1702        let token = self.next()?;
1703        match token.token {
1704            Token::ObjectStart => {}
1705            _ => {
1706                return Err(JsonError::new(
1707                    JsonErrorKind::UnexpectedToken {
1708                        got: format!("{:?}", token.token),
1709                        expected: "'{'",
1710                    },
1711                    token.span,
1712                ));
1713            }
1714        }
1715
1716        // ========== PASS 1: Peek mode - scan all keys, feed to solver ==========
1717        loop {
1718            let token = self.peek()?;
1719            match &token.token {
1720                Token::ObjectEnd => {
1721                    self.next()?; // consume the brace
1722                    break;
1723                }
1724                Token::String(_) => {
1725                    // Parse field name
1726                    let key_token = self.next()?;
1727                    let key = match &key_token.token {
1728                        Token::String(s) => s.clone(),
1729                        _ => unreachable!(),
1730                    };
1731
1732                    // Expect colon
1733                    let colon = self.next()?;
1734                    if !matches!(colon.token, Token::Colon) {
1735                        return Err(JsonError::new(
1736                            JsonErrorKind::UnexpectedToken {
1737                                got: format!("{:?}", colon.token),
1738                                expected: "':'",
1739                            },
1740                            colon.span,
1741                        ));
1742                    }
1743
1744                    // Record the value position before skipping
1745                    let value_start = self.peek()?.span.offset;
1746
1747                    // Feed key to solver (decision not used in peek mode)
1748                    let _decision = solver.see_key(key.clone());
1749
1750                    field_positions.push((key, value_start));
1751
1752                    // Skip the value
1753                    self.skip_value()?;
1754
1755                    // Check for comma
1756                    let next = self.peek()?;
1757                    if matches!(next.token, Token::Comma) {
1758                        self.next()?;
1759                    }
1760                }
1761                _ => {
1762                    let span = token.span;
1763                    return Err(JsonError::new(
1764                        JsonErrorKind::UnexpectedToken {
1765                            got: format!("{:?}", token.token),
1766                            expected: "field name or '}'",
1767                        },
1768                        span,
1769                    ));
1770                }
1771            }
1772        }
1773
1774        // ========== Get the resolved Configuration ==========
1775        // Get seen keys before finish() consumes the solver
1776        let seen_keys = solver.seen_keys().clone();
1777        let config_handle = solver
1778            .finish()
1779            .map_err(|e| JsonError::without_span(JsonErrorKind::Solver(format!("{e}"))))?;
1780        let config = config_handle.resolution();
1781
1782        // ========== PASS 2: Deserialize with proper path handling ==========
1783        // Sort fields by path depth (deepest first within each prefix group)
1784        // This ensures we set all fields at a given nesting level before closing it
1785        let mut fields_to_process: Vec<_> = field_positions
1786            .iter()
1787            .filter_map(|(key, offset)| config.field(key.as_ref()).map(|info| (info, *offset)))
1788            .collect();
1789
1790        // Sort by path to group nested fields together
1791        // We want to process in an order that allows proper begin/end management
1792        fields_to_process.sort_by(|(a, _), (b, _)| a.path.segments().cmp(b.path.segments()));
1793
1794        // Determine which optional fields are missing before PASS 2
1795        let missing_optional_fields: Vec<&FieldInfo> =
1796            config.missing_optional_fields(&seen_keys).collect();
1797
1798        let mut defaults_by_first_segment: BTreeMap<&str, Vec<&FieldInfo>> = BTreeMap::new();
1799        for info in &missing_optional_fields {
1800            if let Some(PathSegment::Field(name)) = info.path.segments().first() {
1801                defaults_by_first_segment
1802                    .entry(name)
1803                    .or_default()
1804                    .push(*info);
1805            }
1806        }
1807
1808        let processed_first_segments: BTreeSet<&str> = fields_to_process
1809            .iter()
1810            .filter_map(|(info, _)| {
1811                if let Some(PathSegment::Field(name)) = info.path.segments().first() {
1812                    Some(*name)
1813                } else {
1814                    None
1815                }
1816            })
1817            .collect();
1818
1819        let missing_first_segments: BTreeSet<&str> =
1820            defaults_by_first_segment.keys().copied().collect();
1821
1822        for first_field in &missing_first_segments {
1823            if processed_first_segments.contains(first_field) {
1824                continue;
1825            }
1826
1827            wip = wip.begin_field(first_field)?;
1828            if matches!(wip.shape().def, Def::Option(_)) {
1829                wip = wip.set_default()?;
1830                defaults_by_first_segment.remove(first_field);
1831            }
1832            wip = wip.end()?;
1833        }
1834
1835        // Track currently open path segments: (field_name, is_option)
1836        let mut open_segments: Vec<(&str, bool)> = Vec::new();
1837
1838        for (field_info, offset) in &fields_to_process {
1839            let segments = field_info.path.segments();
1840            let offset = *offset;
1841
1842            // Extract just the field names from the path (ignoring Variant segments for now)
1843            let field_segments: Vec<&str> = segments
1844                .iter()
1845                .filter_map(|s| match s {
1846                    PathSegment::Field(name) => Some(*name),
1847                    PathSegment::Variant(_, _) => None,
1848                })
1849                .collect();
1850
1851            // Find common prefix with currently open segments
1852            let common_len = open_segments
1853                .iter()
1854                .zip(field_segments.iter())
1855                .take_while(|((name, _), b)| *name == **b)
1856                .count();
1857
1858            // Close segments that are no longer needed (in reverse order)
1859            while open_segments.len() > common_len {
1860                let (segment_name, is_option) = open_segments.pop().unwrap();
1861                wip = self.apply_defaults_for_segment(
1862                    wip,
1863                    segment_name,
1864                    &mut defaults_by_first_segment,
1865                )?;
1866                if is_option {
1867                    wip = wip.end()?; // End the inner Some value
1868                }
1869                wip = wip.end()?; // End the field
1870            }
1871
1872            // Open new segments
1873            for &segment in &field_segments[common_len..] {
1874                wip = wip.begin_field(segment)?;
1875                // Check if we just entered an Option field - if so, initialize it as Some
1876                let is_option = matches!(wip.shape().def, Def::Option(_));
1877                if is_option {
1878                    wip = wip.begin_some()?;
1879                }
1880                open_segments.push((segment, is_option));
1881            }
1882
1883            // Handle variant selection if the path ends with a Variant segment
1884            let ends_with_variant = segments
1885                .last()
1886                .is_some_and(|s| matches!(s, PathSegment::Variant(_, _)));
1887
1888            if ends_with_variant
1889                && let Some(PathSegment::Variant(_, variant_name)) = segments.last()
1890            {
1891                wip = wip.select_variant_named(variant_name)?;
1892            }
1893
1894            // Create sub-deserializer and deserialize the value
1895            // Note: This requires the adapter to support at_offset (slice-based parsing).
1896            // For streaming adapters, flatten is not supported.
1897            let sub_adapter = self.adapter.at_offset(offset).ok_or_else(|| {
1898                JsonError::without_span(JsonErrorKind::InvalidValue {
1899                    message: "flatten is not supported in streaming mode".into(),
1900                })
1901            })?;
1902            let mut sub = Self::from_adapter(sub_adapter);
1903
1904            if ends_with_variant {
1905                wip = sub.deserialize_variant_struct_content(wip)?;
1906            } else {
1907                // Pop the last segment since we're about to deserialize into it
1908                // The deserialize_into will set the value directly
1909                if !open_segments.is_empty() {
1910                    let (segment_name, is_option) = open_segments.pop().unwrap();
1911                    wip = self.apply_defaults_for_segment(
1912                        wip,
1913                        segment_name,
1914                        &mut defaults_by_first_segment,
1915                    )?;
1916                    wip = sub.deserialize_into(wip)?;
1917                    wip = wip.end()?;
1918                    if is_option {
1919                        wip = wip.end()?; // End the Option field itself
1920                    }
1921                } else {
1922                    wip = sub.deserialize_into(wip)?;
1923                }
1924            }
1925        }
1926
1927        // Close any remaining open segments
1928        while let Some((segment_name, is_option)) = open_segments.pop() {
1929            wip =
1930                self.apply_defaults_for_segment(wip, segment_name, &mut defaults_by_first_segment)?;
1931            if is_option {
1932                wip = wip.end()?; // End the inner Some value
1933            }
1934            wip = wip.end()?; // End the field
1935        }
1936        for infos in defaults_by_first_segment.into_values() {
1937            for info in infos {
1938                wip = self.set_missing_field_default(wip, info, false)?;
1939            }
1940        }
1941
1942        Ok(wip)
1943    }
1944
1945    /// Deserialize an enum.
1946    ///
1947    /// Supports externally tagged representation: `{"VariantName": data}` or `"UnitVariant"`
1948    fn deserialize_enum(
1949        &mut self,
1950        mut wip: Partial<'input, BORROW>,
1951    ) -> Result<Partial<'input, BORROW>> {
1952        log::trace!("deserialize_enum: {}", wip.shape().type_identifier);
1953
1954        // Check if this is an untagged enum
1955        if wip.shape().is_untagged() {
1956            return self.deserialize_untagged_enum(wip);
1957        }
1958
1959        let token = self.peek()?;
1960
1961        match &token.token {
1962            // String = unit variant (externally tagged unit)
1963            Token::String(s) => {
1964                let variant_name = s.clone();
1965                self.next()?; // consume
1966
1967                wip = wip.select_variant_named(&variant_name)?;
1968                // Unit variants don't need further deserialization
1969                Ok(wip)
1970            }
1971            // Object = externally tagged variant with data
1972            Token::ObjectStart => {
1973                self.next()?; // consume brace
1974
1975                // Get the variant name (first key)
1976                let key_token = self.next()?;
1977                let key = match &key_token.token {
1978                    Token::String(s) => s.clone(),
1979                    Token::ObjectEnd => {
1980                        // Empty object - error
1981                        return Err(JsonError::new(
1982                            JsonErrorKind::InvalidValue {
1983                                message: "empty object cannot represent enum variant".into(),
1984                            },
1985                            key_token.span,
1986                        ));
1987                    }
1988                    _ => {
1989                        return Err(JsonError::new(
1990                            JsonErrorKind::UnexpectedToken {
1991                                got: format!("{:?}", key_token.token),
1992                                expected: "variant name",
1993                            },
1994                            key_token.span,
1995                        ));
1996                    }
1997                };
1998
1999                // Expect colon
2000                let colon = self.next()?;
2001                if !matches!(colon.token, Token::Colon) {
2002                    return Err(JsonError::new(
2003                        JsonErrorKind::UnexpectedToken {
2004                            got: format!("{:?}", colon.token),
2005                            expected: "':'",
2006                        },
2007                        colon.span,
2008                    ));
2009                }
2010
2011                // Select the variant
2012                wip = wip.select_variant_named(&key)?;
2013
2014                // Get the selected variant info to determine how to deserialize
2015                let variant = wip.selected_variant().ok_or_else(|| {
2016                    JsonError::without_span(JsonErrorKind::InvalidValue {
2017                        message: "failed to get selected variant".into(),
2018                    })
2019                })?;
2020
2021                // Deserialize based on variant kind
2022                match variant.data.kind {
2023                    StructKind::Unit => {
2024                        // Unit variant in object form like {"Unit": null}
2025                        // We should consume some token (null, empty object, etc.)
2026                        let tok = self.next()?;
2027                        if !matches!(tok.token, Token::Null) {
2028                            return Err(JsonError::new(
2029                                JsonErrorKind::UnexpectedToken {
2030                                    got: format!("{:?}", tok.token),
2031                                    expected: "null for unit variant",
2032                                },
2033                                tok.span,
2034                            ));
2035                        }
2036                    }
2037                    StructKind::TupleStruct | StructKind::Tuple => {
2038                        let num_fields = variant.data.fields.len();
2039                        if num_fields == 0 {
2040                            // Zero-field tuple variant, treat like unit
2041                            let tok = self.peek()?;
2042                            if matches!(tok.token, Token::Null) {
2043                                self.next()?;
2044                            }
2045                        } else if num_fields == 1 {
2046                            // Single-element tuple: value directly (e.g., {"X": 123})
2047                            let field = &variant.data.fields[0];
2048                            wip = wip.begin_nth_field(0)?;
2049                            // Check if field has custom deserialization
2050                            if field.proxy_convert_in_fn().is_some() {
2051                                wip = wip.begin_custom_deserialization()?;
2052                                wip = self.deserialize_into(wip)?;
2053                                wip = wip.end()?; // Calls deserialize_with function
2054                            } else {
2055                                wip = self.deserialize_into(wip)?;
2056                            }
2057                            wip = wip.end()?;
2058                        } else {
2059                            // Multi-element tuple: array (e.g., {"Y": ["hello", true]})
2060                            let tok = self.next()?;
2061                            if !matches!(tok.token, Token::ArrayStart) {
2062                                return Err(JsonError::new(
2063                                    JsonErrorKind::UnexpectedToken {
2064                                        got: format!("{:?}", tok.token),
2065                                        expected: "'[' for tuple variant",
2066                                    },
2067                                    tok.span,
2068                                ));
2069                            }
2070
2071                            for i in 0..num_fields {
2072                                let field = &variant.data.fields[i];
2073                                wip = wip.begin_nth_field(i)?;
2074                                // Check if field has custom deserialization
2075                                if field.proxy_convert_in_fn().is_some() {
2076                                    wip = wip.begin_custom_deserialization()?;
2077                                    wip = self.deserialize_into(wip)?;
2078                                    wip = wip.end()?; // Calls deserialize_with function
2079                                } else {
2080                                    wip = self.deserialize_into(wip)?;
2081                                }
2082                                wip = wip.end()?;
2083
2084                                // Check for comma or closing bracket
2085                                let next = self.peek()?;
2086                                if matches!(next.token, Token::Comma) {
2087                                    self.next()?;
2088                                }
2089                            }
2090
2091                            let close = self.next()?;
2092                            if !matches!(close.token, Token::ArrayEnd) {
2093                                return Err(JsonError::new(
2094                                    JsonErrorKind::UnexpectedToken {
2095                                        got: format!("{:?}", close.token),
2096                                        expected: "']'",
2097                                    },
2098                                    close.span,
2099                                ));
2100                            }
2101                        }
2102                    }
2103                    StructKind::Struct => {
2104                        // Struct variant: object with named fields
2105                        wip = self.deserialize_variant_struct_content(wip)?;
2106                    }
2107                }
2108
2109                // Expect closing brace for the outer object
2110                let close = self.next()?;
2111                if !matches!(close.token, Token::ObjectEnd) {
2112                    return Err(JsonError::new(
2113                        JsonErrorKind::UnexpectedToken {
2114                            got: format!("{:?}", close.token),
2115                            expected: "'}'",
2116                        },
2117                        close.span,
2118                    ));
2119                }
2120
2121                Ok(wip)
2122            }
2123            _ => {
2124                let span = token.span;
2125                Err(JsonError::new(
2126                    JsonErrorKind::UnexpectedToken {
2127                        got: format!("{:?}", token.token),
2128                        expected: "string or object for enum",
2129                    },
2130                    span,
2131                ))
2132            }
2133        }
2134    }
2135
2136    /// Deserialize an untagged enum using the Solver to determine which variant matches.
2137    ///
2138    /// For untagged enums, we use facet-solver to:
2139    /// 1. Record the start position of the object
2140    /// 2. Scan all JSON keys, feed them to the solver to narrow down candidates
2141    /// 3. Use finish() to determine which variant's required fields are satisfied
2142    /// 4. Rewind to start position and deserialize the whole object into the matched variant
2143    fn deserialize_untagged_enum(
2144        &mut self,
2145        mut wip: Partial<'input, BORROW>,
2146    ) -> Result<Partial<'input, BORROW>> {
2147        log::trace!("deserialize_untagged_enum: {}", wip.shape().type_identifier);
2148
2149        let shape = wip.shape();
2150
2151        // Build schema - this creates one resolution per variant for untagged enums
2152        let schema = Schema::build_auto(shape).map_err(|e| {
2153            JsonError::without_span(JsonErrorKind::Solver(format!(
2154                "failed to build schema: {e}"
2155            )))
2156        })?;
2157
2158        // Create the solver
2159        let mut solver = Solver::new(&schema);
2160
2161        // Expect opening brace (struct variants) or handle other cases
2162        let token = self.peek()?;
2163        match &token.token {
2164            Token::ObjectStart => {
2165                // Record start position for rewinding after we determine the variant
2166                let start_offset = token.span.offset;
2167
2168                self.next()?; // consume the brace
2169
2170                // ========== PASS 1: Scan all keys, feed to solver ==========
2171                loop {
2172                    let token = self.peek()?;
2173                    match &token.token {
2174                        Token::ObjectEnd => {
2175                            self.next()?;
2176                            break;
2177                        }
2178                        Token::String(_) => {
2179                            let key_token = self.next()?;
2180                            let key = match &key_token.token {
2181                                Token::String(s) => s.clone(),
2182                                _ => unreachable!(),
2183                            };
2184
2185                            let colon = self.next()?;
2186                            if !matches!(colon.token, Token::Colon) {
2187                                return Err(JsonError::new(
2188                                    JsonErrorKind::UnexpectedToken {
2189                                        got: format!("{:?}", colon.token),
2190                                        expected: "':'",
2191                                    },
2192                                    colon.span,
2193                                ));
2194                            }
2195
2196                            // Feed key to solver
2197                            let _decision = solver.see_key(key);
2198
2199                            // Skip the value
2200                            self.skip_value()?;
2201
2202                            // Check for comma
2203                            let next = self.peek()?;
2204                            if matches!(next.token, Token::Comma) {
2205                                self.next()?;
2206                            }
2207                        }
2208                        _ => {
2209                            let span = token.span;
2210                            return Err(JsonError::new(
2211                                JsonErrorKind::UnexpectedToken {
2212                                    got: format!("{:?}", token.token),
2213                                    expected: "field name or '}'",
2214                                },
2215                                span,
2216                            ));
2217                        }
2218                    }
2219                }
2220
2221                // ========== Get the resolved variant ==========
2222                let config_handle = solver
2223                    .finish()
2224                    .map_err(|e| JsonError::without_span(JsonErrorKind::Solver(format!("{e}"))))?;
2225                let config = config_handle.resolution();
2226
2227                // Extract the variant name from the resolution
2228                let variant_name = config
2229                    .variant_selections()
2230                    .first()
2231                    .map(|vs| vs.variant_name)
2232                    .ok_or_else(|| {
2233                        JsonError::without_span(JsonErrorKind::InvalidValue {
2234                            message: "solver returned resolution with no variant selection".into(),
2235                        })
2236                    })?;
2237
2238                // Select the variant
2239                wip = wip.select_variant_named(variant_name)?;
2240
2241                // ========== PASS 2: Rewind and deserialize ==========
2242                // Create a new deserializer at the start of the object
2243                let rewound_adapter = self.adapter.at_offset(start_offset).ok_or_else(|| {
2244                    JsonError::without_span(JsonErrorKind::InvalidValue {
2245                        message: "untagged enums not supported in streaming mode".into(),
2246                    })
2247                })?;
2248                let mut rewound_deser = Self::from_adapter(rewound_adapter);
2249
2250                // Deserialize the object into the selected variant
2251                wip = rewound_deser.deserialize_variant_struct_content(wip)?;
2252
2253                Ok(wip)
2254            }
2255            Token::ArrayStart => {
2256                // Tuple variants - match by arity
2257                self.deserialize_untagged_tuple_variant(wip, shape)
2258            }
2259            Token::Null => {
2260                // Unit variants - select the first unit variant
2261                self.deserialize_untagged_unit_variant(wip, shape)
2262            }
2263            Token::String(_)
2264            | Token::I64(_)
2265            | Token::U64(_)
2266            | Token::I128(_)
2267            | Token::U128(_)
2268            | Token::F64(_)
2269            | Token::True
2270            | Token::False => {
2271                // Scalar variants - select based on value type
2272                self.deserialize_untagged_scalar_variant(wip, shape)
2273            }
2274            _ => Err(JsonError::new(
2275                JsonErrorKind::InvalidValue {
2276                    message: format!("unexpected token {:?} for untagged enum", token.token),
2277                },
2278                token.span,
2279            )),
2280        }
2281    }
2282
2283    /// Deserialize an untagged enum from a null value.
2284    /// Selects the first unit variant.
2285    fn deserialize_untagged_unit_variant(
2286        &mut self,
2287        mut wip: Partial<'input, BORROW>,
2288        shape: &'static Shape,
2289    ) -> Result<Partial<'input, BORROW>> {
2290        let variants_by_format = VariantsByFormat::from_shape(shape).ok_or_else(|| {
2291            JsonError::without_span(JsonErrorKind::InvalidValue {
2292                message: "expected enum shape for untagged deserialization".into(),
2293            })
2294        })?;
2295
2296        if variants_by_format.unit_variants.is_empty() {
2297            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2298                message: format!(
2299                    "no unit variants in untagged enum {} for null value",
2300                    shape.type_identifier
2301                ),
2302            }));
2303        }
2304
2305        // Consume the null token
2306        self.next()?;
2307
2308        // Select the first unit variant (like serde does)
2309        let variant = variants_by_format.unit_variants[0];
2310        wip = wip.select_variant_named(variant.name)?;
2311
2312        Ok(wip)
2313    }
2314
2315    /// Deserialize an untagged enum from a scalar value (string, number, bool).
2316    /// Selects the variant based on the value type.
2317    fn deserialize_untagged_scalar_variant(
2318        &mut self,
2319        mut wip: Partial<'input, BORROW>,
2320        shape: &'static Shape,
2321    ) -> Result<Partial<'input, BORROW>> {
2322        let variants_by_format = VariantsByFormat::from_shape(shape).ok_or_else(|| {
2323            JsonError::without_span(JsonErrorKind::InvalidValue {
2324                message: "expected enum shape for untagged deserialization".into(),
2325            })
2326        })?;
2327
2328        // Check if we have a string token that matches a unit variant name
2329        let token = self.peek()?.clone();
2330        if let Token::String(ref s) = token.token {
2331            // Try to find a unit variant with this name
2332            for variant in &variants_by_format.unit_variants {
2333                if variant.name == s.as_ref() {
2334                    // This is a unit variant - consume the string and select it
2335                    self.next()?;
2336                    wip = wip.select_variant_named(variant.name)?;
2337                    return Ok(wip);
2338                }
2339            }
2340        }
2341
2342        // Not a unit variant - fall back to newtype scalar variant handling
2343        if variants_by_format.scalar_variants.is_empty() {
2344            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2345                message: format!(
2346                    "no scalar-accepting variants in untagged enum {}",
2347                    shape.type_identifier
2348                ),
2349            }));
2350        }
2351
2352        // Select the variant based on the token type
2353        let variant_name = self.select_scalar_variant(&variants_by_format, &token)?;
2354
2355        wip = wip.select_variant_named(variant_name)?;
2356        wip = wip.begin_nth_field(0)?;
2357        wip = self.deserialize_into(wip)?;
2358        wip = wip.end()?;
2359
2360        Ok(wip)
2361    }
2362
2363    /// Select which scalar variant to use based on the JSON token.
2364    fn select_scalar_variant(
2365        &self,
2366        variants: &VariantsByFormat,
2367        token: &SpannedAdapterToken,
2368    ) -> Result<&'static str> {
2369        // Sort by specificity (most specific first)
2370        let mut candidates: Vec<_> = variants.scalar_variants.clone();
2371        candidates.sort_by_key(|(_, inner_shape)| specificity_score(inner_shape));
2372
2373        match &token.token {
2374            Token::True | Token::False => {
2375                // Find a bool variant
2376                for (variant, inner_shape) in &candidates {
2377                    if inner_shape.scalar_type() == Some(ScalarType::Bool) {
2378                        return Ok(variant.name);
2379                    }
2380                }
2381            }
2382            Token::I64(n) => {
2383                // Find the smallest integer type that fits
2384                let n = *n;
2385                for (variant, inner_shape) in &candidates {
2386                    let fits = match inner_shape.scalar_type() {
2387                        Some(ScalarType::U8) => n >= 0 && n <= u8::MAX as i64,
2388                        Some(ScalarType::U16) => n >= 0 && n <= u16::MAX as i64,
2389                        Some(ScalarType::U32) => n >= 0 && n <= u32::MAX as i64,
2390                        Some(ScalarType::U64) => n >= 0,
2391                        Some(ScalarType::I8) => n >= i8::MIN as i64 && n <= i8::MAX as i64,
2392                        Some(ScalarType::I16) => n >= i16::MIN as i64 && n <= i16::MAX as i64,
2393                        Some(ScalarType::I32) => n >= i32::MIN as i64 && n <= i32::MAX as i64,
2394                        Some(ScalarType::I64) => true,
2395                        Some(ScalarType::F32) | Some(ScalarType::F64) => true,
2396                        _ => false,
2397                    };
2398                    if fits {
2399                        return Ok(variant.name);
2400                    }
2401                }
2402            }
2403            Token::U64(n) => {
2404                let n = *n;
2405                for (variant, inner_shape) in &candidates {
2406                    let fits = match inner_shape.scalar_type() {
2407                        Some(ScalarType::U8) => n <= u8::MAX as u64,
2408                        Some(ScalarType::U16) => n <= u16::MAX as u64,
2409                        Some(ScalarType::U32) => n <= u32::MAX as u64,
2410                        Some(ScalarType::U64) => true,
2411                        Some(ScalarType::I8) => n <= i8::MAX as u64,
2412                        Some(ScalarType::I16) => n <= i16::MAX as u64,
2413                        Some(ScalarType::I32) => n <= i32::MAX as u64,
2414                        Some(ScalarType::I64) => n <= i64::MAX as u64,
2415                        Some(ScalarType::F32) | Some(ScalarType::F64) => true,
2416                        _ => false,
2417                    };
2418                    if fits {
2419                        return Ok(variant.name);
2420                    }
2421                }
2422            }
2423            Token::I128(n) => {
2424                let n = *n;
2425                for (variant, inner_shape) in &candidates {
2426                    let fits = match inner_shape.scalar_type() {
2427                        Some(ScalarType::I128) => true,
2428                        Some(ScalarType::U128) => n >= 0,
2429                        _ => false,
2430                    };
2431                    if fits {
2432                        return Ok(variant.name);
2433                    }
2434                }
2435            }
2436            Token::U128(n) => {
2437                let n = *n;
2438                for (variant, inner_shape) in &candidates {
2439                    let fits = match inner_shape.scalar_type() {
2440                        Some(ScalarType::U128) => true,
2441                        Some(ScalarType::I128) => n <= i128::MAX as u128,
2442                        _ => false,
2443                    };
2444                    if fits {
2445                        return Ok(variant.name);
2446                    }
2447                }
2448            }
2449            Token::F64(_) => {
2450                // Find a float variant
2451                for (variant, inner_shape) in &candidates {
2452                    if matches!(
2453                        inner_shape.scalar_type(),
2454                        Some(ScalarType::F32) | Some(ScalarType::F64)
2455                    ) {
2456                        return Ok(variant.name);
2457                    }
2458                }
2459            }
2460            Token::String(_) => {
2461                // Find a string-like variant
2462                for (variant, inner_shape) in &candidates {
2463                    if matches!(
2464                        inner_shape.scalar_type(),
2465                        Some(ScalarType::String) | Some(ScalarType::Str) | Some(ScalarType::CowStr)
2466                    ) || inner_shape.scalar_type().is_none()
2467                    {
2468                        return Ok(variant.name);
2469                    }
2470                }
2471            }
2472            _ => {}
2473        }
2474
2475        // Fall back to the first scalar variant if no specific match
2476        if let Some((variant, _)) = candidates.first() {
2477            return Ok(variant.name);
2478        }
2479
2480        Err(JsonError::new(
2481            JsonErrorKind::InvalidValue {
2482                message: format!("no matching scalar variant for token {:?}", token.token),
2483            },
2484            token.span,
2485        ))
2486    }
2487
2488    /// Deserialize an untagged enum from an array (tuple variant).
2489    fn deserialize_untagged_tuple_variant(
2490        &mut self,
2491        mut wip: Partial<'input, BORROW>,
2492        shape: &'static Shape,
2493    ) -> Result<Partial<'input, BORROW>> {
2494        let variants_by_format = VariantsByFormat::from_shape(shape).ok_or_else(|| {
2495            JsonError::without_span(JsonErrorKind::InvalidValue {
2496                message: "expected enum shape for untagged deserialization".into(),
2497            })
2498        })?;
2499
2500        if variants_by_format.tuple_variants.is_empty() {
2501            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2502                message: format!(
2503                    "no tuple variants in untagged enum {} for array value",
2504                    shape.type_identifier
2505                ),
2506            }));
2507        }
2508
2509        // Record start position for rewinding
2510        let start_token = self.peek()?;
2511        let start_offset = start_token.span.offset;
2512
2513        // Count the array elements
2514        self.next()?; // consume ArrayStart
2515        let mut arity = 0;
2516        loop {
2517            let token = self.peek()?;
2518            match &token.token {
2519                Token::ArrayEnd => {
2520                    self.next()?;
2521                    break;
2522                }
2523                _ => {
2524                    arity += 1;
2525                    self.skip_value()?;
2526                    // Skip comma if present
2527                    let next = self.peek()?;
2528                    if matches!(next.token, Token::Comma) {
2529                        self.next()?;
2530                    }
2531                }
2532            }
2533        }
2534
2535        // Find variants with matching arity
2536        let matching_variants = variants_by_format.tuple_variants_with_arity(arity);
2537        if matching_variants.is_empty() {
2538            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2539                message: format!(
2540                    "no tuple variant with arity {} in untagged enum {}",
2541                    arity, shape.type_identifier
2542                ),
2543            }));
2544        }
2545
2546        // Select the first matching variant
2547        let variant = matching_variants[0];
2548        wip = wip.select_variant_named(variant.name)?;
2549        let is_newtype = variant.data.fields.len() == 1;
2550
2551        // Rewind and deserialize
2552        let rewound_adapter = self.adapter.at_offset(start_offset).ok_or_else(|| {
2553            JsonError::without_span(JsonErrorKind::InvalidValue {
2554                message: "untagged tuple variants not supported in streaming mode".into(),
2555            })
2556        })?;
2557        let mut rewound_deser = Self::from_adapter(rewound_adapter);
2558
2559        if is_newtype {
2560            // Deserialize the entire array into the inner tuple value
2561            wip = wip.begin_nth_field(0)?;
2562            wip = rewound_deser.deserialize_into(wip)?;
2563            wip = wip.end()?;
2564        } else {
2565            // Consume ArrayStart
2566            rewound_deser.next()?;
2567
2568            // Deserialize each field
2569            for i in 0..arity {
2570                wip = wip.begin_nth_field(i)?;
2571                wip = rewound_deser.deserialize_into(wip)?;
2572                wip = wip.end()?;
2573
2574                // Skip comma if present
2575                let next = rewound_deser.peek()?;
2576                if matches!(next.token, Token::Comma) {
2577                    rewound_deser.next()?;
2578                }
2579            }
2580
2581            debug_assert_eq!(
2582                variant.data.fields.len(),
2583                arity,
2584                "tuple variant arity should match array length"
2585            );
2586
2587            // Consume ArrayEnd
2588            rewound_deser.next()?;
2589        }
2590
2591        Ok(wip)
2592    }
2593
2594    /// Deserialize the content of an enum variant in a flattened context.
2595    /// Handles both struct variants and tuple variants.
2596    fn deserialize_variant_struct_content(
2597        &mut self,
2598        mut wip: Partial<'input, BORROW>,
2599    ) -> Result<Partial<'input, BORROW>> {
2600        // Check what kind of variant we have
2601        let variant = wip.selected_variant().ok_or_else(|| {
2602            JsonError::without_span(JsonErrorKind::InvalidValue {
2603                message: "no variant selected".into(),
2604            })
2605        })?;
2606
2607        let is_struct_variant = variant
2608            .data
2609            .fields
2610            .first()
2611            .map(|f| !f.name.starts_with(|c: char| c.is_ascii_digit()))
2612            .unwrap_or(true);
2613
2614        if is_struct_variant {
2615            // Struct variant: {"field1": ..., "field2": ...}
2616            self.deserialize_variant_struct_fields(wip, variant.data.fields)
2617        } else if variant.data.fields.len() == 1 {
2618            // Single-element tuple variant: just the value (not wrapped)
2619            let field = &variant.data.fields[0];
2620            wip = wip.begin_nth_field(0)?;
2621            // Check if field has custom deserialization
2622            if field.proxy_convert_in_fn().is_some() {
2623                wip = wip.begin_custom_deserialization()?;
2624                wip = self.deserialize_into(wip)?;
2625                wip = wip.end()?;
2626            } else {
2627                wip = self.deserialize_into(wip)?;
2628            }
2629            wip = wip.end()?;
2630            Ok(wip)
2631        } else {
2632            // Multi-element tuple variant: [val1, val2, ...]
2633            self.deserialize_variant_tuple_fields(wip)
2634        }
2635    }
2636
2637    /// Deserialize struct fields of a variant.
2638    fn deserialize_variant_struct_fields(
2639        &mut self,
2640        mut wip: Partial<'input, BORROW>,
2641        fields: &[facet_core::Field],
2642    ) -> Result<Partial<'input, BORROW>> {
2643        let token = self.next()?;
2644        if !matches!(token.token, Token::ObjectStart) {
2645            return Err(JsonError::new(
2646                JsonErrorKind::UnexpectedToken {
2647                    got: format!("{:?}", token.token),
2648                    expected: "'{' for struct variant",
2649                },
2650                token.span,
2651            ));
2652        }
2653
2654        loop {
2655            let token = self.peek()?;
2656            if matches!(token.token, Token::ObjectEnd) {
2657                self.next()?;
2658                break;
2659            }
2660
2661            let key_token = self.next()?;
2662            let field_name = match &key_token.token {
2663                Token::String(s) => s.clone(),
2664                _ => {
2665                    return Err(JsonError::new(
2666                        JsonErrorKind::UnexpectedToken {
2667                            got: format!("{:?}", key_token.token),
2668                            expected: "field name",
2669                        },
2670                        key_token.span,
2671                    ));
2672                }
2673            };
2674
2675            let colon = self.next()?;
2676            if !matches!(colon.token, Token::Colon) {
2677                return Err(JsonError::new(
2678                    JsonErrorKind::UnexpectedToken {
2679                        got: format!("{:?}", colon.token),
2680                        expected: "':'",
2681                    },
2682                    colon.span,
2683                ));
2684            }
2685
2686            // Find the field in the variant's fields to check for custom deserialization
2687            let field_info = fields.iter().find(|f| f.name == field_name.as_ref());
2688
2689            if let Some(field) = field_info {
2690                wip = wip.begin_field(field.name)?;
2691                // Check if field has custom deserialization
2692                if field.proxy_convert_in_fn().is_some() {
2693                    wip = wip.begin_custom_deserialization()?;
2694                    wip = self.deserialize_into(wip)?;
2695                    wip = wip.end()?; // Calls deserialize_with function
2696                } else {
2697                    wip = self.deserialize_into(wip)?;
2698                }
2699                wip = wip.end()?;
2700            } else {
2701                // Unknown field, skip its value
2702                self.skip_value()?;
2703            }
2704
2705            let next = self.peek()?;
2706            if matches!(next.token, Token::Comma) {
2707                self.next()?;
2708            }
2709        }
2710
2711        Ok(wip)
2712    }
2713
2714    /// Deserialize tuple fields of a variant.
2715    fn deserialize_variant_tuple_fields(
2716        &mut self,
2717        mut wip: Partial<'input, BORROW>,
2718    ) -> Result<Partial<'input, BORROW>> {
2719        let token = self.next()?;
2720        if !matches!(token.token, Token::ArrayStart) {
2721            return Err(JsonError::new(
2722                JsonErrorKind::UnexpectedToken {
2723                    got: format!("{:?}", token.token),
2724                    expected: "'[' for tuple variant",
2725                },
2726                token.span,
2727            ));
2728        }
2729
2730        let mut idx = 0;
2731        loop {
2732            let token = self.peek()?;
2733            if matches!(token.token, Token::ArrayEnd) {
2734                self.next()?;
2735                break;
2736            }
2737
2738            // Deserialize into field "0", "1", "2", etc.
2739            let field_name = alloc::format!("{idx}");
2740            wip = wip.begin_field(&field_name)?;
2741            wip = self.deserialize_into(wip)?;
2742            wip = wip.end()?;
2743
2744            idx += 1;
2745            let next = self.peek()?;
2746            if matches!(next.token, Token::Comma) {
2747                self.next()?;
2748            }
2749        }
2750
2751        Ok(wip)
2752    }
2753
2754    /// Deserialize a list/Vec.
2755    fn deserialize_list(
2756        &mut self,
2757        mut wip: Partial<'input, BORROW>,
2758    ) -> Result<Partial<'input, BORROW>> {
2759        log::trace!("deserialize_list");
2760
2761        let token = self.next()?;
2762        if !matches!(token.token, Token::ArrayStart) {
2763            return Err(JsonError::new(
2764                JsonErrorKind::UnexpectedToken {
2765                    got: format!("{:?}", token.token),
2766                    expected: "'['",
2767                },
2768                token.span,
2769            ));
2770        }
2771
2772        wip = wip.begin_list()?;
2773
2774        loop {
2775            let token = self.peek()?;
2776            if matches!(token.token, Token::ArrayEnd) {
2777                self.next()?;
2778                break;
2779            }
2780
2781            wip = wip.begin_list_item()?;
2782            wip = self.deserialize_into(wip)?;
2783            wip = wip.end()?; // End the list item frame
2784
2785            let next = self.peek()?;
2786            if matches!(next.token, Token::Comma) {
2787                self.next()?;
2788            }
2789        }
2790
2791        // Note: begin_list() does not push a frame, so we don't call end() here
2792        Ok(wip)
2793    }
2794
2795    /// Deserialize a map.
2796    fn deserialize_map(
2797        &mut self,
2798        mut wip: Partial<'input, BORROW>,
2799    ) -> Result<Partial<'input, BORROW>> {
2800        log::trace!("deserialize_map");
2801
2802        let token = self.next()?;
2803        if !matches!(token.token, Token::ObjectStart) {
2804            return Err(JsonError::new(
2805                JsonErrorKind::UnexpectedToken {
2806                    got: format!("{:?}", token.token),
2807                    expected: "'{'",
2808                },
2809                token.span,
2810            ));
2811        }
2812
2813        wip = wip.begin_map()?;
2814
2815        loop {
2816            let token = self.peek()?;
2817            if matches!(token.token, Token::ObjectEnd) {
2818                self.next()?;
2819                break;
2820            }
2821
2822            // Key
2823            let key_token = self.next()?;
2824            let key = match key_token.token {
2825                Token::String(s) => s,
2826                _ => {
2827                    return Err(JsonError::new(
2828                        JsonErrorKind::UnexpectedToken {
2829                            got: format!("{:?}", key_token.token),
2830                            expected: "string key",
2831                        },
2832                        key_token.span,
2833                    ));
2834                }
2835            };
2836
2837            // Colon
2838            let colon = self.next()?;
2839            if !matches!(colon.token, Token::Colon) {
2840                return Err(JsonError::new(
2841                    JsonErrorKind::UnexpectedToken {
2842                        got: format!("{:?}", colon.token),
2843                        expected: "':'",
2844                    },
2845                    colon.span,
2846                ));
2847            }
2848
2849            // Set key - begin_key pushes a frame for the key type
2850            wip = wip.begin_key()?;
2851            // For transparent types (like UserId(String)), we need to use begin_inner
2852            // to set the inner String value. But NOT for pointer types like &str or Cow<str>
2853            // which are handled directly by set_string_value.
2854            let is_pointer = matches!(wip.shape().def, Def::Pointer(_));
2855            if wip.shape().inner.is_some() && !is_pointer {
2856                wip = wip.begin_inner()?;
2857                wip = self.set_string_value(wip, key)?;
2858                wip = wip.end()?;
2859            } else {
2860                wip = self.set_string_value(wip, key)?;
2861            }
2862            wip = wip.end()?;
2863
2864            // Value - begin_value pushes a frame
2865            wip = wip.begin_value()?;
2866            wip = self.deserialize_into(wip)?;
2867            wip = wip.end()?;
2868
2869            // Comma or end
2870            let next = self.peek()?;
2871            if matches!(next.token, Token::Comma) {
2872                self.next()?;
2873            }
2874        }
2875
2876        // Note: begin_map() does not push a frame, so we don't call end() here
2877        Ok(wip)
2878    }
2879
2880    /// Deserialize an Option.
2881    fn deserialize_option(
2882        &mut self,
2883        mut wip: Partial<'input, BORROW>,
2884    ) -> Result<Partial<'input, BORROW>> {
2885        log::trace!("deserialize_option");
2886
2887        let token = self.peek()?;
2888        if matches!(token.token, Token::Null) {
2889            self.next()?;
2890            wip = wip.set_default()?; // None
2891        } else {
2892            log::trace!("deserialize_option: calling begin_some");
2893            wip = wip.begin_some()?;
2894            log::trace!("deserialize_option: begin_some succeeded, calling deserialize_into");
2895            wip = self.deserialize_into(wip)?;
2896            log::trace!("deserialize_option: deserialize_into succeeded, calling end");
2897            wip = wip.end()?;
2898            log::trace!("deserialize_option: end succeeded");
2899        }
2900        Ok(wip)
2901    }
2902
2903    /// Deserialize a smart pointer (Box, Arc, Rc) or reference (&str).
2904    fn deserialize_pointer(
2905        &mut self,
2906        mut wip: Partial<'input, BORROW>,
2907    ) -> Result<Partial<'input, BORROW>> {
2908        log::trace!("deserialize_pointer");
2909
2910        // Check what kind of pointer this is BEFORE calling begin_smart_ptr
2911        let (is_slice_pointer, is_reference, is_str_ref, is_cow_str) =
2912            if let Def::Pointer(ptr_def) = wip.shape().def {
2913                let is_slice = if let Some(pointee) = ptr_def.pointee() {
2914                    matches!(pointee.ty, Type::Sequence(SequenceType::Slice(_)))
2915                } else {
2916                    false
2917                };
2918                let is_ref = matches!(
2919                    ptr_def.known,
2920                    Some(KnownPointer::SharedReference | KnownPointer::ExclusiveReference)
2921                );
2922                // Special case: &str can be deserialized by borrowing from input
2923                let is_str_ref = matches!(ptr_def.known, Some(KnownPointer::SharedReference))
2924                    && ptr_def
2925                        .pointee()
2926                        .is_some_and(|p| p.type_identifier == "str");
2927                // Special case: Cow<str> can borrow or own depending on whether escaping was needed
2928                let is_cow_str = matches!(ptr_def.known, Some(KnownPointer::Cow))
2929                    && ptr_def
2930                        .pointee()
2931                        .is_some_and(|p| p.type_identifier == "str");
2932                (is_slice, is_ref, is_str_ref, is_cow_str)
2933            } else {
2934                (false, false, false, false)
2935            };
2936
2937        // Special case: Cow<str> can be deserialized directly from string tokens
2938        // preserving borrowed/owned status based on whether escaping was needed
2939        if is_cow_str {
2940            let token = self.next()?;
2941            match token.token {
2942                Token::String(s) => {
2943                    // Zero-copy Cow<str>: preserve borrowed/owned status
2944                    wip = wip.set(s)?;
2945                    return Ok(wip);
2946                }
2947                _ => {
2948                    return Err(JsonError::new(
2949                        JsonErrorKind::UnexpectedToken {
2950                            got: format!("{:?}", token.token),
2951                            expected: "string",
2952                        },
2953                        token.span,
2954                    ));
2955                }
2956            }
2957        }
2958
2959        // Special case: &str can borrow directly from input if no escaping needed
2960        if is_str_ref {
2961            // In owned mode, we cannot borrow from input at all
2962            if !BORROW {
2963                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2964                    message: "cannot deserialize into &str when borrowing is disabled - use String or Cow<str> instead".into(),
2965                }));
2966            }
2967            let token = self.next()?;
2968            match token.token {
2969                Token::String(Cow::Borrowed(s)) => {
2970                    // Zero-copy: borrow directly from input
2971                    wip = wip.set(s)?;
2972                    return Ok(wip);
2973                }
2974                Token::String(Cow::Owned(_)) => {
2975                    return Err(JsonError::new(
2976                        JsonErrorKind::InvalidValue {
2977                            message: "cannot borrow &str from JSON string containing escape sequences - use String instead".into(),
2978                        },
2979                        token.span,
2980                    ));
2981                }
2982                _ => {
2983                    return Err(JsonError::new(
2984                        JsonErrorKind::UnexpectedToken {
2985                            got: format!("{:?}", token.token),
2986                            expected: "string",
2987                        },
2988                        token.span,
2989                    ));
2990                }
2991            }
2992        }
2993
2994        // Other references (&T, &mut T) cannot be deserialized - they require borrowing from
2995        // existing data, which isn't possible when deserializing from owned JSON
2996        if is_reference {
2997            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
2998                message: format!(
2999                    "cannot deserialize into reference type '{wip}' - references require borrowing from existing data",
3000                    wip = wip.shape().type_identifier
3001                ),
3002            }));
3003        }
3004
3005        // For smart pointers, push_smart_ptr will handle:
3006        // - Sized pointees: allocates space for the inner type
3007        // - str pointee: allocates a String that gets converted to Box<str>/Arc<str>/Rc<str>
3008        // - [T] pointee: sets up a slice builder for Arc<[T]>/Box<[T]>/Rc<[T]>
3009        wip = wip.begin_smart_ptr()?;
3010
3011        if is_slice_pointer {
3012            // This is a slice pointer like Arc<[T]> - deserialize as array
3013            let token = self.next()?;
3014            if !matches!(token.token, Token::ArrayStart) {
3015                return Err(JsonError::new(
3016                    JsonErrorKind::UnexpectedToken {
3017                        got: format!("{:?}", token.token),
3018                        expected: "'['",
3019                    },
3020                    token.span,
3021                ));
3022            }
3023
3024            // Peek to check for empty array
3025            let first = self.peek()?;
3026            if matches!(first.token, Token::ArrayEnd) {
3027                self.next()?; // consume the RBracket
3028                wip = wip.end()?;
3029                return Ok(wip);
3030            }
3031
3032            // Deserialize elements
3033            loop {
3034                wip = wip.begin_list_item()?;
3035                wip = self.deserialize_into(wip)?;
3036                wip = wip.end()?;
3037
3038                let next = self.next()?;
3039                match next.token {
3040                    Token::Comma => continue,
3041                    Token::ArrayEnd => break,
3042                    _ => {
3043                        return Err(JsonError::new(
3044                            JsonErrorKind::UnexpectedToken {
3045                                got: format!("{:?}", next.token),
3046                                expected: "',' or ']'",
3047                            },
3048                            next.span,
3049                        ));
3050                    }
3051                }
3052            }
3053
3054            wip = wip.end()?;
3055            return Ok(wip);
3056        }
3057
3058        // For non-slice pointers, deserialize the inner type directly
3059        wip = self.deserialize_into(wip)?;
3060        wip = wip.end()?;
3061        Ok(wip)
3062    }
3063
3064    /// Deserialize a fixed-size array.
3065    fn deserialize_array(
3066        &mut self,
3067        mut wip: Partial<'input, BORROW>,
3068    ) -> Result<Partial<'input, BORROW>> {
3069        log::trace!("deserialize_array");
3070
3071        let token = self.next()?;
3072        if !matches!(token.token, Token::ArrayStart) {
3073            return Err(JsonError::new(
3074                JsonErrorKind::UnexpectedToken {
3075                    got: format!("{:?}", token.token),
3076                    expected: "'['",
3077                },
3078                token.span,
3079            ));
3080        }
3081
3082        // Get array length from the Def
3083        let array_len = match &wip.shape().def {
3084            Def::Array(arr) => arr.n,
3085            _ => {
3086                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
3087                    message: "expected array type".into(),
3088                }));
3089            }
3090        };
3091
3092        // Deserialize each element by index
3093        for i in 0..array_len {
3094            if i > 0 {
3095                let comma = self.next()?;
3096                if !matches!(comma.token, Token::Comma) {
3097                    return Err(JsonError::new(
3098                        JsonErrorKind::UnexpectedToken {
3099                            got: format!("{:?}", comma.token),
3100                            expected: "','",
3101                        },
3102                        comma.span,
3103                    ));
3104                }
3105            }
3106
3107            wip = wip.begin_nth_field(i)?;
3108            wip = self.deserialize_into(wip)?;
3109            wip = wip.end()?;
3110        }
3111
3112        let close = self.next()?;
3113        if !matches!(close.token, Token::ArrayEnd) {
3114            // If we got a comma, that means there are more elements than the fixed array can hold
3115            if matches!(close.token, Token::Comma) {
3116                return Err(JsonError::new(
3117                    JsonErrorKind::InvalidValue {
3118                        message: format!(
3119                            "Too many elements in array, maximum {array_len} elements"
3120                        ),
3121                    },
3122                    close.span,
3123                ));
3124            }
3125            return Err(JsonError::new(
3126                JsonErrorKind::UnexpectedToken {
3127                    got: format!("{:?}", close.token),
3128                    expected: "']'",
3129                },
3130                close.span,
3131            ));
3132        }
3133
3134        Ok(wip)
3135    }
3136
3137    /// Deserialize a set.
3138    fn deserialize_set(
3139        &mut self,
3140        mut wip: Partial<'input, BORROW>,
3141    ) -> Result<Partial<'input, BORROW>> {
3142        log::trace!("deserialize_set");
3143
3144        let token = self.next()?;
3145        if !matches!(token.token, Token::ArrayStart) {
3146            return Err(JsonError::new(
3147                JsonErrorKind::UnexpectedToken {
3148                    got: format!("{:?}", token.token),
3149                    expected: "'['",
3150                },
3151                token.span,
3152            ));
3153        }
3154
3155        wip = wip.begin_set()?;
3156
3157        loop {
3158            let token = self.peek()?;
3159            if matches!(token.token, Token::ArrayEnd) {
3160                self.next()?;
3161                break;
3162            }
3163
3164            wip = wip.begin_set_item()?;
3165            wip = self.deserialize_into(wip)?;
3166            wip = wip.end()?; // End the set item frame
3167
3168            let next = self.peek()?;
3169            if matches!(next.token, Token::Comma) {
3170                self.next()?;
3171            }
3172        }
3173
3174        // Note: begin_set() does not push a frame, so we don't call end() here
3175        Ok(wip)
3176    }
3177
3178    /// Deserialize a tuple.
3179    fn deserialize_tuple(
3180        &mut self,
3181        mut wip: Partial<'input, BORROW>,
3182    ) -> Result<Partial<'input, BORROW>> {
3183        log::trace!("deserialize_tuple");
3184
3185        let token = self.next()?;
3186        if !matches!(token.token, Token::ArrayStart) {
3187            return Err(JsonError::new(
3188                JsonErrorKind::UnexpectedToken {
3189                    got: format!("{:?}", token.token),
3190                    expected: "'['",
3191                },
3192                token.span,
3193            ));
3194        }
3195
3196        // Get tuple info from the struct definition
3197        let tuple_len = match &wip.shape().ty {
3198            Type::User(UserType::Struct(struct_def)) => struct_def.fields.len(),
3199            _ => {
3200                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
3201                    message: "expected tuple type".into(),
3202                }));
3203            }
3204        };
3205
3206        for i in 0..tuple_len {
3207            if i > 0 {
3208                let comma = self.next()?;
3209                if !matches!(comma.token, Token::Comma) {
3210                    return Err(JsonError::new(
3211                        JsonErrorKind::UnexpectedToken {
3212                            got: format!("{:?}", comma.token),
3213                            expected: "','",
3214                        },
3215                        comma.span,
3216                    ));
3217                }
3218            }
3219
3220            wip = wip.begin_nth_field(i)?;
3221            wip = self.deserialize_into(wip)?;
3222            wip = wip.end()?;
3223        }
3224
3225        let close = self.next()?;
3226        if !matches!(close.token, Token::ArrayEnd) {
3227            return Err(JsonError::new(
3228                JsonErrorKind::UnexpectedToken {
3229                    got: format!("{:?}", close.token),
3230                    expected: "']'",
3231                },
3232                close.span,
3233            ));
3234        }
3235
3236        Ok(wip)
3237    }
3238
3239    fn set_missing_field_default(
3240        &mut self,
3241        mut wip: Partial<'input, BORROW>,
3242        field_info: &FieldInfo,
3243        skip_first_segment: bool,
3244    ) -> Result<Partial<'input, BORROW>> {
3245        log::trace!(
3246            "Initializing missing optional field '{}' via solver path {:?}",
3247            field_info.serialized_name,
3248            field_info.path
3249        );
3250        let segments = field_info.path.segments();
3251        if segments.is_empty() {
3252            return Self::apply_default_for_field(wip, field_info.field);
3253        }
3254
3255        #[allow(unused_mut, unused_variables)]
3256        let mut guards: Vec<PathGuard> = Vec::new();
3257
3258        for (idx, segment) in segments
3259            .iter()
3260            .take(segments.len().saturating_sub(1))
3261            .enumerate()
3262        {
3263            if skip_first_segment && idx == 0 {
3264                continue;
3265            }
3266            match segment {
3267                PathSegment::Field(name) => {
3268                    wip = wip.begin_field(name)?;
3269                    let is_option = matches!(wip.shape().def, Def::Option(_));
3270                    if is_option {
3271                        wip = wip.begin_some()?;
3272                    }
3273                    guards.push(PathGuard::Field {
3274                        had_option: is_option,
3275                    });
3276                }
3277                PathSegment::Variant(_, variant_name) => {
3278                    wip = wip.select_variant_named(variant_name)?;
3279                    guards.push(PathGuard::Variant);
3280                }
3281            }
3282        }
3283
3284        wip = Self::apply_default_for_field(wip, field_info.field)?;
3285
3286        while let Some(guard) = guards.pop() {
3287            match guard {
3288                PathGuard::Field { had_option } => {
3289                    if had_option {
3290                        wip = wip.end()?; // Close the inner Some value
3291                    }
3292                    wip = wip.end()?; // Close the field itself
3293                }
3294                PathGuard::Variant => {}
3295            }
3296        }
3297
3298        Ok(wip)
3299    }
3300
3301    fn apply_defaults_for_segment(
3302        &mut self,
3303        mut wip: Partial<'input, BORROW>,
3304        segment_name: &str,
3305        defaults_by_first_segment: &mut BTreeMap<&str, Vec<&FieldInfo>>,
3306    ) -> Result<Partial<'input, BORROW>> {
3307        if let Some(entries) = defaults_by_first_segment.remove(segment_name) {
3308            for info in entries {
3309                wip = self.set_missing_field_default(wip, info, true)?;
3310            }
3311        }
3312        Ok(wip)
3313    }
3314
3315    fn apply_default_for_field(
3316        mut wip: Partial<'input, BORROW>,
3317        target_field: &'static facet_core::Field,
3318    ) -> Result<Partial<'input, BORROW>> {
3319        let struct_def = match &wip.shape().ty {
3320            Type::User(UserType::Struct(def)) => def,
3321            _ => {
3322                return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
3323                    message: format!(
3324                        "expected struct while setting default for field '{}'",
3325                        target_field.name
3326                    ),
3327                }));
3328            }
3329        };
3330
3331        let Some(idx) = struct_def
3332            .fields
3333            .iter()
3334            .position(|field| ptr::eq(field, target_field))
3335        else {
3336            return Err(JsonError::without_span(JsonErrorKind::InvalidValue {
3337                message: format!(
3338                    "could not find field '{}' while applying default",
3339                    target_field.name
3340                ),
3341            }));
3342        };
3343
3344        if target_field.has_default() {
3345            wip = wip.set_nth_field_to_default(idx)?;
3346        } else if matches!(target_field.shape().def, Def::Option(_)) {
3347            // Option<T> fields can always default to None.
3348            wip = wip.begin_nth_field(idx)?;
3349            wip = wip.set_default()?;
3350            wip = wip.end()?;
3351        } else {
3352            // Fall back to the field type's Default (this will error if unavailable).
3353            wip = wip.set_nth_field_to_default(idx)?;
3354        }
3355
3356        Ok(wip)
3357    }
3358}
3359
3360#[derive(Debug)]
3361enum PathGuard {
3362    Field { had_option: bool },
3363    Variant,
3364}
3365
3366// ============================================================================
3367// Public API
3368// ============================================================================
3369
3370/// Deserialize JSON from a byte slice into an owned type.
3371///
3372/// This is the recommended default for most use cases. The input does not need
3373/// to outlive the result, making it suitable for deserializing from temporary
3374/// buffers (e.g., HTTP request bodies).
3375///
3376/// Types containing `&str` fields cannot be deserialized with this function;
3377/// use `String` or `Cow<str>` instead. For zero-copy deserialization into
3378/// borrowed types, use [`from_slice_borrowed`].
3379///
3380/// Note: For rich error diagnostics with source code display, prefer [`from_str`]
3381/// which can attach the source string to errors.
3382pub fn from_slice<T: Facet<'static>>(input: &[u8]) -> Result<T> {
3383    from_slice_inner(input, None)
3384}
3385
3386/// Deserialize JSON from a UTF-8 string slice into an owned type.
3387///
3388/// This is the recommended default for most use cases. The input does not need
3389/// to outlive the result, making it suitable for deserializing from temporary
3390/// buffers (e.g., HTTP request bodies).
3391///
3392/// Types containing `&str` fields cannot be deserialized with this function;
3393/// use `String` or `Cow<str>` instead. For zero-copy deserialization into
3394/// borrowed types, use [`from_str_borrowed`].
3395///
3396/// Errors from this function include source code context for rich diagnostic display
3397/// when using [`miette`]'s reporting features.
3398pub fn from_str<T: Facet<'static>>(input: &str) -> Result<T> {
3399    let input_bytes = input.as_bytes();
3400
3401    // Handle BOM
3402    if input_bytes.starts_with(&[0xef, 0xbb, 0xbf]) {
3403        return from_slice_inner(&input_bytes[3..], Some(&input[3..]));
3404    }
3405    from_slice_inner(input_bytes, Some(input))
3406}
3407
3408/// Deserialize JSON from a byte slice, allowing zero-copy borrowing.
3409///
3410/// This variant requires the input to outlive the result (`'input: 'facet`),
3411/// enabling zero-copy deserialization of string fields as `&str`.
3412///
3413/// Use this when you need maximum performance and can guarantee the input
3414/// buffer outlives the deserialized value. For most use cases, prefer
3415/// [`from_slice`] which doesn't have lifetime requirements.
3416///
3417/// Note: For rich error diagnostics with source code display, prefer [`from_str_borrowed`]
3418/// which can attach the source string to errors.
3419pub fn from_slice_borrowed<'input, 'facet, T: Facet<'facet>>(input: &'input [u8]) -> Result<T>
3420where
3421    'input: 'facet,
3422{
3423    from_slice_borrowed_inner(input, None)
3424}
3425
3426/// Deserialize JSON from a UTF-8 string slice, allowing zero-copy borrowing.
3427///
3428/// This variant requires the input to outlive the result (`'input: 'facet`),
3429/// enabling zero-copy deserialization of string fields as `&str`.
3430///
3431/// Use this when you need maximum performance and can guarantee the input
3432/// buffer outlives the deserialized value. For most use cases, prefer
3433/// [`from_str`] which doesn't have lifetime requirements.
3434///
3435/// Errors from this function include source code context for rich diagnostic display
3436/// when using [`miette`]'s reporting features.
3437pub fn from_str_borrowed<'input, 'facet, T: Facet<'facet>>(input: &'input str) -> Result<T>
3438where
3439    'input: 'facet,
3440{
3441    let input_bytes = input.as_bytes();
3442
3443    // Handle BOM
3444    if input_bytes.starts_with(&[0xef, 0xbb, 0xbf]) {
3445        return from_slice_borrowed_inner(&input_bytes[3..], Some(&input[3..]));
3446    }
3447    from_slice_borrowed_inner(input_bytes, Some(input))
3448}
3449
3450fn from_slice_borrowed_inner<'input, 'facet, T: Facet<'facet>>(
3451    input: &'input [u8],
3452    source: Option<&str>,
3453) -> Result<T>
3454where
3455    'input: 'facet,
3456{
3457    let mut deserializer = JsonDeserializer::new(input);
3458    let wip = Partial::alloc::<T>()?;
3459
3460    let partial = match deserializer.deserialize_into(wip) {
3461        Ok(p) => p,
3462        Err(e) => return Err(attach_source_cold(e, source)),
3463    };
3464
3465    // Check that we've consumed all input (no trailing data after the root value)
3466    let trailing = deserializer.peek()?;
3467    if !matches!(trailing.token, Token::Eof) {
3468        let mut err = JsonError::new(
3469            JsonErrorKind::UnexpectedToken {
3470                got: format!("{:?}", trailing.token),
3471                expected: "end of input",
3472            },
3473            trailing.span,
3474        );
3475        if let Some(src) = source {
3476            err.source_code = Some(src.to_string());
3477        }
3478        return Err(err);
3479    }
3480
3481    // Build and materialize the Partial into the target type
3482    let heap_value = match partial.build() {
3483        Ok(v) => v,
3484        Err(e) => return Err(attach_source_cold(JsonError::from(e), source)),
3485    };
3486
3487    match heap_value.materialize::<T>() {
3488        Ok(v) => Ok(v),
3489        Err(e) => Err(attach_source_cold(JsonError::from(e), source)),
3490    }
3491}
3492
3493fn from_slice_inner<T: Facet<'static>>(input: &[u8], source: Option<&str>) -> Result<T> {
3494    // We need to work around the lifetime constraints in the deserialization machinery.
3495    // The deserializer and Partial are parameterized by 'input (the input slice lifetime),
3496    // but we want to produce a T: Facet<'static> that doesn't borrow from input.
3497    //
3498    // The approach: Use an inner function parameterized by 'input that does all the work,
3499    // then transmute the result back to the 'static lifetime we need.
3500    //
3501    // SAFETY: This is safe because:
3502    // 1. T: Facet<'static> guarantees the type T itself contains no borrowed data
3503    // 2. allow_borrow: false ensures we error before storing any borrowed references
3504    // 3. BORROW: false on Partial/HeapValue documents that no borrowing occurs
3505    // 4. The transmutes only affect phantom lifetime markers, not actual runtime data
3506
3507    fn inner<'input, T: Facet<'static>>(input: &'input [u8], source: Option<&str>) -> Result<T> {
3508        let mut deserializer = JsonDeserializer::new_owned(input);
3509
3510        // Allocate a Partial<'static, false> - owned mode, no borrowing allowed.
3511        // We transmute to Partial<'input, false> to work with the deserializer.
3512        // SAFETY: We're only changing the lifetime marker. The Partial<_, false> doesn't
3513        // store any 'input references because:
3514        // - BORROW=false documents no borrowed data
3515        // - allow_borrow=false on deserializer prevents runtime borrowing
3516        #[allow(unsafe_code)]
3517        let wip: Partial<'input, false> = unsafe {
3518            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
3519                Partial::alloc_owned::<T>()?,
3520            )
3521        };
3522
3523        let partial = match deserializer.deserialize_into(wip) {
3524            Ok(p) => p,
3525            Err(e) => return Err(attach_source_cold(e, source)),
3526        };
3527
3528        // Check that we've consumed all input (no trailing data after the root value)
3529        let trailing = deserializer.peek()?;
3530        if !matches!(trailing.token, Token::Eof) {
3531            let mut err = JsonError::new(
3532                JsonErrorKind::UnexpectedToken {
3533                    got: format!("{:?}", trailing.token),
3534                    expected: "end of input",
3535                },
3536                trailing.span,
3537            );
3538            if let Some(src) = source {
3539                err.source_code = Some(src.to_string());
3540            }
3541            return Err(err);
3542        }
3543
3544        // Build the Partial into a HeapValue
3545        let heap_value = match partial.build() {
3546            Ok(v) => v,
3547            Err(e) => return Err(attach_source_cold(JsonError::from(e), source)),
3548        };
3549
3550        // Transmute HeapValue<'input, false> to HeapValue<'static, false> so we can materialize to T
3551        // SAFETY: The HeapValue contains no borrowed data:
3552        // - BORROW=false documents no borrowed data
3553        // - allow_borrow=false ensured this at runtime
3554        // The transmute only affects the phantom lifetime marker.
3555        #[allow(unsafe_code)]
3556        let heap_value: facet_reflect::HeapValue<'static, false> = unsafe {
3557            core::mem::transmute::<
3558                facet_reflect::HeapValue<'input, false>,
3559                facet_reflect::HeapValue<'static, false>,
3560            >(heap_value)
3561        };
3562
3563        match heap_value.materialize::<T>() {
3564            Ok(v) => Ok(v),
3565            Err(e) => Err(attach_source_cold(JsonError::from(e), source)),
3566        }
3567    }
3568
3569    inner::<T>(input, source)
3570}