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