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}