use std::collections::BTreeMap; use quick_xml::{ events::{BytesStart, BytesText, Event}, name::QName, Reader, }; use super::{Element, IntoElement, Node}; use crate::{JabberError, JID}; const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind"; pub struct Bind { pub resource: Option, pub jid: Option, } impl From for Element { fn from(value: Bind) -> Self { let mut namespace_declarations = Box::new(BTreeMap::new()); namespace_declarations.insert(None, XMLNS.to_owned()); let mut children = Vec::new(); if let Some(resource) = value.resource { children.push(Node::Element( Element { prefix: None, localname: "", namespace: , namespace_declarations: , attributes: , children: } ) ) } Self { prefix: None, localname: "bind".to_string(), namespace: XMLNS.to_owned(), namespace_declarations, attributes: todo!(), children: todo!(), } } } impl IntoElement 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) } }