blob: 94077c55c70d73b2f135c1eaedeb292914c0f7e1 [file] [log] [blame]
use 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##"<item name="hello" source="world.rs" />"##;
/// 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<T> {
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##"<item name="hello" source="world.rs" />"##;
/// 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> {
T::deserialize(&mut Deserializer::new_from_reader(reader))
}
pub struct Deserializer<R: Read> {
depth: usize,
reader: EventReader<R>,
peeked: Option<XmlEvent>,
is_map_value: bool,
}
impl<'de, R: Read> Deserializer<R> {
pub fn new(reader: EventReader<R>) -> 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<XmlEvent> {
loop {
match self.reader.next()? {
XmlEvent::StartDocument { .. }
| XmlEvent::ProcessingInstruction { .. }
| XmlEvent::Whitespace { .. }
| XmlEvent::Comment(_) => { /* skip */ }
other => return Ok(other),
}
}
}
fn next(&mut self) -> Result<XmlEvent> {
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<V: de::Visitor<'de>, T, F: FnOnce(&mut Self) -> Result<T>>(
&mut self,
f: F,
) -> Result<T> {
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<V: de::Visitor<'de>>(&mut self) -> Result<String> {
if let XmlEvent::StartElement { .. } = *self.peek()? {
self.set_map_value()
}
self.read_inner_value::<V, String, _>(|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<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let value = self.prepare_parse_type::<V>()?.parse()?;
visitor.$visit(value)
}
}
}
impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
type Error = Error;
forward_to_deserialize_any! {
identifier
}
fn deserialize_struct<V: de::Visitor<'de>>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
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<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let XmlEvent::StartElement { .. } = *self.peek()? {
self.set_map_value()
}
self.read_inner_value::<V, V::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<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_string(visitor)
}
fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_string(visitor)
}
fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_string(visitor)
}
fn deserialize_byte_buf<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_string(visitor)
}
fn deserialize_unit<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let XmlEvent::StartElement { .. } = *self.peek()? {
self.set_map_value()
}
self.read_inner_value::<V, V::Value, _>(
|this| expect!(this.peek()?, &XmlEvent::EndElement { .. } => visitor.visit_unit()),
)
}
fn deserialize_unit_struct<V: de::Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: de::Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_newtype_struct(self)
}
fn deserialize_tuple_struct<V: de::Visitor<'de>>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value> {
self.deserialize_tuple(len, visitor)
}
fn deserialize_tuple<V: de::Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
visitor.visit_seq(SeqAccess::new(self, Some(len)))
}
fn deserialize_enum<V: de::Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
self.read_inner_value::<V, V::Value, _>(|this| visitor.visit_enum(EnumAccess::new(this)))
}
fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let XmlEvent::StartElement { .. } = *self.peek()? {
self.set_map_value()
}
self.read_inner_value::<V, V::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<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_seq(SeqAccess::new(self, None))
}
fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
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<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match *self.peek()? {
XmlEvent::EndElement { .. } => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_ignored_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.unset_map_value();
let depth = self.depth;
loop {
self.next()?;
if self.depth == depth {
break;
}
}
visitor.visit_unit()
}
fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match *self.peek()? {
XmlEvent::StartElement { .. } => self.deserialize_map(visitor),
XmlEvent::EndElement { .. } => self.deserialize_unit(visitor),
_ => self.deserialize_string(visitor),
}
}
}