aboutsummaryrefslogblamecommitdiffstats
path: root/src/stanza/sasl.rs
blob: 6ac4fc97ec47f52e448e13ec00f9093befafbd2a (plain) (tree)
1
2
                    
 







































































































































































                                                                                                 
use std::ops::Deref;

use peanuts::{
    element::{FromElement, IntoElement},
    DeserializeError, Element,
};
use tracing::debug;

pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-sasl";

#[derive(Debug, Clone)]
pub struct Mechanisms {
    pub mechanisms: Vec<String>,
}

impl FromElement for Mechanisms {
    fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
        element.check_name("mechanisms")?;
        element.check_namespace(XMLNS)?;
        debug!("getting mechanisms");
        let mechanisms: Vec<Mechanism> = element.pop_children()?;
        debug!("gottting mechanisms");
        let mechanisms = mechanisms
            .into_iter()
            .map(|Mechanism(mechanism)| mechanism)
            .collect();
        debug!("gottting mechanisms");

        Ok(Mechanisms { mechanisms })
    }
}

impl IntoElement for Mechanisms {
    fn builder(&self) -> peanuts::element::ElementBuilder {
        Element::builder("mechanisms", Some(XMLNS)).push_children(
            self.mechanisms
                .iter()
                .map(|mechanism| Mechanism(mechanism.to_string()))
                .collect(),
        )
    }
}

pub struct Mechanism(String);

impl FromElement for Mechanism {
    fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
        element.check_name("mechanism")?;
        element.check_namespace(XMLNS)?;

        let mechanism = element.pop_value()?;

        Ok(Mechanism(mechanism))
    }
}

impl IntoElement for Mechanism {
    fn builder(&self) -> peanuts::element::ElementBuilder {
        Element::builder("mechanism", Some(XMLNS)).push_text(self.0.clone())
    }
}

impl Deref for Mechanism {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Debug)]
pub struct Auth {
    pub mechanism: String,
    pub sasl_data: String,
}

impl IntoElement for Auth {
    fn builder(&self) -> peanuts::element::ElementBuilder {
        Element::builder("auth", Some(XMLNS))
            .push_attribute("mechanism", self.mechanism.clone())
            .push_text(self.sasl_data.clone())
    }
}

#[derive(Debug)]
pub struct Challenge(String);

impl Deref for Challenge {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl FromElement for Challenge {
    fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
        element.check_name("challenge")?;
        element.check_namespace(XMLNS)?;

        let sasl_data = element.value()?;

        Ok(Challenge(sasl_data))
    }
}

#[derive(Debug)]
pub struct Success(String);

impl Deref for Success {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl FromElement for Success {
    fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
        element.check_name("success")?;
        element.check_namespace(XMLNS)?;

        let sasl_data = element.value()?;

        Ok(Success(sasl_data))
    }
}

#[derive(Debug)]
pub enum ServerResponse {
    Challenge(Challenge),
    Success(Success),
}

impl FromElement for ServerResponse {
    fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
        match element.identify() {
            (Some(XMLNS), "challenge") => {
                Ok(ServerResponse::Challenge(Challenge::from_element(element)?))
            }
            (Some(XMLNS), "success") => {
                Ok(ServerResponse::Success(Success::from_element(element)?))
            }
            _ => Err(DeserializeError::UnexpectedElement(element)),
        }
    }
}

#[derive(Debug)]
pub struct Response(String);

impl Response {
    pub fn new(response: String) -> Self {
        Self(response)
    }
}

impl Deref for Response {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl IntoElement for Response {
    fn builder(&self) -> peanuts::element::ElementBuilder {
        Element::builder("reponse", Some(XMLNS)).push_text(self.0.clone())
    }
}