forked from lavina/lavina
1
0
Fork 0
lavina/crates/proto-xmpp/src/roster.rs

80 lines
2.4 KiB
Rust

use quick_xml::events::{BytesStart, Event};
use crate::xml::*;
use anyhow::{anyhow, Result};
use quick_xml::name::{Namespace, ResolveResult};
pub const XMLNS: &'static str = "jabber:iq:roster";
#[derive(PartialEq, Eq, Debug)]
pub struct RosterQuery;
impl FromXml for RosterQuery {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(mut namespace, mut event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let ResolveResult::Bound(Namespace(ns)) = namespace else {
return Err(anyhow!("No namespace provided"));
};
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:?}")),
}
}
}
}
impl FromXmlTag for RosterQuery {
const NAME: &'static str = "query";
const NS: &'static str = XMLNS;
}
impl ToXml for RosterQuery {
fn serialize(&self, events: &mut Vec<Event<'static>>) {
events.push(Event::Empty(BytesStart::new(format!(r#"query xmlns="{}""#, XMLNS))));
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bind::{Jid, Name, Resource, Server};
use crate::client::{Iq, IqType};
#[test]
fn test_parse() {
let input =
r#"<iq from='juliet@example.com/balcony' id='bv1bs71f' type='get'><query xmlns='jabber:iq:roster'/></iq>"#;
let result: Iq<RosterQuery> = parse(input).unwrap();
assert_eq!(
result,
Iq {
from: Option::from(Jid {
name: Option::from(Name("juliet".into())),
server: Server("example.com".into()),
resource: Option::from(Resource("balcony".into())),
}),
id: "bv1bs71f".to_string(),
to: None,
r#type: IqType::Get,
body: RosterQuery,
}
)
}
#[test]
fn test_missing_namespace() {
let input = r#"<iq from='juliet@example.com/balcony' id='bv1bs71f' type='get'><query/></iq>"#;
assert!(parse::<Iq<RosterQuery>>(input).is_err());
}
}