diff options
author | cel 🌸 <cel@blos.sm> | 2023-08-02 00:56:38 +0100 |
---|---|---|
committer | cel 🌸 <cel@blos.sm> | 2023-08-02 00:56:38 +0100 |
commit | cd7bb95c0a31d187bfe25bad15043f0b33b111cf (patch) | |
tree | c5be0c651198abf736f8867a36906f9345f3a0ac /src/stanza/bind.rs | |
parent | 322b2a3b46348ec1c5acbc538de93310c9030b96 (diff) | |
download | luz-cd7bb95c0a31d187bfe25bad15043f0b33b111cf.tar.gz luz-cd7bb95c0a31d187bfe25bad15043f0b33b111cf.tar.bz2 luz-cd7bb95c0a31d187bfe25bad15043f0b33b111cf.zip |
implement resource binding
Diffstat (limited to 'src/stanza/bind.rs')
-rw-r--r-- | src/stanza/bind.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/stanza/bind.rs b/src/stanza/bind.rs new file mode 100644 index 0000000..f1bdc2d --- /dev/null +++ b/src/stanza/bind.rs @@ -0,0 +1,111 @@ +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<String>, + pub jid: Option<JID>, +} + +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<Vec<Element<'static>>> { + 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<Element<'static>> for Bind { + type Error = JabberError; + + fn try_from(element: Element<'static>) -> Result<Self, Self::Error> { + if let Event::Start(start) = &element.event { + let buf: Vec<u8> = 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<u8> = 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) + } +} |