Add support for Vec<T>

This commit is contained in:
rsdy 2022-09-28 18:58:57 +01:00 committed by Dirkjan Ochtman
parent 44f8a2cc6d
commit dc9eb50e6c
2 changed files with 74 additions and 6 deletions

View File

@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use crate::{Deserializer, Error, FromXml, Kind, Serializer, ToXml}; use crate::{de::Node, Deserializer, Error, FromXml, Id, Kind, Serializer, ToXml};
// Deserializer // Deserializer
struct FromXmlStr<T: FromStr>(Option<T>); struct FromXmlStr<T: FromStr>(Option<T>);
@ -316,3 +316,68 @@ fn decode(input: &str) -> Cow<'_, str> {
Cow::Owned(result) Cow::Owned(result)
} }
const VEC_TAG: &str = "list";
const VEC_ELEMENT_TAG: &str = "element";
impl<'xml, T> FromXml<'xml> for Vec<T>
where
T: FromXml<'xml>,
{
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
let mut result = Self::new();
while let Some(Ok(node)) = deserializer.next() {
match node {
Node::Open(data) => {
let id = deserializer.element_id(&data)?;
match id.name {
VEC_ELEMENT_TAG => {
let mut nested = deserializer.nested(data);
result.push(<T as FromXml<'xml>>::deserialize(&mut nested)?)
}
_ => return Err(Error::UnexpectedState),
}
}
_ => return Err(Error::UnexpectedState),
}
}
Ok(result)
}
const KIND: Kind = Kind::Element(Id {
ns: "",
name: VEC_TAG,
});
}
impl<T> ToXml for Vec<T>
where
T: ToXml,
{
fn serialize<W: fmt::Write + ?Sized>(
&self,
serializer: &mut Serializer<W>,
) -> Result<(), Error> {
let prefix = serializer.write_start(VEC_TAG, "", false)?;
serializer.end_start()?;
for i in self {
let prefix = serializer.write_start(VEC_ELEMENT_TAG, "", false)?;
serializer.end_start()?;
i.serialize(serializer)?;
serializer.write_close(prefix, VEC_ELEMENT_TAG)?;
}
serializer.write_close(prefix, VEC_TAG)?;
Ok(())
}
const KIND: Kind = Kind::Element(Id {
ns: "",
name: VEC_TAG,
});
}

View File

@ -10,32 +10,34 @@ struct StructSpecialEntities<'a> {
string: String, string: String,
str: &'a str, str: &'a str,
cow: Cow<'a, str>, cow: Cow<'a, str>,
vec: Vec<String>,
} }
#[test] #[test]
fn escape_back() { fn escape_back() {
assert_eq!( assert_eq!(
from_str( from_str(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow></StructSpecialEntities>" "<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow><list xmlns=\"\"><element xmlns=\"\">one</element><element xmlns=\"\">two</element><element xmlns=\"\">three</element></list></StructSpecialEntities>"
), ),
Ok(StructSpecialEntities { Ok(StructSpecialEntities {
string: String::from("<>&\"'adsad\""), string: String::from("<>&\"'adsad\""),
str: "str", str: "str",
cow: Cow::Owned("str&".to_string()), cow: Cow::Owned("str&".to_string()),
vec: vec!["one".into(), "two".into(), "three".into()]
}) })
); );
// Wrong str char // Wrong str char
assert_eq!( assert_eq!(
from_str( from_str(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str&amp;</str></StructSpecialEntities>" "<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str&amp;</str><list xmlns=\"\"><element xmlns=\"\">one</element><element xmlns=\"\">two</element><element xmlns=\"\">three</element></list></StructSpecialEntities>"
), ),
Err::<StructSpecialEntities, _>(Error::UnexpectedValue) Err::<StructSpecialEntities, _>(Error::UnexpectedValue)
); );
// Borrowed // Borrowed
let escape_back = from_str::<StructSpecialEntities>( let escape_back = from_str::<StructSpecialEntities>(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str</cow></StructSpecialEntities>" "<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str</cow><list xmlns=\"\"><element xmlns=\"\">one</element><element xmlns=\"\">two</element><element xmlns=\"\">three</element></list></StructSpecialEntities>"
) )
.unwrap(); .unwrap();
@ -45,7 +47,7 @@ fn escape_back() {
// Owned // Owned
let escape_back = from_str::<StructSpecialEntities>( let escape_back = from_str::<StructSpecialEntities>(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow></StructSpecialEntities>" "<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str</str><cow>str&amp;</cow><list xmlns=\"\"><element xmlns=\"\">one</element><element xmlns=\"\">two</element><element xmlns=\"\">three</element></list></StructSpecialEntities>"
) )
.unwrap(); .unwrap();
@ -61,7 +63,8 @@ fn special_entities() {
string: "&\"<>\'aa".to_string(), string: "&\"<>\'aa".to_string(),
str: "&\"<>\'bb", str: "&\"<>\'bb",
cow: Cow::from("&\"<>\'cc"), cow: Cow::from("&\"<>\'cc"),
vec: vec!["one".into(), "two".into(), "three".into()]
}).unwrap(), }).unwrap(),
"<StructSpecialEntities xmlns=\"URI\"><string>&amp;&quot;&lt;&gt;&apos;aa</string><str>&amp;&quot;&lt;&gt;&apos;bb</str><cow>&amp;&quot;&lt;&gt;&apos;cc</cow></StructSpecialEntities>", "<StructSpecialEntities xmlns=\"URI\"><string>&amp;&quot;&lt;&gt;&apos;aa</string><str>&amp;&quot;&lt;&gt;&apos;bb</str><cow>&amp;&quot;&lt;&gt;&apos;cc</cow><list xmlns=\"\"><element xmlns=\"\">one</element><element xmlns=\"\">two</element><element xmlns=\"\">three</element></list></StructSpecialEntities>",
); );
} }