1use std::str::FromStr;
2
3use minidom::{Element, IntoElements, IntoAttributeValue};
4use minidom::convert::ElementEmitter;
5
6use jid::Jid;
7
8use error::Error;
9
10use ns;
11
12use body;
13use chatstates;
14use receipts;
15use delay;
16use attention;
17use message_correct;
18use eme;
19
20/// Lists every known payload of a `<message/>`.
21#[derive(Debug, Clone)]
22pub enum MessagePayload {
23 Body(body::Body),
24 ChatState(chatstates::ChatState),
25 Receipt(receipts::Receipt),
26 Delay(delay::Delay),
27 Attention(attention::Attention),
28 MessageCorrect(message_correct::Replace),
29 ExplicitMessageEncryption(eme::ExplicitMessageEncryption),
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub enum MessageType {
34 Chat,
35 Error,
36 Groupchat,
37 Headline,
38 Normal,
39}
40
41impl Default for MessageType {
42 fn default() -> MessageType {
43 MessageType::Normal
44 }
45}
46
47impl FromStr for MessageType {
48 type Err = Error;
49
50 fn from_str(s: &str) -> Result<MessageType, Error> {
51 Ok(match s {
52 "chat" => MessageType::Chat,
53 "error" => MessageType::Error,
54 "groupchat" => MessageType::Groupchat,
55 "headline" => MessageType::Headline,
56 "normal" => MessageType::Normal,
57
58 _ => return Err(Error::ParseError("Invalid 'type' attribute on message element.")),
59 })
60 }
61}
62
63impl IntoAttributeValue for MessageType {
64 fn into_attribute_value(self) -> Option<String> {
65 Some(match self {
66 MessageType::Chat => "chat",
67 MessageType::Error => "error",
68 MessageType::Groupchat => "groupchat",
69 MessageType::Headline => "headline",
70 MessageType::Normal => "normal",
71 }.to_owned())
72 }
73}
74
75#[derive(Debug, Clone)]
76pub enum MessagePayloadType {
77 XML(Element),
78 Parsed(MessagePayload),
79}
80
81#[derive(Debug, Clone)]
82pub struct Message {
83 pub from: Option<Jid>,
84 pub to: Option<Jid>,
85 pub id: Option<String>,
86 pub type_: MessageType,
87 pub payloads: Vec<MessagePayloadType>,
88}
89
90pub fn parse_message(root: &Element) -> Result<Message, Error> {
91 if !root.is("message", ns::JABBER_CLIENT) {
92 return Err(Error::ParseError("This is not a message element."));
93 }
94 let from = root.attr("from")
95 .and_then(|value| value.parse().ok());
96 let to = root.attr("to")
97 .and_then(|value| value.parse().ok());
98 let id = root.attr("id")
99 .and_then(|value| value.parse().ok());
100 let type_ = match root.attr("type") {
101 Some(type_) => type_.parse()?,
102 None => Default::default(),
103 };
104 let mut payloads = vec!();
105 for elem in root.children() {
106 let payload = if let Ok(body) = body::parse_body(elem) {
107 Some(MessagePayload::Body(body))
108 } else if let Ok(chatstate) = chatstates::parse_chatstate(elem) {
109 Some(MessagePayload::ChatState(chatstate))
110 } else if let Ok(receipt) = receipts::parse_receipt(elem) {
111 Some(MessagePayload::Receipt(receipt))
112 } else if let Ok(delay) = delay::parse_delay(elem) {
113 Some(MessagePayload::Delay(delay))
114 } else if let Ok(attention) = attention::parse_attention(elem) {
115 Some(MessagePayload::Attention(attention))
116 } else if let Ok(replace) = message_correct::parse_replace(elem) {
117 Some(MessagePayload::MessageCorrect(replace))
118 } else if let Ok(eme) = eme::parse_explicit_message_encryption(elem) {
119 Some(MessagePayload::ExplicitMessageEncryption(eme))
120 } else {
121 None
122 };
123 payloads.push(match payload {
124 Some(payload) => MessagePayloadType::Parsed(payload),
125 None => MessagePayloadType::XML(elem.clone()),
126 });
127 }
128 Ok(Message {
129 from: from,
130 to: to,
131 id: id,
132 type_: type_,
133 payloads: payloads,
134 })
135}
136
137pub fn serialise_payload(payload: &MessagePayload) -> Element {
138 match *payload {
139 MessagePayload::Body(ref body) => body::serialise(body),
140 MessagePayload::Attention(ref attention) => attention::serialise(attention),
141 MessagePayload::ChatState(ref chatstate) => chatstates::serialise(chatstate),
142 MessagePayload::Receipt(ref receipt) => receipts::serialise(receipt),
143 MessagePayload::Delay(ref delay) => delay::serialise(delay),
144 MessagePayload::MessageCorrect(ref replace) => message_correct::serialise(replace),
145 MessagePayload::ExplicitMessageEncryption(ref eme) => eme::serialise(eme),
146 }
147}
148
149pub fn serialise(message: &Message) -> Element {
150 let mut stanza = Element::builder("message")
151 .ns(ns::JABBER_CLIENT)
152 .attr("from", message.from.clone().and_then(|value| Some(String::from(value))))
153 .attr("to", message.to.clone().and_then(|value| Some(String::from(value))))
154 .attr("id", message.id.clone())
155 .attr("type", message.type_.clone())
156 .build();
157 for child in message.payloads.clone() {
158 let elem = match child {
159 MessagePayloadType::XML(elem) => elem,
160 MessagePayloadType::Parsed(payload) => serialise_payload(&payload),
161 };
162 stanza.append_child(elem);
163 }
164 stanza
165}
166
167impl IntoElements for Message {
168 fn into_elements(self, emitter: &mut ElementEmitter) {
169 let elem = serialise(&self);
170 emitter.append_child(elem);
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use std::str::FromStr;
177 use minidom::Element;
178 use jid::Jid;
179 use message;
180
181 #[test]
182 fn test_simple() {
183 let elem: Element = "<message xmlns='jabber:client'/>".parse().unwrap();
184 let message = message::parse_message(&elem).unwrap();
185 assert_eq!(message.from, None);
186 assert_eq!(message.to, None);
187 assert_eq!(message.id, None);
188 assert_eq!(message.type_, message::MessageType::Normal);
189 assert!(message.payloads.is_empty());
190 }
191
192 #[test]
193 fn test_serialise() {
194 let elem: Element = "<message xmlns='jabber:client' type='normal'/>".parse().unwrap();
195 let message = message::parse_message(&elem).unwrap();
196 let message2 = message::Message {
197 from: None,
198 to: None,
199 id: None,
200 type_: message::MessageType::Normal,
201 payloads: vec!(),
202 };
203 let elem2 = message::serialise(&message2);
204 assert_eq!(elem, elem2);
205 println!("{:#?}", message);
206 }
207
208 #[test]
209 fn test_body() {
210 let elem: Element = "<message xmlns='jabber:client' to='coucou@example.org' type='chat'><body>Hello world!</body></message>".parse().unwrap();
211 let message = message::parse_message(&elem).unwrap();
212 println!("{:#?}", message);
213 }
214
215 #[test]
216 fn test_serialise_body() {
217 let elem: Element = "<message xmlns='jabber:client' to='coucou@example.org' type='chat'><body>Hello world!</body></message>".parse().unwrap();
218 let message = message::parse_message(&elem).unwrap();
219 let message2 = message::Message {
220 from: None,
221 to: Some(Jid::from_str("coucou@example.org").unwrap()),
222 id: None,
223 type_: message::MessageType::Chat,
224 payloads: vec!(
225 message::MessagePayloadType::Parsed(message::MessagePayload::Body("Hello world!".to_owned())),
226 ),
227 };
228 let elem2 = message::serialise(&message2);
229 assert_eq!(elem, elem2);
230 println!("{:#?}", message);
231 }
232
233 #[test]
234 fn test_attention() {
235 let elem: Element = "<message xmlns='jabber:client' to='coucou@example.org' type='chat'><attention xmlns='urn:xmpp:attention:0'/></message>".parse().unwrap();
236 let message = message::parse_message(&elem).unwrap();
237 let elem2 = message::serialise(&message);
238 assert_eq!(elem, elem2);
239 }
240}