From f971cbd5c9f541b2857e437ad8887daad3aeadf2 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 6 May 2017 21:21:34 +0100 Subject: [PATCH] message: Switch to Into/TryFrom. --- src/forwarding.rs | 8 +- src/message.rs | 186 +++++++++++++++++++++++----------------------- 2 files changed, 96 insertions(+), 98 deletions(-) diff --git a/src/forwarding.rs b/src/forwarding.rs index 75b7fbc..a2162e0 100644 --- a/src/forwarding.rs +++ b/src/forwarding.rs @@ -11,7 +11,7 @@ use minidom::Element; use error::Error; use delay::Delay; -use message; +use message::Message; use ns; @@ -19,7 +19,7 @@ use ns; pub struct Forwarded { pub delay: Option, // XXX: really? Option? - pub stanza: Option, + pub stanza: Option, } impl<'a> TryFrom<&'a Element> for Forwarded { @@ -35,7 +35,7 @@ impl<'a> TryFrom<&'a Element> for Forwarded { if child.is("delay", ns::DELAY) { delay = Some(Delay::try_from(child)?); } else if child.is("message", ns::JABBER_CLIENT) { - stanza = Some(message::parse_message(child)?); + stanza = Some(Message::try_from(child)?); // TODO: also handle the five other possibilities. } else { return Err(Error::ParseError("Unknown child in forwarded element.")); @@ -53,7 +53,7 @@ impl<'a> Into for &'a Forwarded { Element::builder("forwarded") .ns(ns::FORWARD) .append(match self.delay { Some(ref delay) => { let elem: Element = delay.into(); Some(elem) }, None => None }) - .append(self.stanza.clone()) + .append(match self.stanza { Some(ref stanza) => { let elem: Element = stanza.into(); Some(elem) }, None => None }) .build() } } diff --git a/src/message.rs b/src/message.rs index ee2c644..51baf9b 100644 --- a/src/message.rs +++ b/src/message.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; use std::str::FromStr; -use minidom::{Element, IntoElements, IntoAttributeValue, ElementEmitter}; +use minidom::{Element, IntoAttributeValue}; use jid::Jid; @@ -95,152 +95,150 @@ pub struct Message { pub payloads: Vec, } -pub fn parse_message(root: &Element) -> Result { - if !root.is("message", ns::JABBER_CLIENT) { - return Err(Error::ParseError("This is not a message element.")); - } - let from = root.attr("from") - .and_then(|value| value.parse().ok()); - let to = root.attr("to") - .and_then(|value| value.parse().ok()); - let id = root.attr("id") - .and_then(|value| value.parse().ok()); - let type_ = match root.attr("type") { - Some(type_) => type_.parse()?, - None => Default::default(), - }; - let mut payloads = vec!(); - for elem in root.children() { - let payload = if let Ok(body) = body::parse_body(elem) { - Some(MessagePayload::Body(body)) - } else if let Ok(stanza_error) = StanzaError::try_from(elem) { - Some(MessagePayload::StanzaError(stanza_error)) - } else if let Ok(chatstate) = ChatState::try_from(elem) { - Some(MessagePayload::ChatState(chatstate)) - } else if let Ok(receipt) = Receipt::try_from(elem) { - Some(MessagePayload::Receipt(receipt)) - } else if let Ok(delay) = Delay::try_from(elem) { - Some(MessagePayload::Delay(delay)) - } else if let Ok(attention) = Attention::try_from(elem) { - Some(MessagePayload::Attention(attention)) - } else if let Ok(replace) = Replace::try_from(elem) { - Some(MessagePayload::MessageCorrect(replace)) - } else if let Ok(eme) = ExplicitMessageEncryption::try_from(elem) { - Some(MessagePayload::ExplicitMessageEncryption(eme)) - } else { - None +impl<'a> TryFrom<&'a Element> for Message { + type Error = Error; + + fn try_from(root: &'a Element) -> Result { + if !root.is("message", ns::JABBER_CLIENT) { + return Err(Error::ParseError("This is not a message element.")); + } + let from = root.attr("from") + .and_then(|value| value.parse().ok()); + let to = root.attr("to") + .and_then(|value| value.parse().ok()); + let id = root.attr("id") + .and_then(|value| value.parse().ok()); + let type_ = match root.attr("type") { + Some(type_) => type_.parse()?, + None => Default::default(), }; - payloads.push(match payload { - Some(payload) => MessagePayloadType::Parsed(payload), - None => MessagePayloadType::XML(elem.clone()), - }); - } - Ok(Message { - from: from, - to: to, - id: id, - type_: type_, - payloads: payloads, - }) -} - -pub fn serialise_payload(payload: &MessagePayload) -> Element { - match *payload { - MessagePayload::Body(ref body) => body::serialise(body), - MessagePayload::StanzaError(ref stanza_error) => stanza_error.into(), - MessagePayload::Attention(ref attention) => attention.into(), - MessagePayload::ChatState(ref chatstate) => chatstate.into(), - MessagePayload::Receipt(ref receipt) => receipt.into(), - MessagePayload::Delay(ref delay) => delay.into(), - MessagePayload::MessageCorrect(ref replace) => replace.into(), - MessagePayload::ExplicitMessageEncryption(ref eme) => eme.into(), + let mut payloads = vec!(); + for elem in root.children() { + let payload = if let Ok(body) = body::parse_body(elem) { + Some(MessagePayload::Body(body)) + } else if let Ok(stanza_error) = StanzaError::try_from(elem) { + Some(MessagePayload::StanzaError(stanza_error)) + } else if let Ok(chatstate) = ChatState::try_from(elem) { + Some(MessagePayload::ChatState(chatstate)) + } else if let Ok(receipt) = Receipt::try_from(elem) { + Some(MessagePayload::Receipt(receipt)) + } else if let Ok(delay) = Delay::try_from(elem) { + Some(MessagePayload::Delay(delay)) + } else if let Ok(attention) = Attention::try_from(elem) { + Some(MessagePayload::Attention(attention)) + } else if let Ok(replace) = Replace::try_from(elem) { + Some(MessagePayload::MessageCorrect(replace)) + } else if let Ok(eme) = ExplicitMessageEncryption::try_from(elem) { + Some(MessagePayload::ExplicitMessageEncryption(eme)) + } else { + None + }; + payloads.push(match payload { + Some(payload) => MessagePayloadType::Parsed(payload), + None => MessagePayloadType::XML(elem.clone()), + }); + } + Ok(Message { + from: from, + to: to, + id: id, + type_: type_, + payloads: payloads, + }) } } -pub fn serialise(message: &Message) -> Element { - let mut stanza = Element::builder("message") - .ns(ns::JABBER_CLIENT) - .attr("from", message.from.clone().and_then(|value| Some(String::from(value)))) - .attr("to", message.to.clone().and_then(|value| Some(String::from(value)))) - .attr("id", message.id.clone()) - .attr("type", message.type_.clone()) - .build(); - for child in message.payloads.clone() { - let elem = match child { - MessagePayloadType::XML(elem) => elem, - MessagePayloadType::Parsed(payload) => serialise_payload(&payload), - }; - stanza.append_child(elem); +impl<'a> Into for &'a MessagePayload { + fn into(self) -> Element { + match *self { + MessagePayload::Body(ref body) => body::serialise(body), + MessagePayload::StanzaError(ref stanza_error) => stanza_error.into(), + MessagePayload::Attention(ref attention) => attention.into(), + MessagePayload::ChatState(ref chatstate) => chatstate.into(), + MessagePayload::Receipt(ref receipt) => receipt.into(), + MessagePayload::Delay(ref delay) => delay.into(), + MessagePayload::MessageCorrect(ref replace) => replace.into(), + MessagePayload::ExplicitMessageEncryption(ref eme) => eme.into(), + } } - stanza } -impl IntoElements for Message { - fn into_elements(self, emitter: &mut ElementEmitter) { - let elem = serialise(&self); - emitter.append_child(elem); +impl<'a> Into for &'a Message { + fn into(self) -> Element { + let mut stanza = Element::builder("message") + .ns(ns::JABBER_CLIENT) + .attr("from", self.from.clone().and_then(|value| Some(String::from(value)))) + .attr("to", self.to.clone().and_then(|value| Some(String::from(value)))) + .attr("id", self.id.clone()) + .attr("type", self.type_.clone()) + .build(); + for child in self.payloads.clone() { + let elem = match child { + MessagePayloadType::XML(elem) => elem, + MessagePayloadType::Parsed(payload) => (&payload).into(), + }; + stanza.append_child(elem); + } + stanza } } #[cfg(test)] mod tests { - use std::str::FromStr; - use minidom::Element; - use jid::Jid; - use message; + use super::*; #[test] fn test_simple() { let elem: Element = "".parse().unwrap(); - let message = message::parse_message(&elem).unwrap(); + let message = Message::try_from(&elem).unwrap(); assert_eq!(message.from, None); assert_eq!(message.to, None); assert_eq!(message.id, None); - assert_eq!(message.type_, message::MessageType::Normal); + assert_eq!(message.type_, MessageType::Normal); assert!(message.payloads.is_empty()); } #[test] fn test_serialise() { let elem: Element = "".parse().unwrap(); - let message = message::Message { + let message = Message { from: None, to: None, id: None, - type_: message::MessageType::Normal, + type_: MessageType::Normal, payloads: vec!(), }; - let elem2 = message::serialise(&message); + let elem2 = (&message).into(); assert_eq!(elem, elem2); } #[test] fn test_body() { let elem: Element = "Hello world!".parse().unwrap(); - message::parse_message(&elem).unwrap(); + Message::try_from(&elem).unwrap(); } #[test] fn test_serialise_body() { let elem: Element = "Hello world!".parse().unwrap(); - let message = message::Message { + let message = Message { from: None, to: Some(Jid::from_str("coucou@example.org").unwrap()), id: None, - type_: message::MessageType::Chat, + type_: MessageType::Chat, payloads: vec!( - message::MessagePayloadType::Parsed(message::MessagePayload::Body("Hello world!".to_owned())), + MessagePayloadType::Parsed(MessagePayload::Body("Hello world!".to_owned())), ), }; - let elem2 = message::serialise(&message); + let elem2 = (&message).into(); assert_eq!(elem, elem2); } #[test] fn test_attention() { let elem: Element = "".parse().unwrap(); - let message = message::parse_message(&elem).unwrap(); - let elem2 = message::serialise(&message); + let message = Message::try_from(&elem).unwrap(); + let elem2 = (&message).into(); assert_eq!(elem, elem2); } }