forked from lavina/lavina
xmpp: rewrite xml element parsers using coroutines
This commit is contained in:
parent
048660624d
commit
fbb3d4f4f9
|
@ -1,47 +1,30 @@
|
||||||
use quick_xml::events::{BytesStart, Event};
|
use quick_xml::events::{BytesStart, Event};
|
||||||
|
|
||||||
use crate::xml::*;
|
use crate::xml::*;
|
||||||
use anyhow::{anyhow as ffail, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use quick_xml::name::ResolveResult;
|
||||||
|
|
||||||
pub const XMLNS: &'static str = "jabber:iq:roster";
|
pub const XMLNS: &'static str = "jabber:iq:roster";
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub struct RosterQuery;
|
pub struct RosterQuery;
|
||||||
|
|
||||||
pub struct QueryParser(QueryParserInner);
|
|
||||||
|
|
||||||
enum QueryParserInner {
|
|
||||||
Initial,
|
|
||||||
InQuery,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parser for QueryParser {
|
|
||||||
type Output = Result<RosterQuery>;
|
|
||||||
|
|
||||||
fn consume<'a>(
|
|
||||||
self: Self,
|
|
||||||
namespace: quick_xml::name::ResolveResult,
|
|
||||||
event: &quick_xml::events::Event<'a>,
|
|
||||||
) -> Continuation<Self, Self::Output> {
|
|
||||||
match self.0 {
|
|
||||||
QueryParserInner::Initial => match event {
|
|
||||||
Event::Start(_) => Continuation::Continue(QueryParser(QueryParserInner::InQuery)),
|
|
||||||
Event::Empty(_) => Continuation::Final(Ok(RosterQuery)),
|
|
||||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
|
||||||
},
|
|
||||||
QueryParserInner::InQuery => match event {
|
|
||||||
Event::End(_) => Continuation::Final(Ok(RosterQuery)),
|
|
||||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromXml for RosterQuery {
|
impl FromXml for RosterQuery {
|
||||||
type P = QueryParser;
|
type P = impl Parser<Output = Result<Self>>;
|
||||||
|
|
||||||
fn parse() -> Self::P {
|
fn parse() -> Self::P {
|
||||||
QueryParser(QueryParserInner::Initial)
|
|(mut namespace, mut event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
|
||||||
|
match event {
|
||||||
|
Event::Start(_) => (),
|
||||||
|
Event::Empty(_) => return Ok(RosterQuery),
|
||||||
|
_ => return Err(anyhow!("Unexpected XML event: {event:?}")),
|
||||||
|
}
|
||||||
|
(namespace, event) = yield;
|
||||||
|
match event {
|
||||||
|
Event::End(_) => return Ok(RosterQuery),
|
||||||
|
_ => return Err(anyhow!("Unexpected XML event: {event:?}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,46 +2,29 @@ use quick_xml::events::{BytesStart, Event};
|
||||||
|
|
||||||
use crate::xml::*;
|
use crate::xml::*;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use quick_xml::name::ResolveResult;
|
||||||
|
|
||||||
pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-session";
|
pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-session";
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub struct Session;
|
pub struct Session;
|
||||||
|
|
||||||
pub struct SessionParser(SessionParserInner);
|
|
||||||
|
|
||||||
enum SessionParserInner {
|
|
||||||
Initial,
|
|
||||||
InSession,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parser for SessionParser {
|
|
||||||
type Output = Result<Session>;
|
|
||||||
|
|
||||||
fn consume<'a>(
|
|
||||||
self: Self,
|
|
||||||
namespace: quick_xml::name::ResolveResult,
|
|
||||||
event: &quick_xml::events::Event<'a>,
|
|
||||||
) -> Continuation<Self, Self::Output> {
|
|
||||||
match self.0 {
|
|
||||||
SessionParserInner::Initial => match event {
|
|
||||||
Event::Start(_) => Continuation::Continue(SessionParser(SessionParserInner::InSession)),
|
|
||||||
Event::Empty(_) => Continuation::Final(Ok(Session)),
|
|
||||||
_ => Continuation::Final(Err(anyhow!("Unexpected XML event: {event:?}"))),
|
|
||||||
},
|
|
||||||
SessionParserInner::InSession => match event {
|
|
||||||
Event::End(_) => Continuation::Final(Ok(Session)),
|
|
||||||
_ => Continuation::Final(Err(anyhow!("Unexpected XML event: {event:?}"))),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromXml for Session {
|
impl FromXml for Session {
|
||||||
type P = SessionParser;
|
type P = impl Parser<Output = Result<Self>>;
|
||||||
|
|
||||||
fn parse() -> Self::P {
|
fn parse() -> Self::P {
|
||||||
SessionParser(SessionParserInner::Initial)
|
|(mut namespace, mut event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
|
||||||
|
match event {
|
||||||
|
Event::Start(_) => (),
|
||||||
|
Event::Empty(_) => return Ok(Session),
|
||||||
|
_ => return Err(anyhow!("Unexpected XML event: {event:?}")),
|
||||||
|
}
|
||||||
|
(namespace, event) = yield;
|
||||||
|
match event {
|
||||||
|
Event::End(_) => return Ok(Session),
|
||||||
|
_ => return Err(anyhow!("Unexpected XML event: {event:?}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,35 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use derive_more::From;
|
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Eq)]
|
#[derive(Default, Debug, PartialEq, Eq)]
|
||||||
pub struct Ignore;
|
pub struct Ignore;
|
||||||
|
|
||||||
#[derive(From)]
|
|
||||||
pub struct IgnoreParser(IgnoreParserInner);
|
|
||||||
|
|
||||||
enum IgnoreParserInner {
|
|
||||||
Initial,
|
|
||||||
InTag { name: Vec<u8>, depth: u8 },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parser for IgnoreParser {
|
|
||||||
type Output = Result<Ignore>;
|
|
||||||
|
|
||||||
fn consume<'a>(self: Self, _: ResolveResult, event: &Event<'a>) -> Continuation<Self, Self::Output> {
|
|
||||||
match self.0 {
|
|
||||||
IgnoreParserInner::Initial => match event {
|
|
||||||
Event::Start(bytes) => {
|
|
||||||
let name = bytes.name().0.to_owned();
|
|
||||||
Continuation::Continue(IgnoreParserInner::InTag { name, depth: 0 }.into())
|
|
||||||
}
|
|
||||||
Event::Empty(_) => Continuation::Final(Ok(Ignore)),
|
|
||||||
_ => Continuation::Final(Ok(Ignore)),
|
|
||||||
},
|
|
||||||
IgnoreParserInner::InTag { name, depth } => match event {
|
|
||||||
Event::End(bytes) if name == bytes.name().0 => {
|
|
||||||
if depth == 0 {
|
|
||||||
Continuation::Final(Ok(Ignore))
|
|
||||||
} else {
|
|
||||||
Continuation::Continue(IgnoreParserInner::InTag { name, depth: depth - 1 }.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Continuation::Continue(IgnoreParserInner::InTag { name, depth }.into()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromXml for Ignore {
|
impl FromXml for Ignore {
|
||||||
type P = IgnoreParser;
|
type P = impl Parser<Output = Result<Self>>;
|
||||||
|
|
||||||
fn parse() -> Self::P {
|
fn parse() -> Self::P {
|
||||||
IgnoreParserInner::Initial.into()
|
|(mut namespace, mut event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
|
||||||
|
let mut depth = match event {
|
||||||
|
Event::Start(bytes) => 0,
|
||||||
|
Event::Empty(_) => return Ok(Ignore),
|
||||||
|
_ => return Ok(Ignore),
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
(namespace, event) = yield;
|
||||||
|
match event {
|
||||||
|
Event::End(_) => {
|
||||||
|
if depth == 0 {
|
||||||
|
return Ok(Ignore);
|
||||||
|
} else {
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::Start(_) => {
|
||||||
|
depth += 1;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue