pub trait Grab<'a>
where
Self: Sized + 'a,
{
fn grab_from(reader: &mut FrameReader<'a>) -> Option<Self>;
}
pub fn grab_from_buffer<'a, G: Grab<'a>>(buffer: &'a [u8]) -> Option<G> {
let mut reader = FrameReader::new(buffer);
G::grab_from(&mut reader)
}
#[derive(Debug)]
pub struct FrameReader<'a> {
idx: usize,
buf: &'a [u8],
}
impl<'a> FrameReader<'a> {
pub fn new(buf: &'a [u8]) -> FrameReader<'a> {
FrameReader { idx: 0, buf }
}
pub fn position(&self) -> usize {
self.idx
}
pub fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
let buf_len = self.buf.len();
if self.idx + len <= buf_len {
let idx = self.idx;
self.idx += len;
Some(&self.buf[idx..idx + len])
} else {
None
}
}
pub fn read_bytes_to(&mut self, buf: &mut [u8]) -> Option<()> {
let bytes = self.read_bytes(buf.len())?;
buf.copy_from_slice(bytes);
Some(())
}
pub fn read<G: Grab<'a>>(&mut self) -> Option<G> {
G::grab_from(self)
}
pub fn expect<G: Grab<'a> + PartialEq>(&mut self, expected: G) -> Option<()> {
let data: G = self.read()?;
if data == expected {
Some(())
} else {
None
}
}
pub fn with<T>(buf: &'a [u8], cb: impl FnOnce(&mut FrameReader<'a>) -> Option<T>) -> Option<T> {
let mut reader = FrameReader::new(buf);
cb(&mut reader)
}
}