1mod parsing;
2
3use parsing::{next_nested, next_outer, Res, Value as ParseValue};
4use std::{error::Error, fmt::Display};
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub enum Value {
8 Integer(i64),
9 ByteString(Vec<u8>),
10 List(Vec<Value>),
11 Dictionary(Vec<(Value, Value)>),
12}
13
14pub fn parse_all(bytes: &[u8]) -> Result<Vec<Value>, ParseError> {
15 let (_, out) = parse_many(bytes, next_outer)?;
16 Ok(out)
17}
18
19fn parse_many(
20 mut bytes: &[u8],
21 f: fn(&[u8]) -> Res<Option<ParseValue>>,
22) -> Result<(&[u8], Vec<Value>), ParseError> {
23 let mut out = vec![];
24 loop {
25 let (i, maybe_value) = parse_one(bytes, f)?;
26 bytes = i;
27 match maybe_value {
28 Some(value) => out.push(value),
29 None => break,
30 }
31 }
32 Ok((bytes, out))
33}
34
35#[allow(clippy::type_complexity)]
36fn parse_dictionary(mut bytes: &[u8]) -> Result<(&[u8], Vec<(Value, Value)>), ParseError> {
37 let mut out = vec![];
38 loop {
39 let (i, k) = parse_one(bytes, next_nested)?;
40 bytes = i;
41 let Some(k) = k else { break };
42 let (i, v) = parse_one(bytes, next_nested)?;
43 bytes = i;
44 let Some(v) = v else { return Err(ParseError) };
45 out.push((k, v));
46 }
47 Ok((bytes, out))
48}
49
50fn parse_one(
51 bytes: &[u8],
52 f: fn(&[u8]) -> Res<Option<ParseValue>>,
53) -> Result<(&[u8], Option<Value>), ParseError> {
54 Ok(match f(bytes) {
55 Ok((i, None)) => (i, None),
56 Ok((i, Some(ParseValue::Integer(int)))) => (i, Some(Value::Integer(int))),
57 Ok((i, Some(ParseValue::ByteString(s)))) => (i, Some(Value::ByteString(s.to_vec()))),
58 Ok((i, Some(ParseValue::List))) => {
59 let (i, list) = parse_many(i, next_nested)?;
60 (i, Some(Value::List(list)))
61 }
62 Ok((i, Some(ParseValue::Dictionary))) => {
63 let (i, dictionary) = parse_dictionary(i)?;
64 (i, Some(Value::Dictionary(dictionary)))
65 }
66 Err(e) => {
67 println!("{e:?}");
68 return Err(ParseError);
69 }
70 })
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
74pub struct ParseError;
75
76impl Display for ParseError {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "Invalid bencode")
79 }
80}
81
82impl Error for ParseError {}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn valid_int() {
90 assert_eq!(
91 parse_all(b"i115ei-12e"),
92 Ok(vec![Value::Integer(115), Value::Integer(-12)])
93 );
94 }
95
96 #[test]
97 fn valid_list() {
98 assert_eq!(
99 parse_all(b"li115ei-12ee"),
100 Ok(vec![Value::List(vec![
101 Value::Integer(115),
102 Value::Integer(-12)
103 ])])
104 )
105 }
106
107 #[test]
108 fn valid_dictionary() {
109 assert_eq!(
110 parse_all(b"di1ei2ee"),
111 Ok(vec![Value::Dictionary(vec![(
112 Value::Integer(1),
113 Value::Integer(2),
114 )])])
115 )
116 }
117
118 #[test]
119 fn complex_value() {
120 assert_eq!(
121 parse_all(b"i1eli2el3:foo3:bared3:bazi3el7:listkeye5:valueee"),
122 Ok(vec![
123 Value::Integer(1),
124 Value::List(vec![
125 Value::Integer(2),
126 Value::List(vec![
127 Value::ByteString(b"foo".to_vec()),
128 Value::ByteString(b"bar".to_vec()),
129 ]),
130 Value::Dictionary(vec![
131 (Value::ByteString(b"baz".to_vec()), Value::Integer(3)),
132 (
133 Value::List(vec![Value::ByteString(b"listkey".to_vec())]),
134 Value::ByteString(b"value".to_vec())
135 )
136 ])
137 ])
138 ])
139 )
140 }
141}