From cf31506580c8d1fd646e7a09d0d70cae144c24d7 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 31 Oct 2017 16:25:01 +0000 Subject: [PATCH] jingle_ft: Split Description::try_from into File::try_from. --- src/jingle_ft.rs | 245 ++++++++++++++++++++++++----------------------- 1 file changed, 125 insertions(+), 120 deletions(-) diff --git a/src/jingle_ft.rs b/src/jingle_ft.rs index 3558d3022b790791ddbe00bacf0df52801a50162..5cc739c878327aa84e903bf1efcf983cc30a9772 100644 --- a/src/jingle_ft.rs +++ b/src/jingle_ft.rs @@ -54,134 +54,76 @@ pub struct File { pub hashes: Vec, } -#[derive(Debug, Clone)] -pub struct Description { - pub file: File, -} - -#[derive(Debug, Clone)] -pub struct Checksum { - pub name: ContentId, - pub creator: Creator, - pub file: File, -} - -#[derive(Debug, Clone)] -pub struct Received { - pub name: ContentId, - pub creator: Creator, -} - -impl TryFrom for Received { +impl TryFrom for File { type Err = Error; - fn try_from(elem: Element) -> Result { - check_self!(elem, "received", ns::JINGLE_FT); - check_no_children!(elem, "received"); - check_no_unknown_attributes!(elem, "received", ["name", "creator"]); - Ok(Received { - name: get_attr!(elem, "name", required), - creator: get_attr!(elem, "creator", required), - }) - } -} - -impl From for Element { - fn from(received: Received) -> Element { - Element::builder("received") - .ns(ns::JINGLE_FT) - .attr("name", received.name) - .attr("creator", received.creator) - .build() - } -} - -impl TryFrom for Description { - type Err = Error; - - fn try_from(elem: Element) -> Result { - if !elem.is("description", ns::JINGLE_FT) { - return Err(Error::ParseError("This is not a JingleFT description element.")); - } - if elem.children().count() != 1 { - return Err(Error::ParseError("JingleFT description element must have exactly one child.")); - } + fn try_from(elem: Element) -> Result { + check_self!(elem, "file", ns::JINGLE_FT); + check_no_attributes!(elem, "file"); + + let mut file = File { + date: None, + media_type: None, + name: None, + descs: BTreeMap::new(), + size: None, + range: None, + hashes: vec!(), + }; - let mut date = None; - let mut media_type = None; - let mut name = None; - let mut descs = BTreeMap::new(); - let mut size = None; - let mut range = None; - let mut hashes = vec!(); - for description_payload in elem.children() { - if !description_payload.is("file", ns::JINGLE_FT) { - return Err(Error::ParseError("Unknown element in JingleFT description.")); - } - for file_payload in description_payload.children() { - if file_payload.is("date", ns::JINGLE_FT) { - if date.is_some() { - return Err(Error::ParseError("File must not have more than one date.")); - } - date = Some(file_payload.text().parse()?); - } else if file_payload.is("media-type", ns::JINGLE_FT) { - if media_type.is_some() { - return Err(Error::ParseError("File must not have more than one media-type.")); - } - media_type = Some(file_payload.text()); - } else if file_payload.is("name", ns::JINGLE_FT) { - if name.is_some() { - return Err(Error::ParseError("File must not have more than one name.")); - } - name = Some(file_payload.text()); - } else if file_payload.is("desc", ns::JINGLE_FT) { - let lang = get_attr!(file_payload, "xml:lang", default); - let desc = Desc(file_payload.text()); - if descs.insert(lang, desc).is_some() { - return Err(Error::ParseError("Desc element present twice for the same xml:lang.")); - } - } else if file_payload.is("size", ns::JINGLE_FT) { - if size.is_some() { - return Err(Error::ParseError("File must not have more than one size.")); - } - size = Some(file_payload.text().parse()?); - } else if file_payload.is("range", ns::JINGLE_FT) { - if range.is_some() { - return Err(Error::ParseError("File must not have more than one range.")); - } - let offset = get_attr!(file_payload, "offset", default); - let length = get_attr!(file_payload, "length", optional); - let mut range_hashes = vec!(); - for hash_element in file_payload.children() { - if !hash_element.is("hash", ns::HASHES) { - return Err(Error::ParseError("Unknown element in JingleFT range.")); - } - range_hashes.push(Hash::try_from(hash_element.clone())?); + for child in elem.children() { + if child.is("date", ns::JINGLE_FT) { + if file.date.is_some() { + return Err(Error::ParseError("File must not have more than one date.")); + } + file.date = Some(child.text().parse()?); + } else if child.is("media-type", ns::JINGLE_FT) { + if file.media_type.is_some() { + return Err(Error::ParseError("File must not have more than one media-type.")); + } + file.media_type = Some(child.text()); + } else if child.is("name", ns::JINGLE_FT) { + if file.name.is_some() { + return Err(Error::ParseError("File must not have more than one name.")); + } + file.name = Some(child.text()); + } else if child.is("desc", ns::JINGLE_FT) { + let lang = get_attr!(child, "xml:lang", default); + let desc = Desc(child.text()); + if file.descs.insert(lang, desc).is_some() { + return Err(Error::ParseError("Desc element present twice for the same xml:lang.")); + } + } else if child.is("size", ns::JINGLE_FT) { + if file.size.is_some() { + return Err(Error::ParseError("File must not have more than one size.")); + } + file.size = Some(child.text().parse()?); + } else if child.is("range", ns::JINGLE_FT) { + if file.range.is_some() { + return Err(Error::ParseError("File must not have more than one range.")); + } + let offset = get_attr!(child, "offset", default); + let length = get_attr!(child, "length", optional); + let mut range_hashes = vec!(); + for hash_element in child.children() { + if !hash_element.is("hash", ns::HASHES) { + return Err(Error::ParseError("Unknown element in JingleFT range.")); } - range = Some(Range { - offset: offset, - length: length, - hashes: range_hashes, - }); - } else if file_payload.is("hash", ns::HASHES) { - hashes.push(Hash::try_from(file_payload.clone())?); - } else { - return Err(Error::ParseError("Unknown element in JingleFT file.")); + range_hashes.push(Hash::try_from(hash_element.clone())?); } + file.range = Some(Range { + offset: offset, + length: length, + hashes: range_hashes, + }); + } else if child.is("hash", ns::HASHES) { + file.hashes.push(Hash::try_from(child.clone())?); + } else { + return Err(Error::ParseError("Unknown element in JingleFT file.")); } } - Ok(Description { - file: File { - date: date, - media_type: media_type, - name: name, - descs: descs, - size: size, - range: range, - hashes: hashes, - }, - }) + Ok(file) } } @@ -233,6 +175,32 @@ impl From for Element { root } } +#[derive(Debug, Clone)] +pub struct Description { + pub file: File, +} + +impl TryFrom for Description { + type Err = Error; + + fn try_from(elem: Element) -> Result { + check_self!(elem, "description", ns::JINGLE_FT, "JingleFT description"); + check_no_attributes!(elem, "JingleFT description"); + let mut file = None; + for child in elem.children() { + if file.is_some() { + return Err(Error::ParseError("JingleFT description element must have exactly one child.")); + } + file = Some(File::try_from(child.clone())?); + } + if file.is_none() { + return Err(Error::ParseError("JingleFT description element must have exactly one child.")); + } + Ok(Description { + file: file.unwrap(), + }) + } +} impl From for Element { fn from(description: Description) -> Element { @@ -244,6 +212,43 @@ impl From for Element { } } +#[derive(Debug, Clone)] +pub struct Checksum { + pub name: ContentId, + pub creator: Creator, + pub file: File, +} + +#[derive(Debug, Clone)] +pub struct Received { + pub name: ContentId, + pub creator: Creator, +} + +impl TryFrom for Received { + type Err = Error; + + fn try_from(elem: Element) -> Result { + check_self!(elem, "received", ns::JINGLE_FT); + check_no_children!(elem, "received"); + check_no_unknown_attributes!(elem, "received", ["name", "creator"]); + Ok(Received { + name: get_attr!(elem, "name", required), + creator: get_attr!(elem, "creator", required), + }) + } +} + +impl From for Element { + fn from(received: Received) -> Element { + Element::builder("received") + .ns(ns::JINGLE_FT) + .attr("name", received.name) + .attr("creator", received.creator) + .build() + } +} + #[cfg(test)] mod tests { use super::*;