media_element: Switch to Into/TryFrom.

Emmanuel Gil Peyrot created

Change summary

src/data_forms.rs    |  5 ++-
src/media_element.rs | 66 ++++++++++++++++++++++++---------------------
2 files changed, 38 insertions(+), 33 deletions(-)

Detailed changes

src/data_forms.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 minidom::Element;
@@ -11,7 +12,7 @@ use minidom::Element;
 use error::Error;
 use ns;
 
-use media_element::{MediaElement, parse_media_element};
+use media_element::MediaElement;
 
 #[derive(Debug, Clone)]
 pub struct Field {
@@ -74,7 +75,7 @@ pub fn parse_data_form(root: &Element) -> Result<DataForm, Error> {
                 if element.is("value", ns::DATA_FORMS) {
                     values.push(element.text());
                 } else if element.is("media", ns::MEDIA_ELEMENT) {
-                    match parse_media_element(element) {
+                    match MediaElement::try_from(element) {
                         Ok(media_element) => media.push(media_element),
                         Err(_) => (), // TODO: is it really nice to swallow this error?
                     }

src/media_element.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 error::Error;
@@ -23,40 +25,42 @@ pub struct MediaElement {
     pub uris: Vec<URI>,
 }
 
-pub fn parse_media_element(root: &Element) -> Result<MediaElement, Error> {
-    if !root.is("media", ns::MEDIA_ELEMENT) {
-        return Err(Error::ParseError("This is not a media element."));
-    }
+impl<'a> TryFrom<&'a Element> for MediaElement {
+    type Error = Error;
+
+    fn try_from(elem: &'a Element) -> Result<MediaElement, Error> {
+        if !elem.is("media", ns::MEDIA_ELEMENT) {
+            return Err(Error::ParseError("This is not a media element."));
+        }
 
-    let width = root.attr("width").and_then(|width| width.parse().ok());
-    let height = root.attr("height").and_then(|height| height.parse().ok());
-    let mut uris = vec!();
-    for uri in root.children() {
-        if uri.is("uri", ns::MEDIA_ELEMENT) {
-            let type_ = uri.attr("type").ok_or(Error::ParseError("Attribute type on uri is mandatory."))?;
-            let text = uri.text().trim().to_owned();
-            if text == "" {
-                return Err(Error::ParseError("URI missing in uri."));
+        let width = elem.attr("width").and_then(|width| width.parse().ok());
+        let height = elem.attr("height").and_then(|height| height.parse().ok());
+        let mut uris = vec!();
+        for uri in elem.children() {
+            if uri.is("uri", ns::MEDIA_ELEMENT) {
+                let type_ = uri.attr("type").ok_or(Error::ParseError("Attribute type on uri is mandatory."))?;
+                let text = uri.text().trim().to_owned();
+                if text == "" {
+                    return Err(Error::ParseError("URI missing in uri."));
+                }
+                uris.push(URI { type_: type_.to_owned(), uri: text });
+            } else {
+                return Err(Error::ParseError("Unknown child in media element."));
             }
-            uris.push(URI { type_: type_.to_owned(), uri: text });
-        } else {
-            return Err(Error::ParseError("Unknown child in media element."));
         }
+        Ok(MediaElement { width: width, height: height, uris: uris })
     }
-    Ok(MediaElement { width: width, height: height, uris: uris })
 }
 
 #[cfg(test)]
 mod tests {
-    use minidom::Element;
-    use error::Error;
-    use media_element;
+    use super::*;
     use data_forms;
 
     #[test]
     fn test_simple() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element'/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.width.is_none());
         assert!(media.height.is_none());
         assert!(media.uris.is_empty());
@@ -65,7 +69,7 @@ mod tests {
     #[test]
     fn test_width_height() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element' width='32' height='32'/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert_eq!(media.width.unwrap(), 32);
         assert_eq!(media.height.unwrap(), 32);
     }
@@ -73,7 +77,7 @@ mod tests {
     #[test]
     fn test_uri() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri type='text/html'>https://example.org/</uri></media>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert_eq!(media.uris.len(), 1);
         assert_eq!(media.uris[0].type_, "text/html");
         assert_eq!(media.uris[0].uri, "https://example.org/");
@@ -82,26 +86,26 @@ mod tests {
     #[test]
     fn test_invalid_width_height() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element' width=''/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.width.is_none());
 
         let elem: Element = "<media xmlns='urn:xmpp:media-element' width='coucou'/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.width.is_none());
 
         let elem: Element = "<media xmlns='urn:xmpp:media-element' height=''/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.height.is_none());
 
         let elem: Element = "<media xmlns='urn:xmpp:media-element' height='-10'/>".parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.height.is_none());
     }
 
     #[test]
     fn test_unknown_child() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element'><coucou/></media>".parse().unwrap();
-        let error = media_element::parse_media_element(&elem).unwrap_err();
+        let error = MediaElement::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -112,7 +116,7 @@ mod tests {
     #[test]
     fn test_bad_uri() {
         let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri>https://example.org/</uri></media>".parse().unwrap();
-        let error = media_element::parse_media_element(&elem).unwrap_err();
+        let error = MediaElement::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -120,7 +124,7 @@ mod tests {
         assert_eq!(message, "Attribute type on uri is mandatory.");
 
         let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri type='text/html'/></media>".parse().unwrap();
-        let error = media_element::parse_media_element(&elem).unwrap_err();
+        let error = MediaElement::try_from(&elem).unwrap_err();
         let message = match error {
             Error::ParseError(string) => string,
             _ => panic!(),
@@ -142,7 +146,7 @@ mod tests {
     http://victim.example.com/challenges/speech.mp3?F3A6292C
   </uri>
 </media>"#.parse().unwrap();
-        let media = media_element::parse_media_element(&elem).unwrap();
+        let media = MediaElement::try_from(&elem).unwrap();
         assert!(media.width.is_none());
         assert!(media.height.is_none());
         assert_eq!(media.uris.len(), 3);