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