From dc9eb50e6cd6efe540526bc561c1aa381c38a2a8 Mon Sep 17 00:00:00 2001 From: rsdy Date: Wed, 28 Sep 2022 18:58:57 +0100 Subject: [PATCH] Add support for Vec --- instant-xml/src/impls.rs | 67 ++++++++++++++++++++++++++++++++++- instant-xml/tests/entities.rs | 13 ++++--- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/instant-xml/src/impls.rs b/instant-xml/src/impls.rs index 03e5149..1c876c3 100644 --- a/instant-xml/src/impls.rs +++ b/instant-xml/src/impls.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::fmt; use std::str::FromStr; -use crate::{Deserializer, Error, FromXml, Kind, Serializer, ToXml}; +use crate::{de::Node, Deserializer, Error, FromXml, Id, Kind, Serializer, ToXml}; // Deserializer struct FromXmlStr(Option); @@ -316,3 +316,68 @@ fn decode(input: &str) -> Cow<'_, str> { Cow::Owned(result) } + +const VEC_TAG: &str = "list"; +const VEC_ELEMENT_TAG: &str = "element"; + +impl<'xml, T> FromXml<'xml> for Vec +where + T: FromXml<'xml>, +{ + fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result { + 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(>::deserialize(&mut nested)?) + } + _ => return Err(Error::UnexpectedState), + } + } + _ => return Err(Error::UnexpectedState), + } + } + + Ok(result) + } + + const KIND: Kind = Kind::Element(Id { + ns: "", + name: VEC_TAG, + }); +} + +impl ToXml for Vec +where + T: ToXml, +{ + fn serialize( + &self, + serializer: &mut Serializer, + ) -> 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, + }); +} diff --git a/instant-xml/tests/entities.rs b/instant-xml/tests/entities.rs index 91c57f6..b89a678 100644 --- a/instant-xml/tests/entities.rs +++ b/instant-xml/tests/entities.rs @@ -10,32 +10,34 @@ struct StructSpecialEntities<'a> { string: String, str: &'a str, cow: Cow<'a, str>, + vec: Vec, } #[test] fn escape_back() { assert_eq!( from_str( - "<>&"'adsad"strstr&" + "<>&"'adsad"strstr&onetwothree" ), Ok(StructSpecialEntities { string: String::from("<>&\"'adsad\""), str: "str", cow: Cow::Owned("str&".to_string()), + vec: vec!["one".into(), "two".into(), "three".into()] }) ); // Wrong str char assert_eq!( from_str( - "<>&"'adsad"str&" + "<>&"'adsad"str&onetwothree" ), Err::(Error::UnexpectedValue) ); // Borrowed let escape_back = from_str::( - "<>&"'adsad"strstr" + "<>&"'adsad"strstronetwothree" ) .unwrap(); @@ -45,7 +47,7 @@ fn escape_back() { // Owned let escape_back = from_str::( - "<>&"'adsad"strstr&" + "<>&"'adsad"strstr&onetwothree" ) .unwrap(); @@ -61,7 +63,8 @@ fn special_entities() { string: "&\"<>\'aa".to_string(), str: "&\"<>\'bb", cow: Cow::from("&\"<>\'cc"), + vec: vec!["one".into(), "two".into(), "three".into()] }).unwrap(), - "&"<>'aa&"<>'bb&"<>'cc", + "&"<>'aa&"<>'bb&"<>'cconetwothree", ); }