diff --git a/bip_bencode/src/bencode.rs b/bip_bencode/src/bencode.rs index 79740aaa09..a3d412b31a 100644 --- a/bip_bencode/src/bencode.rs +++ b/bip_bencode/src/bencode.rs @@ -28,7 +28,7 @@ pub enum Bencode<'a> { /// Bencode List. List(Vec>), /// Bencode Dictionary. - Dict(BTreeMap<&'a str, Bencode<'a>>) + Dict(BTreeMap<&'a [u8], Bencode<'a>>) } impl<'a> Bencode<'a> { diff --git a/bip_bencode/src/convert.rs b/bip_bencode/src/convert.rs index 2ffef64cb1..bf8775cf49 100644 --- a/bip_bencode/src/convert.rs +++ b/bip_bencode/src/convert.rs @@ -12,82 +12,87 @@ pub trait BencodeConvert { /// Attempt to convert the given bencode value into an integer. /// /// Error key is used to generate an appropriate error message should the operation return an error. - fn convert_int<'a>(&self, bencode: &Bencode<'a>, error_key: &str) -> Result { + fn convert_int<'a, E>(&self, bencode: &Bencode<'a>, error_key: E) -> Result + where E: AsRef<[u8]> { bencode.int().ok_or(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::WrongType, - "Bencode Is Not An Integer", error_key.to_owned()))) + "Bencode Is Not An Integer", error_key.as_ref().to_owned()))) } /// Attempt to convert the given bencode value into bytes. /// /// EError key is used to generate an appropriate error message should the operation return an error. - fn convert_bytes<'a>(&self, bencode: &Bencode<'a>, error_key: &str) -> Result<&'a [u8], Self::Error> { + fn convert_bytes<'a, E>(&self, bencode: &Bencode<'a>, error_key: E) -> Result<&'a [u8], Self::Error> + where E: AsRef<[u8]> { bencode.bytes().ok_or(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::WrongType, - "Bencode Is Not Bytes", error_key.to_owned()))) + "Bencode Is Not Bytes", error_key.as_ref().to_owned()))) } /// Attempt to convert the given bencode value into a UTF-8 string. /// /// Error key is used to generate an appropriate error message should the operation return an error. - fn convert_str<'a>(&self, bencode: &Bencode<'a>, error_key: &str) -> Result<&'a str, Self::Error> { + fn convert_str<'a, E>(&self, bencode: &Bencode<'a>, error_key: E) -> Result<&'a str, Self::Error> + where E: AsRef<[u8]> { bencode.str().ok_or(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::WrongType, - "Bencode Is Not A String", error_key.to_owned()))) + "Bencode Is Not A String", error_key.as_ref().to_owned()))) } /// Attempty to convert the given bencode value into a list. /// /// Error key is used to generate an appropriate error message should the operation return an error. - fn convert_list<'a, 'b>(&self, bencode: &'b Bencode<'a>, error_key: &str) - -> Result<&'b [Bencode<'a>], Self::Error> { + fn convert_list<'a, 'b, E>(&self, bencode: &'b Bencode<'a>, error_key: E) + -> Result<&'b [Bencode<'a>], Self::Error> where E: AsRef<[u8]> { bencode.list().ok_or(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::WrongType, - "Bencode Is Not A List", error_key.to_owned()))) + "Bencode Is Not A List", error_key.as_ref().to_owned()))) } /// Attempt to convert the given bencode value into a dictionary. /// /// Error key is used to generate an appropriate error message should the operation return an error. - fn convert_dict<'a, 'b>(&self, bencode: &'b Bencode<'a>, error_key: &str) - -> Result<&'b Dictionary<'a, Bencode<'a>>, Self::Error> { + fn convert_dict<'a, 'b, E>(&self, bencode: &'b Bencode<'a>, error_key: E) + -> Result<&'b Dictionary<'a, Bencode<'a>>, Self::Error> where E: AsRef<[u8]> { bencode.dict().ok_or(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::WrongType, - "Bencode Is Not A Dictionary", error_key.to_owned()))) + "Bencode Is Not A Dictionary", error_key.as_ref().to_owned()))) } /// Look up a value in a dictionary of bencoded values using the given key. - fn lookup<'a, 'b>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: &str) - -> Result<&'b Bencode<'a>, Self::Error> { - match dictionary.lookup(key) { + fn lookup<'a, 'b, K>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: K) + -> Result<&'b Bencode<'a>, Self::Error> where K: AsRef<[u8]> { + let key_ref = key.as_ref(); + + match dictionary.lookup(key_ref) { Some(n) => Ok(n), None => Err(self.handle_error(BencodeConvertError::with_key(BencodeConvertErrorKind::MissingKey, - "Dictionary Missing Key", key.to_owned()))) + "Dictionary Missing Key", key_ref.to_owned()))) } } /// Combines a lookup operation on the given key with a conversion of the value, if found, to an integer. - fn lookup_and_convert_int<'a>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: &str) - -> Result { - self.convert_int(try!(self.lookup(dictionary, key)), key) + fn lookup_and_convert_int<'a, K>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: K) + -> Result where K: AsRef<[u8]> { + self.convert_int(try!(self.lookup(dictionary, &key)), &key) } /// Combines a lookup operation on the given key with a conversion of the value, if found, to a series of bytes. - fn lookup_and_convert_bytes<'a>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: &str) - -> Result<&'a [u8], Self::Error> { - self.convert_bytes(try!(self.lookup(dictionary, key)), key) + fn lookup_and_convert_bytes<'a, K>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: K) + -> Result<&'a [u8], Self::Error> where K: AsRef<[u8]> { + self.convert_bytes(try!(self.lookup(dictionary, &key)), &key) } /// Combines a lookup operation on the given key with a conversion of the value, if found, to a UTF-8 string. - fn lookup_and_convert_str<'a>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: &str) - -> Result<&'a str, Self::Error> { - self.convert_str(try!(self.lookup(dictionary, key)), key) + fn lookup_and_convert_str<'a, K>(&self, dictionary: &Dictionary<'a, Bencode<'a>>, key: K) + -> Result<&'a str, Self::Error> where K: AsRef<[u8]> { + self.convert_str(try!(self.lookup(dictionary, &key)), &key) } /// Combines a lookup operation on the given key with a conversion of the value, if found, to a list. - fn lookup_and_convert_list<'a: 'b, 'b>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: &str) - -> Result<&'b [Bencode<'a>], Self::Error> { - self.convert_list(try!(self.lookup(dictionary, key)), key) + fn lookup_and_convert_list<'a: 'b, 'b, K>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: K) + -> Result<&'b [Bencode<'a>], Self::Error> where K: AsRef<[u8]> { + self.convert_list(try!(self.lookup(dictionary, &key)), &key) } /// Combines a lookup operation on the given key with a conversion of the value, if found, to a dictionary. - fn lookup_and_convert_dict<'a: 'b, 'b>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: &str) - -> Result<&'b Dictionary<'a, Bencode<'a>>, Self::Error> { - self.convert_dict(try!(self.lookup(dictionary, key)), key) + fn lookup_and_convert_dict<'a: 'b, 'b, K>(&self, dictionary: &'b Dictionary<'a, Bencode<'a>>, key: K) + -> Result<&'b Dictionary<'a, Bencode<'a>>, Self::Error> where K: AsRef<[u8]> { + self.convert_dict(try!(self.lookup(dictionary, &key)), &key) } } diff --git a/bip_bencode/src/decode.rs b/bip_bencode/src/decode.rs index 1945862947..41cc01e76c 100644 --- a/bip_bencode/src/decode.rs +++ b/bip_bencode/src/decode.rs @@ -9,7 +9,7 @@ use error::{BencodeParseError, BencodeParseErrorKind, BencodeParseResult}; // underlying recursive type is a dictionary, it is a programming error otherwise) enum IBencodeType<'a> { Bencode(Bencode<'a>), - BencodeMapping(&'a str, Bencode<'a>) + BencodeMapping(&'a [u8], Bencode<'a>) } /// Decodes the given list of bytes at the given position into a bencoded structures. @@ -337,17 +337,10 @@ fn decode_bytes<'a>(bytes: &'a [u8], pos: usize) -> BencodeParseResult<(&'a [u8] } /// Returns the key reference as well as the starting byte of the next type. -fn decode_key<'a>(bytes: &'a [u8], pos: usize) -> BencodeParseResult<(&'a str, usize)> { +fn decode_key<'a>(bytes: &'a [u8], pos: usize) -> BencodeParseResult<(&'a [u8], usize)> { let (key_bytes, next_pos) = try!(decode_bytes(bytes, pos)); - let key = match str::from_utf8(key_bytes) { - Ok(n) => n, - Err(_) => { - return Err(BencodeParseError::with_pos(BencodeParseErrorKind::InvalidByte, - "Invalid UTF-8 Key Found For Dictionar", Some(next_pos))) - } - }; - Ok((key, next_pos)) + Ok((key_bytes, next_pos)) } fn peek_byte(bytes: &[u8], pos: usize, err_msg: &'static str) -> BencodeParseResult { @@ -388,12 +381,12 @@ mod tests { let bencode = Bencode::decode(GENERAL).unwrap(); let ben_dict = bencode.dict().unwrap(); - assert_eq!(ben_dict.lookup("").unwrap().str().unwrap(), "zero_len_key"); - assert_eq!(ben_dict.lookup("location").unwrap().str().unwrap(), "udp://test.com:80"); - assert_eq!(ben_dict.lookup("number").unwrap().int().unwrap(), 500500i64); + assert_eq!(ben_dict.lookup("".as_bytes()).unwrap().str().unwrap(), "zero_len_key"); + assert_eq!(ben_dict.lookup("location".as_bytes()).unwrap().str().unwrap(), "udp://test.com:80"); + assert_eq!(ben_dict.lookup("number".as_bytes()).unwrap().int().unwrap(), 500500i64); - let nested_dict = ben_dict.lookup("nested dict").unwrap().dict().unwrap(); - let nested_list = nested_dict.lookup("list").unwrap().list().unwrap(); + let nested_dict = ben_dict.lookup("nested dict".as_bytes()).unwrap().dict().unwrap(); + let nested_list = nested_dict.lookup("list".as_bytes()).unwrap().list().unwrap(); assert_eq!(nested_list[0].int().unwrap(), -500500i64); } @@ -415,12 +408,12 @@ mod tests { fn positive_decode_dict() { let bencode = Bencode::decode(DICTIONARY).unwrap(); let dict = bencode.dict().unwrap(); - assert_eq!(dict.lookup("test_key").unwrap().str().unwrap(), "test_value"); + assert_eq!(dict.lookup("test_key".as_bytes()).unwrap().str().unwrap(), "test_value"); - let nested_dict = dict.lookup("test_dict").unwrap().dict().unwrap(); - assert_eq!(nested_dict.lookup("nested_key").unwrap().str().unwrap(), "nested_value"); + let nested_dict = dict.lookup("test_dict".as_bytes()).unwrap().dict().unwrap(); + assert_eq!(nested_dict.lookup("nested_key".as_bytes()).unwrap().str().unwrap(), "nested_value"); - let nested_list = nested_dict.lookup("nested_list").unwrap().list().unwrap(); + let nested_list = nested_dict.lookup("nested_list".as_bytes()).unwrap().list().unwrap(); assert_eq!(nested_list[0].int().unwrap(), 500i64); assert_eq!(nested_list[1].int().unwrap(), -500i64); assert_eq!(nested_list[2].int().unwrap(), 0i64); @@ -440,7 +433,7 @@ mod tests { assert_eq!(nested_list[0].str().unwrap(), "nested_bytes"); let nested_dict = list[5].dict().unwrap(); - assert_eq!(nested_dict.lookup("test_key").unwrap().str().unwrap(), "test_value"); + assert_eq!(nested_dict.lookup("test_key".as_bytes()).unwrap().str().unwrap(), "test_value"); } #[test] diff --git a/bip_bencode/src/dictionary.rs b/bip_bencode/src/dictionary.rs index 0656b14ebe..626ad89934 100644 --- a/bip_bencode/src/dictionary.rs +++ b/bip_bencode/src/dictionary.rs @@ -3,39 +3,39 @@ use std::collections::{BTreeMap}; /// Trait for working with generic map data structures. pub trait Dictionary<'a, V> { /// Convert the dictionary to an unordered list of key/value pairs. - fn to_list(&self) -> Vec<(&'a str, &V)>; + fn to_list(&self) -> Vec<(&'a [u8], &V)>; /// Lookup a value in the dictionary. - fn lookup(&self, key: &str) -> Option<&V>; + fn lookup(&self, key: &[u8]) -> Option<&V>; /// Lookup a mutable value in the dictionary. - fn lookup_mut(&mut self, key: &str) -> Option<&mut V>; + fn lookup_mut(&mut self, key: &[u8]) -> Option<&mut V>; /// Insert a key/value pair into the dictionary. - fn insert(&mut self, key: &'a str, value: V) -> Option; + fn insert(&mut self, key: &'a [u8], value: V) -> Option; /// Remove a value from the dictionary and return it. - fn remove(&mut self, key: &str) -> Option; + fn remove(&mut self, key: &[u8]) -> Option; } -impl<'a, V> Dictionary<'a, V> for BTreeMap<&'a str, V> { - fn to_list(&self) -> Vec<(&'a str, &V)> { +impl<'a, V> Dictionary<'a, V> for BTreeMap<&'a [u8], V> { + fn to_list(&self) -> Vec<(&'a [u8], &V)> { self.iter().map(|(k, v)| (*k, v)).collect() } - fn lookup(&self, key: &str) -> Option<&V> { + fn lookup(&self, key: &[u8]) -> Option<&V> { self.get(key) } - fn lookup_mut(&mut self, key: &str) -> Option<&mut V> { + fn lookup_mut(&mut self, key: &[u8]) -> Option<&mut V> { self.get_mut(key) } - fn insert(&mut self, key: &'a str, value: V) -> Option { + fn insert(&mut self, key: &'a [u8], value: V) -> Option { self.insert(key, value) } - fn remove(&mut self, key: &str) -> Option { + fn remove(&mut self, key: &[u8]) -> Option { self.remove(key) } } \ No newline at end of file diff --git a/bip_bencode/src/encode.rs b/bip_bencode/src/encode.rs index 3ee8d1c1b8..bd0a120ac0 100644 --- a/bip_bencode/src/encode.rs +++ b/bip_bencode/src/encode.rs @@ -54,7 +54,7 @@ fn encode_dict<'a>(dict: &Dictionary<'a, Bencode<'a>>) -> Vec { bytes.push(::DICT_START); // Iterate And Dictionary Encode The (String, Bencode) Pairs for &(ref key, ref value) in sort_dict.iter() { - bytes.extend(encode_bytes(key.as_bytes())); + bytes.extend(encode_bytes(key)); bytes.extend(encode(*value)); } bytes.push(::BEN_END); diff --git a/bip_bencode/src/error.rs b/bip_bencode/src/error.rs index 52fc6295e3..4f3892081b 100644 --- a/bip_bencode/src/error.rs +++ b/bip_bencode/src/error.rs @@ -87,16 +87,16 @@ pub enum BencodeConvertErrorKind { pub struct BencodeConvertError { kind: BencodeConvertErrorKind, desc: &'static str, - key: Cow<'static, str> + key: Cow<'static, [u8]> } impl BencodeConvertError { pub fn new(kind: BencodeConvertErrorKind, desc: &'static str) -> BencodeConvertError { - BencodeConvertError::with_key(kind, desc, "") + BencodeConvertError::with_key(kind, desc, "".as_bytes()) } pub fn with_key(kind: BencodeConvertErrorKind, desc: &'static str, key: T) - -> BencodeConvertError where T: Into> { + -> BencodeConvertError where T: Into> { BencodeConvertError{ kind: kind, desc: desc, key: key.into() } } @@ -108,7 +108,7 @@ impl BencodeConvertError { self.desc } - pub fn key(&self) -> &str { + pub fn key(&self) -> &[u8] { &self.key } } @@ -119,7 +119,7 @@ impl Display for BencodeConvertError { try!(f.write_fmt(format_args!(", Description: {}", self.desc))); - try!(f.write_fmt(format_args!(", Key: {}", self.key))); + try!(f.write_fmt(format_args!(", Key: {:?}", self.key))); Ok(()) } diff --git a/bip_bencode/src/lib.rs b/bip_bencode/src/lib.rs index 0b68c2a99c..ba05399cc2 100644 --- a/bip_bencode/src/lib.rs +++ b/bip_bencode/src/lib.rs @@ -13,7 +13,7 @@ //! let data = b"d12:lucky_numberi7ee"; //! let bencode = Bencode::decode(data).unwrap(); //! -//! assert_eq!(7, bencode.dict().unwrap().lookup("lucky_number") +//! assert_eq!(7, bencode.dict().unwrap().lookup("lucky_number".as_bytes()) //! .unwrap().int().unwrap()); //! } //! ```