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