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, } impl FromElement for Mechanisms { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { element.check_name("mechanisms")?; element.check_namespace(XMLNS)?; debug!("getting mechanisms"); let mechanisms: Vec = 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 { 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 { 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 { 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 { 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()) } }