aboutsummaryrefslogblamecommitdiffstats
path: root/stanza/src/xep_0060/owner.rs
blob: 1fedc60805a4466b616fe5d82cad4b28c29363f3 (plain) (tree)





































































































































































































































































































































































                                                                                                 
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()
    }
}