use std::{io::Read, marker::PhantomData}; use log::trace; use serde::de::{self, Unexpected}; use serde::forward_to_deserialize_any; use xml::name::OwnedName; use xml::reader::{EventReader, ParserConfig, XmlEvent}; use self::buffer::{BufferedXmlReader, ChildXmlBuffer, RootXmlBuffer}; use self::map::MapAccess; use self::seq::SeqAccess; use self::var::EnumAccess; use crate::error::{Error, Result}; use crate::{debug_expect, expect}; mod buffer; mod map; mod seq; mod var; /// A convenience method for deserialize some object from a string. /// /// ```rust /// # use serde::{Deserialize, Serialize}; /// # 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 /// # use serde::Deserialize; /// # 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)) } type RootDeserializer = Deserializer>; type ChildDeserializer<'parent, R> = Deserializer>; pub struct Deserializer< R: Read, // Kept as type param to avoid type signature breaking-change B: BufferedXmlReader = RootXmlBuffer, > { /// XML document nested element depth depth: usize, buffered_reader: B, is_map_value: bool, non_contiguous_seq_elements: bool, marker: PhantomData, } impl<'de, R: Read> RootDeserializer { pub fn new(reader: EventReader) -> Self { let buffered_reader = RootXmlBuffer::new(reader); Deserializer { buffered_reader, depth: 0, is_map_value: false, non_contiguous_seq_elements: false, marker: PhantomData, } } 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)) } /// Configures whether the deserializer should search all sibling elements when building a /// sequence. Not required if all XML elements for sequences are adjacent. Disabled by /// default. Enabling this option may incur additional memory usage. /// /// ```rust /// # use serde::Deserialize; /// # use serde_xml_rs::from_reader; /// #[derive(Debug, Deserialize, PartialEq)] /// struct Foo { /// bar: Vec, /// baz: String, /// } /// # fn main() { /// let s = r##" /// /// 1 /// 2 /// Hello, world /// 3 /// 4 /// /// "##; /// let mut de = serde_xml_rs::Deserializer::new_from_reader(s.as_bytes()) /// .non_contiguous_seq_elements(true); /// let foo = Foo::deserialize(&mut de).unwrap(); /// assert_eq!(foo, Foo { bar: vec![1, 2, 3, 4], baz: "Hello, world".to_string()}); /// # } /// ``` pub fn non_contiguous_seq_elements(mut self, set: bool) -> Self { self.non_contiguous_seq_elements = set; self } } impl<'de, R: Read, B: BufferedXmlReader> Deserializer { fn child<'a>(&'a mut self) -> Deserializer> { let Deserializer { buffered_reader, depth, is_map_value, non_contiguous_seq_elements, .. } = self; Deserializer { buffered_reader: buffered_reader.child_buffer(), depth: *depth, is_map_value: *is_map_value, non_contiguous_seq_elements: *non_contiguous_seq_elements, marker: PhantomData, } } /// Gets the next XML event without advancing the cursor. fn peek(&mut self) -> Result<&XmlEvent> { let peeked = self.buffered_reader.peek()?; trace!("Peeked {:?}", peeked); Ok(peeked) } /// Gets the XML event at the cursor and advances the cursor. fn next(&mut self) -> Result { let next = self.buffered_reader.next()?; match next { XmlEvent::StartElement { .. } => { self.depth += 1; } XmlEvent::EndElement { .. } => { self.depth -= 1; } _ => {} } trace!("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) } /// If `self.is_map_value`: Performs the read operations specified by `f` on the inner content of an XML element. /// `f` is expected to consume the entire inner contents of the element. The cursor will be moved to the end of the /// element. /// If `!self.is_map_value`: `f` will be performed without additional checks/advances for an outer XML element. 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, B: BufferedXmlReader> 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 { let child_deserializer = self.child(); visitor.visit_seq(SeqAccess::new(child_deserializer, 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 { let child_deserializer = self.child(); visitor.visit_seq(SeqAccess::new(child_deserializer, 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), } } }