Escape entities in context iterator

This commit is contained in:
Dirkjan Ochtman 2023-10-25 17:35:19 +02:00
parent efdf9334c7
commit edad589294
3 changed files with 32 additions and 25 deletions

View File

@ -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(())
}

View File

@ -31,7 +31,7 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> {
}
}
pub fn take_str(&mut self) -> Result<Option<&'xml str>, Error> {
pub fn take_str(&mut self) -> Result<Option<Cow<'xml, str>>, 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<Cow<'_, str>, Error> {
fn decode(input: &str) -> Result<Cow<'_, str>, 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)]

View File

@ -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<T: FromStr>(
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<T> {
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<Utc> {
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(())