From d811c10ed350453826dc6167b4d38245c0795625 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 27 Jan 2019 18:57:25 +0100 Subject: [PATCH] pubsub: Make Item common to both pubsub and pubsub#event namespaces. --- src/pubsub/event.rs | 58 +++----------------------------------------- src/pubsub/mod.rs | 26 ++++++++++++++++++++ src/pubsub/pubsub.rs | 42 +++----------------------------- src/util/macros.rs | 51 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 92 deletions(-) diff --git a/src/pubsub/event.rs b/src/pubsub/event.rs index 5e53acb8..e0f2b598 100644 --- a/src/pubsub/event.rs +++ b/src/pubsub/event.rs @@ -8,66 +8,16 @@ use crate::data_forms::DataForm; use crate::date::DateTime; use crate::util::error::Error; use crate::ns; -use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId, PubSubPayload}; +use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId, Item as PubSubItem}; use jid::Jid; use minidom::Element; use try_from::TryFrom; -/// One PubSub item from a node. +/// Event wrapper for a PubSub ``. #[derive(Debug, Clone)] -pub struct Item { - /// The identifier for this item, unique per node. - pub id: Option, +pub struct Item(pub PubSubItem); - /// The JID of the entity who published this item. - pub publisher: Option, - - /// The actual content of this item. - pub payload: Option, -} - -impl TryFrom for Item { - type Err = Error; - - fn try_from(elem: Element) -> Result { - check_self!(elem, "item", PUBSUB_EVENT); - 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 { - payload, - id: get_attr!(elem, "id", optional), - publisher: get_attr!(elem, "publisher", optional), - }) - } -} - -impl From for Element { - fn from(item: Item) -> Element { - Element::builder("item") - .ns(ns::PUBSUB_EVENT) - .attr("id", item.id) - .attr("publisher", item.publisher) - .append(item.payload) - .build() - } -} - -impl Item { - /// Create a new item event, accepting only payloads implementing `PubSubPayload`. - pub fn new(id: Option, publisher: Option, 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 + } + } + } +}