xmpp-parsers: Convert Forwarded to xso

This commit is contained in:
Emmanuel Gil Peyrot 2024-08-09 15:38:49 +02:00 committed by Jonas Schäfer
commit cb2c4133fe
4 changed files with 75 additions and 25 deletions

View file

@ -19,6 +19,11 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
check whether a child element is present or not, as this is currently check whether a child element is present or not, as this is currently
implemented in xso. We might revert that change if we implement flag implemented in xso. We might revert that change if we implement flag
metas in xso before the next release. metas in xso before the next release.
- The forwarding module now hardcodes that its child is a message in the
jabber:client namespace. It previously half-followed the schema, but
nothing so far uses it for anything but this message. We can always
change it again once any other specification allows e.g. presences or
iqs.
* New parsers/serialisers: * New parsers/serialisers:
- Stream Features (RFC 6120) (!400) - Stream Features (RFC 6120) (!400)
- Extensible SASL Profile (XEP-0388) - Extensible SASL Profile (XEP-0388)

View file

@ -58,6 +58,7 @@ impl MessagePayload for Sent {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use jid::Jid;
use minidom::Element; use minidom::Element;
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
@ -104,7 +105,14 @@ mod tests {
.parse() .parse()
.unwrap(); .unwrap();
let received = Received::try_from(elem).unwrap(); let received = Received::try_from(elem).unwrap();
assert!(received.forwarded.stanza.is_some()); assert_eq!(
received.forwarded.message.to.unwrap(),
Jid::new("juliet@capulet.example/balcony").unwrap()
);
assert_eq!(
received.forwarded.message.from.unwrap(),
Jid::new("romeo@montague.example/home").unwrap()
);
let elem: Element = "<sent xmlns='urn:xmpp:carbons:2'> let elem: Element = "<sent xmlns='urn:xmpp:carbons:2'>
<forwarded xmlns='urn:xmpp:forward:0'> <forwarded xmlns='urn:xmpp:forward:0'>
@ -116,7 +124,14 @@ mod tests {
.parse() .parse()
.unwrap(); .unwrap();
let sent = Sent::try_from(elem).unwrap(); let sent = Sent::try_from(elem).unwrap();
assert!(sent.forwarded.stanza.is_some()); assert_eq!(
sent.forwarded.message.to.unwrap(),
Jid::new("juliet@capulet.example/balcony").unwrap()
);
assert_eq!(
sent.forwarded.message.from.unwrap(),
Jid::new("romeo@montague.example/home").unwrap()
);
} }
#[test] #[test]

View file

@ -4,24 +4,29 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{AsXml, FromXml};
use crate::delay::Delay; use crate::delay::Delay;
use crate::message::Message; use crate::message::Message;
use crate::ns;
generate_element!( /// Contains a forwarded stanza, either standalone or part of another
/// Contains a forwarded stanza, either standalone or part of another /// extension (such as carbons).
/// extension (such as carbons). #[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
Forwarded, "forwarded", FORWARD, #[xml(namespace = ns::FORWARD, name = "forwarded")]
children: [ pub struct Forwarded {
/// When the stanza originally got sent. /// When the stanza originally got sent.
delay: Option<Delay> = ("delay", DELAY) => Delay, #[xml(child(default))]
pub delay: Option<Delay>,
// XXX: really? Option? /// The stanza being forwarded.
/// The stanza being forwarded. // The schema says that we should allow either a Message, Presence or Iq, in either
stanza: Option<Message> = ("message", DEFAULT_NS) => Message // jabber:client or jabber:server, but in the wild so far weve only seen Message being
// transmitted, so lets hardcode that for now. The schema also makes it optional, but so far
// TODO: also handle the two other stanza possibilities. // its always present (or this wrapper is useless).
] #[xml(child)]
); pub message: Message,
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -43,7 +48,10 @@ mod tests {
#[test] #[test]
fn test_simple() { fn test_simple() {
let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'/>".parse().unwrap(); let elem: Element =
"<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/></forwarded>"
.parse()
.unwrap();
Forwarded::try_from(elem).unwrap(); Forwarded::try_from(elem).unwrap();
} }
@ -57,15 +65,15 @@ mod tests {
FromElementError::Invalid(Error::Other(string)) => string, FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(), _ => panic!(),
}; };
assert_eq!(message, "Unknown child in forwarded element."); assert_eq!(message, "Unknown child in Forwarded element.");
} }
#[test] #[test]
fn test_serialise() { fn test_serialise() {
let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'/>".parse().unwrap(); let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client' type='chat'/></forwarded>".parse().unwrap();
let forwarded = Forwarded { let forwarded = Forwarded {
delay: None, delay: None,
stanza: None, message: Message::new(None),
}; };
let elem2 = forwarded.into(); let elem2 = forwarded.into();
assert_eq!(elem, elem2); assert_eq!(elem, elem2);
@ -90,7 +98,7 @@ mod tests {
let forwarded = Forwarded { let forwarded = Forwarded {
delay: Some(delay), delay: Some(delay),
stanza: Some(message), message,
}; };
let serialized: Element = forwarded.into(); let serialized: Element = forwarded.into();
@ -109,7 +117,7 @@ mod tests {
}; };
assert_eq!( assert_eq!(
message, message,
"Element forwarded must not have more than one delay child." "Forwarded element must not have more than one child in field 'delay'."
); );
} }
@ -125,7 +133,7 @@ mod tests {
}; };
assert_eq!( assert_eq!(
message, message,
"Element forwarded must not have more than one message child." "Forwarded element must not have more than one child in field 'message'."
); );
} }
} }

View file

@ -330,6 +330,28 @@ impl From<Message> for Element {
} }
} }
impl ::xso::FromXml for Message {
type Builder = ::xso::minidom_compat::FromEventsViaElement<Message>;
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.0 != crate::ns::DEFAULT_NS || qname.1 != "message" {
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });
}
Self::Builder::new(qname, attrs)
}
}
impl ::xso::AsXml for Message {
type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>;
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, ::xso::error::Error> {
::xso::minidom_compat::AsItemsViaElement::new(self.clone())
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;