use quick_xml::{ events::{BytesStart, BytesText, Event}, name::QName, Reader, }; use super::{Element, IntoElement}; use crate::{JabberError, JID}; const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind"; pub struct Bind { pub resource: Option, pub jid: Option, } impl<'e> IntoElement<'e> for Bind { fn event(&self) -> quick_xml::events::Event<'static> { let mut bind_event = BytesStart::new("bind"); bind_event.push_attribute(("xmlns", XMLNS)); if self.resource.is_none() && self.jid.is_none() { return Event::Empty(bind_event); } else { return Event::Start(bind_event); } } fn children(&self) -> Option>> { if let Some(resource) = &self.resource { let resource_event: BytesStart<'static> = BytesStart::new("resource"); let resource_child: BytesText<'static> = BytesText::new(resource).into_owned(); let resource_child: Element<'static> = Element { event: Event::Text(resource_child), children: None, }; let resource_element: Element<'static> = Element { event: Event::Start(resource_event), children: Some(vec![resource_child]), }; return Some(vec![resource_element]); } else if let Some(jid) = &self.jid { let jid_event = BytesStart::new("jid"); let jid_child = BytesText::new(&jid.to_string()).into_owned(); let jid_child = Element { event: Event::Text(jid_child), children: None, }; let jid_element = Element { event: Event::Start(jid_event), children: Some(vec![jid_child]), }; return Some(vec![jid_element]); } None } } impl TryFrom> for Bind { type Error = JabberError; fn try_from(element: Element<'static>) -> Result { if let Event::Start(start) = &element.event { let buf: Vec = Vec::new(); let reader = Reader::from_reader(buf); if start.name() == QName(b"bind") && start.try_get_attribute("xmlns")?.is_some_and(|attribute| { attribute.decode_and_unescape_value(&reader).unwrap() == XMLNS }) { let child: Element<'static> = element.child()?.clone(); if let Event::Start(start) = &child.event { match start.name() { QName(b"resource") => { let resource_text = child.child()?; if let Event::Text(text) = &resource_text.event { return Ok(Self { resource: Some(text.unescape()?.into_owned()), jid: None, }); } } QName(b"jid") => { let jid_text = child.child()?; if let Event::Text(text) = &jid_text.event { return Ok(Self { jid: Some(text.unescape()?.into_owned().try_into()?), resource: None, }); } } _ => return Err(JabberError::UnexpectedElement), } } } } else if let Event::Empty(start) = &element.event { let buf: Vec = Vec::new(); let reader = Reader::from_reader(buf); if start.name() == QName(b"bind") && start.try_get_attribute("xmlns")?.is_some_and(|attribute| { attribute.decode_and_unescape_value(&reader).unwrap() == XMLNS }) { return Ok(Bind { resource: None, jid: None, }); } } Err(JabberError::UnexpectedElement) } }