Skip to content

Commit b3ebf7a

Browse files
Mingundralley
authored andcommitted
Fix using incorrect deserializer when deserialize Option values in maps and structs
1 parent 38fa3bc commit b3ebf7a

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919

2020
- [#537]: Restore ability to deserialize attributes that represents XML namespace
2121
mappings (`xmlns:xxx`) that was broken since [#490]
22+
- [#510]: Fix an error of deserialization of `Option<T>` fields where `T` is some
23+
sequence type (for example, `Vec` or tuple)
2224

2325
### Misc Changes
2426

2527
[externally tagged]: https://serde.rs/enum-representations.html#externally-tagged
2628
[#490]: https://github.com/tafia/quick-xml/pull/490
29+
[#510]: https://github.com/tafia/quick-xml/issues/510
2730
[#537]: https://github.com/tafia/quick-xml/issues/537
2831
[#541]: https://github.com/tafia/quick-xml/pull/541
2932

src/de/map.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ where
480480

481481
deserialize_primitives!(mut);
482482

483-
forward!(deserialize_option);
484483
forward!(deserialize_unit);
485484
forward!(deserialize_unit_struct(name: &'static str));
486485
forward!(deserialize_newtype_struct(name: &'static str));
@@ -499,6 +498,13 @@ where
499498
forward!(deserialize_any);
500499
forward!(deserialize_ignored_any);
501500

501+
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, DeError>
502+
where
503+
V: Visitor<'de>,
504+
{
505+
deserialize_option!(self.map.de, self, visitor)
506+
}
507+
502508
/// Tuple representation is the same as [sequences](#method.deserialize_seq).
503509
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, DeError>
504510
where
@@ -758,7 +764,6 @@ where
758764

759765
deserialize_primitives!(mut);
760766

761-
forward!(deserialize_option);
762767
forward!(deserialize_unit);
763768
forward!(deserialize_unit_struct(name: &'static str));
764769
forward!(deserialize_newtype_struct(name: &'static str));
@@ -777,6 +782,13 @@ where
777782
forward!(deserialize_any);
778783
forward!(deserialize_ignored_any);
779784

785+
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, DeError>
786+
where
787+
V: Visitor<'de>,
788+
{
789+
deserialize_option!(self.map.de, self, visitor)
790+
}
791+
780792
/// Representation of tuples the same as [sequences](#method.deserialize_seq).
781793
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, DeError>
782794
where

src/de/mod.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,6 @@
912912
//! Use the [`Option`]. In that case inner array will always contains at least one
913913
//! element after deserialization:
914914
//! ```ignore
915-
//! // FIXME: #510,
916-
//! // UnexpectedEnd([97, 110, 121, 45, 116, 97, 103])
917915
//! # use pretty_assertions::assert_eq;
918916
//! # use serde::Deserialize;
919917
//! # type Item = ();
@@ -935,10 +933,6 @@
935933
//! # quick_xml::de::from_str(r#"<any-tag><item/><item/><item/></any-tag>"#).unwrap(),
936934
//! # );
937935
//! ```
938-
//! <div style="background:rgba(80, 240, 100, 0.20);padding:0.75em;">
939-
//!
940-
//! Currently not working. The bug is tracked in [#510].
941-
//! </div>
942936
//!
943937
//! See also [Frequently Used Patterns](#element-lists).
944938
//!
@@ -1728,7 +1722,6 @@
17281722
//! [`deserialize_with`]: https://serde.rs/field-attrs.html#deserialize_with
17291723
//! [#474]: https://github.com/tafia/quick-xml/issues/474
17301724
//! [#497]: https://github.com/tafia/quick-xml/issues/497
1731-
//! [#510]: https://github.com/tafia/quick-xml/issues/510
17321725
17331726
// Macros should be defined before the modules that using them
17341727
// Also, macros should be imported before using them
@@ -1832,6 +1825,17 @@ macro_rules! deserialize_primitives {
18321825
};
18331826
}
18341827

1828+
macro_rules! deserialize_option {
1829+
($de:expr, $deserializer:ident, $visitor:ident) => {
1830+
match $de.peek()? {
1831+
DeEvent::Text(t) if t.is_empty() => $visitor.visit_none(),
1832+
DeEvent::CData(t) if t.is_empty() => $visitor.visit_none(),
1833+
DeEvent::Eof => $visitor.visit_none(),
1834+
_ => $visitor.visit_some($deserializer),
1835+
}
1836+
};
1837+
}
1838+
18351839
mod key;
18361840
mod map;
18371841
mod simple_type;
@@ -2494,12 +2498,7 @@ where
24942498
where
24952499
V: Visitor<'de>,
24962500
{
2497-
match self.peek()? {
2498-
DeEvent::Text(t) if t.is_empty() => visitor.visit_none(),
2499-
DeEvent::CData(t) if t.is_empty() => visitor.visit_none(),
2500-
DeEvent::Eof => visitor.visit_none(),
2501-
_ => visitor.visit_some(self),
2502-
}
2501+
deserialize_option!(self, self, visitor)
25032502
}
25042503

25052504
/// Always call `visitor.visit_unit()` because returned value ignored in any case.

0 commit comments

Comments
 (0)