use std::str::FromStr;
use jid::JID;
use peanuts::{
element::{FromElement, IntoElement},
DeserializeError, Element,
};
use crate::xep_0004::X;
pub const XMLNS: &str = "http://jabber.org/protocol/pubsub#owner";
#[derive(Clone, Debug)]
pub enum Pubsub {
Affiliations(Affiliations),
Configure(Configure),
Default(Default),
Delete(Delete),
Purge(Purge),
Subscriptions(Subscriptions),
}
impl FromElement for Pubsub {
fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("pubsub")?;
element.check_namespace(XMLNS)?;
let child = element.pop_child_one::<Element>()?;
match child.identify() {
(Some(XMLNS), "affiliations") => {
Ok(Self::Affiliations(Affiliations::from_element(child)?))
}
(Some(XMLNS), "configure") => Ok(Self::Configure(Configure::from_element(child)?)),
(Some(XMLNS), "default") => Ok(Self::Default(Default::from_element(child)?)),
(Some(XMLNS), "delete") => Ok(Self::Delete(Delete::from_element(child)?)),
(Some(XMLNS), "purge") => Ok(Self::Purge(Purge::from_element(child)?)),
(Some(XMLNS), "subscriptions") => {
Ok(Self::Subscriptions(Subscriptions::from_element(child)?))
}
_ => Err(DeserializeError::UnexpectedElement(child)),
}
}
}
impl IntoElement for Pubsub {
fn builder(&self) -> peanuts::element::ElementBuilder {
let builder = Element::builder("pubsub", Some(XMLNS));
match self {
Pubsub::Affiliations(affiliations) => builder.push_child(affiliations.clone()),
Pubsub::Configure(configure) => builder.push_child(configure.clone()),
Pubsub::Default(default) => builder.push_child(default.clone()),
Pubsub::Delete(delete) => builder.push_child(delete.clone()),
Pubsub::Purge(purge) => builder.push_child(purge.clone()),
Pubsub::Subscriptions(subscriptions) => builder.push_child(subscriptions.clone()),
}
}
}
#[derive(Clone, Debug)]
pub struct Affiliations {
node: String,
affiliations: Vec<Affiliation>,
}
impl FromElement for Affiliations {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("affiliations")?;
element.check_namespace(XMLNS)?;
let node = element.attribute("node")?;
let affiliations = element.pop_children()?;
Ok(Self { node, affiliations })
}
}
impl IntoElement for Affiliations {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("affiliations", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_children(self.affiliations.clone())
}
}
#[derive(Clone, Debug)]
pub struct Affiliation {
affiliation: AffiliationType,
jid: JID,
}
impl FromElement for Affiliation {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("affiliation")?;
element.check_namespace(XMLNS)?;
let affiliation = element.attribute("affiliation")?;
let jid = element.attribute("jid")?;
Ok(Self { affiliation, jid })
}
}
impl IntoElement for Affiliation {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("affiliation", Some(XMLNS))
.push_attribute("affiliation", self.affiliation.clone())
.push_attribute("jid", self.jid.clone())
}
}
#[derive(Clone, Debug)]
pub enum AffiliationType {
Member,
None,
Outcast,
Owner,
Publisher,
PublishOnly,
}
impl FromStr for AffiliationType {
type Err = DeserializeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"member" => Ok(Self::Member),
"none" => Ok(Self::None),
"outcast" => Ok(Self::Outcast),
"owner" => Ok(Self::Owner),
"publisher" => Ok(Self::Publisher),
"publish-only" => Ok(Self::PublishOnly),
s => Err(DeserializeError::FromStr(s.to_owned())),
}
}
}
impl ToString for AffiliationType {
fn to_string(&self) -> String {
match self {
AffiliationType::Member => "member",
AffiliationType::None => "none",
AffiliationType::Outcast => "outcast",
AffiliationType::Owner => "owner",
AffiliationType::Publisher => "publisher",
AffiliationType::PublishOnly => "publish-only",
}
.to_owned()
}
}
#[derive(Clone, Debug)]
pub struct Configure {
node: Option<String>,
configure: Option<X>,
}
impl FromElement for Configure {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("configure")?;
element.check_namespace(XMLNS)?;
let node = element.attribute_opt("node")?;
let configure = element.pop_child_opt()?;
Ok(Self { node, configure })
}
}
impl IntoElement for Configure {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("configure", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_child_opt(self.configure.clone())
}
}
#[derive(Clone, Debug)]
pub struct Default(Option<X>);
impl FromElement for Default {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("default")?;
element.check_namespace(XMLNS)?;
Ok(Self(element.pop_child_opt()?))
}
}
impl IntoElement for Default {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("default", Some(XMLNS)).push_child_opt(self.0.clone())
}
}
#[derive(Clone, Debug)]
pub struct Delete {
node: String,
redirect: Option<Redirect>,
}
impl FromElement for Delete {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("delete")?;
element.check_namespace(XMLNS)?;
let node = element.attribute("node")?;
let redirect = element.pop_child_opt()?;
Ok(Self { node, redirect })
}
}
impl IntoElement for Delete {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("delete", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_child_opt(self.redirect.clone())
}
}
#[derive(Clone, Debug)]
pub struct Purge {
node: String,
}
impl FromElement for Purge {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("purge")?;
element.check_namespace(XMLNS)?;
let node = element.attribute("node")?;
Ok(Self { node })
}
}
impl IntoElement for Purge {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("purge", Some(XMLNS)).push_attribute("node", self.node.clone())
}
}
#[derive(Clone, Debug)]
pub struct Redirect {
uri: String,
}
impl FromElement for Redirect {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("redirect")?;
element.check_namespace(XMLNS)?;
let uri = element.attribute("uri")?;
Ok(Self { uri })
}
}
impl IntoElement for Redirect {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("redirect", Some(XMLNS)).push_attribute("uri", self.uri.clone())
}
}
#[derive(Clone, Debug)]
pub struct Subscriptions {
node: String,
subscriptions: Vec<Subscription>,
}
impl FromElement for Subscriptions {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("subscriptions")?;
element.check_namespace(XMLNS)?;
let node = element.attribute("node")?;
let subscriptions = element.pop_children()?;
Ok(Self {
node,
subscriptions,
})
}
}
impl IntoElement for Subscriptions {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("subscriptions", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_children(self.subscriptions.clone())
}
}
#[derive(Clone, Debug)]
pub struct Subscription {
subscription: SubscriptionState,
jid: JID,
}
impl FromElement for Subscription {
fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("subscription")?;
element.check_namespace(XMLNS)?;
let subscription = element.attribute("subscription")?;
let jid = element.attribute("jid")?;
Ok(Self { subscription, jid })
}
}
impl IntoElement for Subscription {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("subscription", Some(XMLNS))
.push_attribute("subscription", self.subscription.clone())
.push_attribute("jid", self.jid.clone())
}
}
#[derive(Clone, Debug)]
pub enum SubscriptionState {
None,
Pending,
Subscribed,
Unconfigured,
}
impl FromStr for SubscriptionState {
type Err = DeserializeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"none" => Ok(Self::None),
"pending" => Ok(Self::Pending),
"subscribed" => Ok(Self::Subscribed),
"unconfigured" => Ok(Self::Unconfigured),
s => Err(DeserializeError::FromStr(s.to_owned())),
}
}
}
impl ToString for SubscriptionState {
fn to_string(&self) -> String {
match self {
SubscriptionState::None => "none",
SubscriptionState::Pending => "pending",
SubscriptionState::Subscribed => "subscribed",
SubscriptionState::Unconfigured => "unconfigured",
}
.to_owned()
}
}