facet_format/
deserializer.rs

1extern crate alloc;
2
3use alloc::borrow::Cow;
4use alloc::format;
5use alloc::string::String;
6use core::fmt;
7
8use facet_core::{
9    Def, Facet, KnownPointer, NumericType, PrimitiveType, StructKind, Type, UserType,
10};
11pub use facet_path::{Path, PathStep};
12use facet_reflect::{HeapValue, Partial, ReflectError, Resolution, is_spanned_shape};
13
14use crate::{
15    ContainerKind, FieldLocationHint, FormatParser, ParseEvent, ScalarTypeHint, ScalarValue,
16};
17
18/// Result of variant lookup for HTML/XML elements.
19enum VariantMatch {
20    /// Direct match: a variant with matching rename attribute.
21    Direct(usize),
22    /// Custom element fallback: a variant with `html::custom_element` or `xml::custom_element`.
23    CustomElement(usize),
24}
25
26/// Generic deserializer that drives a format-specific parser directly into `Partial`.
27///
28/// The const generic `BORROW` controls whether string data can be borrowed:
29/// - `BORROW=true`: strings without escapes are borrowed from input
30/// - `BORROW=false`: all strings are owned
31pub struct FormatDeserializer<'input, const BORROW: bool, P> {
32    parser: P,
33    /// The span of the most recently consumed event (for error reporting).
34    last_span: Option<facet_reflect::Span>,
35    /// Current path through the type structure (for error reporting).
36    current_path: Path,
37    _marker: core::marker::PhantomData<&'input ()>,
38}
39
40impl<'input, P> FormatDeserializer<'input, true, P> {
41    /// Create a new deserializer that can borrow strings from input.
42    pub const fn new(parser: P) -> Self {
43        Self {
44            parser,
45            last_span: None,
46            current_path: Path::new(),
47            _marker: core::marker::PhantomData,
48        }
49    }
50}
51
52impl<'input, P> FormatDeserializer<'input, false, P> {
53    /// Create a new deserializer that produces owned strings.
54    pub const fn new_owned(parser: P) -> Self {
55        Self {
56            parser,
57            last_span: None,
58            current_path: Path::new(),
59            _marker: core::marker::PhantomData,
60        }
61    }
62}
63
64impl<'input, const BORROW: bool, P> FormatDeserializer<'input, BORROW, P> {
65    /// Consume the facade and return the underlying parser.
66    pub fn into_inner(self) -> P {
67        self.parser
68    }
69
70    /// Borrow the inner parser mutably.
71    pub fn parser_mut(&mut self) -> &mut P {
72        &mut self.parser
73    }
74}
75
76impl<'input, P> FormatDeserializer<'input, true, P>
77where
78    P: FormatParser<'input>,
79{
80    /// Deserialize the next value in the stream into `T`, allowing borrowed strings.
81    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
82    where
83        T: Facet<'input>,
84    {
85        let wip: Partial<'input, true> =
86            Partial::alloc::<T>().map_err(DeserializeError::reflect)?;
87        let partial = self.deserialize_into(wip)?;
88        let heap_value: HeapValue<'input, true> =
89            partial.build().map_err(DeserializeError::reflect)?;
90        heap_value
91            .materialize::<T>()
92            .map_err(DeserializeError::reflect)
93    }
94
95    /// Deserialize the next value in the stream into `T` (for backward compatibility).
96    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
97    where
98        T: Facet<'input>,
99    {
100        self.deserialize()
101    }
102
103    /// Deserialize using deferred mode, allowing interleaved field initialization.
104    ///
105    /// This is required for formats like TOML that allow table reopening, where
106    /// fields of a nested struct may be set, then fields of a sibling, then more
107    /// fields of the original struct.
108    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
109    where
110        T: Facet<'input>,
111    {
112        let wip: Partial<'input, true> =
113            Partial::alloc::<T>().map_err(DeserializeError::reflect)?;
114        let wip = wip
115            .begin_deferred(Resolution::new())
116            .map_err(DeserializeError::reflect)?;
117        let partial = self.deserialize_into(wip)?;
118        let partial = partial
119            .finish_deferred()
120            .map_err(DeserializeError::reflect)?;
121        let heap_value: HeapValue<'input, true> =
122            partial.build().map_err(DeserializeError::reflect)?;
123        heap_value
124            .materialize::<T>()
125            .map_err(DeserializeError::reflect)
126    }
127}
128
129impl<'input, P> FormatDeserializer<'input, false, P>
130where
131    P: FormatParser<'input>,
132{
133    /// Deserialize the next value in the stream into `T`, using owned strings.
134    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
135    where
136        T: Facet<'static>,
137    {
138        // SAFETY: alloc_owned produces Partial<'static, false>, but our deserializer
139        // expects 'input. Since BORROW=false means we never borrow from input anyway,
140        // this is safe. We also transmute the HeapValue back to 'static before materializing.
141        #[allow(unsafe_code)]
142        let wip: Partial<'input, false> = unsafe {
143            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
144                Partial::alloc_owned::<T>().map_err(DeserializeError::reflect)?,
145            )
146        };
147        let partial = self.deserialize_into(wip)?;
148        let heap_value: HeapValue<'input, false> =
149            partial.build().map_err(DeserializeError::reflect)?;
150
151        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
152        // The transmute only changes the phantom lifetime marker.
153        #[allow(unsafe_code)]
154        let heap_value: HeapValue<'static, false> = unsafe {
155            core::mem::transmute::<HeapValue<'input, false>, HeapValue<'static, false>>(heap_value)
156        };
157
158        heap_value
159            .materialize::<T>()
160            .map_err(DeserializeError::reflect)
161    }
162
163    /// Deserialize the next value in the stream into `T` (for backward compatibility).
164    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
165    where
166        T: Facet<'static>,
167    {
168        self.deserialize()
169    }
170
171    /// Deserialize using deferred mode, allowing interleaved field initialization.
172    ///
173    /// This is required for formats like TOML that allow table reopening, where
174    /// fields of a nested struct may be set, then fields of a sibling, then more
175    /// fields of the original struct.
176    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
177    where
178        T: Facet<'static>,
179    {
180        // SAFETY: alloc_owned produces Partial<'static, false>, but our deserializer
181        // expects 'input. Since BORROW=false means we never borrow from input anyway,
182        // this is safe. We also transmute the HeapValue back to 'static before materializing.
183        #[allow(unsafe_code)]
184        let wip: Partial<'input, false> = unsafe {
185            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
186                Partial::alloc_owned::<T>().map_err(DeserializeError::reflect)?,
187            )
188        };
189        let wip = wip
190            .begin_deferred(Resolution::new())
191            .map_err(DeserializeError::reflect)?;
192        let partial = self.deserialize_into(wip)?;
193        let partial = partial
194            .finish_deferred()
195            .map_err(DeserializeError::reflect)?;
196        let heap_value: HeapValue<'input, false> =
197            partial.build().map_err(DeserializeError::reflect)?;
198
199        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
200        // The transmute only changes the phantom lifetime marker.
201        #[allow(unsafe_code)]
202        let heap_value: HeapValue<'static, false> = unsafe {
203            core::mem::transmute::<HeapValue<'input, false>, HeapValue<'static, false>>(heap_value)
204        };
205
206        heap_value
207            .materialize::<T>()
208            .map_err(DeserializeError::reflect)
209    }
210}
211
212impl<'input, const BORROW: bool, P> FormatDeserializer<'input, BORROW, P>
213where
214    P: FormatParser<'input>,
215{
216    /// Read the next event, returning an error if EOF is reached.
217    #[inline]
218    fn expect_event(
219        &mut self,
220        expected: &'static str,
221    ) -> Result<ParseEvent<'input>, DeserializeError<P::Error>> {
222        let event = self
223            .parser
224            .next_event()
225            .map_err(DeserializeError::Parser)?
226            .ok_or(DeserializeError::UnexpectedEof { expected })?;
227        // Capture the span of the consumed event for error reporting
228        self.last_span = self.parser.current_span();
229        Ok(event)
230    }
231
232    /// Peek at the next event, returning an error if EOF is reached.
233    #[inline]
234    fn expect_peek(
235        &mut self,
236        expected: &'static str,
237    ) -> Result<ParseEvent<'input>, DeserializeError<P::Error>> {
238        self.parser
239            .peek_event()
240            .map_err(DeserializeError::Parser)?
241            .ok_or(DeserializeError::UnexpectedEof { expected })
242    }
243
244    /// Push a step onto the current path (for error reporting).
245    #[inline]
246    fn push_path(&mut self, step: PathStep) {
247        self.current_path.push(step);
248    }
249
250    /// Pop the last step from the current path.
251    #[inline]
252    fn pop_path(&mut self) {
253        self.current_path.pop();
254    }
255
256    /// Get a clone of the current path (for attaching to errors).
257    #[inline]
258    fn path_clone(&self) -> Path {
259        self.current_path.clone()
260    }
261
262    /// Main deserialization entry point - deserialize into a Partial.
263    pub fn deserialize_into(
264        &mut self,
265        mut wip: Partial<'input, BORROW>,
266    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
267        let shape = wip.shape();
268
269        // Check for raw capture type (e.g., RawJson)
270        // Raw capture types are tuple structs with a single Cow<str> field
271        // If capture_raw returns None (e.g., streaming mode), fall through
272        // and try normal deserialization (which will likely fail with a helpful error)
273        if self.parser.raw_capture_shape() == Some(shape)
274            && let Some(raw) = self
275                .parser
276                .capture_raw()
277                .map_err(DeserializeError::Parser)?
278        {
279            // The raw type is a tuple struct like RawJson(Cow<str>)
280            // Access field 0 (the Cow<str>) and set it
281            wip = wip.begin_nth_field(0).map_err(DeserializeError::reflect)?;
282            wip = self.set_string_value(wip, Cow::Borrowed(raw))?;
283            wip = wip.end().map_err(DeserializeError::reflect)?;
284            return Ok(wip);
285        }
286
287        // Check for container-level proxy
288        let (wip_returned, has_proxy) = wip
289            .begin_custom_deserialization_from_shape()
290            .map_err(DeserializeError::reflect)?;
291        wip = wip_returned;
292        if has_proxy {
293            wip = self.deserialize_into(wip)?;
294            return wip.end().map_err(DeserializeError::reflect);
295        }
296
297        // Check for field-level proxy (opaque types with proxy attribute)
298        if wip
299            .parent_field()
300            .and_then(|field| field.proxy_convert_in_fn())
301            .is_some()
302        {
303            wip = wip
304                .begin_custom_deserialization()
305                .map_err(DeserializeError::reflect)?;
306            wip = self.deserialize_into(wip)?;
307            wip = wip.end().map_err(DeserializeError::reflect)?;
308            return Ok(wip);
309        }
310
311        // Check Def first for Option
312        if matches!(&shape.def, Def::Option(_)) {
313            return self.deserialize_option(wip);
314        }
315
316        // Check Def for Result - treat it as a 2-variant enum
317        if matches!(&shape.def, Def::Result(_)) {
318            return self.deserialize_result_as_enum(wip);
319        }
320
321        // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
322        if shape.builder_shape.is_some() {
323            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
324            wip = self.deserialize_into(wip)?;
325            wip = wip.end().map_err(DeserializeError::reflect)?;
326            return Ok(wip);
327        }
328
329        // Priority 2: Check for smart pointers (Box, Arc, Rc)
330        if matches!(&shape.def, Def::Pointer(_)) {
331            return self.deserialize_pointer(wip);
332        }
333
334        // Priority 3: Check for .inner (transparent wrappers like NonZero)
335        // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
336        // Opaque scalars (like ULID) may have .inner for documentation but should NOT be
337        // deserialized as transparent wrappers - they use hint_opaque_scalar instead
338        let is_opaque_scalar =
339            matches!(shape.def, Def::Scalar) && matches!(shape.ty, Type::User(UserType::Opaque));
340        if shape.inner.is_some()
341            && !is_opaque_scalar
342            && !matches!(
343                &shape.def,
344                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
345            )
346        {
347            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
348            wip = self.deserialize_into(wip)?;
349            wip = wip.end().map_err(DeserializeError::reflect)?;
350            return Ok(wip);
351        }
352
353        // Priority 4: Check for metadata-annotated types (like Spanned<T>)
354        if is_spanned_shape(shape) {
355            return self.deserialize_spanned(wip);
356        }
357
358        // Priority 5: Check the Type for structs and enums
359        match &shape.ty {
360            Type::User(UserType::Struct(struct_def)) => {
361                if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
362                    return self.deserialize_tuple(wip);
363                }
364                return self.deserialize_struct(wip);
365            }
366            Type::User(UserType::Enum(_)) => return self.deserialize_enum(wip),
367            _ => {}
368        }
369
370        // Priority 6: Check Def for containers and scalars
371        match &shape.def {
372            Def::Scalar => self.deserialize_scalar(wip),
373            Def::List(_) => self.deserialize_list(wip),
374            Def::Map(_) => self.deserialize_map(wip),
375            Def::Array(_) => self.deserialize_array(wip),
376            Def::Set(_) => self.deserialize_set(wip),
377            Def::DynamicValue(_) => self.deserialize_dynamic_value(wip),
378            _ => Err(DeserializeError::Unsupported(format!(
379                "unsupported shape def: {:?}",
380                shape.def
381            ))),
382        }
383    }
384
385    fn deserialize_option(
386        &mut self,
387        mut wip: Partial<'input, BORROW>,
388    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
389        // Hint to non-self-describing parsers that an Option is expected
390        self.parser.hint_option();
391
392        let event = self.expect_peek("value for option")?;
393
394        if matches!(event, ParseEvent::Scalar(ScalarValue::Null)) {
395            // Consume the null
396            let _ = self.expect_event("null")?;
397            // Set to None (default)
398            wip = wip.set_default().map_err(DeserializeError::reflect)?;
399        } else {
400            // Some(value)
401            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
402            wip = self.deserialize_into(wip)?;
403            wip = wip.end().map_err(DeserializeError::reflect)?;
404        }
405        Ok(wip)
406    }
407
408    fn deserialize_result_as_enum(
409        &mut self,
410        mut wip: Partial<'input, BORROW>,
411    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
412        use facet_core::StructKind;
413
414        // Hint to non-self-describing parsers that a Result enum is expected
415        // Result is encoded as a 2-variant enum: Ok (index 0) and Err (index 1)
416        let variant_hints: Vec<crate::EnumVariantHint> = vec![
417            crate::EnumVariantHint {
418                name: "Ok",
419                kind: StructKind::TupleStruct,
420                field_count: 1,
421            },
422            crate::EnumVariantHint {
423                name: "Err",
424                kind: StructKind::TupleStruct,
425                field_count: 1,
426            },
427        ];
428        self.parser.hint_enum(&variant_hints);
429
430        // Read the StructStart emitted by the parser after hint_enum
431        let event = self.expect_event("struct start for Result")?;
432        if !matches!(event, ParseEvent::StructStart(_)) {
433            return Err(DeserializeError::TypeMismatch {
434                expected: "struct start for Result variant",
435                got: format!("{event:?}"),
436                span: self.last_span,
437                path: None,
438            });
439        }
440
441        // Read the FieldKey with the variant name ("Ok" or "Err")
442        let key_event = self.expect_event("variant key for Result")?;
443        let variant_name = match key_event {
444            ParseEvent::FieldKey(key) => key.name,
445            other => {
446                return Err(DeserializeError::TypeMismatch {
447                    expected: "field key with variant name",
448                    got: format!("{other:?}"),
449                    span: self.last_span,
450                    path: None,
451                });
452            }
453        };
454
455        // Select the appropriate variant and deserialize its content
456        if variant_name == "Ok" {
457            wip = wip.begin_ok().map_err(DeserializeError::reflect)?;
458        } else if variant_name == "Err" {
459            wip = wip.begin_err().map_err(DeserializeError::reflect)?;
460        } else {
461            return Err(DeserializeError::TypeMismatch {
462                expected: "Ok or Err variant",
463                got: alloc::format!("variant '{}'", variant_name),
464                span: self.last_span,
465                path: None,
466            });
467        }
468
469        // Deserialize the variant's value (newtype pattern - single field)
470        wip = self.deserialize_into(wip)?;
471        wip = wip.end().map_err(DeserializeError::reflect)?;
472
473        // Consume StructEnd
474        let end_event = self.expect_event("struct end for Result")?;
475        if !matches!(end_event, ParseEvent::StructEnd) {
476            return Err(DeserializeError::TypeMismatch {
477                expected: "struct end for Result variant",
478                got: format!("{end_event:?}"),
479                span: self.last_span,
480                path: None,
481            });
482        }
483
484        Ok(wip)
485    }
486
487    fn deserialize_pointer(
488        &mut self,
489        mut wip: Partial<'input, BORROW>,
490    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
491        use facet_core::KnownPointer;
492
493        let shape = wip.shape();
494        let is_cow = if let Def::Pointer(ptr_def) = shape.def {
495            matches!(ptr_def.known, Some(KnownPointer::Cow))
496        } else {
497            false
498        };
499
500        if is_cow {
501            // Cow<str> - handle specially to preserve borrowing
502            if let Def::Pointer(ptr_def) = shape.def
503                && let Some(pointee) = ptr_def.pointee()
504                && pointee.type_identifier == "str"
505            {
506                // Hint to non-self-describing parsers that a string is expected
507                self.parser.hint_scalar_type(ScalarTypeHint::String);
508                let event = self.expect_event("string for Cow<str>")?;
509                match event {
510                    ParseEvent::Scalar(ScalarValue::Str(s))
511                    | ParseEvent::Scalar(ScalarValue::StringlyTyped(s)) => {
512                        // Pass through the Cow as-is to preserve borrowing
513                        wip = wip.set(s).map_err(DeserializeError::reflect)?;
514                        return Ok(wip);
515                    }
516                    _ => {
517                        return Err(DeserializeError::TypeMismatch {
518                            expected: "string for Cow<str>",
519                            got: format!("{event:?}"),
520                            span: self.last_span,
521                            path: None,
522                        });
523                    }
524                }
525            }
526            // Cow<[u8]> - handle specially to preserve borrowing
527            if let Def::Pointer(ptr_def) = shape.def
528                && let Some(pointee) = ptr_def.pointee()
529                && let Def::Slice(slice_def) = pointee.def
530                && slice_def.t.type_identifier == "u8"
531            {
532                // Hint to non-self-describing parsers that bytes are expected
533                self.parser.hint_scalar_type(ScalarTypeHint::Bytes);
534                let event = self.expect_event("bytes for Cow<[u8]>")?;
535                if let ParseEvent::Scalar(ScalarValue::Bytes(b)) = event {
536                    // Pass through the Cow as-is to preserve borrowing
537                    wip = wip.set(b).map_err(DeserializeError::reflect)?;
538                    return Ok(wip);
539                } else {
540                    return Err(DeserializeError::TypeMismatch {
541                        expected: "bytes for Cow<[u8]>",
542                        got: format!("{event:?}"),
543                        span: self.last_span,
544                        path: None,
545                    });
546                }
547            }
548            // Other Cow types - use begin_inner
549            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
550            wip = self.deserialize_into(wip)?;
551            wip = wip.end().map_err(DeserializeError::reflect)?;
552            return Ok(wip);
553        }
554
555        // &str - handle specially for zero-copy borrowing
556        if let Def::Pointer(ptr_def) = shape.def
557            && matches!(ptr_def.known, Some(KnownPointer::SharedReference))
558            && ptr_def
559                .pointee()
560                .is_some_and(|p| p.type_identifier == "str")
561        {
562            // Hint to non-self-describing parsers that a string is expected
563            self.parser.hint_scalar_type(ScalarTypeHint::String);
564            let event = self.expect_event("string for &str")?;
565            match event {
566                ParseEvent::Scalar(ScalarValue::Str(s))
567                | ParseEvent::Scalar(ScalarValue::StringlyTyped(s)) => {
568                    return self.set_string_value(wip, s);
569                }
570                _ => {
571                    return Err(DeserializeError::TypeMismatch {
572                        expected: "string for &str",
573                        got: format!("{event:?}"),
574                        span: self.last_span,
575                        path: None,
576                    });
577                }
578            }
579        }
580
581        // &[u8] - handle specially for zero-copy borrowing
582        if let Def::Pointer(ptr_def) = shape.def
583            && matches!(ptr_def.known, Some(KnownPointer::SharedReference))
584            && let Some(pointee) = ptr_def.pointee()
585            && let Def::Slice(slice_def) = pointee.def
586            && slice_def.t.type_identifier == "u8"
587        {
588            // Hint to non-self-describing parsers that bytes are expected
589            self.parser.hint_scalar_type(ScalarTypeHint::Bytes);
590            let event = self.expect_event("bytes for &[u8]")?;
591            if let ParseEvent::Scalar(ScalarValue::Bytes(b)) = event {
592                return self.set_bytes_value(wip, b);
593            } else {
594                return Err(DeserializeError::TypeMismatch {
595                    expected: "bytes for &[u8]",
596                    got: format!("{event:?}"),
597                    span: self.last_span,
598                    path: None,
599                });
600            }
601        }
602
603        // Regular smart pointer (Box, Arc, Rc)
604        wip = wip.begin_smart_ptr().map_err(DeserializeError::reflect)?;
605
606        // Check if begin_smart_ptr set up a slice builder (for Arc<[T]>, Rc<[T]>, Box<[T]>)
607        // In this case, we need to deserialize as a list manually
608        let is_slice_builder = wip.is_building_smart_ptr_slice();
609
610        if is_slice_builder {
611            // Deserialize the list elements into the slice builder
612            // We can't use deserialize_list() because it calls begin_list() which interferes
613            // Hint to non-self-describing parsers that a sequence is expected
614            self.parser.hint_sequence();
615            let event = self.expect_event("value")?;
616
617            // Accept either SequenceStart (JSON arrays) or StructStart (XML elements)
618            // Only accept StructStart if the container kind is ambiguous (e.g., XML Element)
619            let struct_mode = match event {
620                ParseEvent::SequenceStart(_) => false,
621                ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
622                ParseEvent::StructStart(kind) => {
623                    return Err(DeserializeError::TypeMismatch {
624                        expected: "array",
625                        got: kind.name().into(),
626                        span: self.last_span,
627                        path: None,
628                    });
629                }
630                _ => {
631                    return Err(DeserializeError::TypeMismatch {
632                        expected: "sequence start for Arc<[T]>/Rc<[T]>/Box<[T]>",
633                        got: format!("{event:?}"),
634                        span: self.last_span,
635                        path: None,
636                    });
637                }
638            };
639
640            loop {
641                let event = self.expect_peek("value")?;
642
643                // Check for end of container
644                if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
645                    self.expect_event("value")?;
646                    break;
647                }
648
649                // In struct mode, skip FieldKey events
650                if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
651                    self.expect_event("value")?;
652                    continue;
653                }
654
655                wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
656                wip = self.deserialize_into(wip)?;
657                wip = wip.end().map_err(DeserializeError::reflect)?;
658            }
659
660            // Convert the slice builder to Arc/Rc/Box and mark as initialized
661            wip = wip.end().map_err(DeserializeError::reflect)?;
662            // DON'T call end() again - the caller (deserialize_struct) will do that
663        } else {
664            // Regular smart pointer with sized pointee
665            wip = self.deserialize_into(wip)?;
666            wip = wip.end().map_err(DeserializeError::reflect)?;
667        }
668
669        Ok(wip)
670    }
671
672    /// Check if a field matches the given name, namespace, and location constraints.
673    ///
674    /// This implements format-specific field matching for XML and KDL:
675    ///
676    /// Check if a type can be deserialized directly from a scalar value.
677    ///
678    /// This is used for KDL child nodes that contain only a single argument value,
679    /// allowing `#[facet(kdl::child)]` to work on primitive types like `bool`, `u64`, `String`.
680    fn is_scalar_compatible_type(shape: &facet_core::Shape) -> bool {
681        match &shape.def {
682            Def::Scalar => true,
683            Def::Option(opt) => Self::is_scalar_compatible_type(opt.t),
684            Def::Pointer(ptr) => ptr.pointee.is_some_and(Self::is_scalar_compatible_type),
685            _ => {
686                // Also check for transparent wrappers (newtypes)
687                if !matches!(
688                    &shape.def,
689                    Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
690                ) && let Some(inner) = shape.inner
691                {
692                    return Self::is_scalar_compatible_type(inner);
693                }
694                false
695            }
696        }
697    }
698
699    /// Deserialize a KDL child node that contains only a scalar argument into a scalar type.
700    ///
701    /// When a KDL node like `enabled #true` is parsed, it generates:
702    /// - `StructStart`
703    /// - `FieldKey("_node_name", Argument)` → `Scalar("enabled")`
704    /// - `FieldKey("_arg", Argument)` → `Scalar(true)`  ← this is what we want
705    /// - `StructEnd`
706    ///
707    /// This method consumes those events and extracts the scalar value.
708    fn deserialize_kdl_child_scalar(
709        &mut self,
710        mut wip: Partial<'input, BORROW>,
711    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
712        // Consume the StructStart
713        let event = self.expect_event("struct start for kdl child")?;
714        if !matches!(event, ParseEvent::StructStart(_)) {
715            return Err(DeserializeError::TypeMismatch {
716                expected: "struct start for kdl child node",
717                got: format!("{event:?}"),
718                span: self.last_span,
719                path: None,
720            });
721        }
722
723        // Scan through the struct looking for _arg (single argument) or first argument
724        let mut found_scalar: Option<ScalarValue<'input>> = None;
725
726        loop {
727            let event = self.expect_event("field or struct end for kdl child")?;
728            match event {
729                ParseEvent::StructEnd => break,
730                ParseEvent::FieldKey(key) => {
731                    // Check if this is the argument field we're looking for
732                    if key.location == FieldLocationHint::Argument
733                        && (key.name == "_arg" || key.name == "0")
734                    {
735                        // Next event should be the scalar value
736                        let value_event = self.expect_event("scalar value for kdl child")?;
737                        if let ParseEvent::Scalar(scalar) = value_event {
738                            found_scalar = Some(scalar);
739                        } else {
740                            return Err(DeserializeError::TypeMismatch {
741                                expected: "scalar value for kdl::child primitive",
742                                got: format!("{value_event:?}"),
743                                span: self.last_span,
744                                path: None,
745                            });
746                        }
747                    } else {
748                        // Skip this field's value (could be _node_name, _arguments, etc.)
749                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
750                    }
751                }
752                other => {
753                    return Err(DeserializeError::TypeMismatch {
754                        expected: "field key or struct end for kdl child",
755                        got: format!("{other:?}"),
756                        span: self.last_span,
757                        path: None,
758                    });
759                }
760            }
761        }
762
763        // Now deserialize the scalar value into the target type
764        if let Some(scalar) = found_scalar {
765            // Handle Option<T> types - we need to wrap the value in Some
766            if matches!(&wip.shape().def, Def::Option(_)) {
767                wip = wip.begin_some().map_err(DeserializeError::reflect)?;
768                wip = self.set_scalar(wip, scalar)?;
769                wip = wip.end().map_err(DeserializeError::reflect)?;
770            } else {
771                wip = self.set_scalar(wip, scalar)?;
772            }
773            Ok(wip)
774        } else {
775            Err(DeserializeError::TypeMismatch {
776                expected: "argument value in kdl::child node",
777                got: "no argument found".to_string(),
778                span: self.last_span,
779                path: None,
780            })
781        }
782    }
783
784    /// **XML matching:**
785    /// - Text: Match fields with xml::text attribute (name is ignored - text content goes to the field)
786    /// - Attributes: Only match if explicit xml::ns matches (no ns_all inheritance per XML spec)
787    /// - Elements: Match if explicit xml::ns OR ns_all matches
788    ///
789    /// **KDL matching:**
790    /// - Argument: Match fields with kdl::argument attribute
791    /// - Property: Match fields with kdl::property attribute
792    /// - Child: Match fields with kdl::child or kdl::children attribute
793    ///
794    /// **Default (KeyValue):** Match by name/alias only (backwards compatible)
795    ///
796    /// TODO: This function hardcodes knowledge of XML and KDL attributes.
797    /// See <https://github.com/facet-rs/facet/issues/1506> for discussion on
798    /// making this more extensible.
799    fn field_matches_with_namespace(
800        field: &facet_core::Field,
801        name: &str,
802        namespace: Option<&str>,
803        location: FieldLocationHint,
804        ns_all: Option<&str>,
805    ) -> bool {
806        // === XML/HTML: Fields with xml::attribute match only attributes
807        if field.is_attribute() && !matches!(location, FieldLocationHint::Attribute) {
808            return false;
809        }
810
811        // === XML/HTML: Fields with xml::element/elements match only child elements
812        // === KDL: Fields with kdl::child/children match only child nodes
813        if (field.is_element() || field.is_elements())
814            && !matches!(location, FieldLocationHint::Child)
815        {
816            return false;
817        }
818
819        // === XML/HTML: Text location matches fields with text attribute ===
820        // The name "_text" from the parser is ignored - we match by attribute presence
821        if matches!(location, FieldLocationHint::Text) {
822            return field.is_text();
823        }
824
825        // === XML/HTML: Tag location matches fields with html::tag or xml::tag attribute ===
826        // The name "_tag" from the parser is ignored - we match by attribute presence
827        // This allows custom elements to capture the element's tag name
828        if matches!(location, FieldLocationHint::Tag) {
829            return field.is_tag();
830        }
831
832        // === KDL: Node name matching for kdl::node_name attribute ===
833        // The parser emits "_node_name" as the field key for node name
834        if matches!(location, FieldLocationHint::Argument) && name == "_node_name" {
835            return field.is_node_name();
836        }
837
838        // === KDL: Arguments (plural) matching for kdl::arguments attribute ===
839        // The parser emits "_arguments" as the field key for all arguments as a sequence
840        if matches!(location, FieldLocationHint::Argument) && name == "_arguments" {
841            return field.is_arguments_plural();
842        }
843
844        // === KDL: Argument location matches fields with kdl::argument attribute ===
845        // For kdl::argument (singular), we match by attribute presence, not by name
846        // (arguments are positional, name in FieldKey is just "_arg" or index)
847        // Skip fields that want plural (kdl::arguments) - they matched above
848        // If no kdl::argument attr, fall through to name matching
849        if matches!(location, FieldLocationHint::Argument) && field.is_argument() {
850            // Don't match singular _arg to kdl::arguments fields
851            if field.is_arguments_plural() {
852                return false;
853            }
854            return true;
855        }
856
857        // === KDL: Property location matches fields with kdl::property attribute ===
858        // For properties, we need BOTH the attribute AND name match
859        // If no kdl::property attr, fall through to name matching
860        if matches!(location, FieldLocationHint::Property) && field.is_property() {
861            let name_matches = field.name == name || field.alias.iter().any(|alias| *alias == name);
862            return name_matches;
863        }
864
865        // === Check name/alias ===
866        let name_matches = field.name == name || field.alias.iter().any(|alias| *alias == name);
867
868        if !name_matches {
869            return false;
870        }
871
872        // === XML: Namespace matching ===
873        // Get the expected namespace for this field
874        let field_xml_ns = field
875            .get_attr(Some("xml"), "ns")
876            .and_then(|attr| attr.get_as::<&str>().copied());
877
878        // CRITICAL: Attributes don't inherit ns_all (per XML spec)
879        let expected_ns = if matches!(location, FieldLocationHint::Attribute) {
880            field_xml_ns // Attributes: only explicit xml::ns
881        } else {
882            field_xml_ns.or(ns_all) // Elements: xml::ns OR ns_all
883        };
884
885        // Check if namespaces match
886        match (namespace, expected_ns) {
887            (Some(input_ns), Some(expected)) => input_ns == expected,
888            (Some(_input_ns), None) => true, // Input has namespace, field doesn't require one - match
889            (None, Some(_expected)) => false, // Input has no namespace, field requires one - NO match
890            (None, None) => true,             // Neither has namespace - match
891        }
892    }
893
894    /// Run validation on a field value.
895    ///
896    /// This checks for `validate::*` attributes on the field and runs
897    /// the appropriate validators on the deserialized value.
898    #[cfg(feature = "validate")]
899    #[allow(unsafe_code)]
900    fn run_field_validators(
901        &self,
902        field: &facet_core::Field,
903        wip: &Partial<'input, BORROW>,
904    ) -> Result<(), DeserializeError<P::Error>> {
905        use facet_core::ValidatorFn;
906
907        // Get the data pointer from the current frame
908        let Some(data_ptr) = wip.data_ptr() else {
909            return Ok(());
910        };
911
912        // Check for validation attributes
913        for attr in field.attributes.iter() {
914            if attr.ns != Some("validate") {
915                continue;
916            }
917
918            let validation_result: Result<(), String> = match attr.key {
919                "custom" => {
920                    // Custom validators store a ValidatorFn function pointer
921                    let validator_fn = unsafe { *attr.data.ptr().get::<ValidatorFn>() };
922                    unsafe { validator_fn(data_ptr) }
923                }
924                "min" => {
925                    let min_val = unsafe { *attr.data.ptr().get::<i64>() };
926                    self.validate_min(data_ptr, wip.shape(), min_val)
927                }
928                "max" => {
929                    let max_val = unsafe { *attr.data.ptr().get::<i64>() };
930                    self.validate_max(data_ptr, wip.shape(), max_val)
931                }
932                "min_length" => {
933                    let min_len = unsafe { *attr.data.ptr().get::<usize>() };
934                    self.validate_min_length(data_ptr, wip.shape(), min_len)
935                }
936                "max_length" => {
937                    let max_len = unsafe { *attr.data.ptr().get::<usize>() };
938                    self.validate_max_length(data_ptr, wip.shape(), max_len)
939                }
940                "email" => self.validate_email(data_ptr, wip.shape()),
941                "url" => self.validate_url(data_ptr, wip.shape()),
942                "regex" => {
943                    let pattern = unsafe { *attr.data.ptr().get::<&'static str>() };
944                    self.validate_regex(data_ptr, wip.shape(), pattern)
945                }
946                "contains" => {
947                    let needle = unsafe { *attr.data.ptr().get::<&'static str>() };
948                    self.validate_contains(data_ptr, wip.shape(), needle)
949                }
950                _ => Ok(()), // Unknown validator, skip
951            };
952
953            if let Err(message) = validation_result {
954                return Err(DeserializeError::Validation {
955                    field: field.name,
956                    message,
957                    span: self.last_span,
958                    path: Some(self.current_path.clone()),
959                });
960            }
961        }
962
963        Ok(())
964    }
965
966    #[cfg(feature = "validate")]
967    #[allow(unsafe_code)]
968    fn validate_min(
969        &self,
970        ptr: facet_core::PtrConst,
971        shape: &'static facet_core::Shape,
972        min_val: i64,
973    ) -> Result<(), String> {
974        use facet_core::ScalarType;
975        let actual = match shape.scalar_type() {
976            Some(ScalarType::I8) => (unsafe { *ptr.get::<i8>() }) as i64,
977            Some(ScalarType::I16) => (unsafe { *ptr.get::<i16>() }) as i64,
978            Some(ScalarType::I32) => (unsafe { *ptr.get::<i32>() }) as i64,
979            Some(ScalarType::I64) => unsafe { *ptr.get::<i64>() },
980            Some(ScalarType::U8) => (unsafe { *ptr.get::<u8>() }) as i64,
981            Some(ScalarType::U16) => (unsafe { *ptr.get::<u16>() }) as i64,
982            Some(ScalarType::U32) => (unsafe { *ptr.get::<u32>() }) as i64,
983            Some(ScalarType::U64) => {
984                let v = unsafe { *ptr.get::<u64>() };
985                if v > i64::MAX as u64 {
986                    return Ok(()); // Value too large to compare, assume valid
987                }
988                v as i64
989            }
990            _ => return Ok(()), // Not a numeric type, skip validation
991        };
992        if actual < min_val {
993            Err(format!("must be >= {}, got {}", min_val, actual))
994        } else {
995            Ok(())
996        }
997    }
998
999    #[cfg(feature = "validate")]
1000    #[allow(unsafe_code)]
1001    fn validate_max(
1002        &self,
1003        ptr: facet_core::PtrConst,
1004        shape: &'static facet_core::Shape,
1005        max_val: i64,
1006    ) -> Result<(), String> {
1007        use facet_core::ScalarType;
1008        let actual = match shape.scalar_type() {
1009            Some(ScalarType::I8) => (unsafe { *ptr.get::<i8>() }) as i64,
1010            Some(ScalarType::I16) => (unsafe { *ptr.get::<i16>() }) as i64,
1011            Some(ScalarType::I32) => (unsafe { *ptr.get::<i32>() }) as i64,
1012            Some(ScalarType::I64) => unsafe { *ptr.get::<i64>() },
1013            Some(ScalarType::U8) => (unsafe { *ptr.get::<u8>() }) as i64,
1014            Some(ScalarType::U16) => (unsafe { *ptr.get::<u16>() }) as i64,
1015            Some(ScalarType::U32) => (unsafe { *ptr.get::<u32>() }) as i64,
1016            Some(ScalarType::U64) => {
1017                let v = unsafe { *ptr.get::<u64>() };
1018                if v > i64::MAX as u64 {
1019                    return Err(format!("must be <= {}, got {}", max_val, v));
1020                }
1021                v as i64
1022            }
1023            _ => return Ok(()), // Not a numeric type, skip validation
1024        };
1025        if actual > max_val {
1026            Err(format!("must be <= {}, got {}", max_val, actual))
1027        } else {
1028            Ok(())
1029        }
1030    }
1031
1032    #[cfg(feature = "validate")]
1033    #[allow(unsafe_code)]
1034    fn validate_min_length(
1035        &self,
1036        ptr: facet_core::PtrConst,
1037        shape: &'static facet_core::Shape,
1038        min_len: usize,
1039    ) -> Result<(), String> {
1040        let len = self.get_length(ptr, shape)?;
1041        if len < min_len {
1042            Err(format!("length must be >= {}, got {}", min_len, len))
1043        } else {
1044            Ok(())
1045        }
1046    }
1047
1048    #[cfg(feature = "validate")]
1049    #[allow(unsafe_code)]
1050    fn validate_max_length(
1051        &self,
1052        ptr: facet_core::PtrConst,
1053        shape: &'static facet_core::Shape,
1054        max_len: usize,
1055    ) -> Result<(), String> {
1056        let len = self.get_length(ptr, shape)?;
1057        if len > max_len {
1058            Err(format!("length must be <= {}, got {}", max_len, len))
1059        } else {
1060            Ok(())
1061        }
1062    }
1063
1064    #[cfg(feature = "validate")]
1065    #[allow(unsafe_code)]
1066    fn get_length(
1067        &self,
1068        ptr: facet_core::PtrConst,
1069        shape: &'static facet_core::Shape,
1070    ) -> Result<usize, String> {
1071        // Check if it's a String
1072        if shape.is_type::<String>() {
1073            let s = unsafe { ptr.get::<String>() };
1074            return Ok(s.len());
1075        }
1076        // Check if it's a &str
1077        if shape.is_type::<&str>() {
1078            let s = unsafe { *ptr.get::<&str>() };
1079            return Ok(s.len());
1080        }
1081        // For Vec and other list types, we'd need to check shape.def
1082        // For now, return 0 for unknown types
1083        Ok(0)
1084    }
1085
1086    #[cfg(feature = "validate")]
1087    #[allow(unsafe_code)]
1088    fn validate_email(
1089        &self,
1090        ptr: facet_core::PtrConst,
1091        shape: &'static facet_core::Shape,
1092    ) -> Result<(), String> {
1093        let s = self.get_string(ptr, shape)?;
1094        if facet_validate::is_valid_email(s) {
1095            Ok(())
1096        } else {
1097            Err(format!("'{}' is not a valid email address", s))
1098        }
1099    }
1100
1101    #[cfg(feature = "validate")]
1102    #[allow(unsafe_code)]
1103    fn validate_url(
1104        &self,
1105        ptr: facet_core::PtrConst,
1106        shape: &'static facet_core::Shape,
1107    ) -> Result<(), String> {
1108        let s = self.get_string(ptr, shape)?;
1109        if facet_validate::is_valid_url(s) {
1110            Ok(())
1111        } else {
1112            Err(format!("'{}' is not a valid URL", s))
1113        }
1114    }
1115
1116    #[cfg(feature = "validate")]
1117    #[allow(unsafe_code)]
1118    fn validate_regex(
1119        &self,
1120        ptr: facet_core::PtrConst,
1121        shape: &'static facet_core::Shape,
1122        pattern: &str,
1123    ) -> Result<(), String> {
1124        let s = self.get_string(ptr, shape)?;
1125        if facet_validate::matches_pattern(s, pattern) {
1126            Ok(())
1127        } else {
1128            Err(format!("'{}' does not match pattern '{}'", s, pattern))
1129        }
1130    }
1131
1132    #[cfg(feature = "validate")]
1133    #[allow(unsafe_code)]
1134    fn validate_contains(
1135        &self,
1136        ptr: facet_core::PtrConst,
1137        shape: &'static facet_core::Shape,
1138        needle: &str,
1139    ) -> Result<(), String> {
1140        let s = self.get_string(ptr, shape)?;
1141        if s.contains(needle) {
1142            Ok(())
1143        } else {
1144            Err(format!("'{}' does not contain '{}'", s, needle))
1145        }
1146    }
1147
1148    #[cfg(feature = "validate")]
1149    #[allow(unsafe_code)]
1150    fn get_string<'s>(
1151        &self,
1152        ptr: facet_core::PtrConst,
1153        shape: &'static facet_core::Shape,
1154    ) -> Result<&'s str, String> {
1155        if shape.is_type::<String>() {
1156            let s = unsafe { ptr.get::<String>() };
1157            return Ok(s.as_str());
1158        }
1159        if shape.is_type::<&str>() {
1160            let s = unsafe { *ptr.get::<&str>() };
1161            return Ok(s);
1162        }
1163        Err("expected string type".to_string())
1164    }
1165
1166    fn deserialize_struct(
1167        &mut self,
1168        wip: Partial<'input, BORROW>,
1169    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1170        // Get struct fields for lookup
1171        let struct_def = match &wip.shape().ty {
1172            Type::User(UserType::Struct(def)) => def,
1173            _ => {
1174                return Err(DeserializeError::Unsupported(format!(
1175                    "expected struct type but got {:?}",
1176                    wip.shape().ty
1177                )));
1178            }
1179        };
1180
1181        // Check if we have any flattened fields
1182        let has_flatten = struct_def.fields.iter().any(|f| f.is_flattened());
1183
1184        if has_flatten {
1185            // Check if any flatten field is an enum (requires solver)
1186            // or if there's nested flatten (flatten inside flatten) that isn't just a map
1187            let needs_solver = struct_def.fields.iter().any(|f| {
1188                if !f.is_flattened() {
1189                    return false;
1190                }
1191                // Get inner type, unwrapping Option if present
1192                let inner_shape = match f.shape().def {
1193                    Def::Option(opt) => opt.t,
1194                    _ => f.shape(),
1195                };
1196                match inner_shape.ty {
1197                    // Enum flatten needs solver
1198                    Type::User(UserType::Enum(_)) => true,
1199                    // Check for nested flatten (flatten field has its own flatten fields)
1200                    // Exclude flattened maps as they just catch unknown keys, not nested fields
1201                    Type::User(UserType::Struct(inner_struct)) => {
1202                        inner_struct.fields.iter().any(|inner_f| {
1203                            inner_f.is_flattened() && {
1204                                let inner_inner_shape = match inner_f.shape().def {
1205                                    Def::Option(opt) => opt.t,
1206                                    _ => inner_f.shape(),
1207                                };
1208                                // Maps don't create nested field structures
1209                                !matches!(inner_inner_shape.def, Def::Map(_))
1210                            }
1211                        })
1212                    }
1213                    _ => false,
1214                }
1215            });
1216
1217            if needs_solver {
1218                self.deserialize_struct_with_flatten(wip)
1219            } else {
1220                // Simple single-level flatten - use the original approach
1221                self.deserialize_struct_single_flatten(wip)
1222            }
1223        } else {
1224            self.deserialize_struct_simple(wip)
1225        }
1226    }
1227
1228    /// Deserialize a struct without flattened fields (simple case).
1229    fn deserialize_struct_simple(
1230        &mut self,
1231        mut wip: Partial<'input, BORROW>,
1232    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1233        use facet_core::Characteristic;
1234
1235        // Get struct fields for lookup (needed before hint)
1236        let struct_def = match &wip.shape().ty {
1237            Type::User(UserType::Struct(def)) => def,
1238            _ => {
1239                return Err(DeserializeError::Unsupported(format!(
1240                    "expected struct type but got {:?}",
1241                    wip.shape().ty
1242                )));
1243            }
1244        };
1245
1246        // Hint to non-self-describing parsers how many fields to expect
1247        self.parser.hint_struct_fields(struct_def.fields.len());
1248
1249        let struct_has_default = wip.shape().has_default_attr();
1250
1251        // Expect StructStart, but for XML/HTML, a scalar means text-only element
1252        let event = self.expect_event("value")?;
1253        if let ParseEvent::Scalar(scalar) = &event {
1254            // For XML/HTML, a text-only element is emitted as a scalar.
1255            // If the struct has a text field, set it from the scalar.
1256            if let Some((idx, _field)) = struct_def
1257                .fields
1258                .iter()
1259                .enumerate()
1260                .find(|(_, f)| f.is_text())
1261            {
1262                wip = wip
1263                    .begin_nth_field(idx)
1264                    .map_err(DeserializeError::reflect)?;
1265
1266                // Handle Option<T>
1267                let is_option = matches!(&wip.shape().def, Def::Option(_));
1268                if is_option {
1269                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
1270                }
1271
1272                wip = self.set_scalar(wip, scalar.clone())?;
1273
1274                if is_option {
1275                    wip = wip.end().map_err(DeserializeError::reflect)?;
1276                }
1277                wip = wip.end().map_err(DeserializeError::reflect)?;
1278
1279                // Set defaults for other fields
1280                for (other_idx, other_field) in struct_def.fields.iter().enumerate() {
1281                    if other_idx == idx {
1282                        continue;
1283                    }
1284
1285                    let field_has_default = other_field.has_default();
1286                    let field_type_has_default =
1287                        other_field.shape().is(facet_core::Characteristic::Default);
1288                    let field_is_option = matches!(other_field.shape().def, Def::Option(_));
1289
1290                    if field_has_default || (struct_has_default && field_type_has_default) {
1291                        wip = wip
1292                            .set_nth_field_to_default(other_idx)
1293                            .map_err(DeserializeError::reflect)?;
1294                    } else if field_is_option {
1295                        wip = wip
1296                            .begin_field(other_field.name)
1297                            .map_err(DeserializeError::reflect)?;
1298                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
1299                        wip = wip.end().map_err(DeserializeError::reflect)?;
1300                    } else if other_field.should_skip_deserializing() {
1301                        wip = wip
1302                            .set_nth_field_to_default(other_idx)
1303                            .map_err(DeserializeError::reflect)?;
1304                    }
1305                    // If a field is required and not set, that's an error, but we'll
1306                    // leave that for the struct-level validation
1307                }
1308
1309                return Ok(wip);
1310            }
1311
1312            // No xml::text field - this is an error
1313            return Err(DeserializeError::TypeMismatch {
1314                expected: "struct start",
1315                got: format!("{event:?}"),
1316                span: self.last_span,
1317                path: None,
1318            });
1319        }
1320
1321        if !matches!(event, ParseEvent::StructStart(_)) {
1322            return Err(DeserializeError::TypeMismatch {
1323                expected: "struct start",
1324                got: format!("{event:?}"),
1325                span: self.last_span,
1326                path: None,
1327            });
1328        }
1329        let deny_unknown_fields = wip.shape().has_deny_unknown_fields_attr();
1330
1331        // Extract container-level default namespace (xml::ns_all) for namespace-aware matching
1332        let ns_all = wip
1333            .shape()
1334            .attributes
1335            .iter()
1336            .find(|attr| attr.ns == Some("xml") && attr.key == "ns_all")
1337            .and_then(|attr| attr.get_as::<&str>().copied());
1338
1339        // Track which fields have been set
1340        let num_fields = struct_def.fields.len();
1341        let mut fields_set = alloc::vec![false; num_fields];
1342        let mut ordered_field_index = 0usize;
1343
1344        // Track xml::elements field state for collecting child elements into lists
1345        // When Some((idx, in_list)), we're collecting items into field at idx
1346        let mut elements_field_state: Option<(usize, bool)> = None;
1347
1348        loop {
1349            let event = self.expect_event("value")?;
1350            match event {
1351                ParseEvent::StructEnd => {
1352                    // End any open xml::elements field
1353                    // Note: begin_list() doesn't push a frame, so we only need to end the field
1354                    if let Some((_, true)) = elements_field_state {
1355                        wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1356                    }
1357                    break;
1358                }
1359                ParseEvent::OrderedField => {
1360                    // Non-self-describing formats emit OrderedField events in order
1361                    let idx = ordered_field_index;
1362                    ordered_field_index += 1;
1363                    if idx < num_fields {
1364                        // Track path for error reporting
1365                        self.push_path(PathStep::Field(idx as u32));
1366
1367                        wip = wip
1368                            .begin_nth_field(idx)
1369                            .map_err(DeserializeError::reflect)?;
1370                        wip = match self.deserialize_into(wip) {
1371                            Ok(wip) => wip,
1372                            Err(e) => {
1373                                // Only add path if error doesn't already have one
1374                                // (inner errors already have more specific paths)
1375                                let result = if e.path().is_some() {
1376                                    e
1377                                } else {
1378                                    let path = self.path_clone();
1379                                    e.with_path(path)
1380                                };
1381                                self.pop_path();
1382                                return Err(result);
1383                            }
1384                        };
1385                        wip = wip.end().map_err(DeserializeError::reflect)?;
1386
1387                        self.pop_path();
1388
1389                        fields_set[idx] = true;
1390                    }
1391                }
1392                ParseEvent::FieldKey(key) => {
1393                    // Look up field in struct fields (direct match)
1394                    // Exclude xml::elements fields - they accumulate repeated child elements
1395                    // and must be handled via find_elements_field_for_element below
1396                    let field_info = struct_def.fields.iter().enumerate().find(|(_, f)| {
1397                        !f.is_elements()
1398                            && Self::field_matches_with_namespace(
1399                                f,
1400                                key.name.as_ref(),
1401                                key.namespace.as_deref(),
1402                                key.location,
1403                                ns_all,
1404                            )
1405                    });
1406
1407                    if let Some((idx, field)) = field_info {
1408                        // End any open xml::elements field before switching to a different field
1409                        // Note: begin_list() doesn't push a frame, so we only end the field
1410                        if let Some((elem_idx, true)) = elements_field_state
1411                            && elem_idx != idx
1412                        {
1413                            wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1414                            elements_field_state = None;
1415                        }
1416
1417                        // Track path for error reporting
1418                        self.push_path(PathStep::Field(idx as u32));
1419
1420                        wip = wip
1421                            .begin_nth_field(idx)
1422                            .map_err(DeserializeError::reflect)?;
1423
1424                        // Special handling for kdl::child with scalar types
1425                        // When a KDL child node contains only a scalar argument (e.g., `enabled #true`),
1426                        // we need to extract the argument value instead of treating it as a struct.
1427                        let use_kdl_child_scalar = key.location == FieldLocationHint::Child
1428                            && field.has_attr(Some("kdl"), "child")
1429                            && Self::is_scalar_compatible_type(wip.shape())
1430                            && matches!(
1431                                self.expect_peek("value for kdl::child field"),
1432                                Ok(ParseEvent::StructStart(_))
1433                            );
1434
1435                        wip = if use_kdl_child_scalar {
1436                            match self.deserialize_kdl_child_scalar(wip) {
1437                                Ok(wip) => wip,
1438                                Err(e) => {
1439                                    let result = if e.path().is_some() {
1440                                        e
1441                                    } else {
1442                                        let path = self.path_clone();
1443                                        e.with_path(path)
1444                                    };
1445                                    self.pop_path();
1446                                    return Err(result);
1447                                }
1448                            }
1449                        } else {
1450                            match self.deserialize_into(wip) {
1451                                Ok(wip) => wip,
1452                                Err(e) => {
1453                                    // Only add path if error doesn't already have one
1454                                    // (inner errors already have more specific paths)
1455                                    let result = if e.path().is_some() {
1456                                        e
1457                                    } else {
1458                                        let path = self.path_clone();
1459                                        e.with_path(path)
1460                                    };
1461                                    self.pop_path();
1462                                    return Err(result);
1463                                }
1464                            }
1465                        };
1466
1467                        // Run validation on the field value before finalizing
1468                        #[cfg(feature = "validate")]
1469                        self.run_field_validators(field, &wip)?;
1470
1471                        wip = wip.end().map_err(DeserializeError::reflect)?;
1472
1473                        self.pop_path();
1474
1475                        fields_set[idx] = true;
1476                        continue;
1477                    }
1478
1479                    // Check if this child element should go into an elements field
1480                    if key.location == FieldLocationHint::Child
1481                        && let Some((idx, field)) = self.find_elements_field_for_element(
1482                            struct_def.fields,
1483                            key.name.as_ref(),
1484                            key.namespace.as_deref(),
1485                            ns_all,
1486                        )
1487                    {
1488                        // Start or continue the list for this elements field
1489                        match elements_field_state {
1490                            None => {
1491                                // Start new list
1492                                wip = wip
1493                                    .begin_nth_field(idx)
1494                                    .map_err(DeserializeError::reflect)?;
1495                                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
1496                                elements_field_state = Some((idx, true));
1497                                fields_set[idx] = true;
1498                            }
1499                            Some((current_idx, true)) if current_idx != idx => {
1500                                // Switching to a different xml::elements field
1501                                // Note: begin_list() doesn't push a frame, so we only end the field
1502                                wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1503                                wip = wip
1504                                    .begin_nth_field(idx)
1505                                    .map_err(DeserializeError::reflect)?;
1506                                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
1507                                elements_field_state = Some((idx, true));
1508                                fields_set[idx] = true;
1509                            }
1510                            Some((current_idx, true)) if current_idx == idx => {
1511                                // Continue adding to same list
1512                            }
1513                            _ => {}
1514                        }
1515
1516                        // Add item to list
1517                        wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
1518
1519                        // For enum item types, we need to select the variant based on element name
1520                        let item_shape = Self::get_list_item_shape(field.shape());
1521                        if let Some(item_shape) = item_shape {
1522                            if let Type::User(UserType::Enum(enum_def)) = &item_shape.ty {
1523                                // Find matching variant (direct or custom_element fallback)
1524                                match Self::find_variant_for_element(enum_def, key.name.as_ref()) {
1525                                    Some(VariantMatch::Direct(variant_idx))
1526                                    | Some(VariantMatch::CustomElement(variant_idx)) => {
1527                                        wip = wip
1528                                            .select_nth_variant(variant_idx)
1529                                            .map_err(DeserializeError::reflect)?;
1530                                        // After selecting variant, deserialize the variant content
1531                                        // For custom elements, the _tag field will be matched
1532                                        // by FieldLocationHint::Tag
1533                                        wip = self.deserialize_enum_variant_content(wip)?;
1534                                    }
1535                                    None => {
1536                                        // No matching variant - deserialize directly
1537                                        wip = self.deserialize_into(wip)?;
1538                                    }
1539                                }
1540                            } else {
1541                                // Not an enum - deserialize directly
1542                                wip = self.deserialize_into(wip)?;
1543                            }
1544                        } else {
1545                            wip = self.deserialize_into(wip)?;
1546                        }
1547
1548                        wip = wip.end().map_err(DeserializeError::reflect)?; // end list item
1549                        continue;
1550                    }
1551
1552                    if deny_unknown_fields {
1553                        return Err(DeserializeError::UnknownField {
1554                            field: key.name.into_owned(),
1555                            span: self.last_span,
1556                            path: None,
1557                        });
1558                    } else {
1559                        // Unknown field - skip it
1560                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
1561                    }
1562                }
1563                other => {
1564                    return Err(DeserializeError::TypeMismatch {
1565                        expected: "field key or struct end",
1566                        got: format!("{other:?}"),
1567                        span: self.last_span,
1568                        path: None,
1569                    });
1570                }
1571            }
1572        }
1573
1574        // In deferred mode, skip validation - finish_deferred() will handle it.
1575        // This allows formats like TOML to reopen tables and set more fields later.
1576        if wip.is_deferred() {
1577            return Ok(wip);
1578        }
1579
1580        // Apply defaults for missing fields
1581        // First, check if ALL non-elements fields are missing and the struct has a container-level
1582        // default. In that case, use the struct's Default impl directly.
1583        let all_non_elements_missing = struct_def
1584            .fields
1585            .iter()
1586            .enumerate()
1587            .all(|(idx, field)| !fields_set[idx] || field.is_elements());
1588
1589        if struct_has_default && all_non_elements_missing && wip.shape().is(Characteristic::Default)
1590        {
1591            // Use the struct's Default impl for all fields at once
1592            wip = wip.set_default().map_err(DeserializeError::reflect)?;
1593            return Ok(wip);
1594        }
1595
1596        for (idx, field) in struct_def.fields.iter().enumerate() {
1597            if fields_set[idx] {
1598                continue;
1599            }
1600
1601            let field_has_default = field.has_default();
1602            let field_type_has_default = field.shape().is(Characteristic::Default);
1603            let field_is_option = matches!(field.shape().def, Def::Option(_));
1604
1605            // elements fields with no items should get an empty list
1606            // begin_list() doesn't push a frame, so we just begin the field, begin the list,
1607            // then end the field (no end() for the list itself).
1608            if field.is_elements() {
1609                wip = wip
1610                    .begin_nth_field(idx)
1611                    .map_err(DeserializeError::reflect)?;
1612                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
1613                wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1614                continue;
1615            }
1616
1617            if field_has_default || (struct_has_default && field_type_has_default) {
1618                wip = wip
1619                    .set_nth_field_to_default(idx)
1620                    .map_err(DeserializeError::reflect)?;
1621            } else if field_is_option {
1622                wip = wip
1623                    .begin_field(field.name)
1624                    .map_err(DeserializeError::reflect)?;
1625                wip = wip.set_default().map_err(DeserializeError::reflect)?;
1626                wip = wip.end().map_err(DeserializeError::reflect)?;
1627            } else if field.should_skip_deserializing() {
1628                wip = wip
1629                    .set_nth_field_to_default(idx)
1630                    .map_err(DeserializeError::reflect)?;
1631            } else {
1632                return Err(DeserializeError::MissingField {
1633                    field: field.name,
1634                    type_name: wip.shape().type_identifier,
1635                    span: self.last_span,
1636                    path: None,
1637                });
1638            }
1639        }
1640
1641        Ok(wip)
1642    }
1643
1644    /// Find an elements field that can accept a child element with the given name.
1645    fn find_elements_field_for_element<'a>(
1646        &self,
1647        fields: &'a [facet_core::Field],
1648        element_name: &str,
1649        element_ns: Option<&str>,
1650        ns_all: Option<&str>,
1651    ) -> Option<(usize, &'a facet_core::Field)> {
1652        for (idx, field) in fields.iter().enumerate() {
1653            if !field.is_elements() {
1654                continue;
1655            }
1656
1657            // Get the list item shape
1658            let item_shape = Self::get_list_item_shape(field.shape())?;
1659
1660            // Check if the item type can accept this element
1661            if Self::shape_accepts_element(item_shape, element_name, element_ns, ns_all) {
1662                return Some((idx, field));
1663            }
1664
1665            // Also check singularization: if element_name is the singular of field.name
1666            // This handles cases like: field `items: Vec<Item>` with `#[facet(kdl::children)]`
1667            // accepting child nodes named "item"
1668            #[cfg(feature = "singularize")]
1669            if facet_singularize::is_singular_of(element_name, field.name) {
1670                return Some((idx, field));
1671            }
1672        }
1673        None
1674    }
1675
1676    /// Get the item shape from a list-like field shape.
1677    fn get_list_item_shape(shape: &facet_core::Shape) -> Option<&'static facet_core::Shape> {
1678        match &shape.def {
1679            Def::List(list_def) => Some(list_def.t()),
1680            _ => None,
1681        }
1682    }
1683
1684    /// Check if a shape can accept an element with the given name.
1685    fn shape_accepts_element(
1686        shape: &facet_core::Shape,
1687        element_name: &str,
1688        _element_ns: Option<&str>,
1689        _ns_all: Option<&str>,
1690    ) -> bool {
1691        match &shape.ty {
1692            Type::User(UserType::Enum(enum_def)) => {
1693                // For enums, check if element name matches any variant
1694                let matches_variant = enum_def.variants.iter().any(|v| {
1695                    let display_name = Self::get_variant_display_name(v);
1696                    display_name.eq_ignore_ascii_case(element_name)
1697                });
1698                if matches_variant {
1699                    return true;
1700                }
1701                // Also check if enum has a custom_element fallback variant that can accept any element
1702                enum_def.variants.iter().any(|v| v.is_custom_element())
1703            }
1704            Type::User(UserType::Struct(struct_def)) => {
1705                // If the struct has a kdl::node_name field, it can accept any element name
1706                // since the name will be captured into that field
1707                if struct_def.fields.iter().any(|f| f.is_node_name()) {
1708                    return true;
1709                }
1710                // Similarly, if the struct has a tag field (for HTML/XML custom elements),
1711                // it can accept any element name
1712                if struct_def.fields.iter().any(|f| f.is_tag()) {
1713                    return true;
1714                }
1715                // Otherwise, check if element name matches struct's name
1716                // Use case-insensitive comparison since serializers may normalize case
1717                // (e.g., KDL serializer lowercases "Server" to "server")
1718                let display_name = Self::get_shape_display_name(shape);
1719                display_name.eq_ignore_ascii_case(element_name)
1720            }
1721            _ => {
1722                // For other types, use type identifier with case-insensitive comparison
1723                shape.type_identifier.eq_ignore_ascii_case(element_name)
1724            }
1725        }
1726    }
1727
1728    /// Get the display name for a variant (respecting rename attribute).
1729    fn get_variant_display_name(variant: &facet_core::Variant) -> &'static str {
1730        if let Some(attr) = variant.get_builtin_attr("rename")
1731            && let Some(&renamed) = attr.get_as::<&str>()
1732        {
1733            return renamed;
1734        }
1735        variant.name
1736    }
1737
1738    /// Get the display name for a shape (respecting rename attribute).
1739    fn get_shape_display_name(shape: &facet_core::Shape) -> &'static str {
1740        if let Some(renamed) = shape.get_builtin_attr_value::<&str>("rename") {
1741            return renamed;
1742        }
1743        shape.type_identifier
1744    }
1745
1746    /// Find the variant index for an enum that matches the given element name.
1747    ///
1748    /// First tries to find an exact match by name/rename. If no match is found,
1749    /// falls back to the `#[facet(html::custom_element)]` or `#[facet(xml::custom_element)]`
1750    /// variant if present.
1751    fn find_variant_for_element(
1752        enum_def: &facet_core::EnumType,
1753        element_name: &str,
1754    ) -> Option<VariantMatch> {
1755        // First try direct name match
1756        if let Some(idx) = enum_def.variants.iter().position(|v| {
1757            let display_name = Self::get_variant_display_name(v);
1758            display_name == element_name
1759        }) {
1760            return Some(VariantMatch::Direct(idx));
1761        }
1762
1763        // Fall back to custom_element variant if present
1764        if let Some(idx) = enum_def.variants.iter().position(|v| v.is_custom_element()) {
1765            return Some(VariantMatch::CustomElement(idx));
1766        }
1767
1768        None
1769    }
1770
1771    /// Deserialize a struct with single-level flattened fields (original approach).
1772    /// This handles simple flatten cases where there's no nested flatten or enum flatten.
1773    fn deserialize_struct_single_flatten(
1774        &mut self,
1775        mut wip: Partial<'input, BORROW>,
1776    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1777        use alloc::collections::BTreeMap;
1778        use facet_core::Characteristic;
1779        use facet_reflect::Resolution;
1780
1781        // Get struct fields for lookup
1782        let struct_type_name = wip.shape().type_identifier;
1783        let struct_def = match &wip.shape().ty {
1784            Type::User(UserType::Struct(def)) => def,
1785            _ => {
1786                return Err(DeserializeError::Unsupported(format!(
1787                    "expected struct type but got {:?}",
1788                    wip.shape().ty
1789                )));
1790            }
1791        };
1792
1793        let struct_has_default = wip.shape().has_default_attr();
1794
1795        // Expect StructStart, but for XML/HTML, a scalar means text-only element
1796        let event = self.expect_event("value")?;
1797        if let ParseEvent::Scalar(scalar) = &event {
1798            // For XML/HTML, a text-only element is emitted as a scalar.
1799            // If the struct has a text field, set it from the scalar and default the rest.
1800            if let Some((idx, _field)) = struct_def
1801                .fields
1802                .iter()
1803                .enumerate()
1804                .find(|(_, f)| f.is_text())
1805            {
1806                wip = wip
1807                    .begin_nth_field(idx)
1808                    .map_err(DeserializeError::reflect)?;
1809
1810                // Handle Option<T>
1811                let is_option = matches!(&wip.shape().def, Def::Option(_));
1812                if is_option {
1813                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
1814                }
1815
1816                wip = self.set_scalar(wip, scalar.clone())?;
1817
1818                if is_option {
1819                    wip = wip.end().map_err(DeserializeError::reflect)?;
1820                }
1821                wip = wip.end().map_err(DeserializeError::reflect)?;
1822
1823                // Set defaults for other fields (including flattened ones)
1824                for (other_idx, other_field) in struct_def.fields.iter().enumerate() {
1825                    if other_idx == idx {
1826                        continue;
1827                    }
1828
1829                    let field_has_default = other_field.has_default();
1830                    let field_type_has_default =
1831                        other_field.shape().is(facet_core::Characteristic::Default);
1832                    let field_is_option = matches!(other_field.shape().def, Def::Option(_));
1833
1834                    if field_has_default || (struct_has_default && field_type_has_default) {
1835                        wip = wip
1836                            .set_nth_field_to_default(other_idx)
1837                            .map_err(DeserializeError::reflect)?;
1838                    } else if field_is_option {
1839                        wip = wip
1840                            .begin_field(other_field.name)
1841                            .map_err(DeserializeError::reflect)?;
1842                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
1843                        wip = wip.end().map_err(DeserializeError::reflect)?;
1844                    } else if other_field.should_skip_deserializing() {
1845                        // Skip fields that are marked for skip deserializing
1846                        continue;
1847                    } else {
1848                        return Err(DeserializeError::MissingField {
1849                            field: other_field.name,
1850                            type_name: struct_type_name,
1851                            span: self.last_span,
1852                            path: None,
1853                        });
1854                    }
1855                }
1856
1857                return Ok(wip);
1858            }
1859        }
1860
1861        if !matches!(event, ParseEvent::StructStart(_)) {
1862            return Err(DeserializeError::TypeMismatch {
1863                expected: "struct start",
1864                got: format!("{event:?}"),
1865                span: self.last_span,
1866                path: None,
1867            });
1868        }
1869        let deny_unknown_fields = wip.shape().has_deny_unknown_fields_attr();
1870
1871        // Extract container-level default namespace (xml::ns_all) for namespace-aware matching
1872        let ns_all = wip
1873            .shape()
1874            .attributes
1875            .iter()
1876            .find(|attr| attr.ns == Some("xml") && attr.key == "ns_all")
1877            .and_then(|attr| attr.get_as::<&str>().copied());
1878
1879        // Track which fields have been set
1880        let num_fields = struct_def.fields.len();
1881        let mut fields_set = alloc::vec![false; num_fields];
1882
1883        // Build flatten info: for each flattened field, get its inner struct fields
1884        // and track which inner fields have been set
1885        let mut flatten_info: alloc::vec::Vec<
1886            Option<(&'static [facet_core::Field], alloc::vec::Vec<bool>)>,
1887        > = alloc::vec![None; num_fields];
1888
1889        // Track which fields are DynamicValue flattens (like facet_value::Value)
1890        let mut dynamic_value_flattens: alloc::vec::Vec<bool> = alloc::vec![false; num_fields];
1891
1892        // Track flattened map field index (for collecting unknown keys)
1893        // Can be either:
1894        // - (outer_idx, None) for a directly flattened map
1895        // - (outer_idx, Some(inner_idx)) for a map nested inside a flattened struct
1896        let mut flatten_map_idx: Option<(usize, Option<usize>)> = None;
1897
1898        // Track field names across flattened structs to detect duplicates
1899        let mut flatten_field_names: BTreeMap<&str, usize> = BTreeMap::new();
1900
1901        for (idx, field) in struct_def.fields.iter().enumerate() {
1902            if field.is_flattened() {
1903                // Handle Option<T> flatten by unwrapping to inner type
1904                let inner_shape = match field.shape().def {
1905                    Def::Option(opt) => opt.t,
1906                    _ => field.shape(),
1907                };
1908
1909                // Check if this is a DynamicValue flatten (like facet_value::Value)
1910                if matches!(inner_shape.def, Def::DynamicValue(_)) {
1911                    dynamic_value_flattens[idx] = true;
1912                } else if matches!(inner_shape.def, Def::Map(_)) {
1913                    // Flattened map - collects unknown keys
1914                    flatten_map_idx = Some((idx, None));
1915                } else if let Type::User(UserType::Struct(inner_def)) = &inner_shape.ty {
1916                    let inner_fields = inner_def.fields;
1917                    let inner_set = alloc::vec![false; inner_fields.len()];
1918                    flatten_info[idx] = Some((inner_fields, inner_set));
1919
1920                    // Check for duplicate field names across flattened structs
1921                    for inner_field in inner_fields.iter() {
1922                        let field_name = inner_field.rename.unwrap_or(inner_field.name);
1923                        if let Some(_prev_idx) = flatten_field_names.insert(field_name, idx) {
1924                            return Err(DeserializeError::Unsupported(format!(
1925                                "duplicate field `{}` in flattened structs",
1926                                field_name
1927                            )));
1928                        }
1929                    }
1930
1931                    // Also check for nested flattened maps inside this struct
1932                    // (e.g., GlobalAttrs has a flattened HashMap for unknown attributes)
1933                    if flatten_map_idx.is_none() {
1934                        for (inner_idx, inner_field) in inner_fields.iter().enumerate() {
1935                            if inner_field.is_flattened() {
1936                                let inner_inner_shape = match inner_field.shape().def {
1937                                    Def::Option(opt) => opt.t,
1938                                    _ => inner_field.shape(),
1939                                };
1940                                if matches!(inner_inner_shape.def, Def::Map(_)) {
1941                                    flatten_map_idx = Some((idx, Some(inner_idx)));
1942                                    break;
1943                                }
1944                            }
1945                        }
1946                    }
1947                }
1948            }
1949        }
1950
1951        // Enter deferred mode for flatten handling (if not already in deferred mode)
1952        let already_deferred = wip.is_deferred();
1953        if !already_deferred {
1954            let resolution = Resolution::new();
1955            wip = wip
1956                .begin_deferred(resolution)
1957                .map_err(DeserializeError::reflect)?;
1958        }
1959
1960        // Track xml::elements field state for collecting child elements into lists
1961        // (field_idx, is_open)
1962        let mut elements_field_state: Option<(usize, bool)> = None;
1963
1964        loop {
1965            let event = self.expect_event("value")?;
1966            match event {
1967                ParseEvent::StructEnd => {
1968                    // End any open xml::elements field
1969                    if let Some((_, true)) = elements_field_state {
1970                        wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1971                    }
1972                    break;
1973                }
1974                ParseEvent::FieldKey(key) => {
1975                    // First, look up field in direct struct fields (non-flattened, non-elements)
1976                    // Exclude xml::elements fields - they accumulate repeated child elements
1977                    // and must be handled via find_elements_field_for_element below
1978                    let direct_field_info = struct_def.fields.iter().enumerate().find(|(_, f)| {
1979                        !f.is_flattened()
1980                            && !f.is_elements()
1981                            && Self::field_matches_with_namespace(
1982                                f,
1983                                key.name.as_ref(),
1984                                key.namespace.as_deref(),
1985                                key.location,
1986                                ns_all,
1987                            )
1988                    });
1989
1990                    if let Some((idx, _field)) = direct_field_info {
1991                        // End any open xml::elements field before switching to a different field
1992                        if let Some((elem_idx, true)) = elements_field_state
1993                            && elem_idx != idx
1994                        {
1995                            wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
1996                            elements_field_state = None;
1997                        }
1998
1999                        wip = wip
2000                            .begin_nth_field(idx)
2001                            .map_err(DeserializeError::reflect)?;
2002                        wip = self.deserialize_into(wip)?;
2003                        wip = wip.end().map_err(DeserializeError::reflect)?;
2004                        fields_set[idx] = true;
2005                        continue;
2006                    }
2007
2008                    // Check if this child element or text node should go into an xml::elements field
2009                    // This handles both child elements and text nodes in mixed content
2010                    if matches!(
2011                        key.location,
2012                        FieldLocationHint::Child | FieldLocationHint::Text
2013                    ) && let Some((idx, field)) = self.find_elements_field_for_element(
2014                        struct_def.fields,
2015                        key.name.as_ref(),
2016                        key.namespace.as_deref(),
2017                        ns_all,
2018                    ) {
2019                        // Start or continue the list for this elements field
2020                        match elements_field_state {
2021                            None => {
2022                                // Start new list
2023                                wip = wip
2024                                    .begin_nth_field(idx)
2025                                    .map_err(DeserializeError::reflect)?;
2026                                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
2027                                elements_field_state = Some((idx, true));
2028                                fields_set[idx] = true;
2029                            }
2030                            Some((current_idx, true)) if current_idx != idx => {
2031                                // Switching to a different xml::elements field
2032                                wip = wip.end().map_err(DeserializeError::reflect)?; // end field only
2033                                wip = wip
2034                                    .begin_nth_field(idx)
2035                                    .map_err(DeserializeError::reflect)?;
2036                                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
2037                                elements_field_state = Some((idx, true));
2038                                fields_set[idx] = true;
2039                            }
2040                            Some((current_idx, true)) if current_idx == idx => {
2041                                // Continue adding to same list
2042                            }
2043                            _ => {}
2044                        }
2045
2046                        // Add item to list
2047                        wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
2048
2049                        // For enum item types, we need to select the variant based on element name
2050                        let item_shape = Self::get_list_item_shape(field.shape());
2051                        if let Some(item_shape) = item_shape {
2052                            if let Type::User(UserType::Enum(enum_def)) = &item_shape.ty {
2053                                // Find matching variant (direct or custom_element fallback)
2054                                match Self::find_variant_for_element(enum_def, key.name.as_ref()) {
2055                                    Some(VariantMatch::Direct(variant_idx))
2056                                    | Some(VariantMatch::CustomElement(variant_idx)) => {
2057                                        wip = wip
2058                                            .select_nth_variant(variant_idx)
2059                                            .map_err(DeserializeError::reflect)?;
2060                                        // After selecting variant, deserialize the variant content
2061                                        // For custom elements, the _tag field will be matched
2062                                        // by FieldLocationHint::Tag
2063                                        wip = self.deserialize_enum_variant_content(wip)?;
2064                                    }
2065                                    None => {
2066                                        // No matching variant - deserialize directly
2067                                        wip = self.deserialize_into(wip)?;
2068                                    }
2069                                }
2070                            } else {
2071                                // Not an enum - deserialize directly
2072                                wip = self.deserialize_into(wip)?;
2073                            }
2074                        } else {
2075                            wip = self.deserialize_into(wip)?;
2076                        }
2077
2078                        wip = wip.end().map_err(DeserializeError::reflect)?; // end list item
2079                        continue;
2080                    }
2081
2082                    // Check flattened fields for a match
2083                    let mut found_flatten = false;
2084                    for (flatten_idx, field) in struct_def.fields.iter().enumerate() {
2085                        if !field.is_flattened() {
2086                            continue;
2087                        }
2088                        if let Some((inner_fields, inner_set)) = flatten_info[flatten_idx].as_mut()
2089                        {
2090                            let inner_match =
2091                                inner_fields.iter().enumerate().find(|(inner_idx, f)| {
2092                                    // Nested flattened map is handled separately, even if its name
2093                                    // matches the key name it must be skipped.
2094                                    let is_flatten_map =
2095                                        Some((flatten_idx, Some(*inner_idx))) == flatten_map_idx;
2096
2097                                    !is_flatten_map
2098                                        && Self::field_matches_with_namespace(
2099                                            f,
2100                                            key.name.as_ref(),
2101                                            key.namespace.as_deref(),
2102                                            key.location,
2103                                            ns_all,
2104                                        )
2105                                });
2106
2107                            if let Some((inner_idx, _inner_field)) = inner_match {
2108                                // Check if flatten field is Option - if so, wrap in Some
2109                                let is_option = matches!(field.shape().def, Def::Option(_));
2110                                wip = wip
2111                                    .begin_nth_field(flatten_idx)
2112                                    .map_err(DeserializeError::reflect)?;
2113                                if is_option {
2114                                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2115                                }
2116                                wip = wip
2117                                    .begin_nth_field(inner_idx)
2118                                    .map_err(DeserializeError::reflect)?;
2119                                wip = self.deserialize_into(wip)?;
2120                                wip = wip.end().map_err(DeserializeError::reflect)?;
2121                                if is_option {
2122                                    wip = wip.end().map_err(DeserializeError::reflect)?;
2123                                }
2124                                wip = wip.end().map_err(DeserializeError::reflect)?;
2125                                inner_set[inner_idx] = true;
2126                                fields_set[flatten_idx] = true;
2127                                found_flatten = true;
2128                                break;
2129                            }
2130                        }
2131                    }
2132
2133                    if found_flatten {
2134                        continue;
2135                    }
2136
2137                    // Check if this unknown field should go to a DynamicValue flatten
2138                    let mut found_dynamic = false;
2139                    for (flatten_idx, _field) in struct_def.fields.iter().enumerate() {
2140                        if !dynamic_value_flattens[flatten_idx] {
2141                            continue;
2142                        }
2143
2144                        // This is a DynamicValue flatten - insert the field into it
2145                        // First, ensure the DynamicValue is initialized as an object
2146                        let is_option =
2147                            matches!(struct_def.fields[flatten_idx].shape().def, Def::Option(_));
2148
2149                        // Navigate to the DynamicValue field
2150                        wip = wip
2151                            .begin_nth_field(flatten_idx)
2152                            .map_err(DeserializeError::reflect)?;
2153                        if is_option {
2154                            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2155                        }
2156                        // Initialize or re-enter the DynamicValue as an object.
2157                        // begin_map() is idempotent - it returns Ok if already in Object state.
2158                        // We always call it because in deferred mode inside collections (like HashMap),
2159                        // the frame might not be stored/restored, so we can't rely on fields_set alone.
2160                        wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2161                        fields_set[flatten_idx] = true;
2162
2163                        // Insert the key-value pair into the object
2164                        wip = wip
2165                            .begin_object_entry(key.name.as_ref())
2166                            .map_err(DeserializeError::reflect)?;
2167                        wip = self.deserialize_into(wip)?;
2168                        wip = wip.end().map_err(DeserializeError::reflect)?;
2169
2170                        // Navigate back out (Note: we close the map when we're done with ALL fields, not per-field)
2171                        if is_option {
2172                            wip = wip.end().map_err(DeserializeError::reflect)?;
2173                        }
2174                        wip = wip.end().map_err(DeserializeError::reflect)?;
2175
2176                        found_dynamic = true;
2177                        break;
2178                    }
2179
2180                    if found_dynamic {
2181                        continue;
2182                    }
2183
2184                    // Skip _tag fields that have no matching is_tag() field - they should be silently ignored
2185                    // (Tag location hint is used by custom elements to capture the element name,
2186                    // but for regular elements it should just be dropped, not added to extra attributes)
2187                    if key.location == FieldLocationHint::Tag {
2188                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
2189                        continue;
2190                    }
2191
2192                    // Check if this unknown field should go to a flattened map
2193                    // flatten_map_idx is (outer_idx, Option<inner_idx>):
2194                    // - (outer_idx, None): direct flattened map at struct_def.fields[outer_idx]
2195                    // - (outer_idx, Some(inner_idx)): nested map inside a flattened struct
2196                    //
2197                    // For nested maps, we only insert if the value is a scalar. This is important
2198                    // for HTML/XML where child elements also appear as object keys, but should not
2199                    // be inserted into an attribute map (which expects String values).
2200                    let should_insert_into_map = if let Some((_, inner_idx_opt)) = flatten_map_idx {
2201                        if inner_idx_opt.is_some() {
2202                            // Nested case: only insert if value is a scalar
2203                            matches!(
2204                                self.parser.peek_event().ok().flatten(),
2205                                Some(ParseEvent::Scalar(_))
2206                            )
2207                        } else {
2208                            // Direct case: always insert
2209                            true
2210                        }
2211                    } else {
2212                        false
2213                    };
2214
2215                    if should_insert_into_map {
2216                        let (outer_idx, inner_idx_opt) = flatten_map_idx.unwrap();
2217                        let outer_field = &struct_def.fields[outer_idx];
2218                        let outer_is_option = matches!(outer_field.shape().def, Def::Option(_));
2219
2220                        // Navigate to the outer field first
2221                        if !fields_set[outer_idx] {
2222                            // First time - need to initialize
2223                            wip = wip
2224                                .begin_nth_field(outer_idx)
2225                                .map_err(DeserializeError::reflect)?;
2226                            if outer_is_option {
2227                                wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2228                            }
2229
2230                            if let Some(inner_idx) = inner_idx_opt {
2231                                // Nested case: navigate to the inner map field
2232                                let inner_field = flatten_info[outer_idx]
2233                                    .as_ref()
2234                                    .map(|(fields, _)| &fields[inner_idx])
2235                                    .expect("inner field should exist");
2236                                let inner_is_option =
2237                                    matches!(inner_field.shape().def, Def::Option(_));
2238
2239                                wip = wip
2240                                    .begin_nth_field(inner_idx)
2241                                    .map_err(DeserializeError::reflect)?;
2242                                if inner_is_option {
2243                                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2244                                }
2245                                // Initialize the map
2246                                wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2247                            } else {
2248                                // Direct case: initialize the map
2249                                wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2250                            }
2251                            fields_set[outer_idx] = true;
2252                        } else {
2253                            // Already initialized - navigate to it
2254                            wip = wip
2255                                .begin_nth_field(outer_idx)
2256                                .map_err(DeserializeError::reflect)?;
2257                            if outer_is_option {
2258                                wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2259                            }
2260
2261                            if let Some(inner_idx) = inner_idx_opt {
2262                                // Nested case: navigate to the inner map field
2263                                let inner_field = flatten_info[outer_idx]
2264                                    .as_ref()
2265                                    .map(|(fields, _)| &fields[inner_idx])
2266                                    .expect("inner field should exist");
2267                                let inner_is_option =
2268                                    matches!(inner_field.shape().def, Def::Option(_));
2269
2270                                wip = wip
2271                                    .begin_nth_field(inner_idx)
2272                                    .map_err(DeserializeError::reflect)?;
2273                                if inner_is_option {
2274                                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2275                                }
2276                                // In deferred mode, the map frame might not be stored/restored,
2277                                // so we always need to call begin_map() to re-enter it
2278                                wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2279                            } else {
2280                                // Direct case: in deferred mode (e.g., within an array element),
2281                                // we need to re-enter the map even if already initialized
2282                                wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2283                            }
2284                        }
2285
2286                        // Insert the key-value pair into the map using begin_key/begin_value
2287                        // Clone the key to an owned String since we need it beyond the parse event lifetime
2288                        let key_owned: alloc::string::String = key.name.clone().into_owned();
2289                        // First: push key frame
2290                        wip = wip.begin_key().map_err(DeserializeError::reflect)?;
2291                        // Set the key (it's a string)
2292                        wip = wip.set(key_owned).map_err(DeserializeError::reflect)?;
2293                        // Pop key frame
2294                        wip = wip.end().map_err(DeserializeError::reflect)?;
2295                        // Push value frame
2296                        wip = wip.begin_value().map_err(DeserializeError::reflect)?;
2297                        // Deserialize value
2298                        wip = self.deserialize_into(wip)?;
2299                        // Pop value frame
2300                        wip = wip.end().map_err(DeserializeError::reflect)?;
2301
2302                        // Navigate back out
2303                        if let Some(inner_idx) = inner_idx_opt {
2304                            // Nested case: need to pop inner field frames too
2305                            let inner_field = flatten_info[outer_idx]
2306                                .as_ref()
2307                                .map(|(fields, _)| &fields[inner_idx])
2308                                .expect("inner field should exist");
2309                            let inner_is_option = matches!(inner_field.shape().def, Def::Option(_));
2310
2311                            if inner_is_option {
2312                                wip = wip.end().map_err(DeserializeError::reflect)?;
2313                            }
2314                            wip = wip.end().map_err(DeserializeError::reflect)?;
2315                        }
2316
2317                        if outer_is_option {
2318                            wip = wip.end().map_err(DeserializeError::reflect)?;
2319                        }
2320                        wip = wip.end().map_err(DeserializeError::reflect)?;
2321
2322                        // Mark the nested map field as set so defaults won't overwrite it
2323                        if let Some(inner_idx) = inner_idx_opt
2324                            && let Some((_, inner_set)) = flatten_info[outer_idx].as_mut()
2325                        {
2326                            inner_set[inner_idx] = true;
2327                        }
2328
2329                        continue;
2330                    }
2331
2332                    if deny_unknown_fields {
2333                        return Err(DeserializeError::UnknownField {
2334                            field: key.name.into_owned(),
2335                            span: self.last_span,
2336                            path: None,
2337                        });
2338                    } else {
2339                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
2340                    }
2341                }
2342                other => {
2343                    return Err(DeserializeError::TypeMismatch {
2344                        expected: "field key or struct end",
2345                        got: format!("{other:?}"),
2346                        span: self.last_span,
2347                        path: None,
2348                    });
2349                }
2350            }
2351        }
2352
2353        // Apply defaults for missing fields
2354        for (idx, field) in struct_def.fields.iter().enumerate() {
2355            if field.is_flattened() {
2356                // Handle DynamicValue flattens that received no fields
2357                if dynamic_value_flattens[idx] && !fields_set[idx] {
2358                    let is_option = matches!(field.shape().def, Def::Option(_));
2359
2360                    if is_option {
2361                        // Option<DynamicValue> with no fields -> set to None
2362                        wip = wip
2363                            .begin_nth_field(idx)
2364                            .map_err(DeserializeError::reflect)?;
2365                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
2366                        wip = wip.end().map_err(DeserializeError::reflect)?;
2367                    } else {
2368                        // DynamicValue with no fields -> initialize as empty object
2369                        wip = wip
2370                            .begin_nth_field(idx)
2371                            .map_err(DeserializeError::reflect)?;
2372                        // Initialize as object (for DynamicValue, begin_map creates an object)
2373                        wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2374                        // The map is now initialized and empty, just end the field
2375                        wip = wip.end().map_err(DeserializeError::reflect)?;
2376                    }
2377                    continue;
2378                }
2379
2380                // Handle flattened map that received no unknown keys
2381                // Only applies to direct flattened maps (outer_idx, None), not nested ones
2382                if flatten_map_idx == Some((idx, None)) && !fields_set[idx] {
2383                    let is_option = matches!(field.shape().def, Def::Option(_));
2384                    let field_has_default = field.has_default();
2385                    let field_type_has_default =
2386                        field.shape().is(facet_core::Characteristic::Default);
2387
2388                    if is_option {
2389                        // Option<HashMap> with no fields -> set to None
2390                        wip = wip
2391                            .begin_nth_field(idx)
2392                            .map_err(DeserializeError::reflect)?;
2393                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
2394                        wip = wip.end().map_err(DeserializeError::reflect)?;
2395                    } else if field_has_default || (struct_has_default && field_type_has_default) {
2396                        // Has default - use it
2397                        wip = wip
2398                            .set_nth_field_to_default(idx)
2399                            .map_err(DeserializeError::reflect)?;
2400                    } else {
2401                        // No default - initialize as empty map
2402                        wip = wip
2403                            .begin_nth_field(idx)
2404                            .map_err(DeserializeError::reflect)?;
2405                        wip = wip.begin_map().map_err(DeserializeError::reflect)?;
2406                        wip = wip.end().map_err(DeserializeError::reflect)?;
2407                    }
2408                    continue;
2409                }
2410
2411                if let Some((inner_fields, inner_set)) = flatten_info[idx].as_ref() {
2412                    let any_inner_set = inner_set.iter().any(|&s| s);
2413                    let is_option = matches!(field.shape().def, Def::Option(_));
2414
2415                    if any_inner_set {
2416                        // Some inner fields were set - apply defaults to missing ones
2417                        wip = wip
2418                            .begin_nth_field(idx)
2419                            .map_err(DeserializeError::reflect)?;
2420                        if is_option {
2421                            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2422                        }
2423                        for (inner_idx, inner_field) in inner_fields.iter().enumerate() {
2424                            if inner_set[inner_idx] {
2425                                continue;
2426                            }
2427                            let inner_has_default = inner_field.has_default();
2428                            let inner_type_has_default =
2429                                inner_field.shape().is(Characteristic::Default);
2430                            let inner_is_option = matches!(inner_field.shape().def, Def::Option(_));
2431
2432                            if inner_has_default || inner_type_has_default {
2433                                wip = wip
2434                                    .set_nth_field_to_default(inner_idx)
2435                                    .map_err(DeserializeError::reflect)?;
2436                            } else if inner_is_option {
2437                                wip = wip
2438                                    .begin_nth_field(inner_idx)
2439                                    .map_err(DeserializeError::reflect)?;
2440                                wip = wip.set_default().map_err(DeserializeError::reflect)?;
2441                                wip = wip.end().map_err(DeserializeError::reflect)?;
2442                            } else if inner_field.should_skip_deserializing() {
2443                                wip = wip
2444                                    .set_nth_field_to_default(inner_idx)
2445                                    .map_err(DeserializeError::reflect)?;
2446                            } else {
2447                                return Err(DeserializeError::TypeMismatch {
2448                                    expected: "field to be present or have default",
2449                                    got: format!("missing field '{}'", inner_field.name),
2450                                    span: self.last_span,
2451                                    path: None,
2452                                });
2453                            }
2454                        }
2455                        if is_option {
2456                            wip = wip.end().map_err(DeserializeError::reflect)?;
2457                        }
2458                        wip = wip.end().map_err(DeserializeError::reflect)?;
2459                    } else if is_option {
2460                        // No inner fields set and field is Option - set to None
2461                        wip = wip
2462                            .begin_nth_field(idx)
2463                            .map_err(DeserializeError::reflect)?;
2464                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
2465                        wip = wip.end().map_err(DeserializeError::reflect)?;
2466                    } else {
2467                        // No inner fields set - try to default the whole flattened field
2468                        let field_has_default = field.has_default();
2469                        let field_type_has_default = field.shape().is(Characteristic::Default);
2470                        if field_has_default || (struct_has_default && field_type_has_default) {
2471                            wip = wip
2472                                .set_nth_field_to_default(idx)
2473                                .map_err(DeserializeError::reflect)?;
2474                        } else {
2475                            let all_inner_can_default = inner_fields.iter().all(|f| {
2476                                f.has_default()
2477                                    || f.shape().is(Characteristic::Default)
2478                                    || matches!(f.shape().def, Def::Option(_))
2479                                    || f.should_skip_deserializing()
2480                            });
2481                            if all_inner_can_default {
2482                                wip = wip
2483                                    .begin_nth_field(idx)
2484                                    .map_err(DeserializeError::reflect)?;
2485                                for (inner_idx, inner_field) in inner_fields.iter().enumerate() {
2486                                    let inner_has_default = inner_field.has_default();
2487                                    let inner_type_has_default =
2488                                        inner_field.shape().is(Characteristic::Default);
2489                                    let inner_is_option =
2490                                        matches!(inner_field.shape().def, Def::Option(_));
2491
2492                                    if inner_has_default || inner_type_has_default {
2493                                        wip = wip
2494                                            .set_nth_field_to_default(inner_idx)
2495                                            .map_err(DeserializeError::reflect)?;
2496                                    } else if inner_is_option {
2497                                        wip = wip
2498                                            .begin_nth_field(inner_idx)
2499                                            .map_err(DeserializeError::reflect)?;
2500                                        wip =
2501                                            wip.set_default().map_err(DeserializeError::reflect)?;
2502                                        wip = wip.end().map_err(DeserializeError::reflect)?;
2503                                    } else if inner_field.should_skip_deserializing() {
2504                                        wip = wip
2505                                            .set_nth_field_to_default(inner_idx)
2506                                            .map_err(DeserializeError::reflect)?;
2507                                    }
2508                                }
2509                                wip = wip.end().map_err(DeserializeError::reflect)?;
2510                            } else {
2511                                return Err(DeserializeError::TypeMismatch {
2512                                    expected: "field to be present or have default",
2513                                    got: format!("missing flattened field '{}'", field.name),
2514                                    span: self.last_span,
2515                                    path: None,
2516                                });
2517                            }
2518                        }
2519                    }
2520                }
2521                continue;
2522            }
2523
2524            if fields_set[idx] {
2525                continue;
2526            }
2527
2528            let field_has_default = field.has_default();
2529            let field_type_has_default = field.shape().is(Characteristic::Default);
2530            let field_is_option = matches!(field.shape().def, Def::Option(_));
2531
2532            if field_has_default || (struct_has_default && field_type_has_default) {
2533                wip = wip
2534                    .set_nth_field_to_default(idx)
2535                    .map_err(DeserializeError::reflect)?;
2536            } else if field_is_option {
2537                wip = wip
2538                    .begin_field(field.name)
2539                    .map_err(DeserializeError::reflect)?;
2540                wip = wip.set_default().map_err(DeserializeError::reflect)?;
2541                wip = wip.end().map_err(DeserializeError::reflect)?;
2542            } else if field.should_skip_deserializing() {
2543                wip = wip
2544                    .set_nth_field_to_default(idx)
2545                    .map_err(DeserializeError::reflect)?;
2546            } else {
2547                return Err(DeserializeError::TypeMismatch {
2548                    expected: "field to be present or have default",
2549                    got: format!("missing field '{}'", field.name),
2550                    span: self.last_span,
2551                    path: None,
2552                });
2553            }
2554        }
2555
2556        // Finish deferred mode (only if we started it)
2557        if !already_deferred {
2558            wip = wip.finish_deferred().map_err(DeserializeError::reflect)?;
2559        }
2560
2561        Ok(wip)
2562    }
2563
2564    /// Deserialize a struct with flattened fields using facet-solver.
2565    ///
2566    /// This uses the solver's Schema/Resolution to handle arbitrarily nested
2567    /// flatten structures by looking up the full path for each field.
2568    /// It also handles flattened enums by using probing to collect keys first,
2569    /// then using the Solver to disambiguate between resolutions.
2570    fn deserialize_struct_with_flatten(
2571        &mut self,
2572        mut wip: Partial<'input, BORROW>,
2573    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
2574        use alloc::collections::BTreeSet;
2575        use facet_core::Characteristic;
2576        use facet_reflect::Resolution;
2577        use facet_solver::{PathSegment, Schema, Solver};
2578
2579        let deny_unknown_fields = wip.shape().has_deny_unknown_fields_attr();
2580
2581        // Build the schema for this type - this recursively expands all flatten fields
2582        let schema = Schema::build_auto(wip.shape())
2583            .map_err(|e| DeserializeError::Unsupported(format!("failed to build schema: {e}")))?;
2584
2585        // Check if we have multiple resolutions (i.e., flattened enums)
2586        let resolutions = schema.resolutions();
2587        if resolutions.is_empty() {
2588            return Err(DeserializeError::Unsupported(
2589                "schema has no resolutions".into(),
2590            ));
2591        }
2592
2593        // ========== PASS 1: Probe to collect all field keys ==========
2594        let probe = self
2595            .parser
2596            .begin_probe()
2597            .map_err(DeserializeError::Parser)?;
2598        let evidence = Self::collect_evidence(probe).map_err(DeserializeError::Parser)?;
2599
2600        // Feed keys to solver to narrow down resolutions
2601        let mut solver = Solver::new(&schema);
2602        for ev in &evidence {
2603            solver.see_key(ev.name.clone());
2604        }
2605
2606        // Get the resolved configuration
2607        let config_handle = solver
2608            .finish()
2609            .map_err(|e| DeserializeError::Unsupported(format!("solver failed: {e}")))?;
2610        let resolution = config_handle.resolution();
2611
2612        // ========== PASS 2: Parse the struct with resolved paths ==========
2613        // Expect StructStart
2614        let event = self.expect_event("value")?;
2615        if !matches!(event, ParseEvent::StructStart(_)) {
2616            return Err(DeserializeError::TypeMismatch {
2617                expected: "struct start",
2618                got: format!("{event:?}"),
2619                span: self.last_span,
2620                path: None,
2621            });
2622        }
2623
2624        // Enter deferred mode for flatten handling (if not already in deferred mode)
2625        let already_deferred = wip.is_deferred();
2626        if !already_deferred {
2627            let reflect_resolution = Resolution::new();
2628            wip = wip
2629                .begin_deferred(reflect_resolution)
2630                .map_err(DeserializeError::reflect)?;
2631        }
2632
2633        // Track which fields have been set (by serialized name - uses 'static str from resolution)
2634        let mut fields_set: BTreeSet<&'static str> = BTreeSet::new();
2635
2636        // Track currently open path segments: (field_name, is_option, is_variant)
2637        // The is_variant flag indicates if we've selected a variant at this level
2638        let mut open_segments: alloc::vec::Vec<(&str, bool, bool)> = alloc::vec::Vec::new();
2639
2640        loop {
2641            let event = self.expect_event("value")?;
2642            match event {
2643                ParseEvent::StructEnd => break,
2644                ParseEvent::FieldKey(key) => {
2645                    // Look up field in the resolution
2646                    if let Some(field_info) = resolution.field(key.name.as_ref()) {
2647                        let segments = field_info.path.segments();
2648
2649                        // Check if this path ends with a Variant segment (externally-tagged enum)
2650                        let ends_with_variant = segments
2651                            .last()
2652                            .is_some_and(|s| matches!(s, PathSegment::Variant(_, _)));
2653
2654                        // Extract field names from the path (excluding trailing Variant)
2655                        let field_segments: alloc::vec::Vec<&str> = segments
2656                            .iter()
2657                            .filter_map(|s| match s {
2658                                PathSegment::Field(name) => Some(*name),
2659                                PathSegment::Variant(_, _) => None,
2660                            })
2661                            .collect();
2662
2663                        // Find common prefix with currently open segments
2664                        let common_len = open_segments
2665                            .iter()
2666                            .zip(field_segments.iter())
2667                            .take_while(|((name, _, _), b)| *name == **b)
2668                            .count();
2669
2670                        // Close segments that are no longer needed (in reverse order)
2671                        while open_segments.len() > common_len {
2672                            let (_, is_option, _) = open_segments.pop().unwrap();
2673                            if is_option {
2674                                wip = wip.end().map_err(DeserializeError::reflect)?;
2675                            }
2676                            wip = wip.end().map_err(DeserializeError::reflect)?;
2677                        }
2678
2679                        // Open new segments
2680                        for &segment in &field_segments[common_len..] {
2681                            wip = wip
2682                                .begin_field(segment)
2683                                .map_err(DeserializeError::reflect)?;
2684                            let is_option = matches!(wip.shape().def, Def::Option(_));
2685                            if is_option {
2686                                wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2687                            }
2688                            open_segments.push((segment, is_option, false));
2689                        }
2690
2691                        if ends_with_variant {
2692                            // For externally-tagged enums: select variant and deserialize content
2693                            if let Some(PathSegment::Variant(_, variant_name)) = segments.last() {
2694                                wip = wip
2695                                    .select_variant_named(variant_name)
2696                                    .map_err(DeserializeError::reflect)?;
2697                                // Deserialize the variant's struct content (the nested object)
2698                                wip = self.deserialize_variant_struct_fields(wip)?;
2699                            }
2700                        } else {
2701                            // Regular field: deserialize into it
2702                            wip = self.deserialize_into(wip)?;
2703                        }
2704
2705                        // Close segments we just opened (we're done with this field)
2706                        while open_segments.len() > common_len {
2707                            let (_, is_option, _) = open_segments.pop().unwrap();
2708                            if is_option {
2709                                wip = wip.end().map_err(DeserializeError::reflect)?;
2710                            }
2711                            wip = wip.end().map_err(DeserializeError::reflect)?;
2712                        }
2713
2714                        // Store the static serialized_name from the resolution
2715                        fields_set.insert(field_info.serialized_name);
2716                        continue;
2717                    }
2718
2719                    if deny_unknown_fields {
2720                        return Err(DeserializeError::UnknownField {
2721                            field: key.name.into_owned(),
2722                            span: self.last_span,
2723                            path: None,
2724                        });
2725                    } else {
2726                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
2727                    }
2728                }
2729                other => {
2730                    return Err(DeserializeError::TypeMismatch {
2731                        expected: "field key or struct end",
2732                        got: format!("{other:?}"),
2733                        span: self.last_span,
2734                        path: None,
2735                    });
2736                }
2737            }
2738        }
2739
2740        // Close any remaining open segments
2741        while let Some((_, is_option, _)) = open_segments.pop() {
2742            if is_option {
2743                wip = wip.end().map_err(DeserializeError::reflect)?;
2744            }
2745            wip = wip.end().map_err(DeserializeError::reflect)?;
2746        }
2747
2748        // Handle missing fields - apply defaults
2749        // Get all fields sorted by path depth (deepest first for proper default handling)
2750        let all_fields = resolution.deserialization_order();
2751
2752        // Track which top-level flatten fields have had any sub-fields set
2753        let mut touched_top_fields: BTreeSet<&str> = BTreeSet::new();
2754        for field_name in &fields_set {
2755            if let Some(info) = resolution.field(field_name)
2756                && let Some(PathSegment::Field(top)) = info.path.segments().first()
2757            {
2758                touched_top_fields.insert(*top);
2759            }
2760        }
2761
2762        for field_info in all_fields {
2763            if fields_set.contains(field_info.serialized_name) {
2764                continue;
2765            }
2766
2767            // Skip fields that end with Variant - these are handled by enum deserialization
2768            let ends_with_variant = field_info
2769                .path
2770                .segments()
2771                .last()
2772                .is_some_and(|s| matches!(s, PathSegment::Variant(_, _)));
2773            if ends_with_variant {
2774                continue;
2775            }
2776
2777            let path_segments: alloc::vec::Vec<&str> = field_info
2778                .path
2779                .segments()
2780                .iter()
2781                .filter_map(|s| match s {
2782                    PathSegment::Field(name) => Some(*name),
2783                    PathSegment::Variant(_, _) => None,
2784                })
2785                .collect();
2786
2787            // Check if this field's parent was touched
2788            let first_segment = path_segments.first().copied();
2789            let parent_touched = first_segment
2790                .map(|s| touched_top_fields.contains(s))
2791                .unwrap_or(false);
2792
2793            // If parent wasn't touched at all, we might default the whole parent
2794            // For now, handle individual field defaults
2795            let field_has_default = field_info.field.has_default();
2796            let field_type_has_default = field_info.value_shape.is(Characteristic::Default);
2797            let field_is_option = matches!(field_info.value_shape.def, Def::Option(_));
2798
2799            if field_has_default
2800                || field_type_has_default
2801                || field_is_option
2802                || field_info.field.should_skip_deserializing()
2803            {
2804                // Navigate to the field and set default
2805                for &segment in &path_segments[..path_segments.len().saturating_sub(1)] {
2806                    wip = wip
2807                        .begin_field(segment)
2808                        .map_err(DeserializeError::reflect)?;
2809                    if matches!(wip.shape().def, Def::Option(_)) {
2810                        wip = wip.begin_some().map_err(DeserializeError::reflect)?;
2811                    }
2812                }
2813
2814                if let Some(&last) = path_segments.last() {
2815                    wip = wip.begin_field(last).map_err(DeserializeError::reflect)?;
2816                    wip = wip.set_default().map_err(DeserializeError::reflect)?;
2817                    wip = wip.end().map_err(DeserializeError::reflect)?;
2818                }
2819
2820                // Close the path we opened
2821                for _ in 0..path_segments.len().saturating_sub(1) {
2822                    // Need to check if we're in an option
2823                    wip = wip.end().map_err(DeserializeError::reflect)?;
2824                }
2825            } else if !parent_touched && path_segments.len() > 1 {
2826                // Parent wasn't touched and field has no default - this is OK if the whole
2827                // parent can be defaulted (handled by deferred mode)
2828                continue;
2829            } else if field_info.required {
2830                return Err(DeserializeError::TypeMismatch {
2831                    expected: "field to be present or have default",
2832                    got: format!("missing field '{}'", field_info.serialized_name),
2833                    span: self.last_span,
2834                    path: None,
2835                });
2836            }
2837        }
2838
2839        // Finish deferred mode (only if we started it)
2840        if !already_deferred {
2841            wip = wip.finish_deferred().map_err(DeserializeError::reflect)?;
2842        }
2843
2844        Ok(wip)
2845    }
2846
2847    /// Deserialize the struct fields of a variant.
2848    /// Expects the variant to already be selected.
2849    fn deserialize_variant_struct_fields(
2850        &mut self,
2851        mut wip: Partial<'input, BORROW>,
2852    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
2853        use facet_core::StructKind;
2854
2855        let variant = wip
2856            .selected_variant()
2857            .ok_or_else(|| DeserializeError::TypeMismatch {
2858                expected: "selected variant",
2859                got: "no variant selected".into(),
2860                span: self.last_span,
2861                path: None,
2862            })?;
2863
2864        let variant_fields = variant.data.fields;
2865        let kind = variant.data.kind;
2866
2867        // Handle based on variant kind
2868        match kind {
2869            StructKind::TupleStruct if variant_fields.len() == 1 => {
2870                // Single-element tuple variant (newtype): deserialize the inner value directly
2871                wip = wip.begin_nth_field(0).map_err(DeserializeError::reflect)?;
2872                wip = self.deserialize_into(wip)?;
2873                wip = wip.end().map_err(DeserializeError::reflect)?;
2874                return Ok(wip);
2875            }
2876            StructKind::TupleStruct | StructKind::Tuple => {
2877                // Multi-element tuple variant - not yet supported in this context
2878                return Err(DeserializeError::Unsupported(
2879                    "multi-element tuple variants in flatten not yet supported".into(),
2880                ));
2881            }
2882            StructKind::Unit => {
2883                // Unit variant - nothing to deserialize
2884                return Ok(wip);
2885            }
2886            StructKind::Struct => {
2887                // Struct variant - fall through to struct deserialization below
2888            }
2889        }
2890
2891        // Struct variant: deserialize as a struct with named fields
2892        // Expect StructStart for the variant content
2893        let event = self.expect_event("value")?;
2894        if !matches!(event, ParseEvent::StructStart(_)) {
2895            return Err(DeserializeError::TypeMismatch {
2896                expected: "struct start for variant content",
2897                got: format!("{event:?}"),
2898                span: self.last_span,
2899                path: None,
2900            });
2901        }
2902
2903        // Track which fields have been set
2904        let num_fields = variant_fields.len();
2905        let mut fields_set = alloc::vec![false; num_fields];
2906
2907        // Process all fields
2908        loop {
2909            let event = self.expect_event("value")?;
2910            match event {
2911                ParseEvent::StructEnd => break,
2912                ParseEvent::FieldKey(key) => {
2913                    // Look up field in variant's fields
2914                    let field_info = variant_fields.iter().enumerate().find(|(_, f)| {
2915                        Self::field_matches_with_namespace(
2916                            f,
2917                            key.name.as_ref(),
2918                            key.namespace.as_deref(),
2919                            key.location,
2920                            None,
2921                        )
2922                    });
2923
2924                    if let Some((idx, _field)) = field_info {
2925                        wip = wip
2926                            .begin_nth_field(idx)
2927                            .map_err(DeserializeError::reflect)?;
2928                        wip = self.deserialize_into(wip)?;
2929                        wip = wip.end().map_err(DeserializeError::reflect)?;
2930                        fields_set[idx] = true;
2931                    } else {
2932                        // Unknown field - skip
2933                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
2934                    }
2935                }
2936                other => {
2937                    return Err(DeserializeError::TypeMismatch {
2938                        expected: "field key or struct end",
2939                        got: format!("{other:?}"),
2940                        span: self.last_span,
2941                        path: None,
2942                    });
2943                }
2944            }
2945        }
2946
2947        // Apply defaults for missing fields
2948        for (idx, field) in variant_fields.iter().enumerate() {
2949            if fields_set[idx] {
2950                continue;
2951            }
2952
2953            let field_has_default = field.has_default();
2954            let field_type_has_default = field.shape().is(facet_core::Characteristic::Default);
2955            let field_is_option = matches!(field.shape().def, Def::Option(_));
2956
2957            if field_has_default || field_type_has_default {
2958                wip = wip
2959                    .set_nth_field_to_default(idx)
2960                    .map_err(DeserializeError::reflect)?;
2961            } else if field_is_option {
2962                wip = wip
2963                    .begin_nth_field(idx)
2964                    .map_err(DeserializeError::reflect)?;
2965                wip = wip.set_default().map_err(DeserializeError::reflect)?;
2966                wip = wip.end().map_err(DeserializeError::reflect)?;
2967            } else if field.should_skip_deserializing() {
2968                wip = wip
2969                    .set_nth_field_to_default(idx)
2970                    .map_err(DeserializeError::reflect)?;
2971            } else {
2972                return Err(DeserializeError::TypeMismatch {
2973                    expected: "field to be present or have default",
2974                    got: format!("missing field '{}'", field.name),
2975                    span: self.last_span,
2976                    path: None,
2977                });
2978            }
2979        }
2980
2981        Ok(wip)
2982    }
2983
2984    /// Deserialize into a type with span metadata (like `Spanned<T>`).
2985    ///
2986    /// This handles structs that have:
2987    /// - One or more non-metadata fields (the actual values to deserialize)
2988    /// - A field with `#[facet(metadata = span)]` to store source location
2989    ///
2990    /// The metadata field is populated with a default span since most format parsers
2991    /// don't track source locations.
2992    fn deserialize_spanned(
2993        &mut self,
2994        mut wip: Partial<'input, BORROW>,
2995    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
2996        let shape = wip.shape();
2997
2998        // Find the span metadata field and non-metadata fields
2999        let Type::User(UserType::Struct(struct_def)) = &shape.ty else {
3000            return Err(DeserializeError::Unsupported(format!(
3001                "expected struct with span metadata, found {}",
3002                shape.type_identifier
3003            )));
3004        };
3005
3006        let span_field = struct_def
3007            .fields
3008            .iter()
3009            .find(|f| f.metadata_kind() == Some("span"))
3010            .ok_or_else(|| {
3011                DeserializeError::Unsupported(format!(
3012                    "expected struct with span metadata field, found {}",
3013                    shape.type_identifier
3014                ))
3015            })?;
3016
3017        let value_fields: alloc::vec::Vec<_> = struct_def
3018            .fields
3019            .iter()
3020            .filter(|f| !f.is_metadata())
3021            .collect();
3022
3023        // Deserialize all non-metadata fields transparently
3024        // For the common case (Spanned<T> with a single "value" field), this is just one field
3025        for field in value_fields {
3026            wip = wip
3027                .begin_field(field.name)
3028                .map_err(DeserializeError::reflect)?;
3029            wip = self.deserialize_into(wip)?;
3030            wip = wip.end().map_err(DeserializeError::reflect)?;
3031        }
3032
3033        // Set the span metadata field to default
3034        // Most format parsers don't track source spans, so we use a default (unknown) span
3035        wip = wip
3036            .begin_field(span_field.name)
3037            .map_err(DeserializeError::reflect)?;
3038        wip = wip.set_default().map_err(DeserializeError::reflect)?;
3039        wip = wip.end().map_err(DeserializeError::reflect)?;
3040
3041        Ok(wip)
3042    }
3043
3044    fn deserialize_tuple(
3045        &mut self,
3046        mut wip: Partial<'input, BORROW>,
3047    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3048        // Get field count for tuple hints (needed for non-self-describing formats like postcard)
3049        let field_count = match &wip.shape().ty {
3050            Type::User(UserType::Struct(def)) => def.fields.len(),
3051            _ => 0, // Unit type or unknown - will be handled below
3052        };
3053
3054        // Hint to non-self-describing parsers how many fields to expect
3055        // Tuples are like positional structs, so we use hint_struct_fields
3056        self.parser.hint_struct_fields(field_count);
3057
3058        let event = self.expect_peek("value")?;
3059
3060        // Special case: newtype structs (single-field tuple structs) can accept scalar values
3061        // directly without requiring a sequence wrapper. This enables patterns like:
3062        //   struct Wrapper(i32);
3063        //   toml: "value = 42"  ->  Wrapper(42)
3064        if field_count == 1 && matches!(event, ParseEvent::Scalar(_)) {
3065            // Unwrap into field "0" and deserialize the scalar
3066            wip = wip.begin_field("0").map_err(DeserializeError::reflect)?;
3067            wip = self.deserialize_into(wip)?;
3068            wip = wip.end().map_err(DeserializeError::reflect)?;
3069            return Ok(wip);
3070        }
3071
3072        let event = self.expect_event("value")?;
3073
3074        // Accept either SequenceStart (JSON arrays) or StructStart (for XML elements or
3075        // non-self-describing formats like postcard where tuples are positional structs)
3076        let struct_mode = match event {
3077            ParseEvent::SequenceStart(_) => false,
3078            // Ambiguous containers (XML elements) always use struct mode
3079            ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
3080            // For non-self-describing formats, StructStart(Object) is valid for tuples
3081            // because hint_struct_fields was called and tuples are positional structs
3082            ParseEvent::StructStart(_) if !self.parser.is_self_describing() => true,
3083            // For self-describing formats like TOML/JSON, objects with numeric keys
3084            // (e.g., { "0" = true, "1" = 1 }) are valid tuple representations
3085            ParseEvent::StructStart(ContainerKind::Object) => true,
3086            ParseEvent::StructStart(kind) => {
3087                return Err(DeserializeError::TypeMismatch {
3088                    expected: "array",
3089                    got: kind.name().into(),
3090                    span: self.last_span,
3091                    path: None,
3092                });
3093            }
3094            _ => {
3095                return Err(DeserializeError::TypeMismatch {
3096                    expected: "sequence start for tuple",
3097                    got: format!("{event:?}"),
3098                    span: self.last_span,
3099                    path: None,
3100                });
3101            }
3102        };
3103
3104        let mut index = 0usize;
3105        loop {
3106            let event = self.expect_peek("value")?;
3107
3108            // Check for end of container
3109            if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
3110                self.expect_event("value")?;
3111                break;
3112            }
3113
3114            // In struct mode, skip FieldKey events
3115            if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
3116                self.expect_event("value")?;
3117                continue;
3118            }
3119
3120            // Select field by index
3121            let field_name = alloc::string::ToString::to_string(&index);
3122            wip = wip
3123                .begin_field(&field_name)
3124                .map_err(DeserializeError::reflect)?;
3125            wip = self.deserialize_into(wip)?;
3126            wip = wip.end().map_err(DeserializeError::reflect)?;
3127            index += 1;
3128        }
3129
3130        Ok(wip)
3131    }
3132
3133    fn deserialize_enum(
3134        &mut self,
3135        wip: Partial<'input, BORROW>,
3136    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3137        let shape = wip.shape();
3138
3139        // Hint to non-self-describing parsers what variant metadata to expect
3140        if let Type::User(UserType::Enum(enum_def)) = &shape.ty {
3141            let variant_hints: Vec<crate::EnumVariantHint> = enum_def
3142                .variants
3143                .iter()
3144                .map(|v| crate::EnumVariantHint {
3145                    name: v.name,
3146                    kind: v.data.kind,
3147                    field_count: v.data.fields.len(),
3148                })
3149                .collect();
3150            self.parser.hint_enum(&variant_hints);
3151        }
3152
3153        // Check for different tagging modes
3154        let tag_attr = shape.get_tag_attr();
3155        let content_attr = shape.get_content_attr();
3156        let is_numeric = shape.is_numeric();
3157        let is_untagged = shape.is_untagged();
3158
3159        if is_numeric {
3160            return self.deserialize_numeric_enum(wip);
3161        }
3162
3163        // Determine tagging mode
3164        if is_untagged {
3165            return self.deserialize_enum_untagged(wip);
3166        }
3167
3168        if let (Some(tag_key), Some(content_key)) = (tag_attr, content_attr) {
3169            // Adjacently tagged: {"t": "VariantName", "c": {...}}
3170            return self.deserialize_enum_adjacently_tagged(wip, tag_key, content_key);
3171        }
3172
3173        if let Some(tag_key) = tag_attr {
3174            // Internally tagged: {"type": "VariantName", ...fields...}
3175            return self.deserialize_enum_internally_tagged(wip, tag_key);
3176        }
3177
3178        // Externally tagged (default): {"VariantName": {...}} or just "VariantName"
3179        self.deserialize_enum_externally_tagged(wip)
3180    }
3181
3182    fn deserialize_enum_externally_tagged(
3183        &mut self,
3184        mut wip: Partial<'input, BORROW>,
3185    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3186        let event = self.expect_peek("value")?;
3187
3188        // Check for unit variant (just a string)
3189        if let ParseEvent::Scalar(
3190            ScalarValue::Str(variant_name) | ScalarValue::StringlyTyped(variant_name),
3191        ) = &event
3192        {
3193            self.expect_event("value")?;
3194            wip = wip
3195                .select_variant_named(variant_name)
3196                .map_err(DeserializeError::reflect)?;
3197            return Ok(wip);
3198        }
3199
3200        // Otherwise expect a struct { VariantName: ... }
3201        if !matches!(event, ParseEvent::StructStart(_)) {
3202            return Err(DeserializeError::TypeMismatch {
3203                expected: "string or struct for enum",
3204                got: format!("{event:?}"),
3205                span: self.last_span,
3206                path: None,
3207            });
3208        }
3209
3210        self.expect_event("value")?; // consume StructStart
3211
3212        // Get the variant name
3213        let event = self.expect_event("value")?;
3214        let variant_name = match event {
3215            ParseEvent::FieldKey(key) => key.name,
3216            other => {
3217                return Err(DeserializeError::TypeMismatch {
3218                    expected: "variant name",
3219                    got: format!("{other:?}"),
3220                    span: self.last_span,
3221                    path: None,
3222                });
3223            }
3224        };
3225
3226        wip = wip
3227            .select_variant_named(&variant_name)
3228            .map_err(DeserializeError::reflect)?;
3229
3230        // Deserialize the variant content
3231        wip = self.deserialize_enum_variant_content(wip)?;
3232
3233        // Consume StructEnd
3234        let event = self.expect_event("value")?;
3235        if !matches!(event, ParseEvent::StructEnd) {
3236            return Err(DeserializeError::TypeMismatch {
3237                expected: "struct end after enum variant",
3238                got: format!("{event:?}"),
3239                span: self.last_span,
3240                path: None,
3241            });
3242        }
3243
3244        Ok(wip)
3245    }
3246
3247    fn deserialize_enum_internally_tagged(
3248        &mut self,
3249        mut wip: Partial<'input, BORROW>,
3250        tag_key: &str,
3251    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3252        use facet_core::Characteristic;
3253
3254        // Step 1: Probe to find the tag value (handles out-of-order fields)
3255        let probe = self
3256            .parser
3257            .begin_probe()
3258            .map_err(DeserializeError::Parser)?;
3259        let evidence = Self::collect_evidence(probe).map_err(DeserializeError::Parser)?;
3260
3261        let variant_name = Self::find_tag_value(&evidence, tag_key)
3262            .ok_or_else(|| DeserializeError::TypeMismatch {
3263                expected: "tag field in internally tagged enum",
3264                got: format!("missing '{tag_key}' field"),
3265                span: self.last_span,
3266                path: None,
3267            })?
3268            .to_string();
3269
3270        // Step 2: Consume StructStart
3271        let event = self.expect_event("value")?;
3272        if !matches!(event, ParseEvent::StructStart(_)) {
3273            return Err(DeserializeError::TypeMismatch {
3274                expected: "struct for internally tagged enum",
3275                got: format!("{event:?}"),
3276                span: self.last_span,
3277                path: None,
3278            });
3279        }
3280
3281        // Step 3: Select the variant
3282        wip = wip
3283            .select_variant_named(&variant_name)
3284            .map_err(DeserializeError::reflect)?;
3285
3286        // Get the selected variant info
3287        let variant = wip
3288            .selected_variant()
3289            .ok_or_else(|| DeserializeError::TypeMismatch {
3290                expected: "selected variant",
3291                got: "no variant selected".into(),
3292                span: self.last_span,
3293                path: None,
3294            })?;
3295
3296        let variant_fields = variant.data.fields;
3297
3298        // Check if this is a unit variant (no fields)
3299        if variant_fields.is_empty() || variant.data.kind == StructKind::Unit {
3300            // Consume remaining fields in the object
3301            loop {
3302                let event = self.expect_event("value")?;
3303                match event {
3304                    ParseEvent::StructEnd => break,
3305                    ParseEvent::FieldKey(_) => {
3306                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
3307                    }
3308                    other => {
3309                        return Err(DeserializeError::TypeMismatch {
3310                            expected: "field key or struct end",
3311                            got: format!("{other:?}"),
3312                            span: self.last_span,
3313                            path: None,
3314                        });
3315                    }
3316                }
3317            }
3318            return Ok(wip);
3319        }
3320
3321        // Track which fields have been set
3322        let num_fields = variant_fields.len();
3323        let mut fields_set = alloc::vec![false; num_fields];
3324
3325        // Step 4: Process all fields (they can come in any order now)
3326        loop {
3327            let event = self.expect_event("value")?;
3328            match event {
3329                ParseEvent::StructEnd => break,
3330                ParseEvent::FieldKey(key) => {
3331                    // Skip the tag field - already used
3332                    if key.name.as_ref() == tag_key {
3333                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
3334                        continue;
3335                    }
3336
3337                    // Look up field in variant's fields
3338                    // Uses namespace-aware matching when namespace is present
3339                    let field_info = variant_fields.iter().enumerate().find(|(_, f)| {
3340                        Self::field_matches_with_namespace(
3341                            f,
3342                            key.name.as_ref(),
3343                            key.namespace.as_deref(),
3344                            key.location,
3345                            None, // Enums don't have ns_all
3346                        )
3347                    });
3348
3349                    if let Some((idx, _field)) = field_info {
3350                        wip = wip
3351                            .begin_nth_field(idx)
3352                            .map_err(DeserializeError::reflect)?;
3353                        wip = self.deserialize_into(wip)?;
3354                        wip = wip.end().map_err(DeserializeError::reflect)?;
3355                        fields_set[idx] = true;
3356                    } else {
3357                        // Unknown field - skip
3358                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
3359                    }
3360                }
3361                other => {
3362                    return Err(DeserializeError::TypeMismatch {
3363                        expected: "field key or struct end",
3364                        got: format!("{other:?}"),
3365                        span: self.last_span,
3366                        path: None,
3367                    });
3368                }
3369            }
3370        }
3371
3372        // Apply defaults for missing fields
3373        for (idx, field) in variant_fields.iter().enumerate() {
3374            if fields_set[idx] {
3375                continue;
3376            }
3377
3378            let field_has_default = field.has_default();
3379            let field_type_has_default = field.shape().is(Characteristic::Default);
3380            let field_is_option = matches!(field.shape().def, Def::Option(_));
3381
3382            if field_has_default || field_type_has_default {
3383                wip = wip
3384                    .set_nth_field_to_default(idx)
3385                    .map_err(DeserializeError::reflect)?;
3386            } else if field_is_option {
3387                wip = wip
3388                    .begin_nth_field(idx)
3389                    .map_err(DeserializeError::reflect)?;
3390                wip = wip.set_default().map_err(DeserializeError::reflect)?;
3391                wip = wip.end().map_err(DeserializeError::reflect)?;
3392            } else if field.should_skip_deserializing() {
3393                wip = wip
3394                    .set_nth_field_to_default(idx)
3395                    .map_err(DeserializeError::reflect)?;
3396            } else {
3397                return Err(DeserializeError::TypeMismatch {
3398                    expected: "field to be present or have default",
3399                    got: format!("missing field '{}'", field.name),
3400                    span: self.last_span,
3401                    path: None,
3402                });
3403            }
3404        }
3405
3406        Ok(wip)
3407    }
3408
3409    /// Helper to find a tag value from field evidence.
3410    fn find_tag_value<'a>(
3411        evidence: &'a [crate::FieldEvidence<'input>],
3412        tag_key: &str,
3413    ) -> Option<&'a str> {
3414        evidence
3415            .iter()
3416            .find(|e| e.name == tag_key)
3417            .and_then(|e| match &e.scalar_value {
3418                Some(ScalarValue::Str(s) | ScalarValue::StringlyTyped(s)) => Some(s.as_ref()),
3419                _ => None,
3420            })
3421    }
3422
3423    /// Helper to collect all evidence from a probe stream.
3424    fn collect_evidence<S: crate::ProbeStream<'input, Error = P::Error>>(
3425        mut probe: S,
3426    ) -> Result<alloc::vec::Vec<crate::FieldEvidence<'input>>, P::Error> {
3427        let mut evidence = alloc::vec::Vec::new();
3428        while let Some(ev) = probe.next()? {
3429            evidence.push(ev);
3430        }
3431        Ok(evidence)
3432    }
3433
3434    fn deserialize_enum_adjacently_tagged(
3435        &mut self,
3436        mut wip: Partial<'input, BORROW>,
3437        tag_key: &str,
3438        content_key: &str,
3439    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3440        // Step 1: Probe to find the tag value (handles out-of-order fields)
3441        let probe = self
3442            .parser
3443            .begin_probe()
3444            .map_err(DeserializeError::Parser)?;
3445        let evidence = Self::collect_evidence(probe).map_err(DeserializeError::Parser)?;
3446
3447        let variant_name = Self::find_tag_value(&evidence, tag_key)
3448            .ok_or_else(|| DeserializeError::TypeMismatch {
3449                expected: "tag field in adjacently tagged enum",
3450                got: format!("missing '{tag_key}' field"),
3451                span: self.last_span,
3452                path: None,
3453            })?
3454            .to_string();
3455
3456        // Step 2: Consume StructStart
3457        let event = self.expect_event("value")?;
3458        if !matches!(event, ParseEvent::StructStart(_)) {
3459            return Err(DeserializeError::TypeMismatch {
3460                expected: "struct for adjacently tagged enum",
3461                got: format!("{event:?}"),
3462                span: self.last_span,
3463                path: None,
3464            });
3465        }
3466
3467        // Step 3: Select the variant
3468        wip = wip
3469            .select_variant_named(&variant_name)
3470            .map_err(DeserializeError::reflect)?;
3471
3472        // Step 4: Process fields in any order
3473        let mut content_seen = false;
3474        loop {
3475            let event = self.expect_event("value")?;
3476            match event {
3477                ParseEvent::StructEnd => break,
3478                ParseEvent::FieldKey(key) => {
3479                    if key.name.as_ref() == tag_key {
3480                        // Skip the tag field - already used
3481                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
3482                    } else if key.name.as_ref() == content_key {
3483                        // Deserialize the content
3484                        wip = self.deserialize_enum_variant_content(wip)?;
3485                        content_seen = true;
3486                    } else {
3487                        // Unknown field - skip
3488                        self.parser.skip_value().map_err(DeserializeError::Parser)?;
3489                    }
3490                }
3491                other => {
3492                    return Err(DeserializeError::TypeMismatch {
3493                        expected: "field key or struct end",
3494                        got: format!("{other:?}"),
3495                        span: self.last_span,
3496                        path: None,
3497                    });
3498                }
3499            }
3500        }
3501
3502        // If no content field was present, it's a unit variant (already selected above)
3503        if !content_seen {
3504            // Check if the variant expects content
3505            let variant = wip.selected_variant();
3506            if let Some(v) = variant
3507                && v.data.kind != StructKind::Unit
3508                && !v.data.fields.is_empty()
3509            {
3510                return Err(DeserializeError::TypeMismatch {
3511                    expected: "content field for non-unit variant",
3512                    got: format!("missing '{content_key}' field"),
3513                    span: self.last_span,
3514                    path: None,
3515                });
3516            }
3517        }
3518
3519        Ok(wip)
3520    }
3521
3522    fn deserialize_enum_variant_content(
3523        &mut self,
3524        mut wip: Partial<'input, BORROW>,
3525    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3526        use facet_core::Characteristic;
3527
3528        // Get the selected variant's info
3529        let variant = wip
3530            .selected_variant()
3531            .ok_or_else(|| DeserializeError::TypeMismatch {
3532                expected: "selected variant",
3533                got: "no variant selected".into(),
3534                span: self.last_span,
3535                path: None,
3536            })?;
3537
3538        let variant_kind = variant.data.kind;
3539        let variant_fields = variant.data.fields;
3540
3541        match variant_kind {
3542            StructKind::Unit => {
3543                // Unit variant - normally nothing to deserialize
3544                // But some formats (like TOML with [VariantName]) might emit an empty struct
3545                // Check if there's a StructStart that we need to consume
3546                let event = self.expect_peek("value")?;
3547                if matches!(event, ParseEvent::StructStart(_)) {
3548                    self.expect_event("value")?; // consume StructStart
3549                    // Expect immediate StructEnd for empty struct
3550                    let end_event = self.expect_event("value")?;
3551                    if !matches!(end_event, ParseEvent::StructEnd) {
3552                        return Err(DeserializeError::TypeMismatch {
3553                            expected: "empty struct for unit variant",
3554                            got: format!("{end_event:?}"),
3555                            span: self.last_span,
3556                            path: None,
3557                        });
3558                    }
3559                }
3560                Ok(wip)
3561            }
3562            StructKind::Tuple | StructKind::TupleStruct => {
3563                if variant_fields.len() == 1 {
3564                    // Newtype variant - content is the single field's value
3565                    wip = wip.begin_nth_field(0).map_err(DeserializeError::reflect)?;
3566                    wip = self.deserialize_into(wip)?;
3567                    wip = wip.end().map_err(DeserializeError::reflect)?;
3568                } else {
3569                    // Multi-field tuple variant - expect array or struct (for XML/TOML with numeric keys)
3570                    let event = self.expect_event("value")?;
3571
3572                    // Accept SequenceStart (JSON arrays), ambiguous StructStart (XML elements),
3573                    // or Object StructStart (TOML/JSON with numeric keys like "0", "1")
3574                    let struct_mode = match event {
3575                        ParseEvent::SequenceStart(_) => false,
3576                        ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
3577                        // Accept objects with numeric keys as valid tuple representations
3578                        ParseEvent::StructStart(ContainerKind::Object) => true,
3579                        ParseEvent::StructStart(kind) => {
3580                            return Err(DeserializeError::TypeMismatch {
3581                                expected: "array",
3582                                got: kind.name().into(),
3583                                span: self.last_span,
3584                                path: None,
3585                            });
3586                        }
3587                        _ => {
3588                            return Err(DeserializeError::TypeMismatch {
3589                                expected: "sequence for tuple variant",
3590                                got: format!("{event:?}"),
3591                                span: self.last_span,
3592                                path: None,
3593                            });
3594                        }
3595                    };
3596
3597                    let mut idx = 0;
3598                    while idx < variant_fields.len() {
3599                        // In struct mode, skip FieldKey events
3600                        if struct_mode {
3601                            let event = self.expect_peek("value")?;
3602                            if matches!(event, ParseEvent::FieldKey(_)) {
3603                                self.expect_event("value")?;
3604                                continue;
3605                            }
3606                        }
3607
3608                        wip = wip
3609                            .begin_nth_field(idx)
3610                            .map_err(DeserializeError::reflect)?;
3611                        wip = self.deserialize_into(wip)?;
3612                        wip = wip.end().map_err(DeserializeError::reflect)?;
3613                        idx += 1;
3614                    }
3615
3616                    let event = self.expect_event("value")?;
3617                    if !matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
3618                        return Err(DeserializeError::TypeMismatch {
3619                            expected: "sequence end for tuple variant",
3620                            got: format!("{event:?}"),
3621                            span: self.last_span,
3622                            path: None,
3623                        });
3624                    }
3625                }
3626                Ok(wip)
3627            }
3628            StructKind::Struct => {
3629                // Struct variant - expect object with fields
3630                let event = self.expect_event("value")?;
3631                if !matches!(event, ParseEvent::StructStart(_)) {
3632                    return Err(DeserializeError::TypeMismatch {
3633                        expected: "struct for struct variant",
3634                        got: format!("{event:?}"),
3635                        span: self.last_span,
3636                        path: None,
3637                    });
3638                }
3639
3640                let num_fields = variant_fields.len();
3641                let mut fields_set = alloc::vec![false; num_fields];
3642                let mut ordered_field_index = 0usize;
3643
3644                loop {
3645                    let event = self.expect_event("value")?;
3646                    match event {
3647                        ParseEvent::StructEnd => break,
3648                        ParseEvent::OrderedField => {
3649                            // Non-self-describing formats emit OrderedField events in order
3650                            let idx = ordered_field_index;
3651                            ordered_field_index += 1;
3652                            if idx < num_fields {
3653                                wip = wip
3654                                    .begin_nth_field(idx)
3655                                    .map_err(DeserializeError::reflect)?;
3656                                wip = self.deserialize_into(wip)?;
3657                                wip = wip.end().map_err(DeserializeError::reflect)?;
3658                                fields_set[idx] = true;
3659                            }
3660                        }
3661                        ParseEvent::FieldKey(key) => {
3662                            // Uses namespace-aware matching when namespace is present
3663                            let field_info = variant_fields.iter().enumerate().find(|(_, f)| {
3664                                Self::field_matches_with_namespace(
3665                                    f,
3666                                    key.name.as_ref(),
3667                                    key.namespace.as_deref(),
3668                                    key.location,
3669                                    None, // Enums don't have ns_all
3670                                )
3671                            });
3672
3673                            if let Some((idx, _field)) = field_info {
3674                                wip = wip
3675                                    .begin_nth_field(idx)
3676                                    .map_err(DeserializeError::reflect)?;
3677                                wip = self.deserialize_into(wip)?;
3678                                wip = wip.end().map_err(DeserializeError::reflect)?;
3679                                fields_set[idx] = true;
3680                            } else {
3681                                // Unknown field - skip
3682                                self.parser.skip_value().map_err(DeserializeError::Parser)?;
3683                            }
3684                        }
3685                        other => {
3686                            return Err(DeserializeError::TypeMismatch {
3687                                expected: "field key, ordered field, or struct end",
3688                                got: format!("{other:?}"),
3689                                span: self.last_span,
3690                                path: None,
3691                            });
3692                        }
3693                    }
3694                }
3695
3696                // Apply defaults for missing fields
3697                for (idx, field) in variant_fields.iter().enumerate() {
3698                    if fields_set[idx] {
3699                        continue;
3700                    }
3701
3702                    let field_has_default = field.has_default();
3703                    let field_type_has_default = field.shape().is(Characteristic::Default);
3704                    let field_is_option = matches!(field.shape().def, Def::Option(_));
3705
3706                    if field_has_default || field_type_has_default {
3707                        wip = wip
3708                            .set_nth_field_to_default(idx)
3709                            .map_err(DeserializeError::reflect)?;
3710                    } else if field_is_option {
3711                        wip = wip
3712                            .begin_nth_field(idx)
3713                            .map_err(DeserializeError::reflect)?;
3714                        wip = wip.set_default().map_err(DeserializeError::reflect)?;
3715                        wip = wip.end().map_err(DeserializeError::reflect)?;
3716                    } else if field.should_skip_deserializing() {
3717                        wip = wip
3718                            .set_nth_field_to_default(idx)
3719                            .map_err(DeserializeError::reflect)?;
3720                    } else {
3721                        return Err(DeserializeError::TypeMismatch {
3722                            expected: "field to be present or have default",
3723                            got: format!("missing field '{}'", field.name),
3724                            span: self.last_span,
3725                            path: None,
3726                        });
3727                    }
3728                }
3729
3730                Ok(wip)
3731            }
3732        }
3733    }
3734
3735    fn deserialize_numeric_enum(
3736        &mut self,
3737        mut wip: Partial<'input, BORROW>,
3738    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3739        let event = self.parser.peek_event().map_err(DeserializeError::Parser)?;
3740
3741        if let Some(ParseEvent::Scalar(scalar)) = event {
3742            let span = self.last_span;
3743            wip = match scalar {
3744                ScalarValue::I64(discriminant) => {
3745                    wip.select_variant(discriminant)
3746                        .map_err(|error| DeserializeError::Reflect {
3747                            error,
3748                            span,
3749                            path: None,
3750                        })?
3751                }
3752                ScalarValue::U64(discriminant) => {
3753                    wip.select_variant(discriminant as i64).map_err(|error| {
3754                        DeserializeError::Reflect {
3755                            error,
3756                            span,
3757                            path: None,
3758                        }
3759                    })?
3760                }
3761                ScalarValue::Str(str_discriminant)
3762                | ScalarValue::StringlyTyped(str_discriminant) => {
3763                    let discriminant =
3764                        str_discriminant
3765                            .parse()
3766                            .map_err(|_| DeserializeError::TypeMismatch {
3767                                expected: "String representing an integer (i64)",
3768                                got: str_discriminant.to_string(),
3769                                span: self.last_span,
3770                                path: None,
3771                            })?;
3772                    wip.select_variant(discriminant)
3773                        .map_err(|error| DeserializeError::Reflect {
3774                            error,
3775                            span,
3776                            path: None,
3777                        })?
3778                }
3779                _ => {
3780                    return Err(DeserializeError::Unsupported(
3781                        "Unexpected ScalarValue".to_string(),
3782                    ));
3783                }
3784            };
3785            self.parser.next_event().map_err(DeserializeError::Parser)?;
3786            Ok(wip)
3787        } else {
3788            Err(DeserializeError::Unsupported(
3789                "Expected integer value".to_string(),
3790            ))
3791        }
3792    }
3793
3794    fn deserialize_enum_untagged(
3795        &mut self,
3796        mut wip: Partial<'input, BORROW>,
3797    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
3798        use facet_solver::VariantsByFormat;
3799
3800        let shape = wip.shape();
3801        let variants_by_format = VariantsByFormat::from_shape(shape).ok_or_else(|| {
3802            DeserializeError::Unsupported("expected enum type for untagged".into())
3803        })?;
3804
3805        let event = self.expect_peek("value")?;
3806
3807        match &event {
3808            ParseEvent::Scalar(scalar) => {
3809                // Try unit variants for null
3810                if matches!(scalar, ScalarValue::Null)
3811                    && let Some(variant) = variants_by_format.unit_variants.first()
3812                {
3813                    wip = wip
3814                        .select_variant_named(variant.name)
3815                        .map_err(DeserializeError::reflect)?;
3816                    // Consume the null
3817                    self.expect_event("value")?;
3818                    return Ok(wip);
3819                }
3820
3821                // Try unit variants for string values (match variant name)
3822                // This handles untagged enums with only unit variants like:
3823                // #[facet(untagged)] enum Color { Red, Green, Blue }
3824                // which deserialize from "Red", "Green", "Blue"
3825                if let ScalarValue::Str(s) | ScalarValue::StringlyTyped(s) = scalar {
3826                    // For StringlyTyped, handle "null" specially - it should match
3827                    // unit variants named "Null" (case-insensitive) since stringly
3828                    // formats like XML don't have a native null type.
3829                    let is_stringly_null = matches!(scalar, ScalarValue::StringlyTyped(_))
3830                        && s.as_ref().eq_ignore_ascii_case("null");
3831
3832                    for variant in &variants_by_format.unit_variants {
3833                        // Match against variant name or rename attribute
3834                        let variant_display_name = variant
3835                            .get_builtin_attr("rename")
3836                            .and_then(|attr| attr.get_as::<&str>().copied())
3837                            .unwrap_or(variant.name);
3838
3839                        // For StringlyTyped("null"), match any variant named "Null" or "null"
3840                        let matches = if is_stringly_null {
3841                            variant_display_name.eq_ignore_ascii_case("null")
3842                        } else {
3843                            s.as_ref() == variant_display_name
3844                        };
3845
3846                        if matches {
3847                            wip = wip
3848                                .select_variant_named(variant.name)
3849                                .map_err(DeserializeError::reflect)?;
3850                            // Consume the string
3851                            self.expect_event("value")?;
3852                            return Ok(wip);
3853                        }
3854                    }
3855                }
3856
3857                // ┌─────────────────────────────────────────────────────────────────┐
3858                // │ UNTAGGED ENUM SCALAR VARIANT DISCRIMINATION                       │
3859                // └─────────────────────────────────────────────────────────────────┘
3860                //
3861                // For untagged enums, we try to match scalar values against variant
3862                // types. Since we can't backtrack parser state, we use the first
3863                // variant that matches.
3864                //
3865                // ## Regular Scalars (I64, Str, Bool, etc.)
3866                //
3867                // For typed scalars, we simply try variants in definition order.
3868                // The first matching variant wins. This is predictable and matches
3869                // user expectations based on how they defined their enum.
3870                //
3871                // ## StringlyTyped Scalars (from XML and other text-based formats)
3872                //
3873                // StringlyTyped represents a value that arrived as text but may
3874                // encode a more specific type. For example, XML `<value>42</value>`
3875                // produces StringlyTyped("42"), which could be:
3876                //   - A String (any text is valid)
3877                //   - A u64 (if it parses as a number)
3878                //   - NOT a bool (doesn't parse as true/false)
3879                //
3880                // The problem: String always matches StringlyTyped, so if String
3881                // comes first in the enum definition, it would always win.
3882                //
3883                // Solution: Two-tier matching for StringlyTyped:
3884                //
3885                //   **Tier 1 (Parseable types)**: Try non-string types that can
3886                //   parse the value (u64, i32, bool, IpAddr, etc.). First match wins.
3887                //
3888                //   **Tier 2 (String fallback)**: If no parseable type matched,
3889                //   fall back to String/Str/CowStr variants.
3890                //
3891                // This ensures StringlyTyped("42") matches Number(u64) over
3892                // String(String), regardless of definition order, while still
3893                // allowing String as a catch-all fallback.
3894                //
3895                // Example:
3896                //   #[facet(untagged)]
3897                //   enum Value {
3898                //       Text(String),    // Tier 2: fallback
3899                //       Number(u64),     // Tier 1: parseable
3900                //       Flag(bool),      // Tier 1: parseable
3901                //   }
3902                //
3903                //   StringlyTyped("42")    → Number(42)   (parses as u64)
3904                //   StringlyTyped("true")  → Flag(true)   (parses as bool)
3905                //   StringlyTyped("hello") → Text(hello)  (fallback to String)
3906
3907                let is_stringly_typed = matches!(scalar, ScalarValue::StringlyTyped(_));
3908
3909                // Tier 1: Try variants that match the scalar type
3910                // For StringlyTyped, skip string types (they're Tier 2 fallback)
3911                for (variant, inner_shape) in &variants_by_format.scalar_variants {
3912                    // For StringlyTyped, defer String-like types to Tier 2
3913                    if is_stringly_typed
3914                        && let Some(st) = inner_shape.scalar_type()
3915                        && matches!(
3916                            st,
3917                            facet_core::ScalarType::String
3918                                | facet_core::ScalarType::Str
3919                                | facet_core::ScalarType::CowStr
3920                        )
3921                    {
3922                        continue;
3923                    }
3924
3925                    if self.scalar_matches_shape(scalar, inner_shape) {
3926                        wip = wip
3927                            .select_variant_named(variant.name)
3928                            .map_err(DeserializeError::reflect)?;
3929                        wip = self.deserialize_enum_variant_content(wip)?;
3930                        return Ok(wip);
3931                    }
3932                }
3933
3934                // Tier 2: For StringlyTyped, try string types as fallback
3935                if is_stringly_typed {
3936                    for (variant, inner_shape) in &variants_by_format.scalar_variants {
3937                        if let Some(st) = inner_shape.scalar_type()
3938                            && matches!(
3939                                st,
3940                                facet_core::ScalarType::String
3941                                    | facet_core::ScalarType::Str
3942                                    | facet_core::ScalarType::CowStr
3943                            )
3944                            && self.scalar_matches_shape(scalar, inner_shape)
3945                        {
3946                            wip = wip
3947                                .select_variant_named(variant.name)
3948                                .map_err(DeserializeError::reflect)?;
3949                            wip = self.deserialize_enum_variant_content(wip)?;
3950                            return Ok(wip);
3951                        }
3952                    }
3953                }
3954
3955                // Try other scalar variants that don't match primitive types.
3956                // This handles cases like newtype variants wrapping enums with #[facet(rename)]:
3957                //   #[facet(untagged)]
3958                //   enum EditionOrWorkspace {
3959                //       Edition(Edition),  // Edition is an enum with #[facet(rename = "2024")]
3960                //       Workspace(WorkspaceRef),
3961                //   }
3962                // When deserializing "2024", Edition doesn't match as a primitive scalar,
3963                // but it CAN be deserialized from the string via its renamed unit variants.
3964                for (variant, inner_shape) in &variants_by_format.scalar_variants {
3965                    if !self.scalar_matches_shape(scalar, inner_shape) {
3966                        wip = wip
3967                            .select_variant_named(variant.name)
3968                            .map_err(DeserializeError::reflect)?;
3969                        // Try to deserialize - if this fails, it will bubble up as an error.
3970                        // TODO: Implement proper variant trying with backtracking for better error messages
3971                        wip = self.deserialize_enum_variant_content(wip)?;
3972                        return Ok(wip);
3973                    }
3974                }
3975
3976                Err(DeserializeError::TypeMismatch {
3977                    expected: "matching untagged variant for scalar",
3978                    got: format!("{:?}", scalar),
3979                    span: self.last_span,
3980                    path: None,
3981                })
3982            }
3983            ParseEvent::StructStart(_) => {
3984                // For struct input, use solve_variant for proper field-based matching
3985                match crate::solve_variant(shape, &mut self.parser) {
3986                    Ok(Some(outcome)) => {
3987                        // Successfully identified which variant matches based on fields
3988                        let resolution = outcome.resolution();
3989                        // For top-level untagged enum, there should be exactly one variant selection
3990                        let variant_name = resolution
3991                            .variant_selections()
3992                            .first()
3993                            .map(|vs| vs.variant_name)
3994                            .ok_or_else(|| {
3995                                DeserializeError::Unsupported(
3996                                    "solved resolution has no variant selection".into(),
3997                                )
3998                            })?;
3999                        wip = wip
4000                            .select_variant_named(variant_name)
4001                            .map_err(DeserializeError::reflect)?;
4002                        wip = self.deserialize_enum_variant_content(wip)?;
4003                        Ok(wip)
4004                    }
4005                    Ok(None) => {
4006                        // No variant matched - fall back to trying the first struct variant
4007                        // (we can't backtrack parser state to try multiple variants)
4008                        if let Some(variant) = variants_by_format.struct_variants.first() {
4009                            wip = wip
4010                                .select_variant_named(variant.name)
4011                                .map_err(DeserializeError::reflect)?;
4012                            wip = self.deserialize_enum_variant_content(wip)?;
4013                            Ok(wip)
4014                        } else {
4015                            Err(DeserializeError::Unsupported(
4016                                "no struct variant found for untagged enum with struct input"
4017                                    .into(),
4018                            ))
4019                        }
4020                    }
4021                    Err(_) => Err(DeserializeError::Unsupported(
4022                        "failed to solve variant for untagged enum".into(),
4023                    )),
4024                }
4025            }
4026            ParseEvent::SequenceStart(_) => {
4027                // For sequence input, use first tuple variant
4028                if let Some((variant, _arity)) = variants_by_format.tuple_variants.first() {
4029                    wip = wip
4030                        .select_variant_named(variant.name)
4031                        .map_err(DeserializeError::reflect)?;
4032                    wip = self.deserialize_enum_variant_content(wip)?;
4033                    return Ok(wip);
4034                }
4035
4036                Err(DeserializeError::Unsupported(
4037                    "no tuple variant found for untagged enum with sequence input".into(),
4038                ))
4039            }
4040            _ => Err(DeserializeError::TypeMismatch {
4041                expected: "scalar, struct, or sequence for untagged enum",
4042                got: format!("{:?}", event),
4043                span: self.last_span,
4044                path: None,
4045            }),
4046        }
4047    }
4048
4049    fn scalar_matches_shape(
4050        &self,
4051        scalar: &ScalarValue<'input>,
4052        shape: &'static facet_core::Shape,
4053    ) -> bool {
4054        use facet_core::ScalarType;
4055
4056        let Some(scalar_type) = shape.scalar_type() else {
4057            // Not a scalar type - check for Option wrapping null
4058            if matches!(scalar, ScalarValue::Null) {
4059                return matches!(shape.def, Def::Option(_));
4060            }
4061            return false;
4062        };
4063
4064        match scalar {
4065            ScalarValue::Bool(_) => matches!(scalar_type, ScalarType::Bool),
4066            ScalarValue::Char(_) => matches!(scalar_type, ScalarType::Char),
4067            ScalarValue::I64(val) => {
4068                // I64 matches signed types directly
4069                if matches!(
4070                    scalar_type,
4071                    ScalarType::I8
4072                        | ScalarType::I16
4073                        | ScalarType::I32
4074                        | ScalarType::I64
4075                        | ScalarType::I128
4076                        | ScalarType::ISize
4077                ) {
4078                    return true;
4079                }
4080
4081                // I64 can also match unsigned types if the value is non-negative and in range
4082                // This handles TOML's requirement to represent all integers as i64
4083                if *val >= 0 {
4084                    let uval = *val as u64;
4085                    match scalar_type {
4086                        ScalarType::U8 => uval <= u8::MAX as u64,
4087                        ScalarType::U16 => uval <= u16::MAX as u64,
4088                        ScalarType::U32 => uval <= u32::MAX as u64,
4089                        ScalarType::U64 | ScalarType::U128 | ScalarType::USize => true,
4090                        _ => false,
4091                    }
4092                } else {
4093                    false
4094                }
4095            }
4096            ScalarValue::U64(_) => matches!(
4097                scalar_type,
4098                ScalarType::U8
4099                    | ScalarType::U16
4100                    | ScalarType::U32
4101                    | ScalarType::U64
4102                    | ScalarType::U128
4103                    | ScalarType::USize
4104            ),
4105            ScalarValue::U128(_) => matches!(scalar_type, ScalarType::U128 | ScalarType::I128),
4106            ScalarValue::I128(_) => matches!(scalar_type, ScalarType::I128 | ScalarType::U128),
4107            ScalarValue::F64(_) => matches!(scalar_type, ScalarType::F32 | ScalarType::F64),
4108            ScalarValue::Str(s) => {
4109                // String scalars match string types directly
4110                if matches!(
4111                    scalar_type,
4112                    ScalarType::String | ScalarType::Str | ScalarType::CowStr | ScalarType::Char
4113                ) {
4114                    return true;
4115                }
4116                // For other scalar types, check if the shape has a parse function
4117                // and if so, try parsing the string to see if it would succeed.
4118                // This enables untagged enums to correctly match string values like "4.625"
4119                // to the appropriate variant (f64 vs i64).
4120                // See #1615 for discussion of this double-parse pattern.
4121                #[allow(unsafe_code)]
4122                if shape.vtable.has_parse()
4123                    && shape
4124                        .layout
4125                        .sized_layout()
4126                        .is_ok_and(|layout| layout.size() <= 128)
4127                {
4128                    // Attempt to parse - this is a probe, not the actual deserialization
4129                    let mut temp = [0u8; 128];
4130                    let temp_ptr = facet_core::PtrMut::new(temp.as_mut_ptr());
4131                    // SAFETY: temp buffer is properly aligned and sized for this shape
4132                    if let Some(Ok(())) = unsafe { shape.call_parse(s.as_ref(), temp_ptr) } {
4133                        // Parse succeeded - drop the temp value
4134                        // SAFETY: we just successfully parsed into temp_ptr
4135                        unsafe { shape.call_drop_in_place(temp_ptr) };
4136                        return true;
4137                    }
4138                }
4139                false
4140            }
4141            ScalarValue::Bytes(_) => {
4142                // Bytes don't have a ScalarType - would need to check for Vec<u8> or [u8]
4143                false
4144            }
4145            ScalarValue::Null => {
4146                // Null matches Unit type
4147                matches!(scalar_type, ScalarType::Unit)
4148            }
4149            ScalarValue::StringlyTyped(s) => {
4150                // StringlyTyped can match any scalar type - it will be parsed.
4151                // Use the same logic as Str: check if parse would succeed.
4152                #[allow(unsafe_code)]
4153                if shape.vtable.has_parse()
4154                    && shape
4155                        .layout
4156                        .sized_layout()
4157                        .is_ok_and(|layout| layout.size() <= 128)
4158                {
4159                    // Attempt to parse - this is a probe, not the actual deserialization
4160                    let mut temp = [0u8; 128];
4161                    let temp_ptr = facet_core::PtrMut::new(temp.as_mut_ptr());
4162                    // SAFETY: temp buffer is properly aligned and sized for this shape
4163                    if let Some(Ok(())) = unsafe { shape.call_parse(s.as_ref(), temp_ptr) } {
4164                        // Parse succeeded - drop the temp value
4165                        // SAFETY: we just successfully parsed into temp_ptr
4166                        unsafe { shape.call_drop_in_place(temp_ptr) };
4167                        return true;
4168                    }
4169                }
4170                // StringlyTyped also matches string types directly
4171                matches!(
4172                    scalar_type,
4173                    ScalarType::String | ScalarType::Str | ScalarType::CowStr | ScalarType::Char
4174                )
4175            }
4176        }
4177    }
4178
4179    fn deserialize_list(
4180        &mut self,
4181        mut wip: Partial<'input, BORROW>,
4182    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4183        // Hint to non-self-describing parsers that a sequence is expected
4184        self.parser.hint_sequence();
4185
4186        let event = self.expect_event("value")?;
4187
4188        // Accept either SequenceStart (JSON arrays) or StructStart (XML elements)
4189        // In struct mode, we skip FieldKey events and treat values as sequence items
4190        // Only accept StructStart if the container kind is ambiguous (e.g., XML Element)
4191        let struct_mode = match event {
4192            ParseEvent::SequenceStart(_) => false,
4193            ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
4194            ParseEvent::StructStart(kind) => {
4195                return Err(DeserializeError::TypeMismatch {
4196                    expected: "array",
4197                    got: kind.name().into(),
4198                    span: self.last_span,
4199                    path: None,
4200                });
4201            }
4202            _ => {
4203                return Err(DeserializeError::TypeMismatch {
4204                    expected: "sequence start",
4205                    got: format!("{event:?}"),
4206                    span: self.last_span,
4207                    path: None,
4208                });
4209            }
4210        };
4211
4212        // Initialize the list
4213        wip = wip.begin_list().map_err(DeserializeError::reflect)?;
4214
4215        loop {
4216            let event = self.expect_peek("value")?;
4217
4218            // Check for end of container
4219            if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
4220                self.expect_event("value")?;
4221                break;
4222            }
4223
4224            // In struct mode, skip FieldKey events (they're just labels for items)
4225            if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
4226                self.expect_event("value")?;
4227                continue;
4228            }
4229
4230            wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
4231            wip = self.deserialize_into(wip)?;
4232            wip = wip.end().map_err(DeserializeError::reflect)?;
4233        }
4234
4235        Ok(wip)
4236    }
4237
4238    fn deserialize_array(
4239        &mut self,
4240        mut wip: Partial<'input, BORROW>,
4241    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4242        // Get the fixed array length from the type definition
4243        let array_len = match &wip.shape().def {
4244            Def::Array(array_def) => array_def.n,
4245            _ => {
4246                return Err(DeserializeError::Unsupported(
4247                    "deserialize_array called on non-array type".into(),
4248                ));
4249            }
4250        };
4251
4252        // Hint to non-self-describing parsers that a fixed-size array is expected
4253        // (unlike hint_sequence, this doesn't read a length prefix)
4254        self.parser.hint_array(array_len);
4255
4256        let event = self.expect_event("value")?;
4257
4258        // Accept either SequenceStart (JSON arrays) or StructStart (XML elements)
4259        // Only accept StructStart if the container kind is ambiguous (e.g., XML Element)
4260        let struct_mode = match event {
4261            ParseEvent::SequenceStart(_) => false,
4262            ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
4263            ParseEvent::StructStart(kind) => {
4264                return Err(DeserializeError::TypeMismatch {
4265                    expected: "array",
4266                    got: kind.name().into(),
4267                    span: self.last_span,
4268                    path: None,
4269                });
4270            }
4271            _ => {
4272                return Err(DeserializeError::TypeMismatch {
4273                    expected: "sequence start for array",
4274                    got: format!("{event:?}"),
4275                    span: self.last_span,
4276                    path: None,
4277                });
4278            }
4279        };
4280
4281        // Transition to Array tracker state. This is important for empty arrays
4282        // like [u8; 0] which have no elements to initialize but still need
4283        // their tracker state set correctly for require_full_initialization to pass.
4284        wip = wip.begin_array().map_err(DeserializeError::reflect)?;
4285
4286        let mut index = 0usize;
4287        loop {
4288            let event = self.expect_peek("value")?;
4289
4290            // Check for end of container
4291            if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
4292                self.expect_event("value")?;
4293                break;
4294            }
4295
4296            // In struct mode, skip FieldKey events
4297            if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
4298                self.expect_event("value")?;
4299                continue;
4300            }
4301
4302            wip = wip
4303                .begin_nth_field(index)
4304                .map_err(DeserializeError::reflect)?;
4305            wip = self.deserialize_into(wip)?;
4306            wip = wip.end().map_err(DeserializeError::reflect)?;
4307            index += 1;
4308        }
4309
4310        Ok(wip)
4311    }
4312
4313    fn deserialize_set(
4314        &mut self,
4315        mut wip: Partial<'input, BORROW>,
4316    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4317        // Hint to non-self-describing parsers that a sequence is expected
4318        self.parser.hint_sequence();
4319
4320        let event = self.expect_event("value")?;
4321
4322        // Accept either SequenceStart (JSON arrays) or StructStart (XML elements)
4323        // Only accept StructStart if the container kind is ambiguous (e.g., XML Element)
4324        let struct_mode = match event {
4325            ParseEvent::SequenceStart(_) => false,
4326            ParseEvent::StructStart(kind) if kind.is_ambiguous() => true,
4327            ParseEvent::StructStart(kind) => {
4328                return Err(DeserializeError::TypeMismatch {
4329                    expected: "array",
4330                    got: kind.name().into(),
4331                    span: self.last_span,
4332                    path: None,
4333                });
4334            }
4335            _ => {
4336                return Err(DeserializeError::TypeMismatch {
4337                    expected: "sequence start for set",
4338                    got: format!("{event:?}"),
4339                    span: self.last_span,
4340                    path: None,
4341                });
4342            }
4343        };
4344
4345        // Initialize the set
4346        wip = wip.begin_set().map_err(DeserializeError::reflect)?;
4347
4348        loop {
4349            let event = self.expect_peek("value")?;
4350
4351            // Check for end of container
4352            if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
4353                self.expect_event("value")?;
4354                break;
4355            }
4356
4357            // In struct mode, skip FieldKey events
4358            if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
4359                self.expect_event("value")?;
4360                continue;
4361            }
4362
4363            wip = wip.begin_set_item().map_err(DeserializeError::reflect)?;
4364            wip = self.deserialize_into(wip)?;
4365            wip = wip.end().map_err(DeserializeError::reflect)?;
4366        }
4367
4368        Ok(wip)
4369    }
4370
4371    fn deserialize_map(
4372        &mut self,
4373        mut wip: Partial<'input, BORROW>,
4374    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4375        // For non-self-describing formats, hint that a map is expected
4376        self.parser.hint_map();
4377
4378        let event = self.expect_event("value")?;
4379
4380        // Initialize the map
4381        wip = wip.begin_map().map_err(DeserializeError::reflect)?;
4382
4383        // Handle both self-describing (StructStart) and non-self-describing (SequenceStart) formats
4384        match event {
4385            ParseEvent::StructStart(_) => {
4386                // Self-describing format (e.g., JSON): maps are represented as objects
4387                loop {
4388                    let event = self.expect_event("value")?;
4389                    match event {
4390                        ParseEvent::StructEnd => break,
4391                        ParseEvent::FieldKey(key) => {
4392                            // Begin key
4393                            wip = wip.begin_key().map_err(DeserializeError::reflect)?;
4394                            wip = self.deserialize_map_key(wip, key.name)?;
4395                            wip = wip.end().map_err(DeserializeError::reflect)?;
4396
4397                            // Begin value
4398                            wip = wip.begin_value().map_err(DeserializeError::reflect)?;
4399                            wip = self.deserialize_into(wip)?;
4400                            wip = wip.end().map_err(DeserializeError::reflect)?;
4401                        }
4402                        other => {
4403                            return Err(DeserializeError::TypeMismatch {
4404                                expected: "field key or struct end for map",
4405                                got: format!("{other:?}"),
4406                                span: self.last_span,
4407                                path: None,
4408                            });
4409                        }
4410                    }
4411                }
4412            }
4413            ParseEvent::SequenceStart(_) => {
4414                // Non-self-describing format (e.g., postcard): maps are sequences of key-value pairs
4415                loop {
4416                    let event = self.expect_peek("value")?;
4417                    match event {
4418                        ParseEvent::SequenceEnd => {
4419                            self.expect_event("value")?;
4420                            break;
4421                        }
4422                        ParseEvent::OrderedField => {
4423                            self.expect_event("value")?;
4424
4425                            // Deserialize key
4426                            wip = wip.begin_key().map_err(DeserializeError::reflect)?;
4427                            wip = self.deserialize_into(wip)?;
4428                            wip = wip.end().map_err(DeserializeError::reflect)?;
4429
4430                            // Deserialize value
4431                            wip = wip.begin_value().map_err(DeserializeError::reflect)?;
4432                            wip = self.deserialize_into(wip)?;
4433                            wip = wip.end().map_err(DeserializeError::reflect)?;
4434                        }
4435                        other => {
4436                            return Err(DeserializeError::TypeMismatch {
4437                                expected: "ordered field or sequence end for map",
4438                                got: format!("{other:?}"),
4439                                span: self.last_span,
4440                                path: None,
4441                            });
4442                        }
4443                    }
4444                }
4445            }
4446            other => {
4447                return Err(DeserializeError::TypeMismatch {
4448                    expected: "struct start or sequence start for map",
4449                    got: format!("{other:?}"),
4450                    span: self.last_span,
4451                    path: None,
4452                });
4453            }
4454        }
4455
4456        Ok(wip)
4457    }
4458
4459    fn deserialize_scalar(
4460        &mut self,
4461        mut wip: Partial<'input, BORROW>,
4462    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4463        // Hint to non-self-describing parsers what scalar type is expected
4464        let shape = wip.shape();
4465
4466        // First, try hint_opaque_scalar for types that may have format-specific
4467        // binary representations (e.g., UUID as 16 raw bytes in postcard)
4468        let opaque_handled = match shape.type_identifier {
4469            // Standard primitives are never opaque
4470            "bool" | "u8" | "u16" | "u32" | "u64" | "u128" | "usize" | "i8" | "i16" | "i32"
4471            | "i64" | "i128" | "isize" | "f32" | "f64" | "String" | "&str" | "char" => false,
4472            // For all other scalar types, ask the parser if it handles them specially
4473            _ => self.parser.hint_opaque_scalar(shape.type_identifier, shape),
4474        };
4475
4476        // If the parser didn't handle the opaque type, fall back to standard hints
4477        if !opaque_handled {
4478            let hint = match shape.type_identifier {
4479                "bool" => Some(ScalarTypeHint::Bool),
4480                "u8" => Some(ScalarTypeHint::U8),
4481                "u16" => Some(ScalarTypeHint::U16),
4482                "u32" => Some(ScalarTypeHint::U32),
4483                "u64" => Some(ScalarTypeHint::U64),
4484                "u128" => Some(ScalarTypeHint::U128),
4485                "usize" => Some(ScalarTypeHint::Usize),
4486                "i8" => Some(ScalarTypeHint::I8),
4487                "i16" => Some(ScalarTypeHint::I16),
4488                "i32" => Some(ScalarTypeHint::I32),
4489                "i64" => Some(ScalarTypeHint::I64),
4490                "i128" => Some(ScalarTypeHint::I128),
4491                "isize" => Some(ScalarTypeHint::Isize),
4492                "f32" => Some(ScalarTypeHint::F32),
4493                "f64" => Some(ScalarTypeHint::F64),
4494                "String" | "&str" => Some(ScalarTypeHint::String),
4495                "char" => Some(ScalarTypeHint::Char),
4496                // For unknown scalar types, check if they implement FromStr
4497                // (e.g., camino::Utf8PathBuf, types not handled by hint_opaque_scalar)
4498                _ if shape.is_from_str() => Some(ScalarTypeHint::String),
4499                _ => None,
4500            };
4501            if let Some(hint) = hint {
4502                self.parser.hint_scalar_type(hint);
4503            }
4504        }
4505
4506        let event = self.expect_event("value")?;
4507
4508        match event {
4509            ParseEvent::Scalar(scalar) => {
4510                wip = self.set_scalar(wip, scalar)?;
4511                Ok(wip)
4512            }
4513            ParseEvent::StructStart(container_kind) => {
4514                Err(DeserializeError::ExpectedScalarGotStruct {
4515                    expected_shape: shape,
4516                    got_container: container_kind,
4517                    span: self.last_span,
4518                    path: None,
4519                })
4520            }
4521            other => Err(DeserializeError::TypeMismatch {
4522                expected: "scalar value",
4523                got: format!("{other:?}"),
4524                span: self.last_span,
4525                path: None,
4526            }),
4527        }
4528    }
4529
4530    fn set_scalar(
4531        &mut self,
4532        mut wip: Partial<'input, BORROW>,
4533        scalar: ScalarValue<'input>,
4534    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4535        let shape = wip.shape();
4536        // Capture the span for error reporting - this is where the scalar value was parsed
4537        let span = self.last_span;
4538        let reflect_err = |e: ReflectError| DeserializeError::Reflect {
4539            error: e,
4540            span,
4541            path: None,
4542        };
4543
4544        match scalar {
4545            ScalarValue::Null => {
4546                wip = wip.set_default().map_err(&reflect_err)?;
4547            }
4548            ScalarValue::Bool(b) => {
4549                wip = wip.set(b).map_err(&reflect_err)?;
4550            }
4551            ScalarValue::Char(c) => {
4552                wip = wip.set(c).map_err(&reflect_err)?;
4553            }
4554            ScalarValue::I64(n) => {
4555                // Handle signed types
4556                if shape.type_identifier == "i8" {
4557                    wip = wip.set(n as i8).map_err(&reflect_err)?;
4558                } else if shape.type_identifier == "i16" {
4559                    wip = wip.set(n as i16).map_err(&reflect_err)?;
4560                } else if shape.type_identifier == "i32" {
4561                    wip = wip.set(n as i32).map_err(&reflect_err)?;
4562                } else if shape.type_identifier == "i64" {
4563                    wip = wip.set(n).map_err(&reflect_err)?;
4564                } else if shape.type_identifier == "i128" {
4565                    wip = wip.set(n as i128).map_err(&reflect_err)?;
4566                } else if shape.type_identifier == "isize" {
4567                    wip = wip.set(n as isize).map_err(&reflect_err)?;
4568                // Handle unsigned types (I64 can fit in unsigned if non-negative)
4569                } else if shape.type_identifier == "u8" {
4570                    wip = wip.set(n as u8).map_err(&reflect_err)?;
4571                } else if shape.type_identifier == "u16" {
4572                    wip = wip.set(n as u16).map_err(&reflect_err)?;
4573                } else if shape.type_identifier == "u32" {
4574                    wip = wip.set(n as u32).map_err(&reflect_err)?;
4575                } else if shape.type_identifier == "u64" {
4576                    wip = wip.set(n as u64).map_err(&reflect_err)?;
4577                } else if shape.type_identifier == "u128" {
4578                    wip = wip.set(n as u128).map_err(&reflect_err)?;
4579                } else if shape.type_identifier == "usize" {
4580                    wip = wip.set(n as usize).map_err(&reflect_err)?;
4581                // Handle floats
4582                } else if shape.type_identifier == "f32" {
4583                    wip = wip.set(n as f32).map_err(&reflect_err)?;
4584                } else if shape.type_identifier == "f64" {
4585                    wip = wip.set(n as f64).map_err(&reflect_err)?;
4586                // Handle String - stringify the number
4587                } else if shape.type_identifier == "String" {
4588                    wip = wip
4589                        .set(alloc::string::ToString::to_string(&n))
4590                        .map_err(&reflect_err)?;
4591                } else {
4592                    wip = wip.set(n).map_err(&reflect_err)?;
4593                }
4594            }
4595            ScalarValue::U64(n) => {
4596                // Handle unsigned types
4597                if shape.type_identifier == "u8" {
4598                    wip = wip.set(n as u8).map_err(&reflect_err)?;
4599                } else if shape.type_identifier == "u16" {
4600                    wip = wip.set(n as u16).map_err(&reflect_err)?;
4601                } else if shape.type_identifier == "u32" {
4602                    wip = wip.set(n as u32).map_err(&reflect_err)?;
4603                } else if shape.type_identifier == "u64" {
4604                    wip = wip.set(n).map_err(&reflect_err)?;
4605                } else if shape.type_identifier == "u128" {
4606                    wip = wip.set(n as u128).map_err(&reflect_err)?;
4607                } else if shape.type_identifier == "usize" {
4608                    wip = wip.set(n as usize).map_err(&reflect_err)?;
4609                // Handle signed types (U64 can fit in signed if small enough)
4610                } else if shape.type_identifier == "i8" {
4611                    wip = wip.set(n as i8).map_err(&reflect_err)?;
4612                } else if shape.type_identifier == "i16" {
4613                    wip = wip.set(n as i16).map_err(&reflect_err)?;
4614                } else if shape.type_identifier == "i32" {
4615                    wip = wip.set(n as i32).map_err(&reflect_err)?;
4616                } else if shape.type_identifier == "i64" {
4617                    wip = wip.set(n as i64).map_err(&reflect_err)?;
4618                } else if shape.type_identifier == "i128" {
4619                    wip = wip.set(n as i128).map_err(&reflect_err)?;
4620                } else if shape.type_identifier == "isize" {
4621                    wip = wip.set(n as isize).map_err(&reflect_err)?;
4622                // Handle floats
4623                } else if shape.type_identifier == "f32" {
4624                    wip = wip.set(n as f32).map_err(&reflect_err)?;
4625                } else if shape.type_identifier == "f64" {
4626                    wip = wip.set(n as f64).map_err(&reflect_err)?;
4627                // Handle String - stringify the number
4628                } else if shape.type_identifier == "String" {
4629                    wip = wip
4630                        .set(alloc::string::ToString::to_string(&n))
4631                        .map_err(&reflect_err)?;
4632                } else {
4633                    wip = wip.set(n).map_err(&reflect_err)?;
4634                }
4635            }
4636            ScalarValue::U128(n) => {
4637                // Handle u128 scalar
4638                if shape.type_identifier == "u128" {
4639                    wip = wip.set(n).map_err(&reflect_err)?;
4640                } else if shape.type_identifier == "i128" {
4641                    wip = wip.set(n as i128).map_err(&reflect_err)?;
4642                } else {
4643                    // For smaller types, truncate (caller should have used correct hint)
4644                    wip = wip.set(n as u64).map_err(&reflect_err)?;
4645                }
4646            }
4647            ScalarValue::I128(n) => {
4648                // Handle i128 scalar
4649                if shape.type_identifier == "i128" {
4650                    wip = wip.set(n).map_err(&reflect_err)?;
4651                } else if shape.type_identifier == "u128" {
4652                    wip = wip.set(n as u128).map_err(&reflect_err)?;
4653                } else {
4654                    // For smaller types, truncate (caller should have used correct hint)
4655                    wip = wip.set(n as i64).map_err(&reflect_err)?;
4656                }
4657            }
4658            ScalarValue::F64(n) => {
4659                if shape.type_identifier == "f32" {
4660                    wip = wip.set(n as f32).map_err(&reflect_err)?;
4661                } else if shape.type_identifier == "f64" {
4662                    wip = wip.set(n).map_err(&reflect_err)?;
4663                } else if shape.vtable.has_try_from() && shape.inner.is_some() {
4664                    // For opaque types with try_from (like NotNan, OrderedFloat), use
4665                    // begin_inner() + set + end() to trigger conversion
4666                    let inner_shape = shape.inner.unwrap();
4667                    wip = wip.begin_inner().map_err(&reflect_err)?;
4668                    if inner_shape.is_type::<f32>() {
4669                        wip = wip.set(n as f32).map_err(&reflect_err)?;
4670                    } else {
4671                        wip = wip.set(n).map_err(&reflect_err)?;
4672                    }
4673                    wip = wip.end().map_err(&reflect_err)?;
4674                } else if shape.vtable.has_parse() {
4675                    // For types that support parsing (like Decimal), convert to string
4676                    // and use parse_from_str to preserve their parsing semantics
4677                    wip = wip
4678                        .parse_from_str(&alloc::string::ToString::to_string(&n))
4679                        .map_err(&reflect_err)?;
4680                } else {
4681                    wip = wip.set(n).map_err(&reflect_err)?;
4682                }
4683            }
4684            ScalarValue::Str(s) => {
4685                // Try parse_from_str first if the type supports it
4686                if shape.vtable.has_parse() {
4687                    wip = wip.parse_from_str(s.as_ref()).map_err(&reflect_err)?;
4688                } else {
4689                    wip = self.set_string_value(wip, s)?;
4690                }
4691            }
4692            ScalarValue::Bytes(b) => {
4693                // First try parse_from_bytes if the type supports it (e.g., UUID from 16 bytes)
4694                if shape.vtable.has_parse_bytes() {
4695                    wip = wip.parse_from_bytes(b.as_ref()).map_err(&reflect_err)?;
4696                } else {
4697                    // Fall back to setting as Vec<u8>
4698                    wip = wip.set(b.into_owned()).map_err(&reflect_err)?;
4699                }
4700            }
4701            ScalarValue::StringlyTyped(s) => {
4702                // Stringly-typed values from XML need to be parsed based on target type.
4703                //
4704                // For DynamicValue (like facet_value::Value), we need to detect the type
4705                // by trying to parse as null, bool, number, then falling back to string.
4706                //
4707                // For concrete types with has_parse(), use parse_from_str.
4708                // For string types, use set_string_value.
4709                if matches!(shape.def, facet_core::Def::DynamicValue(_)) {
4710                    // Try to detect the type for DynamicValue
4711                    let text = s.as_ref();
4712                    if text.eq_ignore_ascii_case("null") {
4713                        wip = wip.set_default().map_err(&reflect_err)?;
4714                    } else if let Ok(b) = text.parse::<bool>() {
4715                        wip = wip.set(b).map_err(&reflect_err)?;
4716                    } else if let Ok(n) = text.parse::<i64>() {
4717                        wip = wip.set(n).map_err(&reflect_err)?;
4718                    } else if let Ok(n) = text.parse::<u64>() {
4719                        wip = wip.set(n).map_err(&reflect_err)?;
4720                    } else if let Ok(n) = text.parse::<f64>() {
4721                        wip = wip.set(n).map_err(&reflect_err)?;
4722                    } else {
4723                        // Fall back to string
4724                        wip = self.set_string_value(wip, s)?;
4725                    }
4726                } else if shape.vtable.has_parse() {
4727                    wip = wip.parse_from_str(s.as_ref()).map_err(&reflect_err)?;
4728                } else {
4729                    wip = self.set_string_value(wip, s)?;
4730                }
4731            }
4732        }
4733
4734        Ok(wip)
4735    }
4736
4737    /// Set a string value, handling `&str`, `Cow<str>`, and `String` appropriately.
4738    fn set_string_value(
4739        &mut self,
4740        mut wip: Partial<'input, BORROW>,
4741        s: Cow<'input, str>,
4742    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4743        let shape = wip.shape();
4744
4745        // Check if target is &str (shared reference to str)
4746        if let Def::Pointer(ptr_def) = shape.def
4747            && matches!(ptr_def.known, Some(KnownPointer::SharedReference))
4748            && ptr_def
4749                .pointee()
4750                .is_some_and(|p| p.type_identifier == "str")
4751        {
4752            // In owned mode, we cannot borrow from input at all
4753            if !BORROW {
4754                return Err(DeserializeError::CannotBorrow {
4755                    message: "cannot deserialize into &str when borrowing is disabled - use String or Cow<str> instead".into(),
4756                });
4757            }
4758            match s {
4759                Cow::Borrowed(borrowed) => {
4760                    wip = wip.set(borrowed).map_err(DeserializeError::reflect)?;
4761                    return Ok(wip);
4762                }
4763                Cow::Owned(_) => {
4764                    return Err(DeserializeError::CannotBorrow {
4765                        message: "cannot borrow &str from string containing escape sequences - use String or Cow<str> instead".into(),
4766                    });
4767                }
4768            }
4769        }
4770
4771        // Check if target is Cow<str>
4772        if let Def::Pointer(ptr_def) = shape.def
4773            && matches!(ptr_def.known, Some(KnownPointer::Cow))
4774            && ptr_def
4775                .pointee()
4776                .is_some_and(|p| p.type_identifier == "str")
4777        {
4778            wip = wip.set(s).map_err(DeserializeError::reflect)?;
4779            return Ok(wip);
4780        }
4781
4782        // Default: convert to owned String
4783        wip = wip.set(s.into_owned()).map_err(DeserializeError::reflect)?;
4784        Ok(wip)
4785    }
4786
4787    /// Set a bytes value with proper handling for borrowed vs owned data.
4788    ///
4789    /// This handles `&[u8]`, `Cow<[u8]>`, and `Vec<u8>` appropriately based on
4790    /// whether borrowing is enabled and whether the data is borrowed or owned.
4791    fn set_bytes_value(
4792        &mut self,
4793        mut wip: Partial<'input, BORROW>,
4794        b: Cow<'input, [u8]>,
4795    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4796        let shape = wip.shape();
4797
4798        // Helper to check if a shape is a byte slice ([u8])
4799        let is_byte_slice = |pointee: &facet_core::Shape| matches!(pointee.def, Def::Slice(slice_def) if slice_def.t.type_identifier == "u8");
4800
4801        // Check if target is &[u8] (shared reference to byte slice)
4802        if let Def::Pointer(ptr_def) = shape.def
4803            && matches!(ptr_def.known, Some(KnownPointer::SharedReference))
4804            && ptr_def.pointee().is_some_and(is_byte_slice)
4805        {
4806            // In owned mode, we cannot borrow from input at all
4807            if !BORROW {
4808                return Err(DeserializeError::CannotBorrow {
4809                    message: "cannot deserialize into &[u8] when borrowing is disabled - use Vec<u8> or Cow<[u8]> instead".into(),
4810                });
4811            }
4812            match b {
4813                Cow::Borrowed(borrowed) => {
4814                    wip = wip.set(borrowed).map_err(DeserializeError::reflect)?;
4815                    return Ok(wip);
4816                }
4817                Cow::Owned(_) => {
4818                    return Err(DeserializeError::CannotBorrow {
4819                        message: "cannot borrow &[u8] from owned bytes - use Vec<u8> or Cow<[u8]> instead".into(),
4820                    });
4821                }
4822            }
4823        }
4824
4825        // Check if target is Cow<[u8]>
4826        if let Def::Pointer(ptr_def) = shape.def
4827            && matches!(ptr_def.known, Some(KnownPointer::Cow))
4828            && ptr_def.pointee().is_some_and(is_byte_slice)
4829        {
4830            wip = wip.set(b).map_err(DeserializeError::reflect)?;
4831            return Ok(wip);
4832        }
4833
4834        // Default: convert to owned Vec<u8>
4835        wip = wip.set(b.into_owned()).map_err(DeserializeError::reflect)?;
4836        Ok(wip)
4837    }
4838
4839    /// Deserialize a map key from a string.
4840    ///
4841    /// Format parsers typically emit string keys, but the target map might have non-string key types
4842    /// (e.g., integers, enums). This function parses the string key into the appropriate type:
4843    /// - String types: set directly
4844    /// - Enum unit variants: use select_variant_named
4845    /// - Integer types: parse the string as a number
4846    /// - Transparent newtypes: descend into the inner type
4847    fn deserialize_map_key(
4848        &mut self,
4849        mut wip: Partial<'input, BORROW>,
4850        key: Cow<'input, str>,
4851    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4852        let shape = wip.shape();
4853
4854        // For transparent types (like UserId(String)), we need to use begin_inner
4855        // to set the inner value. But NOT for pointer types like &str or Cow<str>
4856        // which are handled directly.
4857        let is_pointer = matches!(shape.def, Def::Pointer(_));
4858        if shape.inner.is_some() && !is_pointer {
4859            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
4860            wip = self.deserialize_map_key(wip, key)?;
4861            wip = wip.end().map_err(DeserializeError::reflect)?;
4862            return Ok(wip);
4863        }
4864
4865        // Check if target is an enum - use select_variant_named for unit variants
4866        if let Type::User(UserType::Enum(_)) = &shape.ty {
4867            wip = wip
4868                .select_variant_named(&key)
4869                .map_err(DeserializeError::reflect)?;
4870            return Ok(wip);
4871        }
4872
4873        // Check if target is a numeric type - parse the string key as a number
4874        if let Type::Primitive(PrimitiveType::Numeric(num_ty)) = &shape.ty {
4875            match num_ty {
4876                NumericType::Integer { signed } => {
4877                    if *signed {
4878                        let n: i64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
4879                            expected: "valid integer for map key",
4880                            got: format!("string '{}'", key),
4881                            span: self.last_span,
4882                            path: None,
4883                        })?;
4884                        // Use set for each size - the Partial handles type conversion
4885                        wip = wip.set(n).map_err(DeserializeError::reflect)?;
4886                    } else {
4887                        let n: u64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
4888                            expected: "valid unsigned integer for map key",
4889                            got: format!("string '{}'", key),
4890                            span: self.last_span,
4891                            path: None,
4892                        })?;
4893                        wip = wip.set(n).map_err(DeserializeError::reflect)?;
4894                    }
4895                    return Ok(wip);
4896                }
4897                NumericType::Float => {
4898                    let n: f64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
4899                        expected: "valid float for map key",
4900                        got: format!("string '{}'", key),
4901                        span: self.last_span,
4902                        path: None,
4903                    })?;
4904                    wip = wip.set(n).map_err(DeserializeError::reflect)?;
4905                    return Ok(wip);
4906                }
4907            }
4908        }
4909
4910        // Default: treat as string
4911        wip = self.set_string_value(wip, key)?;
4912        Ok(wip)
4913    }
4914
4915    /// Deserialize any value into a DynamicValue type (e.g., facet_value::Value).
4916    ///
4917    /// This handles all value types by inspecting the parse events and calling
4918    /// the appropriate methods on the Partial, which delegates to the DynamicValue vtable.
4919    fn deserialize_dynamic_value(
4920        &mut self,
4921        mut wip: Partial<'input, BORROW>,
4922    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
4923        self.parser.hint_dynamic_value();
4924        let event = self.expect_peek("value for dynamic value")?;
4925
4926        match event {
4927            ParseEvent::Scalar(_) => {
4928                // Consume the scalar
4929                let event = self.expect_event("scalar")?;
4930                if let ParseEvent::Scalar(scalar) = event {
4931                    // Use set_scalar which already handles all scalar types
4932                    wip = self.set_scalar(wip, scalar)?;
4933                }
4934            }
4935            ParseEvent::SequenceStart(_) => {
4936                // Array/list
4937                self.expect_event("sequence start")?; // consume '['
4938                wip = wip.begin_list().map_err(DeserializeError::reflect)?;
4939
4940                loop {
4941                    let event = self.expect_peek("value or end")?;
4942                    if matches!(event, ParseEvent::SequenceEnd) {
4943                        self.expect_event("sequence end")?;
4944                        break;
4945                    }
4946
4947                    wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
4948                    wip = self.deserialize_dynamic_value(wip)?;
4949                    wip = wip.end().map_err(DeserializeError::reflect)?;
4950                }
4951            }
4952            ParseEvent::StructStart(_) => {
4953                // Object/map/table
4954                self.expect_event("struct start")?; // consume '{'
4955                wip = wip.begin_map().map_err(DeserializeError::reflect)?;
4956
4957                loop {
4958                    let event = self.expect_peek("field key or end")?;
4959                    if matches!(event, ParseEvent::StructEnd) {
4960                        self.expect_event("struct end")?;
4961                        break;
4962                    }
4963
4964                    // Parse the key
4965                    let key_event = self.expect_event("field key")?;
4966                    let key = match key_event {
4967                        ParseEvent::FieldKey(field_key) => field_key.name.into_owned(),
4968                        _ => {
4969                            return Err(DeserializeError::TypeMismatch {
4970                                expected: "field key",
4971                                got: format!("{:?}", key_event),
4972                                span: self.last_span,
4973                                path: None,
4974                            });
4975                        }
4976                    };
4977
4978                    // Begin the object entry and deserialize the value
4979                    wip = wip
4980                        .begin_object_entry(&key)
4981                        .map_err(DeserializeError::reflect)?;
4982                    wip = self.deserialize_dynamic_value(wip)?;
4983                    wip = wip.end().map_err(DeserializeError::reflect)?;
4984                }
4985            }
4986            _ => {
4987                return Err(DeserializeError::TypeMismatch {
4988                    expected: "scalar, sequence, or struct",
4989                    got: format!("{:?}", event),
4990                    span: self.last_span,
4991                    path: None,
4992                });
4993            }
4994        }
4995
4996        Ok(wip)
4997    }
4998}
4999
5000/// Error produced by [`FormatDeserializer`].
5001#[derive(Debug)]
5002pub enum DeserializeError<E> {
5003    /// Error emitted by the format-specific parser.
5004    Parser(E),
5005    /// Reflection error from Partial operations.
5006    Reflect {
5007        /// The underlying reflection error.
5008        error: ReflectError,
5009        /// Source span where the error occurred (if available).
5010        span: Option<facet_reflect::Span>,
5011        /// Path through the type structure where the error occurred.
5012        path: Option<Path>,
5013    },
5014    /// Type mismatch during deserialization.
5015    TypeMismatch {
5016        /// The expected type or token.
5017        expected: &'static str,
5018        /// The actual type or token that was encountered.
5019        got: String,
5020        /// Source span where the mismatch occurred (if available).
5021        span: Option<facet_reflect::Span>,
5022        /// Path through the type structure where the error occurred.
5023        path: Option<Path>,
5024    },
5025    /// Unsupported type or operation.
5026    Unsupported(String),
5027    /// Unknown field encountered when deny_unknown_fields is set.
5028    UnknownField {
5029        /// The unknown field name.
5030        field: String,
5031        /// Source span where the unknown field was found (if available).
5032        span: Option<facet_reflect::Span>,
5033        /// Path through the type structure where the error occurred.
5034        path: Option<Path>,
5035    },
5036    /// Cannot borrow string from input (e.g., escaped string into &str).
5037    CannotBorrow {
5038        /// Description of why borrowing failed.
5039        message: String,
5040    },
5041    /// Required field missing from input.
5042    MissingField {
5043        /// The field that is missing.
5044        field: &'static str,
5045        /// The type that contains the field.
5046        type_name: &'static str,
5047        /// Source span where the struct was being parsed (if available).
5048        span: Option<facet_reflect::Span>,
5049        /// Path through the type structure where the error occurred.
5050        path: Option<Path>,
5051    },
5052    /// Expected a scalar value but got a struct/object.
5053    ///
5054    /// This typically happens when a format-specific mapping expects a scalar
5055    /// (like a KDL property `name=value`) but receives a child node instead
5056    /// (like KDL node with arguments `name "value"`).
5057    ExpectedScalarGotStruct {
5058        /// The shape that was expected (provides access to type info and attributes).
5059        expected_shape: &'static facet_core::Shape,
5060        /// The container kind that was received (Object, Array, Element).
5061        got_container: crate::ContainerKind,
5062        /// Source span where the mismatch occurred (if available).
5063        span: Option<facet_reflect::Span>,
5064        /// Path through the type structure where the error occurred.
5065        path: Option<Path>,
5066    },
5067    /// Field validation failed.
5068    #[cfg(feature = "validate")]
5069    Validation {
5070        /// The field that failed validation.
5071        field: &'static str,
5072        /// The validation error message.
5073        message: String,
5074        /// Source span where the invalid value was found.
5075        span: Option<facet_reflect::Span>,
5076        /// Path through the type structure where the error occurred.
5077        path: Option<Path>,
5078    },
5079    /// Unexpected end of input.
5080    UnexpectedEof {
5081        /// What was expected before EOF.
5082        expected: &'static str,
5083    },
5084}
5085
5086impl<E: fmt::Display> fmt::Display for DeserializeError<E> {
5087    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5088        match self {
5089            DeserializeError::Parser(err) => write!(f, "{err}"),
5090            DeserializeError::Reflect { error, .. } => write!(f, "{error}"),
5091            DeserializeError::TypeMismatch { expected, got, .. } => {
5092                write!(f, "type mismatch: expected {expected}, got {got}")
5093            }
5094            DeserializeError::Unsupported(msg) => write!(f, "unsupported: {msg}"),
5095            DeserializeError::UnknownField { field, .. } => write!(f, "unknown field: {field}"),
5096            DeserializeError::CannotBorrow { message } => write!(f, "{message}"),
5097            DeserializeError::MissingField {
5098                field, type_name, ..
5099            } => {
5100                write!(f, "missing field `{field}` in type `{type_name}`")
5101            }
5102            DeserializeError::ExpectedScalarGotStruct {
5103                expected_shape,
5104                got_container,
5105                ..
5106            } => {
5107                write!(
5108                    f,
5109                    "expected `{}` value, got {}",
5110                    expected_shape.type_identifier,
5111                    got_container.name()
5112                )
5113            }
5114            #[cfg(feature = "validate")]
5115            DeserializeError::Validation { field, message, .. } => {
5116                write!(f, "validation failed for field `{field}`: {message}")
5117            }
5118            DeserializeError::UnexpectedEof { expected } => {
5119                write!(f, "unexpected end of input, expected {expected}")
5120            }
5121        }
5122    }
5123}
5124
5125impl<E: fmt::Debug + fmt::Display> std::error::Error for DeserializeError<E> {}
5126
5127impl<E> DeserializeError<E> {
5128    /// Create a Reflect error without span or path information.
5129    #[inline]
5130    pub fn reflect(error: ReflectError) -> Self {
5131        DeserializeError::Reflect {
5132            error,
5133            span: None,
5134            path: None,
5135        }
5136    }
5137
5138    /// Create a Reflect error with span information.
5139    #[inline]
5140    pub fn reflect_with_span(error: ReflectError, span: facet_reflect::Span) -> Self {
5141        DeserializeError::Reflect {
5142            error,
5143            span: Some(span),
5144            path: None,
5145        }
5146    }
5147
5148    /// Create a Reflect error with span and path information.
5149    #[inline]
5150    pub fn reflect_with_context(
5151        error: ReflectError,
5152        span: Option<facet_reflect::Span>,
5153        path: Path,
5154    ) -> Self {
5155        DeserializeError::Reflect {
5156            error,
5157            span,
5158            path: Some(path),
5159        }
5160    }
5161
5162    /// Get the path where the error occurred, if available.
5163    pub fn path(&self) -> Option<&Path> {
5164        match self {
5165            DeserializeError::Reflect { path, .. } => path.as_ref(),
5166            DeserializeError::TypeMismatch { path, .. } => path.as_ref(),
5167            DeserializeError::UnknownField { path, .. } => path.as_ref(),
5168            DeserializeError::MissingField { path, .. } => path.as_ref(),
5169            DeserializeError::ExpectedScalarGotStruct { path, .. } => path.as_ref(),
5170            _ => None,
5171        }
5172    }
5173
5174    /// Add path information to an error (consumes and returns the modified error).
5175    pub fn with_path(self, new_path: Path) -> Self {
5176        match self {
5177            DeserializeError::Reflect { error, span, .. } => DeserializeError::Reflect {
5178                error,
5179                span,
5180                path: Some(new_path),
5181            },
5182            DeserializeError::TypeMismatch {
5183                expected,
5184                got,
5185                span,
5186                ..
5187            } => DeserializeError::TypeMismatch {
5188                expected,
5189                got,
5190                span,
5191                path: Some(new_path),
5192            },
5193            DeserializeError::UnknownField { field, span, .. } => DeserializeError::UnknownField {
5194                field,
5195                span,
5196                path: Some(new_path),
5197            },
5198            DeserializeError::MissingField {
5199                field,
5200                type_name,
5201                span,
5202                ..
5203            } => DeserializeError::MissingField {
5204                field,
5205                type_name,
5206                span,
5207                path: Some(new_path),
5208            },
5209            DeserializeError::ExpectedScalarGotStruct {
5210                expected_shape,
5211                got_container,
5212                span,
5213                ..
5214            } => DeserializeError::ExpectedScalarGotStruct {
5215                expected_shape,
5216                got_container,
5217                span,
5218                path: Some(new_path),
5219            },
5220            // Other variants don't have path fields
5221            other => other,
5222        }
5223    }
5224}
5225
5226#[cfg(feature = "miette")]
5227impl<E: miette::Diagnostic + 'static> miette::Diagnostic for DeserializeError<E> {
5228    fn code<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
5229        match self {
5230            DeserializeError::Parser(e) => e.code(),
5231            DeserializeError::TypeMismatch { .. } => Some(Box::new("facet::type_mismatch")),
5232            DeserializeError::MissingField { .. } => Some(Box::new("facet::missing_field")),
5233            _ => None,
5234        }
5235    }
5236
5237    fn severity(&self) -> Option<miette::Severity> {
5238        match self {
5239            DeserializeError::Parser(e) => e.severity(),
5240            _ => Some(miette::Severity::Error),
5241        }
5242    }
5243
5244    fn help<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
5245        match self {
5246            DeserializeError::Parser(e) => e.help(),
5247            DeserializeError::TypeMismatch { expected, .. } => {
5248                Some(Box::new(format!("expected {expected}")))
5249            }
5250            DeserializeError::MissingField { field, .. } => Some(Box::new(format!(
5251                "add `{field}` to your input, or mark the field as optional with #[facet(default)]"
5252            ))),
5253            _ => None,
5254        }
5255    }
5256
5257    fn url<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
5258        match self {
5259            DeserializeError::Parser(e) => e.url(),
5260            _ => None,
5261        }
5262    }
5263
5264    fn source_code(&self) -> Option<&dyn miette::SourceCode> {
5265        match self {
5266            DeserializeError::Parser(e) => e.source_code(),
5267            _ => None,
5268        }
5269    }
5270
5271    fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
5272        match self {
5273            DeserializeError::Parser(e) => e.labels(),
5274            DeserializeError::Reflect {
5275                span: Some(span),
5276                error,
5277                ..
5278            } => {
5279                // Use a shorter label for parse failures
5280                let label = match error {
5281                    facet_reflect::ReflectError::ParseFailed { shape, .. } => {
5282                        alloc::format!("invalid value for `{}`", shape.type_identifier)
5283                    }
5284                    _ => error.to_string(),
5285                };
5286                Some(Box::new(core::iter::once(miette::LabeledSpan::at(
5287                    *span, label,
5288                ))))
5289            }
5290            DeserializeError::TypeMismatch {
5291                span: Some(span),
5292                expected,
5293                ..
5294            } => Some(Box::new(core::iter::once(miette::LabeledSpan::at(
5295                *span,
5296                format!("expected {expected}"),
5297            )))),
5298            DeserializeError::UnknownField {
5299                span: Some(span), ..
5300            } => Some(Box::new(core::iter::once(miette::LabeledSpan::at(
5301                *span,
5302                "unknown field",
5303            )))),
5304            DeserializeError::MissingField {
5305                span: Some(span),
5306                field,
5307                ..
5308            } => Some(Box::new(core::iter::once(miette::LabeledSpan::at(
5309                *span,
5310                format!("missing field '{field}'"),
5311            )))),
5312            DeserializeError::ExpectedScalarGotStruct {
5313                span: Some(span),
5314                got_container,
5315                ..
5316            } => Some(Box::new(core::iter::once(miette::LabeledSpan::at(
5317                *span,
5318                format!("got {} here", got_container.name()),
5319            )))),
5320            _ => None,
5321        }
5322    }
5323
5324    fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
5325        match self {
5326            DeserializeError::Parser(e) => e.related(),
5327            _ => None,
5328        }
5329    }
5330
5331    fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> {
5332        match self {
5333            DeserializeError::Parser(e) => e.diagnostic_source(),
5334            _ => None,
5335        }
5336    }
5337}