bencodex/codec/
encode.rs

1use super::types::*;
2use itertools::Itertools;
3use num_bigint::BigInt;
4use std::cmp::Ordering;
5use std::collections::BTreeMap;
6use std::io;
7use std::result::Result;
8
9/// `Encode` is a trait to encode a [Bencodex] value.
10///
11/// [Bencodex]: https://bencodex.org/
12pub trait Encode {
13    /// Encode a [Bencodex] value from this type.
14    ///
15    /// If encoding succeeds, return [`Ok`]. Otherwise, it will pass [`std::io::Error`] occurred in inner logic.
16    ///
17    /// # Examples
18    /// Basic usage with [`BencodexValue::Text`]:
19    /// ```
20    /// use bencodex::{ Encode, BencodexValue };
21    ///
22    /// let text = "text".to_string();
23    /// let mut vec = Vec::new();
24    /// text.encode(&mut vec);
25    ///
26    /// assert_eq!(vec, vec![b'u', b'4', b':', b't', b'e', b'x', b't']);
27    /// ```
28    /// [Bencodex]: https://bencodex.org/
29    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error>;
30}
31
32impl Encode for Vec<u8> {
33    /// ```
34    /// use bencodex::{ Encode };
35    ///
36    /// let mut buf = vec![];
37    /// b"hello".to_vec().encode(&mut buf);
38    /// assert_eq!(buf, b"5:hello");
39    /// ```
40    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
41        write!(writer, "{}:", self.len())?;
42        writer.write_all(&self)?;
43
44        Ok(())
45    }
46}
47
48impl Encode for i64 {
49    /// ```
50    /// use bencodex::{ Encode };
51    ///
52    /// let mut buf = vec![];
53    /// 1004i64.encode(&mut buf);
54    /// assert_eq!(buf, b"i1004e");
55    /// ```
56    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
57        write!(writer, "i{}e", self)
58    }
59}
60
61impl Encode for String {
62    /// ```
63    /// use bencodex::{ Encode };
64    ///
65    /// let mut buf = vec![];
66    /// "foo".to_string().encode(&mut buf);
67    /// assert_eq!(buf, b"u3:foo");
68    /// ```
69    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
70        let bytes = self.into_bytes();
71        write!(writer, "u{}:", bytes.len())?;
72        writer.write_all(&bytes)?;
73
74        Ok(())
75    }
76}
77
78impl Encode for bool {
79    /// ```
80    /// use bencodex::{ Encode };
81    ///
82    /// let mut buf = vec![];
83    /// true.encode(&mut buf);
84    /// assert_eq!(buf, b"t");
85    /// ```
86    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
87        writer.write_all(match self {
88            true => &[b't'],
89            false => &[b'f'],
90        })?;
91
92        Ok(())
93    }
94}
95
96impl Encode for BigInt {
97    /// ```
98    /// use bencodex::{ Encode };
99    /// use num_bigint::BigInt;
100    ///
101    /// let mut buf = vec![];
102    /// BigInt::from(0).encode(&mut buf);
103    /// assert_eq!(buf, b"i0e");
104    /// ```
105    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
106        writer.write_all(&[b'i'])?;
107        writer.write_all(&self.to_str_radix(10).into_bytes())?;
108        writer.write_all(&[b'e'])?;
109
110        Ok(())
111    }
112}
113
114impl Encode for Vec<BencodexValue> {
115    /// ```
116    /// use bencodex::{ Encode, BencodexValue };
117    /// use num_bigint::BigInt;
118    ///
119    /// let list: Vec<BencodexValue> = vec![0.into(), BencodexValue::Null];
120    /// let mut buf = vec![];
121    /// list.encode(&mut buf);
122    /// assert_eq!(buf, b"li0ene");
123    /// ```
124    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
125        writer.write_all(&[b'l'])?;
126        for el in self {
127            el.encode(writer)?;
128        }
129        writer.write_all(&[b'e'])?;
130
131        Ok(())
132    }
133}
134
135fn encode_null(writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
136    writer.write_all(&[b'n'])?;
137
138    Ok(())
139}
140
141impl Encode for BencodexValue {
142    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
143        // FIXME: rewrite more beautiful.
144        match self {
145            BencodexValue::Binary(x) => x.encode(writer)?,
146            BencodexValue::Text(x) => x.encode(writer)?,
147            BencodexValue::Dictionary(x) => x.encode(writer)?,
148            BencodexValue::List(x) => x.encode(writer)?,
149            BencodexValue::Boolean(x) => x.encode(writer)?,
150            BencodexValue::Null => encode_null(writer)?,
151            BencodexValue::Number(x) => x.encode(writer)?,
152        }
153
154        Ok(())
155    }
156}
157
158fn compare_vector<T: Ord>(xs: &[T], ys: &[T]) -> Ordering {
159    for (x, y) in xs.iter().zip(ys) {
160        match x.cmp(y) {
161            Ordering::Equal => continue,
162            Ordering::Greater => return Ordering::Greater,
163            Ordering::Less => return Ordering::Less,
164        };
165    }
166
167    xs.len().cmp(&ys.len())
168}
169
170fn compare_key(x: &BencodexKey, y: &BencodexKey) -> Ordering {
171    match (x, y) {
172        (BencodexKey::Text(x), BencodexKey::Text(y)) => compare_vector(x.as_bytes(), y.as_bytes()),
173        (BencodexKey::Binary(x), BencodexKey::Binary(y)) => compare_vector(x, y),
174        (BencodexKey::Text(_), BencodexKey::Binary(_)) => Ordering::Greater,
175        (BencodexKey::Binary(_), BencodexKey::Text(_)) => Ordering::Less,
176    }
177}
178
179impl Encode for BTreeMap<BencodexKey, BencodexValue> {
180    /// ```
181    /// use bencodex::{ Encode, BencodexKey, BencodexValue };
182    /// use std::collections::BTreeMap;
183    ///
184    /// let mut dict: BTreeMap<BencodexKey, BencodexValue> = BTreeMap::new();
185    /// dict.insert("".into(), "".into());
186    ///
187    /// let mut buf = vec![];
188    /// dict.encode(&mut buf);
189    ///
190    /// assert_eq!(buf, b"du0:u0:e")
191    /// ```
192    fn encode(self, writer: &mut dyn io::Write) -> Result<(), std::io::Error> {
193        let pairs = self
194            .into_iter()
195            .sorted_by(|(x, _), (y, _)| compare_key(x, y));
196
197        writer.write_all(&[b'd'])?;
198        for (key, value) in pairs {
199            let key = match key {
200                BencodexKey::Binary(x) => BencodexValue::Binary(x),
201                BencodexKey::Text(x) => BencodexValue::Text(x),
202            };
203
204            key.encode(writer)?;
205            value.encode(writer)?;
206        }
207        writer.write_all(&[b'e'])?;
208
209        Ok(())
210    }
211}
212
213#[cfg(test)]
214mod tests {
215    mod compare_key {
216        use super::super::*;
217
218        #[test]
219        fn should_return_equal() {
220            assert_eq!(
221                Ordering::Equal,
222                compare_key(
223                    &BencodexKey::Text("foo".to_string()),
224                    &BencodexKey::Text("foo".to_string())
225                )
226            );
227            assert_eq!(
228                Ordering::Equal,
229                compare_key(
230                    &BencodexKey::Binary(b"bar".to_vec()),
231                    &BencodexKey::Binary(b"bar".to_vec())
232                )
233            );
234        }
235
236        #[test]
237        fn should_return_greater() {
238            assert_eq!(
239                Ordering::Greater,
240                compare_key(
241                    &BencodexKey::Text("".to_string()),
242                    &BencodexKey::Binary(b"".to_vec())
243                )
244            );
245        }
246
247        #[test]
248        fn should_return_less() {
249            assert_eq!(
250                Ordering::Less,
251                compare_key(
252                    &BencodexKey::Binary(b"".to_vec()),
253                    &BencodexKey::Text("".to_string())
254                )
255            );
256        }
257    }
258
259    mod compare_vector {
260        use super::super::*;
261
262        #[test]
263        fn should_return_equal() {
264            assert_eq!(
265                Ordering::Equal,
266                compare_vector(&Vec::<u8>::new(), &Vec::<u8>::new())
267            );
268            assert_eq!(
269                Ordering::Equal,
270                compare_vector(&vec![1, 2, 3], &vec![1, 2, 3])
271            );
272        }
273
274        #[test]
275        fn should_return_less() {
276            assert_eq!(Ordering::Less, compare_vector(&vec![], &vec![3]));
277            assert_eq!(Ordering::Less, compare_vector(&vec![0], &vec![1, 2, 3]));
278            assert_eq!(Ordering::Less, compare_vector(&vec![1], &vec![9, 1, 1]));
279            assert_eq!(Ordering::Less, compare_vector(&vec![1, 2], &vec![1, 2, 3]));
280            assert_eq!(
281                Ordering::Less,
282                compare_vector(&vec![1, 9, 9], &vec![9, 1, 1])
283            );
284        }
285
286        #[test]
287        fn should_return_greater() {
288            assert_eq!(Ordering::Greater, compare_vector(&vec![9], &vec![]));
289            assert_eq!(Ordering::Greater, compare_vector(&vec![9], &vec![1, 2, 3]));
290            assert_eq!(
291                Ordering::Greater,
292                compare_vector(&vec![1, 9, 2], &vec![1, 2, 2])
293            );
294        }
295    }
296
297    mod encode {
298        struct ConditionFailWriter {
299            throw_counts: Vec<u64>,
300            call_count: u64,
301        }
302
303        impl ConditionFailWriter {
304            fn new(throw_counts: Vec<u64>) -> ConditionFailWriter {
305                ConditionFailWriter {
306                    throw_counts: throw_counts,
307                    call_count: 0,
308                }
309            }
310        }
311
312        #[cfg(not(tarpaulin_include))]
313        impl std::io::Write for ConditionFailWriter {
314            fn write(&mut self, bytes: &[u8]) -> std::result::Result<usize, std::io::Error> {
315                self.call_count += 1;
316                if self.throw_counts.contains(&self.call_count) {
317                    Err(std::io::Error::new(std::io::ErrorKind::Other, ""))
318                } else {
319                    Ok(bytes.len())
320                }
321            }
322
323            fn write_all(&mut self, _: &[u8]) -> std::result::Result<(), std::io::Error> {
324                self.call_count += 1;
325                if self.throw_counts.contains(&self.call_count) {
326                    Err(std::io::Error::new(std::io::ErrorKind::Other, ""))
327                } else {
328                    Ok(())
329                }
330            }
331
332            fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
333                Ok(())
334            }
335        }
336
337        mod vec_u8 {
338            use super::super::super::*;
339            use super::*;
340
341            #[test]
342            fn should_pass_error() {
343                let bvalue = Vec::<u8>::new();
344
345                // write length
346                let mut writer = ConditionFailWriter::new(vec![1]);
347                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
348                assert_eq!(std::io::ErrorKind::Other, err.kind());
349                assert_eq!("", err.to_string());
350
351                // write 'e'
352                let mut writer = ConditionFailWriter::new(vec![2]);
353                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
354                assert_eq!(std::io::ErrorKind::Other, err.kind());
355                assert_eq!("", err.to_string());
356
357                // write bytes
358                let mut writer = ConditionFailWriter::new(vec![3]);
359                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
360                assert_eq!(std::io::ErrorKind::Other, err.kind());
361                assert_eq!("", err.to_string());
362            }
363        }
364
365        mod btree_map {
366            use super::super::super::*;
367            use super::*;
368
369            #[test]
370            fn should_order_keys() {
371                let mut bvalue: BTreeMap<BencodexKey, BencodexValue> = BTreeMap::new();
372                bvalue.insert(BencodexKey::Text("ua".to_string()), BencodexValue::Null);
373                bvalue.insert(BencodexKey::Binary(vec![b'a']), BencodexValue::Null);
374                bvalue.insert(BencodexKey::Text("ub".to_string()), BencodexValue::Null);
375                bvalue.insert(BencodexKey::Binary(vec![b'b']), BencodexValue::Null);
376
377                let mut writer = Vec::new();
378                assert!(bvalue.to_owned().encode(&mut writer).is_ok());
379                assert_eq!(b"d1:an1:bnu2:uanu2:ubne".to_vec(), writer);
380            }
381
382            #[test]
383            fn should_pass_error() {
384                let mut bvalue: BTreeMap<BencodexKey, BencodexValue> = BTreeMap::new();
385                bvalue.insert(BencodexKey::Text("".to_string()), BencodexValue::Null);
386
387                // write 'd'
388                let mut writer = ConditionFailWriter::new(vec![1]);
389                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
390                assert_eq!(std::io::ErrorKind::Other, err.kind());
391                assert_eq!("", err.to_string());
392
393                // write 'u' key prefix
394                let mut writer = ConditionFailWriter::new(vec![2]);
395                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
396                assert_eq!(std::io::ErrorKind::Other, err.kind());
397                assert_eq!("", err.to_string());
398
399                // write '{}' key bytes length
400                let mut writer = ConditionFailWriter::new(vec![3]);
401                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
402                assert_eq!(std::io::ErrorKind::Other, err.kind());
403                assert_eq!("", err.to_string());
404
405                // write ":" key delimeter
406                let mut writer = ConditionFailWriter::new(vec![4]);
407                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
408                assert_eq!(std::io::ErrorKind::Other, err.kind());
409                assert_eq!("", err.to_string());
410
411                // write "" key bytes
412                let mut writer = ConditionFailWriter::new(vec![5]);
413                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
414                assert_eq!(std::io::ErrorKind::Other, err.kind());
415                assert_eq!("", err.to_string());
416
417                // write value
418                let mut writer = ConditionFailWriter::new(vec![6]);
419                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
420                assert_eq!(std::io::ErrorKind::Other, err.kind());
421                assert_eq!("", err.to_string());
422
423                // write 'e'
424                let mut writer = ConditionFailWriter::new(vec![7]);
425                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
426                assert_eq!(std::io::ErrorKind::Other, err.kind());
427                assert_eq!("", err.to_string());
428            }
429        }
430
431        mod vec_bvalue {
432            use super::super::super::*;
433            use super::*;
434
435            #[test]
436            fn should_pass_error() {
437                let bvalue: &mut Vec<BencodexValue> = &mut Vec::new();
438                bvalue.push(BencodexValue::Null);
439
440                // write 'l'
441                let mut writer = ConditionFailWriter::new(vec![1]);
442                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
443                assert_eq!(std::io::ErrorKind::Other, err.kind());
444                assert_eq!("", err.to_string());
445
446                // write value
447                let mut writer = ConditionFailWriter::new(vec![2]);
448                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
449                assert_eq!(std::io::ErrorKind::Other, err.kind());
450                assert_eq!("", err.to_string());
451
452                // write 'e'
453                let mut writer = ConditionFailWriter::new(vec![3]);
454                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
455                assert_eq!(std::io::ErrorKind::Other, err.kind());
456                assert_eq!("", err.to_string());
457            }
458        }
459
460        mod string {
461            use super::super::super::*;
462            use super::*;
463
464            #[test]
465            fn should_pass_error() {
466                let bvalue: String = String::new();
467
468                // write 'u'
469                let mut writer = ConditionFailWriter::new(vec![1]);
470                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
471                assert_eq!(std::io::ErrorKind::Other, err.kind());
472                assert_eq!("", err.to_string());
473
474                // write length
475                let mut writer = ConditionFailWriter::new(vec![2]);
476                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
477                assert_eq!(std::io::ErrorKind::Other, err.kind());
478                assert_eq!("", err.to_string());
479
480                // write ':'
481                let mut writer = ConditionFailWriter::new(vec![3]);
482                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
483                assert_eq!(std::io::ErrorKind::Other, err.kind());
484                assert_eq!("", err.to_string());
485
486                // write text
487                let mut writer = ConditionFailWriter::new(vec![4]);
488                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
489                assert_eq!(std::io::ErrorKind::Other, err.kind());
490                assert_eq!("", err.to_string());
491            }
492        }
493
494        mod bool {
495            use super::super::super::*;
496            use super::*;
497
498            #[test]
499            fn should_pass_error() {
500                let bvalue = true;
501
502                // write 't'
503                let mut writer = ConditionFailWriter::new(vec![1]);
504                let err = bvalue.encode(&mut writer).unwrap_err();
505                assert_eq!(std::io::ErrorKind::Other, err.kind());
506                assert_eq!("", err.to_string());
507            }
508        }
509
510        mod big_int {
511            use super::super::super::*;
512            use super::*;
513
514            #[test]
515            fn should_pass_error() {
516                let bvalue = BigInt::from(0);
517
518                // write 'i'
519                let mut writer = ConditionFailWriter::new(vec![1]);
520                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
521                assert_eq!(std::io::ErrorKind::Other, err.kind());
522                assert_eq!("", err.to_string());
523
524                // write number
525                let mut writer = ConditionFailWriter::new(vec![2]);
526                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
527                assert_eq!(std::io::ErrorKind::Other, err.kind());
528                assert_eq!("", err.to_string());
529
530                // write 'e'
531                let mut writer = ConditionFailWriter::new(vec![3]);
532                let err = bvalue.to_owned().encode(&mut writer).unwrap_err();
533                assert_eq!(std::io::ErrorKind::Other, err.kind());
534                assert_eq!("", err.to_string());
535            }
536        }
537
538        mod i64 {
539            use super::super::super::*;
540            use super::*;
541
542            #[test]
543            fn should_pass_error() {
544                let bvalue: i64 = 0;
545                // write 'i'
546                let mut writer = ConditionFailWriter::new(vec![1]);
547                let err = bvalue.encode(&mut writer).unwrap_err();
548                assert_eq!(std::io::ErrorKind::Other, err.kind());
549                assert_eq!("", err.to_string());
550
551                // write number
552                let mut writer = ConditionFailWriter::new(vec![2]);
553                let err = bvalue.encode(&mut writer).unwrap_err();
554                assert_eq!(std::io::ErrorKind::Other, err.kind());
555                assert_eq!("", err.to_string());
556
557                // write 'e'
558                let mut writer = ConditionFailWriter::new(vec![3]);
559                let err = bvalue.encode(&mut writer).unwrap_err();
560                assert_eq!(std::io::ErrorKind::Other, err.kind());
561                assert_eq!("", err.to_string());
562            }
563        }
564    }
565}