diff --git a/src/bencode.rs b/src/bencode.rs index fa39df9..6ab6b4b 100644 --- a/src/bencode.rs +++ b/src/bencode.rs @@ -22,7 +22,7 @@ struct Torrent { extra: HashMap }*/ -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash, Clone)] pub struct ByteString(Vec); impl Display for ByteString { @@ -85,6 +85,30 @@ impl Display for Bencode { } impl Bencode { + + pub fn encode(input: &Self) -> Vec { + match input { + Bencode::Integer(i) => {format!("i{}e", i).as_bytes().to_vec()} + Bencode::Bytes(b) => {[format!("{}:", b.0.len()).as_bytes(), &b.0[..]].concat()} + Bencode::List(l) => { + let mut result = vec!['l' as u8]; + for item in l { + result.extend(Self::encode(item)) + } + result.push('e' as u8); + result + } + Bencode::Dict(d) => { + let mut result = vec!['d' as u8]; + for (k, v) in d { + result.extend(Self::encode(&Bencode::Bytes(k.clone()))); + result.extend(Self::encode(v)); + } + result.push('e' as u8); + result + } + } + } pub fn decode(input: &[u8]) -> Result { let (result, end_pos) = Self::decode_type(input)?; ensure!(end_pos == input.len() - 1, @@ -206,6 +230,28 @@ impl Bencode { mod tests { use super::*; + #[test] + fn test_encode_int() { + assert_eq!(Bencode::encode(&Bencode::Integer(42)), "i42e".as_bytes()); + assert_eq!(Bencode::encode(&Bencode::Integer(17)), "i17e".as_bytes()); + } + + #[test] + fn test_encode_bytes() { + assert_eq!(Bencode::encode(&Bencode::Bytes(ByteString::from_str("foo"))), "3:foo".as_bytes()); + assert_eq!(Bencode::encode(&Bencode::Bytes(ByteString::from_str("bar"))), "3:bar".as_bytes()); + } + + #[test] + fn test_encode_list() { + assert_eq!(Bencode::encode(&Bencode::List(vec![Bencode::Bytes(ByteString::from_str("foo")), Bencode::Integer(42)])), "l3:fooi42ee".as_bytes()); + } + + #[test] + fn test_encode_dict() { + assert_eq!(Bencode::encode(&Bencode::Dict(HashMap::from([(ByteString::from_str("foo"), Bencode::Integer(42))]))), "d3:fooi42ee".as_bytes()); + } + #[test] fn test_integer_only() { assert_eq!(Bencode::decode_int_only("42".as_bytes()).unwrap(), 42); @@ -234,16 +280,16 @@ mod tests { assert_eq!(Bencode::decode_bytes("💩".as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("💩"))); } - fn test_encode_bytes(input: &str) -> String { + fn util_encode_bytes(input: &str) -> String { format!("{}:{input}", input.len()) } #[test] fn test_bytes_str() { - assert_eq!(Bencode::decode(test_encode_bytes("hallo").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("hallo"))); - assert_eq!(Bencode::decode(test_encode_bytes("tschüss").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("tschüss"))); - assert_eq!(Bencode::decode(test_encode_bytes("💩").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("💩"))); - assert_eq!(Bencode::decode(test_encode_bytes("hallo 💩, this is a long text").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("hallo 💩, this is a long text"))); + assert_eq!(Bencode::decode(util_encode_bytes("hallo").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("hallo"))); + assert_eq!(Bencode::decode(util_encode_bytes("tschüss").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("tschüss"))); + assert_eq!(Bencode::decode(util_encode_bytes("💩").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("💩"))); + assert_eq!(Bencode::decode(util_encode_bytes("hallo 💩, this is a long text").as_bytes()).unwrap(), Bencode::Bytes(ByteString::from_str("hallo 💩, this is a long text"))); } #[test] @@ -262,7 +308,7 @@ mod tests { str.len() - 1, ) ); - let str = format!("{}e", test_encode_bytes("hallo")); + let str = format!("{}e", util_encode_bytes("hallo")); assert_eq!(Bencode::decode_list( str.as_bytes()).unwrap(), ( @@ -272,7 +318,7 @@ mod tests { str.len() - 1, ) ); - let str = format!("{}{}e", test_encode_bytes("hallo"), "i42e"); + let str = format!("{}{}e", util_encode_bytes("hallo"), "i42e"); assert_eq!(Bencode::decode_list( str.as_bytes()).unwrap(), ( @@ -283,7 +329,7 @@ mod tests { str.len() - 1, ) ); - let str = format!("{}{}{}{}e", "i-17e", test_encode_bytes("hallo"), "i42e", test_encode_bytes("tschüssi💩")); + let str = format!("{}{}{}{}e", "i-17e", util_encode_bytes("hallo"), "i42e", util_encode_bytes("tschüssi💩")); assert_eq!(Bencode::decode_list( str.as_bytes()).unwrap(), ( @@ -308,7 +354,7 @@ mod tests { ]), 4) ); - let str = format!("l{}{}ee", test_encode_bytes("hallo"), "i42e"); + let str = format!("l{}{}ee", util_encode_bytes("hallo"), "i42e"); assert_eq!(Bencode::decode_list( str.as_bytes()).unwrap(), (Bencode::List(vec![ @@ -319,7 +365,7 @@ mod tests { ]), str.len() - 1) ); - let str = format!("l{}{}el{}{}{}ee", test_encode_bytes("hallo"), "i42e", "i17e", test_encode_bytes("tschüss💩"), "i33e"); + let str = format!("l{}{}el{}{}{}ee", util_encode_bytes("hallo"), "i42e", "i17e", util_encode_bytes("tschüss💩"), "i33e"); assert_eq!(Bencode::decode_list( str.as_bytes()).unwrap(), (Bencode::List(vec![ @@ -350,20 +396,20 @@ mod tests { ]) ); assert_eq!(Bencode::decode( - (format!("l{}e", test_encode_bytes("hallo"))).as_bytes()).unwrap(), + (format!("l{}e", util_encode_bytes("hallo"))).as_bytes()).unwrap(), Bencode::List(vec![ Bencode::Bytes(ByteString::from_str("hallo")), ]) ); assert_eq!(Bencode::decode( - (format!("l{}{}e", test_encode_bytes("hallo"), "i42e")).as_bytes()).unwrap(), + (format!("l{}{}e", util_encode_bytes("hallo"), "i42e")).as_bytes()).unwrap(), Bencode::List(vec![ Bencode::Bytes(ByteString::from_str("hallo")), Bencode::Integer(42), ]) ); assert_eq!(Bencode::decode( - (format!("l{}{}{}{}e", "i-17e", test_encode_bytes("hallo"), "i42e", test_encode_bytes("tschüssi💩"))).as_bytes()).unwrap(), + (format!("l{}{}{}{}e", "i-17e", util_encode_bytes("hallo"), "i42e", util_encode_bytes("tschüssi💩"))).as_bytes()).unwrap(), Bencode::List(vec![ Bencode::Integer(-17), Bencode::Bytes(ByteString::from_str("hallo")), @@ -377,7 +423,7 @@ mod tests { Bencode::List(Vec::new()), ]), ); - let str = format!("ll{}{}ee", test_encode_bytes("hallo"), "i42e"); + let str = format!("ll{}{}ee", util_encode_bytes("hallo"), "i42e"); assert_eq!(Bencode::decode(str.as_bytes()).unwrap(), Bencode::List(vec![ Bencode::List(vec![ @@ -386,7 +432,7 @@ mod tests { ]), ]), ); - let str = format!("ll{}{}el{}{}{}ee", test_encode_bytes("hallo"), "i42e", "i17e", test_encode_bytes("tschüss💩"), "i33e"); + let str = format!("ll{}{}el{}{}{}ee", util_encode_bytes("hallo"), "i42e", "i17e", util_encode_bytes("tschüss💩"), "i33e"); assert_eq!(Bencode::decode(str.as_bytes()).unwrap(), Bencode::List(vec![ Bencode::List(vec![ @@ -400,7 +446,7 @@ mod tests { ]), ]), ); - let str = format!("ll{}{}ed{}{}{}{}ee", test_encode_bytes("hallo"), "i42e", test_encode_bytes("foo"), "i23e", test_encode_bytes("bar"), test_encode_bytes("baz")); + let str = format!("ll{}{}ed{}{}{}{}ee", util_encode_bytes("hallo"), "i42e", util_encode_bytes("foo"), "i23e", util_encode_bytes("bar"), util_encode_bytes("baz")); assert_eq!(Bencode::decode(str.as_bytes()).unwrap(), Bencode::List(vec![ Bencode::List(vec![ @@ -464,7 +510,7 @@ mod tests { (ByteString::from_str("foo"), Bencode::Integer(42)), ])) ); - let str = format!("d{}i42ee", test_encode_bytes("💩")); + let str = format!("d{}i42ee", util_encode_bytes("💩")); assert_eq!(Bencode::decode(str.as_bytes()).unwrap(), Bencode::Dict(HashMap::from([ (ByteString::from_str("💩"), Bencode::Integer(42)),