diff --git a/crates/xml/src/value.rs b/crates/xml/src/value.rs index 2d26820..49a6c6a 100644 --- a/crates/xml/src/value.rs +++ b/crates/xml/src/value.rs @@ -1,9 +1,10 @@ -use std::convert::Infallible; -use std::num::ParseIntError; +use quick_xml::events::{BytesStart, Event}; +use std::num::{ParseFloatError, ParseIntError}; use std::str::FromStr; +use std::{convert::Infallible, io::BufRead}; use thiserror::Error; -use crate::XmlDeError; +use crate::{XmlDeError, XmlDeserialize}; #[derive(Debug, Error)] pub enum ParseValueError { @@ -11,6 +12,8 @@ pub enum ParseValueError { Infallible(#[from] Infallible), #[error(transparent)] ParseIntError(#[from] ParseIntError), + #[error(transparent)] + ParseFloatError(#[from] ParseFloatError), } pub trait Value: Sized { @@ -18,16 +21,60 @@ pub trait Value: Sized { fn deserialize(val: &str) -> Result; } -impl + ToString> Value for T -where - ParseValueError: From, -{ - fn serialize(&self) -> String { - self.to_string() - } - fn deserialize(val: &str) -> Result { - val.parse() - .map_err(ParseValueError::from) - .map_err(XmlDeError::from) +macro_rules! impl_value_parse { + ($t:ty) => { + impl Value for $t { + fn serialize(&self) -> String { + self.to_string() + } + + fn deserialize(val: &str) -> Result { + val.parse() + .map_err(ParseValueError::from) + .map_err(XmlDeError::from) + } + } + }; +} + +impl_value_parse!(String); +impl_value_parse!(i8); +impl_value_parse!(u8); +impl_value_parse!(i16); +impl_value_parse!(u16); +impl_value_parse!(f32); +impl_value_parse!(i32); +impl_value_parse!(u32); +impl_value_parse!(f64); +impl_value_parse!(i64); +impl_value_parse!(u64); +impl_value_parse!(isize); +impl_value_parse!(usize); + +impl XmlDeserialize for T { + fn deserialize( + reader: &mut quick_xml::NsReader, + start: &BytesStart, + empty: bool, + ) -> Result { + let mut string = String::new(); + + if !empty { + let mut buf = Vec::new(); + loop { + match reader.read_event_into(&mut buf)? { + Event::Text(text) => { + if !start.is_empty() { + // Content already written + return Err(XmlDeError::UnsupportedEvent("todo")); + } + string = String::from_utf8_lossy(text.as_ref()).to_string(); + } + _ => return Err(XmlDeError::UnsupportedEvent("todo")), + }; + } + } + + ::deserialize(&string) } } diff --git a/crates/xml/tests/de_struct.rs b/crates/xml/tests/de_struct.rs index a6aa9bd..6f79b94 100644 --- a/crates/xml/tests/de_struct.rs +++ b/crates/xml/tests/de_struct.rs @@ -229,3 +229,27 @@ fn test_struct_unparsed() { ) .unwrap(); } + +#[test] +fn test_xml_values() { + #[derive(XmlDeserialize, XmlRootTag, PartialEq, Debug)] + #[xml(root = b"document", ns_strict)] + struct Document { + href: String, + } + + let doc = Document::parse_str( + r#" + + /asd + + "#, + ) + .unwrap(); + assert_eq!( + doc, + Document { + href: "/asd".to_owned() + } + ); +}