stanza_id: Switch to Into/TryFrom.

Emmanuel Gil Peyrot created

Change summary

src/stanza_id.rs | 102 +++++++++++++++++++++++++------------------------
1 file changed, 53 insertions(+), 49 deletions(-)

Detailed changes

src/stanza_id.rs 🔗

@@ -4,6 +4,8 @@
 // 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 jid::Jid;
 
@@ -22,61 +24,63 @@ pub enum StanzaId {
     },
 }
 
-pub fn parse_stanza_id(root: &Element) -> Result<StanzaId, Error> {
-    let is_stanza_id = root.is("stanza-id", ns::SID);
-    if !is_stanza_id && !root.is("origin-id", ns::SID) {
-        return Err(Error::ParseError("This is not a stanza-id or origin-id element."));
-    }
-    for _ in root.children() {
-        return Err(Error::ParseError("Unknown child in stanza-id or origin-id element."));
-    }
-    let id = match root.attr("id") {
-        Some(id) => id.to_owned(),
-        None => return Err(Error::ParseError("No 'id' attribute present in stanza-id or origin-id.")),
-    };
-    Ok(if is_stanza_id {
-        let by = match root.attr("by") {
-            Some(by) => by.parse().unwrap(),
-            None => return Err(Error::ParseError("No 'by' attribute present in stanza-id.")),
+impl<'a> TryFrom<&'a Element> for StanzaId {
+    type Error = Error;
+
+    fn try_from(elem: &'a Element) -> Result<StanzaId, Error> {
+        let is_stanza_id = elem.is("stanza-id", ns::SID);
+        if !is_stanza_id && !elem.is("origin-id", ns::SID) {
+            return Err(Error::ParseError("This is not a stanza-id or origin-id element."));
+        }
+        for _ in elem.children() {
+            return Err(Error::ParseError("Unknown child in stanza-id or origin-id element."));
+        }
+        let id = match elem.attr("id") {
+            Some(id) => id.to_owned(),
+            None => return Err(Error::ParseError("No 'id' attribute present in stanza-id or origin-id.")),
         };
-        StanzaId::StanzaId { id, by }
-    } else {
-        StanzaId::OriginId { id }
-    })
+        Ok(if is_stanza_id {
+            let by = match elem.attr("by") {
+                Some(by) => by.parse().unwrap(),
+                None => return Err(Error::ParseError("No 'by' attribute present in stanza-id.")),
+            };
+            StanzaId::StanzaId { id, by }
+        } else {
+            StanzaId::OriginId { id }
+        })
+    }
 }
 
-pub fn serialise(stanza_id: &StanzaId) -> Element {
-    match *stanza_id {
-        StanzaId::StanzaId { ref id, ref by } => {
-            Element::builder("stanza-id")
-                    .ns(ns::SID)
-                    .attr("id", id.clone())
-                    .attr("by", String::from(by.clone()))
-                    .build()
-        },
-        StanzaId::OriginId { ref id } => {
-            Element::builder("origin-id")
-                    .ns(ns::SID)
-                    .attr("id", id.clone())
-                    .build()
-        },
+impl<'a> Into<Element> for &'a StanzaId {
+    fn into(self) -> Element {
+        match *self {
+            StanzaId::StanzaId { ref id, ref by } => {
+                Element::builder("stanza-id")
+                        .ns(ns::SID)
+                        .attr("id", id.clone())
+                        .attr("by", String::from(by.clone()))
+                        .build()
+            },
+            StanzaId::OriginId { ref id } => {
+                Element::builder("origin-id")
+                        .ns(ns::SID)
+                        .attr("id", id.clone())
+                        .build()
+            },
+        }
     }
 }
 
 #[cfg(test)]
 mod tests {
+    use super::*;
     use std::str::FromStr;
 
-    use minidom::Element;
-    use jid::Jid;
-    use error::Error;
-    use stanza_id;
-
     #[test]
     fn test_simple() {
         let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou' by='coucou@coucou'/>".parse().unwrap();
-        let stanza_id = stanza_id::parse_stanza_id(&elem).unwrap();
-        if let stanza_id::StanzaId::StanzaId { id, by } = stanza_id {
+        let stanza_id = StanzaId::try_from(&elem).unwrap();
+        if let StanzaId::StanzaId { id, by } = stanza_id {
             assert_eq!(id, String::from("coucou"));
             assert_eq!(by, Jid::from_str("coucou@coucou").unwrap());
         } else {
@@ -84,8 +88,8 @@ mod tests {
         }
 
         let elem: Element = "<origin-id xmlns='urn:xmpp:sid:0' id='coucou'/>".parse().unwrap();
-        let stanza_id = stanza_id::parse_stanza_id(&elem).unwrap();
-        if let stanza_id::StanzaId::OriginId { id } = stanza_id {
+        let stanza_id = StanzaId::try_from(&elem).unwrap();
+        if let StanzaId::OriginId { id } = stanza_id {
             assert_eq!(id, String::from("coucou"));
         } else {
             panic!();
@@ -95,7 +99,7 @@ mod tests {
     #[test]
     fn test_invalid_child() {
         let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0'><coucou/></stanza-id>".parse().unwrap();
-        let error = stanza_id::parse_stanza_id(&elem).unwrap_err();
+        let error = StanzaId::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -106,7 +110,7 @@ mod tests {
     #[test]
     fn test_invalid_id() {
         let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0'/>".parse().unwrap();
-        let error = stanza_id::parse_stanza_id(&elem).unwrap_err();
+        let error = StanzaId::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -117,7 +121,7 @@ mod tests {
     #[test]
     fn test_invalid_by() {
         let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou'/>".parse().unwrap();
-        let error = stanza_id::parse_stanza_id(&elem).unwrap_err();
+        let error = StanzaId::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -128,8 +132,8 @@ mod tests {
     #[test]
     fn test_serialise() {
         let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou' by='coucou@coucou'/>".parse().unwrap();
-        let stanza_id = stanza_id::StanzaId::StanzaId { id: String::from("coucou"), by: Jid::from_str("coucou@coucou").unwrap() };
-        let elem2 = stanza_id::serialise(&stanza_id);
+        let stanza_id = StanzaId::StanzaId { id: String::from("coucou"), by: Jid::from_str("coucou@coucou").unwrap() };
+        let elem2 = (&stanza_id).into();
         assert_eq!(elem, elem2);
     }
 }