diff --git a/src/ecaps2.rs b/src/ecaps2.rs index aa2cde7..62242db 100644 --- a/src/ecaps2.rs +++ b/src/ecaps2.rs @@ -4,10 +4,11 @@ // 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 disco::{Feature, Identity, Disco}; use data_forms::DataForm; -use hashes; -use hashes::{Hash, parse_hash}; +use hashes::Hash; use minidom::Element; use error::Error; @@ -31,7 +32,7 @@ pub fn parse_ecaps2(root: &Element) -> Result { let mut hashes = vec!(); for child in root.children() { if child.is("hash", ns::HASHES) { - let hash = parse_hash(child)?; + let hash = Hash::try_from(child)?; hashes.push(hash); } else { return Err(Error::ParseError("Unknown child in ecaps2 element.")); @@ -47,7 +48,7 @@ pub fn serialise(ecaps2: &ECaps2) -> Element { .ns(ns::ECAPS2) .build(); for hash in ecaps2.hashes.clone() { - let hash_elem = hashes::serialise(&hash); + let hash_elem = (&hash).into(); c.append_child(hash_elem); } c diff --git a/src/hashes.rs b/src/hashes.rs index c489a32..6e7bcb2 100644 --- a/src/hashes.rs +++ b/src/hashes.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; @@ -16,42 +18,46 @@ pub struct Hash { pub hash: String, } -pub fn parse_hash(root: &Element) -> Result { - if !root.is("hash", ns::HASHES) { - return Err(Error::ParseError("This is not a hash element.")); +impl<'a> TryFrom<&'a Element> for Hash { + type Error = Error; + + fn try_from(elem: &'a Element) -> Result { + if !elem.is("hash", ns::HASHES) { + return Err(Error::ParseError("This is not a hash element.")); + } + for _ in elem.children() { + return Err(Error::ParseError("Unknown child in hash element.")); + } + let algo = elem.attr("algo").ok_or(Error::ParseError("Mandatory argument 'algo' not present in hash element."))?.to_owned(); + let hash = match elem.text().as_ref() { + "" => return Err(Error::ParseError("Hash element shouldn’t be empty.")), + text => text.to_owned(), + }; + Ok(Hash { + algo: algo, + hash: hash, + }) } - for _ in root.children() { - return Err(Error::ParseError("Unknown child in hash element.")); - } - let algo = root.attr("algo").ok_or(Error::ParseError("Mandatory argument 'algo' not present in hash element."))?.to_owned(); - let hash = match root.text().as_ref() { - "" => return Err(Error::ParseError("Hash element shouldn’t be empty.")), - text => text.to_owned(), - }; - Ok(Hash { - algo: algo, - hash: hash, - }) } -pub fn serialise(hash: &Hash) -> Element { - Element::builder("hash") - .ns(ns::HASHES) - .attr("algo", hash.algo.clone()) - .append(hash.hash.clone()) - .build() +impl<'a> Into for &'a Hash { + fn into(self) -> Element { + Element::builder("hash") + .ns(ns::HASHES) + .attr("algo", self.algo.clone()) + .append(self.hash.clone()) + .build() + } } #[cfg(test)] mod tests { - use minidom::Element; - use error::Error; - use hashes; + use super::*; #[test] fn test_simple() { let elem: Element = "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=".parse().unwrap(); - let hash = hashes::parse_hash(&elem).unwrap(); + let hash = Hash::try_from(&elem).unwrap(); assert_eq!(hash.algo, "sha-256"); assert_eq!(hash.hash, "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU="); } @@ -59,7 +65,7 @@ mod tests { #[test] fn test_unknown() { let elem: Element = "".parse().unwrap(); - let error = hashes::parse_hash(&elem).unwrap_err(); + let error = Hash::try_from(&elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), @@ -70,7 +76,7 @@ mod tests { #[test] fn test_invalid_child() { let elem: Element = "".parse().unwrap(); - let error = hashes::parse_hash(&elem).unwrap_err(); + let error = Hash::try_from(&elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), diff --git a/src/jingle_ft.rs b/src/jingle_ft.rs index f2b981f..efbe9c9 100644 --- a/src/jingle_ft.rs +++ b/src/jingle_ft.rs @@ -6,8 +6,7 @@ use std::convert::TryFrom; -use hashes; -use hashes::{Hash, parse_hash}; +use hashes::Hash; use minidom::{Element, IntoElements, ElementEmitter}; @@ -32,7 +31,7 @@ impl IntoElements for Range { }) .build(); for hash in self.hashes { - elem.append_child(hashes::serialise(&hash)); + elem.append_child((&hash).into()); } emitter.append_child(elem); } @@ -149,7 +148,7 @@ impl<'a> TryFrom<&'a Element> for Description { if !hash_element.is("hash", ns::HASHES) { return Err(Error::ParseError("Unknown element in JingleFT range.")); } - range_hashes.push(parse_hash(hash_element)?); + range_hashes.push(Hash::try_from(hash_element)?); } range = Some(Range { offset: offset, @@ -157,7 +156,7 @@ impl<'a> TryFrom<&'a Element> for Description { hashes: range_hashes, }); } else if file_payload.is("hash", ns::HASHES) { - hashes.push(parse_hash(file_payload)?); + hashes.push(Hash::try_from(file_payload)?); } else { return Err(Error::ParseError("Unknown element in JingleFT file.")); } @@ -220,7 +219,7 @@ impl<'a> Into for &'a File { .build()); } for hash in self.hashes.clone() { - root.append_child(hashes::serialise(&hash)); + root.append_child((&hash).into()); } root }