Skip to main content

sup_xml/de/
deserializer.rs

1//! `XmlDeserializer` — drives the serde Visitor API from `XmlReader` events.
2
3use std::borrow::Cow;
4
5use serde::de::{self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess, Visitor};
6
7use sup_xml_core::{EventInto, XmlReader};
8
9use super::{DeError, DeOptions};
10
11// ── lookahead-buffered event source ──────────────────────────────────────────
12
13/// One pending event, decoded into a borrow-friendly form so the reader is
14/// free for the next call while a buffered event is alive.
15#[derive(Debug)]
16enum Pending<'src> {
17    Start { name: Cow<'src, str>, attrs: Vec<(Cow<'src, str>, Cow<'src, str>)> },
18    End,
19    Text(Cow<'src, str>),
20    CData(Cow<'src, str>),
21    Eof,
22}
23
24/// Low-level serde XML deserializer.
25///
26/// Most callers should use the convenience entry points
27/// [`from_str`](super::from_str) / [`from_bytes`](super::from_bytes)
28/// rather than constructing this directly.  Use `XmlDeserializer` when you
29/// want to drive the serde [`Deserializer`](serde::de::Deserializer) trait
30/// against XML events yourself — for example, plugging into a custom
31/// visitor or chaining with a `seed`-based `DeserializeSeed` flow.
32///
33/// Holds an [`XmlReader`] and a one-event lookahead so peeking is cheap.
34pub struct XmlDeserializer<'de> {
35    reader:    XmlReader<'de>,
36    opts:      DeOptions,
37    /// Single-event lookahead.
38    lookahead: Option<Pending<'de>>,
39    /// Reusable scratch buffer for eager attribute reads.
40    attr_buf:  Vec<sup_xml_core::Attr<'de>>,
41}
42
43impl<'de> XmlDeserializer<'de> {
44    /// Build a deserializer over a string slice with default options.
45    pub fn from_str(input: &'de str) -> Self {
46        Self::from_str_opts(input, DeOptions::default())
47    }
48
49    /// Build a deserializer over a string slice with caller-supplied
50    /// [`DeOptions`].  The options are forwarded to the underlying
51    /// [`XmlReader`](crate::XmlReader) and govern naming conventions
52    /// (`@` prefix, `$text` / `$value` field names) and behaviour
53    /// (`xsi:nil`, unknown-field handling).
54    pub fn from_str_opts(input: &'de str, opts: DeOptions) -> Self {
55        let reader = XmlReader::from_str(input).with_options(opts.parse.clone());
56        Self {
57            reader,
58            opts,
59            lookahead: None,
60            attr_buf: Vec::new(),
61        }
62    }
63
64    // ── event source ─────────────────────────────────────────────────────────
65
66    fn pull(&mut self) -> Result<Pending<'de>, DeError> {
67        loop {
68            let ev = self.reader.next_into(&mut self.attr_buf)?;
69            match ev {
70                EventInto::Comment(_) | EventInto::Pi { .. } => continue,
71                EventInto::StartElement { name } => {
72                    let attrs = self.attr_buf.drain(..)
73                        // a.name is `&'de str` (lazy reader); wrap in
74                        // Cow::Borrowed to keep `Pending::Start`'s
75                        // shape unchanged for the rest of the
76                        // deserializer.
77                        .map(|a| (Cow::Borrowed(a.name), a.value))
78                        .collect();
79                    return Ok(Pending::Start { name, attrs });
80                }
81                EventInto::EndElement { .. }   => return Ok(Pending::End),
82                EventInto::Text(t)             => return Ok(Pending::Text(t)),
83                EventInto::CData(s)            => return Ok(Pending::CData(s)),
84                EventInto::EntityRef { name }  => {
85                    // EntityRef events only appear under
86                    // `resolve_entities: false`.  Typed deserialization
87                    // can't make sense of unresolved `&name;` markers
88                    // — they have no text value to coerce into a Rust
89                    // type — so surface a clear error instead of
90                    // silently dropping data.  Configure the parser
91                    // with `resolve_entities: true` (the default) for
92                    // typed deserialization to work.
93                    return Err(DeError::msg(format!(
94                        "typed deserialization requires `resolve_entities: true`; \
95                         encountered unresolved entity reference `&{name};`"
96                    )));
97                }
98                EventInto::Eof                 => return Ok(Pending::Eof),
99            }
100        }
101    }
102
103    fn peek(&mut self) -> Result<&Pending<'de>, DeError> {
104        if self.lookahead.is_none() {
105            let p = self.pull()?;
106            self.lookahead = Some(p);
107        }
108        Ok(self.lookahead.as_ref().unwrap())
109    }
110
111    fn advance(&mut self) -> Result<Pending<'de>, DeError> {
112        if let Some(p) = self.lookahead.take() {
113            return Ok(p);
114        }
115        self.pull()
116    }
117
118    /// At top level, discard whitespace-only text events.
119    fn skip_leading_ws(&mut self) -> Result<(), DeError> {
120        loop {
121            match self.peek()? {
122                Pending::Text(t) if t.chars().all(char::is_whitespace) => {
123                    let _ = self.advance()?;
124                }
125                _ => return Ok(()),
126            }
127        }
128    }
129
130    // ── content collection ───────────────────────────────────────────────────
131
132    /// After a Start has been consumed, gather all text/CDATA in its body
133    /// into one string, consuming the matching EndElement.  Errors on a
134    /// nested element.
135    fn read_text_body(&mut self) -> Result<String, DeError> {
136        let mut out = String::new();
137        loop {
138            match self.advance()? {
139                Pending::Text(t) | Pending::CData(t) => out.push_str(&t),
140                Pending::End => return Ok(out),
141                Pending::Start { name, .. } => return Err(DeError::msg(format!(
142                    "expected scalar content but found nested element <{}>", name
143                ))),
144                Pending::Eof => return Err(DeError::msg(
145                    "unexpected EOF while reading element text content"
146                )),
147            }
148        }
149    }
150
151    /// Skip the body of an entered element (including nested elements)
152    /// through its matching EndElement.
153    fn skip_body(&mut self) -> Result<(), DeError> {
154        let mut depth = 1usize;
155        while depth > 0 {
156            match self.advance()? {
157                Pending::Start { .. } => depth += 1,
158                Pending::End   => depth -= 1,
159                Pending::Eof          => return Err(DeError::msg("unexpected EOF in skip_body")),
160                _ => {}
161            }
162        }
163        Ok(())
164    }
165
166    /// Pull a scalar element's text body — used by every scalar deserializer.
167    fn scalar_text(&mut self) -> Result<String, DeError> {
168        self.skip_leading_ws()?;
169        match self.advance()? {
170            Pending::Start { .. } => self.read_text_body(),
171            Pending::Text(t) | Pending::CData(t) => Ok(t.into_owned()),
172            other => Err(DeError::msg(format!(
173                "expected scalar element, got {other:?}"
174            ))),
175        }
176    }
177}
178
179// ── serde Deserializer impl ──────────────────────────────────────────────────
180
181macro_rules! deserialize_int {
182    ($($method:ident => $visit:ident => $ty:ty),* $(,)?) => {$(
183        fn $method<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
184            let s = self.scalar_text()?;
185            let n: $ty = s.trim().parse()
186                .map_err(|e| DeError::msg(format!("invalid {}: {e}", stringify!($ty))))?;
187            v.$visit(n)
188        }
189    )*};
190}
191
192impl<'de, 'a> de::Deserializer<'de> for &'a mut XmlDeserializer<'de> {
193    type Error = DeError;
194
195    fn deserialize_any<V: Visitor<'de>>(self, _v: V) -> Result<V::Value, DeError> {
196        Err(DeError::msg(
197            "deserialize_any is not supported — XML lacks the type metadata for it; \
198             use a typed Deserialize impl instead",
199        ))
200    }
201
202    // ── string scalars ───────────────────────────────────────────────────────
203
204    fn deserialize_str<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
205        self.deserialize_string(v)
206    }
207
208    fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
209        let s = self.scalar_text()?;
210        v.visit_string(s)
211    }
212
213    // ── numeric scalars ──────────────────────────────────────────────────────
214
215    deserialize_int! {
216        deserialize_i8   => visit_i8   => i8,
217        deserialize_i16  => visit_i16  => i16,
218        deserialize_i32  => visit_i32  => i32,
219        deserialize_i64  => visit_i64  => i64,
220        deserialize_i128 => visit_i128 => i128,
221        deserialize_u8   => visit_u8   => u8,
222        deserialize_u16  => visit_u16  => u16,
223        deserialize_u32  => visit_u32  => u32,
224        deserialize_u64  => visit_u64  => u64,
225        deserialize_u128 => visit_u128 => u128,
226        deserialize_f32  => visit_f32  => f32,
227        deserialize_f64  => visit_f64  => f64,
228    }
229
230    fn deserialize_bool<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
231        let s = self.scalar_text()?;
232        match s.trim() {
233            "true"  | "1" => v.visit_bool(true),
234            "false" | "0" => v.visit_bool(false),
235            other => Err(DeError::msg(format!("invalid bool: {other:?}"))),
236        }
237    }
238
239    fn deserialize_char<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
240        let s = self.scalar_text()?;
241        let mut it = s.chars();
242        match (it.next(), it.next()) {
243            (Some(c), None) => v.visit_char(c),
244            _ => Err(DeError::msg(format!("expected single char, got {s:?}"))),
245        }
246    }
247
248    fn deserialize_bytes<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
249        let s = self.scalar_text()?;
250        v.visit_byte_buf(s.into_bytes())
251    }
252
253    fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
254        self.deserialize_bytes(v)
255    }
256
257    // ── unit ─────────────────────────────────────────────────────────────────
258
259    fn deserialize_unit<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
260        self.skip_leading_ws()?;
261        match self.advance()? {
262            Pending::Start { .. } => { self.skip_body()?; v.visit_unit() }
263            Pending::Eof => v.visit_unit(),
264            other => Err(DeError::msg(format!("expected element for unit, got {other:?}"))),
265        }
266    }
267
268    fn deserialize_unit_struct<V: Visitor<'de>>(self, _name: &'static str, v: V)
269        -> Result<V::Value, DeError>
270    {
271        self.deserialize_unit(v)
272    }
273
274    fn deserialize_newtype_struct<V: Visitor<'de>>(self, _name: &'static str, v: V)
275        -> Result<V::Value, DeError>
276    {
277        v.visit_newtype_struct(self)
278    }
279
280    fn deserialize_ignored_any<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
281        self.skip_leading_ws()?;
282        if let Pending::Start { .. } = self.peek()? {
283            let _ = self.advance()?;
284            self.skip_body()?;
285        }
286        v.visit_unit()
287    }
288
289    // ── struct ───────────────────────────────────────────────────────────────
290
291    fn deserialize_struct<V: Visitor<'de>>(
292        self,
293        _name: &'static str,
294        fields: &'static [&'static str],
295        v: V,
296    ) -> Result<V::Value, DeError> {
297        self.skip_leading_ws()?;
298        let attrs = match self.advance()? {
299            Pending::Start { attrs, .. } => attrs,
300            other => return Err(DeError::msg(format!(
301                "expected element start for struct, got {other:?}"
302            ))),
303        };
304        let map = StructMap::new(self, attrs, fields);
305        v.visit_map(map)
306    }
307
308    // ── seq ──────────────────────────────────────────────────────────────────
309
310    fn deserialize_seq<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
311        // Capture the element name from the first peeked StartElement; the
312        // sequence yields one item per consecutive same-name element.  This
313        // is invoked from inside StructMap's value step, where the next
314        // event is the StartElement we yielded the key for.
315        self.skip_leading_ws()?;
316        let tag: Option<String> = match self.peek()? {
317            Pending::Start { name, .. } => Some(name.clone().into_owned()),
318            // No matching element — empty seq.
319            _ => None,
320        };
321        v.visit_seq(ElementSeq { de: self, tag })
322    }
323
324    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, v: V) -> Result<V::Value, DeError> {
325        self.deserialize_seq(v)
326    }
327
328    fn deserialize_tuple_struct<V: Visitor<'de>>(
329        self,
330        _name: &'static str,
331        _len: usize,
332        v: V,
333    ) -> Result<V::Value, DeError> {
334        self.deserialize_seq(v)
335    }
336
337    fn deserialize_map<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
338        // Same machinery as struct: enter the element, then iterate
339        // attrs + child elements, with each element name surfacing as a
340        // key.  HashMap<String, T> works out of the box.
341        self.skip_leading_ws()?;
342        let attrs = match self.advance()? {
343            Pending::Start { attrs, .. } => attrs,
344            other => return Err(DeError::msg(format!(
345                "expected element start for map, got {other:?}"
346            ))),
347        };
348        v.visit_map(StructMap::new(self, attrs, &[]))
349    }
350
351    fn deserialize_option<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
352        self.skip_leading_ws()?;
353        // xsi:nil="true" → None.  We check the *peeked* element's attrs;
354        // if nil, consume the empty/ignored element and visit_none.
355        if self.opts.honor_xsi_nil {
356            let nil = matches!(self.peek()?, Pending::Start { attrs, .. } if is_xsi_nil(attrs));
357            if nil {
358                let _ = self.advance()?;
359                self.skip_body()?;
360                return v.visit_none();
361            }
362        }
363        // The struct-map layer only yields a key for present elements, so
364        // by the time this fires the element is always present.
365        v.visit_some(self)
366    }
367
368    fn deserialize_enum<V: Visitor<'de>>(
369        self,
370        _name: &'static str,
371        _variants: &'static [&'static str],
372        v: V,
373    ) -> Result<V::Value, DeError> {
374        self.skip_leading_ws()?;
375        let variant = match self.peek()? {
376            Pending::Start { name, .. } => name.clone().into_owned(),
377            other => return Err(DeError::msg(format!(
378                "expected element start for enum, got {other:?}"
379            ))),
380        };
381        v.visit_enum(EnumElement { de: self, variant })
382    }
383
384    fn deserialize_identifier<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
385        self.deserialize_str(v)
386    }
387}
388
389// ── element-sequence SeqAccess ───────────────────────────────────────────────
390
391/// Yields one value per consecutive StartElement whose name matches `tag`.
392///
393/// Stops as soon as the next event is anything else — typically the parent's
394/// next child element (different name) or its EndElement.
395struct ElementSeq<'a, 'de> {
396    de:  &'a mut XmlDeserializer<'de>,
397    tag: Option<String>,
398}
399
400impl<'de> SeqAccess<'de> for ElementSeq<'_, 'de> {
401    type Error = DeError;
402
403    fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T)
404        -> Result<Option<T::Value>, DeError>
405    {
406        let tag = match &self.tag {
407            Some(t) => t.as_str(),
408            None    => return Ok(None),
409        };
410        // Skip whitespace-only text between sibling elements.
411        loop {
412            match self.de.peek()? {
413                Pending::Text(t) if t.chars().all(char::is_whitespace) => {
414                    let _ = self.de.advance()?;
415                }
416                Pending::Start { name, .. } if name.as_ref() == tag => {
417                    return seed.deserialize(&mut *self.de).map(Some);
418                }
419                _ => return Ok(None),
420            }
421        }
422    }
423}
424
425// ── enum access ──────────────────────────────────────────────────────────────
426
427/// Drives serde's enum machinery from an XML element whose tag names a
428/// variant.  `variant_seed` returns the variant name without consuming the
429/// XML element; the corresponding `VariantAccess` method then drives the
430/// element body.
431struct EnumElement<'a, 'de> {
432    de:      &'a mut XmlDeserializer<'de>,
433    variant: String,
434}
435
436impl<'de> EnumAccess<'de> for EnumElement<'_, 'de> {
437    type Error   = DeError;
438    type Variant = Self;
439
440    fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V)
441        -> Result<(V::Value, Self::Variant), DeError>
442    {
443        let de: serde::de::value::StringDeserializer<DeError> =
444            self.variant.clone().into_deserializer();
445        let value = seed.deserialize(de)?;
446        Ok((value, self))
447    }
448}
449
450impl<'de> VariantAccess<'de> for EnumElement<'_, 'de> {
451    type Error = DeError;
452
453    fn unit_variant(self) -> Result<(), DeError> {
454        // Consume `<Variant/>`.  Body must be empty (or whitespace).
455        match self.de.advance()? {
456            Pending::Start { .. } => self.de.skip_body(),
457            other => Err(DeError::msg(format!(
458                "expected element for unit variant, got {other:?}"
459            ))),
460        }
461    }
462
463    fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T)
464        -> Result<T::Value, DeError>
465    {
466        // The Start is still queued; T's deserializer consumes the whole
467        // element (e.g. <Variant>42</Variant> deserializes the body as an
468        // i32, with scalar_text walking through the End tag).
469        seed.deserialize(&mut *self.de)
470    }
471
472    fn tuple_variant<V: Visitor<'de>>(self, _len: usize, _v: V) -> Result<V::Value, DeError> {
473        Err(DeError::msg("tuple variants are not supported in v1"))
474    }
475
476    fn struct_variant<V: Visitor<'de>>(
477        self,
478        fields: &'static [&'static str],
479        v: V,
480    ) -> Result<V::Value, DeError> {
481        // Recurse into the element as a struct.  The Start is still queued.
482        de::Deserializer::deserialize_struct(&mut *self.de, "", fields, v)
483    }
484}
485
486// ── struct MapAccess ─────────────────────────────────────────────────────────
487
488/// Yields struct keys in order: attributes first (each named `@name`),
489/// then child elements as they appear (the element name is the key — or
490/// the value-field name, if `$value` is declared and the element name
491/// isn't a known field), and finally `$text` if any non-whitespace text
492/// was collected.
493struct StructMap<'a, 'de> {
494    de:                 &'a mut XmlDeserializer<'de>,
495    attrs:              std::vec::IntoIter<(Cow<'de, str>, Cow<'de, str>)>,
496    pending_attr_value: Option<Cow<'de, str>>,
497    in_body:            bool,
498    body_done:          bool,
499    text_buf:           String,
500    text_yielded:       bool,
501    text_value_pending: bool,
502    /// True once a `$value` key has been yielded so we route the value
503    /// path through `ValueSeqDeserializer`.
504    value_pending:      bool,
505    /// Field names declared on the struct.  Used to decide whether a
506    /// child element should yield its element name as the key, or be
507    /// batched under `$value`.  Empty when called from `deserialize_map`
508    /// (which surfaces every element by name).
509    fields:             &'static [&'static str],
510    /// True when `$value` is declared on the struct.
511    has_value_field:    bool,
512    attr_prefix:        char,
513    text_field_name:    &'static str,
514    value_field_name:   &'static str,
515}
516
517impl<'a, 'de> StructMap<'a, 'de> {
518    fn new(
519        de: &'a mut XmlDeserializer<'de>,
520        attrs: Vec<(Cow<'de, str>, Cow<'de, str>)>,
521        fields: &'static [&'static str],
522    ) -> Self {
523        let attr_prefix      = de.opts.attribute_prefix;
524        let text_field_name  = de.opts.text_field_name;
525        let value_field_name = de.opts.value_field_name;
526        let has_value_field  = fields.contains(&value_field_name);
527        Self {
528            de,
529            attrs: attrs.into_iter(),
530            pending_attr_value: None,
531            in_body: false,
532            body_done: false,
533            text_buf: String::new(),
534            text_yielded: false,
535            text_value_pending: false,
536            value_pending: false,
537            fields,
538            has_value_field,
539            attr_prefix,
540            text_field_name,
541            value_field_name,
542        }
543    }
544
545    /// True if this element name is one of the struct's declared field
546    /// names — meaning we surface it as that key rather than batching it
547    /// under `$value`.
548    fn is_named_field(&self, name: &str) -> bool {
549        self.fields.iter().any(|f| *f == name)
550    }
551}
552
553impl<'de> MapAccess<'de> for StructMap<'_, 'de> {
554    type Error = DeError;
555
556    fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K)
557        -> Result<Option<K::Value>, DeError>
558    {
559        // Phase 1: attributes.
560        if !self.in_body {
561            if let Some((name, value)) = self.attrs.next() {
562                self.pending_attr_value = Some(value);
563                let key = format!("{}{}", self.attr_prefix, name);
564                return seed.deserialize(key.into_deserializer()).map(Some);
565            }
566            self.in_body = true;
567        }
568
569        // Phase 2: walk body events.
570        if !self.body_done {
571            loop {
572                // Decision: surface as $value or by element name?  We need
573                // the element name for the check, so peek (without holding
574                // the borrow across the seed call).
575                let peek_kind = match self.de.peek()? {
576                    Pending::End   => PeekKind::End,
577                    Pending::Eof          => PeekKind::Eof,
578                    Pending::Text(_) | Pending::CData(_) => PeekKind::Text,
579                    Pending::Start { name, .. } => PeekKind::Start(name.clone().into_owned()),
580                };
581                match peek_kind {
582                    PeekKind::End => {
583                        let _ = self.de.advance()?;
584                        self.body_done = true;
585                        break;
586                    }
587                    PeekKind::Eof => {
588                        return Err(DeError::msg("unexpected EOF inside struct"));
589                    }
590                    PeekKind::Text => {
591                        match self.de.advance()? {
592                            Pending::Text(t) | Pending::CData(t) => self.text_buf.push_str(&t),
593                            _ => unreachable!(),
594                        }
595                    }
596                    PeekKind::Start(name) => {
597                        if self.has_value_field && !self.is_named_field(&name) {
598                            // Heterogeneous element body — yield the
599                            // value-field key once; its value is a
600                            // sequence collecting *all remaining* body
601                            // elements (until our matching End).
602                            self.value_pending = true;
603                            return seed
604                                .deserialize(self.value_field_name.into_deserializer())
605                                .map(Some);
606                        }
607                        return seed.deserialize(name.into_deserializer()).map(Some);
608                    }
609                }
610            }
611        }
612
613        // Phase 3: $text.
614        if !self.text_yielded && !self.text_buf.trim().is_empty() {
615            self.text_yielded = true;
616            self.text_value_pending = true;
617            return seed.deserialize(self.text_field_name.into_deserializer()).map(Some);
618        }
619
620        Ok(None)
621    }
622
623    fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V)
624        -> Result<V::Value, DeError>
625    {
626        if let Some(val) = self.pending_attr_value.take() {
627            return seed.deserialize(ScalarStrDeserializer { value: val });
628        }
629
630        if self.text_value_pending {
631            self.text_value_pending = false;
632            let text = std::mem::take(&mut self.text_buf);
633            return seed.deserialize(ScalarStrDeserializer { value: Cow::Owned(text) });
634        }
635
636        if self.value_pending {
637            self.value_pending = false;
638            // Hand the visitor a deserializer that, when asked for a seq,
639            // collects every remaining body element regardless of name.
640            return seed.deserialize(ValueSeqDeserializer { de: &mut *self.de });
641        }
642
643        // Element value: recurse — the next event is the StartElement we
644        // peeked at; the child consumes through its matching EndElement.
645        seed.deserialize(&mut *self.de)
646    }
647}
648
649enum PeekKind {
650    Start(String),
651    End,
652    Text,
653    Eof,
654}
655
656// ── $value support ───────────────────────────────────────────────────────────
657
658/// Deserializer for a `$value` field.  When asked for a `seq` (the common
659/// case), yields each remaining body element until the parent's End — the
660/// element name picks the variant for enum item types.
661struct ValueSeqDeserializer<'a, 'de> {
662    de: &'a mut XmlDeserializer<'de>,
663}
664
665impl<'de> de::Deserializer<'de> for ValueSeqDeserializer<'_, 'de> {
666    type Error = DeError;
667
668    fn deserialize_any<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
669        // Default to seq behaviour — that's what `$value` is for.
670        self.deserialize_seq(v)
671    }
672
673    fn deserialize_seq<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
674        v.visit_seq(AnyElementSeq { de: self.de })
675    }
676
677    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, v: V) -> Result<V::Value, DeError> {
678        self.deserialize_seq(v)
679    }
680
681    fn deserialize_tuple_struct<V: Visitor<'de>>(
682        self,
683        _name: &'static str,
684        _len: usize,
685        v: V,
686    ) -> Result<V::Value, DeError> {
687        self.deserialize_seq(v)
688    }
689
690    // For non-seq types (e.g. user wrote `$value: SingleBlock`), forward
691    // to the underlying deserializer to consume one element.
692    fn deserialize_newtype_struct<V: Visitor<'de>>(self, _name: &'static str, v: V)
693        -> Result<V::Value, DeError>
694    {
695        v.visit_newtype_struct(self)
696    }
697
698    fn deserialize_option<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
699        v.visit_some(self)
700    }
701
702    serde::forward_to_deserialize_any! {
703        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
704        char str string bytes byte_buf unit unit_struct
705        map struct enum identifier ignored_any
706    }
707}
708
709/// SeqAccess that yields one value per remaining body element (any name)
710/// until the parent's matching EndElement is encountered.  Used by
711/// `ValueSeqDeserializer`.
712struct AnyElementSeq<'a, 'de> {
713    de: &'a mut XmlDeserializer<'de>,
714}
715
716impl<'de> SeqAccess<'de> for AnyElementSeq<'_, 'de> {
717    type Error = DeError;
718
719    fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T)
720        -> Result<Option<T::Value>, DeError>
721    {
722        loop {
723            match self.de.peek()? {
724                Pending::End | Pending::Eof => return Ok(None),
725                Pending::Text(t) | Pending::CData(t) if t.chars().all(char::is_whitespace) => {
726                    let _ = self.de.advance()?;
727                }
728                Pending::Text(_) | Pending::CData(_) => {
729                    // Non-whitespace text inside a $value field — drop on
730                    // the floor (matches quick-xml's behaviour: $value is
731                    // for elements, $text is for text).
732                    let _ = self.de.advance()?;
733                }
734                Pending::Start { .. } => {
735                    return seed.deserialize(&mut *self.de).map(Some);
736                }
737            }
738        }
739    }
740}
741
742// ── helpers ──────────────────────────────────────────────────────────────────
743
744fn is_xsi_nil(attrs: &[(Cow<'_, str>, Cow<'_, str>)]) -> bool {
745    attrs.iter().any(|(n, v)|
746        n.as_ref() == "xsi:nil" && matches!(v.trim(), "true" | "1")
747    )
748}
749
750// ── scalar-string Deserializer ───────────────────────────────────────────────
751
752/// Deserializer over a single owned/borrowed string.  Used for attribute
753/// values and the `$text` field — neither of which is an XML element.
754struct ScalarStrDeserializer<'de> {
755    value: Cow<'de, str>,
756}
757
758macro_rules! sv_int {
759    ($($method:ident => $visit:ident => $ty:ty),* $(,)?) => {$(
760        fn $method<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
761            let n: $ty = self.value.trim().parse()
762                .map_err(|e| DeError::msg(format!("invalid {}: {e}", stringify!($ty))))?;
763            v.$visit(n)
764        }
765    )*};
766}
767
768impl<'de> de::Deserializer<'de> for ScalarStrDeserializer<'de> {
769    type Error = DeError;
770
771    fn deserialize_any<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
772        match self.value {
773            Cow::Borrowed(s) => v.visit_borrowed_str(s),
774            Cow::Owned(s)    => v.visit_string(s),
775        }
776    }
777
778    fn deserialize_str<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
779        match self.value {
780            Cow::Borrowed(s) => v.visit_borrowed_str(s),
781            Cow::Owned(s)    => v.visit_string(s),
782        }
783    }
784
785    fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
786        self.deserialize_str(v)
787    }
788
789    fn deserialize_bool<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
790        match self.value.trim() {
791            "true"  | "1" => v.visit_bool(true),
792            "false" | "0" => v.visit_bool(false),
793            other => Err(DeError::msg(format!("invalid bool: {other:?}"))),
794        }
795    }
796
797    fn deserialize_char<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
798        let mut it = self.value.chars();
799        match (it.next(), it.next()) {
800            (Some(c), None) => v.visit_char(c),
801            _ => Err(DeError::msg(format!("expected single char, got {:?}", self.value))),
802        }
803    }
804
805    sv_int! {
806        deserialize_i8   => visit_i8   => i8,
807        deserialize_i16  => visit_i16  => i16,
808        deserialize_i32  => visit_i32  => i32,
809        deserialize_i64  => visit_i64  => i64,
810        deserialize_i128 => visit_i128 => i128,
811        deserialize_u8   => visit_u8   => u8,
812        deserialize_u16  => visit_u16  => u16,
813        deserialize_u32  => visit_u32  => u32,
814        deserialize_u64  => visit_u64  => u64,
815        deserialize_u128 => visit_u128 => u128,
816        deserialize_f32  => visit_f32  => f32,
817        deserialize_f64  => visit_f64  => f64,
818    }
819
820    fn deserialize_bytes<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
821        match self.value {
822            Cow::Borrowed(s) => v.visit_borrowed_bytes(s.as_bytes()),
823            Cow::Owned(s)    => v.visit_byte_buf(s.into_bytes()),
824        }
825    }
826
827    fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
828        self.deserialize_bytes(v)
829    }
830
831    fn deserialize_option<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
832        v.visit_some(self)
833    }
834
835    fn deserialize_unit<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
836        v.visit_unit()
837    }
838
839    fn deserialize_unit_struct<V: Visitor<'de>>(self, _name: &'static str, v: V)
840        -> Result<V::Value, DeError>
841    {
842        v.visit_unit()
843    }
844
845    fn deserialize_newtype_struct<V: Visitor<'de>>(self, _name: &'static str, v: V)
846        -> Result<V::Value, DeError>
847    {
848        v.visit_newtype_struct(self)
849    }
850
851    fn deserialize_seq<V: Visitor<'de>>(self, _v: V) -> Result<V::Value, DeError> {
852        Err(DeError::msg("cannot deserialize attribute/text value as a seq"))
853    }
854
855    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, _v: V) -> Result<V::Value, DeError> {
856        Err(DeError::msg("cannot deserialize attribute/text value as a tuple"))
857    }
858
859    fn deserialize_tuple_struct<V: Visitor<'de>>(self, _n: &'static str, _l: usize, _v: V)
860        -> Result<V::Value, DeError>
861    {
862        Err(DeError::msg("cannot deserialize attribute/text value as a tuple struct"))
863    }
864
865    fn deserialize_map<V: Visitor<'de>>(self, _v: V) -> Result<V::Value, DeError> {
866        Err(DeError::msg("cannot deserialize attribute/text value as a map"))
867    }
868
869    fn deserialize_struct<V: Visitor<'de>>(
870        self,
871        _name: &'static str,
872        _fields: &'static [&'static str],
873        _v: V,
874    ) -> Result<V::Value, DeError> {
875        Err(DeError::msg("cannot deserialize attribute/text value as a struct"))
876    }
877
878    fn deserialize_enum<V: Visitor<'de>>(
879        self,
880        _name: &'static str,
881        _variants: &'static [&'static str],
882        v: V,
883    ) -> Result<V::Value, DeError> {
884        v.visit_enum(self.value.into_owned().into_deserializer())
885    }
886
887    fn deserialize_identifier<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
888        self.deserialize_str(v)
889    }
890
891    fn deserialize_ignored_any<V: Visitor<'de>>(self, v: V) -> Result<V::Value, DeError> {
892        v.visit_unit()
893    }
894}