, payload: Option) -> Item {
- Item {
- id,
- publisher,
- payload: payload.map(|payload| payload.into()),
- }
- }
-}
+impl_pubsub_item!(Item, PUBSUB_EVENT);
/// Represents an event happening to a PubSub node.
#[derive(Debug, Clone)]
diff --git a/src/pubsub/mod.rs b/src/pubsub/mod.rs
index dd39ea1d..81e4e359 100644
--- a/src/pubsub/mod.rs
+++ b/src/pubsub/mod.rs
@@ -13,6 +13,8 @@ pub mod pubsub;
pub use self::event::PubSubEvent;
pub use self::pubsub::PubSub;
+use crate::{Jid, Element};
+
generate_id!(
/// The name of a PubSub node, used to identify it on a JID.
NodeName
@@ -46,5 +48,29 @@ generate_attribute!(
}, Default = None
);
+/// An item from a PubSub node.
+#[derive(Debug, Clone)]
+pub struct Item {
+ /// The identifier for this item, unique per node.
+ pub id: Option,
+
+ /// The JID of the entity who published this item.
+ pub publisher: Option,
+
+ /// The payload of this item, in an arbitrary namespace.
+ pub payload: Option,
+}
+
+impl Item {
+ /// Create a new item, accepting only payloads implementing `PubSubPayload`.
+ pub fn new(id: Option, publisher: Option, payload: Option) -> Item {
+ Item {
+ id,
+ publisher,
+ payload: payload.map(|payload| payload.into()),
+ }
+ }
+}
+
/// This trait should be implemented on any element which can be included as a PubSub payload.
pub trait PubSubPayload: crate::TryFrom + Into {}
diff --git a/src/pubsub/pubsub.rs b/src/pubsub/pubsub.rs
index 637b050a..c7bb6466 100644
--- a/src/pubsub/pubsub.rs
+++ b/src/pubsub/pubsub.rs
@@ -8,7 +8,7 @@ use crate::data_forms::DataForm;
use crate::util::error::Error;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::ns;
-use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId};
+use crate::pubsub::{NodeName, Subscription, SubscriptionId, Item as PubSubItem};
use jid::Jid;
use minidom::Element;
use try_from::TryFrom;
@@ -113,45 +113,11 @@ generate_element!(
]
);
-/// An item from a PubSub node.
+/// Response wrapper for a PubSub ` `.
#[derive(Debug, Clone)]
-pub struct Item {
- /// The payload of this item, in an arbitrary namespace.
- pub payload: Option,
+pub struct Item(pub PubSubItem);
- /// The 'id' attribute of this item.
- pub id: Option,
-}
-
-impl TryFrom for Item {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result- {
- check_self!(elem, "item", PUBSUB);
- check_no_unknown_attributes!(elem, "item", ["id"]);
- let mut payloads = elem.children().cloned().collect::>();
- let payload = payloads.pop();
- if !payloads.is_empty() {
- return Err(Error::ParseError(
- "More than a single payload in item element.",
- ));
- }
- Ok(Item {
- payload,
- id: get_attr!(elem, "id", optional),
- })
- }
-}
-
-impl From
- for Element {
- fn from(item: Item) -> Element {
- Element::builder("item")
- .ns(ns::PUBSUB)
- .attr("id", item.id)
- .append(item.payload)
- .build()
- }
-}
+impl_pubsub_item!(Item, PUBSUB);
generate_element!(
/// The options associated to a subscription request.
diff --git a/src/util/macros.rs b/src/util/macros.rs
index fd3a0ada..0c296abb 100644
--- a/src/util/macros.rs
+++ b/src/util/macros.rs
@@ -596,3 +596,54 @@ macro_rules! assert_size (
assert_eq!(::std::mem::size_of::<$t>(), $sz);
);
);
+
+// TODO: move that to src/pubsub/mod.rs, once we figure out how to use macros from there.
+macro_rules! impl_pubsub_item {
+ ($item:ident, $ns:ident) => {
+ impl crate::TryFrom for $item {
+ type Err = Error;
+
+ fn try_from(elem: crate::Element) -> Result<$item, Error> {
+ check_self!(elem, "item", $ns);
+ check_no_unknown_attributes!(elem, "item", ["id", "publisher"]);
+ let mut payloads = elem.children().cloned().collect::>();
+ let payload = payloads.pop();
+ if !payloads.is_empty() {
+ return Err(Error::ParseError(
+ "More than a single payload in item element.",
+ ));
+ }
+ Ok($item(crate::pubsub::Item {
+ id: get_attr!(elem, "id", optional),
+ publisher: get_attr!(elem, "publisher", optional),
+ payload,
+ }))
+ }
+ }
+
+ impl From<$item> for crate::Element {
+ fn from(item: $item) -> crate::Element {
+ crate::Element::builder("item")
+ .ns(ns::$ns)
+ .attr("id", item.0.id)
+ .attr("publisher", item.0.publisher)
+ .append(item.0.payload)
+ .build()
+ }
+ }
+
+ impl ::std::ops::Deref for $item {
+ type Target = crate::pubsub::Item;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+ }
+
+ impl ::std::ops::DerefMut for $item {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+ }
+ }
+}