diff --git a/xmpp-parsers/doap.xml b/xmpp-parsers/doap.xml
index bb6352f..31d6e13 100644
--- a/xmpp-parsers/doap.xml
+++ b/xmpp-parsers/doap.xml
@@ -415,7 +415,7 @@
complete
- 0.6.3
+ 0.7.5
0.1.0
@@ -531,6 +531,14 @@
0.16.0
+
+
+
+ complete
+ 0.2.0
+ 0.1.0
+
+
diff --git a/xmpp-parsers/src/lib.rs b/xmpp-parsers/src/lib.rs
index 673e7e4..d18f399 100644
--- a/xmpp-parsers/src/lib.rs
+++ b/xmpp-parsers/src/lib.rs
@@ -224,3 +224,6 @@ pub mod bookmarks2;
/// XEP-0421: Anonymous unique occupant identifiers for MUCs
pub mod occupant_id;
+
+/// XEP-0441: Message Archive Management Preferences
+pub mod mam_prefs;
diff --git a/xmpp-parsers/src/mam.rs b/xmpp-parsers/src/mam.rs
index b77aac3..eff0065 100644
--- a/xmpp-parsers/src/mam.rs
+++ b/xmpp-parsers/src/mam.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Emmanuel Gil Peyrot
+// Copyright (c) 2017-2021 Emmanuel Gil Peyrot
//
// 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
@@ -8,13 +8,8 @@ use crate::data_forms::DataForm;
use crate::forwarding::Forwarded;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::message::MessagePayload;
-use crate::ns;
use crate::pubsub::NodeName;
use crate::rsm::{SetQuery, SetResult};
-use crate::util::error::Error;
-use jid::Jid;
-use minidom::{Element, Node};
-use std::convert::TryFrom;
generate_id!(
/// An identifier matching a result message to the query requesting it.
@@ -92,105 +87,12 @@ generate_element!(
impl IqResultPayload for Fin {}
-generate_attribute!(
- /// Notes the default archiving preference for the user.
- DefaultPrefs, "default", {
- /// The default is to always log messages in the archive.
- Always => "always",
-
- /// The default is to never log messages in the archive.
- Never => "never",
-
- /// The default is to log messages in the archive only for contacts
- /// present in the user’s [roster](../roster/index.html).
- Roster => "roster",
- }
-);
-
-/// Controls the archiving preferences of the user.
-#[derive(Debug, Clone)]
-pub struct Prefs {
- /// The default preference for JIDs in neither
- /// [always](#structfield.always) or [never](#structfield.never) lists.
- pub default_: DefaultPrefs,
-
- /// The set of JIDs for which to always store messages in the archive.
- pub always: Vec,
-
- /// The set of JIDs for which to never store messages in the archive.
- pub never: Vec,
-}
-
-impl IqGetPayload for Prefs {}
-impl IqSetPayload for Prefs {}
-impl IqResultPayload for Prefs {}
-
-impl TryFrom for Prefs {
- type Error = Error;
-
- fn try_from(elem: Element) -> Result {
- check_self!(elem, "prefs", MAM);
- check_no_unknown_attributes!(elem, "prefs", ["default"]);
- let mut always = vec![];
- let mut never = vec![];
- for child in elem.children() {
- if child.is("always", ns::MAM) {
- for jid_elem in child.children() {
- if !jid_elem.is("jid", ns::MAM) {
- return Err(Error::ParseError("Invalid jid element in always."));
- }
- always.push(jid_elem.text().parse()?);
- }
- } else if child.is("never", ns::MAM) {
- for jid_elem in child.children() {
- if !jid_elem.is("jid", ns::MAM) {
- return Err(Error::ParseError("Invalid jid element in never."));
- }
- never.push(jid_elem.text().parse()?);
- }
- } else {
- return Err(Error::ParseError("Unknown child in prefs element."));
- }
- }
- let default_ = get_attr!(elem, "default", Required);
- Ok(Prefs {
- default_,
- always,
- never,
- })
- }
-}
-
-fn serialise_jid_list(name: &str, jids: Vec) -> ::std::option::IntoIter {
- if jids.is_empty() {
- None.into_iter()
- } else {
- Some(
- Element::builder(name, ns::MAM)
- .append_all(
- jids.into_iter()
- .map(|jid| Element::builder("jid", ns::MAM).append(String::from(jid))),
- )
- .into(),
- )
- .into_iter()
- }
-}
-
-impl From for Element {
- fn from(prefs: Prefs) -> Element {
- Element::builder("prefs", ns::MAM)
- .attr("default", prefs.default_)
- .append_all(serialise_jid_list("always", prefs.always))
- .append_all(serialise_jid_list("never", prefs.never))
- .build()
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
- use jid::BareJid;
+ use crate::util::error::Error;
+ use minidom::Element;
+ use std::convert::TryFrom;
#[cfg(target_pointer_width = "32")]
#[test]
@@ -200,8 +102,6 @@ mod tests {
assert_size!(Result_, 236);
assert_size!(Complete, 1);
assert_size!(Fin, 44);
- assert_size!(DefaultPrefs, 1);
- assert_size!(Prefs, 28);
}
#[cfg(target_pointer_width = "64")]
@@ -212,8 +112,6 @@ mod tests {
assert_size!(Result_, 456);
assert_size!(Complete, 1);
assert_size!(Fin, 88);
- assert_size!(DefaultPrefs, 1);
- assert_size!(Prefs, 56);
}
#[test]
@@ -307,54 +205,6 @@ mod tests {
Query::try_from(elem).unwrap();
}
- #[test]
- fn test_prefs_get() {
- let elem: Element = ""
- .parse()
- .unwrap();
- let prefs = Prefs::try_from(elem).unwrap();
- assert!(prefs.always.is_empty());
- assert!(prefs.never.is_empty());
-
- let elem: Element = r#"
-
-
-
-
-"#
- .parse()
- .unwrap();
- let prefs = Prefs::try_from(elem).unwrap();
- assert!(prefs.always.is_empty());
- assert!(prefs.never.is_empty());
- }
-
- #[test]
- fn test_prefs_result() {
- let elem: Element = r#"
-
-
- romeo@montague.lit
-
-
- montague@montague.lit
-
-
-"#
- .parse()
- .unwrap();
- let prefs = Prefs::try_from(elem).unwrap();
- assert_eq!(prefs.always, [BareJid::new("romeo", "montague.lit")]);
- assert_eq!(prefs.never, [BareJid::new("montague", "montague.lit")]);
-
- let elem2 = Element::from(prefs.clone());
- println!("{:?}", elem2);
- let prefs2 = Prefs::try_from(elem2).unwrap();
- assert_eq!(prefs.default_, prefs2.default_);
- assert_eq!(prefs.always, prefs2.always);
- assert_eq!(prefs.never, prefs2.never);
- }
-
#[test]
fn test_invalid_child() {
let elem: Element = ""
diff --git a/xmpp-parsers/src/mam_prefs.rs b/xmpp-parsers/src/mam_prefs.rs
new file mode 100644
index 0000000..04e8663
--- /dev/null
+++ b/xmpp-parsers/src/mam_prefs.rs
@@ -0,0 +1,175 @@
+// Copyright (c) 2021 Emmanuel Gil Peyrot
+//
+// 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 crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
+use crate::ns;
+use crate::util::error::Error;
+use jid::Jid;
+use minidom::{Element, Node};
+use std::convert::TryFrom;
+
+generate_attribute!(
+ /// Notes the default archiving preference for the user.
+ DefaultPrefs, "default", {
+ /// The default is to always log messages in the archive.
+ Always => "always",
+
+ /// The default is to never log messages in the archive.
+ Never => "never",
+
+ /// The default is to log messages in the archive only for contacts
+ /// present in the user’s [roster](../roster/index.html).
+ Roster => "roster",
+ }
+);
+
+/// Controls the archiving preferences of the user.
+#[derive(Debug, Clone)]
+pub struct Prefs {
+ /// The default preference for JIDs in neither
+ /// [always](#structfield.always) or [never](#structfield.never) lists.
+ pub default_: DefaultPrefs,
+
+ /// The set of JIDs for which to always store messages in the archive.
+ pub always: Vec,
+
+ /// The set of JIDs for which to never store messages in the archive.
+ pub never: Vec,
+}
+
+impl IqGetPayload for Prefs {}
+impl IqSetPayload for Prefs {}
+impl IqResultPayload for Prefs {}
+
+impl TryFrom for Prefs {
+ type Error = Error;
+
+ fn try_from(elem: Element) -> Result {
+ check_self!(elem, "prefs", MAM);
+ check_no_unknown_attributes!(elem, "prefs", ["default"]);
+ let mut always = vec![];
+ let mut never = vec![];
+ for child in elem.children() {
+ if child.is("always", ns::MAM) {
+ for jid_elem in child.children() {
+ if !jid_elem.is("jid", ns::MAM) {
+ return Err(Error::ParseError("Invalid jid element in always."));
+ }
+ always.push(jid_elem.text().parse()?);
+ }
+ } else if child.is("never", ns::MAM) {
+ for jid_elem in child.children() {
+ if !jid_elem.is("jid", ns::MAM) {
+ return Err(Error::ParseError("Invalid jid element in never."));
+ }
+ never.push(jid_elem.text().parse()?);
+ }
+ } else {
+ return Err(Error::ParseError("Unknown child in prefs element."));
+ }
+ }
+ let default_ = get_attr!(elem, "default", Required);
+ Ok(Prefs {
+ default_,
+ always,
+ never,
+ })
+ }
+}
+
+fn serialise_jid_list(name: &str, jids: Vec) -> ::std::option::IntoIter {
+ if jids.is_empty() {
+ None.into_iter()
+ } else {
+ Some(
+ Element::builder(name, ns::MAM)
+ .append_all(
+ jids.into_iter()
+ .map(|jid| Element::builder("jid", ns::MAM).append(String::from(jid))),
+ )
+ .into(),
+ )
+ .into_iter()
+ }
+}
+
+impl From for Element {
+ fn from(prefs: Prefs) -> Element {
+ Element::builder("prefs", ns::MAM)
+ .attr("default", prefs.default_)
+ .append_all(serialise_jid_list("always", prefs.always))
+ .append_all(serialise_jid_list("never", prefs.never))
+ .build()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use jid::BareJid;
+
+ #[cfg(target_pointer_width = "32")]
+ #[test]
+ fn test_size() {
+ assert_size!(DefaultPrefs, 1);
+ assert_size!(Prefs, 28);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_size() {
+ assert_size!(DefaultPrefs, 1);
+ assert_size!(Prefs, 56);
+ }
+
+ #[test]
+ fn test_prefs_get() {
+ let elem: Element = ""
+ .parse()
+ .unwrap();
+ let prefs = Prefs::try_from(elem).unwrap();
+ assert!(prefs.always.is_empty());
+ assert!(prefs.never.is_empty());
+
+ let elem: Element = r#"
+
+
+
+
+"#
+ .parse()
+ .unwrap();
+ let prefs = Prefs::try_from(elem).unwrap();
+ assert!(prefs.always.is_empty());
+ assert!(prefs.never.is_empty());
+ }
+
+ #[test]
+ fn test_prefs_result() {
+ let elem: Element = r#"
+
+
+ romeo@montague.lit
+
+
+ montague@montague.lit
+
+
+"#
+ .parse()
+ .unwrap();
+ let prefs = Prefs::try_from(elem).unwrap();
+ assert_eq!(prefs.always, [BareJid::new("romeo", "montague.lit")]);
+ assert_eq!(prefs.never, [BareJid::new("montague", "montague.lit")]);
+
+ let elem2 = Element::from(prefs.clone());
+ println!("{:?}", elem2);
+ let prefs2 = Prefs::try_from(elem2).unwrap();
+ assert_eq!(prefs.default_, prefs2.default_);
+ assert_eq!(prefs.always, prefs2.always);
+ assert_eq!(prefs.never, prefs2.never);
+ }
+}