Better serialization of complex types under `Vec<T>`
This commit is contained in:
parent
4d627b514a
commit
55c7c5db99
|
@ -317,6 +317,7 @@ fn decode(input: &str) -> Cow<'_, str> {
|
|||
Cow::Owned(result)
|
||||
}
|
||||
|
||||
const VEC_LIST_TAG: &str = "list";
|
||||
const VEC_ELEMENT_TAG: &str = "element";
|
||||
|
||||
impl<'xml, T> FromXml<'xml> for Vec<T>
|
||||
|
@ -325,10 +326,11 @@ where
|
|||
{
|
||||
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
|
||||
let mut result = Self::new();
|
||||
let kind = <T as FromXml<'xml>>::KIND;
|
||||
|
||||
while let Some(Ok(node)) = deserializer.next() {
|
||||
match node {
|
||||
Node::Open(data) => {
|
||||
match (&kind, node) {
|
||||
(Kind::Scalar, Node::Open(data)) => {
|
||||
let id = deserializer.element_id(&data)?;
|
||||
|
||||
match id.name {
|
||||
|
@ -339,6 +341,10 @@ where
|
|||
_ => return Err(Error::UnexpectedState),
|
||||
}
|
||||
}
|
||||
(Kind::Vec | Kind::Element(_), Node::Open(data)) => {
|
||||
let mut nested = deserializer.nested(data);
|
||||
result.push(<T as FromXml<'xml>>::deserialize(&mut nested)?)
|
||||
}
|
||||
_ => return Err(Error::UnexpectedState),
|
||||
}
|
||||
}
|
||||
|
@ -357,12 +363,30 @@ where
|
|||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
match <T as ToXml>::KIND {
|
||||
Kind::Element(_) => {
|
||||
for i in self {
|
||||
i.serialize(serializer)?;
|
||||
}
|
||||
}
|
||||
Kind::Scalar => {
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
// this would be a Vec<Vec<T>>, where the internal field is unnamed
|
||||
Kind::Vec => {
|
||||
for i in self {
|
||||
let prefix = serializer.write_start(VEC_LIST_TAG, "", false)?;
|
||||
serializer.end_start()?;
|
||||
i.serialize(serializer)?;
|
||||
serializer.write_close(prefix, VEC_LIST_TAG)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -13,6 +13,33 @@ struct StructSpecialEntities<'a> {
|
|||
vec: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, FromXml, ToXml)]
|
||||
#[xml(ns("URI"))]
|
||||
struct VecEntities<'a> {
|
||||
complex: Vec<StructSpecialEntities<'a>>,
|
||||
list1: Vec<String>,
|
||||
list2: Vec<Vec<String>>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_entities() {
|
||||
let serialized = r#"<VecEntities xmlns="URI"><complex><StructSpecialEntities><string><>&"'adsad"</string><str>str</str><cow>str&</cow><vec><element xmlns="">one</element><element xmlns="">two</element><element xmlns="">three</element></vec></StructSpecialEntities></complex><list1><element xmlns="">a</element><element xmlns="">b</element></list1><list2><list xmlns=""><element xmlns="">a</element><element xmlns="">b</element></list></list2></VecEntities>"#;
|
||||
|
||||
let instance = VecEntities {
|
||||
complex: vec![StructSpecialEntities {
|
||||
string: String::from("<>&\"'adsad\""),
|
||||
str: "str",
|
||||
cow: Cow::Owned("str&".to_string()),
|
||||
vec: vec!["one".into(), "two".into(), "three".into()],
|
||||
}],
|
||||
list1: vec!["a".into(), "b".into()],
|
||||
list2: vec![vec!["a".into(), "b".into()]],
|
||||
};
|
||||
|
||||
assert_eq!(to_string(&instance).unwrap(), serialized);
|
||||
assert_eq!(from_str(serialized), Ok(instance));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escape_back() {
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in New Issue