Skip to main content

quick_xml/de/
var.rs

1use crate::{
2    de::key::QNameDeserializer,
3    de::map::ElementMapAccess,
4    de::resolver::EntityResolver,
5    de::simple_type::SimpleTypeDeserializer,
6    de::{DeEvent, Deserializer, XmlRead, TEXT_KEY},
7    errors::serialize::DeError,
8};
9use serde::de::value::BorrowedStrDeserializer;
10use serde::de::{self, DeserializeSeed, Deserializer as _, Visitor};
11
12/// An enum access
13pub struct EnumAccess<'de, 'd, R, E>
14where
15    R: XmlRead<'de>,
16    E: EntityResolver,
17{
18    de: &'d mut Deserializer<'de, R, E>,
19}
20
21impl<'de, 'd, R, E> EnumAccess<'de, 'd, R, E>
22where
23    R: XmlRead<'de>,
24    E: EntityResolver,
25{
26    pub fn new(de: &'d mut Deserializer<'de, R, E>) -> Self {
27        EnumAccess { de }
28    }
29}
30
31impl<'de, 'd, R, E> de::EnumAccess<'de> for EnumAccess<'de, 'd, R, E>
32where
33    R: XmlRead<'de>,
34    E: EntityResolver,
35{
36    type Error = DeError;
37    type Variant = VariantAccess<'de, 'd, R, E>;
38
39    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
40    where
41        V: DeserializeSeed<'de>,
42    {
43        let (name, is_text) = match self.de.peek()? {
44            DeEvent::Start(e) => (seed.deserialize(QNameDeserializer::from_elem(e)?)?, false),
45            DeEvent::Text(_) => (
46                seed.deserialize(BorrowedStrDeserializer::<DeError>::new(TEXT_KEY))?,
47                true,
48            ),
49            // SAFETY: The reader is guaranteed that we don't have unmatched tags
50            // If we here, then our deserializer has a bug
51            DeEvent::End(e) => unreachable!("{:?}", e),
52            DeEvent::Eof => return Err(DeError::UnexpectedEof),
53        };
54        Ok((
55            name,
56            VariantAccess {
57                de: self.de,
58                is_text,
59            },
60        ))
61    }
62}
63
64pub struct VariantAccess<'de, 'd, R, E>
65where
66    R: XmlRead<'de>,
67    E: EntityResolver,
68{
69    de: &'d mut Deserializer<'de, R, E>,
70    /// `true` if variant should be deserialized from a textual content
71    /// and `false` if from tag
72    is_text: bool,
73}
74
75impl<'de, 'd, R, E> de::VariantAccess<'de> for VariantAccess<'de, 'd, R, E>
76where
77    R: XmlRead<'de>,
78    E: EntityResolver,
79{
80    type Error = DeError;
81
82    fn unit_variant(self) -> Result<(), Self::Error> {
83        match self.de.next()? {
84            // Consume subtree
85            DeEvent::Start(e) => self.de.read_to_end(e.name()),
86            // Does not needed to deserialize using SimpleTypeDeserializer, because
87            // it returns `()` when `deserialize_unit()` is requested
88            DeEvent::Text(_) => Ok(()),
89            // SAFETY: the other events are filtered in `variant_seed()`
90            _ => unreachable!("Only `Start` or `Text` events are possible here"),
91        }
92    }
93
94    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
95    where
96        T: DeserializeSeed<'de>,
97    {
98        if self.is_text {
99            match self.de.next()? {
100                DeEvent::Text(e) => seed.deserialize(SimpleTypeDeserializer::from_text_content(e)),
101                // SAFETY: the other events are filtered in `variant_seed()`
102                _ => unreachable!("Only `Text` events are possible here"),
103            }
104        } else {
105            seed.deserialize(self.de)
106        }
107    }
108
109    fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
110    where
111        V: Visitor<'de>,
112    {
113        if self.is_text {
114            match self.de.next()? {
115                DeEvent::Text(e) => {
116                    SimpleTypeDeserializer::from_text_content(e).deserialize_tuple(len, visitor)
117                }
118                // SAFETY: the other events are filtered in `variant_seed()`
119                _ => unreachable!("Only `Text` events are possible here"),
120            }
121        } else {
122            self.de.deserialize_tuple(len, visitor)
123        }
124    }
125
126    fn struct_variant<V>(
127        self,
128        fields: &'static [&'static str],
129        visitor: V,
130    ) -> Result<V::Value, Self::Error>
131    where
132        V: Visitor<'de>,
133    {
134        match self.de.next()? {
135            DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.de, e, fields)),
136            DeEvent::Text(e) => {
137                SimpleTypeDeserializer::from_text_content(e).deserialize_struct("", fields, visitor)
138            }
139            // SAFETY: the other events are filtered in `variant_seed()`
140            _ => unreachable!("Only `Start` or `Text` events are possible here"),
141        }
142    }
143}