use derive_more::From; use quick_xml::events::Event; use quick_xml::name::{Namespace, ResolveResult}; use crate::protos::xmpp::bind::BindRequest; use crate::protos::xmpp::client::{Iq, Message}; use crate::protos::xmpp::session::Session; use crate::util::xml::{Continuation, FromXml, FromXmlTag, Parser}; use crate::prelude::*; #[derive(PartialEq, Eq, Debug, From)] pub enum IqClientBody { Bind(BindRequest), Session(Session), } #[derive(From)] pub struct IqClientBodyParser(IqClientBodyParserInner); #[derive(From)] enum IqClientBodyParserInner { Initial, Bind(::P), SessionV(::P), } impl FromXml for IqClientBody { type P = IqClientBodyParser; fn parse() -> Self::P { IqClientBodyParserInner::Initial.into() } } impl Parser for IqClientBodyParser { type Output = Result; fn consume<'a>( self: Self, namespace: quick_xml::name::ResolveResult, event: &quick_xml::events::Event<'a>, ) -> crate::util::xml::Continuation { use IqClientBodyParserInner::*; match self.0 { Initial => { let bytes = match event { Event::Start(bytes) => bytes, Event::Empty(bytes) => bytes, _ => { return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))) } }; if bytes.name().0 == BindRequest::NAME.as_bytes() && namespace == ResolveResult::Bound(Namespace(BindRequest::NS.as_bytes())) { IqClientBodyParser(BindRequest::parse().into()).consume(namespace, event) } else if bytes.name().0 == Session::NAME.as_bytes() && namespace == ResolveResult::Bound(Namespace(Session::NS.as_bytes())) { IqClientBodyParser(Session::parse().into()).consume(namespace, event) } else { Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))) } } Bind(p) => match p.consume(namespace, event) { Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())), Continuation::Final(Err(e)) => Continuation::Final(Err(e)), Continuation::Continue(s) => { let inner: IqClientBodyParserInner = s.into(); Continuation::Continue(inner.into()) } }, SessionV(p) => match p.consume(namespace, event) { Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())), Continuation::Final(Err(e)) => Continuation::Final(Err(e)), Continuation::Continue(s) => { let inner: IqClientBodyParserInner = s.into(); Continuation::Continue(inner.into()) } }, } } } #[derive(PartialEq, Eq, Debug, From)] pub enum ClientPacket { Iq(Iq), Message(Message), } #[derive(From)] pub struct ClientPacketParser(ClientPacketParserInner); impl FromXml for ClientPacket { type P = ClientPacketParser; fn parse() -> Self::P { ClientPacketParserInner::Initial.into() } } #[derive(From)] enum ClientPacketParserInner { Initial, Iq( as FromXml>::P), Message(::P), } impl Parser for ClientPacketParser { type Output = Result; fn consume<'a>( self: Self, namespace: ResolveResult, event: &Event<'a>, ) -> Continuation { use ClientPacketParserInner::{Initial, Iq as IqV, Message as MessageV}; match self.0 { Initial => { let Event::Start(bytes) = event else { return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))); }; if bytes.name().0 == Iq::::NAME.as_bytes() && namespace == ResolveResult::Bound(Namespace(Iq::::NS.as_bytes())) { ClientPacketParser(IqV(Iq::::parse())).consume(namespace, event) } else if bytes.name().0 == Message::NAME.as_bytes() && namespace == ResolveResult::Bound(Namespace(Message::NS.as_bytes())) { ClientPacketParser(MessageV(Message::parse())).consume(namespace, event) } else { Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))) } } IqV(p) => match p.consume(namespace, event) { Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())), Continuation::Final(Err(e)) => Continuation::Final(Err(e)), Continuation::Continue(s) => { let inner: ClientPacketParserInner = s.into(); Continuation::Continue(inner.into()) } }, MessageV(p) => match p.consume(namespace, event) { Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())), Continuation::Final(Err(e)) => Continuation::Final(Err(e)), Continuation::Continue(s) => { let inner: ClientPacketParserInner = s.into(); Continuation::Continue(inner.into()) } }, } } }