2023-03-07 13:56:31 +00:00
|
|
|
use quick_xml::events::Event;
|
2023-03-11 15:07:02 +00:00
|
|
|
use quick_xml::name::ResolveResult;
|
2023-03-07 13:56:31 +00:00
|
|
|
|
2023-03-08 18:56:53 +00:00
|
|
|
use crate::prelude::Result;
|
|
|
|
|
2023-03-20 16:25:14 +00:00
|
|
|
mod ignore;
|
|
|
|
pub use ignore::Ignore;
|
|
|
|
|
2023-03-08 18:56:53 +00:00
|
|
|
pub trait FromXml: Sized {
|
|
|
|
type P: Parser<Output = Result<Self>>;
|
|
|
|
|
|
|
|
fn parse() -> Self::P;
|
|
|
|
}
|
|
|
|
|
2023-03-12 12:25:23 +00:00
|
|
|
pub trait ToXml: Sized {
|
|
|
|
fn serialize(&self, events: &mut Vec<Event<'static>>);
|
|
|
|
}
|
|
|
|
|
2023-03-12 13:15:13 +00:00
|
|
|
pub trait FromXmlTag: FromXml {
|
|
|
|
const NAME: &'static str;
|
|
|
|
const NS: &'static str;
|
|
|
|
}
|
|
|
|
|
2023-03-07 13:56:31 +00:00
|
|
|
pub trait Parser: Sized {
|
|
|
|
type Output;
|
|
|
|
|
2023-03-11 15:07:02 +00:00
|
|
|
fn consume<'a>(
|
|
|
|
self: Self,
|
|
|
|
namespace: ResolveResult,
|
|
|
|
event: &Event<'a>,
|
|
|
|
) -> Continuation<Self, Self::Output>;
|
2023-03-07 13:56:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Continuation<Parser, Res> {
|
|
|
|
Final(Res),
|
|
|
|
Continue(Parser),
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! fail_fast {
|
|
|
|
($errorable: expr) => {
|
|
|
|
match $errorable {
|
|
|
|
Ok(i) => i,
|
2023-03-07 15:27:09 +00:00
|
|
|
Err(e) => return Continuation::Final(Err(e.into())),
|
2023-03-07 13:56:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-03-12 21:50:28 +00:00
|
|
|
macro_rules! delegate_parsing {
|
|
|
|
($parser: ident, $intermediate: ident, $namespace: expr, $event: expr) => {
|
|
|
|
match $parser.consume($namespace, $event) {
|
|
|
|
Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())),
|
|
|
|
Continuation::Final(Err(e)) => Continuation::Final(Err(e)),
|
|
|
|
Continuation::Continue(s) => {
|
|
|
|
let inner: $intermediate = s.into();
|
|
|
|
Continuation::Continue(inner.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! match_parser {
|
2023-03-21 00:16:02 +00:00
|
|
|
($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty, $fin: block) => {
|
2023-03-12 21:50:28 +00:00
|
|
|
if $name.0 == <$subtype as FromXmlTag>::NAME.as_bytes() && $ns == ResolveResult::Bound(Namespace(<$subtype as FromXmlTag>::NS.as_bytes())) {
|
|
|
|
$outer(<$subtype as FromXml>::parse().into()).consume($ns, $event)
|
|
|
|
} else {
|
2023-03-21 00:16:02 +00:00
|
|
|
$fin
|
2023-03-12 21:50:28 +00:00
|
|
|
}
|
|
|
|
};
|
2023-03-21 00:16:02 +00:00
|
|
|
($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty, $($rest: ty),+, $fin: block) => {
|
2023-03-12 21:50:28 +00:00
|
|
|
if $name.0 == <$subtype as FromXmlTag>::NAME.as_bytes() && $ns == ResolveResult::Bound(Namespace(<$subtype as FromXmlTag>::NS.as_bytes())) {
|
|
|
|
$outer(<$subtype as FromXml>::parse().into()).consume($ns, $event)
|
|
|
|
} else {
|
2023-03-21 00:16:02 +00:00
|
|
|
match_parser!($outer, $name, $ns, $event; $($rest),*, $fin)
|
2023-03-12 21:50:28 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) use delegate_parsing;
|
2023-03-07 15:27:09 +00:00
|
|
|
pub(crate) use fail_fast;
|
2023-03-12 21:50:28 +00:00
|
|
|
pub(crate) use match_parser;
|