/rust/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.42.0/src/de/key.rs
Line | Count | Source |
1 | | use crate::de::simple_type::UnitOnly; |
2 | | use crate::errors::serialize::DeError; |
3 | | use crate::events::BytesStart; |
4 | | use crate::name::QName; |
5 | | use crate::utils::CowRef; |
6 | | use serde::de::{DeserializeSeed, Deserializer, EnumAccess, Visitor}; |
7 | | use serde::forward_to_deserialize_any; |
8 | | use std::borrow::Cow; |
9 | | |
10 | | macro_rules! deserialize_num { |
11 | | ($method:ident, $visit:ident) => { |
12 | 0 | fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
13 | 0 | where |
14 | 0 | V: Visitor<'de>, |
15 | | { |
16 | 0 | match self.name.parse() { |
17 | 0 | Ok(number) => visitor.$visit(number), |
18 | 0 | Err(_) => self.name.deserialize_str(visitor), |
19 | | } |
20 | 0 | } Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_i8::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_u8::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_f32::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_f64::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_i16::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_i32::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_i64::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_u16::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_u32::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_u64::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_i128::<_> Unexecuted instantiation: <quick_xml::de::key::QNameDeserializer as serde_core::de::Deserializer>::deserialize_u128::<_> |
21 | | }; |
22 | | } |
23 | | |
24 | | /// Extracts the local name from a qualified name as a string slice. |
25 | | #[inline] |
26 | 0 | fn local_name_str<'n>(name: QName<'n>) -> &'n str { |
27 | 0 | name.local_name().into_inner() |
28 | 0 | } |
29 | | |
30 | | /// A deserializer for xml names of elements and attributes. |
31 | | /// |
32 | | /// Used for deserializing values from: |
33 | | /// - attribute names (`<... name="..." ...>`) |
34 | | /// - element names (`<name>...</name>`) |
35 | | /// |
36 | | /// Converts a name to an identifier string using the following rules: |
37 | | /// |
38 | | /// - if it is an [`attribute`] name, put `@` in front of the identifier |
39 | | /// - if it is a namespace binding (`xmlns` or `xmlns:xxx`) put the decoded name |
40 | | /// to the identifier |
41 | | /// - if it is an attribute in the `xml` namespace, put the decoded name |
42 | | /// to the identifier |
43 | | /// - put the decoded [`local_name()`] of a name to the identifier |
44 | | /// |
45 | | /// The final identifier looks like `[@]local_name`, or `@xmlns`, or `@xmlns:binding` or |
46 | | /// `xml:attribute` (where `[]` means optional element). |
47 | | /// |
48 | | /// The deserializer also supports deserializing names as other primitive types: |
49 | | /// - numbers |
50 | | /// - booleans |
51 | | /// - unit (`()`) and unit structs |
52 | | /// - unit variants of the enumerations |
53 | | /// |
54 | | /// Because `serde` does not define on which side type conversion should be |
55 | | /// performed, and because [`Deserialize`] implementation for that primitives |
56 | | /// in serde does not accept strings, the deserializer will perform conversion |
57 | | /// by itself. |
58 | | /// |
59 | | /// The deserializer is able to deserialize unit and unit structs, but any name |
60 | | /// will be converted to the same unit instance. This is asymmetry with a serializer, |
61 | | /// which not able to serialize those types, because empty names are impossible |
62 | | /// in XML. |
63 | | /// |
64 | | /// `deserialize_any()` returns the same result as `deserialize_identifier()`. |
65 | | /// |
66 | | /// # Lifetimes |
67 | | /// |
68 | | /// - `'i`: lifetime of the data that the deserializer borrows from the parsed input |
69 | | /// - `'d`: lifetime of a deserializer that holds a buffer with content of events |
70 | | /// |
71 | | /// [`attribute`]: Self::from_attr |
72 | | /// [`local_name()`]: QName::local_name |
73 | | /// [`Deserialize`]: serde::Deserialize |
74 | | pub struct QNameDeserializer<'i, 'd> { |
75 | | name: CowRef<'i, 'd, str>, |
76 | | } |
77 | | |
78 | | impl<'i, 'd> QNameDeserializer<'i, 'd> { |
79 | | /// Creates deserializer from name of an attribute |
80 | 0 | pub fn from_attr(name: QName<'d>, key_buf: &'d mut String) -> Result<Self, DeError> { |
81 | | // https://github.com/tafia/quick-xml/issues/537 |
82 | | // Namespace bindings (xmlns:xxx) map to `@xmlns:xxx` instead of `@xxx` |
83 | 0 | if name.as_namespace_binding().is_some() { |
84 | 0 | key_buf.push_str(name.as_ref()); |
85 | 0 | } else { |
86 | | // https://github.com/tafia/quick-xml/issues/841 |
87 | | // we also want to map to the full name for `xml:xxx`, because `xml:xxx` attributes |
88 | | // can apper only in this literal form, as `xml` prefix cannot be redeclared or unbound |
89 | 0 | let (local, prefix_opt) = name.decompose(); |
90 | 0 | if prefix_opt.map_or(false, |prefix| prefix.is_xml()) { |
91 | 0 | key_buf.push_str(name.as_ref()); |
92 | 0 | } else { |
93 | 0 | key_buf.push_str(local.as_ref()); |
94 | 0 | } |
95 | | }; |
96 | | |
97 | 0 | Ok(Self { |
98 | 0 | name: CowRef::Slice(key_buf), |
99 | 0 | }) |
100 | 0 | } |
101 | | |
102 | | /// Creates deserializer from name of an element |
103 | 0 | pub fn from_elem(start: &'d BytesStart<'i>) -> Result<Self, DeError> { |
104 | 0 | let local = match start.buf { |
105 | 0 | Cow::Borrowed(b) => CowRef::Input(local_name_str(QName(&b[..start.name_len]))), |
106 | 0 | Cow::Owned(ref o) => CowRef::Slice(local_name_str(QName(&o[..start.name_len]))), |
107 | | }; |
108 | | |
109 | 0 | Ok(Self { name: local }) |
110 | 0 | } |
111 | | } |
112 | | |
113 | | impl<'de, 'd> Deserializer<'de> for QNameDeserializer<'de, 'd> { |
114 | | type Error = DeError; |
115 | | |
116 | | forward_to_deserialize_any! { |
117 | | char str string |
118 | | bytes byte_buf |
119 | | seq tuple tuple_struct |
120 | | map struct |
121 | | ignored_any |
122 | | } |
123 | | |
124 | | /// According to the <https://www.w3.org/TR/xmlschema11-2/#boolean>, |
125 | | /// valid boolean representations are only `"true"`, `"false"`, `"1"`, |
126 | | /// and `"0"`. |
127 | 0 | fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
128 | 0 | where |
129 | 0 | V: Visitor<'de>, |
130 | | { |
131 | 0 | self.name.deserialize_bool(visitor) |
132 | 0 | } |
133 | | |
134 | | deserialize_num!(deserialize_i8, visit_i8); |
135 | | deserialize_num!(deserialize_i16, visit_i16); |
136 | | deserialize_num!(deserialize_i32, visit_i32); |
137 | | deserialize_num!(deserialize_i64, visit_i64); |
138 | | |
139 | | deserialize_num!(deserialize_u8, visit_u8); |
140 | | deserialize_num!(deserialize_u16, visit_u16); |
141 | | deserialize_num!(deserialize_u32, visit_u32); |
142 | | deserialize_num!(deserialize_u64, visit_u64); |
143 | | |
144 | | deserialize_num!(deserialize_i128, visit_i128); |
145 | | deserialize_num!(deserialize_u128, visit_u128); |
146 | | |
147 | | deserialize_num!(deserialize_f32, visit_f32); |
148 | | deserialize_num!(deserialize_f64, visit_f64); |
149 | | |
150 | | /// Calls [`Visitor::visit_unit`] |
151 | 0 | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
152 | 0 | where |
153 | 0 | V: Visitor<'de>, |
154 | | { |
155 | 0 | visitor.visit_unit() |
156 | 0 | } |
157 | | |
158 | | /// Forwards deserialization to the [`Self::deserialize_unit`] |
159 | 0 | fn deserialize_unit_struct<V>( |
160 | 0 | self, |
161 | 0 | _name: &'static str, |
162 | 0 | visitor: V, |
163 | 0 | ) -> Result<V::Value, Self::Error> |
164 | 0 | where |
165 | 0 | V: Visitor<'de>, |
166 | | { |
167 | 0 | self.deserialize_unit(visitor) |
168 | 0 | } |
169 | | |
170 | | /// Forwards deserialization to the [`Self::deserialize_identifier`] |
171 | | #[inline] |
172 | 0 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
173 | 0 | where |
174 | 0 | V: Visitor<'de>, |
175 | | { |
176 | 0 | self.deserialize_identifier(visitor) |
177 | 0 | } |
178 | | |
179 | | /// If `name` is an empty string then calls [`Visitor::visit_none`], |
180 | | /// otherwise calls [`Visitor::visit_some`] with itself |
181 | 0 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
182 | 0 | where |
183 | 0 | V: Visitor<'de>, |
184 | | { |
185 | 0 | if self.name.is_empty() { |
186 | 0 | visitor.visit_none() |
187 | | } else { |
188 | 0 | visitor.visit_some(self) |
189 | | } |
190 | 0 | } |
191 | | |
192 | 0 | fn deserialize_newtype_struct<V>( |
193 | 0 | self, |
194 | 0 | _name: &'static str, |
195 | 0 | visitor: V, |
196 | 0 | ) -> Result<V::Value, Self::Error> |
197 | 0 | where |
198 | 0 | V: Visitor<'de>, |
199 | | { |
200 | 0 | visitor.visit_newtype_struct(self) |
201 | 0 | } |
202 | | |
203 | | /// Calls a [`Visitor::visit_str`] if [`name`] contains only UTF-8 |
204 | | /// compatible encoded characters and represents an element name and |
205 | | /// a [`Visitor::visit_string`] in all other cases. |
206 | | /// |
207 | | /// [`name`]: Self::name |
208 | 0 | fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
209 | 0 | where |
210 | 0 | V: Visitor<'de>, |
211 | | { |
212 | 0 | match self.name { |
213 | 0 | CowRef::Input(name) => visitor.visit_borrowed_str(name), |
214 | 0 | CowRef::Slice(name) => visitor.visit_str(name), |
215 | 0 | CowRef::Owned(name) => visitor.visit_string(name), |
216 | | } |
217 | 0 | } |
218 | | |
219 | 0 | fn deserialize_enum<V>( |
220 | 0 | self, |
221 | 0 | _name: &str, |
222 | 0 | _variants: &'static [&'static str], |
223 | 0 | visitor: V, |
224 | 0 | ) -> Result<V::Value, Self::Error> |
225 | 0 | where |
226 | 0 | V: Visitor<'de>, |
227 | | { |
228 | 0 | visitor.visit_enum(self) |
229 | 0 | } |
230 | | } |
231 | | |
232 | | impl<'de, 'd> EnumAccess<'de> for QNameDeserializer<'de, 'd> { |
233 | | type Error = DeError; |
234 | | type Variant = UnitOnly; |
235 | | |
236 | 0 | fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> |
237 | 0 | where |
238 | 0 | V: DeserializeSeed<'de>, |
239 | | { |
240 | 0 | let name = seed.deserialize(self)?; |
241 | 0 | Ok((name, UnitOnly)) |
242 | 0 | } |
243 | | } |
244 | | |
245 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
246 | | |
247 | | #[cfg(test)] |
248 | | mod tests { |
249 | | use super::*; |
250 | | use crate::se::key::QNameSerializer; |
251 | | use crate::utils::{ByteBuf, Bytes}; |
252 | | use pretty_assertions::assert_eq; |
253 | | use serde::de::IgnoredAny; |
254 | | use serde::{Deserialize, Serialize}; |
255 | | use std::collections::HashMap; |
256 | | |
257 | | #[derive(Debug, Deserialize, Serialize, PartialEq)] |
258 | | struct Unit; |
259 | | |
260 | | #[derive(Debug, Deserialize, Serialize, PartialEq)] |
261 | | struct Newtype(String); |
262 | | |
263 | | #[derive(Debug, Deserialize, Serialize, PartialEq)] |
264 | | struct Tuple((), ()); |
265 | | |
266 | | #[derive(Debug, Deserialize, Serialize, PartialEq)] |
267 | | struct Struct { |
268 | | key: String, |
269 | | val: usize, |
270 | | } |
271 | | |
272 | | #[derive(Debug, Deserialize, Serialize, PartialEq)] |
273 | | enum Enum { |
274 | | Unit, |
275 | | #[serde(rename = "@Attr")] |
276 | | Attr, |
277 | | Newtype(String), |
278 | | Tuple(String, usize), |
279 | | Struct { |
280 | | key: String, |
281 | | val: usize, |
282 | | }, |
283 | | } |
284 | | |
285 | | #[derive(Debug, Deserialize, PartialEq)] |
286 | | #[serde(field_identifier)] |
287 | | enum Id { |
288 | | Field, |
289 | | } |
290 | | |
291 | | #[derive(Debug, Deserialize)] |
292 | | #[serde(transparent)] |
293 | | struct Any(IgnoredAny); |
294 | | impl PartialEq for Any { |
295 | | fn eq(&self, _other: &Any) -> bool { |
296 | | true |
297 | | } |
298 | | } |
299 | | |
300 | | /// Checks that given `$input` successfully deserializing into given `$result` |
301 | | macro_rules! deserialized_to_only { |
302 | | ($name:ident: $type:ty = $input:literal => $result:expr) => { |
303 | | #[test] |
304 | | fn $name() { |
305 | | let de = QNameDeserializer { |
306 | | name: CowRef::Input($input), |
307 | | }; |
308 | | let data: $type = Deserialize::deserialize(de).unwrap(); |
309 | | |
310 | | assert_eq!(data, $result); |
311 | | } |
312 | | }; |
313 | | } |
314 | | |
315 | | /// Checks that given `$input` successfully deserializing into given `$result` |
316 | | macro_rules! deserialized_to { |
317 | | ($name:ident: $type:ty = $input:literal => $result:expr) => { |
318 | | #[test] |
319 | | fn $name() { |
320 | | let de = QNameDeserializer { |
321 | | name: CowRef::Input($input), |
322 | | }; |
323 | | let data: $type = Deserialize::deserialize(de).unwrap(); |
324 | | |
325 | | assert_eq!(data, $result); |
326 | | |
327 | | // Roundtrip to ensure that serializer corresponds to deserializer |
328 | | assert_eq!( |
329 | | data.serialize(QNameSerializer { |
330 | | writer: String::new() |
331 | | }) |
332 | | .unwrap(), |
333 | | $input |
334 | | ); |
335 | | } |
336 | | }; |
337 | | } |
338 | | |
339 | | /// Checks that attempt to deserialize given `$input` as a `$type` results to a |
340 | | /// deserialization error `$kind` with `$reason` |
341 | | macro_rules! err { |
342 | | ($name:ident: $type:ty = $input:literal => $kind:ident($reason:literal)) => { |
343 | | #[test] |
344 | | fn $name() { |
345 | | let de = QNameDeserializer { |
346 | | name: CowRef::Input($input), |
347 | | }; |
348 | | let err = <$type as Deserialize>::deserialize(de).unwrap_err(); |
349 | | |
350 | | match err { |
351 | | DeError::$kind(e) => assert_eq!(e, $reason), |
352 | | _ => panic!( |
353 | | "Expected `Err({}({}))`, but got `{:?}`", |
354 | | stringify!($kind), |
355 | | $reason, |
356 | | err |
357 | | ), |
358 | | } |
359 | | } |
360 | | }; |
361 | | } |
362 | | |
363 | | deserialized_to!(false_: bool = "false" => false); |
364 | | deserialized_to!(true_: bool = "true" => true); |
365 | | |
366 | | deserialized_to!(i8_: i8 = "-2" => -2); |
367 | | deserialized_to!(i16_: i16 = "-2" => -2); |
368 | | deserialized_to!(i32_: i32 = "-2" => -2); |
369 | | deserialized_to!(i64_: i64 = "-2" => -2); |
370 | | |
371 | | deserialized_to!(u8_: u8 = "3" => 3); |
372 | | deserialized_to!(u16_: u16 = "3" => 3); |
373 | | deserialized_to!(u32_: u32 = "3" => 3); |
374 | | deserialized_to!(u64_: u64 = "3" => 3); |
375 | | |
376 | | deserialized_to!(i128_: i128 = "-2" => -2); |
377 | | deserialized_to!(u128_: u128 = "2" => 2); |
378 | | |
379 | | deserialized_to!(f32_: f32 = "1.23" => 1.23); |
380 | | deserialized_to!(f64_: f64 = "1.23" => 1.23); |
381 | | |
382 | | deserialized_to!(char_unescaped: char = "h" => 'h'); |
383 | | err!(char_escaped: char = "<" |
384 | | => Custom("invalid value: string \"<\", expected a character")); |
385 | | |
386 | | deserialized_to!(string: String = "<escaped string" => "<escaped string"); |
387 | | deserialized_to!(borrowed_str: &str = "name" => "name"); |
388 | | |
389 | | err!(byte_buf: ByteBuf = "<escaped string" |
390 | | => Custom("invalid type: string \"<escaped string\", expected byte data")); |
391 | | err!(borrowed_bytes: Bytes = "name" |
392 | | => Custom("invalid type: string \"name\", expected borrowed bytes")); |
393 | | |
394 | | deserialized_to!(option_none: Option<String> = "" => None); |
395 | | deserialized_to!(option_some: Option<String> = "name" => Some("name".into())); |
396 | | |
397 | | // Unit structs cannot be represented in some meaningful way, but it meaningful |
398 | | // to use them as a placeholder when we want to deserialize _something_ |
399 | | deserialized_to_only!(unit: () = "anything" => ()); |
400 | | deserialized_to_only!(unit_struct: Unit = "anything" => Unit); |
401 | | |
402 | | deserialized_to!(newtype: Newtype = "<escaped string" => Newtype("<escaped string".into())); |
403 | | |
404 | | err!(seq: Vec<()> = "name" |
405 | | => Custom("invalid type: string \"name\", expected a sequence")); |
406 | | err!(tuple: ((), ()) = "name" |
407 | | => Custom("invalid type: string \"name\", expected a tuple of size 2")); |
408 | | err!(tuple_struct: Tuple = "name" |
409 | | => Custom("invalid type: string \"name\", expected tuple struct Tuple")); |
410 | | |
411 | | err!(map: HashMap<(), ()> = "name" |
412 | | => Custom("invalid type: string \"name\", expected a map")); |
413 | | err!(struct_: Struct = "name" |
414 | | => Custom("invalid type: string \"name\", expected struct Struct")); |
415 | | |
416 | | deserialized_to!(enum_unit: Enum = "Unit" => Enum::Unit); |
417 | | deserialized_to!(enum_unit_for_attr: Enum = "@Attr" => Enum::Attr); |
418 | | err!(enum_newtype: Enum = "Newtype" |
419 | | => Custom("invalid type: unit value, expected a string")); |
420 | | err!(enum_tuple: Enum = "Tuple" |
421 | | => Custom("invalid type: unit value, expected tuple variant Enum::Tuple")); |
422 | | err!(enum_struct: Enum = "Struct" |
423 | | => Custom("invalid type: unit value, expected struct variant Enum::Struct")); |
424 | | |
425 | | // Field identifiers cannot be serialized, and IgnoredAny represented _something_ |
426 | | // which is not concrete |
427 | | deserialized_to_only!(identifier: Id = "Field" => Id::Field); |
428 | | deserialized_to_only!(ignored_any: Any = "any-name" => Any(IgnoredAny)); |
429 | | } |