bencode-minimal 0.1.0

A Bencode library depending only on the Rust standard library.
Documentation
use super::Value;
use std::borrow::Cow;
use std::collections::BTreeMap;

pub struct Encoder<'a> {
    buf: &'a mut Vec<u8>,
}

impl<'a> Encoder<'a> {
    pub fn new(buf: &'a mut Vec<u8>) -> Self {
        buf.clear();
        Self { buf }
    }

    pub fn clear(&mut self) {
        self.buf.clear();
    }

    pub fn int(&mut self, n: i64) {
        self.raw_u8(b'i');
        if n < 0 {
            self.raw_u8(b'-');
        }
        self.raw_u64(n.unsigned_abs());
        self.raw_u8(b'e');
    }

    pub fn str(&mut self, s: &[u8]) {
        self.raw_usize(s.len());
        self.raw_u8(b':');
        self.raw_slice(s);
    }

    pub fn list(&mut self, l: &[Value<'_>]) {
        self.raw_u8(b'l');
        for v in l {
            self.value(v);
        }
        self.raw_u8(b'e');
    }

    pub fn dict(&mut self, d: &BTreeMap<Cow<'_, [u8]>, Value<'_>>) {
        self.raw_u8(b'd');
        for (k, v) in d {
            self.str(k);
            self.value(v);
        }
        self.raw_u8(b'e');
    }

    pub fn value(&mut self, v: &Value<'_>) {
        match v {
            Value::Int(i) => self.int(*i),
            Value::Str(s) => self.str(s),
            Value::List(l) => self.list(l),
            Value::Dict(d) => self.dict(d),
        }
    }

    pub fn raw_u8(&mut self, n: u8) {
        self.buf.push(n);
    }

    pub fn raw_u64(&mut self, n: u64) {
        let len = n.checked_ilog10().map(|i| i + 1).unwrap_or(1) as usize;
        let buf = self.alloc(len);
        let mut n = n;
        for b in buf.iter_mut().rev() {
            *b = b'0' + (n % 10) as u8;
            n /= 10;
        }
    }

    pub fn raw_usize(&mut self, n: usize) {
        let len = n.checked_ilog10().map(|i| i + 1).unwrap_or(1) as usize;
        let buf = self.alloc(len);
        let mut n = n;
        for b in buf.iter_mut().rev() {
            *b = b'0' + (n % 10) as u8;
            n /= 10;
        }
    }

    pub fn raw_slice(&mut self, data: &[u8]) {
        self.buf.extend(data);
    }

    pub fn alloc(&mut self, len: usize) -> &mut [u8] {
        let start = self.buf.len();
        self.buf.resize(start + len, 0);
        &mut self.buf[start..start + len]
    }
}