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;
 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}