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