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}