#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CursorBuffer {
data: Vec<u8>,
cursor: usize,
}
impl CursorBuffer {
pub fn new(data: Vec<u8>) -> Self {
CursorBuffer { data, cursor: 0 }
}
pub fn empty() -> Self {
CursorBuffer::new(vec![])
}
pub fn remaining(&self) -> usize {
self.data.len().saturating_sub(self.cursor)
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_done(&self) -> bool {
self.cursor >= self.data.len()
}
pub fn read_bytes(&mut self, n: usize) -> Option<&[u8]> {
if self.cursor + n > self.data.len() {
return None;
}
let slice = &self.data[self.cursor..self.cursor + n];
self.cursor += n;
Some(slice)
}
pub fn read_u8(&mut self) -> Option<u8> {
self.read_bytes(1).map(|b| b[0])
}
pub fn read_u16_le(&mut self) -> Option<u16> {
let b = self.read_bytes(2)?;
Some(u16::from_le_bytes([b[0], b[1]]))
}
pub fn read_u32_le(&mut self) -> Option<u32> {
let b = self.read_bytes(4)?;
Some(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
}
pub fn peek_u8(&self) -> Option<u8> {
self.data.get(self.cursor).copied()
}
pub fn rewind(&mut self) {
self.cursor = 0;
}
pub fn position(&self) -> usize {
self.cursor
}
pub fn append(&mut self, bytes: &[u8]) {
self.data.extend_from_slice(bytes);
}
}
pub fn new_cursor_buffer(data: Vec<u8>) -> CursorBuffer {
CursorBuffer::new(data)
}
pub fn cb_read_bytes(buf: &mut CursorBuffer, n: usize) -> Option<Vec<u8>> {
buf.read_bytes(n).map(|s| s.to_vec())
}
pub fn cb_read_u8(buf: &mut CursorBuffer) -> Option<u8> {
buf.read_u8()
}
pub fn cb_remaining(buf: &CursorBuffer) -> usize {
buf.remaining()
}
pub fn cb_rewind(buf: &mut CursorBuffer) {
buf.rewind();
}
pub fn cb_position(buf: &CursorBuffer) -> usize {
buf.position()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_bytes() {
let mut buf = new_cursor_buffer(vec![1, 2, 3, 4]);
assert_eq!(cb_read_bytes(&mut buf, 2), Some(vec![1, 2]) );
}
#[test]
fn test_remaining() {
let mut buf = new_cursor_buffer(vec![0; 10]);
cb_read_bytes(&mut buf, 3);
assert_eq!(cb_remaining(&buf), 7 );
}
#[test]
fn test_read_u8() {
let mut buf = new_cursor_buffer(vec![42, 0]);
assert_eq!(cb_read_u8(&mut buf), Some(42u8) );
}
#[test]
fn test_read_u16_le() {
let mut buf = new_cursor_buffer(vec![0x01, 0x00]);
assert_eq!(buf.read_u16_le(), Some(1u16) );
}
#[test]
fn test_read_u32_le() {
let mut buf = new_cursor_buffer(vec![0x04, 0x00, 0x00, 0x00]);
assert_eq!(buf.read_u32_le(), Some(4u32) );
}
#[test]
fn test_peek_u8() {
let buf = new_cursor_buffer(vec![99, 0]);
assert_eq!(buf.peek_u8(), Some(99u8) );
assert_eq!(cb_position(&buf), 0 );
}
#[test]
fn test_rewind() {
let mut buf = new_cursor_buffer(vec![1, 2, 3]);
cb_read_bytes(&mut buf, 3);
cb_rewind(&mut buf);
assert_eq!(cb_position(&buf), 0 );
}
#[test]
fn test_read_past_end_returns_none() {
let mut buf = new_cursor_buffer(vec![1, 2]);
assert_eq!(cb_read_bytes(&mut buf, 5), None );
}
#[test]
fn test_is_done() {
let mut buf = new_cursor_buffer(vec![1]);
buf.read_u8();
assert!(buf.is_done() );
}
#[test]
fn test_append() {
let mut buf = new_cursor_buffer(vec![1]);
buf.append(&[2, 3]);
assert_eq!(cb_remaining(&buf), 3 );
}
}