1use std::str::FromStr;
2
3use minidom::Element;
4use minidom::IntoAttributeValue;
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
167#[cfg(test)]
168mod tests {
169 use std::str::FromStr;
170 use minidom::Element;
171 use jid::Jid;
172 use message;
173
174 #[test]
175 fn test_simple() {
176 let elem: Element = "<message xmlns='jabber:client'/>".parse().unwrap();
177 let message = message::parse_message(&elem).unwrap();
178 assert_eq!(message.from, None);
179 assert_eq!(message.to, None);
180 assert_eq!(message.id, None);
181 assert_eq!(message.type_, message::MessageType::Normal);
182 assert!(message.payloads.is_empty());
183 }
184
185 #[test]
186 fn test_serialise() {
187 let elem: Element = "<message xmlns='jabber:client' type='normal'/>".parse().unwrap();
188 let message = message::parse_message(&elem).unwrap();
189 let message2 = message::Message {
190 from: None,
191 to: None,
192 id: None,
193 type_: message::MessageType::Normal,
194 payloads: vec!(),
195 };
196 let elem2 = message::serialise(&message2);
197 assert_eq!(elem, elem2);
198 println!("{:#?}", message);
199 }
200
201 #[test]
202 fn test_body() {
203 let elem: Element = "<message xmlns='jabber:client' to='coucou@example.org' type='chat'><body>Hello world!</body></message>".parse().unwrap();
204 let message = message::parse_message(&elem).unwrap();
205 println!("{:#?}", message);
206 }
207
208 #[test]
209 fn test_serialise_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 let message2 = message::Message {
213 from: None,
214 to: Some(Jid::from_str("coucou@example.org").unwrap()),
215 id: None,
216 type_: message::MessageType::Chat,
217 payloads: vec!(
218 message::MessagePayloadType::Parsed(message::MessagePayload::Body("Hello world!".to_owned())),
219 ),
220 };
221 let elem2 = message::serialise(&message2);
222 assert_eq!(elem, elem2);
223 println!("{:#?}", message);
224 }
225
226 #[test]
227 fn test_attention() {
228 let elem: Element = "<message xmlns='jabber:client' to='coucou@example.org' type='chat'><attention xmlns='urn:xmpp:attention:0'/></message>".parse().unwrap();
229 let message = message::parse_message(&elem).unwrap();
230 let elem2 = message::serialise(&message);
231 assert_eq!(elem, elem2);
232 }
233}