use bumpalo::Bump;
pub struct QueryArena {
bump: Bump,
}
impl QueryArena {
#[inline]
pub fn new() -> Self {
Self::with_capacity(1024 * 1024) }
#[inline]
pub fn with_capacity(bytes: usize) -> Self {
Self { bump: Bump::with_capacity(bytes) }
}
#[inline]
pub fn alloc_bitmap(&self, len: usize) -> &mut [bool] {
self.bump.alloc_slice_fill_default(len)
}
#[inline]
pub fn alloc_bitmap_filled(&self, len: usize, value: bool) -> &mut [bool] {
self.bump.alloc_slice_fill_copy(len, value)
}
#[inline]
pub fn alloc_slice<T: Default + Copy>(&self, len: usize) -> &mut [T] {
self.bump.alloc_slice_fill_default(len)
}
#[inline]
pub fn alloc_slice_filled<T: Copy>(&self, len: usize, value: T) -> &mut [T] {
self.bump.alloc_slice_fill_copy(len, value)
}
#[inline]
pub fn alloc<T>(&self, value: T) -> &mut T {
self.bump.alloc(value)
}
#[inline]
pub fn alloc_vec<T>(&self) -> bumpalo::collections::Vec<'_, T> {
bumpalo::collections::Vec::new_in(&self.bump)
}
#[inline]
pub fn alloc_vec_with_capacity<T>(&self, capacity: usize) -> bumpalo::collections::Vec<'_, T> {
bumpalo::collections::Vec::with_capacity_in(capacity, &self.bump)
}
#[inline]
pub fn reset(&mut self) {
self.bump.reset();
}
#[inline]
pub fn allocated_bytes(&self) -> usize {
self.bump.allocated_bytes()
}
}
impl Default for QueryArena {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_allocation() {
let arena = QueryArena::new();
let bitmap = arena.alloc_bitmap(100);
assert_eq!(bitmap.len(), 100);
bitmap[0] = true;
bitmap[99] = true;
assert!(bitmap[0]);
assert!(!bitmap[50]);
assert!(bitmap[99]);
}
#[test]
fn test_bitmap_filled() {
let arena = QueryArena::new();
let all_true = arena.alloc_bitmap_filled(50, true);
assert!(all_true.iter().all(|&b| b));
let all_false = arena.alloc_bitmap_filled(50, false);
assert!(all_false.iter().all(|&b| !b));
}
#[test]
fn test_slice_allocation() {
let arena = QueryArena::new();
let ints: &mut [i64] = arena.alloc_slice(10);
for (i, val) in ints.iter_mut().enumerate() {
*val = i as i64;
}
assert_eq!(ints[5], 5);
let floats = arena.alloc_slice_filled(5, 3.5);
assert_eq!(floats.len(), 5);
assert_eq!(floats[0], 3.5);
}
#[test]
fn test_vec_allocation() {
let arena = QueryArena::new();
let mut v = arena.alloc_vec();
v.push(1);
v.push(2);
v.push(3);
assert_eq!(v.len(), 3);
assert_eq!(v[1], 2);
}
#[test]
fn test_reset() {
let mut arena = QueryArena::new();
let _bitmap1 = arena.alloc_bitmap(1000);
let bytes1 = arena.allocated_bytes();
assert!(bytes1 > 0);
arena.reset();
let bytes2 = arena.allocated_bytes();
assert_eq!(bytes2, bytes1, "Reset should keep chunks for reuse");
let _bitmap2 = arena.alloc_bitmap(1000);
let bytes3 = arena.allocated_bytes();
assert_eq!(bytes3, bytes1, "Should reuse existing chunk without growing");
}
#[test]
fn test_with_capacity() {
let arena = QueryArena::with_capacity(1024);
let initial_bytes = arena.allocated_bytes();
assert!(initial_bytes >= 1024, "Should allocate at least requested capacity");
let _bitmap = arena.alloc_bitmap(100);
let after_alloc = arena.allocated_bytes();
assert_eq!(after_alloc, initial_bytes, "Small allocation should not grow chunk");
}
#[test]
fn test_large_allocation() {
let arena = QueryArena::new();
let large = arena.alloc_bitmap(10_000_000); assert_eq!(large.len(), 10_000_000);
assert!(arena.allocated_bytes() >= 10_000_000);
}
}