benko/
encode.rs

1//! The implementations for the EncodeBencode trait. Which allow a Benc enum to be encoded back
2//! into an array of ascii bytes.
3use crate::parse::ParseBenc;
4use crate::{BInt, BMap, BStr, BVec};
5
6/// Any type that implements the ParseBenc can also by design be converted back into a bencoded
7/// byte array.
8pub trait EncodeBencode<T: ParseBenc<T>> {
9    /// Parses the Bencode typed object back into a bencoded array of bytes.
10    ///
11    /// This function won't fail. If a type implements [ParseBenc] it will have come from bencode
12    /// already.
13    fn bytes(&self) -> Vec<u8>;
14}
15
16impl EncodeBencode<BInt> for BInt {
17    fn bytes(&self) -> Vec<u8> {
18        let mut bytes: Vec<u8> = Vec::new();
19        bytes.push('i' as u8);
20        bytes.append(&mut self.to_string().as_bytes().to_vec());
21        bytes.push('e' as u8);
22        bytes
23    }
24}
25impl EncodeBencode<BStr> for BStr {
26    fn bytes(&self) -> Vec<u8> {
27        let mut bytes: Vec<u8> = Vec::new();
28        bytes.append(&mut self.len().to_string().as_bytes().to_vec());
29        bytes.push(':' as u8);
30        bytes.append(&mut self.clone());
31        bytes
32    }
33}
34impl EncodeBencode<BVec> for BVec {
35    fn bytes(&self) -> Vec<u8> {
36        let mut bytes: Vec<u8> = Vec::new();
37        bytes.push('l' as u8);
38        self.into_iter().for_each(|e| bytes.append(&mut e.bytes()));
39        bytes.push('e' as u8);
40        bytes
41    }
42}
43impl EncodeBencode<BMap> for BMap {
44    fn bytes(&self) -> Vec<u8> {
45        let mut bytes: Vec<u8> = Vec::new();
46        bytes.push('d' as u8);
47        self.items().into_iter().for_each(|(k, v)| {
48            bytes.append(&mut k.bytes());
49            bytes.append(&mut v.bytes());
50        });
51        bytes.push('e' as u8);
52        bytes
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::Benc;
60
61    #[test]
62    fn test_encode_bint() {
63        assert_eq!(b"i10e".to_vec(), (10 as BInt).bytes());
64        assert_eq!(b"i0e".to_vec(), (0 as BInt).bytes());
65        assert_eq!(b"i12345e".to_vec(), (12345 as BInt).bytes());
66    }
67
68    #[test]
69    fn test_encode_bstr() {
70        assert_eq!(vec![51, 58, 1, 2, 3], (vec![1 as u8, 2, 3] as BStr).bytes());
71        assert_eq!(b"3:foo".to_vec(), (b"foo".to_vec() as BStr).bytes());
72        assert_eq!(b"0:".to_vec(), (b"".to_vec() as BStr).bytes());
73        assert_eq!(
74            b"10:abcdefghij".to_vec(),
75            (b"abcdefghij".to_vec() as BStr).bytes()
76        );
77    }
78
79    #[test]
80    fn test_encode_bvec() {
81        assert_eq!(b"li10ee".to_vec(), (vec![Benc::Int(10)] as BVec).bytes());
82        assert_eq!(
83            b"li1ei2ei3ei4ei5ee".to_vec(),
84            (vec![
85                Benc::Int(1),
86                Benc::Int(2),
87                Benc::Int(3),
88                Benc::Int(4),
89                Benc::Int(5),
90            ] as BVec)
91                .bytes()
92        );
93        assert_eq!(
94            b"li1e3:foo3:bari5ee".to_vec(),
95            (vec![
96                Benc::Int(1),
97                Benc::Str(b"foo".to_vec()),
98                Benc::Str(b"bar".to_vec()),
99                Benc::Int(5),
100            ] as BVec)
101                .bytes()
102        );
103        assert_eq!(b"le".to_vec(), (vec!() as BVec).bytes());
104    }
105
106    #[test]
107    fn test_encode_bmap() {
108        let mut bmap = BMap::new();
109        assert_eq!(b"de".to_vec(), bmap.bytes());
110        bmap.insert(b"foo".to_vec(), Benc::Int(10));
111        assert_eq!(b"d3:fooi10ee".to_vec(), bmap.bytes());
112        bmap.insert(b"bar".to_vec(), Benc::Int(20));
113        // note that it should be sorting so that bar is before foo, even though foo was inserted
114        // first.
115        assert_eq!(b"d3:bari20e3:fooi10ee".to_vec(), bmap.bytes());
116
117        let mut sorted = BMap::new();
118        sorted.insert(b"a".to_vec(), Benc::Int(1));
119        sorted.insert(b"b".to_vec(), Benc::Int(2));
120        assert_eq!(b"d1:ai1e1:bi2ee".to_vec(), sorted.bytes());
121    }
122}