[bencode] Decode dicts
This commit is contained in:
parent
e2b2f8efca
commit
f9ed2388a2
122
src/bencode.rs
122
src/bencode.rs
@ -109,8 +109,8 @@ impl Bencode {
|
||||
Ok((result, end_pos + 1))
|
||||
},
|
||||
BencodeType::Dict => {
|
||||
let result = Self::dummy(to_decode)?;
|
||||
Ok((result, end_decoded))
|
||||
let (result, end_pos) = Self::decode_dict(to_decode)?;
|
||||
Ok((result, end_pos + 1))
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -146,8 +146,25 @@ impl Bencode {
|
||||
Ok((Bencode::List(result), decoded_pos))
|
||||
}
|
||||
|
||||
fn dummy(_input: &[u8]) -> Result<Bencode> {
|
||||
Ok(Bencode::Integer(42))
|
||||
fn decode_dict(input: &[u8]) -> Result<(Bencode, usize)> {
|
||||
let mut result = HashMap::new();
|
||||
let mut decoded_pos = 0;
|
||||
loop {
|
||||
if decoded_pos >= input.len() {
|
||||
return Err(anyhow!("Unfinished dict. Could not find terminating character 'e'"))
|
||||
}
|
||||
if input[decoded_pos] == 'e' as u8 {
|
||||
break;
|
||||
}
|
||||
let (Bencode::Bytes(key_result), end_pos) = Self::decode_type(&input[decoded_pos..])? else {
|
||||
return Err(anyhow!("Type of dictionary key not Bytes"))
|
||||
};
|
||||
decoded_pos += end_pos + 1;
|
||||
let (value_result, end_pos) = Self::decode_type(&input[decoded_pos..])?;
|
||||
result.insert(key_result, value_result);
|
||||
decoded_pos += end_pos + 1;
|
||||
}
|
||||
Ok((Bencode::Dict(result), decoded_pos))
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,6 +366,103 @@ 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"));
|
||||
assert_eq!(Bencode::decode(&str).unwrap(),
|
||||
Bencode::List(vec![
|
||||
Bencode::List(vec![
|
||||
Bencode::Bytes(ByteString::from_str("hallo")),
|
||||
Bencode::Integer(42),
|
||||
]),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Integer(23)),
|
||||
(ByteString::from_str("bar"), Bencode::Bytes(ByteString::from_str("baz"))),
|
||||
])),
|
||||
]),
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_dict() {
|
||||
assert_eq!(Bencode::decode_dict(
|
||||
("e").as_bytes()).unwrap(),
|
||||
(Bencode::Dict(HashMap::new()), 0)
|
||||
);
|
||||
let str = "3:fooi42ee";
|
||||
assert_eq!(Bencode::decode_dict(
|
||||
str.as_bytes()).unwrap(),
|
||||
(Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Integer(42)),
|
||||
])), str.len() - 1)
|
||||
);
|
||||
let str = "3:foo3:bare";
|
||||
assert_eq!(Bencode::decode_dict(
|
||||
str.as_bytes()).unwrap(),
|
||||
(Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Bytes(ByteString::from_str("bar"))),
|
||||
])), str.len() - 1)
|
||||
);
|
||||
let str = "3:fooi42e3:bar3:baze";
|
||||
assert_eq!(Bencode::decode_dict(
|
||||
str.as_bytes()).unwrap(),
|
||||
(Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Integer(42)),
|
||||
(ByteString::from_str("bar"), Bencode::Bytes(ByteString::from_str("baz"))),
|
||||
])), str.len() - 1)
|
||||
);
|
||||
let str = "3:fooli42ei17ee3:bar3:baze";
|
||||
assert_eq!(Bencode::decode_dict(
|
||||
str.as_bytes()).unwrap(),
|
||||
(Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::List(
|
||||
vec![Bencode::Integer(42), Bencode::Integer(17)])),
|
||||
(ByteString::from_str("bar"), Bencode::Bytes(ByteString::from_str("baz"))),
|
||||
])), str.len() - 1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dict_str() {
|
||||
assert_eq!(Bencode::decode("de").unwrap(),
|
||||
Bencode::Dict(HashMap::new())
|
||||
);
|
||||
let str = "d3:fooi42ee";
|
||||
assert_eq!(Bencode::decode(str).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Integer(42)),
|
||||
]))
|
||||
);
|
||||
let str = format!("d{}i42ee", test_encode_bytes("💩"));
|
||||
assert_eq!(Bencode::decode(str.as_str()).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("💩"), Bencode::Integer(42)),
|
||||
]))
|
||||
);
|
||||
let str = "d3:foo3:bare";
|
||||
assert_eq!(Bencode::decode(str).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Bytes(ByteString::from_str("bar"))),
|
||||
]))
|
||||
);
|
||||
let str = "d3:fooi42e3:bar3:baze";
|
||||
assert_eq!(Bencode::decode(str).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Integer(42)),
|
||||
(ByteString::from_str("bar"), Bencode::Bytes(ByteString::from_str("baz"))),
|
||||
]))
|
||||
);
|
||||
let str = "d3:fooli42ei17ee3:bar3:baze";
|
||||
assert_eq!(Bencode::decode(str).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::List(
|
||||
vec![Bencode::Integer(42), Bencode::Integer(17)])),
|
||||
(ByteString::from_str("bar"), Bencode::Bytes(ByteString::from_str("baz"))),
|
||||
]))
|
||||
);
|
||||
let str = "d3:foo3:bare";
|
||||
assert_eq!(Bencode::decode(str).unwrap(),
|
||||
Bencode::Dict(HashMap::from([
|
||||
(ByteString::from_str("foo"), Bencode::Bytes(ByteString::from_str("bar"))),
|
||||
]))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user