mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 23:02:31 +00:00
xml: Implement XmlDeserialize for values
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
use std::convert::Infallible;
|
use quick_xml::events::{BytesStart, Event};
|
||||||
use std::num::ParseIntError;
|
use std::num::{ParseFloatError, ParseIntError};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::{convert::Infallible, io::BufRead};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::XmlDeError;
|
use crate::{XmlDeError, XmlDeserialize};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ParseValueError {
|
pub enum ParseValueError {
|
||||||
@@ -11,6 +12,8 @@ pub enum ParseValueError {
|
|||||||
Infallible(#[from] Infallible),
|
Infallible(#[from] Infallible),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ParseIntError(#[from] ParseIntError),
|
ParseIntError(#[from] ParseIntError),
|
||||||
|
#[error(transparent)]
|
||||||
|
ParseFloatError(#[from] ParseFloatError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Value: Sized {
|
pub trait Value: Sized {
|
||||||
@@ -18,16 +21,60 @@ pub trait Value: Sized {
|
|||||||
fn deserialize(val: &str) -> Result<Self, XmlDeError>;
|
fn deserialize(val: &str) -> Result<Self, XmlDeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, T: FromStr<Err = E> + ToString> Value for T
|
macro_rules! impl_value_parse {
|
||||||
where
|
($t:ty) => {
|
||||||
ParseValueError: From<E>,
|
impl Value for $t {
|
||||||
{
|
|
||||||
fn serialize(&self) -> String {
|
fn serialize(&self) -> String {
|
||||||
self.to_string()
|
self.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(val: &str) -> Result<Self, XmlDeError> {
|
fn deserialize(val: &str) -> Result<Self, XmlDeError> {
|
||||||
val.parse()
|
val.parse()
|
||||||
.map_err(ParseValueError::from)
|
.map_err(ParseValueError::from)
|
||||||
.map_err(XmlDeError::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<T: Value> XmlDeserialize for T {
|
||||||
|
fn deserialize<R: BufRead>(
|
||||||
|
reader: &mut quick_xml::NsReader<R>,
|
||||||
|
start: &BytesStart,
|
||||||
|
empty: bool,
|
||||||
|
) -> Result<Self, XmlDeError> {
|
||||||
|
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")),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<Self as Value>::deserialize(&string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -229,3 +229,27 @@ fn test_struct_unparsed() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.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#"
|
||||||
|
<document>
|
||||||
|
<href>/asd</href>
|
||||||
|
</document>
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
doc,
|
||||||
|
Document {
|
||||||
|
href: "/asd".to_owned()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user