diff --git a/src/data_forms.rs b/src/data_forms.rs index 3b3757e..94dae1c 100644 --- a/src/data_forms.rs +++ b/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 { 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? } diff --git a/src/media_element.rs b/src/media_element.rs index a3c360e..be2adda 100644 --- a/src/media_element.rs +++ b/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, } -pub fn parse_media_element(root: &Element) -> Result { - 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; - 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.")); - } - uris.push(URI { type_: type_.to_owned(), uri: text }); - } else { - return Err(Error::ParseError("Unknown child in media element.")); + fn try_from(elem: &'a Element) -> Result { + if !elem.is("media", ns::MEDIA_ELEMENT) { + return Err(Error::ParseError("This is not a media element.")); } + + 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.")); + } + } + 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 = "".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 = "".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 = "https://example.org/".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 = "".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 = "".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 = "".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 = "".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 = "".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 = "https://example.org/".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 = "".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 "#.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);