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
 7#![allow(missing_docs)]
 8
 9use std::str::FromStr;
10use try_from::TryFrom;
11
12use minidom::Element;
13
14use error::Error;
15use jid::Jid;
16use ns;
17use iq::{IqSetPayload, IqResultPayload};
18
19#[derive(Debug, Clone, PartialEq)]
20pub enum Bind {
21    None,
22    Resource(String),
23    Jid(Jid),
24}
25
26impl Bind {
27    pub fn new(resource: Option<String>) -> Bind {
28        match resource {
29            None => Bind::None,
30            Some(resource) => Bind::Resource(resource),
31        }
32    }
33}
34
35impl IqSetPayload for Bind {}
36impl IqResultPayload for Bind {}
37
38impl TryFrom<Element> for Bind {
39    type Err = Error;
40
41    fn try_from(elem: Element) -> Result<Bind, Error> {
42        check_self!(elem, "bind", BIND);
43        check_no_attributes!(elem, "bind");
44
45        let mut bind = Bind::None;
46        for child in elem.children() {
47            if bind != Bind::None {
48                return Err(Error::ParseError("Bind can only have one child."));
49            }
50            if child.is("resource", ns::BIND) {
51                check_no_children!(child, "resource");
52                bind = Bind::Resource(child.text());
53            } else if child.is("jid", ns::BIND) {
54                check_no_children!(child, "jid");
55                bind = Bind::Jid(Jid::from_str(&child.text())?);
56            } else {
57                return Err(Error::ParseError("Unknown element in bind."));
58            }
59        }
60
61        Ok(bind)
62    }
63}
64
65impl From<Bind> for Element {
66    fn from(bind: Bind) -> Element {
67        Element::builder("bind")
68                .ns(ns::BIND)
69                .append(match bind {
70                     Bind::None => vec!(),
71                     Bind::Resource(resource) => vec!(
72                         Element::builder("resource")
73                                 .ns(ns::BIND)
74                                 .append(resource)
75                                 .build()
76                     ),
77                     Bind::Jid(jid) => vec!(
78                         Element::builder("jid")
79                                 .ns(ns::BIND)
80                                 .append(jid)
81                                 .build()
82                     ),
83                 })
84                .build()
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_simple() {
94        let elem: Element = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>".parse().unwrap();
95        let bind = Bind::try_from(elem).unwrap();
96        assert_eq!(bind, Bind::None);
97    }
98}