From 4e04fe247c51e7bb206b61b5bcc9c9bef29e4230 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 18 Dec 2022 14:08:12 +0500 Subject: [PATCH 1/2] Group Deserializer definition and Deserializer impl blocks --- src/de/mod.rs | 74 ++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index b9ca4ae0..75e6afe2 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -2066,42 +2066,6 @@ impl<'i, R: XmlRead<'i>> XmlReader<'i, R> { //////////////////////////////////////////////////////////////////////////////////////////////////// -/// A structure that deserializes XML into Rust values. -pub struct Deserializer<'de, R> -where - R: XmlRead<'de>, -{ - /// An XML reader that streams events into this deserializer - reader: XmlReader<'de, R>, - - /// When deserializing sequences sometimes we have to skip unwanted events. - /// That events should be stored and then replayed. This is a replay buffer, - /// that streams events while not empty. When it exhausted, events will - /// requested from [`Self::reader`]. - #[cfg(feature = "overlapped-lists")] - read: VecDeque>, - /// When deserializing sequences sometimes we have to skip events, because XML - /// is tolerant to elements order and even if in the XSD order is strictly - /// specified (using `xs:sequence`) most of XML parsers allows order violations. - /// That means, that elements, forming a sequence, could be overlapped with - /// other elements, do not related to that sequence. - /// - /// In order to support this, deserializer will scan events and skip unwanted - /// events, store them here. After call [`Self::start_replay()`] all events - /// moved from this to [`Self::read`]. - #[cfg(feature = "overlapped-lists")] - write: VecDeque>, - /// Maximum number of events that can be skipped when processing sequences - /// that occur out-of-order. This field is used to prevent potential - /// denial-of-service (DoS) attacks which could cause infinite memory - /// consumption when parsing a very large amount of XML into a sequence field. - #[cfg(feature = "overlapped-lists")] - limit: Option, - - #[cfg(not(feature = "overlapped-lists"))] - peek: Option>, -} - /// Deserialize an instance of type `T` from a string of XML text. pub fn from_str<'de, T>(s: &'de str) -> Result where @@ -2166,6 +2130,44 @@ where } } +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/// A structure that deserializes XML into Rust values. +pub struct Deserializer<'de, R> +where + R: XmlRead<'de>, +{ + /// An XML reader that streams events into this deserializer + reader: XmlReader<'de, R>, + + /// When deserializing sequences sometimes we have to skip unwanted events. + /// That events should be stored and then replayed. This is a replay buffer, + /// that streams events while not empty. When it exhausted, events will + /// requested from [`Self::reader`]. + #[cfg(feature = "overlapped-lists")] + read: VecDeque>, + /// When deserializing sequences sometimes we have to skip events, because XML + /// is tolerant to elements order and even if in the XSD order is strictly + /// specified (using `xs:sequence`) most of XML parsers allows order violations. + /// That means, that elements, forming a sequence, could be overlapped with + /// other elements, do not related to that sequence. + /// + /// In order to support this, deserializer will scan events and skip unwanted + /// events, store them here. After call [`Self::start_replay()`] all events + /// moved from this to [`Self::read`]. + #[cfg(feature = "overlapped-lists")] + write: VecDeque>, + /// Maximum number of events that can be skipped when processing sequences + /// that occur out-of-order. This field is used to prevent potential + /// denial-of-service (DoS) attacks which could cause infinite memory + /// consumption when parsing a very large amount of XML into a sequence field. + #[cfg(feature = "overlapped-lists")] + limit: Option, + + #[cfg(not(feature = "overlapped-lists"))] + peek: Option>, +} + impl<'de, R> Deserializer<'de, R> where R: XmlRead<'de>, From 098a2ea391542d15f8d5d1e59974d5b021a5b1ca Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 4 Mar 2023 22:52:30 +0500 Subject: [PATCH 2/2] Wrap text in the `DeEvent::Text` to the dedicated `Text` type This type would be useful when span support would be added or to implement configurable stripping leading / trailing spaces --- src/de/mod.rs | 271 +++++++++++++++++------------------------- src/de/simple_type.rs | 6 +- 2 files changed, 115 insertions(+), 162 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index 75e6afe2..6b5fea8a 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -1852,12 +1852,46 @@ use std::io::BufRead; use std::mem::replace; #[cfg(feature = "overlapped-lists")] use std::num::NonZeroUsize; +use std::ops::Deref; /// Data represented by a text node or a CDATA node. XML markup is not expected pub(crate) const TEXT_KEY: &str = "$text"; /// Data represented by any XML markup inside pub(crate) const VALUE_KEY: &str = "$value"; +/// Decoded and concatenated content of consequent [`Text`] and [`CData`] +/// events. _Consequent_ means that events should follow each other or be +/// delimited only by (any count of) [`Comment`] or [`PI`] events. +/// +/// [`Text`]: Event::Text +/// [`CData`]: Event::CData +/// [`Comment`]: Event::Comment +/// [`PI`]: Event::PI +#[derive(Debug, PartialEq, Eq)] +pub struct Text<'a> { + text: Cow<'a, str>, +} + +impl<'a> Deref for Text<'a> { + type Target = str; + + #[inline] + fn deref(&self) -> &Self::Target { + self.text.deref() + } +} + +impl<'a> From<&'a str> for Text<'a> { + #[inline] + fn from(text: &'a str) -> Self { + Self { + text: Cow::Borrowed(text), + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + /// Simplified event which contains only these variants that used by deserializer #[derive(Debug, PartialEq, Eq)] pub enum DeEvent<'a> { @@ -1873,7 +1907,7 @@ pub enum DeEvent<'a> { /// [`CData`]: Event::CData /// [`Comment`]: Event::Comment /// [`PI`]: Event::PI - Text(Cow<'a, str>), + Text(Text<'a>), /// End of XML document. Eof, } @@ -1976,7 +2010,7 @@ impl<'i, R: XmlRead<'i>> XmlReader<'i, R> { _ => break, } } - Ok(DeEvent::Text(result)) + Ok(DeEvent::Text(Text { text: result })) } /// Read one text event, panics if current event is not a text event @@ -2423,12 +2457,12 @@ where /// [`CData`]: Event::CData fn read_string_impl(&mut self, allow_start: bool) -> Result, DeError> { match self.next()? { - DeEvent::Text(e) => Ok(e), + DeEvent::Text(e) => Ok(e.text), // allow one nested level DeEvent::Start(e) if allow_start => match self.next()? { DeEvent::Text(t) => { self.read_to_end(e.name())?; - Ok(t) + Ok(t.text) } DeEvent::Start(s) => Err(DeError::UnexpectedStart(s.name().as_ref().to_owned())), // We can get End event in case of `` or `` input @@ -2871,7 +2905,7 @@ mod tests { de.write, vec![ Start(BytesStart::new("inner")), - Text(Cow::Borrowed("text")), + Text("text".into()), Start(BytesStart::new("inner")), End(BytesEnd::new("inner")), End(BytesEnd::new("inner")), @@ -2905,7 +2939,7 @@ mod tests { de.read, vec![ Start(BytesStart::new("inner")), - Text(Cow::Borrowed("text")), + Text("text".into()), Start(BytesStart::new("inner")), End(BytesEnd::new("inner")), End(BytesEnd::new("inner")), @@ -2933,7 +2967,7 @@ mod tests { vec![ // This comment here to keep the same formatting of both arrays // otherwise rustfmt suggest one-line it - Text(Cow::Borrowed("text")), + Text("text".into()), ] ); @@ -2955,12 +2989,12 @@ mod tests { vec![ // This comment here to keep the same formatting as others // otherwise rustfmt suggest one-line it - Text(Cow::Borrowed("text")), + Text("text".into()), End(BytesEnd::new("inner")), ] ); assert_eq!(de.write, vec![]); - assert_eq!(de.next().unwrap(), Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), Text("text".into())); assert_eq!(de.next().unwrap(), End(BytesEnd::new("inner"))); assert_eq!(de.next().unwrap(), Start(BytesStart::new("target"))); assert_eq!(de.next().unwrap(), End(BytesEnd::new("target"))); @@ -3002,7 +3036,7 @@ mod tests { de.write, vec![ Start(BytesStart::new("skip")), - Text(Cow::Borrowed("text")), + Text("text".into()), Start(BytesStart::new("skip")), End(BytesEnd::new("skip")), End(BytesEnd::new("skip")), @@ -3023,7 +3057,7 @@ mod tests { de.write, vec![ Start(BytesStart::new("skip")), - Text(Cow::Borrowed("text")), + Text("text".into()), Start(BytesStart::new("skip")), End(BytesEnd::new("skip")), End(BytesEnd::new("skip")), @@ -3045,7 +3079,7 @@ mod tests { de.read, vec![ Start(BytesStart::new("skip")), - Text(Cow::Borrowed("text")), + Text("text".into()), Start(BytesStart::new("skip")), End(BytesEnd::new("skip")), End(BytesEnd::new("skip")), @@ -3335,7 +3369,7 @@ mod tests { de.next().unwrap(), Start(BytesStart::from_content(r#"tag a="2""#, 3)) ); - assert_eq!(de.next().unwrap(), Text(Cow::Borrowed("cdata content"))); + assert_eq!(de.next().unwrap(), Text("cdata content".into())); assert_eq!(de.next().unwrap(), End(BytesEnd::new("tag"))); assert_eq!(de.next().unwrap(), Start(BytesStart::new("self-closed"))); @@ -3364,7 +3398,7 @@ mod tests { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), Start(BytesStart::new("tag"))); - assert_eq!(de.peek().unwrap(), &Text(Cow::Borrowed(""))); + assert_eq!(de.peek().unwrap(), &Text("".into())); match de.read_to_end(QName(b"tag")) { Err(DeError::UnexpectedEof) => (), @@ -3495,49 +3529,37 @@ mod tests { #[test] fn text() { let mut de = Deserializer::from_str("text"); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); } #[test] fn cdata() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("cdata"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata".into())); } #[test] fn text_and_cdata() { let mut de = Deserializer::from_str("text and "); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text and cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text and cdata".into())); } #[test] fn text_and_empty_cdata() { let mut de = Deserializer::from_str("text and "); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text and ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text and ".into())); } #[test] fn cdata_and_text() { let mut de = Deserializer::from_str(" and text"); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata and text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata and text".into())); } #[test] fn empty_cdata_and_text() { let mut de = Deserializer::from_str(" and text"); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" and text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" and text".into())); } #[test] @@ -3548,10 +3570,7 @@ mod tests { cdata]]>\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata]]>cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata]]>cdata".into())); } mod comment_between { @@ -3567,10 +3586,7 @@ mod tests { text\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text text".into())); } #[test] @@ -3582,10 +3598,7 @@ mod tests { cdata]]>\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata]]>cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata]]>cdata".into())); } #[test] @@ -3597,10 +3610,7 @@ mod tests { \ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata".into())); } #[test] @@ -3612,7 +3622,7 @@ mod tests { \ ", ); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text "))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text ".into())); } #[test] @@ -3624,10 +3634,7 @@ mod tests { text \ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata text".into())); } #[test] @@ -3639,7 +3646,7 @@ mod tests { text \ ", ); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" text".into())); } #[test] @@ -3651,10 +3658,7 @@ mod tests { cdata]]>\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata]]>cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata]]>cdata".into())); } } @@ -3671,10 +3675,7 @@ mod tests { text\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text text".into())); } #[test] @@ -3686,10 +3687,7 @@ mod tests { cdata]]>\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata]]>cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata]]>cdata".into())); } #[test] @@ -3701,10 +3699,7 @@ mod tests { \ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata".into())); } #[test] @@ -3716,7 +3711,7 @@ mod tests { \ ", ); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text "))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text ".into())); } #[test] @@ -3728,10 +3723,7 @@ mod tests { text \ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata text".into())); } #[test] @@ -3743,7 +3735,7 @@ mod tests { text \ ", ); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" text".into())); } #[test] @@ -3755,10 +3747,7 @@ mod tests { cdata]]>\ ", ); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("cdata]]>cdata")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("cdata]]>cdata".into())); } } } @@ -3804,7 +3793,7 @@ mod tests { assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag1"))); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3813,7 +3802,7 @@ mod tests { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag1"))); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3862,7 +3851,7 @@ mod tests { assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3871,7 +3860,7 @@ mod tests { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3895,7 +3884,7 @@ mod tests { let mut de = Deserializer::from_str(" text "); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3905,7 +3894,7 @@ mod tests { let mut de = Deserializer::from_str(" text "); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3917,10 +3906,7 @@ mod tests { let mut de = Deserializer::from_str(" text "); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from the start - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3929,7 +3915,7 @@ mod tests { let mut de = Deserializer::from_str(" text "); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3944,7 +3930,7 @@ mod tests { fn start() { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3953,7 +3939,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3963,10 +3949,7 @@ mod tests { let mut de = Deserializer::from_str(" text "); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from the end - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3975,10 +3958,7 @@ mod tests { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata cdata2 ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -3986,7 +3966,7 @@ mod tests { fn eof() { let mut de = Deserializer::from_str(""); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4019,7 +3999,7 @@ mod tests { fn start() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag1"))); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4030,7 +4010,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4040,10 +4020,10 @@ mod tests { fn text() { let mut de = Deserializer::from_str(" text text2 "); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text2"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text2".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4051,9 +4031,9 @@ mod tests { fn cdata() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4061,7 +4041,7 @@ mod tests { fn eof() { // Text is trimmed from both sides let mut de = Deserializer::from_str(" text "); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4073,7 +4053,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); match de.next() { Err(DeError::InvalidXml(Error::EndEventMismatch { expected, found })) => { assert_eq!(expected, ""); @@ -4094,10 +4074,7 @@ mod tests { fn start() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the start - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4106,10 +4083,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the start - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata ".into())); match de.next() { Err(DeError::InvalidXml(Error::EndEventMismatch { expected, found })) => { assert_eq!(expected, ""); @@ -4126,7 +4100,7 @@ mod tests { // Text is trimmed from the start and from the end assert_eq!( de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata text2")) + DeEvent::Text("text cdata text2".into()) ); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4138,7 +4112,7 @@ mod tests { // Text is trimmed from the start assert_eq!( de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata cdata2 ")) + DeEvent::Text("text cdata cdata2 ".into()) ); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4147,10 +4121,7 @@ mod tests { fn eof() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the start - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed("text cdata ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text("text cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4168,7 +4139,7 @@ mod tests { #[test] fn start() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag1"))); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag2"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4178,7 +4149,7 @@ mod tests { #[test] fn end() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::End(BytesEnd::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4187,10 +4158,10 @@ mod tests { #[test] fn text() { let mut de = Deserializer::from_str(" text "); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); // Text is trimmed from both sides - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed("text"))); + assert_eq!(de.next().unwrap(), DeEvent::Text("text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4198,16 +4169,16 @@ mod tests { fn cdata() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata2 "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata2 ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); } #[test] fn eof() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); @@ -4218,7 +4189,7 @@ mod tests { #[test] fn end() { let mut de = Deserializer::from_str(""); - assert_eq!(de.next().unwrap(), DeEvent::Text(Cow::Borrowed(" cdata "))); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata ".into())); match de.next() { Err(DeError::InvalidXml(Error::EndEventMismatch { expected, found })) => { assert_eq!(expected, ""); @@ -4237,10 +4208,7 @@ mod tests { fn start() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the end - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata text".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4249,10 +4217,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the end - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata text".into())); match de.next() { Err(DeError::InvalidXml(Error::EndEventMismatch { expected, found })) => { assert_eq!(expected, ""); @@ -4271,7 +4236,7 @@ mod tests { Deserializer::from_str(" text "); assert_eq!( de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata text cdata2 ")) + DeEvent::Text(" cdata text cdata2 ".into()) ); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4280,10 +4245,7 @@ mod tests { fn eof() { let mut de = Deserializer::from_str(" text "); // Text is trimmed from the end - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata text")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata text".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4297,10 +4259,7 @@ mod tests { fn start() { let mut de = Deserializer::from_str(""); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata cdata2 ".into())); assert_eq!(de.next().unwrap(), DeEvent::Start(BytesStart::new("tag"))); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4309,10 +4268,7 @@ mod tests { fn end() { let mut de = Deserializer::from_str(""); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata cdata2 ".into())); match de.next() { Err(DeError::InvalidXml(Error::EndEventMismatch { expected, found })) => { assert_eq!(expected, ""); @@ -4330,7 +4286,7 @@ mod tests { // Text is trimmed from the end assert_eq!( de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 text")) + DeEvent::Text(" cdata cdata2 text".into()) ); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4342,7 +4298,7 @@ mod tests { ); assert_eq!( de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 cdata3 ")) + DeEvent::Text(" cdata cdata2 cdata3 ".into()) ); assert_eq!(de.next().unwrap(), DeEvent::Eof); } @@ -4350,10 +4306,7 @@ mod tests { #[test] fn eof() { let mut de = Deserializer::from_str(""); - assert_eq!( - de.next().unwrap(), - DeEvent::Text(Cow::Borrowed(" cdata cdata2 ")) - ); + assert_eq!(de.next().unwrap(), DeEvent::Text(" cdata cdata2 ".into())); assert_eq!(de.next().unwrap(), DeEvent::Eof); assert_eq!(de.next().unwrap(), DeEvent::Eof); } diff --git a/src/de/simple_type.rs b/src/de/simple_type.rs index 81462713..3a532cca 100644 --- a/src/de/simple_type.rs +++ b/src/de/simple_type.rs @@ -3,7 +3,7 @@ //! [simple types]: https://www.w3schools.com/xml/el_simpletype.asp //! [as defined]: https://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition -use crate::de::{deserialize_bool, str2bool}; +use crate::de::{deserialize_bool, str2bool, Text}; use crate::encoding::Decoder; use crate::errors::serialize::DeError; use crate::escape::unescape; @@ -495,8 +495,8 @@ pub struct SimpleTypeDeserializer<'de, 'a> { impl<'de, 'a> SimpleTypeDeserializer<'de, 'a> { /// Creates a deserializer from a value, that possible borrowed from input - pub fn from_text_content(value: Cow<'de, str>) -> Self { - let content = match value { + pub fn from_text_content(value: Text<'de>) -> Self { + let content = match value.text { Cow::Borrowed(slice) => CowRef::Input(slice.as_bytes()), Cow::Owned(content) => CowRef::Owned(content.into_bytes()), };