facet_xml/
deserialize.rs

1//! XML deserialization using quick-xml streaming events.
2//!
3//! This deserializer uses quick-xml's event-based API, processing events
4//! on-demand and supporting rewind via event indices for flatten deserialization.
5
6use base64::Engine;
7use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
8use facet_core::{
9    Def, EnumType, Facet, Field, NumericType, PrimitiveType, ShapeLayout, StructKind, StructType,
10    Type, UserType, Variant,
11};
12use facet_reflect::{Partial, is_spanned_shape};
13use facet_solver::{PathSegment, Schema, Solver};
14use miette::SourceSpan;
15use quick_xml::events::{BytesStart, Event};
16use quick_xml::name::ResolveResult;
17use quick_xml::reader::NsReader;
18
19use crate::annotation::{XmlAnnotationPhase, fields_missing_xml_annotations};
20use crate::error::{MissingAnnotationPhase, XmlError, XmlErrorKind};
21
22pub(crate) type Result<T> = std::result::Result<T, XmlError>;
23
24// ============================================================================
25// Deserialize Options
26// ============================================================================
27
28/// Options for controlling XML deserialization behavior.
29///
30/// # Example
31///
32/// ```
33/// use facet::Facet;
34/// use facet_xml::{self as xml, DeserializeOptions};
35///
36/// #[derive(Facet, Debug, PartialEq)]
37/// struct Person {
38///     #[facet(xml::attribute)]
39///     name: String,
40/// }
41///
42/// let xml_str = r#"<Person name="Alice" extra="unknown"/>"#;
43///
44/// // Without options: unknown attributes are silently ignored
45/// let person: Person = xml::from_str(xml_str).unwrap();
46/// assert_eq!(person.name, "Alice");
47///
48/// // With deny_unknown_fields: unknown attributes cause an error
49/// let options = DeserializeOptions::default().deny_unknown_fields(true);
50/// let result: Result<Person, _> = xml::from_str_with_options(xml_str, &options);
51/// assert!(result.is_err());
52/// ```
53#[derive(Debug, Clone, Default)]
54pub struct DeserializeOptions {
55    /// If `true`, reject XML documents with unknown attributes or elements
56    /// that don't correspond to any field in the target struct.
57    ///
58    /// When `false` (the default), unknown attributes and elements are
59    /// silently ignored.
60    ///
61    /// This option is combined with any `#[facet(deny_unknown_fields)]`
62    /// attribute on the struct - if either is set, unknown fields cause
63    /// an error.
64    pub deny_unknown_fields: bool,
65}
66
67impl DeserializeOptions {
68    /// Create new options with default values.
69    pub fn new() -> Self {
70        Self::default()
71    }
72
73    /// Set whether to deny unknown fields.
74    ///
75    /// When enabled, deserialization will fail if the XML contains
76    /// attributes or elements that don't match any field in the struct.
77    pub fn deny_unknown_fields(mut self, deny: bool) -> Self {
78        self.deny_unknown_fields = deny;
79        self
80    }
81}
82
83/// Get the display name for a variant (respecting `rename` attribute).
84fn get_variant_display_name(variant: &Variant) -> &'static str {
85    if let Some(attr) = variant.get_builtin_attr("rename")
86        && let Some(&renamed) = attr.get_as::<&str>()
87    {
88        return renamed;
89    }
90    variant.name
91}
92
93/// Get the display name for a shape (respecting `rename` attribute).
94pub(crate) fn get_shape_display_name(shape: &facet_core::Shape) -> &'static str {
95    if let Some(renamed) = shape.get_builtin_attr_value::<&str>("rename") {
96        return renamed;
97    }
98    shape.type_identifier
99}
100
101/// Get the display name for a field (respecting `rename` attribute).
102fn get_field_display_name(field: &Field) -> &'static str {
103    if let Some(attr) = field.get_builtin_attr("rename")
104        && let Some(&renamed) = attr.get_as::<&str>()
105    {
106        return renamed;
107    }
108    field.name
109}
110
111/// Extract the local name from a potentially prefixed name.
112///
113/// For example: `"android:name"` -> `"name"`, `"name"` -> `"name"`
114///
115/// This handles the case where field names use `rename = "prefix:localname"`
116/// to match elements/attributes with a specific prefix in the document.
117fn local_name_of(name: &str) -> &str {
118    // Use rsplit_once to handle names with multiple colons correctly
119    // (though that's unusual in XML)
120    name.rsplit_once(':')
121        .map(|(_, local)| local)
122        .unwrap_or(name)
123}
124
125/// Check if a shape can accept an element with the given name.
126/// For structs: element name must match struct's display name.
127/// For enums: element name must match one of the variant's display names.
128fn shape_accepts_element(shape: &facet_core::Shape, element_name: &str) -> bool {
129    match &shape.ty {
130        Type::User(UserType::Enum(enum_type)) => {
131            // For enums, check if element name matches any variant
132            enum_type
133                .variants
134                .iter()
135                .any(|v| get_variant_display_name(v) == element_name)
136        }
137        Type::User(UserType::Struct(_)) => {
138            // For structs, check if element name matches struct's name
139            get_shape_display_name(shape) == element_name
140        }
141        _ => {
142            // For other types (opaque, etc.), use type identifier
143            shape.type_identifier == element_name
144        }
145    }
146}
147
148/// Get the list item shape from a field's shape (if it's a list type).
149fn get_list_item_shape(shape: &facet_core::Shape) -> Option<&'static facet_core::Shape> {
150    match &shape.def {
151        Def::List(list_def) => Some(list_def.t()),
152        _ => None,
153    }
154}
155
156// ============================================================================
157// Public API
158// ============================================================================
159
160/// Deserialize an XML string into a value of type `T`.
161///
162/// # Example
163///
164/// ```
165/// use facet::Facet;
166/// use facet_xml as xml;
167///
168/// #[derive(Facet, Debug, PartialEq)]
169/// struct Person {
170///     #[facet(xml::attribute)]
171///     id: u32,
172///     #[facet(xml::element)]
173///     name: String,
174/// }
175///
176/// let xml_str = r#"<Person id="42"><name>Alice</name></Person>"#;
177/// let person: Person = facet_xml::from_str(xml_str).unwrap();
178/// assert_eq!(person.name, "Alice");
179/// assert_eq!(person.id, 42);
180/// ```
181pub fn from_str<'input, 'facet, T>(xml: &'input str) -> Result<T>
182where
183    T: Facet<'facet>,
184    'input: 'facet,
185{
186    from_str_with_options(xml, &DeserializeOptions::default())
187}
188
189/// Deserialize an XML string into a value of type `T` with custom options.
190///
191/// # Example
192///
193/// ```
194/// use facet::Facet;
195/// use facet_xml::{self as xml, DeserializeOptions};
196///
197/// #[derive(Facet, Debug, PartialEq)]
198/// struct Person {
199///     #[facet(xml::attribute)]
200///     name: String,
201/// }
202///
203/// // With deny_unknown_fields, unknown attributes cause an error
204/// let options = DeserializeOptions::default().deny_unknown_fields(true);
205/// let xml_str = r#"<Person name="Alice" extra="unknown"/>"#;
206/// let result: Result<Person, _> = xml::from_str_with_options(xml_str, &options);
207/// assert!(result.is_err());
208///
209/// // Valid XML without unknown fields works fine
210/// let xml_str = r#"<Person name="Alice"/>"#;
211/// let person: Person = xml::from_str_with_options(xml_str, &options).unwrap();
212/// assert_eq!(person.name, "Alice");
213/// ```
214pub fn from_str_with_options<'input, 'facet, T>(
215    xml: &'input str,
216    options: &DeserializeOptions,
217) -> Result<T>
218where
219    T: Facet<'facet>,
220    'input: 'facet,
221{
222    log::trace!(
223        "from_str_with_options: parsing XML for type {}",
224        core::any::type_name::<T>()
225    );
226
227    let mut deserializer = XmlDeserializer::new(xml, options.clone())?;
228    let partial = Partial::alloc::<T>()?;
229
230    let partial = deserializer.deserialize_document(partial)?;
231
232    let result = partial
233        .build()
234        .map_err(|e| XmlError::new(XmlErrorKind::Reflect(e)).with_source(xml))?
235        .materialize()
236        .map_err(|e| XmlError::new(XmlErrorKind::Reflect(e)).with_source(xml))?;
237
238    Ok(result)
239}
240
241/// Deserialize an XML byte slice into a value of type `T`.
242///
243/// This is a convenience wrapper around [`from_str`] that first validates
244/// that the input is valid UTF-8.
245///
246/// # Example
247///
248/// ```
249/// use facet::Facet;
250/// use facet_xml as xml;
251///
252/// #[derive(Facet, Debug, PartialEq)]
253/// struct Person {
254///     #[facet(xml::attribute)]
255///     id: u32,
256///     #[facet(xml::element)]
257///     name: String,
258/// }
259///
260/// let xml_bytes = b"<Person id=\"42\"><name>Alice</name></Person>";
261/// let person: Person = facet_xml::from_slice(xml_bytes).unwrap();
262/// assert_eq!(person.name, "Alice");
263/// assert_eq!(person.id, 42);
264/// ```
265pub fn from_slice<'input, 'facet, T>(xml: &'input [u8]) -> Result<T>
266where
267    T: Facet<'facet>,
268    'input: 'facet,
269{
270    from_slice_with_options(xml, &DeserializeOptions::default())
271}
272
273/// Deserialize an XML byte slice into a value of type `T` with custom options.
274///
275/// This is a convenience wrapper around [`from_str_with_options`] that first validates
276/// that the input is valid UTF-8.
277///
278/// # Example
279///
280/// ```
281/// use facet::Facet;
282/// use facet_xml::{self as xml, DeserializeOptions};
283///
284/// #[derive(Facet, Debug, PartialEq)]
285/// struct Person {
286///     #[facet(xml::attribute)]
287///     name: String,
288/// }
289///
290/// let options = DeserializeOptions::default().deny_unknown_fields(true);
291/// let xml_bytes = b"<Person name=\"Alice\"/>";
292/// let person: Person = xml::from_slice_with_options(xml_bytes, &options).unwrap();
293/// assert_eq!(person.name, "Alice");
294/// ```
295pub fn from_slice_with_options<'input, 'facet, T>(
296    xml: &'input [u8],
297    options: &DeserializeOptions,
298) -> Result<T>
299where
300    T: Facet<'facet>,
301    'input: 'facet,
302{
303    let xml_str = std::str::from_utf8(xml)
304        .map_err(|e| XmlError::new(XmlErrorKind::InvalidUtf8(e.to_string())))?;
305    from_str_with_options(xml_str, options)
306}
307
308/// Deserialize an XML byte slice into an owned type.
309///
310/// This variant does not require the input to outlive the result, making it
311/// suitable for deserializing from temporary buffers (e.g., HTTP request bodies).
312///
313/// Types containing `&str` fields cannot be deserialized with this function;
314/// use `String` or `Cow<str>` instead.
315///
316/// # Example
317///
318/// ```
319/// use facet::Facet;
320/// use facet_xml as xml;
321///
322/// #[derive(Facet, Debug, PartialEq)]
323/// struct Person {
324///     #[facet(xml::attribute)]
325///     id: u32,
326///     #[facet(xml::element)]
327///     name: String,
328/// }
329///
330/// let xml_bytes = b"<Person id=\"42\"><name>Alice</name></Person>";
331/// let person: Person = xml::from_slice_owned(xml_bytes).unwrap();
332/// assert_eq!(person.name, "Alice");
333/// assert_eq!(person.id, 42);
334/// ```
335pub fn from_slice_owned<T: Facet<'static>>(xml: &[u8]) -> Result<T> {
336    let xml_str = std::str::from_utf8(xml)
337        .map_err(|e| XmlError::new(XmlErrorKind::InvalidUtf8(e.to_string())))?;
338
339    log::trace!(
340        "from_slice_owned: parsing XML for type {}",
341        core::any::type_name::<T>()
342    );
343
344    let options = DeserializeOptions::default();
345    let mut deserializer = XmlDeserializer::new(xml_str, options)?;
346    let partial = Partial::alloc::<T>()?;
347
348    let partial = deserializer.deserialize_document(partial)?;
349
350    let result = partial
351        .build()
352        .map_err(|e| XmlError::new(XmlErrorKind::Reflect(e)).with_source(xml_str))?
353        .materialize()
354        .map_err(|e| XmlError::new(XmlErrorKind::Reflect(e)).with_source(xml_str))?;
355
356    Ok(result)
357}
358
359// ============================================================================
360// Extension trait for XML-specific field attributes
361// ============================================================================
362
363/// Extension trait for Field to check XML-specific attributes.
364pub(crate) trait XmlFieldExt {
365    /// Returns true if this field is an element field.
366    fn is_xml_element(&self) -> bool;
367    /// Returns true if this field is an elements (list) field.
368    fn is_xml_elements(&self) -> bool;
369    /// Returns true if this field is an attribute field.
370    fn is_xml_attribute(&self) -> bool;
371    /// Returns true if this field is a text field.
372    fn is_xml_text(&self) -> bool;
373    /// Returns true if this field stores the element name.
374    #[allow(dead_code)]
375    fn is_xml_element_name(&self) -> bool;
376    /// Returns the expected XML namespace URI for this field, if specified.
377    ///
378    /// Returns `Some(ns)` if the field has `#[facet(xml::ns = "...")]`,
379    /// or `None` if no namespace constraint is specified (matches any namespace).
380    fn xml_ns(&self) -> Option<&'static str>;
381}
382
383impl XmlFieldExt for Field {
384    fn is_xml_element(&self) -> bool {
385        self.is_child() || self.has_attr(Some("xml"), "element")
386    }
387
388    fn is_xml_elements(&self) -> bool {
389        self.has_attr(Some("xml"), "elements")
390    }
391
392    fn is_xml_attribute(&self) -> bool {
393        self.has_attr(Some("xml"), "attribute")
394    }
395
396    fn is_xml_text(&self) -> bool {
397        self.has_attr(Some("xml"), "text")
398    }
399
400    fn is_xml_element_name(&self) -> bool {
401        self.has_attr(Some("xml"), "element_name")
402    }
403
404    fn xml_ns(&self) -> Option<&'static str> {
405        self.get_attr(Some("xml"), "ns")
406            .and_then(|attr| attr.get_as::<&str>().copied())
407    }
408}
409
410/// Extension trait for Shape to check XML-specific container attributes.
411pub(crate) trait XmlShapeExt {
412    /// Returns the default XML namespace URI for all fields in this container.
413    ///
414    /// Returns `Some(ns)` if the shape has `#[facet(xml::ns_all = "...")]`,
415    /// or `None` if no default namespace is specified.
416    fn xml_ns_all(&self) -> Option<&'static str>;
417}
418
419impl XmlShapeExt for facet_core::Shape {
420    fn xml_ns_all(&self) -> Option<&'static str> {
421        self.attributes
422            .iter()
423            .find(|attr| attr.ns == Some("xml") && attr.key == "ns_all")
424            .and_then(|attr| attr.get_as::<&str>().copied())
425    }
426}
427
428// ============================================================================
429// Qualified Name (namespace + local name)
430// ============================================================================
431
432/// A qualified XML name with optional namespace URI.
433///
434/// In XML, elements and attributes can be in a namespace. The namespace is
435/// identified by a URI, not the prefix used in the document. For example,
436/// `android:label` and `a:label` are the same if both prefixes resolve to
437/// the same namespace URI.
438#[derive(Debug, Clone, PartialEq, Eq)]
439struct QName {
440    /// The namespace URI, or `None` for "no namespace".
441    ///
442    /// - Elements without a prefix and no default `xmlns` are in no namespace.
443    /// - Attributes without a prefix are always in no namespace (even with default xmlns).
444    /// - Elements/attributes with a prefix have their namespace resolved via xmlns declarations.
445    namespace: Option<String>,
446    /// The local name (without prefix).
447    local_name: String,
448}
449
450impl QName {
451    /// Create a qualified name with no namespace.
452    fn local(name: impl Into<String>) -> Self {
453        Self {
454            namespace: None,
455            local_name: name.into(),
456        }
457    }
458
459    /// Create a qualified name with a namespace.
460    fn with_ns(namespace: impl Into<String>, local_name: impl Into<String>) -> Self {
461        Self {
462            namespace: Some(namespace.into()),
463            local_name: local_name.into(),
464        }
465    }
466
467    /// Check if this name matches a local name with an optional expected namespace.
468    ///
469    /// If `expected_ns` is `None`, matches any name with the given local name.
470    /// If `expected_ns` is `Some(ns)`, only matches if both local name and namespace match.
471    fn matches(&self, local_name: &str, expected_ns: Option<&str>) -> bool {
472        if self.local_name != local_name {
473            return false;
474        }
475        match expected_ns {
476            None => true, // No namespace constraint - match any namespace (or none)
477            Some(ns) => self.namespace.as_deref() == Some(ns),
478        }
479    }
480
481    /// Check if this name matches exactly (same local name and same namespace presence).
482    ///
483    /// Unlike `matches()`, this requires the namespace to match exactly:
484    /// - expected_ns: None means the element must be in "no namespace"
485    /// - expected_ns: Some(ns) means the element must be in that specific namespace
486    #[allow(dead_code)]
487    fn matches_exact(&self, local_name: &str, expected_ns: Option<&str>) -> bool {
488        self.local_name == local_name && self.namespace.as_deref() == expected_ns
489    }
490}
491
492impl std::fmt::Display for QName {
493    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
494        match &self.namespace {
495            Some(ns) => write!(f, "{{{}}}{}", ns, self.local_name),
496            None => write!(f, "{}", self.local_name),
497        }
498    }
499}
500
501/// Compare QName with str by local name only (for backward compatibility).
502impl PartialEq<str> for QName {
503    fn eq(&self, other: &str) -> bool {
504        self.local_name == other
505    }
506}
507
508impl PartialEq<&str> for QName {
509    fn eq(&self, other: &&str) -> bool {
510        self.local_name == *other
511    }
512}
513
514impl PartialEq<QName> for str {
515    fn eq(&self, other: &QName) -> bool {
516        self == other.local_name
517    }
518}
519
520impl PartialEq<QName> for &str {
521    fn eq(&self, other: &QName) -> bool {
522        *self == other.local_name
523    }
524}
525
526// ============================================================================
527// Event wrapper with owned strings
528// ============================================================================
529
530/// An XML event with owned string data and span information.
531#[derive(Debug, Clone)]
532enum OwnedEvent {
533    /// Start of an element with qualified name and attributes
534    Start {
535        name: QName,
536        attributes: Vec<(QName, String)>,
537    },
538    /// End of an element
539    End { name: QName },
540    /// Empty element (self-closing)
541    Empty {
542        name: QName,
543        attributes: Vec<(QName, String)>,
544    },
545    /// Text content
546    Text { content: String },
547    /// CDATA content
548    CData { content: String },
549    /// End of file
550    Eof,
551}
552
553#[derive(Debug, Clone)]
554struct SpannedEvent {
555    event: OwnedEvent,
556    /// Byte offset in the original input where this event starts.
557    offset: usize,
558    /// Length of the event in bytes.
559    len: usize,
560}
561
562impl SpannedEvent {
563    fn span(&self) -> SourceSpan {
564        SourceSpan::from((self.offset, self.len))
565    }
566}
567
568// ============================================================================
569// Event Collector
570// ============================================================================
571
572/// Collects all events from the parser upfront, resolving namespaces.
573struct EventCollector<'input> {
574    reader: NsReader<&'input [u8]>,
575    input: &'input str,
576}
577
578impl<'input> EventCollector<'input> {
579    fn new(input: &'input str) -> Self {
580        let mut reader = NsReader::from_str(input);
581        reader.config_mut().trim_text(true);
582        Self { reader, input }
583    }
584
585    /// Convert a ResolveResult to an optional namespace string.
586    fn resolve_ns(resolve: ResolveResult<'_>) -> Option<String> {
587        match resolve {
588            ResolveResult::Bound(ns) => Some(String::from_utf8_lossy(ns.as_ref()).into_owned()),
589            ResolveResult::Unbound => None,
590            ResolveResult::Unknown(prefix) => {
591                // Unknown prefix - treat as unbound but log a warning
592                log::warn!(
593                    "Unknown namespace prefix: {}",
594                    String::from_utf8_lossy(&prefix)
595                );
596                None
597            }
598        }
599    }
600
601    fn collect_all(mut self) -> Result<Vec<SpannedEvent>> {
602        let mut events = Vec::new();
603        let mut buf = Vec::new();
604
605        loop {
606            let offset = self.reader.buffer_position() as usize;
607            let (resolve, event) = self
608                .reader
609                .read_resolved_event_into(&mut buf)
610                .map_err(|e| {
611                    XmlError::new(XmlErrorKind::Parse(e.to_string())).with_source(self.input)
612                })?;
613
614            let (owned, len) = match event {
615                Event::Start(ref e) => {
616                    // Convert namespace to owned before calling methods on self
617                    let ns = Self::resolve_ns(resolve);
618                    let local = String::from_utf8_lossy(e.local_name().as_ref()).into_owned();
619                    let name = match ns {
620                        Some(uri) => QName::with_ns(uri, local),
621                        None => QName::local(local),
622                    };
623                    let attributes = self.collect_attributes(e)?;
624                    let len = self.reader.buffer_position() as usize - offset;
625                    (OwnedEvent::Start { name, attributes }, len)
626                }
627                Event::End(ref e) => {
628                    // For End events, we need to resolve the element name
629                    let (resolve, _) = self.reader.resolve_element(e.name());
630                    let ns = Self::resolve_ns(resolve);
631                    let local = String::from_utf8_lossy(e.local_name().as_ref()).into_owned();
632                    let name = match ns {
633                        Some(uri) => QName::with_ns(uri, local),
634                        None => QName::local(local),
635                    };
636                    let len = self.reader.buffer_position() as usize - offset;
637                    (OwnedEvent::End { name }, len)
638                }
639                Event::Empty(ref e) => {
640                    // Convert namespace to owned before calling methods on self
641                    let ns = Self::resolve_ns(resolve);
642                    let local = String::from_utf8_lossy(e.local_name().as_ref()).into_owned();
643                    let name = match ns {
644                        Some(uri) => QName::with_ns(uri, local),
645                        None => QName::local(local),
646                    };
647                    let attributes = self.collect_attributes(e)?;
648                    let len = self.reader.buffer_position() as usize - offset;
649                    (OwnedEvent::Empty { name, attributes }, len)
650                }
651                Event::Text(e) => {
652                    let content = e.decode().map_err(|e| {
653                        XmlError::new(XmlErrorKind::Parse(e.to_string())).with_source(self.input)
654                    })?;
655                    if content.trim().is_empty() {
656                        buf.clear();
657                        continue; // Skip whitespace-only text
658                    }
659                    let len = self.reader.buffer_position() as usize - offset;
660                    (
661                        OwnedEvent::Text {
662                            content: content.into_owned(),
663                        },
664                        len,
665                    )
666                }
667                Event::CData(e) => {
668                    let content = String::from_utf8_lossy(&e).into_owned();
669                    let len = self.reader.buffer_position() as usize - offset;
670                    (OwnedEvent::CData { content }, len)
671                }
672                Event::Eof => {
673                    events.push(SpannedEvent {
674                        event: OwnedEvent::Eof,
675                        offset,
676                        len: 0,
677                    });
678                    break;
679                }
680                Event::Comment(_)
681                | Event::Decl(_)
682                | Event::PI(_)
683                | Event::DocType(_)
684                | Event::GeneralRef(_) => {
685                    // Skip comments, declarations, processing instructions, doctypes, general references
686                    buf.clear();
687                    continue;
688                }
689            };
690
691            log::trace!("XML event: {owned:?} at offset {offset}");
692            events.push(SpannedEvent {
693                event: owned,
694                offset,
695                len,
696            });
697            buf.clear();
698        }
699
700        Ok(events)
701    }
702
703    fn collect_attributes(&self, e: &BytesStart<'_>) -> Result<Vec<(QName, String)>> {
704        let mut attrs = Vec::new();
705        for attr in e.attributes() {
706            let attr = attr.map_err(|e| {
707                XmlError::new(XmlErrorKind::Parse(e.to_string())).with_source(self.input)
708            })?;
709
710            // Resolve attribute namespace
711            let (resolve, _) = self.reader.resolve_attribute(attr.key);
712            let ns = Self::resolve_ns(resolve);
713            let local = String::from_utf8_lossy(attr.key.local_name().as_ref()).into_owned();
714            let qname = match ns {
715                Some(uri) => QName::with_ns(uri, local),
716                None => QName::local(local),
717            };
718
719            let value = attr
720                .unescape_value()
721                .map_err(|e| {
722                    XmlError::new(XmlErrorKind::Parse(e.to_string())).with_source(self.input)
723                })?
724                .into_owned();
725
726            attrs.push((qname, value));
727        }
728        Ok(attrs)
729    }
730}
731
732// ============================================================================
733// Deserializer
734// ============================================================================
735
736/// XML deserializer that processes events from a collected event stream.
737struct XmlDeserializer<'input> {
738    input: &'input str,
739    events: Vec<SpannedEvent>,
740    pos: usize,
741    options: DeserializeOptions,
742}
743
744impl<'input> XmlDeserializer<'input> {
745    /// Create a new deserializer by parsing the input and collecting all events.
746    fn new(input: &'input str, options: DeserializeOptions) -> Result<Self> {
747        let collector = EventCollector::new(input);
748        let events = collector.collect_all()?;
749
750        Ok(Self {
751            input,
752            events,
753            pos: 0,
754            options,
755        })
756    }
757
758    /// Create an error with source code attached for diagnostics.
759    fn err(&self, kind: impl Into<XmlErrorKind>) -> XmlError {
760        XmlError::new(kind).with_source(self.input.to_string())
761    }
762
763    /// Create an error with source code and span attached for diagnostics.
764    fn err_at(&self, kind: impl Into<XmlErrorKind>, span: impl Into<SourceSpan>) -> XmlError {
765        XmlError::new(kind)
766            .with_source(self.input.to_string())
767            .with_span(span)
768    }
769
770    /// Consume and return the current event (cloned to avoid borrow issues).
771    fn next(&mut self) -> Option<SpannedEvent> {
772        if self.pos < self.events.len() {
773            let event = self.events[self.pos].clone();
774            self.pos += 1;
775            Some(event)
776        } else {
777            None
778        }
779    }
780
781    /// Save current position for potential rewind.
782    #[allow(dead_code)]
783    fn save_position(&self) -> usize {
784        self.pos
785    }
786
787    /// Restore to a previously saved position.
788    #[allow(dead_code)]
789    fn restore_position(&mut self, pos: usize) {
790        self.pos = pos;
791    }
792
793    /// Deserialize the document starting from the root element.
794    fn deserialize_document<'facet>(
795        &mut self,
796        partial: Partial<'facet>,
797    ) -> Result<Partial<'facet>> {
798        // Expect a start or empty element
799        let Some(event) = self.next() else {
800            return Err(self.err(XmlErrorKind::UnexpectedEof));
801        };
802
803        let span = event.span();
804
805        match event.event {
806            OwnedEvent::Start { name, attributes } => {
807                self.deserialize_element(partial, &name, &attributes, span, false)
808            }
809            OwnedEvent::Empty { name, attributes } => {
810                self.deserialize_element(partial, &name, &attributes, span, true)
811            }
812            other => Err(self.err(XmlErrorKind::UnexpectedEvent(format!(
813                "expected start element, got {other:?}"
814            )))),
815        }
816    }
817
818    /// Deserialize an element into a partial value.
819    fn deserialize_element<'facet>(
820        &mut self,
821        partial: Partial<'facet>,
822        element_name: &QName,
823        attributes: &[(QName, String)],
824        span: SourceSpan,
825        is_empty: bool,
826    ) -> Result<Partial<'facet>> {
827        let mut partial = partial;
828        let shape = partial.shape();
829
830        log::trace!(
831            "deserialize_element: {:?} into shape {:?}",
832            element_name,
833            shape.ty
834        );
835
836        // Check Def first for scalars (String, etc.)
837        if matches!(&shape.def, Def::Scalar) {
838            // For scalar types, we expect text content
839            if is_empty {
840                // Empty element for a string means empty string
841                if shape.is_type::<String>() {
842                    partial = partial.set(String::new())?;
843                    return Ok(partial);
844                }
845                return Err(self.err_at(
846                    XmlErrorKind::InvalidValueForShape(
847                        "expected text content for scalar type".into(),
848                    ),
849                    span,
850                ));
851            }
852
853            // Get text content
854            let text = self.read_text_until_end(element_name)?;
855            partial = self.set_scalar_value(partial, &text)?;
856            return Ok(partial);
857        }
858
859        // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
860        if shape.builder_shape.is_some() {
861            partial = partial.begin_inner()?;
862            partial =
863                self.deserialize_element(partial, element_name, attributes, span, is_empty)?;
864            partial = partial.end()?;
865            return Ok(partial);
866        }
867
868        // Handle Vec<u8> as base64
869        if let Def::List(list_def) = &shape.def
870            && list_def.t().is_type::<u8>()
871        {
872            if is_empty {
873                // Empty element = empty bytes
874                partial = partial.begin_list()?;
875                // Empty list, nothing to add
876                return Ok(partial);
877            }
878            let text = self.read_text_until_end(element_name)?;
879            let bytes = BASE64_STANDARD
880                .decode(text.trim())
881                .map_err(|e| self.err_at(XmlErrorKind::Base64Decode(e.to_string()), span))?;
882            partial = partial.begin_list()?;
883            for byte in bytes {
884                partial = partial.begin_list_item()?;
885                partial = partial.set(byte)?;
886                partial = partial.end()?; // end list item
887            }
888            return Ok(partial);
889        }
890
891        // Handle [u8; N] as base64
892        if let Def::Array(arr_def) = &shape.def
893            && arr_def.t().is_type::<u8>()
894        {
895            if is_empty {
896                return Err(self.err_at(
897                    XmlErrorKind::InvalidValueForShape("empty element for byte array".into()),
898                    span,
899                ));
900            }
901            let text = self.read_text_until_end(element_name)?;
902            let bytes = BASE64_STANDARD
903                .decode(text.trim())
904                .map_err(|e| self.err_at(XmlErrorKind::Base64Decode(e.to_string()), span))?;
905            if bytes.len() != arr_def.n {
906                return Err(self.err_at(
907                    XmlErrorKind::InvalidValueForShape(format!(
908                        "base64 decoded {} bytes, expected {}",
909                        bytes.len(),
910                        arr_def.n
911                    )),
912                    span,
913                ));
914            }
915            for (idx, byte) in bytes.into_iter().enumerate() {
916                partial = partial.begin_nth_field(idx)?;
917                partial = partial.set(byte)?;
918                partial = partial.end()?;
919            }
920            return Ok(partial);
921        }
922
923        // Handle fixed arrays (non-byte)
924        if let Def::Array(arr_def) = &shape.def {
925            if is_empty {
926                return Err(self.err_at(
927                    XmlErrorKind::InvalidValueForShape("empty element for array".into()),
928                    span,
929                ));
930            }
931            let array_len = arr_def.n;
932            return self.deserialize_array_content(partial, array_len, element_name);
933        }
934
935        // Handle sets
936        if matches!(&shape.def, Def::Set(_)) {
937            if is_empty {
938                partial = partial.begin_set()?;
939                // Empty set - nothing to do
940                return Ok(partial);
941            }
942            return self.deserialize_set_content(partial, element_name);
943        }
944
945        // Handle maps
946        if matches!(&shape.def, Def::Map(_)) {
947            if is_empty {
948                partial = partial.begin_map()?;
949                // Empty map - nothing to do
950                return Ok(partial);
951            }
952            return self.deserialize_map_content(partial, element_name);
953        }
954
955        // Check for .inner (transparent wrappers like NonZero)
956        // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
957        if shape.inner.is_some()
958            && !matches!(
959                &shape.def,
960                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
961            )
962        {
963            partial = partial.begin_inner()?;
964            partial =
965                self.deserialize_element(partial, element_name, attributes, span, is_empty)?;
966            partial = partial.end()?;
967            return Ok(partial);
968        }
969
970        // Handle different shapes
971        match &shape.ty {
972            Type::User(UserType::Struct(struct_def)) => {
973                // Get fields
974                let fields = struct_def.fields;
975                // Deny unknown if either the option or the attribute is set
976                let deny_unknown =
977                    self.options.deny_unknown_fields || shape.has_deny_unknown_fields_attr();
978
979                match struct_def.kind {
980                    StructKind::Unit => {
981                        // Unit struct - nothing to deserialize, just skip content
982                        if !is_empty {
983                            self.skip_element(element_name)?;
984                        }
985                        return Ok(partial);
986                    }
987                    StructKind::Tuple | StructKind::TupleStruct => {
988                        // Tuple struct - deserialize fields by position
989                        if is_empty {
990                            // Set defaults for all fields
991                            partial = self.set_defaults_for_unset_fields(partial, fields)?;
992                            return Ok(partial);
993                        }
994
995                        // Deserialize tuple fields from child elements
996                        partial = self.deserialize_tuple_content(partial, fields, element_name)?;
997
998                        // Set defaults for any unset fields
999                        partial = self.set_defaults_for_unset_fields(partial, fields)?;
1000                        return Ok(partial);
1001                    }
1002                    StructKind::Struct => {
1003                        // Check if this struct has flattened fields - if so, use the solver
1004                        if Self::has_flatten_fields(struct_def) {
1005                            return self.deserialize_struct_with_flatten(
1006                                partial,
1007                                struct_def,
1008                                element_name,
1009                                attributes,
1010                                span,
1011                                is_empty,
1012                            );
1013                        }
1014                        // Normal named struct - fall through to standard handling
1015                    }
1016                }
1017
1018                let missing =
1019                    fields_missing_xml_annotations(fields, XmlAnnotationPhase::Deserialize);
1020                if !missing.is_empty() {
1021                    let field_info = missing
1022                        .into_iter()
1023                        .map(|field| (field.name, field.shape().type_identifier))
1024                        .collect();
1025                    return Err(self.err(XmlErrorKind::MissingXmlAnnotations {
1026                        type_name: shape.type_identifier,
1027                        phase: MissingAnnotationPhase::Deserialize,
1028                        fields: field_info,
1029                    }));
1030                }
1031
1032                // First, deserialize attributes
1033                partial =
1034                    self.deserialize_attributes(partial, fields, attributes, deny_unknown, span)?;
1035
1036                // If empty element, we're done with content
1037                if is_empty {
1038                    // Set defaults for missing fields
1039                    partial = self.set_defaults_for_unset_fields(partial, fields)?;
1040                    return Ok(partial);
1041                }
1042
1043                // Deserialize child elements and text content
1044                partial =
1045                    self.deserialize_element_content(partial, fields, element_name, deny_unknown)?;
1046
1047                // Set defaults for any unset fields
1048                partial = self.set_defaults_for_unset_fields(partial, fields)?;
1049
1050                Ok(partial)
1051            }
1052            Type::User(UserType::Enum(enum_def)) => {
1053                // Determine enum tagging strategy
1054                let is_untagged = shape.is_untagged();
1055                let tag_attr = shape.get_tag_attr();
1056                let content_attr = shape.get_content_attr();
1057
1058                if is_untagged {
1059                    // Untagged: try each variant until one works
1060                    return self.deserialize_untagged_enum(
1061                        partial,
1062                        enum_def,
1063                        element_name,
1064                        attributes,
1065                        span,
1066                        is_empty,
1067                    );
1068                } else if let Some(tag) = tag_attr {
1069                    // Get variant name from attribute
1070                    let variant_name = attributes
1071                        .iter()
1072                        .find(|(k, _)| k == tag)
1073                        .map(|(_, v)| v.clone())
1074                        .ok_or_else(|| {
1075                            self.err_at(XmlErrorKind::MissingAttribute(tag.to_string()), span)
1076                        })?;
1077
1078                    // Find the variant by name
1079                    let variant = enum_def
1080                        .variants
1081                        .iter()
1082                        .find(|v| v.name == variant_name)
1083                        .ok_or_else(|| {
1084                            self.err_at(
1085                                XmlErrorKind::NoMatchingElement(variant_name.to_string()),
1086                                span,
1087                            )
1088                        })?;
1089
1090                    // Select the variant
1091                    partial = partial.select_variant_named(&variant_name)?;
1092                    let variant_fields = variant.data.fields;
1093
1094                    if let Some(content) = content_attr {
1095                        // Adjacently tagged: <Element tag="Variant"><content>...</content></Element>
1096                        if is_empty {
1097                            // No content element for empty element
1098                            partial =
1099                                self.set_defaults_for_unset_fields(partial, variant_fields)?;
1100                        } else {
1101                            // Find the content element
1102                            partial = self.deserialize_adjacently_tagged_content(
1103                                partial,
1104                                variant,
1105                                content,
1106                                element_name,
1107                            )?;
1108                        }
1109                    } else {
1110                        // Internally tagged: <Element tag="Variant">...fields...</Element>
1111                        // Filter out the tag attribute
1112                        let other_attrs: Vec<_> = attributes
1113                            .iter()
1114                            .filter(|(k, _)| k != tag)
1115                            .cloned()
1116                            .collect();
1117
1118                        match variant.data.kind {
1119                            StructKind::Unit => {
1120                                // Unit variant - nothing to deserialize
1121                                if !is_empty {
1122                                    self.skip_element(element_name)?;
1123                                }
1124                            }
1125                            StructKind::Tuple | StructKind::TupleStruct => {
1126                                // Tuple variant - deserialize fields by position
1127                                if !is_empty {
1128                                    partial = self.deserialize_tuple_content(
1129                                        partial,
1130                                        variant_fields,
1131                                        element_name,
1132                                    )?;
1133                                }
1134                                partial =
1135                                    self.set_defaults_for_unset_fields(partial, variant_fields)?;
1136                            }
1137                            StructKind::Struct => {
1138                                // Struct variant - deserialize as struct
1139                                partial = self.deserialize_attributes(
1140                                    partial,
1141                                    variant_fields,
1142                                    &other_attrs,
1143                                    false,
1144                                    span,
1145                                )?;
1146                                if !is_empty {
1147                                    partial = self.deserialize_element_content(
1148                                        partial,
1149                                        variant_fields,
1150                                        element_name,
1151                                        false,
1152                                    )?;
1153                                }
1154                                partial =
1155                                    self.set_defaults_for_unset_fields(partial, variant_fields)?;
1156                            }
1157                        }
1158                    }
1159
1160                    return Ok(partial);
1161                }
1162
1163                // Externally tagged (default) - two modes:
1164                // 1. Element name IS a variant name: <VariantName attr="...">...</VariantName>
1165                // 2. Element is a wrapper: <Wrapper><VariantName>...</VariantName></Wrapper>
1166
1167                // Check if element name matches a variant's display name
1168                if let Some(variant) = enum_def
1169                    .variants
1170                    .iter()
1171                    .find(|v| get_variant_display_name(v) == element_name)
1172                {
1173                    // Mode 1: The element itself is the variant
1174                    // Use the original variant name for selection
1175                    partial = partial.select_variant_named(variant.name)?;
1176                    let variant_fields = variant.data.fields;
1177
1178                    match variant.data.kind {
1179                        StructKind::Unit => {
1180                            // Unit variant - nothing to deserialize
1181                            if !is_empty {
1182                                self.skip_element(element_name)?;
1183                            }
1184                        }
1185                        StructKind::Tuple | StructKind::TupleStruct => {
1186                            // Tuple variant - check for newtype pattern
1187                            if variant_fields.len() == 1 {
1188                                // Newtype variant - deserialize inner value from current element
1189                                partial = partial.begin_nth_field(0)?;
1190                                partial = self.deserialize_element(
1191                                    partial,
1192                                    element_name,
1193                                    attributes,
1194                                    span,
1195                                    is_empty,
1196                                )?;
1197                                partial = partial.end()?;
1198                            } else if !is_empty {
1199                                // Multi-field tuple - deserialize from child elements
1200                                partial = self.deserialize_tuple_content(
1201                                    partial,
1202                                    variant_fields,
1203                                    element_name,
1204                                )?;
1205                                partial =
1206                                    self.set_defaults_for_unset_fields(partial, variant_fields)?;
1207                            } else {
1208                                partial =
1209                                    self.set_defaults_for_unset_fields(partial, variant_fields)?;
1210                            }
1211                        }
1212                        StructKind::Struct => {
1213                            // Struct variant - deserialize attributes and content
1214                            partial = self.deserialize_attributes(
1215                                partial,
1216                                variant_fields,
1217                                attributes,
1218                                false,
1219                                span,
1220                            )?;
1221                            if !is_empty {
1222                                partial = self.deserialize_element_content(
1223                                    partial,
1224                                    variant_fields,
1225                                    element_name,
1226                                    false,
1227                                )?;
1228                            }
1229                            partial =
1230                                self.set_defaults_for_unset_fields(partial, variant_fields)?;
1231                        }
1232                    }
1233
1234                    return Ok(partial);
1235                }
1236
1237                // Mode 2: Element is a wrapper containing the variant element
1238                if is_empty {
1239                    return Err(self.err_at(
1240                        XmlErrorKind::InvalidValueForShape(
1241                            "empty element for externally tagged enum".into(),
1242                        ),
1243                        span,
1244                    ));
1245                }
1246
1247                // Read the variant element
1248                let variant_event = loop {
1249                    let Some(event) = self.next() else {
1250                        return Err(self.err(XmlErrorKind::UnexpectedEof));
1251                    };
1252
1253                    match &event.event {
1254                        OwnedEvent::Text { content } if content.trim().is_empty() => {
1255                            // Skip whitespace
1256                            continue;
1257                        }
1258                        OwnedEvent::Start { .. } | OwnedEvent::Empty { .. } => {
1259                            break event;
1260                        }
1261                        _ => {
1262                            return Err(self.err_at(
1263                                XmlErrorKind::UnexpectedEvent(format!(
1264                                    "expected variant element, got {:?}",
1265                                    event.event
1266                                )),
1267                                event.span(),
1268                            ));
1269                        }
1270                    }
1271                };
1272
1273                let variant_span = variant_event.span();
1274                let (variant_name, variant_attrs, variant_is_empty) = match &variant_event.event {
1275                    OwnedEvent::Start { name, attributes } => {
1276                        (name.clone(), attributes.clone(), false)
1277                    }
1278                    OwnedEvent::Empty { name, attributes } => {
1279                        (name.clone(), attributes.clone(), true)
1280                    }
1281                    _ => unreachable!(),
1282                };
1283
1284                // Find the variant by display name (considering rename)
1285                let variant = enum_def
1286                    .variants
1287                    .iter()
1288                    .find(|v| get_variant_display_name(v) == variant_name)
1289                    .ok_or_else(|| {
1290                        self.err_at(
1291                            XmlErrorKind::NoMatchingElement(variant_name.to_string()),
1292                            variant_span,
1293                        )
1294                    })?;
1295
1296                // Select the variant using its original name
1297                partial = partial.select_variant_named(variant.name)?;
1298
1299                let variant_fields = variant.data.fields;
1300
1301                match variant.data.kind {
1302                    StructKind::Unit => {
1303                        // Unit variant - nothing to deserialize
1304                        if !variant_is_empty {
1305                            self.skip_element(&variant_name)?;
1306                        }
1307                    }
1308                    StructKind::Tuple | StructKind::TupleStruct => {
1309                        // Tuple variant - deserialize fields by position
1310                        if !variant_is_empty {
1311                            partial = self.deserialize_tuple_content(
1312                                partial,
1313                                variant_fields,
1314                                &variant_name,
1315                            )?;
1316                        }
1317                        partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
1318                    }
1319                    StructKind::Struct => {
1320                        // Struct variant - deserialize as struct
1321                        partial = self.deserialize_attributes(
1322                            partial,
1323                            variant_fields,
1324                            &variant_attrs,
1325                            false,
1326                            variant_span,
1327                        )?;
1328                        if !variant_is_empty {
1329                            partial = self.deserialize_element_content(
1330                                partial,
1331                                variant_fields,
1332                                &variant_name,
1333                                false,
1334                            )?;
1335                        }
1336                        partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
1337                    }
1338                }
1339
1340                // Skip to the end of the wrapper element
1341                loop {
1342                    let Some(event) = self.next() else {
1343                        return Err(self.err(XmlErrorKind::UnexpectedEof));
1344                    };
1345
1346                    match &event.event {
1347                        OwnedEvent::End { name } if name == element_name => {
1348                            break;
1349                        }
1350                        OwnedEvent::Text { content } if content.trim().is_empty() => {
1351                            // Skip whitespace
1352                            continue;
1353                        }
1354                        _ => {
1355                            return Err(self.err_at(
1356                                XmlErrorKind::UnexpectedEvent(format!(
1357                                    "expected end of enum wrapper, got {:?}",
1358                                    event.event
1359                                )),
1360                                event.span(),
1361                            ));
1362                        }
1363                    }
1364                }
1365
1366                Ok(partial)
1367            }
1368            _ => Err(self.err_at(
1369                XmlErrorKind::UnsupportedShape(format!("cannot deserialize into {:?}", shape.ty)),
1370                span,
1371            )),
1372        }
1373    }
1374
1375    /// Deserialize XML attributes into struct fields.
1376    fn deserialize_attributes<'facet>(
1377        &mut self,
1378        partial: Partial<'facet>,
1379        fields: &[Field],
1380        attributes: &[(QName, String)],
1381        deny_unknown: bool,
1382        element_span: SourceSpan,
1383    ) -> Result<Partial<'facet>> {
1384        let mut partial = partial;
1385
1386        for (attr_name, attr_value) in attributes {
1387            // Find the field that matches this attribute.
1388            // Uses namespace-aware matching:
1389            // - If field has xml::ns, it must match exactly
1390            // - Otherwise, match any namespace (including "no namespace")
1391            //
1392            // NOTE: Unlike elements, attributes do NOT inherit the default namespace (ns_all).
1393            // In XML, unprefixed attributes are always in "no namespace", even when a default
1394            // xmlns is declared. Only prefixed attributes (e.g., foo:bar) have a namespace.
1395            // See: https://www.w3.org/TR/xml-names/#defaulting
1396            let field_match = fields.iter().enumerate().find(|(_, f)| {
1397                f.is_xml_attribute() && attr_name.matches(local_name_of(f.name), f.xml_ns())
1398            });
1399
1400            if let Some((idx, field)) = field_match {
1401                log::trace!(
1402                    "deserialize attribute {} into field {}",
1403                    attr_name,
1404                    field.name
1405                );
1406
1407                partial = partial.begin_nth_field(idx)?;
1408
1409                // Check if field has custom deserialization - must check BEFORE navigating
1410                // into Option/Spanned wrappers, because begin_custom_deserialization needs
1411                // the field context (parent_field()) to access proxy_shape().
1412                let has_custom_deser = field.proxy_convert_in_fn().is_some();
1413                if has_custom_deser {
1414                    // When using proxy, the proxy type handles the full conversion including
1415                    // any Option/Spanned wrappers, so we deserialize directly into the proxy.
1416                    partial = partial.begin_custom_deserialization()?;
1417                    partial = self.set_scalar_value(partial, attr_value)?;
1418                    partial = partial.end()?; // end custom deserialization
1419                } else {
1420                    // No proxy - handle Option<T> and Spanned<T> wrappers manually
1421                    let is_option = matches!(&partial.shape().def, Def::Option(_));
1422                    if is_option {
1423                        partial = partial.begin_some()?;
1424                    }
1425
1426                    // Handle Spanned<T>
1427                    if is_spanned_shape(partial.shape()) {
1428                        partial = partial.begin_field("value")?;
1429                    }
1430
1431                    // Deserialize the value
1432                    partial = self.set_scalar_value(partial, attr_value)?;
1433
1434                    // End Spanned<T> if needed
1435                    if is_spanned_shape(field.shape()) {
1436                        partial = partial.end()?; // end value field
1437                    }
1438
1439                    // End Option<T> if needed
1440                    if is_option {
1441                        partial = partial.end()?; // end Some
1442                    }
1443                }
1444
1445                partial = partial.end()?; // end field
1446            } else if deny_unknown {
1447                // Unknown attribute when deny_unknown_fields is set
1448                let expected: Vec<&'static str> = fields
1449                    .iter()
1450                    .filter(|f| f.is_xml_attribute())
1451                    .map(|f| f.name)
1452                    .collect();
1453                return Err(self.err_at(
1454                    XmlErrorKind::UnknownAttribute {
1455                        attribute: attr_name.to_string(),
1456                        expected,
1457                    },
1458                    element_span,
1459                ));
1460            }
1461            // Otherwise ignore unknown attributes
1462        }
1463
1464        Ok(partial)
1465    }
1466
1467    /// Deserialize child elements and text content.
1468    fn deserialize_element_content<'facet>(
1469        &mut self,
1470        partial: Partial<'facet>,
1471        fields: &[Field],
1472        parent_element_name: &QName,
1473        deny_unknown: bool,
1474    ) -> Result<Partial<'facet>> {
1475        let mut partial = partial;
1476        let mut text_content = String::new();
1477
1478        // Track which element fields are lists (for xml::elements)
1479        let mut elements_field_started: Option<usize> = None;
1480
1481        loop {
1482            let Some(event) = self.next() else {
1483                return Err(self.err(XmlErrorKind::UnexpectedEof));
1484            };
1485
1486            let span = event.span();
1487
1488            match event.event {
1489                OwnedEvent::End { ref name } if name == parent_element_name => {
1490                    // End any open elements list field
1491                    // Note: begin_list() doesn't push a frame, so we only end the field
1492                    if elements_field_started.is_some() {
1493                        partial = partial.end()?; // end the elements field
1494                    }
1495
1496                    // Handle accumulated text content
1497                    if !text_content.is_empty() {
1498                        partial = self.set_text_field(partial, fields, &text_content)?;
1499                    }
1500
1501                    break;
1502                }
1503                OwnedEvent::Start { name, attributes } => {
1504                    partial = self.deserialize_child_element(
1505                        partial,
1506                        fields,
1507                        &name,
1508                        &attributes,
1509                        span,
1510                        false,
1511                        &mut elements_field_started,
1512                        deny_unknown,
1513                    )?;
1514                }
1515                OwnedEvent::Empty { name, attributes } => {
1516                    partial = self.deserialize_child_element(
1517                        partial,
1518                        fields,
1519                        &name,
1520                        &attributes,
1521                        span,
1522                        true,
1523                        &mut elements_field_started,
1524                        deny_unknown,
1525                    )?;
1526                }
1527                OwnedEvent::Text { content } | OwnedEvent::CData { content } => {
1528                    text_content.push_str(&content);
1529                }
1530                OwnedEvent::End { name } => {
1531                    // End tag for a different element - this shouldn't happen
1532                    return Err(self.err_at(
1533                        XmlErrorKind::UnexpectedEvent(format!(
1534                            "unexpected end tag for '{name}' while parsing '{parent_element_name}'"
1535                        )),
1536                        span,
1537                    ));
1538                }
1539                OwnedEvent::Eof => {
1540                    return Err(self.err(XmlErrorKind::UnexpectedEof));
1541                }
1542            }
1543        }
1544
1545        Ok(partial)
1546    }
1547
1548    /// Deserialize tuple struct content - fields are numbered elements like `<_0>`, `<_1>`, etc.
1549    fn deserialize_tuple_content<'facet>(
1550        &mut self,
1551        partial: Partial<'facet>,
1552        fields: &[Field],
1553        parent_element_name: &QName,
1554    ) -> Result<Partial<'facet>> {
1555        let mut partial = partial;
1556        let mut field_idx = 0;
1557
1558        loop {
1559            let Some(event) = self.next() else {
1560                return Err(self.err(XmlErrorKind::UnexpectedEof));
1561            };
1562
1563            let span = event.span();
1564
1565            match event.event {
1566                OwnedEvent::End { ref name } if name == parent_element_name => {
1567                    break;
1568                }
1569                OwnedEvent::Start { name, attributes } => {
1570                    if field_idx >= fields.len() {
1571                        return Err(self.err_at(
1572                            XmlErrorKind::UnexpectedEvent(format!(
1573                                "too many elements for tuple struct (expected {})",
1574                                fields.len()
1575                            )),
1576                            span,
1577                        ));
1578                    }
1579
1580                    partial = partial.begin_nth_field(field_idx)?;
1581
1582                    // Handle Option<T>
1583                    let is_option = matches!(&partial.shape().def, Def::Option(_));
1584                    if is_option {
1585                        partial = partial.begin_some()?;
1586                    }
1587
1588                    partial = self.deserialize_element(partial, &name, &attributes, span, false)?;
1589                    if is_option {
1590                        partial = partial.end()?; // end Some
1591                    }
1592                    partial = partial.end()?; // end field
1593                    field_idx += 1;
1594                }
1595                OwnedEvent::Empty { name, attributes } => {
1596                    if field_idx >= fields.len() {
1597                        return Err(self.err_at(
1598                            XmlErrorKind::UnexpectedEvent(format!(
1599                                "too many elements for tuple struct (expected {})",
1600                                fields.len()
1601                            )),
1602                            span,
1603                        ));
1604                    }
1605
1606                    partial = partial.begin_nth_field(field_idx)?;
1607
1608                    // Handle Option<T>
1609                    let is_option = matches!(&partial.shape().def, Def::Option(_));
1610                    if is_option {
1611                        partial = partial.begin_some()?;
1612                    }
1613
1614                    partial = self.deserialize_element(partial, &name, &attributes, span, true)?;
1615                    if is_option {
1616                        partial = partial.end()?; // end Some
1617                    }
1618                    partial = partial.end()?; // end field
1619                    field_idx += 1;
1620                }
1621                OwnedEvent::Text { .. } | OwnedEvent::CData { .. } => {
1622                    // Ignore text content in tuple structs
1623                }
1624                OwnedEvent::End { name } => {
1625                    return Err(self.err_at(
1626                        XmlErrorKind::UnexpectedEvent(format!(
1627                            "unexpected end tag for '{name}' while parsing '{parent_element_name}'"
1628                        )),
1629                        span,
1630                    ));
1631                }
1632                OwnedEvent::Eof => {
1633                    return Err(self.err(XmlErrorKind::UnexpectedEof));
1634                }
1635            }
1636        }
1637
1638        Ok(partial)
1639    }
1640
1641    /// Deserialize fixed array content - expects sequential child elements
1642    fn deserialize_array_content<'facet>(
1643        &mut self,
1644        partial: Partial<'facet>,
1645        array_len: usize,
1646        parent_element_name: &QName,
1647    ) -> Result<Partial<'facet>> {
1648        let mut partial = partial;
1649        let mut idx = 0;
1650
1651        loop {
1652            let Some(event) = self.next() else {
1653                return Err(self.err(XmlErrorKind::UnexpectedEof));
1654            };
1655
1656            let span = event.span();
1657
1658            match event.event {
1659                OwnedEvent::End { ref name } if name == parent_element_name => {
1660                    if idx < array_len {
1661                        return Err(self.err_at(
1662                            XmlErrorKind::InvalidValueForShape(format!(
1663                                "not enough elements for array (got {idx}, expected {array_len})"
1664                            )),
1665                            span,
1666                        ));
1667                    }
1668                    break;
1669                }
1670                OwnedEvent::Start { name, attributes } => {
1671                    if idx >= array_len {
1672                        return Err(self.err_at(
1673                            XmlErrorKind::InvalidValueForShape(format!(
1674                                "too many elements for array (expected {array_len})"
1675                            )),
1676                            span,
1677                        ));
1678                    }
1679                    partial = partial.begin_nth_field(idx)?;
1680                    partial = self.deserialize_element(partial, &name, &attributes, span, false)?;
1681                    partial = partial.end()?;
1682                    idx += 1;
1683                }
1684                OwnedEvent::Empty { name, attributes } => {
1685                    if idx >= array_len {
1686                        return Err(self.err_at(
1687                            XmlErrorKind::InvalidValueForShape(format!(
1688                                "too many elements for array (expected {array_len})"
1689                            )),
1690                            span,
1691                        ));
1692                    }
1693                    partial = partial.begin_nth_field(idx)?;
1694                    partial = self.deserialize_element(partial, &name, &attributes, span, true)?;
1695                    partial = partial.end()?;
1696                    idx += 1;
1697                }
1698                OwnedEvent::Text { .. } | OwnedEvent::CData { .. } => {
1699                    // Ignore whitespace between elements
1700                }
1701                OwnedEvent::End { name } => {
1702                    return Err(self.err_at(
1703                        XmlErrorKind::UnexpectedEvent(format!(
1704                            "unexpected end tag for '{name}' while parsing '{parent_element_name}'"
1705                        )),
1706                        span,
1707                    ));
1708                }
1709                OwnedEvent::Eof => {
1710                    return Err(self.err(XmlErrorKind::UnexpectedEof));
1711                }
1712            }
1713        }
1714
1715        Ok(partial)
1716    }
1717
1718    /// Deserialize set content - each child element is a set item
1719    fn deserialize_set_content<'facet>(
1720        &mut self,
1721        partial: Partial<'facet>,
1722        parent_element_name: &QName,
1723    ) -> Result<Partial<'facet>> {
1724        let mut partial = partial;
1725        partial = partial.begin_set()?;
1726
1727        loop {
1728            let Some(event) = self.next() else {
1729                return Err(self.err(XmlErrorKind::UnexpectedEof));
1730            };
1731
1732            let span = event.span();
1733
1734            match event.event {
1735                OwnedEvent::End { ref name } if name == parent_element_name => {
1736                    break;
1737                }
1738                OwnedEvent::Start { name, attributes } => {
1739                    partial = partial.begin_set_item()?;
1740                    partial = self.deserialize_element(partial, &name, &attributes, span, false)?;
1741                    partial = partial.end()?; // end set item
1742                }
1743                OwnedEvent::Empty { name, attributes } => {
1744                    partial = partial.begin_set_item()?;
1745                    partial = self.deserialize_element(partial, &name, &attributes, span, true)?;
1746                    partial = partial.end()?; // end set item
1747                }
1748                OwnedEvent::Text { .. } | OwnedEvent::CData { .. } => {
1749                    // Ignore whitespace between elements
1750                }
1751                OwnedEvent::End { name } => {
1752                    return Err(self.err_at(
1753                        XmlErrorKind::UnexpectedEvent(format!(
1754                            "unexpected end tag for '{name}' while parsing '{parent_element_name}'"
1755                        )),
1756                        span,
1757                    ));
1758                }
1759                OwnedEvent::Eof => {
1760                    return Err(self.err(XmlErrorKind::UnexpectedEof));
1761                }
1762            }
1763        }
1764
1765        Ok(partial)
1766    }
1767
1768    /// Deserialize map content - expects <entry key="...">value</entry> or similar structure
1769    fn deserialize_map_content<'facet>(
1770        &mut self,
1771        partial: Partial<'facet>,
1772        parent_element_name: &QName,
1773    ) -> Result<Partial<'facet>> {
1774        let mut partial = partial;
1775        partial = partial.begin_map()?;
1776
1777        loop {
1778            let Some(event) = self.next() else {
1779                return Err(self.err(XmlErrorKind::UnexpectedEof));
1780            };
1781
1782            let span = event.span();
1783
1784            match event.event {
1785                OwnedEvent::End { ref name } if name == parent_element_name => {
1786                    break;
1787                }
1788                OwnedEvent::Start { name, attributes } => {
1789                    // Map entry: element name is the key, content is the value
1790                    partial = partial.begin_key()?;
1791                    partial = partial.set(name.local_name.clone())?;
1792                    partial = partial.end()?; // end key
1793
1794                    partial = partial.begin_value()?;
1795                    // If there's a key attribute, use that as context; otherwise read content
1796                    partial = self.deserialize_map_entry_value(partial, &name, &attributes)?;
1797                    partial = partial.end()?; // end value
1798                }
1799                OwnedEvent::Empty { name, .. } => {
1800                    // Empty element as map entry - key is element name, value is default/empty
1801                    partial = partial.begin_key()?;
1802                    partial = partial.set(name.local_name.clone())?;
1803                    partial = partial.end()?; // end key
1804
1805                    partial = partial.begin_value()?;
1806                    // Set default value for the map value type
1807                    let value_shape = partial.shape();
1808                    if value_shape.is_type::<String>() {
1809                        partial = partial.set(String::new())?;
1810                    } else if value_shape.is_type::<bool>() {
1811                        partial = partial.set(true)?; // presence implies true
1812                    } else {
1813                        return Err(self.err_at(
1814                            XmlErrorKind::InvalidValueForShape(
1815                                "empty element for non-string/bool map value".into(),
1816                            ),
1817                            span,
1818                        ));
1819                    }
1820                    partial = partial.end()?; // end value
1821                }
1822                OwnedEvent::Text { .. } | OwnedEvent::CData { .. } => {
1823                    // Ignore whitespace between elements
1824                }
1825                OwnedEvent::End { name } => {
1826                    return Err(self.err_at(
1827                        XmlErrorKind::UnexpectedEvent(format!(
1828                            "unexpected end tag for '{name}' while parsing '{parent_element_name}'"
1829                        )),
1830                        span,
1831                    ));
1832                }
1833                OwnedEvent::Eof => {
1834                    return Err(self.err(XmlErrorKind::UnexpectedEof));
1835                }
1836            }
1837        }
1838
1839        Ok(partial)
1840    }
1841
1842    /// Deserialize the value portion of a map entry
1843    fn deserialize_map_entry_value<'facet>(
1844        &mut self,
1845        partial: Partial<'facet>,
1846        element_name: &QName,
1847        _attributes: &[(QName, String)],
1848    ) -> Result<Partial<'facet>> {
1849        let mut partial = partial;
1850        let shape = partial.shape();
1851
1852        // For scalar values, read text content
1853        if matches!(&shape.def, Def::Scalar) {
1854            let text = self.read_text_until_end(element_name)?;
1855            partial = self.set_scalar_value(partial, &text)?;
1856            return Ok(partial);
1857        }
1858
1859        // For complex values, read the element content
1860        // This is a simplified version - complex map values would need more work
1861        let text = self.read_text_until_end(element_name)?;
1862        if shape.is_type::<String>() {
1863            partial = partial.set(text)?;
1864        } else {
1865            partial = self.set_scalar_value(partial, &text)?;
1866        }
1867
1868        Ok(partial)
1869    }
1870
1871    /// Deserialize a child element into the appropriate field.
1872    #[allow(clippy::too_many_arguments)]
1873    fn deserialize_child_element<'facet>(
1874        &mut self,
1875        partial: Partial<'facet>,
1876        fields: &[Field],
1877        element_name: &QName,
1878        attributes: &[(QName, String)],
1879        span: SourceSpan,
1880        is_empty: bool,
1881        elements_field_started: &mut Option<usize>,
1882        deny_unknown: bool,
1883    ) -> Result<Partial<'facet>> {
1884        let mut partial = partial;
1885
1886        // Get container-level default namespace (xml::ns_all)
1887        let ns_all = partial.shape().xml_ns_all();
1888
1889        // First try to find a direct element field match.
1890        // Uses namespace-aware matching:
1891        // - If field has xml::ns, it must match exactly
1892        // - Otherwise, if container has xml::ns_all, use that
1893        // - Otherwise, match any namespace
1894        if let Some((idx, field)) = fields.iter().enumerate().find(|(_, f)| {
1895            f.is_xml_element() && element_name.matches(local_name_of(f.name), f.xml_ns().or(ns_all))
1896        }) {
1897            log::trace!("matched element {} to field {}", element_name, field.name);
1898
1899            // End any open elements list field
1900            // Note: begin_list() doesn't push a frame, so we only end the field
1901            if elements_field_started.is_some() {
1902                partial = partial.end()?; // end previous field
1903                *elements_field_started = None;
1904            }
1905
1906            partial = partial.begin_nth_field(idx)?;
1907
1908            // Check if field has custom deserialization - must check BEFORE navigating
1909            // into Option wrappers, because begin_custom_deserialization needs
1910            // the field context (parent_field()) to access proxy_shape().
1911            let has_custom_deser = field.proxy_convert_in_fn().is_some();
1912            if has_custom_deser {
1913                // When using proxy, the proxy type handles the full conversion including
1914                // any Option wrappers, so we deserialize directly into the proxy.
1915                partial = partial.begin_custom_deserialization()?;
1916                partial =
1917                    self.deserialize_element(partial, element_name, attributes, span, is_empty)?;
1918                partial = partial.end()?; // end custom deserialization
1919            } else {
1920                // No proxy - handle Option<T> wrapper manually
1921                let is_option = matches!(&partial.shape().def, Def::Option(_));
1922                if is_option {
1923                    partial = partial.begin_some()?;
1924                }
1925
1926                // Deserialize the element content
1927                partial =
1928                    self.deserialize_element(partial, element_name, attributes, span, is_empty)?;
1929
1930                // End Option<T> if needed
1931                if is_option {
1932                    partial = partial.end()?; // end Some
1933                }
1934            }
1935
1936            partial = partial.end()?; // end field
1937            return Ok(partial);
1938        }
1939
1940        // Try to find an elements (list) field that accepts this element
1941        // We check: 1) if the item type accepts this element name, or
1942        //           2) if the field name matches the element name (fallback)
1943        // Uses namespace-aware matching for field name comparison.
1944        if let Some((idx, _field)) = fields.iter().enumerate().find(|(_, f)| {
1945            if !f.is_xml_elements() {
1946                return false;
1947            }
1948            // First, check if field name matches element name (common case for Vec<T>)
1949            // Uses namespace-aware matching with ns_all fallback.
1950            if element_name.matches(
1951                local_name_of(get_field_display_name(f)),
1952                f.xml_ns().or(ns_all),
1953            ) {
1954                return true;
1955            }
1956            // Otherwise, check if the list item type accepts this element
1957            let field_shape = f.shape();
1958            if let Some(item_shape) = get_list_item_shape(field_shape) {
1959                shape_accepts_element(item_shape, &element_name.local_name)
1960            } else {
1961                // Not a list type - shouldn't happen for xml::elements
1962                false
1963            }
1964        }) {
1965            // If we haven't started this list yet, begin it
1966            if elements_field_started.is_none() || *elements_field_started != Some(idx) {
1967                // End previous list field if any
1968                // Note: begin_list() doesn't push a frame, so we only end the field
1969                if elements_field_started.is_some() {
1970                    partial = partial.end()?; // end previous field
1971                }
1972
1973                partial = partial.begin_nth_field(idx)?;
1974                partial = partial.begin_list()?;
1975                *elements_field_started = Some(idx);
1976            }
1977
1978            // Add item to list
1979            partial = partial.begin_list_item()?;
1980            partial =
1981                self.deserialize_element(partial, element_name, attributes, span, is_empty)?;
1982            partial = partial.end()?; // end list item
1983
1984            return Ok(partial);
1985        }
1986
1987        // No matching field found
1988        if deny_unknown {
1989            // Unknown element when deny_unknown_fields is set
1990            let expected: Vec<&'static str> = fields
1991                .iter()
1992                .filter(|f| f.is_xml_element() || f.is_xml_elements())
1993                .map(|f| f.name)
1994                .collect();
1995            return Err(self.err_at(
1996                XmlErrorKind::UnknownField {
1997                    field: element_name.to_string(),
1998                    expected,
1999                },
2000                span,
2001            ));
2002        }
2003
2004        // Skip this element
2005        log::trace!("skipping unknown element: {element_name}");
2006        if !is_empty {
2007            self.skip_element(element_name)?;
2008        }
2009        Ok(partial)
2010    }
2011
2012    /// Set the text content field.
2013    fn set_text_field<'facet>(
2014        &mut self,
2015        partial: Partial<'facet>,
2016        fields: &[Field],
2017        text: &str,
2018    ) -> Result<Partial<'facet>> {
2019        let mut partial = partial;
2020
2021        // Find the text field
2022        if let Some((idx, _field)) = fields.iter().enumerate().find(|(_, f)| f.is_xml_text()) {
2023            partial = partial.begin_nth_field(idx)?;
2024
2025            // Handle Option<T>
2026            let is_option = matches!(&partial.shape().def, Def::Option(_));
2027            if is_option {
2028                partial = partial.begin_some()?;
2029            }
2030
2031            partial = partial.set(text.to_string())?;
2032
2033            // End Option<T> if needed
2034            if is_option {
2035                partial = partial.end()?; // end Some
2036            }
2037
2038            partial = partial.end()?; // end field
2039        }
2040        // If no text field, ignore the text content
2041
2042        Ok(partial)
2043    }
2044
2045    /// Read text content until the end tag.
2046    fn read_text_until_end(&mut self, element_name: &QName) -> Result<String> {
2047        let mut text = String::new();
2048
2049        loop {
2050            let Some(event) = self.next() else {
2051                return Err(self.err(XmlErrorKind::UnexpectedEof));
2052            };
2053
2054            match event.event {
2055                OwnedEvent::End { ref name } if name == element_name => {
2056                    break;
2057                }
2058                OwnedEvent::Text { content } | OwnedEvent::CData { content } => {
2059                    text.push_str(&content);
2060                }
2061                other => {
2062                    return Err(self.err(XmlErrorKind::UnexpectedEvent(format!(
2063                        "expected text or end tag, got {other:?}"
2064                    ))));
2065                }
2066            }
2067        }
2068
2069        Ok(text)
2070    }
2071
2072    /// Skip an element and all its content.
2073    fn skip_element(&mut self, element_name: &QName) -> Result<()> {
2074        let mut depth = 1;
2075
2076        while depth > 0 {
2077            let Some(event) = self.next() else {
2078                return Err(self.err(XmlErrorKind::UnexpectedEof));
2079            };
2080
2081            match &event.event {
2082                OwnedEvent::Start { .. } => depth += 1,
2083                OwnedEvent::End { name } if name == element_name && depth == 1 => {
2084                    depth -= 1;
2085                }
2086                OwnedEvent::End { .. } => depth -= 1,
2087                OwnedEvent::Empty { .. } => {}
2088                OwnedEvent::Text { .. } | OwnedEvent::CData { .. } => {}
2089                OwnedEvent::Eof => return Err(self.err(XmlErrorKind::UnexpectedEof)),
2090            }
2091        }
2092
2093        Ok(())
2094    }
2095
2096    /// Set defaults for any unset fields.
2097    fn set_defaults_for_unset_fields<'facet>(
2098        &self,
2099        partial: Partial<'facet>,
2100        fields: &[Field],
2101    ) -> Result<Partial<'facet>> {
2102        use facet_core::Characteristic;
2103        let mut partial = partial;
2104
2105        for (idx, field) in fields.iter().enumerate() {
2106            if partial.is_field_set(idx)? {
2107                continue;
2108            }
2109
2110            let field_has_default = field.has_default();
2111            let field_type_has_default = field.shape().is(Characteristic::Default);
2112            let should_skip = field.should_skip_deserializing();
2113            let field_is_option = matches!(field.shape().def, Def::Option(_));
2114
2115            if field_has_default || field_type_has_default || should_skip {
2116                log::trace!("setting default for unset field: {}", field.name);
2117                partial = partial.set_nth_field_to_default(idx)?;
2118            } else if field_is_option {
2119                log::trace!("initializing missing Option field `{}` to None", field.name);
2120                partial = partial.begin_field(field.name)?;
2121                partial = partial.set_default()?;
2122                partial = partial.end()?;
2123            }
2124        }
2125
2126        Ok(partial)
2127    }
2128
2129    /// Set a scalar value on the partial based on its type.
2130    fn set_scalar_value<'facet>(
2131        &self,
2132        partial: Partial<'facet>,
2133        value: &str,
2134    ) -> Result<Partial<'facet>> {
2135        let mut partial = partial;
2136        let shape = partial.shape();
2137
2138        // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
2139        if shape.builder_shape.is_some() {
2140            partial = partial.begin_inner()?;
2141            partial = self.set_scalar_value(partial, value)?;
2142            partial = partial.end()?;
2143            return Ok(partial);
2144        }
2145
2146        // Priority 2: Check for .inner (transparent wrappers like NonZero)
2147        // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
2148        if shape.inner.is_some()
2149            && !matches!(
2150                &shape.def,
2151                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
2152            )
2153        {
2154            partial = partial.begin_inner()?;
2155            partial = self.set_scalar_value(partial, value)?;
2156            partial = partial.end()?;
2157            return Ok(partial);
2158        }
2159
2160        // Handle usize and isize explicitly before other numeric types
2161        if shape.is_type::<usize>() {
2162            let n: usize = value.parse().map_err(|_| {
2163                self.err(XmlErrorKind::InvalidValueForShape(format!(
2164                    "cannot parse `{value}` as usize"
2165                )))
2166            })?;
2167            partial = partial.set(n)?;
2168            return Ok(partial);
2169        }
2170
2171        if shape.is_type::<isize>() {
2172            let n: isize = value.parse().map_err(|_| {
2173                self.err(XmlErrorKind::InvalidValueForShape(format!(
2174                    "cannot parse `{value}` as isize"
2175                )))
2176            })?;
2177            partial = partial.set(n)?;
2178            return Ok(partial);
2179        }
2180
2181        // Try numeric types
2182        if let Type::Primitive(PrimitiveType::Numeric(numeric_type)) = shape.ty {
2183            let size = match shape.layout {
2184                ShapeLayout::Sized(layout) => layout.size(),
2185                ShapeLayout::Unsized => {
2186                    return Err(self.err(XmlErrorKind::InvalidValueForShape(
2187                        "cannot assign to unsized type".into(),
2188                    )));
2189                }
2190            };
2191
2192            return self.set_numeric_value(partial, value, numeric_type, size);
2193        }
2194
2195        // Boolean
2196        if shape.is_type::<bool>() {
2197            let b = match value.to_lowercase().as_str() {
2198                "true" | "1" | "yes" => true,
2199                "false" | "0" | "no" => false,
2200                _ => {
2201                    return Err(self.err(XmlErrorKind::InvalidValueForShape(format!(
2202                        "cannot parse `{value}` as boolean"
2203                    ))));
2204                }
2205            };
2206            partial = partial.set(b)?;
2207            return Ok(partial);
2208        }
2209
2210        // Char
2211        if shape.is_type::<char>() {
2212            let mut chars = value.chars();
2213            let c = chars.next().ok_or_else(|| {
2214                self.err(XmlErrorKind::InvalidValueForShape(
2215                    "empty string cannot be converted to char".into(),
2216                ))
2217            })?;
2218            if chars.next().is_some() {
2219                return Err(self.err(XmlErrorKind::InvalidValueForShape(
2220                    "string has more than one character".into(),
2221                )));
2222            }
2223            partial = partial.set(c)?;
2224            return Ok(partial);
2225        }
2226
2227        // String
2228        if shape.is_type::<String>() {
2229            partial = partial.set(value.to_string())?;
2230            return Ok(partial);
2231        }
2232
2233        // Try parse_from_str for other types (IpAddr, DateTime, etc.)
2234        if partial.shape().vtable.has_parse() {
2235            partial = partial
2236                .parse_from_str(value)
2237                .map_err(|e| self.err(XmlErrorKind::Reflect(e)))?;
2238            return Ok(partial);
2239        }
2240
2241        // Last resort: try setting as string
2242        partial = partial
2243            .set(value.to_string())
2244            .map_err(|e| self.err(XmlErrorKind::Reflect(e)))?;
2245
2246        Ok(partial)
2247    }
2248
2249    /// Set a numeric value with proper type conversion.
2250    fn set_numeric_value<'facet>(
2251        &self,
2252        partial: Partial<'facet>,
2253        value: &str,
2254        numeric_type: NumericType,
2255        size: usize,
2256    ) -> Result<Partial<'facet>> {
2257        let mut partial = partial;
2258        match numeric_type {
2259            NumericType::Integer { signed: false } => {
2260                let n: u64 = value.parse().map_err(|_| {
2261                    self.err(XmlErrorKind::InvalidValueForShape(format!(
2262                        "cannot parse `{value}` as unsigned integer"
2263                    )))
2264                })?;
2265
2266                match size {
2267                    1 => {
2268                        let v = u8::try_from(n).map_err(|_| {
2269                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2270                                "`{value}` out of range for u8"
2271                            )))
2272                        })?;
2273                        partial = partial.set(v)?;
2274                    }
2275                    2 => {
2276                        let v = u16::try_from(n).map_err(|_| {
2277                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2278                                "`{value}` out of range for u16"
2279                            )))
2280                        })?;
2281                        partial = partial.set(v)?;
2282                    }
2283                    4 => {
2284                        let v = u32::try_from(n).map_err(|_| {
2285                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2286                                "`{value}` out of range for u32"
2287                            )))
2288                        })?;
2289                        partial = partial.set(v)?;
2290                    }
2291                    8 => {
2292                        partial = partial.set(n)?;
2293                    }
2294                    16 => {
2295                        let n: u128 = value.parse().map_err(|_| {
2296                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2297                                "cannot parse `{value}` as u128"
2298                            )))
2299                        })?;
2300                        partial = partial.set(n)?;
2301                    }
2302                    _ => {
2303                        return Err(self.err(XmlErrorKind::InvalidValueForShape(format!(
2304                            "unsupported unsigned integer size: {size}"
2305                        ))));
2306                    }
2307                }
2308            }
2309            NumericType::Integer { signed: true } => {
2310                let n: i64 = value.parse().map_err(|_| {
2311                    self.err(XmlErrorKind::InvalidValueForShape(format!(
2312                        "cannot parse `{value}` as signed integer"
2313                    )))
2314                })?;
2315
2316                match size {
2317                    1 => {
2318                        let v = i8::try_from(n).map_err(|_| {
2319                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2320                                "`{value}` out of range for i8"
2321                            )))
2322                        })?;
2323                        partial = partial.set(v)?;
2324                    }
2325                    2 => {
2326                        let v = i16::try_from(n).map_err(|_| {
2327                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2328                                "`{value}` out of range for i16"
2329                            )))
2330                        })?;
2331                        partial = partial.set(v)?;
2332                    }
2333                    4 => {
2334                        let v = i32::try_from(n).map_err(|_| {
2335                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2336                                "`{value}` out of range for i32"
2337                            )))
2338                        })?;
2339                        partial = partial.set(v)?;
2340                    }
2341                    8 => {
2342                        partial = partial.set(n)?;
2343                    }
2344                    16 => {
2345                        let n: i128 = value.parse().map_err(|_| {
2346                            self.err(XmlErrorKind::InvalidValueForShape(format!(
2347                                "cannot parse `{value}` as i128"
2348                            )))
2349                        })?;
2350                        partial = partial.set(n)?;
2351                    }
2352                    _ => {
2353                        return Err(self.err(XmlErrorKind::InvalidValueForShape(format!(
2354                            "unsupported signed integer size: {size}"
2355                        ))));
2356                    }
2357                }
2358            }
2359            NumericType::Float => match size {
2360                4 => {
2361                    let v: f32 = value.parse().map_err(|_| {
2362                        self.err(XmlErrorKind::InvalidValueForShape(format!(
2363                            "cannot parse `{value}` as f32"
2364                        )))
2365                    })?;
2366                    partial = partial.set(v)?;
2367                }
2368                8 => {
2369                    let v: f64 = value.parse().map_err(|_| {
2370                        self.err(XmlErrorKind::InvalidValueForShape(format!(
2371                            "cannot parse `{value}` as f64"
2372                        )))
2373                    })?;
2374                    partial = partial.set(v)?;
2375                }
2376                _ => {
2377                    return Err(self.err(XmlErrorKind::InvalidValueForShape(format!(
2378                        "unsupported float size: {size}"
2379                    ))));
2380                }
2381            },
2382        }
2383
2384        Ok(partial)
2385    }
2386
2387    /// Deserialize adjacently tagged enum content.
2388    /// Format: <Element tag="Variant"><content>...</content></Element>
2389    fn deserialize_adjacently_tagged_content<'facet>(
2390        &mut self,
2391        partial: Partial<'facet>,
2392        variant: &Variant,
2393        content_tag: &str,
2394        parent_element_name: &QName,
2395    ) -> Result<Partial<'facet>> {
2396        let mut partial = partial;
2397        let variant_fields = variant.data.fields;
2398
2399        loop {
2400            let Some(event) = self.next() else {
2401                return Err(self.err(XmlErrorKind::UnexpectedEof));
2402            };
2403
2404            let span = event.span();
2405
2406            match event.event {
2407                OwnedEvent::End { ref name } if name == parent_element_name => {
2408                    // End of wrapper - set defaults for unset fields
2409                    partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
2410                    break;
2411                }
2412                OwnedEvent::Start {
2413                    ref name,
2414                    ref attributes,
2415                } if name == content_tag => {
2416                    // Found content element - deserialize based on variant kind
2417                    match variant.data.kind {
2418                        StructKind::Unit => {
2419                            // Unit variant - skip content
2420                            self.skip_element(name)?;
2421                        }
2422                        StructKind::Tuple | StructKind::TupleStruct => {
2423                            partial =
2424                                self.deserialize_tuple_content(partial, variant_fields, name)?;
2425                        }
2426                        StructKind::Struct => {
2427                            partial = self.deserialize_attributes(
2428                                partial,
2429                                variant_fields,
2430                                attributes,
2431                                false,
2432                                span,
2433                            )?;
2434                            partial = self.deserialize_element_content(
2435                                partial,
2436                                variant_fields,
2437                                name,
2438                                false,
2439                            )?;
2440                        }
2441                    }
2442                    partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
2443                }
2444                OwnedEvent::Empty {
2445                    ref name,
2446                    ref attributes,
2447                } if name == content_tag => {
2448                    // Empty content element
2449                    match variant.data.kind {
2450                        StructKind::Unit => {}
2451                        StructKind::Struct => {
2452                            partial = self.deserialize_attributes(
2453                                partial,
2454                                variant_fields,
2455                                attributes,
2456                                false,
2457                                span,
2458                            )?;
2459                        }
2460                        _ => {}
2461                    }
2462                    partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
2463                }
2464                OwnedEvent::Text { ref content } if content.trim().is_empty() => {
2465                    // Skip whitespace
2466                    continue;
2467                }
2468                _ => {
2469                    return Err(self.err_at(
2470                        XmlErrorKind::UnexpectedEvent(format!(
2471                            "expected content element <{}>, got {:?}",
2472                            content_tag, event.event
2473                        )),
2474                        span,
2475                    ));
2476                }
2477            }
2478        }
2479
2480        Ok(partial)
2481    }
2482
2483    /// Deserialize untagged enum - try each variant until one succeeds.
2484    fn deserialize_untagged_enum<'facet>(
2485        &mut self,
2486        partial: Partial<'facet>,
2487        enum_type: &EnumType,
2488        element_name: &QName,
2489        attributes: &[(QName, String)],
2490        span: SourceSpan,
2491        is_empty: bool,
2492    ) -> Result<Partial<'facet>> {
2493        // For untagged enums, we need to try each variant
2494        // This is tricky because we can't easily "rewind" the partial
2495        // For now, we'll use a simple heuristic based on available fields
2496
2497        // Collect child element names to help determine variant
2498        let saved_pos = self.pos;
2499
2500        // For untagged enums, try variants in order
2501        for variant in enum_type.variants.iter() {
2502            // Try to match this variant
2503            self.pos = saved_pos; // Reset position for each attempt
2504
2505            // Allocate a fresh partial for this attempt
2506            let attempt_partial = Partial::alloc_shape(partial.shape())?;
2507            let attempt_partial = attempt_partial.select_variant_named(variant.name)?;
2508
2509            // Try to deserialize into this variant
2510            let result = self.try_deserialize_variant(
2511                attempt_partial,
2512                variant,
2513                element_name,
2514                attributes,
2515                span,
2516                is_empty,
2517            );
2518
2519            if result.is_ok() {
2520                // Successfully matched - return this partial
2521                // But we need to transfer the data to the original partial
2522                // This is complex with the current API, so we return the new one
2523                return result;
2524            }
2525        }
2526
2527        // No variant matched
2528        Err(self.err_at(
2529            XmlErrorKind::InvalidValueForShape("no variant matched for untagged enum".to_string()),
2530            span,
2531        ))
2532    }
2533
2534    /// Try to deserialize a specific variant.
2535    fn try_deserialize_variant<'facet>(
2536        &mut self,
2537        partial: Partial<'facet>,
2538        variant: &Variant,
2539        element_name: &QName,
2540        attributes: &[(QName, String)],
2541        span: SourceSpan,
2542        is_empty: bool,
2543    ) -> Result<Partial<'facet>> {
2544        let mut partial = partial;
2545        let variant_fields = variant.data.fields;
2546
2547        match variant.data.kind {
2548            StructKind::Unit => {
2549                // Unit variant - nothing to deserialize
2550                if !is_empty {
2551                    self.skip_element(element_name)?;
2552                }
2553            }
2554            StructKind::Tuple | StructKind::TupleStruct => {
2555                if !is_empty {
2556                    partial =
2557                        self.deserialize_tuple_content(partial, variant_fields, element_name)?;
2558                }
2559                partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
2560            }
2561            StructKind::Struct => {
2562                partial =
2563                    self.deserialize_attributes(partial, variant_fields, attributes, false, span)?;
2564                if !is_empty {
2565                    partial = self.deserialize_element_content(
2566                        partial,
2567                        variant_fields,
2568                        element_name,
2569                        false,
2570                    )?;
2571                }
2572                partial = self.set_defaults_for_unset_fields(partial, variant_fields)?;
2573            }
2574        }
2575
2576        Ok(partial)
2577    }
2578
2579    /// Check if a struct has any flattened fields.
2580    fn has_flatten_fields(struct_def: &StructType) -> bool {
2581        struct_def.fields.iter().any(|f| f.is_flattened())
2582    }
2583
2584    /// Deserialize a struct with flattened fields using facet-solver.
2585    ///
2586    /// This uses a two-pass approach:
2587    /// 1. Peek mode: Scan all element names and attributes, feed to solver
2588    /// 2. Deserialize: Use the resolved Configuration to deserialize with proper path handling
2589    fn deserialize_struct_with_flatten<'facet>(
2590        &mut self,
2591        partial: Partial<'facet>,
2592        struct_def: &StructType,
2593        element_name: &QName,
2594        attributes: &[(QName, String)],
2595        span: SourceSpan,
2596        is_empty: bool,
2597    ) -> Result<Partial<'facet>> {
2598        let mut partial = partial;
2599
2600        log::trace!(
2601            "deserialize_struct_with_flatten: {}",
2602            partial.shape().type_identifier
2603        );
2604
2605        // Build the schema for this type
2606        let schema = Schema::build_auto(partial.shape())
2607            .map_err(|e| self.err_at(XmlErrorKind::SchemaError(e), span))?;
2608
2609        // Create the solver
2610        let mut solver = Solver::new(&schema);
2611
2612        // Feed attribute names to solver
2613        for (attr_name, _) in attributes {
2614            let _decision = solver.see_key(attr_name.local_name.clone());
2615        }
2616
2617        // Track child element positions for pass 2
2618        let mut element_positions: Vec<(String, usize)> = Vec::new();
2619        let saved_pos = self.pos;
2620
2621        // ========== PASS 1: Peek mode - scan all child elements ==========
2622        if !is_empty {
2623            loop {
2624                let Some(event) = self.next() else {
2625                    return Err(self.err(XmlErrorKind::UnexpectedEof));
2626                };
2627
2628                match &event.event {
2629                    OwnedEvent::End { name } if name == element_name => {
2630                        break;
2631                    }
2632                    OwnedEvent::Start { name, .. } | OwnedEvent::Empty { name, .. } => {
2633                        // Record position before this element
2634                        let elem_pos = self.pos - 1; // We already consumed this event
2635
2636                        let key = name.local_name.clone();
2637                        let _decision = solver.see_key(key.clone());
2638                        element_positions.push((key, elem_pos));
2639
2640                        // Skip the element content if it's a Start event
2641                        if matches!(&event.event, OwnedEvent::Start { .. }) {
2642                            self.skip_element(name)?;
2643                        }
2644                    }
2645                    OwnedEvent::Text { content } if content.trim().is_empty() => {
2646                        // Skip whitespace
2647                        continue;
2648                    }
2649                    OwnedEvent::Text { .. } => {
2650                        // Text content - might be for a text field
2651                        // For now we skip it in the peek pass
2652                        continue;
2653                    }
2654                    _ => {
2655                        return Err(self.err_at(
2656                            XmlErrorKind::UnexpectedEvent(format!(
2657                                "expected element or end tag, got {:?}",
2658                                event.event
2659                            )),
2660                            event.span(),
2661                        ));
2662                    }
2663                }
2664            }
2665        }
2666
2667        // ========== Get the resolved Configuration ==========
2668        let config = solver
2669            .finish()
2670            .map_err(|e| self.err_at(XmlErrorKind::Solver(e), span))?;
2671
2672        // ========== PASS 2: Deserialize with proper path handling ==========
2673
2674        // First, handle attributes using the configuration
2675        for (attr_name, attr_value) in attributes {
2676            if let Some(field_info) = config.resolution().field(&attr_name.local_name) {
2677                let segments = field_info.path.segments();
2678
2679                // Navigate to the field through the path, tracking Option fields
2680                let mut option_count = 0;
2681                for segment in segments {
2682                    match segment {
2683                        PathSegment::Field(name) => {
2684                            partial = partial.begin_field(name)?;
2685                            // Handle Option fields
2686                            if matches!(partial.shape().def, Def::Option(_)) {
2687                                partial = partial.begin_some()?;
2688                                option_count += 1;
2689                            }
2690                        }
2691                        PathSegment::Variant(_, variant_name) => {
2692                            partial = partial.select_variant_named(variant_name)?;
2693                        }
2694                    }
2695                }
2696
2697                // Handle Spanned<T>
2698                if is_spanned_shape(partial.shape()) {
2699                    partial = partial.begin_field("value")?;
2700                }
2701
2702                // Deserialize the attribute value
2703                partial = self.set_scalar_value(partial, attr_value)?;
2704
2705                // Unwind: end Spanned if needed
2706                if is_spanned_shape(partial.shape()) {
2707                    partial = partial.end()?;
2708                }
2709
2710                // Unwind the path (including Option Some wrappers)
2711                for _ in 0..option_count {
2712                    partial = partial.end()?; // end Some
2713                }
2714                for segment in segments.iter().rev() {
2715                    if matches!(segment, PathSegment::Field(_)) {
2716                        partial = partial.end()?;
2717                    }
2718                }
2719            }
2720        }
2721
2722        // Handle elements using the configuration
2723        // Reset position to replay elements
2724        self.pos = saved_pos;
2725
2726        if !is_empty {
2727            loop {
2728                let Some(event) = self.next() else {
2729                    return Err(self.err(XmlErrorKind::UnexpectedEof));
2730                };
2731
2732                let event_span = event.span();
2733
2734                match event.event {
2735                    OwnedEvent::End { ref name } if name == element_name => {
2736                        break;
2737                    }
2738                    OwnedEvent::Start {
2739                        ref name,
2740                        ref attributes,
2741                    }
2742                    | OwnedEvent::Empty {
2743                        ref name,
2744                        ref attributes,
2745                    } => {
2746                        let is_elem_empty = matches!(event.event, OwnedEvent::Empty { .. });
2747
2748                        if let Some(field_info) = config.resolution().field(&name.local_name) {
2749                            let segments = field_info.path.segments();
2750
2751                            // Navigate to the field through the path, tracking Option fields
2752                            let mut option_count = 0;
2753                            for segment in segments {
2754                                match segment {
2755                                    PathSegment::Field(field_name) => {
2756                                        partial = partial.begin_field(field_name)?;
2757                                        // Handle Option fields
2758                                        if matches!(partial.shape().def, Def::Option(_)) {
2759                                            partial = partial.begin_some()?;
2760                                            option_count += 1;
2761                                        }
2762                                    }
2763                                    PathSegment::Variant(_, variant_name) => {
2764                                        partial = partial.select_variant_named(variant_name)?;
2765                                    }
2766                                }
2767                            }
2768
2769                            // Deserialize the element
2770                            partial = self.deserialize_element(
2771                                partial,
2772                                name,
2773                                attributes,
2774                                event_span,
2775                                is_elem_empty,
2776                            )?;
2777
2778                            // Unwind the path (including Option Some wrappers)
2779                            for _ in 0..option_count {
2780                                partial = partial.end()?; // end Some
2781                            }
2782                            for segment in segments.iter().rev() {
2783                                if matches!(segment, PathSegment::Field(_)) {
2784                                    partial = partial.end()?;
2785                                }
2786                            }
2787                        } else {
2788                            // Unknown element - skip it
2789                            if !is_elem_empty {
2790                                self.skip_element(name)?;
2791                            }
2792                        }
2793                    }
2794                    OwnedEvent::Text { ref content } if content.trim().is_empty() => {
2795                        continue;
2796                    }
2797                    OwnedEvent::Text { .. } => {
2798                        // Text content - handle if there's a text field
2799                        // For now skip
2800                        continue;
2801                    }
2802                    _ => {
2803                        return Err(self.err_at(
2804                            XmlErrorKind::UnexpectedEvent(format!(
2805                                "expected element or end tag, got {:?}",
2806                                event.event
2807                            )),
2808                            event_span,
2809                        ));
2810                    }
2811                }
2812            }
2813        }
2814
2815        // Set defaults for any unset fields
2816        partial = self.set_defaults_for_unset_fields(partial, struct_def.fields)?;
2817
2818        Ok(partial)
2819    }
2820}