Skip to main content

oxixml_xml/de/
attributes.rs

1//! Implementation of the deserializer from attributes
2
3use std::borrow::Cow;
4
5use serde::de::{DeserializeSeed, Deserializer, Error, MapAccess, Visitor};
6use serde::forward_to_deserialize_any;
7
8use crate::XmlVersion;
9use crate::de::SimpleTypeDeserializer;
10use crate::de::key::QNameDeserializer;
11use crate::errors::serialize::DeError;
12use crate::events::attributes::Attributes;
13
14impl<'i> Attributes<'i> {
15    /// Converts this iterator into a serde's [`MapAccess`] trait to use with serde.
16    /// The returned object also implements the [`Deserializer`] trait.
17    ///
18    /// # Parameters
19    /// - `prefix`: a prefix of the field names in structs that should be stripped
20    ///   to get the local attribute name. The [`crate::de::Deserializer`] uses `"@"`
21    ///   as a prefix.
22    ///
23    /// # Example
24    /// ```
25    /// use oxixml_xml::events::BytesStart;
26    /// use oxixml_xml::XmlVersion;
27    /// use serde::Deserialize;
28    ///
29    /// #[derive(Debug, PartialEq, Deserialize)]
30    /// struct MyData<'i> {
31    ///     question: &'i str,
32    ///     answer: u32,
33    /// }
34    ///
35    /// #[derive(Debug, PartialEq, Deserialize)]
36    /// struct MyDataPrefixed<'i> {
37    ///     #[serde(rename = "@question")] question: &'i str,
38    ///     #[serde(rename = "@answer")]   answer: u32,
39    /// }
40    ///
41    /// let tag = BytesStart::from_content(
42    ///     "tag
43    ///         question = 'The Ultimate Question of Life, the Universe, and Everything'
44    ///         answer = '42'",
45    ///     3
46    /// );
47    /// // Strip nothing from the field names
48    /// let de = tag.attributes().clone().into_map_access(XmlVersion::Implicit1_0, "");
49    /// assert_eq!(
50    ///     MyData::deserialize(de).expect("should be Ok"),
51    ///     MyData {
52    ///         question: "The Ultimate Question of Life, the Universe, and Everything",
53    ///         answer: 42,
54    ///     }
55    /// );
56    ///
57    /// // Strip "@" from the field name
58    /// let de = tag.attributes().into_map_access(XmlVersion::Implicit1_0, "@");
59    /// assert_eq!(
60    ///     MyDataPrefixed::deserialize(de).expect("should be Ok"),
61    ///     MyDataPrefixed {
62    ///         question: "The Ultimate Question of Life, the Universe, and Everything",
63    ///         answer: 42,
64    ///     }
65    /// );
66    /// ```
67    #[inline]
68    pub const fn into_map_access(
69        self,
70        version: XmlVersion,
71        prefix: &'static str,
72    ) -> AttributesDeserializer<'i> {
73        AttributesDeserializer {
74            iter: self,
75            value: None,
76            prefix,
77            key_buf: String::new(),
78            version,
79        }
80    }
81}
82
83////////////////////////////////////////////////////////////////////////////////////////////////////
84
85/// A deserializer used to make possible to pack all attributes into a struct.
86/// It is created by [`Attributes::into_map_access`] method.
87///
88/// This deserializer always call [`Visitor::visit_map`] with self as [`MapAccess`].
89///
90/// # Lifetime
91///
92/// `'i` is a lifetime of the original buffer from which attributes were parsed.
93/// In particular, when reader was created from a string, this is lifetime of the
94/// string.
95#[derive(Debug, Clone)]
96pub struct AttributesDeserializer<'i> {
97    iter: Attributes<'i>,
98    /// The value of the attribute, read in last call to `next_key_seed`.
99    value: Option<Cow<'i, [u8]>>,
100    /// This prefix will be stripped from struct fields before match against attribute name.
101    prefix: &'static str,
102    /// Buffer to store attribute name as a field name exposed to serde consumers.
103    /// Kept in the deserializer to avoid many small allocations
104    key_buf: String,
105    version: XmlVersion,
106}
107
108impl<'de> Deserializer<'de> for AttributesDeserializer<'de> {
109    type Error = DeError;
110
111    #[inline]
112    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
113    where
114        V: Visitor<'de>,
115    {
116        visitor.visit_map(self)
117    }
118
119    forward_to_deserialize_any! {
120        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
121        bytes byte_buf option unit unit_struct newtype_struct seq tuple
122        tuple_struct map struct enum identifier ignored_any
123    }
124}
125
126impl<'de> MapAccess<'de> for AttributesDeserializer<'de> {
127    type Error = DeError;
128
129    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
130    where
131        K: DeserializeSeed<'de>,
132    {
133        debug_assert_eq!(self.value, None);
134
135        match self.iter.next() {
136            None => Ok(None),
137            Some(Ok(attr)) => {
138                self.value = Some(attr.value);
139                self.key_buf.clear();
140                self.key_buf.push_str(self.prefix);
141                let de =
142                    QNameDeserializer::from_attr(attr.key, self.iter.decoder(), &mut self.key_buf)?;
143                seed.deserialize(de).map(Some)
144            }
145            Some(Err(err)) => Err(Error::custom(err)),
146        }
147    }
148
149    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
150    where
151        V: DeserializeSeed<'de>,
152    {
153        match self.value.take() {
154            Some(value) => {
155                let de = SimpleTypeDeserializer::from_attr(
156                    &value,
157                    0..value.len(),
158                    self.version,
159                    self.iter.decoder(),
160                );
161                seed.deserialize(de)
162            }
163            None => Err(DeError::KeyNotRead),
164        }
165    }
166}