1// Copyright (c) 2017 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 try_from::TryFrom;
8use minidom::Element;
9use error::Error;
10use ns;
11use iq::{IqGetPayload, IqResultPayload};
12
13#[derive(Debug, Clone)]
14pub struct Version {
15 pub name: String,
16 pub version: String,
17 pub os: Option<String>,
18}
19
20impl IqGetPayload for Version {}
21impl IqResultPayload for Version {}
22
23impl TryFrom<Element> for Version {
24 type Err = Error;
25
26 fn try_from(elem: Element) -> Result<Version, Error> {
27 check_self!(elem, "query", VERSION, "version");
28 check_no_attributes!(elem, "version");
29 let mut name = None;
30 let mut version = None;
31 let mut os = None;
32 for child in elem.children() {
33 if child.is("name", ns::VERSION) {
34 if name.is_some() {
35 return Err(Error::ParseError("More than one name in version element."));
36 }
37 name = Some(child.text());
38 } else if child.is("version", ns::VERSION) {
39 if version.is_some() {
40 return Err(Error::ParseError("More than one version in version element."));
41 }
42 version = Some(child.text());
43 } else if child.is("os", ns::VERSION) {
44 if os.is_some() {
45 return Err(Error::ParseError("More than one os in version element."));
46 }
47 os = Some(child.text());
48 } else {
49 return Err(Error::ParseError("Unknown child in version element."));
50 }
51 }
52 let name = name.unwrap();
53 let version = version.unwrap();
54 Ok(Version {
55 name,
56 version,
57 os,
58 })
59 }
60}
61
62impl From<Version> for Element {
63 fn from(version: Version) -> Element {
64 Element::builder("query")
65 .ns(ns::VERSION)
66 .append(Element::builder("name")
67 .ns(ns::VERSION)
68 .append(version.name)
69 .build())
70 .append(Element::builder("version")
71 .ns(ns::VERSION)
72 .append(version.version)
73 .build())
74 .append(Element::builder("os")
75 .ns(ns::VERSION)
76 .append(version.os)
77 .build())
78 .build()
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use compare_elements::NamespaceAwareCompare;
86
87 #[test]
88 fn test_simple() {
89 let elem: Element = "<query xmlns='jabber:iq:version'><name>xmpp-rs</name><version>0.3.0</version></query>".parse().unwrap();
90 let version = Version::try_from(elem).unwrap();
91 assert_eq!(version.name, String::from("xmpp-rs"));
92 assert_eq!(version.version, String::from("0.3.0"));
93 assert_eq!(version.os, None);
94 }
95
96 #[test]
97 fn serialisation() {
98 let version = Version {
99 name: String::from("xmpp-rs"),
100 version: String::from("0.3.0"),
101 os: None,
102 };
103 let elem1 = Element::from(version);
104 let elem2: Element = "<query xmlns='jabber:iq:version'><name>xmpp-rs</name><version>0.3.0</version></query>".parse().unwrap();
105 println!("{:?}", elem1);
106 assert!(elem1.compare_to(&elem2));
107 }
108}