diff --git a/parsers/ChangeLog b/parsers/ChangeLog index 2783a2a4552002680d93356cb2446a3180131dcd..c589ebd4d2aa08cdf28d131331b72a0ff2286723 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -62,6 +62,8 @@ XXXX-YY-ZZ RELEASER having been exchanged, and the stream_id is now a String instead of &str. - Add a lang property in Presence, to avoid parser errors. + - pubsub::Owner is now a wrapper for the pubsub::owner::Paylolad enum, + and all its direct children have been merged into this enum (!532) * New parsers/serialisers: - Stream Features (RFC 6120) (!400) - Spam Reporting (XEP-0377) (!506) diff --git a/parsers/src/pubsub/mod.rs b/parsers/src/pubsub/mod.rs index e4beae2092696e4e33327fc097a3e418e4fb090e..ae8220aa5380c678da5a86df2b448c08865f072b 100644 --- a/parsers/src/pubsub/mod.rs +++ b/parsers/src/pubsub/mod.rs @@ -15,7 +15,7 @@ pub mod owner; pub mod pubsub; pub use self::event::Event; -pub use self::owner::PubSubOwner; +pub use self::owner::Owner; pub use self::pubsub::PubSub; use minidom::Element; diff --git a/parsers/src/pubsub/owner.rs b/parsers/src/pubsub/owner.rs index b371ec5a3509bc3bb88e121386c25ac8236c626e..38c7c3a6b5994a06475736727b9f6e294a1420f3 100644 --- a/parsers/src/pubsub/owner.rs +++ b/parsers/src/pubsub/owner.rs @@ -12,21 +12,6 @@ use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload}; use crate::ns; use crate::pubsub::{AffiliationAttribute, NodeName, Subscription}; use jid::Jid; -use minidom::Element; -use xso::error::{Error, FromElementError}; - -/// A list of affiliations you have on a service, or on a node. -#[derive(FromXml, AsXml, PartialEq, Debug, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "affiliations")] -pub struct Affiliations { - /// The node name this request pertains to. - #[xml(attribute)] - pub node: NodeName, - - /// The actual list of affiliation elements. - #[xml(child(n = ..))] - pub affiliations: Vec, -} /// An affiliation element. #[derive(FromXml, AsXml, PartialEq, Debug, Clone)] @@ -41,72 +26,6 @@ pub struct Affiliation { affiliation: AffiliationAttribute, } -/// Request to configure a node. -#[derive(FromXml, AsXml, Debug, PartialEq, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "configure")] -pub struct Configure { - /// The node to be configured. - #[xml(attribute(default))] - pub node: Option, - - /// The form to configure it. - #[xml(child(default))] - pub form: Option, -} - -/// Request to retrieve default configuration. -#[derive(FromXml, AsXml, Debug, PartialEq, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "default")] -pub struct Default { - /// The form to configure it. - #[xml(child(default))] - pub form: Option, -} - -/// Request to delete a node. -#[derive(FromXml, AsXml, Debug, PartialEq, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "delete")] -pub struct Delete { - /// The node to be deleted. - #[xml(attribute)] - pub node: NodeName, - - /// Redirection to replace the deleted node. - #[xml(child(default))] - pub redirect: Option, -} - -/// A redirect element. -#[derive(FromXml, AsXml, PartialEq, Debug, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "redirect")] -pub struct Redirect { - /// The node this node will be redirected to. - #[xml(attribute)] - pub uri: String, -} - -/// Request to clear a node. -#[derive(FromXml, AsXml, PartialEq, Debug, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "purge")] -pub struct Purge { - /// The node to be cleared. - #[xml(attribute)] - pub node: NodeName, -} - -/// A request for current subscriptions. -#[derive(FromXml, AsXml, PartialEq, Debug, Clone)] -#[xml(namespace = ns::PUBSUB_OWNER, name = "subscriptions")] -pub struct Subscriptions { - /// The node to query. - #[xml(attribute)] - pub node: NodeName, - - /// The list of subscription elements returned. - #[xml(child(n = ..))] - pub subscriptions: Vec, -} - /// A subscription element, describing the state of a subscription. #[derive(FromXml, AsXml, PartialEq, Debug, Clone)] #[xml(namespace = ns::PUBSUB_OWNER, name = "subscription")] @@ -124,68 +43,89 @@ pub struct SubscriptionElem { pub subid: Option, } -/// Main payload used to communicate with a PubSubOwner service. +/// Represents an owner request to a PubSub service. +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::PUBSUB_OWNER, name = "pubsub")] +pub struct Owner { + /// The inner child of this request. + #[xml(child)] + pub payload: Payload, +} + +// TODO: Differentiate each payload per type someday, to simplify our types. +impl IqGetPayload for Owner {} +impl IqSetPayload for Owner {} +impl IqResultPayload for Owner {} + +/// Main payload used to communicate with a PubSub service. /// /// `` -#[derive(Debug, Clone, PartialEq)] -pub enum PubSubOwner { +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::PUBSUB_OWNER, exhaustive)] +pub enum Payload { /// Manage the affiliations of a node. - Affiliations(Affiliations), - /// Request to configure a node, with optional suggested name and suggested configuration. - Configure(Configure), + #[xml(name = "affiliations")] + Affiliations { + /// The node name this request pertains to. + #[xml(attribute)] + node: NodeName, + + /// The actual list of affiliation elements. + #[xml(child(n = ..))] + affiliations: Vec, + }, + + /// Request to configure a node. + #[xml(name = "configure")] + Configure { + /// The node to be configured. + #[xml(attribute(default))] + node: Option, + + /// The form to configure it. + #[xml(child(default))] + form: Option, + }, + /// Request the default node configuration. - Default(Default), + #[xml(name = "default")] + Default { + /// The form to configure it. + #[xml(child(default))] + form: Option, + }, + /// Delete a node. - Delete(Delete), - /// Purge all items from node. - Purge(Purge), - /// Request subscriptions of a node. - Subscriptions(Subscriptions), -} + #[xml(name = "delete")] + Delete { + /// The node to be deleted. + #[xml(attribute)] + node: NodeName, -impl IqGetPayload for PubSubOwner {} -impl IqSetPayload for PubSubOwner {} -impl IqResultPayload for PubSubOwner {} - -impl TryFrom for PubSubOwner { - type Error = FromElementError; - - fn try_from(elem: Element) -> Result { - check_self!(elem, "pubsub", PUBSUB_OWNER); - check_no_attributes!(elem, "pubsub"); - - let mut payload = None; - for child in elem.children() { - if child.is("configure", ns::PUBSUB_OWNER) { - if payload.is_some() { - return Err(Error::Other( - "Payload is already defined in pubsub owner element.", - ) - .into()); - } - let configure = Configure::try_from(child.clone())?; - payload = Some(PubSubOwner::Configure(configure)); - } else { - return Err(Error::Other("Unknown child in pubsub element.").into()); - } - } - payload.ok_or(Error::Other("No payload in pubsub element.").into()) - } -} + /// Redirection to replace the deleted node. + #[xml(extract(default, name = "redirect", fields(attribute(name = "uri", type_ = String))))] + redirect_uri: Option, + }, -impl From for Element { - fn from(pubsub: PubSubOwner) -> Element { - Element::builder("pubsub", ns::PUBSUB_OWNER) - .append_all(match pubsub { - PubSubOwner::Affiliations(affiliations) => vec![Element::from(affiliations)], - PubSubOwner::Configure(configure) => vec![Element::from(configure)], - PubSubOwner::Default(default) => vec![Element::from(default)], - PubSubOwner::Delete(delete) => vec![Element::from(delete)], - PubSubOwner::Purge(purge) => vec![Element::from(purge)], - PubSubOwner::Subscriptions(subscriptions) => vec![Element::from(subscriptions)], - }) - .build() - } + /// Purge all items from node. + #[xml(name = "purge")] + Purge { + /// The node to be cleared. + #[xml(attribute)] + node: NodeName, + }, + + /// Request the current subscriptions to a node. + #[xml(name = "subscriptions")] + Subscriptions { + /// The node to query. + #[xml(attribute)] + node: NodeName, + + /// The list of subscription elements returned. + #[xml(child(n = ..))] + subscriptions: Vec, + }, } #[cfg(test)] @@ -194,6 +134,7 @@ mod tests { use crate::data_forms::{DataFormType, Field, FieldType}; use core::str::FromStr; use jid::BareJid; + use minidom::Element; #[test] fn affiliations() { @@ -202,7 +143,7 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Affiliations(Affiliations { + let payload = Payload::Affiliations { node: NodeName(String::from("foo")), affiliations: vec![ Affiliation { @@ -214,7 +155,8 @@ mod tests { affiliation: AffiliationAttribute::Outcast, }, ], - }); + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2); @@ -227,7 +169,7 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Configure(Configure { + let payload = Payload::Configure { node: Some(NodeName(String::from("foo"))), form: Some(DataForm::new( DataFormType::Submit, @@ -235,7 +177,8 @@ mod tests { vec![Field::new("pubsub#access_model", FieldType::ListSingle) .with_value("whitelist")], )), - }); + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2); @@ -251,10 +194,11 @@ mod tests { let form = DataForm::try_from(elem).unwrap(); - let configure = PubSubOwner::Configure(Configure { + let payload = Payload::Configure { node: Some(NodeName(String::from("foo"))), form: Some(form), - }); + }; + let configure = Owner { payload }; let serialized: Element = configure.into(); assert_eq!(serialized, reference); } @@ -266,14 +210,15 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Default(Default { + let payload = Payload::Default { form: Some(DataForm::new( DataFormType::Submit, ns::PUBSUB_CONFIGURE, vec![Field::new("pubsub#access_model", FieldType::ListSingle) .with_value("whitelist")], )), - }); + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2); @@ -286,12 +231,11 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Delete(Delete { + let payload = Payload::Delete { node: NodeName(String::from("foo")), - redirect: Some(Redirect { - uri: String::from("xmpp:hamlet@denmark.lit?;node=blog"), - }), - }); + redirect_uri: Some(String::from("xmpp:hamlet@denmark.lit?;node=blog")), + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2); @@ -304,9 +248,10 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Purge(Purge { + let payload = Payload::Purge { node: NodeName(String::from("foo")), - }); + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2); @@ -319,7 +264,7 @@ mod tests { .unwrap(); let elem1 = elem.clone(); - let pubsub = PubSubOwner::Subscriptions(Subscriptions { + let payload = Payload::Subscriptions { node: NodeName(String::from("foo")), subscriptions: vec![ SubscriptionElem { @@ -343,7 +288,8 @@ mod tests { subid: Some(String::from("004-yyy")), }, ], - }); + }; + let pubsub = Owner { payload }; let elem2 = Element::from(pubsub); assert_eq!(elem1, elem2);