bind.rs

 1// Copyright (c) 2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
 2//
 3// This Source Code Form is subject to the terms of the Mozilla Public
 4// License, v. 2.0. If a copy of the MPL was not distributed with this
 5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
 6
 7use std::str::FromStr;
 8use try_from::TryFrom;
 9
10use minidom::Element;
11
12use error::Error;
13use jid::Jid;
14use ns;
15
16#[derive(Debug, Clone)]
17pub struct Bind {
18    pub resource: Option<String>,
19    pub jid: Option<Jid>,
20}
21
22impl Bind {
23    pub fn new(resource: Option<String>) -> Bind {
24        Bind {
25            resource,
26            jid: None,
27        }
28    }
29}
30
31impl TryFrom<Element> for Bind {
32    type Err = Error;
33
34    fn try_from(elem: Element) -> Result<Bind, Error> {
35        check_self!(elem, "bind", ns::BIND);
36        check_no_attributes!(elem, "bind");
37
38        let mut bind = Bind {
39            resource: None,
40            jid: None,
41        };
42        let mut already_set = false;
43        for child in elem.children() {
44            if already_set {
45                return Err(Error::ParseError("Bind can only have one child."));
46            }
47            if child.is("resource", ns::BIND) {
48                check_no_children!(child, "resource");
49                bind.resource = Some(child.text());
50                already_set = true;
51            } else if child.is("jid", ns::BIND) {
52                check_no_children!(child, "jid");
53                bind.jid = Some(Jid::from_str(&child.text())?);
54                already_set = true;
55            } else {
56                return Err(Error::ParseError("Unknown element in bind."));
57            }
58        }
59
60        Ok(bind)
61    }
62}
63
64impl From<Bind> for Element {
65    fn from(bind: Bind) -> Element {
66        Element::builder("bind")
67                .ns(ns::BIND)
68                .append(bind.resource.map(|resource|
69                     Element::builder("resource")
70                             .ns(ns::BIND)
71                             .append(resource)
72                             .build()))
73                .append(bind.jid.map(|jid|
74                     Element::builder("jid")
75                             .ns(ns::BIND)
76                             .append(jid)
77                             .build()))
78                .build()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_simple() {
88        let elem: Element = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>".parse().unwrap();
89        let bind = Bind::try_from(elem).unwrap();
90        assert_eq!(bind.resource, None);
91        assert_eq!(bind.jid, None);
92    }
93}