Skip to content

Commit a54f6c2

Browse files
Mingundralley
authored andcommitted
Merge module seq into module map because of it size
1 parent 9afa816 commit a54f6c2

File tree

3 files changed

+86
-84
lines changed

3 files changed

+86
-84
lines changed

src/de/map.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
33
use crate::{
44
de::key::QNameDeserializer,
5-
de::seq::{not_in, TagFilter},
65
de::simple_type::SimpleTypeDeserializer,
76
de::{str2bool, DeEvent, Deserializer, XmlRead, TEXT_KEY, VALUE_KEY},
7+
encoding::Decoder,
88
errors::serialize::DeError,
99
events::attributes::IterState,
1010
events::BytesStart,
@@ -144,6 +144,8 @@ enum ValueSource {
144144
Nested,
145145
}
146146

147+
////////////////////////////////////////////////////////////////////////////////////////////////////
148+
147149
/// A deserializer that extracts map-like structures from an XML. This deserializer
148150
/// represents a one XML tag:
149151
///
@@ -549,6 +551,72 @@ where
549551

550552
////////////////////////////////////////////////////////////////////////////////////////////////////
551553

554+
/// Check if tag `start` is included in the `fields` list. `decoder` is used to
555+
/// get a string representation of a tag.
556+
///
557+
/// Returns `true`, if `start` is not in the `fields` list and `false` otherwise.
558+
fn not_in(
559+
fields: &'static [&'static str],
560+
start: &BytesStart,
561+
decoder: Decoder,
562+
) -> Result<bool, DeError> {
563+
let tag = decoder.decode(start.name().into_inner())?;
564+
565+
Ok(fields.iter().all(|&field| field != tag.as_ref()))
566+
}
567+
568+
/// A filter that determines, what tags should form a sequence.
569+
///
570+
/// There are two types of sequences:
571+
/// - sequence where each element represented by tags with the same name
572+
/// - sequence where each element can have a different tag
573+
///
574+
/// The first variant could represent a collection of structs, the second --
575+
/// a collection of enum variants.
576+
///
577+
/// In the second case we don't know what tag name should be expected as a
578+
/// sequence element, so we accept any element. Since the sequence are flattened
579+
/// into maps, we skip elements which have dedicated fields in a struct by using an
580+
/// `Exclude` filter that filters out elements with names matching field names
581+
/// from the struct.
582+
///
583+
/// # Lifetimes
584+
///
585+
/// `'de` represents a lifetime of the XML input, when filter stores the
586+
/// dedicated tag name
587+
#[derive(Debug)]
588+
enum TagFilter<'de> {
589+
/// A `SeqAccess` interested only in tags with specified name to deserialize
590+
/// an XML like this:
591+
///
592+
/// ```xml
593+
/// <...>
594+
/// <tag/>
595+
/// <tag/>
596+
/// <tag/>
597+
/// ...
598+
/// </...>
599+
/// ```
600+
///
601+
/// The tag name is stored inside (`b"tag"` for that example)
602+
Include(BytesStart<'de>), //TODO: Need to store only name instead of a whole tag
603+
/// A `SeqAccess` interested in tags with any name, except explicitly listed.
604+
/// Excluded tags are used as struct field names and therefore should not
605+
/// fall into a `$value` category
606+
Exclude(&'static [&'static str]),
607+
}
608+
609+
impl<'de> TagFilter<'de> {
610+
fn is_suitable(&self, start: &BytesStart, decoder: Decoder) -> Result<bool, DeError> {
611+
match self {
612+
Self::Include(n) => Ok(n.name() == start.name()),
613+
Self::Exclude(fields) => not_in(fields, start, decoder),
614+
}
615+
}
616+
}
617+
618+
////////////////////////////////////////////////////////////////////////////////////////////////////
619+
552620
/// An accessor to sequence elements forming a value for struct field.
553621
/// Technically, this sequence is flattened out into structure and sequence
554622
/// elements are overlapped with other fields of a structure
@@ -750,3 +818,20 @@ where
750818
self.map.de.is_human_readable()
751819
}
752820
}
821+
822+
////////////////////////////////////////////////////////////////////////////////////////////////////
823+
824+
#[test]
825+
fn test_not_in() {
826+
let tag = BytesStart::new("tag");
827+
828+
assert_eq!(not_in(&[], &tag, Decoder::utf8()).unwrap(), true);
829+
assert_eq!(
830+
not_in(&["no", "such", "tags"], &tag, Decoder::utf8()).unwrap(),
831+
true
832+
);
833+
assert_eq!(
834+
not_in(&["some", "tag", "included"], &tag, Decoder::utf8()).unwrap(),
835+
false
836+
);
837+
}

src/de/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ macro_rules! deserialize_primitives {
333333
mod escape;
334334
mod key;
335335
mod map;
336-
mod seq;
337336
mod simple_type;
338337
mod var;
339338

src/de/seq.rs

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)