summaryrefslogblamecommitdiffstats
path: root/src/stanza/bind.rs
blob: 5e9704f4884d851d8ef136f003caeceb2118756f (plain) (tree)
1
2
3
4
5
6
7
8
9

                               





                                           
                                        








                                                       























                                                                                                                        





























































































                                                                                           
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<String>,
    pub jid: Option<JID>,
}

impl From<Bind> 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<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)
    }
}