use quick_xml::{
events::{BytesStart, BytesText, Event},
name::QName,
};
use crate::error::SASLError;
use crate::JabberError;
use super::Element;
const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-sasl";
#[derive(Debug)]
pub struct Auth<'e> {
pub mechanism: &'e str,
pub sasl_data: &'e str,
}
impl<'e> Auth<'e> {
fn event(&self) -> Event<'e> {
let mut start = BytesStart::new("auth");
start.push_attribute(("xmlns", XMLNS));
start.push_attribute(("mechanism", self.mechanism));
Event::Start(start)
}
fn children(&self) -> Option<Vec<Element<'e>>> {
let sasl = BytesText::from_escaped(self.sasl_data);
let sasl = Element {
event: Event::Text(sasl),
children: None,
};
Some(vec![sasl])
}
}
impl<'e> Into<Element<'e>> for Auth<'e> {
fn into(self) -> Element<'e> {
Element {
event: self.event(),
children: self.children(),
}
}
}
#[derive(Debug)]
pub struct Challenge {
pub sasl_data: Vec<u8>,
}
impl<'e> TryFrom<&Element<'e>> for Challenge {
type Error = JabberError;
fn try_from(element: &Element<'e>) -> Result<Challenge, Self::Error> {
if let Event::Start(start) = &element.event {
if start.name() == QName(b"challenge") {
let sasl_data: &Element<'_> = super::child(element)?;
if let Event::Text(sasl_data) = &sasl_data.event {
let s = sasl_data.clone();
let s = s.into_inner();
let s = s.to_vec();
return Ok(Challenge { sasl_data: s });
}
}
}
Err(SASLError::NoChallenge.into())
}
}
// impl<'e> TryFrom<Element<'e>> for Challenge {
// type Error = JabberError;
// fn try_from(element: Element<'e>) -> Result<Challenge, Self::Error> {
// if let Event::Start(start) = &element.event {
// if start.name() == QName(b"challenge") {
// println!("one");
// if let Some(children) = element.children.as_deref() {
// if children.len() == 1 {
// let sasl_data = children.first().unwrap();
// if let Event::Text(sasl_data) = &sasl_data.event {
// return Ok(Challenge {
// sasl_data: sasl_data.clone().into_inner().to_vec(),
// });
// } else {
// return Err(SASLError::NoChallenge.into());
// }
// } else {
// return Err(SASLError::NoChallenge.into());
// }
// } else {
// return Err(SASLError::NoChallenge.into());
// }
// }
// }
// Err(SASLError::NoChallenge.into())
// }
// }
#[derive(Debug)]
pub struct Response<'e> {
pub sasl_data: &'e str,
}
impl<'e> Response<'e> {
fn event(&self) -> Event<'e> {
let mut start = BytesStart::new("response");
start.push_attribute(("xmlns", XMLNS));
Event::Start(start)
}
fn children(&self) -> Option<Vec<Element<'e>>> {
let sasl = BytesText::from_escaped(self.sasl_data);
let sasl = Element {
event: Event::Text(sasl),
children: None,
};
Some(vec![sasl])
}
}
impl<'e> Into<Element<'e>> for Response<'e> {
fn into(self) -> Element<'e> {
Element {
event: self.event(),
children: self.children(),
}
}
}
#[derive(Debug)]
pub struct Success {
pub sasl_data: Option<Vec<u8>>,
}
impl<'e> TryFrom<&Element<'e>> for Success {
type Error = JabberError;
fn try_from(element: &Element<'e>) -> Result<Success, Self::Error> {
match &element.event {
Event::Start(start) => {
if start.name() == QName(b"success") {
match super::child(element) {
Ok(sasl_data) => {
if let Event::Text(sasl_data) = &sasl_data.event {
return Ok(Success {
sasl_data: Some(sasl_data.clone().into_inner().to_vec()),
});
}
}
Err(_) => return Ok(Success { sasl_data: None }),
};
}
}
Event::Empty(empty) => {
if empty.name() == QName(b"success") {
return Ok(Success { sasl_data: None });
}
}
_ => {}
}
Err(SASLError::NoSuccess.into())
}
}