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::Message(_) => todo!(),
|
||||||
proto::ClientPacket::Presence(p) => {
|
proto::ClientPacket::Presence(p) => {
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
let response = Presence {
|
let response = Presence::<()> {
|
||||||
to: Some("darova@localhost/kek".to_string()),
|
to: Some("darova@localhost/kek".to_string()),
|
||||||
from: Some("darova@localhost/kek".to_string()),
|
from: Some("darova@localhost/kek".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl Parser for IqClientBodyParser {
|
||||||
pub enum ClientPacket {
|
pub enum ClientPacket {
|
||||||
Iq(Iq<IqClientBody>),
|
Iq(Iq<IqClientBody>),
|
||||||
Message(Message),
|
Message(Message),
|
||||||
Presence(Presence),
|
Presence(Presence<Ignore>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(From)]
|
#[derive(From)]
|
||||||
|
@ -91,7 +91,7 @@ enum ClientPacketParserInner {
|
||||||
Initial,
|
Initial,
|
||||||
IqV(<Iq<IqClientBody> as FromXml>::P),
|
IqV(<Iq<IqClientBody> as FromXml>::P),
|
||||||
MessageV(<Message as FromXml>::P),
|
MessageV(<Message as FromXml>::P),
|
||||||
PresenceV(<Presence as FromXml>::P),
|
PresenceV(<Presence<Ignore> as FromXml>::P),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser for ClientPacketParser {
|
impl Parser for ClientPacketParser {
|
||||||
|
@ -111,7 +111,7 @@ impl Parser for ClientPacketParser {
|
||||||
let name = bytes.name();
|
let name = bytes.name();
|
||||||
match_parser!(ClientPacketParser, name, namespace, event;
|
match_parser!(ClientPacketParser, name, namespace, event;
|
||||||
Iq::<IqClientBody>,
|
Iq::<IqClientBody>,
|
||||||
Presence,
|
Presence::<Ignore>,
|
||||||
Message
|
Message
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,13 +342,27 @@ impl<T: ToXml> ToXml for Iq<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Default)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub struct Presence {
|
pub struct Presence<T> {
|
||||||
pub to: Option<String>,
|
pub to: Option<String>,
|
||||||
pub from: Option<String>,
|
pub from: Option<String>,
|
||||||
pub priority: Option<PresencePriority>,
|
pub priority: Option<PresencePriority>,
|
||||||
pub show: Option<PresenceShow>,
|
pub show: Option<PresenceShow>,
|
||||||
pub status: Vec<String>,
|
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)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
|
@ -389,20 +403,21 @@ impl PresenceShow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(From)]
|
#[derive(From)]
|
||||||
pub struct PresenceParser(PresenceParserInner);
|
pub struct PresenceParser<T: FromXml>(PresenceParserInner<T>);
|
||||||
enum PresenceParserInner {
|
enum PresenceParserInner<T: FromXml> {
|
||||||
Initial,
|
Initial,
|
||||||
InPresence(Presence),
|
InPresence(Presence<T>),
|
||||||
InPriority(Presence),
|
InPriority(Presence<T>),
|
||||||
InPriorityEnd(Presence),
|
InPriorityEnd(Presence<T>),
|
||||||
InShow(Presence),
|
InShow(Presence<T>),
|
||||||
InShowEnd(Presence),
|
InShowEnd(Presence<T>),
|
||||||
InStatus(Presence),
|
InStatus(Presence<T>),
|
||||||
InStatusEnd(Presence),
|
InStatusEnd(Presence<T>),
|
||||||
|
InCustom(Presence<T>, T::P),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser for PresenceParser {
|
impl<T: FromXml> Parser for PresenceParser<T> {
|
||||||
type Output = Result<Presence>;
|
type Output = Result<Presence<T>>;
|
||||||
|
|
||||||
fn consume<'a>(
|
fn consume<'a>(
|
||||||
self: Self,
|
self: Self,
|
||||||
|
@ -425,8 +440,11 @@ impl Parser for PresenceParser {
|
||||||
b"priority" => {
|
b"priority" => {
|
||||||
Continuation::Continue(PresenceParserInner::InPriority(p).into())
|
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)),
|
Event::End(_) => Continuation::Final(Ok(p)),
|
||||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||||
},
|
},
|
||||||
|
@ -489,24 +507,36 @@ impl Parser for PresenceParser {
|
||||||
Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()),
|
Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()),
|
||||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
_ => 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 {
|
impl<T: FromXml> FromXml for Presence<T> {
|
||||||
type P = PresenceParser;
|
type P = PresenceParser<T>;
|
||||||
|
|
||||||
fn parse() -> Self::P {
|
fn parse() -> Self::P {
|
||||||
PresenceParserInner::Initial.into()
|
PresenceParserInner::Initial.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromXmlTag for Presence {
|
impl<T: FromXml> FromXmlTag for Presence<T> {
|
||||||
const NAME: &'static str = "presence";
|
const NAME: &'static str = "presence";
|
||||||
const NS: &'static str = XMLNS;
|
const NS: &'static str = XMLNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToXml for Presence {
|
impl<T: ToXml> ToXml for Presence<T> {
|
||||||
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
||||||
let mut start = BytesStart::new("presence");
|
let mut start = BytesStart::new("presence");
|
||||||
if let Some(ref to) = self.to {
|
if let Some(ref to) = self.to {
|
||||||
|
|
|
@ -3,6 +3,9 @@ use quick_xml::name::ResolveResult;
|
||||||
|
|
||||||
use crate::prelude::Result;
|
use crate::prelude::Result;
|
||||||
|
|
||||||
|
mod ignore;
|
||||||
|
pub use ignore::Ignore;
|
||||||
|
|
||||||
pub trait FromXml: Sized {
|
pub trait FromXml: Sized {
|
||||||
type P: Parser<Output = Result<Self>>;
|
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