serde-xml-rs-0.4.0/.gitignore010064400017500001750000000000221344366255700142570ustar0000000000000000target Cargo.lock serde-xml-rs-0.4.0/.travis.yml010066400017500001750000000003531362120443100143660ustar0000000000000000language: rust rust: - stable - beta - nightly cache: cargo before_cache: - cargo clean -p serde-xml-rs - rm -rf target/ env: global: - RUST_BACKTRACE=1 matrix: fast_finish: true allow_failures: - rust: nightly serde-xml-rs-0.4.0/Cargo.toml.orig010066400017500001750000000006311363211542100151450ustar0000000000000000[package] authors = ["Ingvar Stepanyan "] description = "xml-rs based deserializer for Serde (compatible with 0.9+)" license = "MIT" name = "serde-xml-rs" repository = "https://github.com/RReverser/serde-xml-rs" version = "0.4.0" [dependencies] log = "0.4" serde = "1.0" xml-rs = "0.8.0" thiserror = "1.0" [dev-dependencies] serde_derive = "1.0" simple_logger = "1.0.1" docmatic = "0.1.2" serde-xml-rs-0.4.0/Cargo.toml0000644000000020641363211621600114560ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "serde-xml-rs" version = "0.4.0" authors = ["Ingvar Stepanyan "] description = "xml-rs based deserializer for Serde (compatible with 0.9+)" license = "MIT" repository = "https://github.com/RReverser/serde-xml-rs" [dependencies.log] version = "0.4" [dependencies.serde] version = "1.0" [dependencies.thiserror] version = "1.0" [dependencies.xml-rs] version = "0.8.0" [dev-dependencies.docmatic] version = "0.1.2" [dev-dependencies.serde_derive] version = "1.0" [dev-dependencies.simple_logger] version = "1.0.1" serde-xml-rs-0.4.0/LICENSE010064400017500001750000000020611344366255700133010ustar0000000000000000MIT License Copyright (c) 2017 Ingvar Stepanyan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. serde-xml-rs-0.4.0/README.md010064400017500001750000000031751344366255700135620ustar0000000000000000# serde-xml-rs [![Build Status](https://travis-ci.org/RReverser/serde-xml-rs.svg?branch=master)](https://travis-ci.org/RReverser/serde-xml-rs) xml-rs based deserializer for Serde (compatible with 0.9+) ## Usage Use `serde_xml_rs::from_reader(...)` on any type that implements [`std::io::Read`](https://doc.rust-lang.org/std/io/trait.Read.html) as following: ```rust #[macro_use] extern crate serde_derive; extern crate serde; extern crate serde_xml_rs; use serde_xml_rs::from_reader; #[derive(Debug, Deserialize)] struct Item { pub name: String, pub source: String } #[derive(Debug, Deserialize)] struct Project { pub name: String, #[serde(rename = "Item", default)] pub items: Vec } fn main() { let s = r##" "##; let project: Project = from_reader(s.as_bytes()).unwrap(); println!("{:#?}", project); } ``` Alternatively, you can use `serde_xml_rs::Deserializer` to create a deserializer from a preconfigured [`xml_rs::EventReader`](https://netvl.github.io/xml-rs/xml/reader/struct.EventReader.html). ## Parsing the "value" of a tag If you have an input of the form `bar`, and you want to get at the`bar`, you can use the special name `$value`: ```rust,ignore struct Foo { pub abc: String, #[serde(rename = "$value")] pub body: String, } ``` ## Parsed representations Deserializer tries to be as intuitive as possible. However, there are some edge cases where you might get unexpected errors, so it's best to check out [`tests`](tests/test.rs) for expectations. serde-xml-rs-0.4.0/rustfmt.toml010064400017500001750000000000421344366255700146720ustar0000000000000000match_block_trailing_comma = true serde-xml-rs-0.4.0/src/de/map.rs010066400017500001750000000102371362120443100145610ustar0000000000000000use std::io::Read; use serde::de::{self, IntoDeserializer, Unexpected}; use xml::attribute::OwnedAttribute; use xml::reader::XmlEvent; use Deserializer; use error::{Error, Result}; pub struct MapAccess<'a, R: 'a + Read> { attrs: ::std::vec::IntoIter, next_value: Option, de: &'a mut Deserializer, inner_value: bool, } impl<'a, R: 'a + Read> MapAccess<'a, R> { pub fn new(de: &'a mut Deserializer, attrs: Vec, inner_value: bool) -> Self { MapAccess { attrs: attrs.into_iter(), next_value: None, de: de, inner_value: inner_value, } } } impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for MapAccess<'a, R> { type Error = Error; fn next_key_seed>(&mut self, seed: K) -> Result> { debug_assert_eq!(self.next_value, None); match self.attrs.next() { Some(OwnedAttribute { name, value }) => { self.next_value = Some(value); seed.deserialize(name.local_name.into_deserializer()) .map(Some) }, None => match *self.de.peek()? { XmlEvent::StartElement { ref name, .. } => seed.deserialize( if !self.inner_value { name.local_name.as_str() } else { "$value" }.into_deserializer(), ).map(Some), XmlEvent::Characters(_) => seed.deserialize("$value".into_deserializer()).map(Some), _ => Ok(None), }, } } fn next_value_seed>(&mut self, seed: V) -> Result { match self.next_value.take() { Some(value) => seed.deserialize(AttrValueDeserializer(value)), None => { if !self.inner_value { if let XmlEvent::StartElement { .. } = *self.de.peek()? { self.de.set_map_value(); } } let result = seed.deserialize(&mut *self.de)?; Ok(result) }, } } fn size_hint(&self) -> Option { self.attrs.size_hint().1 } } struct AttrValueDeserializer(String); macro_rules! deserialize_type_attr { ($deserialize:ident => $visit:ident) => { fn $deserialize>(self, visitor: V) -> Result { visitor.$visit(self.0.parse()?) } } } impl<'de> de::Deserializer<'de> for AttrValueDeserializer { type Error = Error; fn deserialize_any>(self, visitor: V) -> Result { visitor.visit_string(self.0) } deserialize_type_attr!(deserialize_i8 => visit_i8); deserialize_type_attr!(deserialize_i16 => visit_i16); deserialize_type_attr!(deserialize_i32 => visit_i32); deserialize_type_attr!(deserialize_i64 => visit_i64); deserialize_type_attr!(deserialize_u8 => visit_u8); deserialize_type_attr!(deserialize_u16 => visit_u16); deserialize_type_attr!(deserialize_u32 => visit_u32); deserialize_type_attr!(deserialize_u64 => visit_u64); deserialize_type_attr!(deserialize_f32 => visit_f32); deserialize_type_attr!(deserialize_f64 => visit_f64); fn deserialize_enum>( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result { visitor.visit_enum(self.0.into_deserializer()) } fn deserialize_option>(self, visitor: V) -> Result { visitor.visit_some(self) } fn deserialize_bool>(self, visitor: V) -> Result { match self.0.as_str() { "true" | "1" => visitor.visit_bool(true), "false" | "0" => visitor.visit_bool(false), _ => Err(de::Error::invalid_value(Unexpected::Str(&self.0), &"a boolean")), } } forward_to_deserialize_any! { char str string unit seq bytes map unit_struct newtype_struct tuple_struct struct identifier tuple ignored_any byte_buf } } serde-xml-rs-0.4.0/src/de/mod.rs010066400017500001750000000261651362120443100145720ustar0000000000000000use std::io::Read; use serde::de::{self, Unexpected}; use xml::name::OwnedName; use xml::reader::{EventReader, ParserConfig, XmlEvent}; use self::map::MapAccess; use self::seq::SeqAccess; use self::var::EnumAccess; use error::{Error, Result}; mod map; mod seq; mod var; /// A convenience method for deserialize some object from a string. /// /// ```rust /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde; /// # extern crate serde_xml_rs; /// # use serde_xml_rs::from_str; /// #[derive(Debug, Deserialize, PartialEq)] /// struct Item { /// name: String, /// source: String, /// } /// # fn main() { /// let s = r##""##; /// let item: Item = from_str(s).unwrap(); /// assert_eq!(item, Item { name: "hello".to_string(),source: "world.rs".to_string()}); /// # } /// ``` pub fn from_str<'de, T: de::Deserialize<'de>>(s: &str) -> Result { from_reader(s.as_bytes()) } /// A convenience method for deserialize some object from a reader. /// /// ```rust /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde; /// # extern crate serde_xml_rs; /// # use serde_xml_rs::from_reader; /// #[derive(Debug, Deserialize, PartialEq)] /// struct Item { /// name: String, /// source: String, /// } /// # fn main() { /// let s = r##""##; /// let item: Item = from_reader(s.as_bytes()).unwrap(); /// assert_eq!(item, Item { name: "hello".to_string(),source: "world.rs".to_string()}); /// # } /// ``` pub fn from_reader<'de, R: Read, T: de::Deserialize<'de>>(reader: R) -> Result { T::deserialize(&mut Deserializer::new_from_reader(reader)) } pub struct Deserializer { depth: usize, reader: EventReader, peeked: Option, is_map_value: bool, } impl<'de, R: Read> Deserializer { pub fn new(reader: EventReader) -> Self { Deserializer { depth: 0, reader: reader, peeked: None, is_map_value: false, } } pub fn new_from_reader(reader: R) -> Self { let config = ParserConfig::new() .trim_whitespace(true) .whitespace_to_characters(true) .cdata_to_characters(true) .ignore_comments(true) .coalesce_characters(true); Self::new(EventReader::new_with_config(reader, config)) } fn peek(&mut self) -> Result<&XmlEvent> { if self.peeked.is_none() { self.peeked = Some(self.inner_next()?); } debug_expect!(self.peeked.as_ref(), Some(peeked) => { debug!("Peeked {:?}", peeked); Ok(peeked) }) } fn inner_next(&mut self) -> Result { loop { match self.reader.next()? { XmlEvent::StartDocument { .. } | XmlEvent::ProcessingInstruction { .. } | XmlEvent::Comment(_) => { /* skip */ } other => return Ok(other), } } } fn next(&mut self) -> Result { let next = if let Some(peeked) = self.peeked.take() { peeked } else { self.inner_next()? }; match next { XmlEvent::StartElement { .. } => { self.depth += 1; } XmlEvent::EndElement { .. } => { self.depth -= 1; } _ => {} } debug!("Fetched {:?}", next); Ok(next) } fn set_map_value(&mut self) { self.is_map_value = true; } pub fn unset_map_value(&mut self) -> bool { ::std::mem::replace(&mut self.is_map_value, false) } fn read_inner_value, T, F: FnOnce(&mut Self) -> Result>( &mut self, f: F, ) -> Result { if self.unset_map_value() { debug_expect!(self.next(), Ok(XmlEvent::StartElement { name, .. }) => { let result = f(self)?; self.expect_end_element(name)?; Ok(result) }) } else { f(self) } } fn expect_end_element(&mut self, start_name: OwnedName) -> Result<()> { expect!(self.next()?, XmlEvent::EndElement { name, .. } => { if name == start_name { Ok(()) } else { Err(Error::Custom { field: format!( "End tag didn't match the start tag <{}>", name.local_name, start_name.local_name ) }) } }) } fn prepare_parse_type>(&mut self) -> Result { if let XmlEvent::StartElement { .. } = *self.peek()? { self.set_map_value() } self.read_inner_value::(|this| { if let XmlEvent::EndElement { .. } = *this.peek()? { return Err(Error::UnexpectedToken { token: "EndElement".into(), found: "Characters".into(), }); } expect!(this.next()?, XmlEvent::Characters(s) => { return Ok(s) }) }) } } macro_rules! deserialize_type { ($deserialize:ident => $visit:ident) => { fn $deserialize>(self, visitor: V) -> Result { let value = self.prepare_parse_type::()?.parse()?; visitor.$visit(value) } } } impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer { type Error = Error; forward_to_deserialize_any! { identifier } fn deserialize_struct>( self, _name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result { self.unset_map_value(); expect!(self.next()?, XmlEvent::StartElement { name, attributes, .. } => { let map_value = visitor.visit_map(MapAccess::new( self, attributes, fields.contains(&"$value") ))?; self.expect_end_element(name)?; Ok(map_value) }) } deserialize_type!(deserialize_i8 => visit_i8); deserialize_type!(deserialize_i16 => visit_i16); deserialize_type!(deserialize_i32 => visit_i32); deserialize_type!(deserialize_i64 => visit_i64); deserialize_type!(deserialize_u8 => visit_u8); deserialize_type!(deserialize_u16 => visit_u16); deserialize_type!(deserialize_u32 => visit_u32); deserialize_type!(deserialize_u64 => visit_u64); deserialize_type!(deserialize_f32 => visit_f32); deserialize_type!(deserialize_f64 => visit_f64); fn deserialize_bool>(self, visitor: V) -> Result { if let XmlEvent::StartElement { .. } = *self.peek()? { self.set_map_value() } self.read_inner_value::(|this| { if let XmlEvent::EndElement { .. } = *this.peek()? { return visitor.visit_bool(false); } expect!(this.next()?, XmlEvent::Characters(s) => { match s.as_str() { "true" | "1" => visitor.visit_bool(true), "false" | "0" => visitor.visit_bool(false), _ => Err(de::Error::invalid_value(Unexpected::Str(&s), &"a boolean")), } }) }) } fn deserialize_char>(self, visitor: V) -> Result { self.deserialize_string(visitor) } fn deserialize_str>(self, visitor: V) -> Result { self.deserialize_string(visitor) } fn deserialize_bytes>(self, visitor: V) -> Result { self.deserialize_string(visitor) } fn deserialize_byte_buf>(self, visitor: V) -> Result { self.deserialize_string(visitor) } fn deserialize_unit>(self, visitor: V) -> Result { if let XmlEvent::StartElement { .. } = *self.peek()? { self.set_map_value() } self.read_inner_value::( |this| expect!(this.peek()?, &XmlEvent::EndElement { .. } => visitor.visit_unit()), ) } fn deserialize_unit_struct>( self, _name: &'static str, visitor: V, ) -> Result { self.deserialize_unit(visitor) } fn deserialize_newtype_struct>( self, _name: &'static str, visitor: V, ) -> Result { visitor.visit_newtype_struct(self) } fn deserialize_tuple_struct>( self, _name: &'static str, len: usize, visitor: V, ) -> Result { self.deserialize_tuple(len, visitor) } fn deserialize_tuple>(self, len: usize, visitor: V) -> Result { visitor.visit_seq(SeqAccess::new(self, Some(len))) } fn deserialize_enum>( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result { self.read_inner_value::(|this| visitor.visit_enum(EnumAccess::new(this))) } fn deserialize_string>(self, visitor: V) -> Result { if let XmlEvent::StartElement { .. } = *self.peek()? { self.set_map_value() } self.read_inner_value::(|this| { if let XmlEvent::EndElement { .. } = *this.peek()? { return visitor.visit_str(""); } expect!(this.next()?, XmlEvent::Characters(s) => { visitor.visit_string(s) }) }) } fn deserialize_seq>(self, visitor: V) -> Result { visitor.visit_seq(SeqAccess::new(self, None)) } fn deserialize_map>(self, visitor: V) -> Result { self.unset_map_value(); expect!(self.next()?, XmlEvent::StartElement { name, attributes, .. } => { let map_value = visitor.visit_map(MapAccess::new(self, attributes, false))?; self.expect_end_element(name)?; Ok(map_value) }) } fn deserialize_option>(self, visitor: V) -> Result { match *self.peek()? { XmlEvent::EndElement { .. } => visitor.visit_none(), _ => visitor.visit_some(self), } } fn deserialize_ignored_any>(self, visitor: V) -> Result { self.unset_map_value(); let depth = self.depth; loop { self.next()?; if self.depth == depth { break; } } visitor.visit_unit() } fn deserialize_any>(self, visitor: V) -> Result { match *self.peek()? { XmlEvent::StartElement { .. } => self.deserialize_map(visitor), XmlEvent::EndElement { .. } => self.deserialize_unit(visitor), _ => self.deserialize_string(visitor), } } } serde-xml-rs-0.4.0/src/de/seq.rs010064400017500001750000000035621347616117500146140ustar0000000000000000use std::io::Read; use serde::de; use xml::reader::XmlEvent; use de::Deserializer; use error::{Error, Result}; pub struct SeqAccess<'a, R: 'a + Read> { de: &'a mut Deserializer, max_size: Option, expected_name: Option, } impl<'a, R: 'a + Read> SeqAccess<'a, R> { pub fn new(de: &'a mut Deserializer, max_size: Option) -> Self { let expected_name = if de.unset_map_value() { debug_expect!(de.peek(), Ok(&XmlEvent::StartElement { ref name, .. }) => { Some(name.local_name.clone()) }) } else { None }; SeqAccess { de: de, max_size: max_size, expected_name: expected_name, } } } impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for SeqAccess<'a, R> { type Error = Error; fn next_element_seed>( &mut self, seed: T, ) -> Result> { match self.max_size.as_mut() { Some(&mut 0) => { return Ok(None); }, Some(max_size) => { *max_size -= 1; }, None => {}, } let more = match (self.de.peek()?, self.expected_name.as_ref()) { (&XmlEvent::StartElement { ref name, .. }, Some(expected_name)) => { &name.local_name == expected_name }, (&XmlEvent::EndElement { .. }, None) | (_, Some(_)) | (&XmlEvent::EndDocument { .. }, _) => false, (_, None) => true, }; if more { if self.expected_name.is_some() { self.de.set_map_value(); } seed.deserialize(&mut *self.de).map(Some) } else { Ok(None) } } fn size_hint(&self) -> Option { self.max_size } } serde-xml-rs-0.4.0/src/de/var.rs010066400017500001750000000044711357272752600146230ustar0000000000000000use std::io::Read; use serde::de::{self, Deserializer as SerdeDeserializer, IntoDeserializer}; use xml::name::OwnedName; use xml::reader::XmlEvent; use de::Deserializer; use error::{Error, Result}; pub struct EnumAccess<'a, R: 'a + Read> { de: &'a mut Deserializer, } impl<'a, R: 'a + Read> EnumAccess<'a, R> { pub fn new(de: &'a mut Deserializer) -> Self { EnumAccess { de: de } } } impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for EnumAccess<'a, R> { type Error = Error; type Variant = VariantAccess<'a, R>; fn variant_seed>( self, seed: V, ) -> Result<(V::Value, VariantAccess<'a, R>)> { let name = expect!( self.de.peek()?, &XmlEvent::Characters(ref name) | &XmlEvent::StartElement { name: OwnedName { local_name: ref name, .. }, .. } => { seed.deserialize(name.as_str().into_deserializer()) } )?; self.de.set_map_value(); Ok((name, VariantAccess::new(self.de))) } } pub struct VariantAccess<'a, R: 'a + Read> { de: &'a mut Deserializer, } impl<'a, R: 'a + Read> VariantAccess<'a, R> { pub fn new(de: &'a mut Deserializer) -> Self { VariantAccess { de: de } } } impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for VariantAccess<'a, R> { type Error = Error; fn unit_variant(self) -> Result<()> { self.de.unset_map_value(); match self.de.next()? { XmlEvent::StartElement { name, attributes, .. } => if attributes.is_empty() { self.de.expect_end_element(name) } else { Err(de::Error::invalid_length(attributes.len(), &"0")) }, XmlEvent::Characters(_) => Ok(()), _ => unreachable!(), } } fn newtype_variant_seed>(self, seed: T) -> Result { seed.deserialize(&mut *self.de) } fn tuple_variant>(self, len: usize, visitor: V) -> Result { self.de.deserialize_tuple(len, visitor) } fn struct_variant>( self, _fields: &'static [&'static str], visitor: V, ) -> Result { self.de.deserialize_map(visitor) } } serde-xml-rs-0.4.0/src/error.rs010066400017500001750000000046521362120443100145510ustar0000000000000000use serde::de::Error as DeError; use serde::ser::Error as SerError; use std::fmt::Display; use thiserror::Error; #[derive(Debug, Error)] pub enum Error { #[error("Expected token {token}, found {found}")] UnexpectedToken { token: String, found: String }, #[error("custom: {field}")] Custom { field: String }, #[error("unsupported operation: '{operation}'")] UnsupportedOperation { operation: String }, #[error("IO error: {source}")] Io { #[from] source: ::std::io::Error, }, #[error("FromUtf8Error: {source}")] FromUtf8Error { #[from] source: ::std::string::FromUtf8Error, }, #[error("ParseIntError: {source}")] ParseIntError { #[from] source: ::std::num::ParseIntError, }, #[error("ParseFloatError: {source}")] ParseFloatError { #[from] source: ::std::num::ParseFloatError, }, #[error("ParseBoolError: {source}")] ParseBoolError { #[from] source: ::std::str::ParseBoolError, }, #[error("Syntax: {source}")] Syntax { #[from] source: ::xml::reader::Error, }, } pub type Result = std::result::Result; macro_rules! expect { ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => { match $actual { $($expected)|+ => $if_ok, actual => Err($crate::Error::UnexpectedToken { token: stringify!($($expected)|+).to_string(), found: format!("{:?}",actual) }) as Result<_> } } } #[cfg(debug_assertions)] macro_rules! debug_expect { ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => { match $actual { $($expected)|+ => $if_ok, actual => panic!( "Internal error: Expected token {}, found {:?}", stringify!($($expected)|+), actual ) } } } #[cfg(not(debug_assertions))] macro_rules! debug_expect { ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => { match $actual { $($expected)|+ => $if_ok, _ => unreachable!() } } } impl DeError for Error { fn custom(msg: T) -> Self { Error::Custom { field: msg.to_string(), } } } impl SerError for Error { fn custom(msg: T) -> Self { Error::Custom { field: msg.to_string(), } } } serde-xml-rs-0.4.0/src/lib.rs010066400017500001750000000021671362120443100141650ustar0000000000000000//! //! //! # Examples //! //! ```rust //! extern crate serde; //! extern crate serde_xml_rs; //! //! #[macro_use] //! extern crate serde_derive; //! //! use serde_xml_rs::{from_str, to_string}; //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Item { //! name: String, //! source: String, //! } //! //! fn main() { //! let src = r#"BananaStore"#; //! let should_be = Item { //! name: "Banana".to_string(), //! source: "Store".to_string(), //! }; //! //! let item: Item = from_str(src).unwrap(); //! assert_eq!(item, should_be); //! //! let reserialized_item = to_string(&item).unwrap(); //! assert_eq!(src, reserialized_item); //! } //! ``` #[macro_use] extern crate log; #[macro_use] extern crate serde; extern crate xml; extern crate thiserror; #[cfg(test)] #[macro_use] extern crate serde_derive; #[macro_use] mod error; pub mod de; pub mod ser; pub use de::{from_reader, from_str, Deserializer}; pub use error::Error; pub use ser::{to_string, to_writer, Serializer}; pub use xml::reader::{EventReader, ParserConfig}; serde-xml-rs-0.4.0/src/ser/mod.rs010066400017500001750000000247421362120443100147720ustar0000000000000000use std::fmt::Display; use std::io::Write; use serde::ser::{self, Impossible, Serialize}; use self::var::{Map, Struct}; use error::{Error, Result}; mod var; /// A convenience method for serializing some object to a buffer. /// /// # Examples /// /// ```rust /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde; /// # extern crate serde_xml_rs; /// # use serde_xml_rs::to_writer; /// #[derive(Serialize)] /// struct Person { /// name: String, /// age: u32, /// } /// /// # fn main() { /// let mut buffer = Vec::new(); /// let joe = Person {name: "Joe".to_string(), age: 42}; /// /// to_writer(&mut buffer, &joe).unwrap(); /// /// let serialized = String::from_utf8(buffer).unwrap(); /// println!("{}", serialized); /// # } /// ``` pub fn to_writer(writer: W, value: &S) -> Result<()> { let mut ser = Serializer::new(writer); value.serialize(&mut ser) } /// A convenience method for serializing some object to a string. /// /// # Examples /// /// ```rust /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde; /// # extern crate serde_xml_rs; /// # use serde_xml_rs::to_string; /// #[derive(Serialize)] /// struct Person { /// name: String, /// age: u32, /// } /// /// # fn main() { /// /// let joe = Person {name: "Joe".to_string(), age: 42}; /// let serialized = to_string(&joe).unwrap(); /// println!("{}", serialized); /// # } /// ``` pub fn to_string(value: &S) -> Result { // Create a buffer and serialize our nodes into it let mut writer = Vec::with_capacity(128); to_writer(&mut writer, value)?; // We then check that the serialized string is the same as what we expect let string = String::from_utf8(writer)?; Ok(string) } /// An XML `Serializer`. pub struct Serializer where W: Write, { writer: W, } impl Serializer where W: Write, { pub fn new(writer: W) -> Self { Self { writer: writer } } fn write_primitive(&mut self, primitive: P) -> Result<()> { write!(self.writer, "{}", primitive)?; Ok(()) } fn write_wrapped(&mut self, tag: &str, value: S) -> Result<()> { write!(self.writer, "<{}>", tag)?; value.serialize(&mut *self)?; write!(self.writer, "", tag)?; Ok(()) } } #[allow(unused_variables)] impl<'w, W> ser::Serializer for &'w mut Serializer where W: Write, { type Ok = (); type Error = Error; type SerializeSeq = Impossible; type SerializeTuple = Impossible; type SerializeTupleStruct = Impossible; type SerializeTupleVariant = Impossible; type SerializeMap = Map<'w, W>; type SerializeStruct = Struct<'w, W>; type SerializeStructVariant = Impossible; fn serialize_bool(self, v: bool) -> Result { if v { write!(self.writer, "true")?; } else { write!(self.writer, "false")?; } Ok(()) } fn serialize_i8(self, v: i8) -> Result { self.write_primitive(v) } fn serialize_i16(self, v: i16) -> Result { self.write_primitive(v) } fn serialize_i32(self, v: i32) -> Result { self.write_primitive(v) } fn serialize_i64(self, v: i64) -> Result { self.write_primitive(v) } fn serialize_u8(self, v: u8) -> Result { self.write_primitive(v) } fn serialize_u16(self, v: u16) -> Result { self.write_primitive(v) } fn serialize_u32(self, v: u32) -> Result { self.write_primitive(v) } fn serialize_u64(self, v: u64) -> Result { self.write_primitive(v) } fn serialize_f32(self, v: f32) -> Result { self.write_primitive(v) } fn serialize_f64(self, v: f64) -> Result { self.write_primitive(v) } fn serialize_char(self, v: char) -> Result { self.write_primitive(v) } fn serialize_str(self, value: &str) -> Result { self.write_primitive(value) } fn serialize_bytes(self, value: &[u8]) -> Result { // TODO: I imagine you'd want to use base64 here. // Not sure how to roundtrip effectively though... Err(Error::UnsupportedOperation { operation: "serialize_bytes".to_string(), }) } fn serialize_none(self) -> Result { Ok(()) } fn serialize_some(self, value: &T) -> Result { value.serialize(self) } fn serialize_unit(self) -> Result { self.serialize_none() } fn serialize_unit_struct(self, name: &'static str) -> Result { self.write_wrapped(name, ()) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { Err(Error::UnsupportedOperation { operation: "serialize_unit_variant".to_string(), }) } fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result { Err(Error::UnsupportedOperation { operation: "serialize_newtype_struct".to_string(), }) } fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result { self.write_wrapped(variant, value) } fn serialize_seq(self, len: Option) -> Result { // TODO: Figure out how to constrain the things written to only be composites Err(Error::UnsupportedOperation { operation: "serialize_seq".to_string(), }) } fn serialize_tuple(self, len: usize) -> Result { Err(Error::UnsupportedOperation { operation: "serialize_tuple".to_string(), }) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { Err(Error::UnsupportedOperation { operation: "serialize_tuple_struct".to_string(), }) } fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Err(Error::UnsupportedOperation { operation: "serialize_tuple_variant".to_string(), }) } fn serialize_map(self, len: Option) -> Result { Ok(Map::new(self)) } fn serialize_struct(self, name: &'static str, len: usize) -> Result { write!(self.writer, "<{}>", name)?; Ok(Struct::new(self, name)) } fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Err(Error::UnsupportedOperation { operation: "Result".to_string(), }) } } #[cfg(test)] mod tests { use super::*; use serde::ser::{SerializeMap, SerializeStruct}; use serde::Serializer as SerSerializer; #[test] fn test_serialize_bool() { let inputs = vec![(true, "true"), (false, "false")]; for (src, should_be) in inputs { let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); ser.serialize_bool(src).unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, should_be); } } #[test] fn test_start_serialize_struct() { let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); let _ = ser.serialize_struct("foo", 0).unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, ""); } #[test] fn test_serialize_struct_field() { let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); let mut struct_ser = Struct::new(&mut ser, "baz"); struct_ser.serialize_field("foo", "bar").unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, "bar"); } #[test] fn test_serialize_struct() { #[derive(Serialize)] struct Person { name: String, age: u32, } let bob = Person { name: "Bob".to_string(), age: 42, }; let should_be = "Bob42"; let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); bob.serialize(&mut ser).unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, should_be); } #[test] fn test_serialize_map_entries() { let should_be = "Bob5"; let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); let mut map = Map::new(&mut ser); map.serialize_entry("name", "Bob").unwrap(); map.serialize_entry("age", "5").unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, should_be); } #[test] fn test_serialize_enum() { #[derive(Serialize)] #[allow(dead_code)] enum Node { Boolean(bool), Number(f64), String(String), } let mut buffer = Vec::new(); let should_be = "true"; { let mut ser = Serializer::new(&mut buffer); let node = Node::Boolean(true); node.serialize(&mut ser).unwrap(); } let got = String::from_utf8(buffer).unwrap(); assert_eq!(got, should_be); } #[test] #[ignore] fn serialize_a_list() { let inputs = vec![1, 2, 3, 4]; let mut buffer = Vec::new(); { let mut ser = Serializer::new(&mut buffer); inputs.serialize(&mut ser).unwrap(); } let got = String::from_utf8(buffer).unwrap(); println!("{}", got); panic!(); } } serde-xml-rs-0.4.0/src/ser/var.rs010064400017500001750000000045611347616117500150150ustar0000000000000000use std::io::Write; use serde::ser::{self, Serialize}; use ser::Serializer; use error::{Error, Result}; /// An implementation of `SerializeMap` for serializing to XML. pub struct Map<'w, W> where W: 'w + Write, { parent: &'w mut Serializer, } impl<'w, W> Map<'w, W> where W: 'w + Write, { pub fn new(parent: &'w mut Serializer) -> Map<'w, W> { Map { parent } } } impl<'w, W> ser::SerializeMap for Map<'w, W> where W: 'w + Write, { type Ok = (); type Error = Error; fn serialize_key(&mut self, _: &T) -> Result<()> { panic!("impossible to serialize the key on its own, please use serialize_entry()") } fn serialize_value(&mut self, value: &T) -> Result<()> { value.serialize(&mut *self.parent) } fn end(self) -> Result { Ok(()) } fn serialize_entry( &mut self, key: &K, value: &V, ) -> Result<()> { // TODO: Is it possible to ensure our key is never a composite type? // Anything which isn't a "primitive" would lead to malformed XML here... write!(self.parent.writer, "<")?; key.serialize(&mut *self.parent)?; write!(self.parent.writer, ">")?; value.serialize(&mut *self.parent)?; write!(self.parent.writer, "")?; Ok(()) } } /// An implementation of `SerializeStruct` for serializing to XML. pub struct Struct<'w, W> where W: 'w + Write, { parent: &'w mut Serializer, name: &'w str, } impl<'w, W> Struct<'w, W> where W: 'w + Write, { pub fn new(parent: &'w mut Serializer, name: &'w str) -> Struct<'w, W> { Struct { parent, name } } } impl<'w, W> ser::SerializeStruct for Struct<'w, W> where W: 'w + Write, { type Ok = (); type Error = Error; fn serialize_field( &mut self, key: &'static str, value: &T, ) -> Result<()> { write!(self.parent.writer, "<{}>", key)?; value.serialize(&mut *self.parent)?; write!(self.parent.writer, "", key)?; Ok(()) } fn end(self) -> Result { write!(self.parent.writer, "", self.name).map_err(|e| e.into()) } } serde-xml-rs-0.4.0/tests/failures.rs010064400017500001750000000021111344366255700156120ustar0000000000000000#[macro_use] extern crate serde_derive; extern crate serde_xml_rs; #[macro_use] extern crate log; extern crate simple_logger; use serde_xml_rs::from_str; #[derive(Debug, Deserialize, PartialEq)] struct Item { name: String, source: String, } #[test] fn simple_struct_from_attributes_should_fail() { let _ = simple_logger::init(); let s = r##" = from_str(s); match item { Ok(_) => assert!(false), Err(e) => { info!("simple_struct_from_attributes_should_fail(): {}", e); assert!(true) } } } #[test] fn multiple_roots_attributes_should_fail() { let _ = simple_logger::init(); let s = r##" "##; let item: Result, _> = from_str(s); match item { Ok(_) => assert!(false), Err(e) => { info!("multiple_roots_attributes_should_fail(): {}", e); assert!(true) } } } serde-xml-rs-0.4.0/tests/migrated.rs010066400017500001750000000654631362120443100155760ustar0000000000000000#[macro_use] extern crate serde_derive; extern crate log; extern crate simple_logger; extern crate serde; extern crate serde_xml_rs; use std::fmt::Debug; use serde::{de, ser}; use serde_xml_rs::{from_str, Error}; #[derive(PartialEq, Debug, Serialize, Deserialize)] enum Animal { Dog, Frog(String), Ant(Simple), Cat { age: usize, name: String }, } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Simple { a: (), b: usize, c: String, d: Option, } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Inner { a: (), b: (usize, String, i8), c: Vec, } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Outer { inner: Option, } fn test_parse_ok<'de, 'a, T>(errors: &[(&'a str, T)]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>, { for &(s, ref value) in errors { let v: T = from_str(s).unwrap(); assert_eq!(v, *value); // // Make sure we can deserialize into an `Element`. // let xml_value: Element = from_str(s).unwrap(); // // Make sure we can deserialize from an `Element`. // let v: T = from_value(xml_value.clone()).unwrap(); // assert_eq!(v, *value); } } fn test_parse_err<'de, 'a, T>(errors: &[&'a str]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>, { for &s in errors { assert!(match from_str::(s) { Err(Error::Syntax { source: _ }) => true, _ => false, }); } } fn test_parse_invalid<'de, 'a, T>(errors: &[&'a str]) where T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>, { for &s in errors { assert!(match from_str::(s) { Err(_) => true, _ => false, }); } } #[test] fn test_namespaces() { let _ = simple_logger::init(); #[derive(PartialEq, Serialize, Deserialize, Debug)] struct Envelope { subject: String, } let s = r#" Reference rates "#; test_parse_ok(&[( s, Envelope { subject: "Reference rates".to_string(), }, )]); } #[test] #[ignore] // FIXME fn test_doctype() { let _ = simple_logger::init(); #[derive(PartialEq, Serialize, Deserialize, Debug)] struct Envelope { subject: String, } test_parse_ok(&[ ( r#" Reference rates "#, Envelope { subject: "Reference rates".to_string(), }, ), ( r#" Reference rates "#, Envelope { subject: "Reference rates".to_string(), }, ), ( r#" ] > Reference rates "#, Envelope { subject: "Reference rates".to_string(), }, ), ]); } #[test] fn test_doctype_fail() { let _ = simple_logger::init(); #[derive(PartialEq, Serialize, Deserialize, Debug)] struct Envelope { subject: String, } test_parse_err::(&[ r#" > Reference rates "#, r#" Reference rates ]> "#, ]) } #[test] #[ignore] // FIXME fn test_forwarded_namespace() { #[derive(PartialEq, Serialize, Deserialize, Debug)] struct Graphml { #[serde(rename = "xsi:schemaLocation")] schema_location: String, } let s = r#" "#; test_parse_ok(&[( s, Graphml { schema_location: "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd" .to_string(), }, )]); } #[test] fn test_parse_string() { let _ = simple_logger::init(); test_parse_ok(&[ ( "This is a String", "This is a String".to_string(), ), ("", "".to_string()), (" ", "".to_string()), ("<boom/>", "".to_string()), ("", "♫".to_string()), ("", "♫".to_string()), ( "]]>♫", "♫♫".to_string(), ), ]); } #[test] #[ignore] // FIXME fn test_parse_string_not_trim() { let _ = simple_logger::init(); test_parse_ok(&[(" ", " ".to_string())]); } #[test] #[ignore] // FIXME fn test_parse_enum() { use self::Animal::*; let _ = simple_logger::init(); test_parse_ok(&[ ("", Dog), ( "Quak", Frog("Quak".to_string()), ), ( "bla15Foo", Ant(Simple { a: (), b: 15, c: "bla".to_string(), d: Some("Foo".to_string()), }), ), ( "bla15", Ant(Simple { a: (), b: 15, c: "bla".to_string(), d: None, }), ), ( "42Shere Khan", Cat { age: 42, name: "Shere Khan".to_string(), }, ), ]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Helper { x: Animal, } test_parse_ok(&[ ("", Helper { x: Dog }), ( "Quak", Helper { x: Frog("Quak".to_string()), }, ), ( " 42 Shere Khan ", Helper { x: Cat { age: 42, name: "Shere Khan".to_string(), }, }, ), ]); } #[test] fn test_parse_i64() { let _ = simple_logger::init(); test_parse_ok(&[ ("0", 0), ("-2", -2), ("-1234", -1234), (" -1234 ", -1234), ]); } #[test] fn test_parse_u64() { let _ = simple_logger::init(); test_parse_ok(&[ ("0", 0), ("1234", 1234), (" 1234 ", 1234), ]); } #[test] fn test_parse_bool_element() { let _ = simple_logger::init(); test_parse_ok(&[ ("true", true), ("false", false), (" true ", true), (" false ", false), ("1", true), ("0", false), ]); test_parse_invalid::(&["verum"]); } #[test] fn test_parse_bool_attribute() { #[derive(PartialEq, Debug, Deserialize, Serialize)] struct Dummy { foo: bool, } let _ = simple_logger::init(); test_parse_ok(&[ ("", Dummy { foo: true }), ("", Dummy { foo: false }), ("", Dummy { foo: true }), ("", Dummy { foo: false }), ]); test_parse_invalid::(&[ "", "", "", "", "", ]); } #[test] fn test_parse_unit() { let _ = simple_logger::init(); test_parse_ok(&[("", ())]); } #[test] fn test_parse_f64() { let _ = simple_logger::init(); test_parse_ok(&[ ("3.0", 3.0f64), ("3.1", 3.1), ("-1.2", -1.2), ("0.4", 0.4), ("0.4e5", 0.4e5), ("0.4e15", 0.4e15), ("0.4e-01", 0.4e-01), // precision troubles (" 0.4e-01 ", 0.4e-01), ]); } #[test] fn test_parse_struct() { let _ = simple_logger::init(); test_parse_ok(&[ ( " abc 2 ", Simple { a: (), b: 2, c: "abc".to_string(), d: None, }, ), ( " abc 2 ", Simple { a: (), b: 2, c: "abc".to_string(), d: None, }, ), ( " abc 2 ", Simple { a: (), b: 2, c: "abc".to_string(), d: Some("Foo".to_string()), }, ), ]); } #[test] fn test_option() { let _ = simple_logger::init(); test_parse_ok(&[ ("", Some("".to_string())), ("", Some("".to_string())), (" ", Some("".to_string())), ("42", Some("42".to_string())), ]); } #[test] #[ignore] // FIXME fn test_option_not_trim() { let _ = simple_logger::init(); test_parse_ok(&[(" ", Some(" ".to_string()))]); } #[test] fn test_amoskvin() { let _ = simple_logger::init(); #[derive(Debug, Deserialize, PartialEq, Serialize)] struct Root { foo: Vec, } #[derive(Debug, Deserialize, PartialEq, Serialize)] struct Foo { a: String, b: Option, } test_parse_ok(&[( " Hello World Hi ", Root { foo: vec![ Foo { a: "Hello".to_string(), b: Some("World".to_string()), }, Foo { a: "Hi".to_string(), b: None, }, ], }, )]); } #[test] #[ignore] // FIXME fn test_nicolai86() { let _ = simple_logger::init(); #[derive(Serialize, Deserialize, PartialEq, Debug)] struct TheSender { name: String, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct CurrencyCube { currency: String, rate: String, } #[derive(Serialize, Deserialize, PartialEq, Debug)] #[allow(non_snake_case)] struct InnerCube { Cube: Vec, } #[derive(Serialize, Deserialize, PartialEq, Debug)] #[allow(non_snake_case)] struct OuterCube { Cube: Vec, } #[derive(Serialize, Deserialize, PartialEq, Debug)] #[allow(non_snake_case)] struct Envelope { subject: String, Sender: TheSender, Cube: OuterCube, } test_parse_ok(&[ ( r#" Reference rates European Central Bank "#, Envelope { subject: "Reference rates".to_string(), Sender: TheSender { name: "European Central Bank".to_string(), }, Cube: OuterCube { Cube: vec![] }, }, ), ( r#" Reference rates European Central Bank "#, Envelope { subject: "Reference rates".to_string(), Sender: TheSender { name: "European Central Bank".to_string(), }, Cube: OuterCube { Cube: vec![InnerCube { Cube: vec![ CurrencyCube { currency: "GBP".to_string(), rate: "0.81725".to_string(), }, CurrencyCube { currency: "Latinum".to_string(), rate: "999999".to_string(), }, ], }], }, }, ), ]); } #[test] fn test_hugo_duncan2() { let _ = simple_logger::init(); let s = r#" 8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1 vpc-ba0d18d8 available "#; #[derive(PartialEq, Debug, Serialize, Deserialize)] #[allow(non_snake_case)] struct VpcSet { vpcId: String, state: String, } #[derive(PartialEq, Debug, Serialize)] struct ItemVec(Vec); impl<'de, T: de::Deserialize<'de>> de::Deserialize<'de> for ItemVec { fn deserialize(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Helper { item: Vec, } let h: Helper<_> = de::Deserialize::deserialize(deserializer)?; Ok(ItemVec(h.item)) } } #[derive(PartialEq, Debug, Serialize, Deserialize)] #[allow(non_snake_case)] struct DescribeVpcsResponse { requestId: String, vpcSet: ItemVec, } test_parse_ok(&[( s, DescribeVpcsResponse { requestId: "8d521e9a-509e-4ef6-bbb7-9f1ac0d49cd1".to_string(), vpcSet: ItemVec(vec![VpcSet { vpcId: "vpc-ba0d18d8".to_string(), state: "available".to_string(), }]), }, )]); } #[test] fn test_hugo_duncan() { let _ = simple_logger::init(); let s = " 9474f558-10a5-42e8-84d1-f9ee181fe943 "; #[derive(PartialEq, Debug, Serialize, Deserialize)] #[allow(non_snake_case)] struct DescribeInstancesResponse { requestId: String, reservationSet: (), } test_parse_ok(&[( s, DescribeInstancesResponse { requestId: "9474f558-10a5-42e8-84d1-f9ee181fe943".to_string(), reservationSet: (), }, )]); } #[test] fn test_parse_xml_value() { let _ = simple_logger::init(); #[derive(Eq, Debug, PartialEq, Deserialize, Serialize)] struct Test { #[serde(rename = "$value")] myval: String, } test_parse_ok(&[( "abc", Test { myval: "abc".to_string(), }, )]); } #[test] #[ignore] // FIXME fn test_parse_complexstruct() { let _ = simple_logger::init(); test_parse_ok(&[ ( " 2 boom 88 ", Outer { inner: Some(Inner { a: (), b: (2, "boom".to_string(), 88), c: vec![], }), }, ), ( " abc xyz 2 boom 88 ", Outer { inner: Some(Inner { a: (), b: (2, "boom".to_string(), 88), c: vec!["abc".to_string(), "xyz".to_string()], }), }, ), ("", Outer { inner: None }), ]); } #[test] fn test_parse_attributes() { let _ = simple_logger::init(); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct A { a1: String, #[serde(rename = "$value")] a2: i32, } test_parse_ok(&[( r#"42"#, A { a1: "What is the answer to the ultimate question?".to_string(), a2: 42, }, )]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct B { b1: String, b2: i32, } test_parse_ok(&[( r#""#, B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, )]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct C { c1: B, } test_parse_ok(&[ ( r#""#, C { c1: B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, }, ), ( r#" "#, C { c1: B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, }, ), ( r#" "#, C { c1: B { b1: "What is the answer to the ultimate question?".to_string(), b2: 42, }, }, ), ]); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct D { d1: Option, } test_parse_ok(&[( r#"42"#, D { d1: Some(A { a1: "What is the answer to the ultimate question?".to_string(), a2: 42, }), }, )]); } #[test] #[ignore] // FIXME fn test_parse_hierarchies() { let _ = simple_logger::init(); #[derive(PartialEq, Debug, Serialize, Deserialize)] struct A { a1: String, a2: (String, String), } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct B { b1: A, b2: (A, A), } #[derive(PartialEq, Debug, Serialize, Deserialize)] struct C { c1: B, c2: Vec, } test_parse_ok(&[ ( " No Maybe Yes Red Green Blue London Berlin Paris ", C { c1: B { b1: A { a1: "No".to_string(), a2: ("Maybe".to_string(), "Yes".to_string()), }, b2: ( A { a1: "Red".to_string(), a2: ("Green".to_string(), "Blue".to_string()), }, A { a1: "London".to_string(), a2: ("Berlin".to_string(), "Paris".to_string()), }, ), }, c2: vec![], }, ), ( " Green Blue Red Berlin Paris London Maybe Yes No ", C { c1: B { b1: A { a1: "No".to_string(), a2: ("Maybe".to_string(), "Yes".to_string()), }, b2: ( A { a1: "Red".to_string(), a2: ("Green".to_string(), "Blue".to_string()), }, A { a1: "London".to_string(), a2: ("Berlin".to_string(), "Paris".to_string()), }, ), }, c2: vec![], }, ), ]); } #[test] fn unknown_field() { #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)] struct A { other: Vec, } #[derive(Deserialize, Debug, PartialEq, Eq, Serialize)] struct Other { d: i32, } test_parse_ok(&[( " 5 6 ", A { other: vec![Other { d: 6 }], }, )]); } // #[test] // fn eoz() { // use std::io::Read; // let mut file = std::fs::File::open("Report_test.2.xml").unwrap(); // let mut s = String::new(); // file.read_to_string(&mut s).unwrap(); // let _xml_value: Element = from_str(&s).unwrap(); // } #[test] fn test_parse_unfinished() { test_parse_err::(&[" abc 2 "]); } #[test] fn test_things_qc_found() { test_parse_err::(&["<\u{0}:/"]); } #[test] fn futile() { let _ = simple_logger::init(); #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] struct Object { id: u8, name: String, x: u8, y: u8, width: u8, height: u8, ellipse: Option<()>, } test_parse_ok(&[ ( r###" "###, Object { id: 11, name: "testEllipse".to_owned(), x: 102, y: 38, width: 21, height: 14, ellipse: Some(()), }, ), ( r###" "###, Object { id: 11, name: "testEllipse".to_owned(), x: 102, y: 38, width: 21, height: 14, ellipse: None, }, ), ]); } #[test] fn futile2() { let _ = simple_logger::init(); #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] struct Null; #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] struct Object { field: Option, }; #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] struct Stuff { stuff_field: Option, }; test_parse_ok(&[ ( r###" "###, Object { field: Some(Null) }, ), ( r###" "###, Object { field: None }, ), ]); test_parse_ok(&[ ( r###" "###, Stuff { stuff_field: Some(Object { field: None }), }, ), ( r###" "###, Stuff { stuff_field: Some(Object { field: Some(Null) }), }, ), ( r###" "###, Stuff { stuff_field: None }, ), ( r###" "###, Stuff { stuff_field: None }, ), ]); } #[test] fn newtype_struct() { #[derive(PartialEq, Debug, Serialize, Deserialize)] struct Wrapper(String); test_parse_ok(&[( r###"Content"###, Wrapper("Content".into()), )]); } serde-xml-rs-0.4.0/tests/readme.rs010064400017500001750000000001351344366255700152410ustar0000000000000000extern crate docmatic; #[test] fn test_readme() { docmatic::assert_file("README.md"); } serde-xml-rs-0.4.0/tests/round_trip.rs010064400017500001750000000033131347616117500161660ustar0000000000000000#[macro_use] extern crate serde_derive; extern crate serde_xml_rs; use serde_xml_rs::{from_str, to_string}; #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Item { name: String, source: String, } #[derive(Debug, Serialize, Deserialize, PartialEq)] enum Node { Boolean(bool), Identifier { value: String, index: u32 }, EOF, } #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Nodes { #[serde(rename = "$value")] items: Vec, } #[test] fn basic_struct() { let src = r#"BananaStore"#; let should_be = Item { name: "Banana".to_string(), source: "Store".to_string(), }; let item: Item = from_str(src).unwrap(); assert_eq!(item, should_be); let reserialized_item = to_string(&item).unwrap(); assert_eq!(src, reserialized_item); } #[test] #[ignore] fn round_trip_list_of_enums() { // Construct some inputs let nodes = Nodes { items: vec![ Node::Boolean(true), Node::Identifier { value: "foo".to_string(), index: 5, }, Node::EOF, ], }; let should_be = r#" true foo 5 "#; let serialized_nodes = to_string(&nodes).unwrap(); assert_eq!(serialized_nodes, should_be); // Then turn it back into a `Nodes` struct and make sure it's the same // as the original let deserialized_nodes: Nodes = from_str(serialized_nodes.as_str()).unwrap(); assert_eq!(deserialized_nodes, nodes); } serde-xml-rs-0.4.0/tests/test.rs010066400017500001750000000062521362120443100147500ustar0000000000000000#[macro_use] extern crate serde_derive; extern crate serde_xml_rs; extern crate log; extern crate simple_logger; use serde_xml_rs::from_str; #[derive(Debug, Deserialize, PartialEq)] struct Item { name: String, source: String, } #[test] fn simple_struct_from_attributes() { let _ = simple_logger::init(); let s = r##" "##; let item: Item = from_str(s).unwrap(); assert_eq!( item, Item { name: "hello".to_string(), source: "world.rs".to_string(), } ); } #[test] fn multiple_roots_attributes() { let _ = simple_logger::init(); let s = r##" "##; let item: Vec = from_str(s).unwrap(); assert_eq!( item, vec![ Item { name: "hello".to_string(), source: "world.rs".to_string(), }, Item { name: "hello".to_string(), source: "world.rs".to_string(), }, ] ); } #[test] fn simple_struct_from_attribute_and_child() { let _ = simple_logger::init(); let s = r##" world.rs "##; let item: Item = from_str(s).unwrap(); assert_eq!( item, Item { name: "hello".to_string(), source: "world.rs".to_string(), } ); } #[derive(Debug, Deserialize, PartialEq)] struct Project { name: String, #[serde(rename = "item", default)] items: Vec, } #[test] fn nested_collection() { let _ = simple_logger::init(); let s = r##" "##; let project: Project = from_str(s).unwrap(); assert_eq!( project, Project { name: "my_project".to_string(), items: vec![ Item { name: "hello1".to_string(), source: "world1.rs".to_string(), }, Item { name: "hello2".to_string(), source: "world2.rs".to_string(), }, ], } ); } #[derive(Debug, Deserialize, PartialEq)] enum MyEnum { A(String), B { name: String, flag: bool }, C, } #[derive(Debug, Deserialize, PartialEq)] struct MyEnums { #[serde(rename = "$value")] items: Vec, } #[test] fn collection_of_enums() { let _ = simple_logger::init(); let s = r##" test "##; let project: MyEnums = from_str(s).unwrap(); assert_eq!( project, MyEnums { items: vec![ MyEnum::A("test".to_string()), MyEnum::B { name: "hello".to_string(), flag: true, }, MyEnum::C, ], } ); } serde-xml-rs-0.4.0/.cargo_vcs_info.json0000644000000001121363211621600134500ustar00{ "git": { "sha1": "bea4f9afb0c42fac8b489283ea4bdc7e1ff9cd05" } }