bencoderus/
libencode.rs

1pub use super::*;
2
3#[cfg(test)]
4mod tests {
5
6    use Bencoding;
7    use libencode::encode;
8    use libdecode::decode;
9    use std::collections::HashMap;
10
11    #[test]
12    fn test_run() {
13        assert!(true);
14    }
15
16    struct TestCase {
17        pub input: Vec<u8>,
18        pub expected: Bencoding,
19    }
20
21    #[test]
22    fn test_encode_number() {
23        let test_cases: Vec<TestCase> = vec![
24            TestCase{
25                input: vec![105, 49, 50, 51, 101],
26                expected: Bencoding::Integer(123) },
27            TestCase{
28                input: vec![105, 57, 56, 55, 101],
29                expected: Bencoding::Integer(987) },
30        ];
31
32        // Note that for the tests we're both decoding and encoding.
33        // Partly just because it was easier.
34        for t in test_cases {
35            println!("test number encode...");
36            let decode_input = t.input.clone();
37            let test_input = t.input.clone();
38            let benc = decode(decode_input);
39            let num = encode(benc);
40            println!("expect: {:?} ; got: {:?}", test_input, num);
41            assert!(test_input == num);
42        }
43    }
44
45    #[test]
46    fn test_encode_bytestring() {
47        let test_cases: Vec<TestCase> = vec![
48            TestCase{
49                input: vec![51, 58, 117, 118, 119], 
50                expected: Bencoding::ByteString("uvw".to_string().into_bytes())
51            },
52            TestCase{   
53                input: vec![51, 58, 120, 121, 122], 
54                expected: Bencoding::ByteString("xyz".to_string().into_bytes())
55            },
56        ];
57
58        // Note that for the tests we're both decoding and encoding.
59        // Partly just because it was easier.
60        for t in test_cases {
61            let decode_input = t.input.clone();
62            let test_input = t.input.clone();
63            let benc = decode(decode_input);
64            let str = encode(benc);
65            assert!(test_input == str);   
66        }
67    }
68
69    #[test]
70    fn test_encode_list() {
71        let test_cases: Vec<TestCase> = vec![
72            TestCase{
73                input: "l5:ItemA5:ItemBe".to_string().into_bytes(), 
74                expected: Bencoding::List( vec![
75                                    Bencoding::ByteString("ItemA".to_string().into_bytes()),
76                                    Bencoding::ByteString("ItemB".to_string().into_bytes())
77                                ])
78            },
79        ];
80
81        // Note that for the tests we're both decoding and encoding.
82        // Partly just because it was easier.
83        for t in test_cases {
84            let decode_input = t.input.clone();
85            let test_input = t.input.clone();
86            let benc = decode(decode_input);
87            let str = encode(benc);
88            assert!(test_input == str);
89        }
90    }
91
92    #[test]
93    fn test_encode_dictionary() {
94
95        let mut test_result: HashMap<Vec<u8>, Bencoding> = HashMap::new();
96        test_result.insert(
97            "announce".to_string().into_bytes(), 
98            Bencoding::ByteString("http://192.168.1.74:6969/announce".to_string().into_bytes()));
99        test_result.insert(
100            "comment".to_string().into_bytes(), 
101            Bencoding::ByteString("This is a comment".to_string().into_bytes()));
102        let test_cases: Vec<TestCase> = vec![
103            TestCase{
104                input: "d8:announce33:http://192.168.1.74:6969/announce7:comment17:This is a commente".to_string().into_bytes(),
105                expected: Bencoding::Dictionary(test_result)
106            },
107        ];
108
109        // Note that for the tests we're both decoding and encoding.
110        // Partly just because it was easier.
111        for t in test_cases {
112            let decode_input = t.input.clone();
113            let test_input = t.input.clone();
114            let benc = decode(decode_input);
115            let s = encode(benc);
116            assert!(test_input == s);
117        }
118
119    }
120}
121
122// encode transforms objects to Bencoded bytes.
123pub fn encode(benc: Bencoding) -> Vec<u8> {
124    let mut mem_stream = vec![];
125    encode_next(&mut mem_stream, benc);
126    mem_stream
127}
128
129fn encode_next(mem_stream: &mut Vec<u8>, obj: Bencoding) {
130    match obj {
131        Bencoding::Integer(ref v) => {
132            encode_number(mem_stream, Bencoding::Integer(*v))
133        }
134        Bencoding::ByteString(ref v) => {
135            let v_2 = v.clone();
136            encode_bytestring(mem_stream, Bencoding::ByteString(v_2))
137        }
138        Bencoding::List(ref v) => {
139            let v_2 = v.clone();
140            encode_list(mem_stream, Bencoding::List(v_2))
141        }
142        Bencoding::Dictionary(ref v) => {
143            let v_2 = v.clone();
144            encode_dictionary(mem_stream, Bencoding::Dictionary(v_2))
145        }
146        _ => {
147            println!("panic on obj: {:?}, unexpected type", obj);
148        }
149    };
150}
151
152fn encode_number(mem_stream: &mut Vec<u8>, num: Bencoding) {
153    mem_stream.push(NUMBER_START);
154    let mut val = match num {
155        Bencoding::Integer(ref v) => v.to_string().into_bytes(),
156        _ => panic!("unexpected type"),
157    };
158    mem_stream.append(&mut val);
159    mem_stream.push(NUMBER_END);
160}
161
162fn encode_bytestring(mem_stream: &mut Vec<u8>, benc_str: Bencoding) {
163    let mut str = match benc_str {
164        Bencoding::ByteString(v) => v,
165        _ => panic!("unexpected type"),
166    };
167    mem_stream.append(& mut str.len().to_string().into_bytes());
168    mem_stream.push(58);
169    mem_stream.append(&mut str);
170}
171
172// enocde_list converts a list (a vec) into bencoding formatted bytes and
173// writes them to the mem_stream, a mut vec<u8>.
174fn encode_list(mem_stream: &mut Vec<u8>, benc_list: Bencoding) {
175    mem_stream.push(LIST_START);
176    // eg. input: "l5:ItemA5:ItemBe"
177    let val = match benc_list {
178        Bencoding::List(ref v) => v, 
179        _ => panic!("unexpected type"),
180    };
181    for i in val {
182        let ii = i.clone();
183        encode_next(mem_stream, ii);
184    }
185    mem_stream.push(LIST_END);
186}
187
188fn encode_dictionary(mem_stream: &mut Vec<u8>, benc_dict: Bencoding) {
189    mem_stream.push(DICTIONARY_START);
190    // eg. input: d3:bar4:spam3:fooi42ee
191    let val = match benc_dict {
192        Bencoding::Dictionary(ref v) => v,
193        _ => panic!("unexpected type"),
194    };
195
196    let mut keys: Vec<Vec<u8>> = vec![];
197    
198    for key in val.keys() {
199        let key_2 = key.clone();
200        keys.push(key_2);
201    }
202    keys.sort();
203    for k in keys {
204        let kk = k.clone();
205
206        let vv = match val.get(&kk) {
207            Some(o) => o.clone(),
208            _ => panic!("no such key in dictionary"),
209        };
210
211        encode_next(mem_stream, Bencoding::ByteString(kk));
212        encode_next(mem_stream, vv);
213    }
214    mem_stream.push(DICTIONARY_END);
215}