mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
stanza: new Stanza trait with .payloads method
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
70cba2279e
commit
2de10b53ae
5 changed files with 155 additions and 0 deletions
|
@ -6,6 +6,7 @@
|
|||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use crate::ns;
|
||||
use crate::stanza::Stanza;
|
||||
use crate::stanza_error::StanzaError;
|
||||
use crate::util::error::Error;
|
||||
use crate::Element;
|
||||
|
@ -224,6 +225,21 @@ impl From<Iq> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
impl Stanza for Iq {
|
||||
fn payloads(&self) -> Box<dyn Iterator<Item = Element>> {
|
||||
Box::new(
|
||||
match &self.payload {
|
||||
IqType::Get(elem) | IqType::Set(elem) | IqType::Result(Some(elem)) => {
|
||||
Some(elem.clone())
|
||||
}
|
||||
IqType::Error(error) => Some(Into::into(error.clone())),
|
||||
IqType::Result(None) => None,
|
||||
}
|
||||
.into_iter(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -33,6 +33,9 @@ pub mod ns;
|
|||
#[macro_use]
|
||||
mod util;
|
||||
|
||||
/// Generic Stanza trait
|
||||
pub mod stanza;
|
||||
|
||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||
pub mod bind;
|
||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use crate::ns;
|
||||
use crate::stanza::Stanza;
|
||||
use crate::util::error::Error;
|
||||
use crate::Element;
|
||||
use jid::Jid;
|
||||
|
@ -238,6 +239,42 @@ impl From<Message> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
impl Stanza for Message {
|
||||
fn payloads(&self) -> Box<dyn Iterator<Item = Element>> {
|
||||
Box::new(
|
||||
self.bodies
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(lang, body)| {
|
||||
Element::builder("body", ns::DEFAULT_NS)
|
||||
.attr(
|
||||
"xml:lang",
|
||||
match lang.as_ref() {
|
||||
"" => None,
|
||||
lang => Some(lang),
|
||||
},
|
||||
)
|
||||
.append(body)
|
||||
.build()
|
||||
})
|
||||
.chain(self.subjects.clone().into_iter().map(|(lang, subject)| {
|
||||
Element::builder("subject", ns::DEFAULT_NS)
|
||||
.attr(
|
||||
"xml:lang",
|
||||
match lang.as_ref() {
|
||||
"" => None,
|
||||
lang => Some(lang),
|
||||
},
|
||||
)
|
||||
.append(subject)
|
||||
.build()
|
||||
}))
|
||||
.chain(self.thread.clone().map(Into::into).into_iter())
|
||||
.chain(self.payloads.clone().into_iter()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -404,4 +441,31 @@ mod tests {
|
|||
let elem2 = message.into();
|
||||
assert_eq!(elem1, elem2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_stanza_payloads() {
|
||||
let mut message = Message::new(None);
|
||||
message.thread = Some(Thread::from_str("thread-id").unwrap());
|
||||
message.bodies = BTreeMap::new();
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(""), Body::from_str("Body").unwrap());
|
||||
message.payloads = vec![Element::builder("x", "urn:xmpp:example").build()];
|
||||
|
||||
let mut sorted: Vec<Element> = message.payloads().collect::<Vec<Element>>();
|
||||
sorted.sort_by(|e1, e2| Ord::cmp(e1.name(), e2.name()));
|
||||
|
||||
let res: Vec<Element> = vec![
|
||||
Element::builder("body", ns::DEFAULT_NS)
|
||||
.attr("xml:lang", None::<String>)
|
||||
.append(Body::from_str("Body").unwrap())
|
||||
.build(),
|
||||
Element::builder("thread", ns::DEFAULT_NS)
|
||||
.append(String::from("thread-id"))
|
||||
.build(),
|
||||
Element::builder("x", "urn:xmpp:example").build(),
|
||||
];
|
||||
|
||||
assert_eq!(sorted, res);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use crate::ns;
|
||||
use crate::stanza::Stanza;
|
||||
use crate::util::error::Error;
|
||||
use jid::Jid;
|
||||
use minidom::{Element, IntoAttributeValue};
|
||||
|
@ -333,6 +334,42 @@ impl From<Presence> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
impl Stanza for Presence {
|
||||
fn payloads(&self) -> Box<dyn Iterator<Item = Element> + '_> {
|
||||
Box::new(
|
||||
self.statuses
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(lang, status)| {
|
||||
Element::builder("status", ns::DEFAULT_NS)
|
||||
.attr(
|
||||
"xml:lang",
|
||||
match lang.as_ref() {
|
||||
"" => None,
|
||||
lang => Some(lang),
|
||||
},
|
||||
)
|
||||
.append(status)
|
||||
.build()
|
||||
})
|
||||
.chain(
|
||||
if self.priority == 0 {
|
||||
None
|
||||
} else {
|
||||
Some({
|
||||
Element::builder("priority", ns::DEFAULT_NS)
|
||||
.append(format!("{}", &self.priority))
|
||||
.build()
|
||||
})
|
||||
}
|
||||
.into_iter(),
|
||||
)
|
||||
.chain(self.show.as_ref().into_iter().cloned().map(Into::into))
|
||||
.chain(self.payloads.clone().into_iter()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -651,4 +688,25 @@ mod tests {
|
|||
let elem: Element = presence.into();
|
||||
assert_eq!(elem.attr("to"), Some("test@localhost/coucou"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn presence_stanza_payloads() {
|
||||
let presence = Presence::new(Type::None)
|
||||
.with_priority(42)
|
||||
.with_show(Show::Away)
|
||||
.with_payloads(vec![Element::builder("x", "urn:xmpp:example").build()]);
|
||||
|
||||
let mut sorted: Vec<Element> = presence.payloads().collect::<Vec<Element>>();
|
||||
sorted.sort_by(|e1, e2| Ord::cmp(e1.name(), e2.name()));
|
||||
|
||||
let res: Vec<Element> = vec![
|
||||
Element::builder("priority", ns::DEFAULT_NS)
|
||||
.append(String::from("42"))
|
||||
.build(),
|
||||
Show::Away.into(),
|
||||
Element::builder("x", "urn:xmpp:example").build(),
|
||||
];
|
||||
|
||||
assert_eq!(sorted, res);
|
||||
}
|
||||
}
|
||||
|
|
14
parsers/src/stanza.rs
Normal file
14
parsers/src/stanza.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2022 Maxime “pep” Buquet <pep@bouah.net>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// 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/.
|
||||
|
||||
use minidom::Element;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Generic trait for user libraries to use
|
||||
pub trait Stanza: TryFrom<Element> + Into<Element> {
|
||||
/// Returns an iterator over all children elements of the stanza
|
||||
fn payloads(&self) -> Box<dyn Iterator<Item = Element> + '_>;
|
||||
}
|
Loading…
Reference in a new issue