From 0e78f24fbdf28f8ec5c0a5e6daa545959eb0414c Mon Sep 17 00:00:00 2001 From: Nikita Vilunov Date: Sat, 25 Mar 2023 10:59:14 +0100 Subject: [PATCH] feat(xmpp): implement muc base element parsing --- src/protos/xmpp/mod.rs | 1 + src/protos/xmpp/muc/mod.rs | 160 +++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/protos/xmpp/muc/mod.rs diff --git a/src/protos/xmpp/mod.rs b/src/protos/xmpp/mod.rs index 49c973e..8e46e8d 100644 --- a/src/protos/xmpp/mod.rs +++ b/src/protos/xmpp/mod.rs @@ -1,5 +1,6 @@ pub mod bind; pub mod client; +pub mod muc; pub mod roster; pub mod sasl; pub mod session; diff --git a/src/protos/xmpp/muc/mod.rs b/src/protos/xmpp/muc/mod.rs new file mode 100644 index 0000000..9c1ba6c --- /dev/null +++ b/src/protos/xmpp/muc/mod.rs @@ -0,0 +1,160 @@ +use quick_xml::events::Event; +use quick_xml::name::ResolveResult; + +use crate::prelude::*; +use crate::util::xml::*; + +pub const XMLNS: &'static str = "http://jabber.org/protocol/muc"; + +#[derive(PartialEq, Eq, Debug, Default)] +pub struct History { + pub maxchars: Option, + pub maxstanzas: Option, + pub seconds: Option, +} + +impl FromXml for History { + type P = impl Parser>; + + fn parse() -> Self::P { + |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { + let mut history = History::default(); + let (bytes, end) = match event { + Event::Start(bytes) => (bytes, false), + Event::Empty(bytes) => (bytes, true), + _ => return Err(ffail!("Unexpected XML event: {event:?}")), + }; + for attr in bytes.attributes() { + let attr = attr?; + match attr.key.0 { + b"maxchars" => { + let s = std::str::from_utf8(bytes)?; + let a = s.parse()?; + history.maxchars = Some(a) + } + b"maxstanzas" => { + let s = std::str::from_utf8(bytes)?; + let a = s.parse()?; + history.maxstanzas = Some(a) + } + b"seconds" => { + let s = std::str::from_utf8(bytes)?; + let a = s.parse()?; + history.seconds = Some(a) + } + _ => {} + } + } + if end { + return Ok(history); + } + + let (namespace, event) = yield; + let Event::End(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + Ok(history) + } + } +} + +impl FromXmlTag for History { + const NAME: &'static str = "history"; + + const NS: &'static str = XMLNS; +} + +#[derive(PartialEq, Eq, Debug)] +pub struct Password(pub String); + +impl FromXml for Password { + type P = impl Parser>; + + fn parse() -> Self::P { + |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { + let Event::Start(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + let (namespace, event) = yield; + let Event::Text(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + let s = std::str::from_utf8(bytes)?.to_string(); + let Event::End(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + Ok(Password(s)) + } + } +} + +impl FromXmlTag for Password { + const NAME: &'static str = "password"; + + const NS: &'static str = XMLNS; +} + +#[derive(PartialEq, Eq, Debug, Default)] +pub struct X { + pub history: Option, + pub password: Option, +} + +impl FromXml for X { + type P = impl Parser>; + + fn parse() -> Self::P { + |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { + let mut res = X::default(); + let (bytes, end) = match event { + Event::Start(bytes) => (bytes, false), + Event::Empty(bytes) => (bytes, true), + _ => return Err(ffail!("Unexpected XML event: {event:?}")), + }; + if end { + return Ok(res); + } + + loop { + let (namespace, event) = yield; + let bytes = match event { + Event::Start(bytes) => bytes, + Event::Empty(bytes) => bytes, + Event::End(_) => break, + _ => return Err(ffail!("Unexpected XML event: {event:?}")), + }; + if bytes.name().0 == Password::NAME.as_bytes() { + let mut parser = Password::parse().consume(namespace, event); + let password = loop { + match parser { + Continuation::Final(Ok(res)) => break Ok(res), + Continuation::Final(Err(err)) => break Err(err), + Continuation::Continue(p) => { + let (namespace, event) = yield; + parser = p.consume(namespace, event); + } + } + }?; + res.password = Some(password); + } else if bytes.name().0 == History::NAME.as_bytes() { + let mut parser = History::parse().consume(namespace, event); + let history = loop { + match parser { + Continuation::Final(Ok(res)) => break Ok(res), + Continuation::Final(Err(err)) => break Err(err), + Continuation::Continue(p) => { + let (namespace, event) = yield; + parser = p.consume(namespace, event); + } + } + }?; + res.history = Some(history); + } else { + return Err(ffail!("Unexpected XML event: {event:?}")); + } + } + + Ok(res) + } + } +}