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