diff --git a/instant-xml-macros/src/de.rs b/instant-xml-macros/src/de.rs index f666cd3..72ffd53 100644 --- a/instant-xml-macros/src/de.rs +++ b/instant-xml-macros/src/de.rs @@ -63,7 +63,7 @@ fn deserialize_scalar_enum( }; let serialize_as = meta.serialize_as; - variants.extend(quote!(Some(#serialize_as) => #ident::#v_ident,)); + variants.extend(quote!(#serialize_as => #ident::#v_ident,)); } let generics = meta.xml_generics(BTreeSet::new()); @@ -92,14 +92,18 @@ fn deserialize_scalar_enum( return Err(Error::DuplicateValue); } - let value = match deserializer.take_str()? { - #variants - Some(val) => return Err(Error::UnexpectedValue( - format!("enum variant not found for '{}'", val) - )), + let cow_str = match deserializer.take_str()? { + Some(val) => val, None => return Err(Error::MissingValue(#type_str)), }; + let value = match cow_str.as_ref() { + #variants + _ => return Err(Error::UnexpectedValue( + format!("enum variant not found for '{}'", cow_str), + )), + }; + *into = Some(value); Ok(()) } diff --git a/instant-xml/src/de.rs b/instant-xml/src/de.rs index 76cd47a..c2fbbc3 100644 --- a/instant-xml/src/de.rs +++ b/instant-xml/src/de.rs @@ -31,7 +31,7 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> { } } - pub fn take_str(&mut self) -> Result, Error> { + pub fn take_str(&mut self) -> Result>, Error> { loop { match self.next() { Some(Ok(Node::AttributeValue(s))) => return Ok(Some(s)), @@ -321,18 +321,23 @@ impl<'xml> Iterator for Context<'xml> { } } } else { + let value = match decode(value.as_str()) { + Ok(value) => value, + Err(e) => return Some(Err(e)), + }; + self.records.push_back(Node::Attribute(Attribute { prefix: match prefix.is_empty() { true => None, false => Some(prefix.as_str()), }, local: local.as_str(), - value: value.as_str(), + value, })); } } Ok(Token::Text { text }) => { - return Some(Ok(Node::Text(text.as_str()))); + return Some(decode(text.as_str()).map(Node::Text)); } Ok(Token::Declaration { .. }) => match self.stack.is_empty() { false => return Some(Err(Error::UnexpectedToken(format!("{token:?}")))), @@ -354,12 +359,11 @@ pub fn borrow_cow_str<'a, 'xml: 'a>( return Err(Error::DuplicateValue); } - let value = match deserializer.take_str()? { - Some(value) => value, + match deserializer.take_str()? { + Some(value) => into.inner = Some(value), None => return Ok(()), }; - into.inner = Some(decode(value)?); deserializer.ignore()?; Ok(()) } @@ -374,7 +378,7 @@ pub fn borrow_cow_slice_u8<'xml>( } if let Some(value) = deserializer.take_str()? { - *into = Some(match decode(value)? { + *into = Some(match value { Cow::Borrowed(v) => Cow::Borrowed(v.as_bytes()), Cow::Owned(v) => Cow::Owned(v.into_bytes()), }); @@ -384,7 +388,7 @@ pub fn borrow_cow_slice_u8<'xml>( Ok(()) } -pub(crate) fn decode(input: &str) -> Result, Error> { +fn decode(input: &str) -> Result, Error> { let mut result = String::with_capacity(input.len()); let (mut state, mut last_end) = (DecodeState::Normal, 0); for (i, &b) in input.as_bytes().iter().enumerate() { @@ -489,12 +493,12 @@ fn valid_xml_character(c: &char) -> bool { #[derive(Debug)] pub enum Node<'xml> { Attribute(Attribute<'xml>), - AttributeValue(&'xml str), + AttributeValue(Cow<'xml, str>), Close { prefix: Option<&'xml str>, local: &'xml str, }, - Text(&'xml str), + Text(Cow<'xml, str>), Open(Element<'xml>), } @@ -519,7 +523,7 @@ struct Level<'xml> { pub struct Attribute<'xml> { pub prefix: Option<&'xml str>, pub local: &'xml str, - pub value: &'xml str, + pub value: Cow<'xml, str>, } #[cfg(test)] diff --git a/instant-xml/src/impls.rs b/instant-xml/src/impls.rs index 10371aa..3ee1614 100644 --- a/instant-xml/src/impls.rs +++ b/instant-xml/src/impls.rs @@ -8,7 +8,6 @@ use std::{any::type_name, marker::PhantomData}; #[cfg(feature = "chrono")] use chrono::{DateTime, NaiveDate, Utc}; -use crate::de::decode; use crate::{Accumulate, Deserializer, Error, FromXml, Id, Kind, Serializer, ToXml}; // Deserializer @@ -26,7 +25,7 @@ pub fn from_xml_str( None => return Ok(()), }; - match T::from_str(value) { + match T::from_str(value.as_ref()) { Ok(value) => { *into = Some(value); Ok(()) @@ -63,7 +62,7 @@ impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr { None => return Ok(()), }; - match T::from_str(value) { + match T::from_str(value.as_ref()) { Ok(value) => { *into = Some(FromXmlStr(value)); Ok(()) @@ -102,7 +101,7 @@ impl<'xml> FromXml<'xml> for bool { None => return Ok(()), }; - let value = match value { + let value = match value.as_ref() { "true" | "1" => true, "false" | "0" => false, val => { @@ -271,7 +270,7 @@ impl<'xml> FromXml<'xml> for String { } match deserializer.take_str()? { - Some(value) => *into = Some(decode(value)?.into_owned()), + Some(value) => *into = Some(value.into_owned()), None => return Ok(()), } @@ -305,7 +304,7 @@ impl<'xml, 'a> FromXml<'xml> for Cow<'a, str> { None => return Ok(()), }; - into.inner = Some(decode(value)?.into_owned().into()); + into.inner = Some(value.into_owned().into()); Ok(()) } @@ -608,7 +607,7 @@ impl<'xml> FromXml<'xml> for DateTime { None => return Ok(()), }; - match DateTime::parse_from_rfc3339(value) { + match DateTime::parse_from_rfc3339(value.as_ref()) { Ok(dt) if dt.timezone().utc_minus_local() == 0 => { *into = Some(dt.with_timezone(&Utc)); Ok(()) @@ -670,7 +669,7 @@ impl<'xml> FromXml<'xml> for NaiveDate { None => return Ok(()), }; - match NaiveDate::parse_from_str(value, "%Y-%m-%d") { + match NaiveDate::parse_from_str(value.as_ref(), "%Y-%m-%d") { Ok(d) => { *into = Some(d); Ok(())