ecksport-codec 0.3.3

Utils for defining type encodings in the Ecksport RPC library
Documentation
use crate::errors::CodecError;
use crate::traits::RpcCodec;

pub struct Cursor<'b> {
    buf: &'b [u8],
    pos: usize,
}

impl<'b> Cursor<'b> {
    pub fn new(buf: &'b [u8]) -> Self {
        Self { buf, pos: 0 }
    }

    pub fn inner(&self) -> &'b [u8] {
        self.buf
    }

    pub fn ensure_space(&self, need: usize) -> Result<(), CodecError> {
        let min_len = self.pos + need;
        if self.buf.len() < min_len {
            Err(CodecError::InputTooShort)
        } else {
            Ok(())
        }
    }

    pub fn remaining_bytes(&self) -> usize {
        self.buf.len() - self.pos
    }

    pub fn is_at_end(&self) -> bool {
        self.remaining_bytes() == 0
    }

    pub fn take_buf(&mut self, need: usize) -> Result<&[u8], CodecError> {
        self.ensure_space(need)?;
        let start = self.pos;
        let end = self.pos + need;
        self.pos = end;
        Ok(&self.buf[start..end])
    }

    pub fn take_arr<const N: usize>(&mut self) -> Result<[u8; N], CodecError> {
        self.ensure_space(N)?;
        let start = self.pos;
        let end = self.pos + N;
        let mut dbuf = [0; N];
        dbuf.copy_from_slice(&self.buf[start..end]);
        self.pos = end;
        Ok(dbuf)
    }

    pub fn take_u32(&mut self) -> Result<u32, CodecError> {
        let src = self.take_arr::<4>()?;
        Ok(u32::from_be_bytes(src))
    }

    pub fn take_len_tagged_inst<T: RpcCodec>(&mut self) -> Result<T, CodecError> {
        let t_len = self.take_u32()?;
        let t_buf = self.take_buf(t_len as usize)?;
        Ok(T::from_slice(t_buf)?)
    }
}

pub fn write_u32(v: u32, buf: &mut Vec<u8>) {
    buf.extend_from_slice(&v.to_be_bytes());
}

pub fn write_u32_at(v: u32, pos: usize, buf: &mut Vec<u8>) {
    let min_len = pos + 4;
    if buf.len() < min_len {
        buf.resize(min_len, 0);
    }

    buf[pos..(pos + 4)].copy_from_slice(&v.to_be_bytes())
}

pub fn write_len_tagged_inst<T: RpcCodec>(t: &T, buf: &mut Vec<u8>) -> Result<(), CodecError> {
    let pos = buf.len();
    buf.extend_from_slice(&[0; 4]);
    t.fill_buf(buf)?;
    let t_len = (buf.len() - pos - 4) as u32; // TODO bounds checking
    write_u32_at(t_len, pos, buf);
    Ok(())
}

// TODO write tests