1 | //! Contains Serde `Deserializer` for XML [simple types] [as defined] in the XML Schema.
|
2 | //!
|
3 | //! [simple types]: https://www.w3schools.com/xml/el_simpletype.asp
|
4 | //! [as defined]: https://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition
|
5 |
|
6 | use crate::de::{deserialize_bool, str2bool, Text};
|
7 | use crate::encoding::Decoder;
|
8 | use crate::errors::serialize::DeError;
|
9 | use crate::escape::unescape;
|
10 | use crate::utils::CowRef;
|
11 | use memchr::memchr;
|
12 | use serde::de::{DeserializeSeed, Deserializer, EnumAccess, SeqAccess, VariantAccess, Visitor};
|
13 | use serde::{self, serde_if_integer128};
|
14 | use std::borrow::Cow;
|
15 | use std::ops::Range;
|
16 |
|
17 | macro_rules! deserialize_num {
|
18 | ($method:ident, $visit:ident) => {
|
19 | fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
20 | where
|
21 | V: Visitor<'de>,
|
22 | {
|
23 | visitor.$visit(self.content.as_str().parse()?)
|
24 | }
|
25 | };
|
26 | ($method:ident => $visit:ident) => {
|
27 | fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
28 | where
|
29 | V: Visitor<'de>,
|
30 | {
|
31 | let string = self.decode()?;
|
32 | visitor.$visit(string.as_str().parse()?)
|
33 | }
|
34 | };
|
35 | }
|
36 |
|
37 | macro_rules! unsupported {
|
38 | (
|
39 | $deserialize:ident
|
40 | $(
|
41 | ($($type:ty),*)
|
42 | )?
|
43 | => $message:literal
|
44 | ) => {
|
45 | #[inline]
|
46 | fn $deserialize<V: Visitor<'de>>(
|
47 | self,
|
48 | $($(_: $type,)*)?
|
49 | _visitor: V
|
50 | ) -> Result<V::Value, Self::Error> {
|
51 | Err(DeError::Unsupported($message.into()))
|
52 | }
|
53 | };
|
54 | }
|
55 |
|
56 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
57 |
|
58 | /// A version of [`Cow`] that can borrow from two different buffers, one of them
|
59 | /// is a deserializer input, and conceptually contains only part of owned data.
|
60 | ///
|
61 | /// # Lifetimes
|
62 | /// - `'de` -- lifetime of the data that deserializer borrow from the parsed input
|
63 | /// - `'a` -- lifetime of the data that owned by a deserializer
|
64 | enum Content<'de, 'a> {
|
65 | /// An input borrowed from the parsed data
|
66 | Input(&'de str),
|
67 | /// An input borrowed from the buffer owned by another deserializer
|
68 | Slice(&'a str),
|
69 | /// An input taken from an external deserializer, owned by that deserializer.
|
70 | /// Only part of this data, located after offset represented by `usize`, used
|
71 | /// to deserialize data, the other is a garbage that can't be dropped because
|
72 | /// we do not want to make reallocations if they will not required.
|
73 | Owned(String, usize),
|
74 | }
|
75 | impl<'de, 'a> Content<'de, 'a> {
|
76 | /// Returns string representation of the content
|
77 | fn as_str(&self) -> &str {
|
78 | match self {
|
79 | Content::Input(s) => s,
|
80 | Content::Slice(s) => s,
|
81 | Content::Owned(s, offset) => s.split_at(*offset).1,
|
82 | }
|
83 | }
|
84 |
|
85 | /// Supply to the visitor a borrowed string, a string slice, or an owned
|
86 | /// string depending on the kind of input. Unlike [`Self::deserialize_item`],
|
87 | /// the whole [`Self::Owned`] string will be passed to the visitor.
|
88 | ///
|
89 | /// Calls
|
90 | /// - `visitor.visit_borrowed_str` if data borrowed from the input
|
91 | /// - `visitor.visit_str` if data borrowed from another source
|
92 | /// - `visitor.visit_string` if data owned by this type
|
93 | #[inline ]
|
94 | fn deserialize_all<V>(self, visitor: V) -> Result<V::Value, DeError>
|
95 | where
|
96 | V: Visitor<'de>,
|
97 | {
|
98 | match self {
|
99 | Content::Input(s) => visitor.visit_borrowed_str(s),
|
100 | Content::Slice(s) => visitor.visit_str(s),
|
101 | Content::Owned(s, _) => visitor.visit_string(s),
|
102 | }
|
103 | }
|
104 |
|
105 | /// Supply to the visitor a borrowed string, a string slice, or an owned
|
106 | /// string depending on the kind of input. Unlike [`Self::deserialize_all`],
|
107 | /// only part of [`Self::Owned`] string will be passed to the visitor.
|
108 | ///
|
109 | /// Calls
|
110 | /// - `visitor.visit_borrowed_str` if data borrowed from the input
|
111 | /// - `visitor.visit_str` if data borrowed from another source
|
112 | /// - `visitor.visit_string` if data owned by this type
|
113 | #[inline ]
|
114 | fn deserialize_item<V>(self, visitor: V) -> Result<V::Value, DeError>
|
115 | where
|
116 | V: Visitor<'de>,
|
117 | {
|
118 | match self {
|
119 | Content::Input(s) => visitor.visit_borrowed_str(s),
|
120 | Content::Slice(s) => visitor.visit_str(s),
|
121 | Content::Owned(s, 0) => visitor.visit_string(s),
|
122 | Content::Owned(s, offset) => visitor.visit_str(s.split_at(offset).1),
|
123 | }
|
124 | }
|
125 | }
|
126 |
|
127 | /// A deserializer that handles ordinary [simple type definition][item] with
|
128 | /// `{variety} = atomic`, or an ordinary [simple type] definition with
|
129 | /// `{variety} = union` whose basic members are all atomic.
|
130 | ///
|
131 | /// This deserializer can deserialize only primitive types:
|
132 | /// - numbers
|
133 | /// - booleans
|
134 | /// - strings
|
135 | /// - units
|
136 | /// - options
|
137 | /// - unit variants of enums
|
138 | ///
|
139 | /// Identifiers represented as strings and deserialized accordingly.
|
140 | ///
|
141 | /// Deserialization of all other types returns [`Unsupported`][DeError::Unsupported] error.
|
142 | ///
|
143 | /// The `Owned` variant of the content acts as a storage for data, allocated by
|
144 | /// an external deserializer that pass it via [`ListIter`].
|
145 | ///
|
146 | /// [item]: https://www.w3.org/TR/xmlschema11-1/#std-item_type_definition
|
147 | /// [simple type]: https://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition
|
148 | struct AtomicDeserializer<'de, 'a> {
|
149 | /// Content of the attribute value, text content or CDATA content
|
150 | content: Content<'de, 'a>,
|
151 | /// If `true`, `content` in an escaped form and should be unescaped before use
|
152 | escaped: bool,
|
153 | }
|
154 |
|
155 | impl<'de, 'a> Deserializer<'de> for AtomicDeserializer<'de, 'a> {
|
156 | type Error = DeError;
|
157 |
|
158 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
159 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
160 | where
|
161 | V: Visitor<'de>,
|
162 | {
|
163 | self.deserialize_str(visitor)
|
164 | }
|
165 |
|
166 | /// According to the <https://www.w3.org/TR/xmlschema11-2/#boolean>,
|
167 | /// valid boolean representations are only `"true"`, `"false"`, `"1"`,
|
168 | /// and `"0"`. But this method also handles following:
|
169 | ///
|
170 | /// |`bool` |XML content
|
171 | /// |-------|-------------------------------------------------------------
|
172 | /// |`true` |`"True"`, `"TRUE"`, `"t"`, `"Yes"`, `"YES"`, `"yes"`, `"y"`
|
173 | /// |`false`|`"False"`, `"FALSE"`, `"f"`, `"No"`, `"NO"`, `"no"`, `"n"`
|
174 | fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
175 | where
|
176 | V: Visitor<'de>,
|
177 | {
|
178 | str2bool(self.content.as_str(), visitor)
|
179 | }
|
180 |
|
181 | deserialize_num!(deserialize_i8, visit_i8);
|
182 | deserialize_num!(deserialize_i16, visit_i16);
|
183 | deserialize_num!(deserialize_i32, visit_i32);
|
184 | deserialize_num!(deserialize_i64, visit_i64);
|
185 |
|
186 | deserialize_num!(deserialize_u8, visit_u8);
|
187 | deserialize_num!(deserialize_u16, visit_u16);
|
188 | deserialize_num!(deserialize_u32, visit_u32);
|
189 | deserialize_num!(deserialize_u64, visit_u64);
|
190 |
|
191 | serde_if_integer128! {
|
192 | deserialize_num!(deserialize_i128, visit_i128);
|
193 | deserialize_num!(deserialize_u128, visit_u128);
|
194 | }
|
195 |
|
196 | deserialize_num!(deserialize_f32, visit_f32);
|
197 | deserialize_num!(deserialize_f64, visit_f64);
|
198 |
|
199 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
200 | fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
201 | where
|
202 | V: Visitor<'de>,
|
203 | {
|
204 | self.deserialize_str(visitor)
|
205 | }
|
206 |
|
207 | /// Supply to the visitor borrowed string, string slice, or owned string
|
208 | /// depending on the kind of input and presence of the escaped data.
|
209 | ///
|
210 | /// If string requires unescaping, then calls [`Visitor::visit_string`] with
|
211 | /// new allocated buffer with unescaped data.
|
212 | ///
|
213 | /// Otherwise calls
|
214 | /// - [`Visitor::visit_borrowed_str`] if data borrowed from the input
|
215 | /// - [`Visitor::visit_str`] if data borrowed from other deserializer
|
216 | /// - [`Visitor::visit_string`] if data owned by this deserializer
|
217 | fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
218 | where
|
219 | V: Visitor<'de>,
|
220 | {
|
221 | if self.escaped {
|
222 | match unescape(self.content.as_str())? {
|
223 | Cow::Borrowed(_) => self.content.deserialize_item(visitor),
|
224 | Cow::Owned(s) => visitor.visit_string(s),
|
225 | }
|
226 | } else {
|
227 | self.content.deserialize_item(visitor)
|
228 | }
|
229 | }
|
230 |
|
231 | fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
232 | where
|
233 | V: Visitor<'de>,
|
234 | {
|
235 | self.deserialize_str(visitor)
|
236 | }
|
237 |
|
238 | /// If `content` is an empty string then calls [`Visitor::visit_none`],
|
239 | /// otherwise calls [`Visitor::visit_some`] with itself
|
240 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
241 | where
|
242 | V: Visitor<'de>,
|
243 | {
|
244 | if self.content.as_str().is_empty() {
|
245 | visitor.visit_none()
|
246 | } else {
|
247 | visitor.visit_some(self)
|
248 | }
|
249 | }
|
250 |
|
251 | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
252 | where
|
253 | V: Visitor<'de>,
|
254 | {
|
255 | visitor.visit_unit()
|
256 | }
|
257 |
|
258 | /// Forwards deserialization to the [`Self::deserialize_unit`]
|
259 | fn deserialize_unit_struct<V>(
|
260 | self,
|
261 | _name: &'static str,
|
262 | visitor: V,
|
263 | ) -> Result<V::Value, Self::Error>
|
264 | where
|
265 | V: Visitor<'de>,
|
266 | {
|
267 | self.deserialize_unit(visitor)
|
268 | }
|
269 |
|
270 | fn deserialize_newtype_struct<V>(
|
271 | self,
|
272 | _name: &'static str,
|
273 | visitor: V,
|
274 | ) -> Result<V::Value, Self::Error>
|
275 | where
|
276 | V: Visitor<'de>,
|
277 | {
|
278 | visitor.visit_newtype_struct(self)
|
279 | }
|
280 |
|
281 | fn deserialize_enum<V>(
|
282 | self,
|
283 | _name: &'static str,
|
284 | _variants: &'static [&'static str],
|
285 | visitor: V,
|
286 | ) -> Result<V::Value, Self::Error>
|
287 | where
|
288 | V: Visitor<'de>,
|
289 | {
|
290 | visitor.visit_enum(self)
|
291 | }
|
292 |
|
293 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
294 | fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
295 | where
|
296 | V: Visitor<'de>,
|
297 | {
|
298 | self.deserialize_str(visitor)
|
299 | }
|
300 |
|
301 | fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
302 | where
|
303 | V: Visitor<'de>,
|
304 | {
|
305 | visitor.visit_unit()
|
306 | }
|
307 |
|
308 | unsupported!(deserialize_bytes => "byte arrays are not supported as `xs:list` items" );
|
309 | unsupported!(deserialize_byte_buf => "byte arrays are not supported as `xs:list` items" );
|
310 | unsupported!(deserialize_seq => "sequences are not supported as `xs:list` items" );
|
311 | unsupported!(deserialize_tuple(usize) => "tuples are not supported as `xs:list` items" );
|
312 | unsupported!(deserialize_tuple_struct(&'static str, usize) => "tuples are not supported as `xs:list` items" );
|
313 | unsupported!(deserialize_map => "maps are not supported as `xs:list` items" );
|
314 | unsupported!(deserialize_struct(&'static str, &'static [&'static str]) => "structures are not supported as `xs:list` items" );
|
315 | }
|
316 |
|
317 | impl<'de, 'a> EnumAccess<'de> for AtomicDeserializer<'de, 'a> {
|
318 | type Error = DeError;
|
319 | type Variant = AtomicUnitOnly;
|
320 |
|
321 | fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), DeError>
|
322 | where
|
323 | V: DeserializeSeed<'de>,
|
324 | {
|
325 | let name: >::Value = seed.deserialize(self)?;
|
326 | Ok((name, AtomicUnitOnly))
|
327 | }
|
328 | }
|
329 |
|
330 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
331 |
|
332 | /// Deserializer of variant data, that supports only unit variants.
|
333 | /// Attempt to deserialize newtype, tuple or struct variant will return a
|
334 | /// [`DeError::Unsupported`] error.
|
335 | pub struct AtomicUnitOnly;
|
336 | impl<'de> VariantAccess<'de> for AtomicUnitOnly {
|
337 | type Error = DeError;
|
338 |
|
339 | #[inline ]
|
340 | fn unit_variant(self) -> Result<(), DeError> {
|
341 | Ok(())
|
342 | }
|
343 |
|
344 | fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, DeError>
|
345 | where
|
346 | T: DeserializeSeed<'de>,
|
347 | {
|
348 | Err(DeError::Unsupported(
|
349 | "enum newtype variants are not supported as `xs:list` items" .into(),
|
350 | ))
|
351 | }
|
352 |
|
353 | fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, DeError>
|
354 | where
|
355 | V: Visitor<'de>,
|
356 | {
|
357 | Err(DeError::Unsupported(
|
358 | "enum tuple variants are not supported as `xs:list` items" .into(),
|
359 | ))
|
360 | }
|
361 |
|
362 | fn struct_variant<V>(
|
363 | self,
|
364 | _fields: &'static [&'static str],
|
365 | _visitor: V,
|
366 | ) -> Result<V::Value, DeError>
|
367 | where
|
368 | V: Visitor<'de>,
|
369 | {
|
370 | Err(DeError::Unsupported(
|
371 | "enum struct variants are not supported as `xs:list` items" .into(),
|
372 | ))
|
373 | }
|
374 | }
|
375 |
|
376 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
377 |
|
378 | /// Iterator over string sub-slices delimited by one or several spaces.
|
379 | /// Contains decoded value of the `simpleType`.
|
380 | /// Iteration ends when list contains `None`.
|
381 | struct ListIter<'de, 'a> {
|
382 | /// If `Some`, contains unconsumed data of the list
|
383 | content: Option<Content<'de, 'a>>,
|
384 | /// If `true`, `content` in escaped form and should be unescaped before use
|
385 | escaped: bool,
|
386 | }
|
387 | impl<'de, 'a> SeqAccess<'de> for ListIter<'de, 'a> {
|
388 | type Error = DeError;
|
389 |
|
390 | fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, DeError>
|
391 | where
|
392 | T: DeserializeSeed<'de>,
|
393 | {
|
394 | if let Some(mut content) = self.content.take() {
|
395 | const DELIMITER: u8 = b' ' ;
|
396 |
|
397 | loop {
|
398 | let string = content.as_str();
|
399 | if string.is_empty() {
|
400 | return Ok(None);
|
401 | }
|
402 | return match memchr(DELIMITER, string.as_bytes()) {
|
403 | // No delimiters in the `content`, deserialize it as a whole atomic
|
404 | None => seed.deserialize(AtomicDeserializer {
|
405 | content,
|
406 | escaped: self.escaped,
|
407 | }),
|
408 | // `content` started with a space, skip them all
|
409 | Some(0) => {
|
410 | // Skip all spaces
|
411 | let start = string.as_bytes().iter().position(|ch| *ch != DELIMITER);
|
412 | content = match (start, content) {
|
413 | // We cannot find any non-space character, so string contains only spaces
|
414 | (None, _) => return Ok(None),
|
415 | // Borrow result from input or deserializer depending on the initial borrowing
|
416 | (Some(start), Content::Input(s)) => Content::Input(s.split_at(start).1),
|
417 | (Some(start), Content::Slice(s)) => Content::Slice(s.split_at(start).1),
|
418 | // Skip additional bytes if we own data
|
419 | (Some(start), Content::Owned(s, skip)) => {
|
420 | Content::Owned(s, skip + start)
|
421 | }
|
422 | };
|
423 | continue;
|
424 | }
|
425 | // `content` started from an atomic
|
426 | Some(end) => match content {
|
427 | // Borrow for the next iteration from input or deserializer depending on
|
428 | // the initial borrowing
|
429 | Content::Input(s) => {
|
430 | let (item, rest) = s.split_at(end);
|
431 | self.content = Some(Content::Input(rest));
|
432 |
|
433 | seed.deserialize(AtomicDeserializer {
|
434 | content: Content::Input(item),
|
435 | escaped: self.escaped,
|
436 | })
|
437 | }
|
438 | Content::Slice(s) => {
|
439 | let (item, rest) = s.split_at(end);
|
440 | self.content = Some(Content::Slice(rest));
|
441 |
|
442 | seed.deserialize(AtomicDeserializer {
|
443 | content: Content::Slice(item),
|
444 | escaped: self.escaped,
|
445 | })
|
446 | }
|
447 | // Skip additional bytes if we own data for next iteration, but deserialize from
|
448 | // the borrowed data from our buffer
|
449 | Content::Owned(s, skip) => {
|
450 | let item = s.split_at(skip + end).0;
|
451 | let result = seed.deserialize(AtomicDeserializer {
|
452 | content: Content::Slice(item),
|
453 | escaped: self.escaped,
|
454 | });
|
455 |
|
456 | self.content = Some(Content::Owned(s, skip + end));
|
457 |
|
458 | result
|
459 | }
|
460 | },
|
461 | }
|
462 | .map(Some);
|
463 | }
|
464 | }
|
465 | Ok(None)
|
466 | }
|
467 | }
|
468 |
|
469 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
470 |
|
471 | /// A deserializer for an xml probably escaped and encoded value of XSD [simple types].
|
472 | /// This deserializer will borrow from the input as much as possible.
|
473 | ///
|
474 | /// `deserialize_any()` returns the whole string that deserializer contains.
|
475 | ///
|
476 | /// Escaping the value is actually not always necessary, for instance when
|
477 | /// converting to a float, we don't expect any escapable character anyway.
|
478 | /// In that cases deserializer skips unescaping step.
|
479 | ///
|
480 | /// Used for deserialize values from:
|
481 | /// - attribute values (`<... ...="value" ...>`)
|
482 | /// - mixed text / CDATA content (`<...>text<![CDATA[cdata]]></...>`)
|
483 | ///
|
484 | /// [simple types]: https://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition
|
485 | pub struct SimpleTypeDeserializer<'de, 'a> {
|
486 | /// - In case of attribute contains escaped attribute value
|
487 | /// - In case of text contains unescaped text value
|
488 | content: CowRef<'de, 'a, [u8]>,
|
489 | /// If `true`, `content` in escaped form and should be unescaped before use
|
490 | escaped: bool,
|
491 | /// Decoder used to deserialize string data, numeric and boolean data.
|
492 | /// Not used for deserializing raw byte buffers
|
493 | decoder: Decoder,
|
494 | }
|
495 |
|
496 | impl<'de, 'a> SimpleTypeDeserializer<'de, 'a> {
|
497 | /// Creates a deserializer from a value, that possible borrowed from input
|
498 | pub fn from_text_content(value: Text<'de>) -> Self {
|
499 | let content = match value.text {
|
500 | Cow::Borrowed(slice) => CowRef::Input(slice.as_bytes()),
|
501 | Cow::Owned(content) => CowRef::Owned(content.into_bytes()),
|
502 | };
|
503 | Self::new(content, false, Decoder::utf8())
|
504 | }
|
505 |
|
506 | /// Creates a deserializer from a part of value at specified range
|
507 | #[allow (clippy::ptr_arg)]
|
508 | pub fn from_part(
|
509 | value: &'a Cow<'de, [u8]>,
|
510 | range: Range<usize>,
|
511 | escaped: bool,
|
512 | decoder: Decoder,
|
513 | ) -> Self {
|
514 | let content = match value {
|
515 | Cow::Borrowed(slice) => CowRef::Input(&slice[range]),
|
516 | Cow::Owned(slice) => CowRef::Slice(&slice[range]),
|
517 | };
|
518 | Self::new(content, escaped, decoder)
|
519 | }
|
520 |
|
521 | /// Constructor for tests
|
522 | #[inline ]
|
523 | fn new(content: CowRef<'de, 'a, [u8]>, escaped: bool, decoder: Decoder) -> Self {
|
524 | Self {
|
525 | content,
|
526 | escaped,
|
527 | decoder,
|
528 | }
|
529 | }
|
530 |
|
531 | /// Decodes raw bytes using the encoding specified.
|
532 | /// The method will borrow if has the UTF-8 compatible representation.
|
533 | #[inline ]
|
534 | fn decode<'b>(&'b self) -> Result<Content<'de, 'b>, DeError> {
|
535 | Ok(match self.content {
|
536 | CowRef::Input(content) => match self.decoder.decode(content)? {
|
537 | Cow::Borrowed(content) => Content::Input(content),
|
538 | Cow::Owned(content) => Content::Owned(content, 0),
|
539 | },
|
540 | CowRef::Slice(content) => match self.decoder.decode(content)? {
|
541 | Cow::Borrowed(content) => Content::Slice(content),
|
542 | Cow::Owned(content) => Content::Owned(content, 0),
|
543 | },
|
544 | CowRef::Owned(ref content) => match self.decoder.decode(content)? {
|
545 | Cow::Borrowed(content) => Content::Slice(content),
|
546 | Cow::Owned(content) => Content::Owned(content, 0),
|
547 | },
|
548 | })
|
549 | }
|
550 | }
|
551 |
|
552 | impl<'de, 'a> Deserializer<'de> for SimpleTypeDeserializer<'de, 'a> {
|
553 | type Error = DeError;
|
554 |
|
555 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
556 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
557 | where
|
558 | V: Visitor<'de>,
|
559 | {
|
560 | self.deserialize_str(visitor)
|
561 | }
|
562 |
|
563 | fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
564 | where
|
565 | V: Visitor<'de>,
|
566 | {
|
567 | deserialize_bool(&self.content, self.decoder, visitor)
|
568 | }
|
569 |
|
570 | deserialize_num!(deserialize_i8 => visit_i8);
|
571 | deserialize_num!(deserialize_i16 => visit_i16);
|
572 | deserialize_num!(deserialize_i32 => visit_i32);
|
573 | deserialize_num!(deserialize_i64 => visit_i64);
|
574 |
|
575 | deserialize_num!(deserialize_u8 => visit_u8);
|
576 | deserialize_num!(deserialize_u16 => visit_u16);
|
577 | deserialize_num!(deserialize_u32 => visit_u32);
|
578 | deserialize_num!(deserialize_u64 => visit_u64);
|
579 |
|
580 | serde_if_integer128! {
|
581 | deserialize_num!(deserialize_i128 => visit_i128);
|
582 | deserialize_num!(deserialize_u128 => visit_u128);
|
583 | }
|
584 |
|
585 | deserialize_num!(deserialize_f32 => visit_f32);
|
586 | deserialize_num!(deserialize_f64 => visit_f64);
|
587 |
|
588 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
589 | fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
590 | where
|
591 | V: Visitor<'de>,
|
592 | {
|
593 | self.deserialize_str(visitor)
|
594 | }
|
595 |
|
596 | fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
597 | where
|
598 | V: Visitor<'de>,
|
599 | {
|
600 | let content = self.decode()?;
|
601 | if self.escaped {
|
602 | match unescape(content.as_str())? {
|
603 | Cow::Borrowed(_) => content.deserialize_all(visitor),
|
604 | Cow::Owned(s) => visitor.visit_string(s),
|
605 | }
|
606 | } else {
|
607 | content.deserialize_all(visitor)
|
608 | }
|
609 | }
|
610 |
|
611 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
612 | fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
613 | where
|
614 | V: Visitor<'de>,
|
615 | {
|
616 | self.deserialize_str(visitor)
|
617 | }
|
618 |
|
619 | /// Returns [`DeError::Unsupported`]
|
620 | fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
|
621 | where
|
622 | V: Visitor<'de>,
|
623 | {
|
624 | Err(DeError::Unsupported(
|
625 | "binary data content is not supported by XML format" .into(),
|
626 | ))
|
627 | }
|
628 |
|
629 | /// Forwards deserialization to the [`Self::deserialize_bytes`]
|
630 | fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
631 | where
|
632 | V: Visitor<'de>,
|
633 | {
|
634 | self.deserialize_bytes(visitor)
|
635 | }
|
636 |
|
637 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
638 | where
|
639 | V: Visitor<'de>,
|
640 | {
|
641 | if self.content.is_empty() {
|
642 | visitor.visit_none()
|
643 | } else {
|
644 | visitor.visit_some(self)
|
645 | }
|
646 | }
|
647 |
|
648 | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
649 | where
|
650 | V: Visitor<'de>,
|
651 | {
|
652 | visitor.visit_unit()
|
653 | }
|
654 |
|
655 | /// Forwards deserialization to the [`Self::deserialize_unit`]
|
656 | fn deserialize_unit_struct<V>(
|
657 | self,
|
658 | _name: &'static str,
|
659 | visitor: V,
|
660 | ) -> Result<V::Value, Self::Error>
|
661 | where
|
662 | V: Visitor<'de>,
|
663 | {
|
664 | self.deserialize_unit(visitor)
|
665 | }
|
666 |
|
667 | fn deserialize_newtype_struct<V>(
|
668 | self,
|
669 | _name: &'static str,
|
670 | visitor: V,
|
671 | ) -> Result<V::Value, Self::Error>
|
672 | where
|
673 | V: Visitor<'de>,
|
674 | {
|
675 | visitor.visit_newtype_struct(self)
|
676 | }
|
677 |
|
678 | fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
679 | where
|
680 | V: Visitor<'de>,
|
681 | {
|
682 | visitor.visit_seq(ListIter {
|
683 | content: Some(self.decode()?),
|
684 | escaped: self.escaped,
|
685 | })
|
686 | }
|
687 |
|
688 | /// Representation of tuples the same as [sequences][Self::deserialize_seq].
|
689 | fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
690 | where
|
691 | V: Visitor<'de>,
|
692 | {
|
693 | self.deserialize_seq(visitor)
|
694 | }
|
695 |
|
696 | /// Representation of named tuples the same as [unnamed tuples][Self::deserialize_tuple].
|
697 | fn deserialize_tuple_struct<V>(
|
698 | self,
|
699 | _name: &'static str,
|
700 | len: usize,
|
701 | visitor: V,
|
702 | ) -> Result<V::Value, DeError>
|
703 | where
|
704 | V: Visitor<'de>,
|
705 | {
|
706 | self.deserialize_tuple(len, visitor)
|
707 | }
|
708 |
|
709 | unsupported!(deserialize_map => "maps are not supported for XSD `simpleType`s" );
|
710 | unsupported!(deserialize_struct(&'static str, &'static [&'static str])
|
711 | => "structures are not supported for XSD `simpleType`s" );
|
712 |
|
713 | fn deserialize_enum<V>(
|
714 | self,
|
715 | _name: &'static str,
|
716 | _variants: &'static [&'static str],
|
717 | visitor: V,
|
718 | ) -> Result<V::Value, Self::Error>
|
719 | where
|
720 | V: Visitor<'de>,
|
721 | {
|
722 | visitor.visit_enum(self)
|
723 | }
|
724 |
|
725 | /// Forwards deserialization to the [`Self::deserialize_str`]
|
726 | fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
727 | where
|
728 | V: Visitor<'de>,
|
729 | {
|
730 | self.deserialize_str(visitor)
|
731 | }
|
732 |
|
733 | fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
734 | where
|
735 | V: Visitor<'de>,
|
736 | {
|
737 | visitor.visit_unit()
|
738 | }
|
739 | }
|
740 |
|
741 | impl<'de, 'a> EnumAccess<'de> for SimpleTypeDeserializer<'de, 'a> {
|
742 | type Error = DeError;
|
743 | type Variant = SimpleTypeUnitOnly;
|
744 |
|
745 | fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), DeError>
|
746 | where
|
747 | V: DeserializeSeed<'de>,
|
748 | {
|
749 | let name: >::Value = seed.deserialize(self)?;
|
750 | Ok((name, SimpleTypeUnitOnly))
|
751 | }
|
752 | }
|
753 |
|
754 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
755 |
|
756 | /// Deserializer of variant data, that supports only unit variants.
|
757 | /// Attempt to deserialize newtype, tuple or struct variant will return a
|
758 | /// [`DeError::Unsupported`] error.
|
759 | pub struct SimpleTypeUnitOnly;
|
760 | impl<'de> VariantAccess<'de> for SimpleTypeUnitOnly {
|
761 | type Error = DeError;
|
762 |
|
763 | #[inline ]
|
764 | fn unit_variant(self) -> Result<(), DeError> {
|
765 | Ok(())
|
766 | }
|
767 |
|
768 | fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, DeError>
|
769 | where
|
770 | T: DeserializeSeed<'de>,
|
771 | {
|
772 | Err(DeError::Unsupported(
|
773 | "enum newtype variants are not supported for XSD `simpleType`s" .into(),
|
774 | ))
|
775 | }
|
776 |
|
777 | fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, DeError>
|
778 | where
|
779 | V: Visitor<'de>,
|
780 | {
|
781 | Err(DeError::Unsupported(
|
782 | "enum tuple variants are not supported for XSD `simpleType`s" .into(),
|
783 | ))
|
784 | }
|
785 |
|
786 | fn struct_variant<V>(
|
787 | self,
|
788 | _fields: &'static [&'static str],
|
789 | _visitor: V,
|
790 | ) -> Result<V::Value, DeError>
|
791 | where
|
792 | V: Visitor<'de>,
|
793 | {
|
794 | Err(DeError::Unsupported(
|
795 | "enum struct variants are not supported for XSD `simpleType`s" .into(),
|
796 | ))
|
797 | }
|
798 | }
|
799 |
|
800 | ////////////////////////////////////////////////////////////////////////////////////////////////////
|
801 |
|
802 | #[cfg (test)]
|
803 | mod tests {
|
804 | use super::*;
|
805 | use crate::se::simple_type::{QuoteTarget, SimpleTypeSerializer};
|
806 | use crate::se::{Indent, QuoteLevel};
|
807 | use crate::utils::{ByteBuf, Bytes};
|
808 | use serde::de::IgnoredAny;
|
809 | use serde::{Deserialize, Serialize};
|
810 | use std::collections::HashMap;
|
811 |
|
812 | macro_rules! simple_only {
|
813 | ($encoding:ident, $name:ident: $type:ty = $xml:expr => $result:expr) => {
|
814 | #[test]
|
815 | fn $name() {
|
816 | let decoder = Decoder::$encoding();
|
817 | let xml = $xml;
|
818 | let de = SimpleTypeDeserializer::new(CowRef::Input(xml.as_ref()), true, decoder);
|
819 | let data: $type = Deserialize::deserialize(de).unwrap();
|
820 |
|
821 | assert_eq!(data, $result);
|
822 | }
|
823 | };
|
824 | }
|
825 |
|
826 | macro_rules! simple {
|
827 | ($encoding:ident, $name:ident: $type:ty = $xml:expr => $result:expr) => {
|
828 | #[test]
|
829 | fn $name() {
|
830 | let decoder = Decoder::$encoding();
|
831 | let xml = $xml;
|
832 | let de = SimpleTypeDeserializer::new(CowRef::Input(xml.as_ref()), true, decoder);
|
833 | let data: $type = Deserialize::deserialize(de).unwrap();
|
834 |
|
835 | assert_eq!(data, $result);
|
836 |
|
837 | // Roundtrip to ensure that serializer corresponds to deserializer
|
838 | assert_eq!(
|
839 | data.serialize(SimpleTypeSerializer {
|
840 | writer: String::new(),
|
841 | target: QuoteTarget::Text,
|
842 | level: QuoteLevel::Full,
|
843 | indent: Indent::None,
|
844 | })
|
845 | .unwrap(),
|
846 | xml
|
847 | );
|
848 | }
|
849 | };
|
850 | }
|
851 |
|
852 | macro_rules! err {
|
853 | ($encoding:ident, $name:ident: $type:ty = $xml:expr => $kind:ident($reason:literal)) => {
|
854 | #[test]
|
855 | fn $name() {
|
856 | let decoder = Decoder::$encoding();
|
857 | let xml = $xml;
|
858 | let de = SimpleTypeDeserializer::new(CowRef::Input(xml.as_ref()), true, decoder);
|
859 | let err = <$type as Deserialize>::deserialize(de).unwrap_err();
|
860 |
|
861 | match err {
|
862 | DeError::$kind(e) => assert_eq!(e, $reason),
|
863 | _ => panic!(
|
864 | "Expected `{}({})`, found `{:?}`" ,
|
865 | stringify!($kind),
|
866 | $reason,
|
867 | err
|
868 | ),
|
869 | }
|
870 | }
|
871 | };
|
872 | }
|
873 |
|
874 | #[derive (Debug, Deserialize, Serialize, PartialEq)]
|
875 | struct Unit;
|
876 |
|
877 | #[derive (Debug, Deserialize, Serialize, PartialEq)]
|
878 | struct Newtype(String);
|
879 |
|
880 | #[derive (Debug, Deserialize, Serialize, PartialEq)]
|
881 | struct BorrowedNewtype<'a>(&'a str);
|
882 |
|
883 | #[derive (Debug, Deserialize, Serialize, PartialEq)]
|
884 | struct Struct {
|
885 | key: String,
|
886 | val: usize,
|
887 | }
|
888 |
|
889 | #[derive (Debug, Deserialize, Serialize, PartialEq)]
|
890 | enum Enum {
|
891 | Unit,
|
892 | Newtype(String),
|
893 | Tuple(String, usize),
|
894 | Struct { key: String, val: usize },
|
895 | }
|
896 |
|
897 | #[derive (Debug, Deserialize, PartialEq)]
|
898 | #[serde(field_identifier)]
|
899 | enum Id {
|
900 | Field,
|
901 | }
|
902 |
|
903 | #[derive (Debug, Deserialize)]
|
904 | #[serde(transparent)]
|
905 | struct Any(IgnoredAny);
|
906 | impl PartialEq for Any {
|
907 | fn eq(&self, _other: &Any) -> bool {
|
908 | true
|
909 | }
|
910 | }
|
911 |
|
912 | /// Tests for deserialize atomic and union values, as defined in XSD specification
|
913 | mod atomic {
|
914 | use super::*;
|
915 | use crate::se::simple_type::AtomicSerializer;
|
916 | use pretty_assertions::assert_eq;
|
917 |
|
918 | /// Checks that given `$input` successfully deserializing into given `$result`
|
919 | macro_rules! deserialized_to_only {
|
920 | ($name:ident: $type:ty = $input:literal => $result:expr) => {
|
921 | #[test]
|
922 | fn $name() {
|
923 | let de = AtomicDeserializer {
|
924 | content: Content::Input($input),
|
925 | escaped: true,
|
926 | };
|
927 | let data: $type = Deserialize::deserialize(de).unwrap();
|
928 |
|
929 | assert_eq!(data, $result);
|
930 | }
|
931 | };
|
932 | }
|
933 |
|
934 | /// Checks that given `$input` successfully deserializing into given `$result`
|
935 | /// and the result is serialized back to the `$input`
|
936 | macro_rules! deserialized_to {
|
937 | ($name:ident: $type:ty = $input:literal => $result:expr) => {
|
938 | #[test]
|
939 | fn $name() {
|
940 | let de = AtomicDeserializer {
|
941 | content: Content::Input($input),
|
942 | escaped: true,
|
943 | };
|
944 | let data: $type = Deserialize::deserialize(de).unwrap();
|
945 |
|
946 | assert_eq!(data, $result);
|
947 |
|
948 | // Roundtrip to ensure that serializer corresponds to deserializer
|
949 | assert_eq!(
|
950 | data.serialize(AtomicSerializer {
|
951 | writer: String::new(),
|
952 | target: QuoteTarget::Text,
|
953 | level: QuoteLevel::Full,
|
954 | })
|
955 | .unwrap(),
|
956 | $input
|
957 | );
|
958 | }
|
959 | };
|
960 | }
|
961 |
|
962 | /// Checks that attempt to deserialize given `$input` as a `$type` results to a
|
963 | /// deserialization error `$kind` with `$reason`
|
964 | macro_rules! err {
|
965 | ($name:ident: $type:ty = $input:literal => $kind:ident($reason:literal)) => {
|
966 | #[test]
|
967 | fn $name() {
|
968 | let de = AtomicDeserializer {
|
969 | content: Content::Input($input),
|
970 | escaped: true,
|
971 | };
|
972 | let err = <$type as Deserialize>::deserialize(de).unwrap_err();
|
973 |
|
974 | match err {
|
975 | DeError::$kind(e) => assert_eq!(e, $reason),
|
976 | _ => panic!(
|
977 | "Expected `{}({})`, found `{:?}`" ,
|
978 | stringify!($kind),
|
979 | $reason,
|
980 | err
|
981 | ),
|
982 | }
|
983 | }
|
984 | };
|
985 | }
|
986 |
|
987 | deserialized_to!(false_: bool = "false" => false);
|
988 | deserialized_to!(true_: bool = "true" => true);
|
989 |
|
990 | deserialized_to!(i8_: i8 = "-2" => -2);
|
991 | deserialized_to!(i16_: i16 = "-2" => -2);
|
992 | deserialized_to!(i32_: i32 = "-2" => -2);
|
993 | deserialized_to!(i64_: i64 = "-2" => -2);
|
994 |
|
995 | deserialized_to!(u8_: u8 = "3" => 3);
|
996 | deserialized_to!(u16_: u16 = "3" => 3);
|
997 | deserialized_to!(u32_: u32 = "3" => 3);
|
998 | deserialized_to!(u64_: u64 = "3" => 3);
|
999 |
|
1000 | serde_if_integer128! {
|
1001 | deserialized_to!(i128_: i128 = "-2" => -2);
|
1002 | deserialized_to!(u128_: u128 = "2" => 2);
|
1003 | }
|
1004 |
|
1005 | deserialized_to!(f32_: f32 = "1.23" => 1.23);
|
1006 | deserialized_to!(f64_: f64 = "1.23" => 1.23);
|
1007 |
|
1008 | deserialized_to!(char_unescaped: char = "h" => 'h' );
|
1009 | deserialized_to!(char_escaped: char = "<" => '<' );
|
1010 |
|
1011 | deserialized_to!(string: String = "<escaped string" => "<escaped string" );
|
1012 | // Serializer will escape space. Because borrowing has meaning only for deserializer,
|
1013 | // no need to test roundtrip here, it is already tested with non-borrowing version
|
1014 | deserialized_to_only!(borrowed_str: &str = "non-escaped string" => "non-escaped string" );
|
1015 | err!(escaped_str: &str = "escaped string"
|
1016 | => Custom("invalid type: string \"escaped string \", expected a borrowed string" ));
|
1017 |
|
1018 | err!(byte_buf: ByteBuf = "<escaped string"
|
1019 | => Unsupported("byte arrays are not supported as `xs:list` items" ));
|
1020 | err!(borrowed_bytes: Bytes = "non-escaped string"
|
1021 | => Unsupported("byte arrays are not supported as `xs:list` items" ));
|
1022 |
|
1023 | deserialized_to!(option_none: Option<&str> = "" => None);
|
1024 | deserialized_to!(option_some: Option<&str> = "non-escaped-string" => Some("non-escaped-string" ));
|
1025 |
|
1026 | deserialized_to_only!(unit: () = "<root>anything</root>" => ());
|
1027 | deserialized_to_only!(unit_struct: Unit = "<root>anything</root>" => Unit);
|
1028 |
|
1029 | deserialized_to!(newtype_owned: Newtype = "<escaped string" => Newtype("<escaped string" .into()));
|
1030 | // Serializer will escape space. Because borrowing has meaning only for deserializer,
|
1031 | // no need to test roundtrip here, it is already tested with non-borrowing version
|
1032 | deserialized_to_only!(newtype_borrowed: BorrowedNewtype = "non-escaped string"
|
1033 | => BorrowedNewtype("non-escaped string" ));
|
1034 |
|
1035 | err!(seq: Vec<()> = "non-escaped string"
|
1036 | => Unsupported("sequences are not supported as `xs:list` items" ));
|
1037 | err!(tuple: ((), ()) = "non-escaped string"
|
1038 | => Unsupported("tuples are not supported as `xs:list` items" ));
|
1039 | err!(tuple_struct: ((), ()) = "non-escaped string"
|
1040 | => Unsupported("tuples are not supported as `xs:list` items" ));
|
1041 |
|
1042 | err!(map: HashMap<(), ()> = "non-escaped string"
|
1043 | => Unsupported("maps are not supported as `xs:list` items" ));
|
1044 | err!(struct_: Struct = "non-escaped string"
|
1045 | => Unsupported("structures are not supported as `xs:list` items" ));
|
1046 |
|
1047 | deserialized_to!(enum_unit: Enum = "Unit" => Enum::Unit);
|
1048 | err!(enum_newtype: Enum = "Newtype"
|
1049 | => Unsupported("enum newtype variants are not supported as `xs:list` items" ));
|
1050 | err!(enum_tuple: Enum = "Tuple"
|
1051 | => Unsupported("enum tuple variants are not supported as `xs:list` items" ));
|
1052 | err!(enum_struct: Enum = "Struct"
|
1053 | => Unsupported("enum struct variants are not supported as `xs:list` items" ));
|
1054 | err!(enum_other: Enum = "any data"
|
1055 | => Custom("unknown variant `any data`, expected one of `Unit`, `Newtype`, `Tuple`, `Struct`" ));
|
1056 |
|
1057 | deserialized_to_only!(identifier: Id = "Field" => Id::Field);
|
1058 | deserialized_to_only!(ignored_any: Any = "any data" => Any(IgnoredAny));
|
1059 |
|
1060 | /// Checks that deserialization from an owned content is working
|
1061 | #[test ]
|
1062 | #[cfg (feature = "encoding" )]
|
1063 | fn owned_data() {
|
1064 | let de = AtomicDeserializer {
|
1065 | content: Content::Owned("string slice" .into(), 7),
|
1066 | escaped: true,
|
1067 | };
|
1068 | assert_eq!(de.content.as_str(), "slice" );
|
1069 |
|
1070 | let data: String = Deserialize::deserialize(de).unwrap();
|
1071 | assert_eq!(data, "slice" );
|
1072 | }
|
1073 |
|
1074 | /// Checks that deserialization from a content borrowed from some
|
1075 | /// buffer other that input is working
|
1076 | #[test ]
|
1077 | fn borrowed_from_deserializer() {
|
1078 | let de = AtomicDeserializer {
|
1079 | content: Content::Slice("string slice" ),
|
1080 | escaped: true,
|
1081 | };
|
1082 | assert_eq!(de.content.as_str(), "string slice" );
|
1083 |
|
1084 | let data: String = Deserialize::deserialize(de).unwrap();
|
1085 | assert_eq!(data, "string slice" );
|
1086 | }
|
1087 | }
|
1088 |
|
1089 | /// Module for testing list accessor
|
1090 | mod list {
|
1091 | use super::*;
|
1092 | use pretty_assertions::assert_eq;
|
1093 |
|
1094 | #[test ]
|
1095 | fn empty() {
|
1096 | let mut seq = ListIter {
|
1097 | content: Some(Content::Input("" )),
|
1098 | escaped: true,
|
1099 | };
|
1100 |
|
1101 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1102 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1103 | }
|
1104 |
|
1105 | #[test ]
|
1106 | fn only_spaces() {
|
1107 | let mut seq = ListIter {
|
1108 | content: Some(Content::Input(" " )),
|
1109 | escaped: true,
|
1110 | };
|
1111 |
|
1112 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1113 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1114 | }
|
1115 |
|
1116 | #[test ]
|
1117 | fn one_item() {
|
1118 | let mut seq = ListIter {
|
1119 | content: Some(Content::Input("abc" )),
|
1120 | escaped: true,
|
1121 | };
|
1122 |
|
1123 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("abc" ));
|
1124 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1125 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1126 | }
|
1127 |
|
1128 | #[test ]
|
1129 | fn two_items() {
|
1130 | let mut seq = ListIter {
|
1131 | content: Some(Content::Input("abc def" )),
|
1132 | escaped: true,
|
1133 | };
|
1134 |
|
1135 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("abc" ));
|
1136 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("def" ));
|
1137 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1138 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1139 | }
|
1140 |
|
1141 | #[test ]
|
1142 | fn leading_spaces() {
|
1143 | let mut seq = ListIter {
|
1144 | content: Some(Content::Input(" def" )),
|
1145 | escaped: true,
|
1146 | };
|
1147 |
|
1148 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("def" ));
|
1149 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1150 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1151 | }
|
1152 |
|
1153 | #[test ]
|
1154 | fn trailing_spaces() {
|
1155 | let mut seq = ListIter {
|
1156 | content: Some(Content::Input("abc " )),
|
1157 | escaped: true,
|
1158 | };
|
1159 |
|
1160 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("abc" ));
|
1161 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1162 | assert_eq!(seq.next_element::<&str>().unwrap(), None);
|
1163 | }
|
1164 |
|
1165 | #[test ]
|
1166 | fn mixed_types() {
|
1167 | let mut seq = ListIter {
|
1168 | content: Some(Content::Input("string 1.23 42 true false h Unit" )),
|
1169 | escaped: true,
|
1170 | };
|
1171 |
|
1172 | assert_eq!(seq.next_element::<&str>().unwrap(), Some("string" ));
|
1173 | assert_eq!(seq.next_element::<f32>().unwrap(), Some(1.23));
|
1174 | assert_eq!(seq.next_element::<u32>().unwrap(), Some(42));
|
1175 | assert_eq!(seq.next_element::<bool>().unwrap(), Some(true));
|
1176 | assert_eq!(seq.next_element::<bool>().unwrap(), Some(false));
|
1177 | assert_eq!(seq.next_element::<char>().unwrap(), Some('h' ));
|
1178 | assert_eq!(seq.next_element::<Enum>().unwrap(), Some(Enum::Unit));
|
1179 | assert_eq!(seq.next_element::<()>().unwrap(), None);
|
1180 | assert_eq!(seq.next_element::<()>().unwrap(), None);
|
1181 | }
|
1182 | }
|
1183 |
|
1184 | mod utf8 {
|
1185 | use super::*;
|
1186 | use pretty_assertions::assert_eq;
|
1187 |
|
1188 | simple!(utf8, i8_: i8 = "-2" => -2);
|
1189 | simple!(utf8, i16_: i16 = "-2" => -2);
|
1190 | simple!(utf8, i32_: i32 = "-2" => -2);
|
1191 | simple!(utf8, i64_: i64 = "-2" => -2);
|
1192 |
|
1193 | simple!(utf8, u8_: u8 = "3" => 3);
|
1194 | simple!(utf8, u16_: u16 = "3" => 3);
|
1195 | simple!(utf8, u32_: u32 = "3" => 3);
|
1196 | simple!(utf8, u64_: u64 = "3" => 3);
|
1197 |
|
1198 | serde_if_integer128! {
|
1199 | simple!(utf8, i128_: i128 = "-2" => -2);
|
1200 | simple!(utf8, u128_: u128 = "2" => 2);
|
1201 | }
|
1202 |
|
1203 | simple!(utf8, f32_: f32 = "1.23" => 1.23);
|
1204 | simple!(utf8, f64_: f64 = "1.23" => 1.23);
|
1205 |
|
1206 | simple!(utf8, false_: bool = "false" => false);
|
1207 | simple!(utf8, true_: bool = "true" => true);
|
1208 | simple!(utf8, char_unescaped: char = "h" => 'h' );
|
1209 | simple!(utf8, char_escaped: char = "<" => '<' );
|
1210 |
|
1211 | simple!(utf8, string: String = "<escaped string" => "<escaped string" );
|
1212 | err!(utf8, byte_buf: ByteBuf = "<escaped string"
|
1213 | => Unsupported("binary data content is not supported by XML format" ));
|
1214 |
|
1215 | simple!(utf8, borrowed_str: &str = "non-escaped string" => "non-escaped string" );
|
1216 | err!(utf8, borrowed_bytes: Bytes = "<escaped string"
|
1217 | => Unsupported("binary data content is not supported by XML format" ));
|
1218 |
|
1219 | simple!(utf8, option_none: Option<&str> = "" => None);
|
1220 | simple!(utf8, option_some: Option<&str> = "non-escaped string" => Some("non-escaped string" ));
|
1221 |
|
1222 | simple_only!(utf8, unit: () = "any data" => ());
|
1223 | simple_only!(utf8, unit_struct: Unit = "any data" => Unit);
|
1224 |
|
1225 | // Serializer will not escape space because this is unnecessary.
|
1226 | // Because borrowing has meaning only for deserializer, no need to test
|
1227 | // roundtrip here, it is already tested for strings where compatible list
|
1228 | // of escaped characters is used
|
1229 | simple_only!(utf8, newtype_owned: Newtype = "<escaped string"
|
1230 | => Newtype("<escaped string" .into()));
|
1231 | simple_only!(utf8, newtype_borrowed: BorrowedNewtype = "non-escaped string"
|
1232 | => BorrowedNewtype("non-escaped string" ));
|
1233 |
|
1234 | err!(utf8, map: HashMap<(), ()> = "any data"
|
1235 | => Unsupported("maps are not supported for XSD `simpleType`s" ));
|
1236 | err!(utf8, struct_: Struct = "any data"
|
1237 | => Unsupported("structures are not supported for XSD `simpleType`s" ));
|
1238 |
|
1239 | simple!(utf8, enum_unit: Enum = "Unit" => Enum::Unit);
|
1240 | err!(utf8, enum_newtype: Enum = "Newtype"
|
1241 | => Unsupported("enum newtype variants are not supported for XSD `simpleType`s" ));
|
1242 | err!(utf8, enum_tuple: Enum = "Tuple"
|
1243 | => Unsupported("enum tuple variants are not supported for XSD `simpleType`s" ));
|
1244 | err!(utf8, enum_struct: Enum = "Struct"
|
1245 | => Unsupported("enum struct variants are not supported for XSD `simpleType`s" ));
|
1246 | err!(utf8, enum_other: Enum = "any data"
|
1247 | => Custom("unknown variant `any data`, expected one of `Unit`, `Newtype`, `Tuple`, `Struct`" ));
|
1248 |
|
1249 | simple_only!(utf8, identifier: Id = "Field" => Id::Field);
|
1250 | simple_only!(utf8, ignored_any: Any = "any data" => Any(IgnoredAny));
|
1251 | }
|
1252 |
|
1253 | #[cfg (feature = "encoding" )]
|
1254 | mod utf16 {
|
1255 | use super::*;
|
1256 | use pretty_assertions::assert_eq;
|
1257 |
|
1258 | fn to_utf16(string: &str) -> Vec<u8> {
|
1259 | let mut bytes = Vec::new();
|
1260 | for ch in string.encode_utf16() {
|
1261 | bytes.extend_from_slice(&ch.to_le_bytes());
|
1262 | }
|
1263 | bytes
|
1264 | }
|
1265 |
|
1266 | macro_rules! utf16 {
|
1267 | ($name:ident: $type:ty = $xml:literal => $result:expr) => {
|
1268 | simple_only!(utf16, $name: $type = to_utf16($xml) => $result);
|
1269 | };
|
1270 | }
|
1271 |
|
1272 | macro_rules! unsupported {
|
1273 | ($name:ident: $type:ty = $xml:literal => $err:literal) => {
|
1274 | err!(utf16, $name: $type = to_utf16($xml) => Unsupported($err));
|
1275 | };
|
1276 | }
|
1277 |
|
1278 | utf16!(i8_: i8 = "-2" => -2);
|
1279 | utf16!(i16_: i16 = "-2" => -2);
|
1280 | utf16!(i32_: i32 = "-2" => -2);
|
1281 | utf16!(i64_: i64 = "-2" => -2);
|
1282 |
|
1283 | utf16!(u8_: u8 = "3" => 3);
|
1284 | utf16!(u16_: u16 = "3" => 3);
|
1285 | utf16!(u32_: u32 = "3" => 3);
|
1286 | utf16!(u64_: u64 = "3" => 3);
|
1287 |
|
1288 | serde_if_integer128! {
|
1289 | utf16!(i128_: i128 = "-2" => -2);
|
1290 | utf16!(u128_: u128 = "2" => 2);
|
1291 | }
|
1292 |
|
1293 | utf16!(f32_: f32 = "1.23" => 1.23);
|
1294 | utf16!(f64_: f64 = "1.23" => 1.23);
|
1295 |
|
1296 | utf16!(false_: bool = "false" => false);
|
1297 | utf16!(true_: bool = "true" => true);
|
1298 | utf16!(char_unescaped: char = "h" => 'h' );
|
1299 | utf16!(char_escaped: char = "<" => '<' );
|
1300 |
|
1301 | utf16!(string: String = "<escaped string" => "<escaped string" );
|
1302 | unsupported!(borrowed_bytes: Bytes = "<escaped string"
|
1303 | => "binary data content is not supported by XML format" );
|
1304 |
|
1305 | utf16!(option_none: Option<()> = "" => None);
|
1306 | utf16!(option_some: Option<()> = "any data" => Some(()));
|
1307 |
|
1308 | utf16!(unit: () = "any data" => ());
|
1309 | utf16!(unit_struct: Unit = "any data" => Unit);
|
1310 |
|
1311 | utf16!(newtype_owned: Newtype = "<escaped string" => Newtype("<escaped string" .into()));
|
1312 |
|
1313 | // UTF-16 data never borrow because data was decoded not in-place
|
1314 | err!(utf16, newtype_borrowed: BorrowedNewtype = to_utf16("non-escaped string" )
|
1315 | => Custom("invalid type: string \"non-escaped string \", expected a borrowed string" ));
|
1316 |
|
1317 | unsupported!(map: HashMap<(), ()> = "any data"
|
1318 | => "maps are not supported for XSD `simpleType`s" );
|
1319 | unsupported!(struct_: Struct = "any data"
|
1320 | => "structures are not supported for XSD `simpleType`s" );
|
1321 |
|
1322 | utf16!(enum_unit: Enum = "Unit" => Enum::Unit);
|
1323 | unsupported!(enum_newtype: Enum = "Newtype"
|
1324 | => "enum newtype variants are not supported for XSD `simpleType`s" );
|
1325 | unsupported!(enum_tuple: Enum = "Tuple"
|
1326 | => "enum tuple variants are not supported for XSD `simpleType`s" );
|
1327 | unsupported!(enum_struct: Enum = "Struct"
|
1328 | => "enum struct variants are not supported for XSD `simpleType`s" );
|
1329 | err!(utf16, enum_other: Enum = to_utf16("any data" )
|
1330 | => Custom("unknown variant `any data`, expected one of `Unit`, `Newtype`, `Tuple`, `Struct`" ));
|
1331 |
|
1332 | utf16!(identifier: Id = "Field" => Id::Field);
|
1333 | utf16!(ignored_any: Any = "any data" => Any(IgnoredAny));
|
1334 | }
|
1335 | }
|
1336 | |