mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 12:52:27 +00:00
some changes to rustical_xml
This commit is contained in:
@@ -10,6 +10,8 @@ pub enum XmlDeError {
|
||||
QuickXmlDeError(#[from] quick_xml::de::DeError),
|
||||
#[error(transparent)]
|
||||
QuickXmlError(#[from] quick_xml::Error),
|
||||
#[error(transparent)]
|
||||
QuickXmlAttrError(#[from] quick_xml::events::attributes::AttrError),
|
||||
#[error("Unknown error")]
|
||||
UnknownError,
|
||||
#[error("Invalid tag {0}. Expected {1}")]
|
||||
@@ -26,6 +28,8 @@ pub enum XmlDeError {
|
||||
InvalidVariant(String),
|
||||
#[error("Invalid field name: ")]
|
||||
InvalidFieldName,
|
||||
#[error(transparent)]
|
||||
InvalidValue(#[from] crate::value::ParseValueError),
|
||||
}
|
||||
|
||||
pub trait XmlDeserialize: Sized {
|
||||
@@ -36,12 +40,16 @@ pub trait XmlDeserialize: Sized {
|
||||
) -> Result<Self, XmlDeError>;
|
||||
}
|
||||
|
||||
pub trait XmlRoot: XmlDeserialize {
|
||||
fn parse<R: BufRead>(mut reader: quick_xml::NsReader<R>) -> Result<Self, XmlDeError> {
|
||||
pub trait XmlRoot {
|
||||
fn parse<R: BufRead>(mut reader: quick_xml::NsReader<R>) -> Result<Self, XmlDeError>
|
||||
where
|
||||
Self: XmlDeserialize,
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
let event = reader.read_event_into(&mut buf)?;
|
||||
let empty = event.is_empty();
|
||||
match event {
|
||||
Event::Start(start) => {
|
||||
Event::Start(start) | Event::Empty(start) => {
|
||||
let (_ns, name) = reader.resolve_element(start.name());
|
||||
if name.as_ref() != Self::root_tag() {
|
||||
return Err(XmlDeError::InvalidTag(
|
||||
@@ -49,32 +57,33 @@ pub trait XmlRoot: XmlDeserialize {
|
||||
String::from_utf8_lossy(Self::root_tag()).to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
// TODO: check namespace
|
||||
|
||||
return Self::deserialize(&mut reader, &start, false);
|
||||
}
|
||||
Event::Empty(start) => {
|
||||
let (_ns, name) = reader.resolve_element(start.name());
|
||||
if name.as_ref() != Self::root_tag() {
|
||||
return Err(XmlDeError::InvalidTag(
|
||||
String::from_utf8_lossy(name.as_ref()).to_string(),
|
||||
String::from_utf8_lossy(Self::root_tag()).to_string(),
|
||||
));
|
||||
};
|
||||
// TODO: check namespace
|
||||
|
||||
return Self::deserialize(&mut reader, &start, true);
|
||||
return Self::deserialize(&mut reader, &start, empty);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Err(XmlDeError::UnknownError)
|
||||
}
|
||||
|
||||
fn parse_str(input: &str) -> Result<Self, XmlDeError> {
|
||||
let mut reader = quick_xml::NsReader::from_str(input);
|
||||
fn parse_reader<R: BufRead>(input: R) -> Result<Self, XmlDeError>
|
||||
where
|
||||
Self: XmlDeserialize,
|
||||
{
|
||||
let mut reader = quick_xml::NsReader::from_reader(input);
|
||||
reader.config_mut().trim_text(true);
|
||||
Self::parse(reader)
|
||||
}
|
||||
|
||||
fn root_tag() -> &'static [u8];
|
||||
}
|
||||
|
||||
pub trait XmlRootParseStr<'i>: XmlRoot + XmlDeserialize {
|
||||
#[inline]
|
||||
fn parse_str(s: &'i str) -> Result<Self, XmlDeError> {
|
||||
Self::parse_reader(s.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, T: XmlRoot + XmlDeserialize> XmlRootParseStr<'i> for T {}
|
||||
|
||||
@@ -2,10 +2,12 @@ use quick_xml::events::{BytesStart, Event};
|
||||
use std::io::BufRead;
|
||||
|
||||
pub mod de;
|
||||
mod value;
|
||||
|
||||
pub use de::XmlDeError;
|
||||
pub use de::XmlDeserialize;
|
||||
pub use de::XmlRoot;
|
||||
pub use value::Value;
|
||||
|
||||
impl<T: XmlDeserialize> XmlDeserialize for Option<T> {
|
||||
fn deserialize<R: BufRead>(
|
||||
@@ -17,6 +19,7 @@ impl<T: XmlDeserialize> XmlDeserialize for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Unit;
|
||||
|
||||
impl XmlDeserialize for Unit {
|
||||
@@ -65,3 +68,19 @@ impl XmlDeserialize for String {
|
||||
Ok(content)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: actually implement
|
||||
pub struct Unparsed(BytesStart<'static>);
|
||||
|
||||
impl XmlDeserialize for Unparsed {
|
||||
fn deserialize<R: BufRead>(
|
||||
reader: &mut quick_xml::NsReader<R>,
|
||||
start: &BytesStart,
|
||||
_empty: bool,
|
||||
) -> Result<Self, XmlDeError> {
|
||||
// let reader_cloned = NsReader::from_reader(reader.get_ref().to_owned());
|
||||
let mut buf = vec![];
|
||||
reader.read_to_end_into(start.name(), &mut buf)?;
|
||||
Ok(Self(start.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
33
crates/xml/src/value.rs
Normal file
33
crates/xml/src/value.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use std::convert::Infallible;
|
||||
use std::num::ParseIntError;
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::XmlDeError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ParseValueError {
|
||||
#[error(transparent)]
|
||||
Infallible(#[from] Infallible),
|
||||
#[error(transparent)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
}
|
||||
|
||||
pub trait Value: Sized {
|
||||
fn serialize(&self) -> String;
|
||||
fn deserialize(val: &str) -> Result<Self, XmlDeError>;
|
||||
}
|
||||
|
||||
impl<E, T: FromStr<Err = E> + ToString> Value for T
|
||||
where
|
||||
ParseValueError: From<E>,
|
||||
{
|
||||
fn serialize(&self) -> String {
|
||||
self.to_string()
|
||||
}
|
||||
fn deserialize(val: &str) -> Result<Self, XmlDeError> {
|
||||
val.parse()
|
||||
.map_err(ParseValueError::from)
|
||||
.map_err(XmlDeError::from)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user