chatstates.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
  7#![deny(missing_docs)]
  8
  9use try_from::TryFrom;
 10
 11use minidom::Element;
 12
 13use error::Error;
 14
 15use ns;
 16
 17/// Enum representing chatstate elements part of the
 18/// `http://jabber.org/protocol/chatstates` namespace.
 19#[derive(Debug, Clone)]
 20pub enum ChatState {
 21    /// `<active xmlns='http://jabber.org/protocol/chatstates'/>`
 22    Active,
 23
 24    /// `<composing xmlns='http://jabber.org/protocol/chatstates'/>`
 25    Composing,
 26
 27    /// `<gone xmlns='http://jabber.org/protocol/chatstates'/>`
 28    Gone,
 29
 30    /// `<inactive xmlns='http://jabber.org/protocol/chatstates'/>`
 31    Inactive,
 32
 33    /// `<paused xmlns='http://jabber.org/protocol/chatstates'/>`
 34    Paused,
 35}
 36
 37impl TryFrom<Element> for ChatState {
 38    type Err = Error;
 39
 40    fn try_from(elem: Element) -> Result<ChatState, Error> {
 41        if !elem.has_ns(ns::CHATSTATES) {
 42            return Err(Error::ParseError("This is not a chatstate element."));
 43        }
 44        for _ in elem.children() {
 45            return Err(Error::ParseError("Unknown child in chatstate element."));
 46        }
 47        for _ in elem.attrs() {
 48            return Err(Error::ParseError("Unknown attribute in chatstate element."));
 49        }
 50        Ok(match elem.name() {
 51            "active" => ChatState::Active,
 52            "composing" => ChatState::Composing,
 53            "gone" => ChatState::Gone,
 54            "inactive" => ChatState::Inactive,
 55            "paused" => ChatState::Paused,
 56            _ => return Err(Error::ParseError("This is not a chatstate element.")),
 57        })
 58    }
 59}
 60
 61impl From<ChatState> for Element {
 62    fn from(chatstate: ChatState) -> Element {
 63        Element::builder(match chatstate {
 64            ChatState::Active => "active",
 65            ChatState::Composing => "composing",
 66            ChatState::Gone => "gone",
 67            ChatState::Inactive => "inactive",
 68            ChatState::Paused => "paused",
 69        }).ns(ns::CHATSTATES)
 70          .build()
 71    }
 72}
 73
 74#[cfg(test)]
 75mod tests {
 76    use super::*;
 77
 78    #[test]
 79    fn test_simple() {
 80        let elem: Element = "<active xmlns='http://jabber.org/protocol/chatstates'/>".parse().unwrap();
 81        ChatState::try_from(elem).unwrap();
 82    }
 83
 84    #[test]
 85    fn test_invalid() {
 86        let elem: Element = "<coucou xmlns='http://jabber.org/protocol/chatstates'/>".parse().unwrap();
 87        let error = ChatState::try_from(elem).unwrap_err();
 88        let message = match error {
 89            Error::ParseError(string) => string,
 90            _ => panic!(),
 91        };
 92        assert_eq!(message, "This is not a chatstate element.");
 93    }
 94
 95    #[test]
 96    fn test_invalid_child() {
 97        let elem: Element = "<gone xmlns='http://jabber.org/protocol/chatstates'><coucou/></gone>".parse().unwrap();
 98        let error = ChatState::try_from(elem).unwrap_err();
 99        let message = match error {
100            Error::ParseError(string) => string,
101            _ => panic!(),
102        };
103        assert_eq!(message, "Unknown child in chatstate element.");
104    }
105
106    #[test]
107    fn test_invalid_attribute() {
108        let elem: Element = "<inactive xmlns='http://jabber.org/protocol/chatstates' coucou=''/>".parse().unwrap();
109        let error = ChatState::try_from(elem).unwrap_err();
110        let message = match error {
111            Error::ParseError(string) => string,
112            _ => panic!(),
113        };
114        assert_eq!(message, "Unknown attribute in chatstate element.");
115    }
116
117    #[test]
118    fn test_serialise() {
119        let chatstate = ChatState::Active;
120        let elem: Element = chatstate.into();
121        assert!(elem.is("active", ns::CHATSTATES));
122    }
123}