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