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