version.rs

 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}