jingle_ft: Improve <range/> parsing.
This commit is contained in:
parent
667ae4c40f
commit
97abc37f1a
1 changed files with 56 additions and 25 deletions
|
|
@ -12,7 +12,7 @@ use std::str::FromStr;
|
|||
use hashes::Hash;
|
||||
use jingle::{Creator, ContentId};
|
||||
|
||||
use minidom::{Element, IntoElements, IntoAttributeValue, ElementEmitter};
|
||||
use minidom::{Element, IntoAttributeValue};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
|
||||
use error::Error;
|
||||
|
|
@ -25,17 +25,32 @@ pub struct Range {
|
|||
pub hashes: Vec<Hash>,
|
||||
}
|
||||
|
||||
impl IntoElements for Range {
|
||||
fn into_elements(self, emitter: &mut ElementEmitter) {
|
||||
let mut elem = Element::builder("range")
|
||||
.ns(ns::JINGLE_FT)
|
||||
.attr("offset", if self.offset == 0 { None } else { Some(self.offset) })
|
||||
.attr("length", self.length)
|
||||
.build();
|
||||
for hash in self.hashes {
|
||||
elem.append_child(hash.into());
|
||||
impl TryFrom<Element> for Range {
|
||||
type Err = Error;
|
||||
|
||||
fn try_from(elem: Element) -> Result<Range, Error> {
|
||||
check_self!(elem, "range", ns::JINGLE_FT);
|
||||
check_no_unknown_attributes!(elem, "range", ["offset", "length"]);
|
||||
let mut hashes = vec!();
|
||||
for child in elem.children() {
|
||||
hashes.push(Hash::try_from(child.clone())?);
|
||||
}
|
||||
emitter.append_child(elem);
|
||||
Ok(Range {
|
||||
offset: get_attr!(elem, "offset", default),
|
||||
length: get_attr!(elem, "length", optional),
|
||||
hashes: hashes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Range> for Element {
|
||||
fn from(range: Range) -> Element {
|
||||
Element::builder("range")
|
||||
.ns(ns::JINGLE_FT)
|
||||
.attr("offset", if range.offset == 0 { None } else { Some(range.offset) })
|
||||
.attr("length", range.length)
|
||||
.append(range.hashes)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,20 +117,7 @@ impl TryFrom<Element> for File {
|
|||
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_hashes.push(Hash::try_from(hash_element.clone())?);
|
||||
}
|
||||
file.range = Some(Range {
|
||||
offset: offset,
|
||||
length: length,
|
||||
hashes: range_hashes,
|
||||
});
|
||||
file.range = Some(Range::try_from(child.clone())?);
|
||||
} else if child.is("hash", ns::HASHES) {
|
||||
file.hashes.push(Hash::try_from(child.clone())?);
|
||||
} else {
|
||||
|
|
@ -463,4 +465,33 @@ mod tests {
|
|||
};
|
||||
assert_eq!(message, "Unknown value for 'creator' attribute.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range() {
|
||||
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5'/>".parse().unwrap();
|
||||
let range = Range::try_from(elem).unwrap();
|
||||
assert_eq!(range.offset, 0);
|
||||
assert_eq!(range.length, None);
|
||||
assert_eq!(range.hashes, vec!());
|
||||
|
||||
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5' offset='2048' length='1024'><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>kHp5RSzW/h7Gm1etSf90Mr5PC/k=</hash></range>".parse().unwrap();
|
||||
let hashes = vec!(Hash { algo: Algo::Sha_1, hash: vec!(144, 122, 121, 69, 44, 214, 254, 30, 198, 155, 87, 173, 73, 255, 116, 50, 190, 79, 11, 249) });
|
||||
let range = Range::try_from(elem).unwrap();
|
||||
assert_eq!(range.offset, 2048);
|
||||
assert_eq!(range.length, Some(1024));
|
||||
assert_eq!(range.hashes, hashes);
|
||||
let elem2 = Element::from(range);
|
||||
let range2 = Range::try_from(elem2).unwrap();
|
||||
assert_eq!(range2.offset, 2048);
|
||||
assert_eq!(range2.length, Some(1024));
|
||||
assert_eq!(range2.hashes, hashes);
|
||||
|
||||
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5' coucou=''/>".parse().unwrap();
|
||||
let error = Range::try_from(elem).unwrap_err();
|
||||
let message = match error {
|
||||
Error::ParseError(string) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Unknown attribute in range element.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue