forked from lavina/lavina
1
0
Fork 0

feat(xmpp): implement muc base element parsing

This commit is contained in:
Nikita Vilunov 2023-03-25 10:59:14 +01:00
parent a73bbdb5f1
commit 0e78f24fbd
2 changed files with 161 additions and 0 deletions

View File

@ -1,5 +1,6 @@
pub mod bind; pub mod bind;
pub mod client; pub mod client;
pub mod muc;
pub mod roster; pub mod roster;
pub mod sasl; pub mod sasl;
pub mod session; pub mod session;

160
src/protos/xmpp/muc/mod.rs Normal file
View File

@ -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<u32>,
pub maxstanzas: Option<u32>,
pub seconds: Option<u32>,
}
impl FromXml for History {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
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<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
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<History>,
pub password: Option<Password>,
}
impl FromXml for X {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
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)
}
}
}