pub trait Dump {
fn dump_to<T: FrameTarget>(&self, writer: &mut FrameWriter<T>);
fn size(&self) -> usize {
let mut writer = FrameWriter::new(());
self.dump_to(&mut writer);
writer.position()
}
}
pub fn dump_to_buffer<D: Dump>(data: &D, buffer: &mut [u8]) -> usize {
let mut writer = FrameWriter::new(buffer);
data.dump_to(&mut writer);
writer.position()
}
pub trait FrameTarget {
fn write_bytes_at(&mut self, pos: usize, bytes: &[u8]);
fn size(&self) -> usize;
}
impl FrameTarget for () {
#[inline(always)]
fn write_bytes_at(&mut self, _pos: usize, _bytes: &[u8]) {}
fn size(&self) -> usize {
usize::MAX
}
}
impl<'a> FrameTarget for &'a mut [u8] {
fn write_bytes_at(&mut self, pos: usize, bytes: &[u8]) {
let len = bytes.len();
self[pos..pos + len].copy_from_slice(bytes);
}
fn size(&self) -> usize {
self.len()
}
}
#[derive(Debug)]
pub struct FrameWriter<T: FrameTarget> {
idx: usize,
buf: T,
}
impl<T: FrameTarget> FrameWriter<T> {
pub fn new(buf: T) -> FrameWriter<T> {
FrameWriter { idx: 0, buf }
}
pub fn position(&self) -> usize {
self.idx
}
pub fn write_bytes(&mut self, bytes: &[u8]) {
self.buf.write_bytes_at(self.idx, bytes);
self.idx += bytes.len();
}
pub fn write<D: Dump>(&mut self, data: D) {
data.dump_to(self);
}
pub fn fits<D: Dump>(&mut self, data: D) -> bool {
let size = data.size();
dbg!(size);
dbg!(self.buf.size());
self.idx + size <= self.buf.size()
}
pub fn fits_bytes(&mut self, bytes: &[u8]) -> bool {
self.idx + bytes.len() <= self.buf.size()
}
pub fn with(buf: T, cb: impl FnOnce(&mut FrameWriter<T>)) {
let mut writer = FrameWriter::new(buf);
cb(&mut writer);
}
}
impl<'a> FrameWriter<&'a mut [u8]> {
pub fn as_bytes(&self) -> &[u8] {
&self.buf[..self.idx]
}
}