message.rs

  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}