From 7c0975dd5dcac94deb269fb9bbbd00d7e8de16d7 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 20 Feb 2018 17:43:19 +0100 Subject: [PATCH] Add a Bind parser. --- src/bind.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/ns.rs | 2 ++ 3 files changed, 97 insertions(+) create mode 100644 src/bind.rs diff --git a/src/bind.rs b/src/bind.rs new file mode 100644 index 0000000..6974ce5 --- /dev/null +++ b/src/bind.rs @@ -0,0 +1,93 @@ +// Copyright (c) 2018 Emmanuel Gil Peyrot +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use std::str::FromStr; +use try_from::TryFrom; + +use minidom::Element; + +use error::Error; +use jid::Jid; +use ns; + +#[derive(Debug, Clone)] +pub struct Bind { + pub resource: Option, + pub jid: Option, +} + +impl Bind { + pub fn new(resource: Option) -> Bind { + Bind { + resource, + jid: None, + } + } +} + +impl TryFrom for Bind { + type Err = Error; + + fn try_from(elem: Element) -> Result { + check_self!(elem, "bind", ns::BIND); + check_no_attributes!(elem, "bind"); + + let mut bind = Bind { + resource: None, + jid: None, + }; + let mut already_set = false; + for child in elem.children() { + if already_set { + return Err(Error::ParseError("Bind can only have one child.")); + } + if child.is("resource", ns::BIND) { + check_no_children!(child, "resource"); + bind.resource = Some(child.text()); + already_set = true; + } else if child.is("jid", ns::BIND) { + check_no_children!(child, "jid"); + bind.jid = Some(Jid::from_str(&child.text())?); + already_set = true; + } else { + return Err(Error::ParseError("Unknown element in bind.")); + } + } + + Ok(bind) + } +} + +impl From for Element { + fn from(bind: Bind) -> Element { + Element::builder("bind") + .ns(ns::BIND) + .append(bind.resource.map(|resource| + Element::builder("resource") + .ns(ns::BIND) + .append(resource) + .build())) + .append(bind.jid.map(|jid| + Element::builder("jid") + .ns(ns::BIND) + .append(jid) + .build())) + .build() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + let bind = Bind::try_from(elem).unwrap(); + assert_eq!(bind.resource, None); + assert_eq!(bind.jid, None); + } +} diff --git a/src/lib.rs b/src/lib.rs index 3f3df91..b7afeac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,8 @@ pub mod iq; pub mod stanza_error; /// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core pub mod sasl; +/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core +pub mod bind; /// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence pub mod roster; diff --git a/src/ns.rs b/src/ns.rs index f17e602..b09c9d7 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -11,6 +11,8 @@ pub const JABBER_CLIENT: &str = "jabber:client"; pub const XMPP_STANZAS: &str = "urn:ietf:params:xml:ns:xmpp-stanzas"; /// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core pub const SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; +/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core +pub const BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind"; /// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence pub const ROSTER: &str = "jabber:iq:roster";