rustybit_serde_bencode/
value.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::marker::PhantomData;
4
5use serde::{Deserialize, Deserializer, Serialize};
6
7#[derive(Debug, Deserialize, PartialEq, Eq, Hash)]
8pub struct Bytes<'a>(Cow<'a, [u8]>);
9
10impl<'a> Serialize for Bytes<'a> {
11    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12    where
13        S: serde::Serializer,
14    {
15        serializer.serialize_bytes(&self.0)
16    }
17}
18
19#[derive(Debug, Serialize, PartialEq, Eq)]
20#[serde(untagged)]
21pub enum BencodeValue<'a> {
22    Int(i64),
23    Bytes(Bytes<'a>),
24    List(Vec<BencodeValue<'a>>),
25    Dict(HashMap<Bytes<'a>, BencodeValue<'a>>),
26}
27
28impl<'a, 'de: 'a> serde::de::Deserialize<'de> for BencodeValue<'a> {
29    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30    where
31        D: Deserializer<'de>,
32    {
33        struct Visitor<'a> {
34            lifetime: PhantomData<BencodeValue<'a>>,
35        }
36
37        impl<'a, 'de: 'a> serde::de::Visitor<'de> for Visitor<'a> {
38            type Value = BencodeValue<'a>;
39
40            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
41                write!(formatter, "a valid bencode value")
42            }
43
44            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
45            where
46                E: serde::de::Error,
47            {
48                Ok(v.into())
49            }
50
51            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
52            where
53                A: serde::de::SeqAccess<'de>,
54            {
55                let mut v: Vec<BencodeValue<'a>> = Vec::new();
56                while let Some(value) = seq.next_element()? {
57                    v.push(value);
58                }
59                Ok(v.into())
60            }
61
62            fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
63            where
64                E: serde::de::Error,
65            {
66                Ok(v.into())
67            }
68
69            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
70            where
71                A: serde::de::MapAccess<'de>,
72            {
73                let mut hashmap = HashMap::new();
74                while let Some(key) = map.next_key::<&'de [u8]>()? {
75                    let value = map.next_value()?;
76                    hashmap.insert(Bytes(Cow::Borrowed(key)), value);
77                }
78                Ok(hashmap.into())
79            }
80        }
81
82        deserializer.deserialize_any(Visitor { lifetime: PhantomData })
83    }
84}
85
86impl From<i64> for BencodeValue<'_> {
87    fn from(value: i64) -> Self {
88        BencodeValue::Int(value)
89    }
90}
91
92impl<'a> From<&'a [u8]> for BencodeValue<'a> {
93    fn from(value: &'a [u8]) -> Self {
94        BencodeValue::Bytes(Bytes(Cow::Borrowed(value)))
95    }
96}
97
98impl From<String> for BencodeValue<'_> {
99    fn from(s: String) -> Self {
100        BencodeValue::Bytes(Bytes(Cow::Owned(s.into_bytes())))
101    }
102}
103
104impl<'a> From<&'a str> for BencodeValue<'a> {
105    fn from(v: &'a str) -> Self {
106        BencodeValue::Bytes(Bytes(Cow::Borrowed(v.as_bytes())))
107    }
108}
109
110impl From<Vec<u8>> for BencodeValue<'_> {
111    fn from(value: Vec<u8>) -> Self {
112        BencodeValue::Bytes(Bytes(Cow::Owned(value)))
113    }
114}
115
116impl<'a> From<Vec<BencodeValue<'a>>> for BencodeValue<'a> {
117    fn from(value: Vec<BencodeValue<'a>>) -> Self {
118        BencodeValue::List(value)
119    }
120}
121
122impl<'a> From<HashMap<Bytes<'a>, BencodeValue<'a>>> for BencodeValue<'a> {
123    fn from(value: HashMap<Bytes<'a>, BencodeValue<'a>>) -> Self {
124        BencodeValue::Dict(value)
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131    use crate::{from_str, to_string};
132
133    mod basic_types {
134        use super::*;
135
136        #[test]
137        fn can_roundtrip_int() {
138            let value: BencodeValue = 888i64.into();
139            let serialized = to_string(&value).expect("failed to serialize an integer");
140            assert_eq!(serialized, "i888e");
141            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize an integer");
142            assert_eq!(deserialized, value)
143        }
144
145        #[test]
146        fn can_roundtrip_negative_int() {
147            let value: BencodeValue = (-888i64).into();
148            let serialized = to_string(&value).expect("failed to serialize a neg integer");
149            assert_eq!(serialized, "i-888e");
150            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a neg integer");
151            assert_eq!(deserialized, value)
152        }
153
154        #[test]
155        fn can_roundtrip_bytes() {
156            let value: BencodeValue = "a nice value".into();
157            let serialized = to_string(&value).expect("failed to serialize a string");
158            assert_eq!(serialized, "12:a nice value");
159            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a string");
160            assert_eq!(deserialized, value)
161        }
162
163        #[test]
164        fn can_roundtrip_list_of_bytes() {
165            let list: Vec<BencodeValue> = vec!["a nice value".into(), "another".into()];
166            let value: BencodeValue = list.into();
167            let serialized = to_string(&value).expect("failed to serialize a list of bytes");
168            assert_eq!(serialized, "l12:a nice value7:anothere");
169            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a list of bytes");
170            assert_eq!(deserialized, value)
171        }
172
173        #[test]
174        fn can_roundtrip_list_of_ints() {
175            let list: Vec<BencodeValue> = vec![10i64.into(), 11i64.into()];
176            let value: BencodeValue = list.into();
177            let serialized = to_string(&value).expect("failed to serialize a list of ints");
178            assert_eq!(serialized, "li10ei11ee");
179            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a list of ints");
180            assert_eq!(deserialized, value)
181        }
182
183        #[test]
184        fn can_roundtrip_list_of_lists() {
185            let list: Vec<BencodeValue> = vec![
186                BencodeValue::List(vec!["bytes".into()]),
187                BencodeValue::List(vec![20i64.into()]),
188            ];
189            let value: BencodeValue = list.into();
190            let serialized = to_string(&value).expect("failed to serialize a list of lists");
191            assert_eq!(serialized, "ll5:byteseli20eee");
192            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a list of lists");
193            assert_eq!(deserialized, value)
194        }
195
196        #[test]
197        fn can_roundtrip_list_of_dicts() {
198            let dict_1 = HashMap::from([(Bytes(b"test".into()), BencodeValue::List(vec![21i64.into()]))]);
199            let dict_2 = HashMap::from([(Bytes(b"another".into()), BencodeValue::Dict(HashMap::new()))]);
200
201            let list: Vec<BencodeValue> = vec![dict_1.into(), dict_2.into()];
202            let value: BencodeValue = list.into();
203            let serialized = to_string(&value).expect("failed to serialize a list of dicts");
204            assert_eq!(serialized, "ld4:testli21eeed7:anotherdeee");
205            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a list of dicts");
206            assert_eq!(deserialized, value)
207        }
208
209        #[test]
210        fn can_roundtrip_dict_of_ints() {
211            let dict: HashMap<Bytes, BencodeValue> = HashMap::from([(Bytes(b"key1".into()), 4i64.into())]);
212            let value: BencodeValue = dict.into();
213            let serialized = to_string(&value).expect("failed to serialize a dict of ints");
214            assert_eq!(serialized, "d4:key1i4ee");
215            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a dict of ints");
216            assert_eq!(deserialized, value)
217        }
218
219        #[test]
220        fn can_roundtrip_dict_of_bytes() {
221            let dict: HashMap<Bytes, BencodeValue> = HashMap::from([(Bytes(b"key1".into()), "my value".into())]);
222            let value: BencodeValue = dict.into();
223            let serialized = to_string(&value).expect("failed to serialize a dict of bytes");
224            assert_eq!(serialized, "d4:key18:my valuee");
225            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a dict of bytes");
226            assert_eq!(deserialized, value)
227        }
228
229        #[test]
230        fn can_roundtrip_dict_of_lists() {
231            let dict: HashMap<Bytes, BencodeValue> =
232                HashMap::from([(Bytes(b"key1".into()), vec![BencodeValue::Dict(HashMap::new())].into())]);
233            let value: BencodeValue = dict.into();
234            let serialized = to_string(&value).expect("failed to serialize a dict of lists");
235            assert_eq!(serialized, "d4:key1ldeee");
236            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a dict of lists");
237            assert_eq!(deserialized, value)
238        }
239
240        #[test]
241        fn can_roundtrip_dict_of_dicts() {
242            let dict: HashMap<Bytes, BencodeValue> = HashMap::from([(
243                Bytes(b"key1".into()),
244                HashMap::from([(Bytes(b"inner".into()), BencodeValue::Dict(HashMap::new()))]).into(),
245            )]);
246            let value: BencodeValue = dict.into();
247            let serialized = to_string(&value).expect("failed to serialize a dict of dicts");
248            assert_eq!(serialized, "d4:key1d5:innerdeee");
249            let deserialized = from_str::<BencodeValue>(&serialized).expect("failed to deserialize a dict of dicts");
250            assert_eq!(deserialized, value)
251        }
252    }
253
254    mod option {
255        use super::*;
256
257        #[test]
258        fn can_roundtrip_some() {
259            let value: Option<i64> = Some(10);
260            let serialized = to_string(&value).expect("failed to serialize an Option::Some");
261            assert_eq!(serialized, "i10e");
262            let deserialized = from_str::<Option<i64>>(&serialized).expect("failed to deserialize an Option::Some");
263            assert_eq!(deserialized, value)
264        }
265
266        #[test]
267        fn can_roundtrip_none() {
268            let value: Option<i64> = None;
269            let serialized = to_string(&value).expect("failed to serialize an Option::None");
270            assert_eq!(serialized, "0:");
271            let deserialized = from_str::<Option<i64>>(&serialized).expect("failed to deserialize an Option::None");
272            assert_eq!(deserialized, value)
273        }
274    }
275
276    mod unit {
277        use super::*;
278
279        #[test]
280        fn can_roundtrip_unit() {
281            let value = ();
282            let serialized = to_string(&value).expect("failed to serialize the unit type");
283            assert_eq!(serialized, "0:");
284            let deserialized = from_str::<()>(&serialized).expect("failed to deserialize the unit type");
285            assert_eq!(deserialized, value)
286        }
287    }
288
289    mod _struct {
290        use super::*;
291
292        #[test]
293        fn can_roundtrip_unit_struct() {
294            #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
295            struct Test;
296
297            let value = Test;
298            let serialized = to_string(&value).expect("failed to serialize a unit struct");
299            assert_eq!(serialized, "0:");
300            let deserialized = from_str::<Test>(&serialized).expect("failed to deserialize a unit struct");
301            assert_eq!(deserialized, value)
302        }
303
304        #[test]
305        fn can_roundtrip_newtype_struct() {
306            #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
307            struct Test(i64);
308
309            let value = Test(11);
310            let serialized = to_string(&value).expect("failed to serialize a newtype struct");
311            assert_eq!(serialized, "i11e");
312            let deserialized = from_str::<Test>(&serialized).expect("failed to deserialize a newtype struct");
313            assert_eq!(deserialized, value)
314        }
315
316        #[test]
317        fn can_roundtrip_tuple_struct() {
318            #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
319            struct Test<'a>(i64, i64, &'a str);
320
321            let value = Test(10, 11, "hey!");
322            let serialized = to_string(&value).expect("failed to serialize a tuple struct");
323            assert_eq!(serialized, "li10ei11e4:hey!e");
324            let deserialized = from_str::<Test>(&serialized).expect("failed to deserialize a tuple struct");
325            assert_eq!(deserialized, value)
326        }
327
328        #[test]
329        fn can_roundtrip_struct() {
330            #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
331            struct Test<'a> {
332                field_1: &'a str,
333                field_2: i64,
334            }
335
336            let value = Test {
337                field_1: "test",
338                field_2: 555,
339            };
340            let serialized = to_string(&value).expect("failed to serialize a struct");
341            assert_eq!(serialized, "d7:field_14:test7:field_2i555ee");
342            let deserialized = from_str::<Test>(&serialized).expect("failed to deserialize a struct");
343            assert_eq!(deserialized, value)
344        }
345    }
346
347    mod _enum {
348        use super::*;
349
350        #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
351        enum Enumeration<'a> {
352            Unit,
353            NewType(i64),
354            Tuple(i64, i64, &'a str),
355            Struct { field: &'a str, integer: i64 },
356        }
357
358        #[test]
359        fn can_roundtrip_unit_variant() {
360            let value = Enumeration::Unit;
361            let serialized = to_string(&value).expect("failed to serialize a unit variant");
362            assert_eq!(serialized, "d4:Unit0:e");
363            let deserialized = from_str::<Enumeration>(&serialized).expect("failed to deserialize a unit variant");
364            assert_eq!(deserialized, value)
365        }
366
367        #[test]
368        fn can_roundtrip_newtype_variant() {
369            let value = Enumeration::NewType(15);
370            let serialized = to_string(&value).expect("failed to serialize a newtype variant");
371            assert_eq!(serialized, "d7:NewTypei15ee");
372            let deserialized = from_str::<Enumeration>(&serialized).expect("failed to deserialize a newtype variant");
373            assert_eq!(deserialized, value)
374        }
375
376        #[test]
377        fn can_roundtrip_tuple_variant() {
378            let value = Enumeration::Tuple(10, 12, "hi from enum");
379            let serialized = to_string(&value).expect("failed to serialize a tuple variant");
380            assert_eq!(serialized, "d5:Tupleli10ei12e12:hi from enumee");
381            let deserialized = from_str::<Enumeration>(&serialized).expect("failed to deserialize a tuple variant");
382            assert_eq!(deserialized, value)
383        }
384
385        #[test]
386        fn can_roundtrip_struct_variant() {
387            let value = Enumeration::Struct {
388                field: "hi from enum",
389                integer: 22,
390            };
391            let serialized = to_string(&value).expect("failed to serialize a struct variant");
392            assert_eq!(serialized, "d6:Structd5:field12:hi from enum7:integeri22eee");
393            let deserialized = from_str::<Enumeration>(&serialized).expect("failed to deserialize a struct variant");
394            assert_eq!(deserialized, value)
395        }
396    }
397}