Skip to main content

serde_xml/
de.rs

1//! Serde deserializer for XML.
2//!
3//! This module provides a full-featured Serde deserializer that converts
4//! XML documents into Rust data structures.
5
6use crate::error::{Error, Result};
7use crate::reader::{Attribute, XmlEvent, XmlReader};
8use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor};
9use std::borrow::Cow;
10
11/// Deserializes a value from an XML string.
12///
13/// # Example
14///
15/// ```
16/// use serde::Deserialize;
17/// use serde_xml::from_str;
18///
19/// #[derive(Deserialize)]
20/// struct Person {
21///     name: String,
22///     age: u32,
23/// }
24///
25/// let xml = "<Person><name>Alice</name><age>30</age></Person>";
26/// let person: Person = from_str(xml).unwrap();
27/// assert_eq!(person.name, "Alice");
28/// assert_eq!(person.age, 30);
29/// ```
30pub fn from_str<'de, T>(s: &'de str) -> Result<T>
31where
32    T: de::Deserialize<'de>,
33{
34    let mut de = Deserializer::from_str(s);
35    T::deserialize(&mut de)
36}
37
38/// Deserializes a value from XML bytes.
39pub fn from_bytes<'de, T>(bytes: &'de [u8]) -> Result<T>
40where
41    T: de::Deserialize<'de>,
42{
43    let s = std::str::from_utf8(bytes).map_err(|e| {
44        let offset = e.valid_up_to();
45        let mut line = 1;
46        let mut column = 1;
47        for &b in &bytes[..offset] {
48            if b == b'\n' {
49                line += 1;
50                column = 1;
51            } else if b & 0xC0 != 0x80 {
52                column += 1;
53            }
54        }
55        Error::new(crate::error::ErrorKind::InvalidUtf8)
56            .with_position(crate::error::Position { line, column, offset })
57    })?;
58    from_str(s)
59}
60
61/// The XML deserializer.
62pub struct Deserializer<'de> {
63    reader: XmlReader<'de>,
64    /// Peeked event for look-ahead.
65    peeked: Option<XmlEvent<'de>>,
66    /// Pending value to deserialize (for text content or attribute values).
67    ///
68    /// Borrowed when the value comes straight from the input (e.g. an
69    /// attribute value that needed no unescaping), so `deserialize_str` can
70    /// hand out `&'de str`.
71    pending_value: Option<Cow<'de, str>>,
72    /// Whether we already consumed the start element for the current struct.
73    start_consumed: bool,
74    /// Whether the current element is empty (<tag/>).
75    is_empty_element: bool,
76    /// Key emitted for text content in the next map ("$value" or "$text").
77    text_key: &'static str,
78    /// Whether the next element to be consumed is a field wrapper (set while
79    /// deserializing a struct-field, map-entry, or sequence-item value whose
80    /// element has not been consumed yet). Lets `deserialize_enum` know the
81    /// variant lives *inside* the wrapper rather than being the element
82    /// itself.
83    pending_wrapper: bool,
84}
85
86impl<'de> Deserializer<'de> {
87    /// Creates a new deserializer from a string.
88    #[allow(clippy::should_implement_trait)]
89    pub fn from_str(s: &'de str) -> Self {
90        Self {
91            reader: XmlReader::from_str(s),
92            peeked: None,
93            pending_value: None,
94            start_consumed: false,
95            is_empty_element: false,
96            text_key: "$value",
97            pending_wrapper: false,
98        }
99    }
100
101    /// Peeks at the next event without consuming it.
102    fn peek_event(&mut self) -> Result<&XmlEvent<'de>> {
103        if self.peeked.is_none() {
104            self.peeked = Some(self.reader.next_event()?);
105        }
106        Ok(self.peeked.as_ref().unwrap())
107    }
108
109    /// Consumes and returns the next event.
110    fn next_event(&mut self) -> Result<XmlEvent<'de>> {
111        if let Some(event) = self.peeked.take() {
112            Ok(event)
113        } else {
114            self.reader.next_event()
115        }
116    }
117
118    /// Skips events that never carry data for the value being deserialized:
119    /// the XML declaration, comments, and processing instructions.
120    ///
121    /// Called wherever an element start is expected so that a prolog before
122    /// the root element (or a comment before a nested element) does not get
123    /// consumed as if it were the element itself.
124    fn skip_ignorable_events(&mut self) -> Result<()> {
125        loop {
126            match self.peek_event()? {
127                XmlEvent::XmlDecl { .. }
128                | XmlEvent::Comment(_)
129                | XmlEvent::ProcessingInstruction { .. } => {
130                    self.next_event()?;
131                }
132                _ => return Ok(()),
133            }
134        }
135    }
136
137    /// Reads text content until we hit an end tag or another element.
138    ///
139    /// Returns borrowed text when a single event borrows from the input.
140    fn read_text_content(&mut self) -> Result<Cow<'de, str>> {
141        let mut content: Option<Cow<'de, str>> = None;
142
143        loop {
144            match self.peek_event()? {
145                XmlEvent::Text(_) | XmlEvent::CData(_) => {
146                    let text = match self.next_event()? {
147                        XmlEvent::Text(text) | XmlEvent::CData(text) => text,
148                        _ => unreachable!(),
149                    };
150                    content = Some(match content {
151                        None => text,
152                        Some(existing) => {
153                            let mut joined = existing.into_owned();
154                            joined.push_str(&text);
155                            Cow::Owned(joined)
156                        }
157                    });
158                }
159                XmlEvent::Comment(_) | XmlEvent::ProcessingInstruction { .. } => {
160                    self.next_event()?;
161                }
162                _ => break,
163            }
164        }
165
166        Ok(content.unwrap_or(Cow::Borrowed("")))
167    }
168
169    /// Reads element text and consumes the end tag.
170    fn read_element_text(&mut self) -> Result<Cow<'de, str>> {
171        if self.is_empty_element {
172            self.is_empty_element = false;
173            self.start_consumed = false;
174            return Ok(Cow::Borrowed(""));
175        }
176
177        let content = self.read_text_content()?;
178
179        // Consume end element if we're after a start element
180        if self.start_consumed {
181            self.start_consumed = false;
182            if let XmlEvent::EndElement { .. } = self.peek_event()? {
183                self.next_event()?;
184            }
185        }
186
187        Ok(content)
188    }
189
190    /// Skips the current element and all its children.
191    fn skip_element(&mut self) -> Result<()> {
192        self.drain_to_matching_end()
193    }
194
195    /// Consumes remaining content up to and including the end tag matching
196    /// the already-consumed start tag, tracking depth so leftover nested
197    /// elements don't desynchronize the reader.
198    ///
199    /// Reaching [`XmlEvent::Eof`] mid-drain means the end tag never came, so
200    /// it is reported as an error.
201    fn drain_to_matching_end(&mut self) -> Result<()> {
202        let mut depth = 0usize;
203        loop {
204            match self.peek_event()? {
205                XmlEvent::StartElement { .. } => {
206                    depth += 1;
207                    self.next_event()?;
208                }
209                XmlEvent::EndElement { .. } => {
210                    self.next_event()?;
211                    if depth == 0 {
212                        return Ok(());
213                    }
214                    depth -= 1;
215                }
216                XmlEvent::Eof => {
217                    return Err(Error::unexpected_eof().with_position(self.reader.position()))
218                }
219                _ => {
220                    self.next_event()?;
221                }
222            }
223        }
224    }
225
226    /// Parses a value from a string.
227    fn parse_value<T>(&self, s: &str) -> Result<T>
228    where
229        T: std::str::FromStr,
230        T::Err: std::fmt::Display,
231    {
232        s.parse().map_err(|e: T::Err| {
233            Error::invalid_value(e.to_string()).with_position(self.reader.position())
234        })
235    }
236
237    /// Gets text for primitive deserialization, borrowing from the input when possible.
238    fn get_text_cow(&mut self) -> Result<Cow<'de, str>> {
239        // Text consumes the field wrapper (if any) itself.
240        self.pending_wrapper = false;
241        if let Some(value) = self.pending_value.take() {
242            return Ok(value);
243        }
244
245        // If start was already consumed
246        if self.start_consumed {
247            return self.read_element_text();
248        }
249
250        // Otherwise, we might need to consume a start element first
251        self.skip_ignorable_events()?;
252        match self.peek_event()? {
253            XmlEvent::StartElement { .. } => {
254                self.next_event()?;
255                self.start_consumed = true;
256                self.is_empty_element = false;
257                self.read_element_text()
258            }
259            XmlEvent::EmptyElement { .. } => {
260                self.next_event()?;
261                Ok(Cow::Borrowed(""))
262            }
263            _ => self.read_text_content(),
264        }
265    }
266
267    /// Gets owned text for primitive deserialization.
268    fn get_text(&mut self) -> Result<String> {
269        Ok(self.get_text_cow()?.into_owned())
270    }
271}
272
273/// Picks the key emitted for text content based on a struct's fields:
274/// "$text" when the struct has a "$text" field and no "$value" field,
275/// otherwise the default "$value".
276fn text_key_for(fields: &[&'static str]) -> &'static str {
277    if fields.contains(&"$text") && !fields.contains(&"$value") {
278        "$text"
279    } else {
280        "$value"
281    }
282}
283
284impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
285    type Error = Error;
286
287    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
288    where
289        V: Visitor<'de>,
290    {
291        if let Some(value) = self.pending_value.take() {
292            return match value {
293                Cow::Borrowed(text) => visitor.visit_borrowed_str(text),
294                Cow::Owned(text) => visitor.visit_string(text),
295            };
296        }
297
298        match self.peek_event()? {
299            XmlEvent::StartElement { .. } | XmlEvent::EmptyElement { .. } => {
300                self.deserialize_map(visitor)
301            }
302            XmlEvent::Text(text) => {
303                let text = text.clone().into_owned();
304                self.next_event()?;
305                visitor.visit_string(text)
306            }
307            XmlEvent::CData(data) => {
308                let data = data.clone().into_owned();
309                self.next_event()?;
310                visitor.visit_string(data)
311            }
312            XmlEvent::EndElement { .. } => visitor.visit_unit(),
313            XmlEvent::Eof => visitor.visit_unit(),
314            _ => {
315                self.next_event()?;
316                self.deserialize_any(visitor)
317            }
318        }
319    }
320
321    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
322    where
323        V: Visitor<'de>,
324    {
325        let text = self.get_text_cow()?;
326        match &*text {
327            "true" | "1" | "yes" => visitor.visit_bool(true),
328            "false" | "0" | "no" => visitor.visit_bool(false),
329            _ => Err(Error::invalid_value(format!("expected boolean, got '{}'", text))
330                .with_position(self.reader.position())),
331        }
332    }
333
334    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
335    where
336        V: Visitor<'de>,
337    {
338        let text = self.get_text_cow()?;
339        visitor.visit_i8(self.parse_value(&text)?)
340    }
341
342    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
343    where
344        V: Visitor<'de>,
345    {
346        let text = self.get_text_cow()?;
347        visitor.visit_i16(self.parse_value(&text)?)
348    }
349
350    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
351    where
352        V: Visitor<'de>,
353    {
354        let text = self.get_text_cow()?;
355        visitor.visit_i32(self.parse_value(&text)?)
356    }
357
358    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
359    where
360        V: Visitor<'de>,
361    {
362        let text = self.get_text_cow()?;
363        visitor.visit_i64(self.parse_value(&text)?)
364    }
365
366    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
367    where
368        V: Visitor<'de>,
369    {
370        let text = self.get_text_cow()?;
371        visitor.visit_u8(self.parse_value(&text)?)
372    }
373
374    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
375    where
376        V: Visitor<'de>,
377    {
378        let text = self.get_text_cow()?;
379        visitor.visit_u16(self.parse_value(&text)?)
380    }
381
382    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
383    where
384        V: Visitor<'de>,
385    {
386        let text = self.get_text_cow()?;
387        visitor.visit_u32(self.parse_value(&text)?)
388    }
389
390    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
391    where
392        V: Visitor<'de>,
393    {
394        let text = self.get_text_cow()?;
395        visitor.visit_u64(self.parse_value(&text)?)
396    }
397
398    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
399    where
400        V: Visitor<'de>,
401    {
402        let text = self.get_text_cow()?;
403        visitor.visit_f32(self.parse_value(&text)?)
404    }
405
406    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
407    where
408        V: Visitor<'de>,
409    {
410        let text = self.get_text_cow()?;
411        visitor.visit_f64(self.parse_value(&text)?)
412    }
413
414    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
415    where
416        V: Visitor<'de>,
417    {
418        let text = self.get_text_cow()?;
419        let mut chars = text.chars();
420        match (chars.next(), chars.next()) {
421            (Some(c), None) => visitor.visit_char(c),
422            _ => Err(Error::invalid_value("expected single character")
423                .with_position(self.reader.position())),
424        }
425    }
426
427    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
428    where
429        V: Visitor<'de>,
430    {
431        match self.get_text_cow()? {
432            Cow::Borrowed(text) => visitor.visit_borrowed_str(text),
433            Cow::Owned(text) => visitor.visit_string(text),
434        }
435    }
436
437    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
438    where
439        V: Visitor<'de>,
440    {
441        let text = self.get_text()?;
442        visitor.visit_string(text)
443    }
444
445    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
446    where
447        V: Visitor<'de>,
448    {
449        match self.get_text_cow()? {
450            Cow::Borrowed(text) => visitor.visit_borrowed_bytes(text.as_bytes()),
451            Cow::Owned(text) => visitor.visit_byte_buf(text.into_bytes()),
452        }
453    }
454
455    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
456    where
457        V: Visitor<'de>,
458    {
459        self.deserialize_bytes(visitor)
460    }
461
462    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
463    where
464        V: Visitor<'de>,
465    {
466        if self.pending_value.is_some() || self.start_consumed {
467            return visitor.visit_some(self);
468        }
469
470        match self.peek_event()? {
471            XmlEvent::EndElement { .. } | XmlEvent::Eof => visitor.visit_none(),
472            _ => visitor.visit_some(self),
473        }
474    }
475
476    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
477    where
478        V: Visitor<'de>,
479    {
480        self.pending_value = None;
481        self.pending_wrapper = false;
482        if self.start_consumed && !self.is_empty_element {
483            // Consume end element
484            if let XmlEvent::EndElement { .. } = self.peek_event()? {
485                self.next_event()?;
486            }
487        }
488        self.start_consumed = false;
489        self.is_empty_element = false;
490        visitor.visit_unit()
491    }
492
493    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
494    where
495        V: Visitor<'de>,
496    {
497        self.pending_wrapper = false;
498        if self.start_consumed {
499            if !self.is_empty_element {
500                // Consume remaining content plus the end element
501                self.drain_to_matching_end()?;
502            }
503            self.start_consumed = false;
504            self.is_empty_element = false;
505            return visitor.visit_unit();
506        }
507
508        match self.peek_event()? {
509            XmlEvent::EmptyElement { .. } => {
510                self.next_event()?;
511            }
512            XmlEvent::StartElement { .. } => {
513                self.next_event()?;
514                self.drain_to_matching_end()?;
515            }
516            _ => {}
517        }
518        visitor.visit_unit()
519    }
520
521    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
522    where
523        V: Visitor<'de>,
524    {
525        visitor.visit_newtype_struct(self)
526    }
527
528    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
529    where
530        V: Visitor<'de>,
531    {
532        visitor.visit_seq(SeqDeserializer::new(self))
533    }
534
535    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
536    where
537        V: Visitor<'de>,
538    {
539        self.deserialize_seq(visitor)
540    }
541
542    fn deserialize_tuple_struct<V>(
543        self,
544        _name: &'static str,
545        _len: usize,
546        visitor: V,
547    ) -> Result<V::Value>
548    where
549        V: Visitor<'de>,
550    {
551        self.deserialize_seq(visitor)
552    }
553
554    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
555    where
556        V: Visitor<'de>,
557    {
558        // A map consumes the field wrapper (if any) as its own element.
559        self.pending_wrapper = false;
560
561        // Capture the text key for this map and reset to the default so that
562        // nested (or subsequent) maps don't inherit a stale "$text" setting.
563        let text_key = std::mem::replace(&mut self.text_key, "$value");
564
565        // Check if start was already consumed (for nested structs)
566        let (attrs, is_empty) = if self.start_consumed {
567            self.start_consumed = false;
568            let is_empty = self.is_empty_element;
569            self.is_empty_element = false;
570            (vec![], is_empty)
571        } else {
572            // Skip the prolog and any other leading non-content events so
573            // the element start itself is what gets consumed below.
574            self.skip_ignorable_events()?;
575            // Get attributes from the start element
576            match self.next_event()? {
577                XmlEvent::StartElement { attributes, .. } => (attributes, false),
578                XmlEvent::EmptyElement { attributes, .. } => (attributes, true),
579                XmlEvent::Eof => {
580                    return Err(Error::unexpected_eof().with_position(self.reader.position()))
581                }
582                _ => (vec![], false),
583            }
584        };
585
586        let result = visitor.visit_map(MapDeserializer {
587            de: self,
588            attrs,
589            attr_idx: 0,
590            finished: is_empty,
591            text_key,
592        })?;
593
594        // Consume remaining content until the matching end element.
595        if !is_empty {
596            self.drain_to_matching_end()?;
597        }
598
599        Ok(result)
600    }
601
602    fn deserialize_struct<V>(
603        self,
604        _name: &'static str,
605        fields: &'static [&'static str],
606        visitor: V,
607    ) -> Result<V::Value>
608    where
609        V: Visitor<'de>,
610    {
611        // Text content matches whichever spelling the struct uses.
612        self.text_key = text_key_for(fields);
613        self.deserialize_map(visitor)
614    }
615
616    fn deserialize_enum<V>(
617        self,
618        _name: &'static str,
619        _variants: &'static [&'static str],
620        visitor: V,
621    ) -> Result<V::Value>
622    where
623        V: Visitor<'de>,
624    {
625        // In field position the current element is the field wrapper, e.g.
626        // <status><Count>42</Count></status>: consume the wrapper so the
627        // variant (element or text content) inside it names the variant.
628        if std::mem::take(&mut self.pending_wrapper) && self.pending_value.is_none() {
629            self.skip_ignorable_events()?;
630            if matches!(self.peek_event()?, XmlEvent::EmptyElement { .. }) {
631                // An empty field wrapper (e.g. <status/>) names no variant;
632                // consume it so the reader stays synchronized and report a
633                // clear error instead of misreading the field as a variant.
634                let name = match self.next_event()? {
635                    XmlEvent::EmptyElement { name, .. } => name.into_owned(),
636                    _ => unreachable!(),
637                };
638                return Err(Error::custom(format!(
639                    "cannot deserialize enum from empty element `<{}/>`",
640                    name
641                ))
642                .with_position(self.reader.position()));
643            }
644            if matches!(self.peek_event()?, XmlEvent::StartElement { .. }) {
645                self.next_event()?;
646                let value = visitor.visit_enum(EnumDeserializer::new(&mut *self))?;
647
648                // Consume any leftover content plus the wrapper's end tag.
649                self.drain_to_matching_end()?;
650                return Ok(value);
651            }
652        }
653
654        visitor.visit_enum(EnumDeserializer::new(self))
655    }
656
657    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
658    where
659        V: Visitor<'de>,
660    {
661        self.deserialize_string(visitor)
662    }
663
664    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
665    where
666        V: Visitor<'de>,
667    {
668        self.pending_value = None;
669        self.pending_wrapper = false;
670
671        if self.start_consumed {
672            if !self.is_empty_element {
673                self.skip_element()?;
674            }
675            self.start_consumed = false;
676            self.is_empty_element = false;
677            return visitor.visit_unit();
678        }
679
680        match self.peek_event()? {
681            XmlEvent::StartElement { .. } => {
682                self.next_event()?;
683                self.skip_element()?;
684            }
685            XmlEvent::EmptyElement { .. } => {
686                self.next_event()?;
687            }
688            XmlEvent::Text(_) | XmlEvent::CData(_) => {
689                self.next_event()?;
690            }
691            _ => {}
692        }
693        visitor.visit_unit()
694    }
695}
696
697/// Sequence deserializer for arrays and vectors.
698struct SeqDeserializer<'a, 'de> {
699    de: &'a mut Deserializer<'de>,
700    element_name: Option<String>,
701}
702
703impl<'a, 'de> SeqDeserializer<'a, 'de> {
704    fn new(de: &'a mut Deserializer<'de>) -> Self {
705        Self {
706            de,
707            element_name: None,
708        }
709    }
710}
711
712impl<'de, 'a> SeqAccess<'de> for SeqDeserializer<'a, 'de> {
713    type Error = Error;
714
715    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
716    where
717        T: DeserializeSeed<'de>,
718    {
719        loop {
720            match self.de.peek_event()? {
721                XmlEvent::StartElement { name, .. } | XmlEvent::EmptyElement { name, .. } => {
722                    if let Some(ref expected) = self.element_name {
723                        if name.as_ref() != expected.as_str() {
724                            return Ok(None);
725                        }
726                    } else {
727                        self.element_name = Some(name.clone().into_owned());
728                    }
729
730                    // Each repeated element wraps one item; enums read their
731                    // variant from inside it.
732                    self.de.pending_wrapper = true;
733                    return seed.deserialize(&mut *self.de).map(Some);
734                }
735                XmlEvent::EndElement { .. } | XmlEvent::Eof => return Ok(None),
736                XmlEvent::Text(_) | XmlEvent::CData(_) => {
737                    return seed.deserialize(&mut *self.de).map(Some);
738                }
739                _ => {
740                    self.de.next_event()?;
741                }
742            }
743        }
744    }
745}
746
747/// Map deserializer for structs.
748struct MapDeserializer<'a, 'de> {
749    de: &'a mut Deserializer<'de>,
750    attrs: Vec<Attribute<'de>>,
751    attr_idx: usize,
752    finished: bool,
753    /// Key emitted for text content ("$value" or "$text").
754    text_key: &'static str,
755}
756
757impl<'de, 'a> MapAccess<'de> for MapDeserializer<'a, 'de> {
758    type Error = Error;
759
760    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
761    where
762        K: DeserializeSeed<'de>,
763    {
764        // First, return any remaining attributes (prefixed with @)
765        if self.attr_idx < self.attrs.len() {
766            let name = &self.attrs[self.attr_idx].name;
767            // Prefix with @ to match serde rename convention for attributes
768            let mut key = String::with_capacity(name.len() + 1);
769            key.push('@');
770            key.push_str(name);
771            self.de.pending_value = Some(Cow::Owned(key));
772            return seed.deserialize(&mut *self.de).map(Some);
773        }
774
775        if self.finished {
776            return Ok(None);
777        }
778
779        // Then check for child elements
780        loop {
781            match self.de.peek_event()? {
782                XmlEvent::StartElement { name, .. } | XmlEvent::EmptyElement { name, .. } => {
783                    let name = name.clone();
784                    // Don't consume the element here - let the value deserializer do it
785                    self.de.pending_value = Some(name);
786                    return seed.deserialize(&mut *self.de).map(Some);
787                }
788                XmlEvent::EndElement { .. } | XmlEvent::Eof => {
789                    self.finished = true;
790                    return Ok(None);
791                }
792                XmlEvent::Text(_) | XmlEvent::CData(_) => {
793                    self.de.pending_value = Some(Cow::Borrowed(self.text_key));
794                    return seed.deserialize(&mut *self.de).map(Some);
795                }
796                _ => {
797                    self.de.next_event()?;
798                }
799            }
800        }
801    }
802
803    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
804    where
805        V: DeserializeSeed<'de>,
806    {
807        // Handle attribute values; cloning a `Cow::Borrowed` keeps the
808        // borrow, so unescaped attribute values can still be zero-copy.
809        if self.attr_idx < self.attrs.len() {
810            let value = &self.attrs[self.attr_idx].value;
811            self.attr_idx += 1;
812            self.de.pending_value = Some(value.clone());
813            return seed.deserialize(&mut *self.de);
814        }
815
816        // Handle element values - the element itself was not consumed in
817        // next_key_seed, so mark it as a field wrapper for enum values.
818        self.de.pending_wrapper = true;
819        seed.deserialize(&mut *self.de)
820    }
821}
822
823/// Enum deserializer.
824struct EnumDeserializer<'a, 'de> {
825    de: &'a mut Deserializer<'de>,
826}
827
828impl<'a, 'de> EnumDeserializer<'a, 'de> {
829    fn new(de: &'a mut Deserializer<'de>) -> Self {
830        Self { de }
831    }
832}
833
834impl<'de, 'a> de::EnumAccess<'de> for EnumDeserializer<'a, 'de> {
835    type Error = Error;
836    type Variant = Self;
837
838    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
839    where
840        V: DeserializeSeed<'de>,
841    {
842        // Check for pending value (text-based enum)
843        if self.de.pending_value.is_some() {
844            let variant = seed.deserialize(&mut *self.de)?;
845            return Ok((variant, self));
846        }
847
848        // The variant name is the element name
849        match self.de.peek_event()? {
850            XmlEvent::StartElement { name, .. } | XmlEvent::EmptyElement { name, .. } => {
851                let name = name.clone();
852                self.de.pending_value = Some(name);
853            }
854            XmlEvent::Text(text) => {
855                let text = text.clone();
856                self.de.pending_value = Some(text);
857            }
858            _ => {}
859        }
860
861        let variant = seed.deserialize(&mut *self.de)?;
862        Ok((variant, self))
863    }
864}
865
866impl<'de, 'a> de::VariantAccess<'de> for EnumDeserializer<'a, 'de> {
867    type Error = Error;
868
869    fn unit_variant(self) -> Result<()> {
870        if self.de.start_consumed {
871            if !self.de.is_empty_element {
872                self.de.skip_element()?;
873            }
874            self.de.start_consumed = false;
875            self.de.is_empty_element = false;
876            return Ok(());
877        }
878
879        match self.de.peek_event()? {
880            XmlEvent::EmptyElement { .. } => {
881                self.de.next_event()?;
882            }
883            XmlEvent::StartElement { .. } => {
884                self.de.next_event()?;
885                self.de.skip_element()?;
886            }
887            _ => {}
888        }
889        Ok(())
890    }
891
892    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
893    where
894        T: DeserializeSeed<'de>,
895    {
896        // The variant element wraps the inner value; nested enums read their
897        // variant from inside it.
898        self.de.pending_wrapper = true;
899        seed.deserialize(&mut *self.de)
900    }
901
902    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
903    where
904        V: Visitor<'de>,
905    {
906        // The variant element wraps the tuple items (<Pair><item>1</item>
907        // ...</Pair>); consume it so the sequence sees the items themselves.
908        if matches!(self.de.peek_event()?, XmlEvent::StartElement { .. }) {
909            self.de.next_event()?;
910            let value = de::Deserializer::deserialize_seq(&mut *self.de, visitor)?;
911            // Consume the variant's end element
912            if let XmlEvent::EndElement { .. } = self.de.peek_event()? {
913                self.de.next_event()?;
914            }
915            return Ok(value);
916        }
917        de::Deserializer::deserialize_seq(&mut *self.de, visitor)
918    }
919
920    fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
921    where
922        V: Visitor<'de>,
923    {
924        // Match text content against whichever spelling the variant uses,
925        // the same way `deserialize_struct` does for plain structs.
926        self.de.text_key = text_key_for(fields);
927        de::Deserializer::deserialize_map(&mut *self.de, visitor)
928    }
929}
930
931#[cfg(test)]
932mod tests {
933    use super::*;
934    use serde::{Deserialize, Serialize};
935
936    #[test]
937    fn test_deserialize_simple_struct() {
938        #[derive(Debug, Deserialize, PartialEq)]
939        struct Person {
940            name: String,
941            age: u32,
942        }
943
944        let xml = "<Person><name>Alice</name><age>30</age></Person>";
945        let person: Person = from_str(xml).unwrap();
946        assert_eq!(person.name, "Alice");
947        assert_eq!(person.age, 30);
948    }
949
950    #[test]
951    fn test_deserialize_with_attributes() {
952        #[derive(Debug, Deserialize, PartialEq)]
953        struct Item {
954            #[serde(rename = "@id")]
955            id: String,
956            name: String,
957        }
958
959        let xml = r#"<Item id="123"><name>Widget</name></Item>"#;
960        let item: Item = from_str(xml).unwrap();
961        assert_eq!(item.id, "123");
962        assert_eq!(item.name, "Widget");
963    }
964
965    #[test]
966    fn test_deserialize_nested_struct() {
967        #[derive(Debug, Deserialize, PartialEq)]
968        struct Address {
969            city: String,
970            country: String,
971        }
972
973        #[derive(Debug, Deserialize, PartialEq)]
974        struct Person {
975            name: String,
976            address: Address,
977        }
978
979        let xml = r#"
980            <Person>
981                <name>Bob</name>
982                <address>
983                    <city>New York</city>
984                    <country>USA</country>
985                </address>
986            </Person>
987        "#;
988        let person: Person = from_str(xml).unwrap();
989        assert_eq!(person.name, "Bob");
990        assert_eq!(person.address.city, "New York");
991    }
992
993    #[test]
994    fn test_deserialize_optional() {
995        #[derive(Debug, Deserialize, PartialEq)]
996        struct Config {
997            name: String,
998            #[serde(default)]
999            value: Option<String>,
1000        }
1001
1002        let xml1 = "<Config><name>test</name><value>val</value></Config>";
1003        let config1: Config = from_str(xml1).unwrap();
1004        assert_eq!(config1.value, Some("val".to_string()));
1005
1006        let xml2 = "<Config><name>test</name></Config>";
1007        let config2: Config = from_str(xml2).unwrap();
1008        assert_eq!(config2.value, None);
1009    }
1010
1011    #[test]
1012    fn test_deserialize_bool() {
1013        #[derive(Debug, Deserialize, PartialEq)]
1014        struct Flags {
1015            enabled: bool,
1016            active: bool,
1017        }
1018
1019        let xml = "<Flags><enabled>true</enabled><active>false</active></Flags>";
1020        let flags: Flags = from_str(xml).unwrap();
1021        assert!(flags.enabled);
1022        assert!(!flags.active);
1023    }
1024
1025    #[test]
1026    fn test_deserialize_numbers() {
1027        #[derive(Debug, Deserialize, PartialEq)]
1028        struct Numbers {
1029            i: i32,
1030            u: u64,
1031            f: f64,
1032        }
1033
1034        let xml = "<Numbers><i>-42</i><u>100</u><f>1.234</f></Numbers>";
1035        let nums: Numbers = from_str(xml).unwrap();
1036        assert_eq!(nums.i, -42);
1037        assert_eq!(nums.u, 100);
1038        assert!((nums.f - 1.234).abs() < 0.001);
1039    }
1040
1041    #[test]
1042    fn test_deserialize_vector() {
1043        #[derive(Debug, Deserialize, PartialEq)]
1044        struct Items {
1045            item: Vec<String>,
1046        }
1047
1048        let xml = r#"<Items><item>one</item><item>two</item><item>three</item></Items>"#;
1049        let items: Items = from_str(xml).unwrap();
1050        assert_eq!(items.item, vec!["one", "two", "three"]);
1051    }
1052
1053    #[test]
1054    fn test_deserialize_escaped_content() {
1055        #[derive(Debug, Deserialize, PartialEq)]
1056        struct Data {
1057            content: String,
1058        }
1059
1060        let xml = "<Data><content>&lt;hello&gt; &amp; &quot;world&quot;</content></Data>";
1061        let data: Data = from_str(xml).unwrap();
1062        assert_eq!(data.content, "<hello> & \"world\"");
1063    }
1064
1065    #[test]
1066    fn test_deserialize_empty_element() {
1067        #[derive(Debug, Deserialize, PartialEq)]
1068        struct Empty {
1069            #[serde(default)]
1070            value: String,
1071        }
1072
1073        let xml = "<Empty><value></value></Empty>";
1074        let empty: Empty = from_str(xml).unwrap();
1075        assert_eq!(empty.value, "");
1076    }
1077
1078    #[test]
1079    fn test_deserialize_char() {
1080        #[derive(Debug, Deserialize, PartialEq)]
1081        struct Data {
1082            c: char,
1083        }
1084
1085        let xml = "<Data><c>A</c></Data>";
1086        let data: Data = from_str(xml).unwrap();
1087        assert_eq!(data.c, 'A');
1088    }
1089
1090    #[test]
1091    fn test_deserialize_unit_struct() {
1092        #[derive(Debug, Deserialize, PartialEq)]
1093        struct Unit;
1094
1095        let xml = "<Unit/>";
1096        let _unit: Unit = from_str(xml).unwrap();
1097    }
1098
1099    #[test]
1100    fn test_from_bytes() {
1101        #[derive(Debug, Deserialize, PartialEq)]
1102        struct Data {
1103            value: String,
1104        }
1105
1106        let bytes = b"<Data><value>test</value></Data>";
1107        let data: Data = from_bytes(bytes).unwrap();
1108        assert_eq!(data.value, "test");
1109    }
1110
1111    #[test]
1112    fn test_deserialize_vector_of_structs() {
1113        #[derive(Debug, Deserialize, PartialEq)]
1114        struct Item {
1115            name: String,
1116            count: u32,
1117        }
1118
1119        #[derive(Debug, Deserialize, PartialEq)]
1120        struct Items {
1121            item: Vec<Item>,
1122        }
1123
1124        let xml = r#"<Items><item><name>A</name><count>1</count></item><item><name>B</name><count>2</count></item></Items>"#;
1125        let items: Items = from_str(xml).unwrap();
1126        assert_eq!(items.item.len(), 2);
1127        assert_eq!(items.item[0].name, "A");
1128        assert_eq!(items.item[1].name, "B");
1129    }
1130
1131    #[test]
1132    fn test_deserialize_multiple_attributes() {
1133        #[derive(Debug, Deserialize, PartialEq)]
1134        struct Element {
1135            #[serde(rename = "@id")]
1136            id: String,
1137            #[serde(rename = "@class")]
1138            class: String,
1139            name: String,
1140        }
1141
1142        let xml = r#"<Element id="main" class="container"><name>Test</name></Element>"#;
1143        let elem: Element = from_str(xml).unwrap();
1144        assert_eq!(elem.id, "main");
1145        assert_eq!(elem.class, "container");
1146        assert_eq!(elem.name, "Test");
1147    }
1148
1149    #[test]
1150    fn test_deserialize_attributes_with_special_chars() {
1151        #[derive(Debug, Deserialize, PartialEq)]
1152        struct Element {
1153            #[serde(rename = "@title")]
1154            title: String,
1155        }
1156
1157        let xml = r#"<Element title="Hello &amp; &quot;World&quot;"/>"#;
1158        let elem: Element = from_str(xml).unwrap();
1159        assert_eq!(elem.title, "Hello & \"World\"");
1160    }
1161
1162    #[test]
1163    fn test_deserialize_numeric_attributes() {
1164        #[derive(Debug, Deserialize, PartialEq)]
1165        struct Item {
1166            #[serde(rename = "@id")]
1167            id: u32,
1168            #[serde(rename = "@count")]
1169            count: i32,
1170            #[serde(rename = "@price")]
1171            price: f64,
1172            #[serde(rename = "@active")]
1173            active: bool,
1174        }
1175
1176        let xml = r#"<Item id="42" count="-10" price="19.99" active="true"/>"#;
1177        let item: Item = from_str(xml).unwrap();
1178        assert_eq!(item.id, 42);
1179        assert_eq!(item.count, -10);
1180        assert!((item.price - 19.99).abs() < 0.001);
1181        assert!(item.active);
1182    }
1183
1184    #[test]
1185    fn test_deserialize_empty_element_with_attributes() {
1186        #[derive(Debug, Deserialize, PartialEq)]
1187        struct Empty {
1188            #[serde(rename = "@id")]
1189            id: String,
1190            #[serde(default)]
1191            value: String,
1192        }
1193
1194        let xml = r#"<Empty id="test"/>"#;
1195        let elem: Empty = from_str(xml).unwrap();
1196        assert_eq!(elem.id, "test");
1197        assert_eq!(elem.value, "");
1198    }
1199
1200    #[test]
1201    fn test_deserialize_nested_with_attributes() {
1202        #[derive(Debug, Deserialize, PartialEq)]
1203        struct Child {
1204            #[serde(rename = "@name")]
1205            name: String,
1206        }
1207
1208        #[derive(Debug, Deserialize, PartialEq)]
1209        struct Parent {
1210            #[serde(rename = "@id")]
1211            id: String,
1212            child: Child,
1213        }
1214
1215        let xml = r#"<Parent id="p1"><child name="c1"/></Parent>"#;
1216        let parent: Parent = from_str(xml).unwrap();
1217        assert_eq!(parent.id, "p1");
1218        assert_eq!(parent.child.name, "c1");
1219    }
1220
1221    #[test]
1222    fn test_deserialize_vector_with_attributes() {
1223        #[derive(Debug, Deserialize, PartialEq)]
1224        struct Item {
1225            #[serde(rename = "@id")]
1226            id: u32,
1227            name: String,
1228        }
1229
1230        #[derive(Debug, Deserialize, PartialEq)]
1231        struct List {
1232            #[serde(rename = "@version")]
1233            version: String,
1234            item: Vec<Item>,
1235        }
1236
1237        let xml = r#"<List version="1.0"><item id="1"><name>A</name></item><item id="2"><name>B</name></item></List>"#;
1238        let list: List = from_str(xml).unwrap();
1239        assert_eq!(list.version, "1.0");
1240        assert_eq!(list.item.len(), 2);
1241        assert_eq!(list.item[0].id, 1);
1242        assert_eq!(list.item[1].id, 2);
1243    }
1244
1245    #[test]
1246    fn test_deserialize_value_text_with_attribute() {
1247        #[derive(Debug, Deserialize, PartialEq)]
1248        struct Link {
1249            #[serde(rename = "@href")]
1250            href: String,
1251            #[serde(rename = "$value")]
1252            value: String,
1253        }
1254
1255        let xml = r#"<Link href="https://example.com">Example</Link>"#;
1256        let link: Link = from_str(xml).unwrap();
1257        assert_eq!(link.href, "https://example.com");
1258        assert_eq!(link.value, "Example");
1259    }
1260
1261    #[test]
1262    fn test_round_trip_text_rename_with_attribute() {
1263        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1264        struct Link {
1265            #[serde(rename = "@href")]
1266            href: String,
1267            #[serde(rename = "$text")]
1268            text: String,
1269        }
1270
1271        let link = Link {
1272            href: "https://example.com".to_string(),
1273            text: "Example".to_string(),
1274        };
1275
1276        let xml = crate::to_string(&link).unwrap();
1277        let parsed: Link = from_str(&xml).unwrap();
1278        assert_eq!(parsed, link);
1279    }
1280
1281    #[test]
1282    fn test_deserialize_text_rename() {
1283        #[derive(Debug, Deserialize, PartialEq)]
1284        struct Link {
1285            #[serde(rename = "@href")]
1286            href: String,
1287            #[serde(rename = "$text")]
1288            text: String,
1289        }
1290
1291        let xml = r#"<Link href="https://example.com">Example</Link>"#;
1292        let link: Link = from_str(xml).unwrap();
1293        assert_eq!(link.href, "https://example.com");
1294        assert_eq!(link.text, "Example");
1295    }
1296
1297    #[test]
1298    fn test_invalid_number_error_has_position() {
1299        #[derive(Debug, Deserialize)]
1300        struct Person {
1301            age: u32,
1302        }
1303
1304        let xml = "<Person><age>abc</age></Person>";
1305        let err = from_str::<Person>(xml).unwrap_err();
1306        // The parse error is raised right after the reader consumed `</age>`
1307        // (byte offset 22, i.e. column 23 on line 1).
1308        let pos = err.position().expect("error should carry a position");
1309        assert_eq!(pos.line, 1);
1310        assert_eq!(pos.column, 23);
1311        assert_eq!(pos.offset, 22);
1312
1313        // The same input with a valid number deserializes fine.
1314        let person: Person = from_str("<Person><age>30</age></Person>").unwrap();
1315        assert_eq!(person.age, 30);
1316    }
1317
1318    #[test]
1319    fn test_deserialize_borrowed_str() {
1320        #[derive(Debug, Deserialize, PartialEq)]
1321        struct Borrowed<'a> {
1322            #[serde(borrow)]
1323            name: &'a str,
1324        }
1325
1326        let xml = "<Borrowed><name>hi</name></Borrowed>";
1327        let borrowed: Borrowed<'_> = from_str(xml).unwrap();
1328        assert_eq!(borrowed.name, "hi");
1329    }
1330
1331    #[test]
1332    fn test_deserialize_skips_comments_and_pis() {
1333        #[derive(Debug, Deserialize, PartialEq)]
1334        struct Person {
1335            name: String,
1336            age: u32,
1337        }
1338
1339        let xml = "<Person><!-- a comment --><name>Alice</name><?pi data?><age>30</age><!-- trailing --></Person>";
1340        let person: Person = from_str(xml).unwrap();
1341        assert_eq!(person.name, "Alice");
1342        assert_eq!(person.age, 30);
1343    }
1344
1345    #[test]
1346    fn test_invalid_bool_error_has_position() {
1347        #[derive(Debug, Deserialize)]
1348        struct Flags {
1349            b: bool,
1350        }
1351
1352        let xml = "<a><b>maybe</b></a>";
1353        let err = from_str::<Flags>(xml).unwrap_err();
1354        // The error is raised right after the reader consumed `</b>`
1355        // (byte offset 15, i.e. column 16 on line 1).
1356        let pos = err.position().expect("error should carry a position");
1357        assert_eq!(pos.line, 1);
1358        assert_eq!(pos.column, 16);
1359        assert_eq!(pos.offset, 15);
1360
1361        // The same input with a valid boolean deserializes fine.
1362        let flags: Flags = from_str("<a><b>yes</b></a>").unwrap();
1363        assert!(flags.b);
1364    }
1365
1366    #[test]
1367    fn test_invalid_char_error_has_position() {
1368        #[derive(Debug, Deserialize)]
1369        struct Data {
1370            c: char,
1371        }
1372
1373        let xml = "<Data><c>abc</c></Data>";
1374        let err = from_str::<Data>(xml).unwrap_err();
1375        // The error is raised right after the reader consumed `</c>`
1376        // (byte offset 16, i.e. column 17 on line 1).
1377        let pos = err.position().expect("error should carry a position");
1378        assert_eq!(pos.line, 1);
1379        assert_eq!(pos.column, 17);
1380        assert_eq!(pos.offset, 16);
1381
1382        // The same input with a single character deserializes fine.
1383        let data: Data = from_str("<Data><c>x</c></Data>").unwrap();
1384        assert_eq!(data.c, 'x');
1385    }
1386
1387    #[test]
1388    fn test_deserialize_borrowed_attribute() {
1389        #[derive(Debug, Deserialize, PartialEq)]
1390        struct Tag<'a> {
1391            #[serde(rename = "@href", borrow)]
1392            href: &'a str,
1393        }
1394
1395        let xml = r#"<Tag href="x"/>"#;
1396        let tag: Tag<'_> = from_str(xml).unwrap();
1397        assert_eq!(tag.href, "x");
1398    }
1399
1400    #[test]
1401    fn test_deserialize_escaped_attribute_falls_back_to_owned() {
1402        #[derive(Debug, Deserialize, PartialEq)]
1403        struct Tag<'a> {
1404            #[serde(rename = "@href", borrow)]
1405            href: Cow<'a, str>,
1406        }
1407
1408        let xml = r#"<Tag href="a &amp; b"/>"#;
1409        let tag: Tag<'_> = from_str(xml).unwrap();
1410        assert_eq!(tag.href, "a & b");
1411        assert!(matches!(tag.href, Cow::Owned(_)));
1412    }
1413
1414    #[test]
1415    fn test_deserialize_comment_before_root() {
1416        #[derive(Debug, Deserialize, PartialEq)]
1417        struct Person {
1418            name: String,
1419            age: u32,
1420        }
1421
1422        let xml = "<!-- leading --><Person><name>Alice</name><age>30</age></Person>";
1423        let person: Person = from_str(xml).unwrap();
1424        assert_eq!(person.name, "Alice");
1425        assert_eq!(person.age, 30);
1426    }
1427
1428    #[test]
1429    fn test_deserialize_pi_before_root() {
1430        #[derive(Debug, Deserialize, PartialEq)]
1431        struct Person {
1432            name: String,
1433            age: u32,
1434        }
1435
1436        let xml = "<?pi data?><Person><name>Alice</name><age>30</age></Person>";
1437        let person: Person = from_str(xml).unwrap();
1438        assert_eq!(person.name, "Alice");
1439        assert_eq!(person.age, 30);
1440    }
1441
1442    #[test]
1443    fn test_deserialize_xml_decl_before_root() {
1444        #[derive(Debug, Deserialize, PartialEq)]
1445        struct Person {
1446            name: String,
1447            age: u32,
1448        }
1449
1450        let xml = r#"<?xml version="1.0"?><Person><name>Alice</name><age>30</age></Person>"#;
1451        let person: Person = from_str(xml).unwrap();
1452        assert_eq!(person.name, "Alice");
1453        assert_eq!(person.age, 30);
1454    }
1455
1456    #[test]
1457    fn test_round_trip_enum_field_unit_variant() {
1458        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1459        enum Status {
1460            Active,
1461            Inactive,
1462        }
1463
1464        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1465        struct Item {
1466            status: Status,
1467            name: String,
1468        }
1469
1470        let item = Item {
1471            status: Status::Active,
1472            name: "widget".to_string(),
1473        };
1474
1475        let xml = crate::to_string(&item).unwrap();
1476        let parsed: Item = from_str(&xml).unwrap();
1477        assert_eq!(parsed, item);
1478
1479        let item = Item {
1480            status: Status::Inactive,
1481            name: "gadget".to_string(),
1482        };
1483
1484        let xml = crate::to_string(&item).unwrap();
1485        let parsed: Item = from_str(&xml).unwrap();
1486        assert_eq!(parsed, item);
1487    }
1488
1489    #[test]
1490    fn test_round_trip_enum_field_newtype_variant() {
1491        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1492        enum Status {
1493            Count(u32),
1494        }
1495
1496        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1497        struct Item {
1498            status: Status,
1499            name: String,
1500        }
1501
1502        let item = Item {
1503            status: Status::Count(42),
1504            name: "widget".to_string(),
1505        };
1506
1507        let xml = crate::to_string(&item).unwrap();
1508        let parsed: Item = from_str(&xml).unwrap();
1509        assert_eq!(parsed, item);
1510    }
1511
1512    #[test]
1513    fn test_round_trip_enum_field_tuple_variant() {
1514        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1515        enum Status {
1516            Pair(u32, String),
1517        }
1518
1519        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1520        struct Item {
1521            status: Status,
1522            name: String,
1523        }
1524
1525        let item = Item {
1526            status: Status::Pair(1, "one".to_string()),
1527            name: "widget".to_string(),
1528        };
1529
1530        let xml = crate::to_string(&item).unwrap();
1531        let parsed: Item = from_str(&xml).unwrap();
1532        assert_eq!(parsed, item);
1533    }
1534
1535    #[test]
1536    fn test_round_trip_enum_field_struct_variant() {
1537        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1538        enum Status {
1539            Point { x: i32, y: i32 },
1540        }
1541
1542        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1543        struct Item {
1544            status: Status,
1545            name: String,
1546        }
1547
1548        let item = Item {
1549            status: Status::Point { x: 1, y: 2 },
1550            name: "widget".to_string(),
1551        };
1552
1553        let xml = crate::to_string(&item).unwrap();
1554        let parsed: Item = from_str(&xml).unwrap();
1555        assert_eq!(parsed, item);
1556    }
1557
1558    #[test]
1559    fn test_round_trip_enum_field_struct_variant_text() {
1560        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1561        enum Content {
1562            Message {
1563                #[serde(rename = "@lang")]
1564                lang: String,
1565                #[serde(rename = "$text")]
1566                text: String,
1567            },
1568        }
1569
1570        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1571        struct Doc {
1572            content: Content,
1573            footer: String,
1574        }
1575
1576        let doc = Doc {
1577            content: Content::Message {
1578                lang: "en".to_string(),
1579                text: "hello".to_string(),
1580            },
1581            footer: "bye".to_string(),
1582        };
1583
1584        let xml = crate::to_string(&doc).unwrap();
1585        let parsed: Doc = from_str(&xml).unwrap();
1586        assert_eq!(parsed, doc);
1587    }
1588
1589    #[test]
1590    fn test_deserialize_top_level_enum_variants() {
1591        #[derive(Debug, Serialize, Deserialize, PartialEq)]
1592        enum Value {
1593            Unit,
1594            Count(u32),
1595            Pair(u32, String),
1596            Point { x: i32, y: i32 },
1597        }
1598
1599        let unit: Value = from_str("<Unit/>").unwrap();
1600        assert_eq!(unit, Value::Unit);
1601
1602        let count: Value = from_str("<Count>42</Count>").unwrap();
1603        assert_eq!(count, Value::Count(42));
1604
1605        let pair: Value = from_str("<Pair><item>1</item><item>one</item></Pair>").unwrap();
1606        assert_eq!(pair, Value::Pair(1, "one".to_string()));
1607
1608        let point: Value = from_str("<Point><x>1</x><y>2</y></Point>").unwrap();
1609        assert_eq!(point, Value::Point { x: 1, y: 2 });
1610    }
1611
1612    #[test]
1613    fn test_deserialize_cdata_content() {
1614        #[derive(Debug, Deserialize, PartialEq)]
1615        struct Data {
1616            content: String,
1617        }
1618
1619        let xml = "<Data><content><![CDATA[<raw> & stuff]]></content></Data>";
1620        let data: Data = from_str(xml).unwrap();
1621        assert_eq!(data.content, "<raw> & stuff");
1622    }
1623
1624    #[test]
1625    fn test_from_bytes_invalid_utf8_has_position() {
1626        // The valid prefix is `<a>\n` (4 bytes), so the invalid byte sits at
1627        // the start of line 2.
1628        let bytes = b"<a>\n\xff</a>";
1629        let err = from_bytes::<String>(bytes).unwrap_err();
1630        let pos = err.position().expect("error should carry a position");
1631        assert_eq!(pos.line, 2);
1632        assert_eq!(pos.column, 1);
1633        assert_eq!(pos.offset, 4);
1634    }
1635
1636    #[test]
1637    fn test_deserialize_mixed_text_and_cdata() {
1638        #[derive(Debug, Deserialize, PartialEq)]
1639        struct Data {
1640            content: String,
1641        }
1642
1643        let xml = "<Data><content>a<![CDATA[<b>]]>c</content></Data>";
1644        let data: Data = from_str(xml).unwrap();
1645        assert_eq!(data.content, "a<b>c");
1646    }
1647
1648    #[test]
1649    fn test_deserialize_bytes_borrowed() {
1650        #[derive(Debug, PartialEq)]
1651        struct Bytes<'a>(Cow<'a, [u8]>);
1652
1653        impl<'de: 'a, 'a> Deserialize<'de> for Bytes<'a> {
1654            fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1655            where
1656                D: de::Deserializer<'de>,
1657            {
1658                struct BytesVisitor;
1659
1660                impl<'de> Visitor<'de> for BytesVisitor {
1661                    type Value = Bytes<'de>;
1662
1663                    fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1664                        f.write_str("bytes")
1665                    }
1666
1667                    fn visit_borrowed_bytes<E>(
1668                        self,
1669                        v: &'de [u8],
1670                    ) -> std::result::Result<Self::Value, E> {
1671                        Ok(Bytes(Cow::Borrowed(v)))
1672                    }
1673
1674                    fn visit_byte_buf<E>(self, v: Vec<u8>) -> std::result::Result<Self::Value, E> {
1675                        Ok(Bytes(Cow::Owned(v)))
1676                    }
1677                }
1678
1679                deserializer.deserialize_bytes(BytesVisitor)
1680            }
1681        }
1682
1683        #[derive(Debug, Deserialize, PartialEq)]
1684        struct Doc<'a> {
1685            #[serde(borrow)]
1686            b: Bytes<'a>,
1687        }
1688
1689        // Plain text needs no unescaping, so the bytes borrow from the input.
1690        let xml = "<D><b>hi</b></D>";
1691        let doc: Doc<'_> = from_str(xml).unwrap();
1692        assert_eq!(doc.b.0.as_ref(), b"hi");
1693        assert!(matches!(doc.b.0, Cow::Borrowed(_)));
1694
1695        // Escaped content cannot borrow, so it takes the owned arm.
1696        let xml = "<D><b>a &amp; b</b></D>";
1697        let doc: Doc<'_> = from_str(xml).unwrap();
1698        assert_eq!(doc.b.0.as_ref(), b"a & b");
1699        assert!(matches!(doc.b.0, Cow::Owned(_)));
1700    }
1701
1702    #[test]
1703    fn test_deserialize_ignores_unknown_nested_element() {
1704        #[derive(Debug, Deserialize, PartialEq)]
1705        struct Person {
1706            name: String,
1707        }
1708
1709        let xml = "<Person><name>Alice</name><extra><deep>x</deep></extra></Person>";
1710        let person: Person = from_str(xml).unwrap();
1711        assert_eq!(person.name, "Alice");
1712
1713        // Skipping the unknown element must leave the reader synchronized so
1714        // that a following sibling still parses.
1715        #[derive(Debug, Deserialize, PartialEq)]
1716        struct People {
1717            person: Vec<Person>,
1718        }
1719
1720        let xml = "<People>\
1721            <person><name>Alice</name><extra><deep>x</deep></extra></person>\
1722            <person><name>Bob</name></person>\
1723            </People>";
1724        let people: People = from_str(xml).unwrap();
1725        assert_eq!(
1726            people.person,
1727            vec![
1728                Person {
1729                    name: "Alice".to_string()
1730                },
1731                Person {
1732                    name: "Bob".to_string()
1733                },
1734            ]
1735        );
1736    }
1737
1738    #[test]
1739    fn test_deserialize_empty_input_errors() {
1740        #[derive(Debug, Deserialize, PartialEq)]
1741        struct Person {
1742            name: String,
1743            age: u32,
1744        }
1745
1746        let err = from_str::<Person>("").unwrap_err();
1747        assert!(matches!(
1748            err.kind(),
1749            crate::error::ErrorKind::UnexpectedEof
1750        ));
1751    }
1752
1753    #[test]
1754    fn test_deserialize_unit_struct_truncated_errors() {
1755        #[derive(Debug, Deserialize, PartialEq)]
1756        struct Unit;
1757
1758        // A start tag with no matching end tag must not silently succeed.
1759        assert!(from_str::<Unit>("<Unit>").is_err());
1760    }
1761
1762    #[test]
1763    fn test_deserialize_enum_field_empty_element_errors() {
1764        #[derive(Debug, Deserialize, PartialEq)]
1765        enum Status {
1766            Active,
1767        }
1768
1769        #[derive(Debug, Deserialize, PartialEq)]
1770        struct S {
1771            status: Status,
1772        }
1773
1774        let err = from_str::<S>("<S><status/></S>").unwrap_err();
1775        assert!(err.to_string().contains("empty element `<status/>`"));
1776    }
1777}