use std::{
alloc::Layout,
ptr::{copy_nonoverlapping, null_mut},
};
use bumpalo::Bump;
pub struct Arena {
bump: Bump,
}
impl Arena {
pub fn new() -> Self {
Self {
bump: Bump::new(),
}
}
pub fn alloc(&self, size: usize) -> *mut u8 {
if size == 0 {
return null_mut();
}
let layout = Layout::from_size_align(size, 8).unwrap();
self.bump.alloc_layout(layout).as_ptr()
}
pub fn copy_bytes(&self, bytes: &[u8]) -> *mut u8 {
if bytes.is_empty() {
return null_mut();
}
let ptr = self.alloc(bytes.len());
if !ptr.is_null() {
unsafe {
copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len());
}
}
ptr
}
pub fn clear(&mut self) {
self.bump.reset();
}
}
impl Default for Arena {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn test_arena_basic() {
let arena = Arena::new();
let ptr1 = arena.alloc(100);
assert!(!ptr1.is_null());
let ptr2 = arena.alloc(200);
assert!(!ptr2.is_null());
}
#[test]
fn test_arena_copy_bytes() {
let arena = Arena::new();
let data = vec![1u8, 2, 3, 4, 5];
let ptr = arena.copy_bytes(&data);
assert!(!ptr.is_null());
unsafe {
for i in 0..5 {
assert_eq!(*ptr.add(i), data[i]);
}
}
}
#[test]
fn test_arena_clear() {
let mut arena = Arena::new();
arena.alloc(100);
arena.alloc(200);
arena.clear();
let ptr = arena.alloc(50);
assert!(!ptr.is_null());
}
#[test]
fn test_arena_zero_size() {
let arena = Arena::new();
let ptr = arena.alloc(0);
assert!(ptr.is_null());
}
#[test]
fn test_arena_empty_bytes() {
let arena = Arena::new();
let ptr = arena.copy_bytes(&[]);
assert!(ptr.is_null());
}
}