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/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
|
use crate::stanza::Stanza;
|
||||||
use crate::stanza_error::StanzaError;
|
use crate::stanza_error::StanzaError;
|
||||||
use crate::util::error::Error;
|
use crate::util::error::Error;
|
||||||
use crate::Element;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -33,6 +33,9 @@ pub mod ns;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
/// Generic Stanza trait
|
||||||
|
pub mod stanza;
|
||||||
|
|
||||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||||
pub mod bind;
|
pub mod bind;
|
||||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
/// 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/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
|
use crate::stanza::Stanza;
|
||||||
use crate::util::error::Error;
|
use crate::util::error::Error;
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use jid::Jid;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -404,4 +441,31 @@ mod tests {
|
||||||
let elem2 = message.into();
|
let elem2 = message.into();
|
||||||
assert_eq!(elem1, elem2);
|
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/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
|
use crate::stanza::Stanza;
|
||||||
use crate::util::error::Error;
|
use crate::util::error::Error;
|
||||||
use jid::Jid;
|
use jid::Jid;
|
||||||
use minidom::{Element, IntoAttributeValue};
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -651,4 +688,25 @@ mod tests {
|
||||||
let elem: Element = presence.into();
|
let elem: Element = presence.into();
|
||||||
assert_eq!(elem.attr("to"), Some("test@localhost/coucou"));
|
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