diff --git a/src/delay.rs b/src/delay.rs index 2b2149eb..a15b61bc 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -4,7 +4,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use minidom::{Element, IntoElements, ElementEmitter}; +use std::convert::TryFrom; + +use minidom::Element; use error::Error; use jid::Jid; @@ -18,54 +20,50 @@ pub struct Delay { pub data: Option, } -pub fn parse_delay(root: &Element) -> Result { - if !root.is("delay", ns::DELAY) { - return Err(Error::ParseError("This is not a delay element.")); +impl<'a> TryFrom<&'a Element> for Delay { + type Error = Error; + + fn try_from(elem: &'a Element) -> Result { + if !elem.is("delay", ns::DELAY) { + return Err(Error::ParseError("This is not a delay element.")); + } + for _ in elem.children() { + return Err(Error::ParseError("Unknown child in delay element.")); + } + let from = elem.attr("from").and_then(|value| value.parse().ok()); + let stamp = elem.attr("stamp").ok_or(Error::ParseError("Mandatory argument 'stamp' not present in delay element."))?.to_owned(); + let data = match elem.text().as_ref() { + "" => None, + text => Some(text.to_owned()), + }; + Ok(Delay { + from: from, + stamp: stamp, + data: data, + }) } - for _ in root.children() { - return Err(Error::ParseError("Unknown child in delay element.")); - } - let from = root.attr("from").and_then(|value| value.parse().ok()); - let stamp = root.attr("stamp").ok_or(Error::ParseError("Mandatory argument 'stamp' not present in delay element."))?.to_owned(); - let data = match root.text().as_ref() { - "" => None, - text => Some(text.to_owned()), - }; - Ok(Delay { - from: from, - stamp: stamp, - data: data, - }) } -pub fn serialise(delay: &Delay) -> Element { - Element::builder("delay") - .ns(ns::DELAY) - .attr("from", delay.from.clone().and_then(|value| Some(String::from(value)))) - .attr("stamp", delay.stamp.clone()) - .append(delay.data.clone()) - .build() -} - -impl IntoElements for Delay { - fn into_elements(self, emitter: &mut ElementEmitter) { - let elem = serialise(&self); - emitter.append_child(elem) +impl<'a> Into for &'a Delay { + fn into(self) -> Element { + Element::builder("delay") + .ns(ns::DELAY) + .attr("from", self.from.clone().and_then(|value| Some(String::from(value)))) + .attr("stamp", self.stamp.clone()) + .append(self.data.clone()) + .build() } } #[cfg(test)] mod tests { use std::str::FromStr; - use minidom::Element; - use error::Error; - use jid::Jid; - use delay; + use super::*; #[test] fn test_simple() { let elem: Element = "".parse().unwrap(); - let delay = delay::parse_delay(&elem).unwrap(); + let delay = Delay::try_from(&elem).unwrap(); assert_eq!(delay.from, Some(Jid::from_str("capulet.com").unwrap())); assert_eq!(delay.stamp, "2002-09-10T23:08:25Z"); assert_eq!(delay.data, None); @@ -74,7 +72,7 @@ mod tests { #[test] fn test_unknown() { let elem: Element = "".parse().unwrap(); - let error = delay::parse_delay(&elem).unwrap_err(); + let error = Delay::try_from(&elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), @@ -85,7 +83,7 @@ mod tests { #[test] fn test_invalid_child() { let elem: Element = "".parse().unwrap(); - let error = delay::parse_delay(&elem).unwrap_err(); + let error = Delay::try_from(&elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), @@ -96,24 +94,24 @@ mod tests { #[test] fn test_serialise() { let elem: Element = "".parse().unwrap(); - let delay = delay::Delay { + let delay = Delay { from: None, stamp: "2002-09-10T23:08:25Z".to_owned(), data: None, }; - let elem2 = delay::serialise(&delay); + let elem2 = (&delay).into(); assert_eq!(elem, elem2); } #[test] fn test_serialise_data() { let elem: Element = "Reason".parse().unwrap(); - let delay = delay::Delay { + let delay = Delay { from: Some(Jid::from_str("juliet@example.org").unwrap()), stamp: "2002-09-10T23:08:25Z".to_owned(), data: Some(String::from("Reason")), }; - let elem2 = delay::serialise(&delay); + let elem2 = (&delay).into(); assert_eq!(elem, elem2); } } diff --git a/src/forwarding.rs b/src/forwarding.rs index 991d508a..d3441457 100644 --- a/src/forwarding.rs +++ b/src/forwarding.rs @@ -4,18 +4,20 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::convert::TryFrom; + use minidom::Element; use error::Error; -use delay; +use delay::Delay; use message; use ns; #[derive(Debug, Clone)] pub struct Forwarded { - pub delay: Option, + pub delay: Option, // XXX: really? Option? pub stanza: Option, } @@ -28,7 +30,7 @@ pub fn parse_forwarded(root: &Element) -> Result { let mut stanza = None; for child in root.children() { if child.is("delay", ns::DELAY) { - delay = Some(delay::parse_delay(child)?); + delay = Some(Delay::try_from(child)?); } else if child.is("message", ns::JABBER_CLIENT) { stanza = Some(message::parse_message(child)?); // TODO: also handle the five other possibilities. @@ -45,7 +47,7 @@ pub fn parse_forwarded(root: &Element) -> Result { pub fn serialise(forwarded: &Forwarded) -> Element { Element::builder("forwarded") .ns(ns::FORWARD) - .append(forwarded.delay.clone()) + .append(match forwarded.delay { Some(ref delay) => { let elem: Element = delay.into(); Some(elem) }, None => None }) .append(forwarded.stanza.clone()) .build() } diff --git a/src/message.rs b/src/message.rs index dfc5e6eb..476920a0 100644 --- a/src/message.rs +++ b/src/message.rs @@ -19,7 +19,7 @@ use body; use stanza_error; use chatstates::ChatState; use receipts::Receipt; -use delay; +use delay::Delay; use attention::Attention; use message_correct::Replace; use eme; @@ -31,7 +31,7 @@ pub enum MessagePayload { StanzaError(stanza_error::StanzaError), ChatState(ChatState), Receipt(Receipt), - Delay(delay::Delay), + Delay(Delay), Attention(Attention), MessageCorrect(Replace), ExplicitMessageEncryption(eme::ExplicitMessageEncryption), @@ -119,7 +119,7 @@ pub fn parse_message(root: &Element) -> Result { Some(MessagePayload::ChatState(chatstate)) } else if let Ok(receipt) = Receipt::try_from(elem) { Some(MessagePayload::Receipt(receipt)) - } else if let Ok(delay) = delay::parse_delay(elem) { + } 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)) @@ -151,7 +151,7 @@ pub fn serialise_payload(payload: &MessagePayload) -> Element { MessagePayload::Attention(ref attention) => attention.into(), MessagePayload::ChatState(ref chatstate) => chatstate.into(), MessagePayload::Receipt(ref receipt) => receipt.into(), - MessagePayload::Delay(ref delay) => delay::serialise(delay), + MessagePayload::Delay(ref delay) => delay.into(), MessagePayload::MessageCorrect(ref replace) => replace.into(), MessagePayload::ExplicitMessageEncryption(ref eme) => eme::serialise(eme), } diff --git a/src/presence.rs b/src/presence.rs index bf7b57df..de5944c2 100644 --- a/src/presence.rs +++ b/src/presence.rs @@ -4,6 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::convert::TryFrom; use std::str::FromStr; use std::collections::BTreeMap; @@ -16,7 +17,7 @@ use error::Error; use ns; use stanza_error; -use delay; +use delay::Delay; use ecaps2; #[derive(Debug, Clone, PartialEq)] @@ -51,7 +52,7 @@ pub enum PresencePayload { Status(Status), Priority(Priority), StanzaError(stanza_error::StanzaError), - Delay(delay::Delay), + Delay(Delay), ECaps2(ecaps2::ECaps2), } @@ -180,7 +181,7 @@ pub fn parse_presence(root: &Element) -> Result { } else { let payload = if let Ok(stanza_error) = stanza_error::parse_stanza_error(elem) { Some(PresencePayload::StanzaError(stanza_error)) - } else if let Ok(delay) = delay::parse_delay(elem) { + } else if let Ok(delay) = Delay::try_from(elem) { Some(PresencePayload::Delay(delay)) } else if let Ok(ecaps2) = ecaps2::parse_ecaps2(elem) { Some(PresencePayload::ECaps2(ecaps2)) @@ -226,7 +227,7 @@ pub fn serialise_payload(payload: &PresencePayload) -> Element { .build() }, PresencePayload::StanzaError(ref stanza_error) => stanza_error::serialise(stanza_error), - PresencePayload::Delay(ref delay) => delay::serialise(delay), + PresencePayload::Delay(ref delay) => delay.into(), PresencePayload::ECaps2(ref ecaps2) => ecaps2::serialise(ecaps2), } }