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)
|
Cow::Owned(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VEC_LIST_TAG: &str = "list";
|
||||||
const VEC_ELEMENT_TAG: &str = "element";
|
const VEC_ELEMENT_TAG: &str = "element";
|
||||||
|
|
||||||
impl<'xml, T> FromXml<'xml> for Vec<T>
|
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> {
|
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
|
||||||
let mut result = Self::new();
|
let mut result = Self::new();
|
||||||
|
let kind = <T as FromXml<'xml>>::KIND;
|
||||||
|
|
||||||
while let Some(Ok(node)) = deserializer.next() {
|
while let Some(Ok(node)) = deserializer.next() {
|
||||||
match node {
|
match (&kind, node) {
|
||||||
Node::Open(data) => {
|
(Kind::Scalar, Node::Open(data)) => {
|
||||||
let id = deserializer.element_id(&data)?;
|
let id = deserializer.element_id(&data)?;
|
||||||
|
|
||||||
match id.name {
|
match id.name {
|
||||||
|
@ -339,6 +341,10 @@ where
|
||||||
_ => return Err(Error::UnexpectedState),
|
_ => 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),
|
_ => return Err(Error::UnexpectedState),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,12 +363,30 @@ where
|
||||||
&self,
|
&self,
|
||||||
serializer: &mut Serializer<W>,
|
serializer: &mut Serializer<W>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
match <T as ToXml>::KIND {
|
||||||
|
Kind::Element(_) => {
|
||||||
|
for i in self {
|
||||||
|
i.serialize(serializer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::Scalar => {
|
||||||
for i in self {
|
for i in self {
|
||||||
let prefix = serializer.write_start(VEC_ELEMENT_TAG, "", false)?;
|
let prefix = serializer.write_start(VEC_ELEMENT_TAG, "", false)?;
|
||||||
serializer.end_start()?;
|
serializer.end_start()?;
|
||||||
i.serialize(serializer)?;
|
i.serialize(serializer)?;
|
||||||
serializer.write_close(prefix, VEC_ELEMENT_TAG)?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,33 @@ struct StructSpecialEntities<'a> {
|
||||||
vec: Vec<String>,
|
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]
|
#[test]
|
||||||
fn escape_back() {
|
fn escape_back() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue