use std::cell::RefCell;
#[derive(Debug, Default)]
pub struct DecodeArena {
buffers: RefCell<Vec<Box<[u8]>>>,
}
impl DecodeArena {
pub fn new() -> Self {
Self::default()
}
pub fn alloc(&self, bytes: Box<[u8]>) -> &[u8] {
let mut buffers = self.buffers.borrow_mut();
buffers.push(bytes);
let slice: &[u8] = buffers.last().expect("a buffer was just pushed").as_ref();
unsafe { std::slice::from_raw_parts(slice.as_ptr(), slice.len()) }
}
}
#[cfg(test)]
mod tests {
use super::DecodeArena;
fn buffer(index: usize) -> Box<[u8]> {
let len = (index % 7) + 1;
vec![index as u8; len].into_boxed_slice()
}
fn check(index: usize, slice: &[u8]) {
assert_eq!(slice.len(), (index % 7) + 1, "length of buffer {index}");
assert!(
slice.iter().all(|&byte| byte == index as u8),
"contents of buffer {index}",
);
}
#[test]
fn interleaved_alloc_and_read_across_many_buffers() {
let arena = DecodeArena::new();
let mut borrows: Vec<&[u8]> = Vec::new();
for index in 0..256usize {
borrows.push(arena.alloc(buffer(index)));
for (i, slice) in borrows.iter().enumerate() {
check(i, slice);
}
}
}
}