1use num_bigint::BigInt;
2use std::{collections::BTreeMap, fmt::Debug};
3
4pub type BencodexDictionary = BTreeMap<BencodexKey, BencodexValue>;
17pub type BencodexList = Vec<BencodexValue>;
31
32pub const BENCODEX_NULL: BencodexValue = BencodexValue::Null;
42
43#[derive(PartialEq, Debug, Clone)]
44pub enum BencodexValue {
45 Binary(Vec<u8>),
46 Text(String),
47 Boolean(bool),
48 Number(BigInt),
49 List(BencodexList),
50 Dictionary(BencodexDictionary),
51 Null,
52}
53
54#[derive(PartialEq, Eq, Debug, PartialOrd, Clone, Ord)]
55pub enum BencodexKey {
56 Binary(Vec<u8>),
57 Text(String),
58}
59
60impl From<&str> for BencodexKey {
61 fn from(val: &str) -> Self {
62 BencodexKey::Text(val.to_string())
63 }
64}
65
66impl From<String> for BencodexKey {
67 fn from(val: String) -> Self {
68 BencodexKey::Text(val)
69 }
70}
71
72impl From<&String> for BencodexKey {
73 fn from(val: &String) -> Self {
74 BencodexKey::Text(val.clone())
75 }
76}
77
78impl From<Vec<u8>> for BencodexKey {
79 fn from(val: Vec<u8>) -> Self {
80 BencodexKey::Binary(val)
81 }
82}
83
84impl From<&Vec<u8>> for BencodexKey {
85 fn from(val: &Vec<u8>) -> Self {
86 BencodexKey::Binary(val.clone())
87 }
88}
89
90impl From<&[u8]> for BencodexKey {
91 fn from(val: &[u8]) -> Self {
92 BencodexKey::Binary(val.to_vec())
93 }
94}
95
96impl From<&[u8]> for BencodexValue {
97 fn from(val: &[u8]) -> Self {
98 BencodexValue::Binary(val.to_vec())
99 }
100}
101
102impl From<Vec<u8>> for BencodexValue {
103 fn from(val: Vec<u8>) -> Self {
104 BencodexValue::Binary(val)
105 }
106}
107
108impl From<&str> for BencodexValue {
109 fn from(val: &str) -> Self {
110 BencodexValue::Text(val.to_string())
111 }
112}
113
114impl From<String> for BencodexValue {
115 fn from(val: String) -> Self {
116 BencodexValue::Text(val)
117 }
118}
119
120macro_rules! bencodex_value_number_impl {
121 ($x:tt) => {
122 impl From<$x> for BencodexValue {
123 fn from(val: $x) -> Self {
124 BencodexValue::Number(val.into())
125 }
126 }
127 };
128}
129
130bencodex_value_number_impl!(u16);
131bencodex_value_number_impl!(u32);
132bencodex_value_number_impl!(u64);
133bencodex_value_number_impl!(i8);
134bencodex_value_number_impl!(i16);
135bencodex_value_number_impl!(i32);
136bencodex_value_number_impl!(i64);
137
138impl From<bool> for BencodexValue {
139 fn from(val: bool) -> Self {
140 BencodexValue::Boolean(val)
141 }
142}
143
144impl<T> From<Vec<T>> for BencodexValue
145where
146 T: Into<BencodexValue>,
147{
148 fn from(val: Vec<T>) -> Self {
149 let mut vec = Vec::new();
150 for v in val {
151 vec.push(v.into());
152 }
153
154 BencodexValue::List(vec)
155 }
156}
157
158impl<T, U> From<BTreeMap<T, U>> for BencodexValue
159where
160 T: Into<BencodexKey>,
161 U: Into<BencodexValue>,
162{
163 fn from(val: BTreeMap<T, U>) -> Self {
164 let mut map = BTreeMap::<BencodexKey, BencodexValue>::new();
165 for (key, value) in val {
166 map.insert(key.into(), value.into());
167 }
168
169 BencodexValue::Dictionary(map)
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 mod into {
176 use std::array::IntoIter;
177 use std::{collections::BTreeMap, iter::FromIterator};
178
179 use super::super::{BencodexKey, BencodexValue};
180
181 #[test]
182 fn text() {
183 let s: &str = "value";
184 let value: BencodexKey = s.into();
185 assert_eq!(value, BencodexKey::Text("value".to_string()));
186
187 let s: String = "value".to_string();
188 let value: BencodexKey = s.into();
189 assert_eq!(value, BencodexKey::Text("value".to_string()));
190
191 let s: &str = "value";
192 let value: BencodexValue = s.into();
193 assert_eq!(value, BencodexValue::Text("value".to_string()));
194
195 let s: String = "value".to_string();
196 let value: BencodexValue = s.into();
197 assert_eq!(value, BencodexValue::Text("value".to_string()));
198 }
199
200 #[test]
201 fn binary() {
202 let b: &[u8] = &[0, 1, 2, 3];
203 let value: BencodexKey = b.into();
204 assert_eq!(value, BencodexKey::Binary(vec![0, 1, 2, 3]));
205
206 let b: Vec<u8> = vec![0, 1, 2, 3];
207 let value: BencodexKey = b.into();
208 assert_eq!(value, BencodexKey::Binary(vec![0, 1, 2, 3]));
209
210 let b: &[u8] = &[0, 1, 2, 3];
211 let value: BencodexValue = b.into();
212 assert_eq!(value, BencodexValue::Binary(vec![0, 1, 2, 3]));
213
214 let b: Vec<u8> = vec![0, 1, 2, 3];
215 let value: BencodexValue = b.into();
216 assert_eq!(value, BencodexValue::Binary(vec![0, 1, 2, 3]));
217 }
218
219 #[test]
220 fn number() {
221 let n: u16 = 0;
222 let value: BencodexValue = n.into();
223 assert_eq!(value, BencodexValue::Number(0.into()));
224
225 let n: u32 = 0;
226 let value: BencodexValue = n.into();
227 assert_eq!(value, BencodexValue::Number(0.into()));
228
229 let n: u64 = 0;
230 let value: BencodexValue = n.into();
231 assert_eq!(value, BencodexValue::Number(0.into()));
232
233 let n: i8 = 0;
234 let value: BencodexValue = n.into();
235 assert_eq!(value, BencodexValue::Number(0.into()));
236
237 let n: i16 = 0;
238 let value: BencodexValue = n.into();
239 assert_eq!(value, BencodexValue::Number(0.into()));
240
241 let n: i32 = 0;
242 let value: BencodexValue = n.into();
243 assert_eq!(value, BencodexValue::Number(0.into()));
244
245 let n: i64 = 0;
246 let value: BencodexValue = n.into();
247 assert_eq!(value, BencodexValue::Number(0.into()));
248 }
249
250 #[test]
251 fn boolean() {
252 let value: BencodexValue = true.into();
253 assert_eq!(value, BencodexValue::Boolean(true));
254
255 let value: BencodexValue = false.into();
256 assert_eq!(value, BencodexValue::Boolean(false));
257 }
258
259 #[test]
260 fn null() {
261 let value: BencodexValue = BencodexValue::Null;
262 assert_eq!(value, BencodexValue::Null);
263 }
264
265 #[test]
266 fn list() {
267 let l = vec!["A", "B", "C", "D"];
268 let value: BencodexValue = l.into();
269 assert_eq!(
270 value,
271 BencodexValue::List(vec!["A".into(), "B".into(), "C".into(), "D".into()])
272 );
273
274 let l = vec![0, 1, 2, 3];
275 let value: BencodexValue = l.into();
276 assert_eq!(
277 value,
278 BencodexValue::List(vec![0.into(), 1.into(), 2.into(), 3.into()])
279 );
280
281 let l = vec![
282 BencodexValue::Null,
283 BencodexValue::Null,
284 BencodexValue::Null,
285 ];
286 let value: BencodexValue = l.into();
287 assert_eq!(
288 value,
289 BencodexValue::List(vec![
290 BencodexValue::Null,
291 BencodexValue::Null,
292 BencodexValue::Null
293 ])
294 );
295
296 let l: Vec<Vec<u8>> = vec![vec![0, 1, 2, 3], vec![4, 5, 6, 7]];
297 let value: BencodexValue = l.into();
298 assert_eq!(
299 value,
300 BencodexValue::List(vec![vec![0u8, 1, 2, 3].into(), vec![4u8, 5, 6, 7].into(),])
301 );
302 }
303
304 #[test]
305 fn dictionary() {
306 let mut map = BTreeMap::<String, &[u8]>::new();
307 map.insert("foo".to_string(), b"bar");
308 let actual: BencodexValue = map.into();
309
310 let expected = BencodexValue::Dictionary(BTreeMap::from_iter(IntoIter::new([(
311 BencodexKey::Text("foo".to_string()),
312 BencodexValue::Binary(vec![b'b', b'a', b'r']),
313 )])));
314
315 assert_eq!(actual, expected);
316 }
317 }
318}