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;
11
12#[derive(Debug, Clone)]
13pub struct Version {
14 pub name: String,
15 pub version: String,
16 pub os: Option<String>,
17}
18
19impl TryFrom<Element> for Version {
20 type Err = Error;
21
22 fn try_from(elem: Element) -> Result<Version, Error> {
23 if !elem.is("query", ns::VERSION) {
24 return Err(Error::ParseError("This is not a version element."));
25 }
26 for _ in elem.attrs() {
27 return Err(Error::ParseError("Unknown child in version element."));
28 }
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
86 #[test]
87 fn test_simple() {
88 let elem: Element = "<query xmlns='jabber:iq:version'><name>xmpp-rs</name><version>0.3.0</version></query>".parse().unwrap();
89 let version = Version::try_from(elem).unwrap();
90 assert_eq!(version.name, String::from("xmpp-rs"));
91 assert_eq!(version.version, String::from("0.3.0"));
92 assert_eq!(version.os, None);
93 }
94}