From 1af06fdf6d90c29d2bc4997efc3e0fa92779c963 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 29 Jul 2017 11:45:45 +0100 Subject: [PATCH] Add an iq version parser (XEP-0092). --- src/lib.rs | 3 ++ src/ns.rs | 3 ++ src/version.rs | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/version.rs diff --git a/src/lib.rs b/src/lib.rs index f881082..cc9a8c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,6 +207,9 @@ pub mod ibr; /// XEP-0085: Chat State Notifications pub mod chatstates; +/// XEP-0092: Software Version +pub mod version; + /// XEP-0115: Entity Capabilities pub mod caps; diff --git a/src/ns.rs b/src/ns.rs index 5df077e..22e5f15 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -47,6 +47,9 @@ pub const REGISTER: &str = "jabber:iq:register"; /// XEP-0085: Chat State Notifications pub const CHATSTATES: &str = "http://jabber.org/protocol/chatstates"; +/// XEP-0092: Software Version +pub const VERSION: &str = "jabber:iq:version"; + /// XEP-0114: Jabber Component Protocol pub const COMPONENT_ACCEPT: &str = "jabber:component:accept"; diff --git a/src/version.rs b/src/version.rs new file mode 100644 index 0000000..5e7f0ab --- /dev/null +++ b/src/version.rs @@ -0,0 +1,94 @@ +// Copyright (c) 2017 Emmanuel Gil Peyrot +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use try_from::TryFrom; +use minidom::Element; +use error::Error; +use ns; + +#[derive(Debug, Clone)] +pub struct Version { + pub name: String, + pub version: String, + pub os: Option, +} + +impl TryFrom for Version { + type Err = Error; + + fn try_from(elem: Element) -> Result { + if !elem.is("query", ns::VERSION) { + return Err(Error::ParseError("This is not a version element.")); + } + for _ in elem.attrs() { + return Err(Error::ParseError("Unknown child in version element.")); + } + let mut name = None; + let mut version = None; + let mut os = None; + for child in elem.children() { + if child.is("name", ns::VERSION) { + if name.is_some() { + return Err(Error::ParseError("More than one name in version element.")); + } + name = Some(child.text()); + } else if child.is("version", ns::VERSION) { + if version.is_some() { + return Err(Error::ParseError("More than one version in version element.")); + } + version = Some(child.text()); + } else if child.is("os", ns::VERSION) { + if os.is_some() { + return Err(Error::ParseError("More than one os in version element.")); + } + os = Some(child.text()); + } else { + return Err(Error::ParseError("Unknown child in version element.")); + } + } + let name = name.unwrap(); + let version = version.unwrap(); + Ok(Version { + name, + version, + os, + }) + } +} + +impl From for Element { + fn from(version: Version) -> Element { + Element::builder("query") + .ns(ns::VERSION) + .append(Element::builder("name") + .ns(ns::VERSION) + .append(version.name) + .build()) + .append(Element::builder("version") + .ns(ns::VERSION) + .append(version.version) + .build()) + .append(Element::builder("os") + .ns(ns::VERSION) + .append(version.os) + .build()) + .build() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simple() { + let elem: Element = "xmpp-rs0.3.0".parse().unwrap(); + let version = Version::try_from(elem).unwrap(); + assert_eq!(version.name, String::from("xmpp-rs")); + assert_eq!(version.version, String::from("0.3.0")); + assert_eq!(version.os, None); + } +}