forked from lavina/lavina
feat(xmpp): make presence polymorphic wrt any fields
This commit is contained in:
parent
1cc4761aeb
commit
a65ea89ce1
|
@ -337,7 +337,7 @@ async fn socket_final(
|
|||
proto::ClientPacket::Message(_) => todo!(),
|
||||
proto::ClientPacket::Presence(p) => {
|
||||
let mut events = vec![];
|
||||
let response = Presence {
|
||||
let response = Presence::<()> {
|
||||
to: Some("darova@localhost/kek".to_string()),
|
||||
from: Some("darova@localhost/kek".to_string()),
|
||||
..Default::default()
|
||||
|
|
|
@ -72,7 +72,7 @@ impl Parser for IqClientBodyParser {
|
|||
pub enum ClientPacket {
|
||||
Iq(Iq<IqClientBody>),
|
||||
Message(Message),
|
||||
Presence(Presence),
|
||||
Presence(Presence<Ignore>),
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
|
@ -91,7 +91,7 @@ enum ClientPacketParserInner {
|
|||
Initial,
|
||||
IqV(<Iq<IqClientBody> as FromXml>::P),
|
||||
MessageV(<Message as FromXml>::P),
|
||||
PresenceV(<Presence as FromXml>::P),
|
||||
PresenceV(<Presence<Ignore> as FromXml>::P),
|
||||
}
|
||||
|
||||
impl Parser for ClientPacketParser {
|
||||
|
@ -111,7 +111,7 @@ impl Parser for ClientPacketParser {
|
|||
let name = bytes.name();
|
||||
match_parser!(ClientPacketParser, name, namespace, event;
|
||||
Iq::<IqClientBody>,
|
||||
Presence,
|
||||
Presence::<Ignore>,
|
||||
Message
|
||||
)
|
||||
}
|
||||
|
|
|
@ -342,13 +342,27 @@ impl<T: ToXml> ToXml for Iq<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
pub struct Presence {
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Presence<T> {
|
||||
pub to: Option<String>,
|
||||
pub from: Option<String>,
|
||||
pub priority: Option<PresencePriority>,
|
||||
pub show: Option<PresenceShow>,
|
||||
pub status: Vec<String>,
|
||||
pub custom: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T> Default for Presence<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
to: Default::default(),
|
||||
from: Default::default(),
|
||||
priority: Default::default(),
|
||||
show: Default::default(),
|
||||
status: Default::default(),
|
||||
custom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
|
@ -389,20 +403,21 @@ impl PresenceShow {
|
|||
}
|
||||
|
||||
#[derive(From)]
|
||||
pub struct PresenceParser(PresenceParserInner);
|
||||
enum PresenceParserInner {
|
||||
pub struct PresenceParser<T: FromXml>(PresenceParserInner<T>);
|
||||
enum PresenceParserInner<T: FromXml> {
|
||||
Initial,
|
||||
InPresence(Presence),
|
||||
InPriority(Presence),
|
||||
InPriorityEnd(Presence),
|
||||
InShow(Presence),
|
||||
InShowEnd(Presence),
|
||||
InStatus(Presence),
|
||||
InStatusEnd(Presence),
|
||||
InPresence(Presence<T>),
|
||||
InPriority(Presence<T>),
|
||||
InPriorityEnd(Presence<T>),
|
||||
InShow(Presence<T>),
|
||||
InShowEnd(Presence<T>),
|
||||
InStatus(Presence<T>),
|
||||
InStatusEnd(Presence<T>),
|
||||
InCustom(Presence<T>, T::P),
|
||||
}
|
||||
|
||||
impl Parser for PresenceParser {
|
||||
type Output = Result<Presence>;
|
||||
impl<T: FromXml> Parser for PresenceParser<T> {
|
||||
type Output = Result<Presence<T>>;
|
||||
|
||||
fn consume<'a>(
|
||||
self: Self,
|
||||
|
@ -425,8 +440,11 @@ impl Parser for PresenceParser {
|
|||
b"priority" => {
|
||||
Continuation::Continue(PresenceParserInner::InPriority(p).into())
|
||||
}
|
||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||
_ => PresenceParser(PresenceParserInner::InCustom(p, T::parse()))
|
||||
.consume(namespace, event),
|
||||
},
|
||||
Event::Empty(_) => PresenceParser(PresenceParserInner::InCustom(p, T::parse()))
|
||||
.consume(namespace, event),
|
||||
Event::End(_) => Continuation::Final(Ok(p)),
|
||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||
},
|
||||
|
@ -489,24 +507,36 @@ impl Parser for PresenceParser {
|
|||
Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()),
|
||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||
},
|
||||
PresenceParserInner::InCustom(mut p, c) => match c.consume(namespace, event) {
|
||||
Continuation::Final(Ok(res)) => {
|
||||
p.custom.push(res);
|
||||
Continuation::Continue(PresenceParserInner::InPresence(p).into())
|
||||
}
|
||||
Continuation::Final(Err(err)) => Continuation::Final(Err(ffail!(
|
||||
"Failed to parse custom presence element: {err}"
|
||||
))),
|
||||
Continuation::Continue(c) => {
|
||||
Continuation::Continue(PresenceParserInner::InCustom(p, c).into())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromXml for Presence {
|
||||
type P = PresenceParser;
|
||||
impl<T: FromXml> FromXml for Presence<T> {
|
||||
type P = PresenceParser<T>;
|
||||
|
||||
fn parse() -> Self::P {
|
||||
PresenceParserInner::Initial.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromXmlTag for Presence {
|
||||
impl<T: FromXml> FromXmlTag for Presence<T> {
|
||||
const NAME: &'static str = "presence";
|
||||
const NS: &'static str = XMLNS;
|
||||
}
|
||||
|
||||
impl ToXml for Presence {
|
||||
impl<T: ToXml> ToXml for Presence<T> {
|
||||
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
||||
let mut start = BytesStart::new("presence");
|
||||
if let Some(ref to) = self.to {
|
||||
|
|
|
@ -3,6 +3,9 @@ use quick_xml::name::ResolveResult;
|
|||
|
||||
use crate::prelude::Result;
|
||||
|
||||
mod ignore;
|
||||
pub use ignore::Ignore;
|
||||
|
||||
pub trait FromXml: Sized {
|
||||
type P: Parser<Output = Result<Self>>;
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
use super::*;
|
||||
use derive_more::From;
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub struct Ignore;
|
||||
|
||||
#[derive(From)]
|
||||
pub struct IgnoreParser(IgnoreParserInner);
|
||||
|
||||
enum IgnoreParserInner {
|
||||
Initial,
|
||||
InTag { name: Vec<u8>, depth: u8 },
|
||||
}
|
||||
|
||||
impl Parser for IgnoreParser {
|
||||
type Output = Result<Ignore>;
|
||||
|
||||
fn consume<'a>(
|
||||
self: Self,
|
||||
namespace: ResolveResult,
|
||||
event: &Event<'a>,
|
||||
) -> Continuation<Self, Self::Output> {
|
||||
match self.0 {
|
||||
IgnoreParserInner::Initial => match event {
|
||||
Event::Start(bytes) => {
|
||||
let name = bytes.name().0.to_owned();
|
||||
Continuation::Continue(IgnoreParserInner::InTag { name, depth: 0 }.into())
|
||||
}
|
||||
Event::Empty(_) => Continuation::Final(Ok(Ignore)),
|
||||
_ => Continuation::Final(Ok(Ignore)),
|
||||
},
|
||||
IgnoreParserInner::InTag { name, depth } => match event {
|
||||
Event::End(bytes) if name == bytes.name().0 => {
|
||||
if depth == 0 {
|
||||
Continuation::Final(Ok(Ignore))
|
||||
} else {
|
||||
Continuation::Continue(
|
||||
IgnoreParserInner::InTag {
|
||||
name,
|
||||
depth: depth - 1,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => Continuation::Final(Ok(Ignore)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromXml for Ignore {
|
||||
type P = IgnoreParser;
|
||||
|
||||
fn parse() -> Self::P {
|
||||
IgnoreParserInner::Initial.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToXml for () {
|
||||
fn serialize(&self, events: &mut Vec<Event<'static>>) {}
|
||||
}
|
Loading…
Reference in New Issue