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}