rustical_xml: Use darling for proc-macro parsing

This commit is contained in:
Lennart
2024-11-27 17:47:55 +01:00
parent a9ef680c30
commit 57268f202d
11 changed files with 227 additions and 479 deletions

View File

@@ -1,87 +1,18 @@
use quick_xml::events::{BytesStart, Event};
use std::io::BufRead;
use thiserror::Error;
pub use xml_derive::XmlDeserialize;
#[derive(Debug, Error)]
pub enum XmlError {
#[error(transparent)]
QuickXmlDeError(#[from] quick_xml::de::DeError),
#[error(transparent)]
QuickXmlError(#[from] quick_xml::Error),
#[error("Unknown error")]
UnknownError,
#[error("Invalid tag {0}. Expected {1}")]
InvalidTag(String, String),
#[error("Missing field {0}")]
MissingField(&'static str),
#[error("End of file, expected closing tags")]
Eof,
#[error("Unsupported xml event: {0}")]
UnsupportedEvent(&'static str),
#[error("{0}")]
Other(String),
#[error("Invalid variant: {0}")]
InvalidVariant(String),
}
pub mod de;
pub trait XmlDeserialize: Sized {
fn deserialize<R: BufRead>(
reader: &mut quick_xml::NsReader<R>,
start: &BytesStart,
empty: bool,
) -> Result<Self, XmlError>;
}
pub trait XmlRoot: XmlDeserialize {
fn parse<R: BufRead>(mut reader: quick_xml::NsReader<R>) -> Result<Self, XmlError> {
let mut buf = Vec::new();
let event = reader.read_event_into(&mut buf)?;
match event {
Event::Start(start) => {
let (_ns, name) = reader.resolve_element(start.name());
if name.as_ref() != Self::root_tag() {
return Err(XmlError::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, false);
}
Event::Empty(start) => {
let (_ns, name) = reader.resolve_element(start.name());
if name.as_ref() != Self::root_tag() {
return Err(XmlError::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);
}
_ => {}
};
Err(XmlError::UnknownError)
}
fn parse_str(input: &str) -> Result<Self, XmlError> {
let mut reader = quick_xml::NsReader::from_str(input);
reader.config_mut().trim_text(true);
Self::parse(reader)
}
fn root_tag() -> &'static [u8];
}
pub use de::XmlDeError;
pub use de::XmlDeserialize;
pub use de::XmlRoot;
impl<T: XmlDeserialize> XmlDeserialize for Option<T> {
fn deserialize<R: BufRead>(
reader: &mut quick_xml::NsReader<R>,
start: &BytesStart,
empty: bool,
) -> Result<Self, XmlError> {
) -> Result<Self, XmlDeError> {
Ok(Some(T::deserialize(reader, start, empty)?))
}
}
@@ -93,7 +24,7 @@ impl XmlDeserialize for Unit {
reader: &mut quick_xml::NsReader<R>,
start: &BytesStart,
empty: bool,
) -> Result<Self, XmlError> {
) -> Result<Self, XmlDeError> {
if empty {
return Ok(Unit);
}
@@ -101,7 +32,7 @@ impl XmlDeserialize for Unit {
loop {
match reader.read_event_into(&mut buf)? {
Event::End(e) if e.name() == start.name() => return Ok(Unit),
Event::Eof => return Err(XmlError::Eof),
Event::Eof => return Err(XmlDeError::Eof),
_ => {}
};
}
@@ -113,7 +44,7 @@ impl XmlDeserialize for String {
reader: &mut quick_xml::NsReader<R>,
start: &BytesStart,
empty: bool,
) -> Result<Self, XmlError> {
) -> Result<Self, XmlDeError> {
if empty {
return Ok(String::new());
}
@@ -124,11 +55,11 @@ impl XmlDeserialize for String {
Event::End(e) if e.name() == start.name() => {
break;
}
Event::Eof => return Err(XmlError::Eof),
Event::Eof => return Err(XmlDeError::Eof),
Event::Text(text) => {
content.push_str(&text.unescape()?);
}
_a => return Err(XmlError::UnknownError),
_a => return Err(XmlDeError::UnknownError),
};
}
Ok(content)