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