Skip to content

Commit 86eeeea

Browse files
committed
Skip unwanted text events in sequences
If sequence expected only tags, skip any texts (CDATA included) If sequence expected any values, skip texts (CDATA included) if there is a dedicated "$text" field Fixed: serde-de-seq: fixed_name::variable_size::text_and_value variable_name::variable_size::text_and_value serde-issues: issue868
1 parent 87d4727 commit 86eeeea

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ XML specification. See the updated `custom_entities` example!
3535

3636
- [#868]: Allow to have both `$text` and `$value` special fields in one struct. Previously
3737
any text will be recognized as `$value` field even when `$text` field is also presented.
38+
- [#868]: Skip text events when deserialize a sequence of items overlapped with text (including CDATA).
3839

3940
### Misc Changes
4041

src/de/map.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ where
611611
_ => unreachable!(),
612612
}
613613
} else {
614-
TagFilter::Exclude(self.map.fields)
614+
TagFilter::Exclude(self.map.fields, self.map.has_text_field)
615615
};
616616
visitor.visit_seq(MapValueSeqAccess {
617617
#[cfg(feature = "overlapped-lists")]
@@ -852,15 +852,27 @@ enum TagFilter<'de> {
852852
Include(BytesStart<'de>), //TODO: Need to store only name instead of a whole tag
853853
/// A `SeqAccess` interested in tags with any name, except explicitly listed.
854854
/// Excluded tags are used as struct field names and therefore should not
855-
/// fall into a `$value` category
856-
Exclude(&'static [&'static str]),
855+
/// fall into a `$value` category.
856+
///
857+
/// The `bool` represents the having of a `$text` special field in fields array.
858+
/// It is used to exclude text events when `$text` fields is defined together with
859+
/// `$value` fieldб and `$value` accepts sequence.
860+
Exclude(&'static [&'static str], bool),
857861
}
858862

859863
impl<'de> TagFilter<'de> {
860864
fn is_suitable(&self, start: &BytesStart) -> Result<bool, DeError> {
861865
match self {
862866
Self::Include(n) => Ok(n.name() == start.name()),
863-
Self::Exclude(fields) => not_in(fields, start),
867+
Self::Exclude(fields, _) => not_in(fields, start),
868+
}
869+
}
870+
const fn need_skip_text(&self) -> bool {
871+
match self {
872+
// If we look only for tags, we should skip any $text keys
873+
Self::Include(_) => true,
874+
// If we look fo any data, we should exclude $text keys if it in the list
875+
Self::Exclude(_, has_text_field) => *has_text_field,
864876
}
865877
}
866878
}
@@ -944,9 +956,17 @@ where
944956
self.map.de.skip()?;
945957
continue;
946958
}
959+
// Skip any text events if sequence expects only specific tag names
960+
#[cfg(feature = "overlapped-lists")]
961+
DeEvent::Text(_) if self.filter.need_skip_text() => {
962+
self.map.de.skip()?;
963+
continue;
964+
}
947965
// Stop iteration when list elements ends
948966
#[cfg(not(feature = "overlapped-lists"))]
949967
DeEvent::Start(e) if !self.filter.is_suitable(e)? => Ok(None),
968+
#[cfg(not(feature = "overlapped-lists"))]
969+
DeEvent::Text(_) if self.filter.need_skip_text() => Ok(None),
950970

951971
// Stop iteration after reaching a closing tag
952972
// The matching tag name is guaranteed by the reader

0 commit comments

Comments
 (0)