From dc530a1912f191ca43874f747b9702ea5d482d1f Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 21 May 2017 20:22:48 +0100 Subject: [PATCH] Add an idle parser. --- src/idle.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/ns.rs | 3 ++ 3 files changed, 91 insertions(+) create mode 100644 src/idle.rs diff --git a/src/idle.rs b/src/idle.rs new file mode 100644 index 00000000..5261788e --- /dev/null +++ b/src/idle.rs @@ -0,0 +1,85 @@ +// 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 std::convert::TryFrom; + +use minidom::Element; + +use error::Error; + +use ns; + +type Date = String; + +#[derive(Debug, Clone)] +pub struct Idle { + pub since: Date, +} + +impl<'a> TryFrom<&'a Element> for Idle { + type Error = Error; + + fn try_from(elem: &'a Element) -> Result { + if !elem.is("idle", ns::IDLE) { + return Err(Error::ParseError("This is not an idle element.")); + } + for _ in elem.children() { + return Err(Error::ParseError("Unknown child in idle element.")); + } + let since = get_attr!(elem, "since", required); + Ok(Idle { since: since }) + } +} + +impl<'a> Into for &'a Idle { + fn into(self) -> Element { + Element::builder("idle") + .ns(ns::IDLE) + .attr("since", self.since.clone()) + .build() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + Idle::try_from(&elem).unwrap(); + } + + #[test] + fn test_invalid_child() { + let elem: Element = "".parse().unwrap(); + let error = Idle::try_from(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown child in idle element."); + } + + #[test] + fn test_invalid_id() { + let elem: Element = "".parse().unwrap(); + let error = Idle::try_from(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Required attribute 'since' missing."); + } + + #[test] + fn test_serialise() { + let elem: Element = "".parse().unwrap(); + let idle = Idle { since: Date::from("2017-05-21T20:19:55+01:00") }; + let elem2 = (&idle).into(); + assert_eq!(elem, elem2); + } +} diff --git a/src/lib.rs b/src/lib.rs index db9b95aa..2eb2aecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,6 +114,9 @@ pub mod message_correct; /// XEP-0313: Message Archive Management pub mod mam; +/// XEP-0319: Last User Interaction in Presence +pub mod idle; + /// XEP-0359: Unique and Stable Stanza IDs pub mod stanza_id; diff --git a/src/ns.rs b/src/ns.rs index c98bff58..b51c6530 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -77,6 +77,9 @@ pub const MESSAGE_CORRECT: &'static str = "urn:xmpp:message-correct:0"; /// XEP-0313: Message Archive Management pub const MAM: &'static str = "urn:xmpp:mam:2"; +/// XEP-0319: Last User Interaction in Presence +pub const IDLE: &'static str = "urn:xmpp:idle:1"; + /// XEP-0359: Unique and Stable Stanza IDs pub const SID: &'static str = "urn:xmpp:sid:0";