Skip to content

Commit b96a7e9

Browse files
MingunJoseph Gilby
authored and
Joseph Gilby
committed
Fix tafia#500: deserialize top-level sequence correctly as if it is a field annotated with #[serde(rename = "$value")]
1 parent 7db34f5 commit b96a7e9

File tree

3 files changed

+34
-54
lines changed

3 files changed

+34
-54
lines changed

Changelog.md

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
In particular, that means that maps with numeric and numeric-like keys (for
1919
example, `"42"`) no longer can be serialized because [XML name] cannot start
2020
from a digit
21+
- [#500]: Fix deserialization of top-level sequences of enums, like
22+
```xml
23+
<?xml version="1.0" encoding="UTF-8"?>
24+
<!-- list of enum Enum { A, B, С } -->
25+
<A/>
26+
<B/>
27+
<C/>
28+
```
2129

2230
### Misc Changes
2331

@@ -44,6 +52,7 @@
4452
Refer to [documentation] for details.
4553

4654
[#490]: https://github.com/tafia/quick-xml/pull/490
55+
[#500]: https://github.com/tafia/quick-xml/issues/500
4756
[XML name]: https://www.w3.org/TR/xml11/#NT-Name
4857
[documentation]: https://docs.rs/quick-xml/0.27.0/quick_xml/de/index.html#difference-between-text-and-value-special-names
4958

src/de/seq.rs

+5-54
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,6 @@ where
7474
{
7575
/// Deserializer used to deserialize sequence items
7676
de: &'a mut Deserializer<'de, R>,
77-
/// Filter that determines whether a tag is a part of this sequence.
78-
///
79-
/// When feature `overlapped-lists` is not activated, iteration will stop
80-
/// when found a tag that does not pass this filter.
81-
///
82-
/// When feature `overlapped-lists` is activated, all tags, that not pass
83-
/// this check, will be skipped.
84-
filter: TagFilter<'de>,
85-
86-
/// Checkpoint after which all skipped events should be returned. All events,
87-
/// that was skipped before creating this checkpoint, will still stay buffered
88-
/// and will not be returned
89-
#[cfg(feature = "overlapped-lists")]
90-
checkpoint: usize,
9177
}
9278

9379
impl<'a, 'de, R> TopLevelSeqAccess<'de, 'a, R>
@@ -96,29 +82,7 @@ where
9682
{
9783
/// Creates a new accessor to a top-level sequence of XML elements.
9884
pub fn new(de: &'a mut Deserializer<'de, R>) -> Result<Self, DeError> {
99-
let filter = if let DeEvent::Start(e) = de.peek()? {
100-
// Clone is cheap if event borrows from the input
101-
TagFilter::Include(e.clone())
102-
} else {
103-
TagFilter::Exclude(&[])
104-
};
105-
Ok(Self {
106-
#[cfg(feature = "overlapped-lists")]
107-
checkpoint: de.skip_checkpoint(),
108-
109-
de,
110-
filter,
111-
})
112-
}
113-
}
114-
115-
#[cfg(feature = "overlapped-lists")]
116-
impl<'de, 'a, R> Drop for TopLevelSeqAccess<'de, 'a, R>
117-
where
118-
R: XmlRead<'de>,
119-
{
120-
fn drop(&mut self) {
121-
self.de.start_replay(self.checkpoint);
85+
Ok(Self { de })
12286
}
12387
}
12488

@@ -132,24 +96,11 @@ where
13296
where
13397
T: DeserializeSeed<'de>,
13498
{
135-
let decoder = self.de.reader.decoder();
136-
loop {
137-
break match self.de.peek()? {
138-
// If we see a tag that we not interested, skip it
139-
#[cfg(feature = "overlapped-lists")]
140-
DeEvent::Start(e) if !self.filter.is_suitable(e, decoder)? => {
141-
self.de.skip()?;
142-
continue;
143-
}
144-
// Stop iteration when list elements ends
145-
#[cfg(not(feature = "overlapped-lists"))]
146-
DeEvent::Start(e) if !self.filter.is_suitable(e, decoder)? => Ok(None),
147-
DeEvent::End(_) => Ok(None),
148-
DeEvent::Eof => Ok(None),
99+
match self.de.peek()? {
100+
DeEvent::Eof => Ok(None),
149101

150-
// Start(tag), Text, CData
151-
_ => seed.deserialize(&mut *self.de).map(Some),
152-
};
102+
// Start(tag), End(tag), Text, CData
103+
_ => seed.deserialize(&mut *self.de).map(Some),
153104
}
154105
}
155106
}

tests/serde-de.rs

+20
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,26 @@ mod seq {
609609
]
610610
);
611611
}
612+
613+
/// Test for https://github.com/tafia/quick-xml/issues/500
614+
#[test]
615+
fn list_of_enum() {
616+
#[derive(Debug, PartialEq, Deserialize)]
617+
enum Enum {
618+
One,
619+
Two,
620+
}
621+
622+
let data: Vec<Enum> = from_str(
623+
r#"
624+
<One/>
625+
<Two/>
626+
<One/>
627+
"#,
628+
)
629+
.unwrap();
630+
assert_eq!(data, vec![Enum::One, Enum::Two, Enum::One]);
631+
}
612632
}
613633

614634
/// Tests where each sequence item have an identical name in an XML.

0 commit comments

Comments
 (0)