[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))
|
Ok((result, end_pos + 1))
|
||||||
},
|
},
|
||||||
BencodeType::Dict => {
|
BencodeType::Dict => {
|
||||||
let result = Self::dummy(to_decode)?;
|
let (result, end_pos) = Self::decode_dict(to_decode)?;
|
||||||
Ok((result, end_decoded))
|
Ok((result, end_pos + 1))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,8 +146,25 @@ impl Bencode {
|
|||||||
Ok((Bencode::List(result), decoded_pos))
|
Ok((Bencode::List(result), decoded_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dummy(_input: &[u8]) -> Result<Bencode> {
|
fn decode_dict(input: &[u8]) -> Result<(Bencode, usize)> {
|
||||||
Ok(Bencode::Integer(42))
|
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