use quick_xml::events::Event; use quick_xml::name::ResolveResult; use crate::prelude::Result; mod ignore; pub use ignore::Ignore; pub trait FromXml: Sized { type P: Parser>; fn parse() -> Self::P; } pub trait ToXml: Sized { fn serialize(&self, events: &mut Vec>); } pub trait FromXmlTag: FromXml { const NAME: &'static str; const NS: &'static str; } pub trait Parser: Sized { type Output; fn consume<'a>( self: Self, namespace: ResolveResult, event: &Event<'a>, ) -> Continuation; } pub enum Continuation { Final(Res), Continue(Parser), } macro_rules! fail_fast { ($errorable: expr) => { match $errorable { Ok(i) => i, Err(e) => return Continuation::Final(Err(e.into())), } }; } 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 { ($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty, $fin: block) => { 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 { $fin } }; ($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty, $($rest: ty),+, $fin: block) => { 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 { match_parser!($outer, $name, $ns, $event; $($rest),*, $fin) } }; } pub(crate) use delegate_parsing; pub(crate) use fail_fast; pub(crate) use match_parser;