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}