use anyhow::anyhow; use derive_more::From; use quick_xml::events::Event; use quick_xml::name::{Namespace, ResolveResult}; use lavina_core::prelude::*; use proto_xmpp::bind::BindRequest; use proto_xmpp::client::{Iq, Message, Presence}; use proto_xmpp::disco::{InfoQuery, ItemQuery}; use proto_xmpp::roster::RosterQuery; use proto_xmpp::session::Session; use proto_xmpp::xml::*; #[derive(PartialEq, Eq, Debug, From)] pub enum IqClientBody { Bind(BindRequest), Session(Session), Roster(RosterQuery), DiscoInfo(InfoQuery), DiscoItem(ItemQuery), Unknown(Ignore), } impl FromXml for IqClientBody { type P = impl Parser>; fn parse() -> Self::P { |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { let bytes = match event { Event::Start(bytes) => bytes, Event::Empty(bytes) => bytes, _ => return Err(anyhow!("Unexpected XML event: {event:?}")), }; let name = bytes.name(); match_parser!(name, namespace, event; BindRequest, Session, RosterQuery, InfoQuery, ItemQuery, { delegate_parsing!(Ignore, namespace, event).into() } ) } } } #[derive(PartialEq, Eq, Debug, From)] pub enum ClientPacket { Iq(Iq), Message(Message), Presence(Presence), StreamEnd, } impl FromXml for ClientPacket { type P = impl Parser>; fn parse() -> Self::P { |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { match event { Event::Start(bytes) | Event::Empty(bytes) => { let name = bytes.name(); match_parser!(name, namespace, event; Iq::, Presence::, Message::, { Err(anyhow!( "Unexpected XML event of name {:?} in namespace {:?}", name, namespace )) } ) } Event::End(bytes) => { let name = bytes.name(); if name.local_name().as_ref() == b"stream" { return Ok(ClientPacket::StreamEnd); } else { return Err(anyhow!("Unexpected XML event: {event:?}")); } } _ => { return Err(anyhow!("Unexpected XML event: {event:?}")); } } } } }