#![allow(unsafe_code)]
use bumpalo::Bump;
use std::marker::PhantomData;
use std::ops::{Deref, Index};
use std::ptr::NonNull;
use std::slice;
pub struct ArenaVec<'arena, T> {
ptr: NonNull<T>,
len: usize,
_marker: PhantomData<&'arena [T]>,
}
impl<'arena, T> ArenaVec<'arena, T> {
pub fn empty() -> Self {
Self {
ptr: NonNull::dangling(),
len: 0,
_marker: PhantomData,
}
}
pub fn from_slice(arena: &'arena Bump, slice: &[T]) -> Self
where
T: Copy,
{
if slice.is_empty() {
return Self::empty();
}
let arena_storage = arena.alloc_slice_copy(slice);
Self {
ptr: NonNull::new(arena_storage.as_mut_ptr()).expect("arena allocation is non-null"),
len: slice.len(),
_marker: PhantomData,
}
}
pub fn from_iter(arena: &'arena Bump, iter: impl IntoIterator<Item = T>) -> Self
where
T: Copy,
{
let items: Vec<T> = iter.into_iter().collect();
Self::from_slice(arena, &items)
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn as_slice(&self) -> &[T] {
if self.len == 0 {
&[]
} else {
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
}
pub fn iter(&self) -> slice::Iter<'_, T> {
self.as_slice().iter()
}
pub fn get(&self, index: usize) -> Option<&T> {
self.as_slice().get(index)
}
pub fn first(&self) -> Option<&T> {
self.as_slice().first()
}
pub fn last(&self) -> Option<&T> {
self.as_slice().last()
}
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.as_slice().to_vec()
}
}
impl<'arena, T> Deref for ArenaVec<'arena, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<'arena, T> Index<usize> for ArenaVec<'arena, T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.as_slice()[index]
}
}
impl<'arena, T> Clone for ArenaVec<'arena, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'arena, T> Copy for ArenaVec<'arena, T> {}
impl<'arena, T: std::fmt::Debug> std::fmt::Debug for ArenaVec<'arena, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_slice().fmt(f)
}
}
impl<'arena, T: PartialEq> PartialEq for ArenaVec<'arena, T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<'arena, T: Eq> Eq for ArenaVec<'arena, T> {}
impl<'arena, T: PartialEq> PartialEq<[T]> for ArenaVec<'arena, T> {
fn eq(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
impl<'arena, T: PartialEq> PartialEq<&[T]> for ArenaVec<'arena, T> {
fn eq(&self, other: &&[T]) -> bool {
self.as_slice() == *other
}
}
impl<'arena, T: PartialEq> PartialEq<Vec<T>> for ArenaVec<'arena, T> {
fn eq(&self, other: &Vec<T>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<'arena, T> IntoIterator for ArenaVec<'arena, T> {
type Item = &'arena T;
type IntoIter = slice::Iter<'arena, T>;
fn into_iter(self) -> Self::IntoIter {
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len).iter() }
}
}
impl<'a, 'arena, T> IntoIterator for &'a ArenaVec<'arena, T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty() {
let vec: ArenaVec<'_, i32> = ArenaVec::empty();
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
assert_eq!(vec.as_slice(), &[]);
}
#[test]
fn test_from_slice() {
let arena = Bump::new();
let data = [1, 2, 3, 4, 5];
let vec = ArenaVec::from_slice(&arena, &data);
assert_eq!(vec.len(), 5);
assert!(!vec.is_empty());
assert_eq!(vec.as_slice(), &data);
}
#[test]
fn test_from_empty_slice() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[] as &[i32]);
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
}
#[test]
fn test_from_iter() {
let arena = Bump::new();
let vec = ArenaVec::from_iter(&arena, [1, 2, 3, 4, 5].iter().copied());
assert_eq!(vec.len(), 5);
assert_eq!(vec.as_slice(), &[1, 2, 3, 4, 5]);
}
#[test]
fn test_indexing() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[10, 20, 30, 40, 50]);
assert_eq!(vec[0], 10);
assert_eq!(vec[2], 30);
assert_eq!(vec[4], 50);
}
#[test]
fn test_get() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[10, 20, 30]);
assert_eq!(vec.get(0), Some(&10));
assert_eq!(vec.get(2), Some(&30));
assert_eq!(vec.get(3), None);
}
#[test]
fn test_first_last() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[10, 20, 30]);
assert_eq!(vec.first(), Some(&10));
assert_eq!(vec.last(), Some(&30));
let empty: ArenaVec<'_, i32> = ArenaVec::empty();
assert_eq!(empty.first(), None);
assert_eq!(empty.last(), None);
}
#[test]
fn test_iter() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3, 4, 5]);
let sum: i32 = vec.iter().sum();
assert_eq!(sum, 15);
let doubled: Vec<i32> = vec.iter().map(|x| x * 2).collect();
assert_eq!(doubled, vec![2, 4, 6, 8, 10]);
}
#[test]
fn test_into_iter() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let sum: i32 = vec.into_iter().sum();
assert_eq!(sum, 6);
}
#[test]
fn test_to_vec() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let owned = vec.to_vec();
assert_eq!(owned, vec![1, 2, 3]);
}
#[test]
fn test_clone_copy() {
let arena = Bump::new();
let vec1 = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let vec2 = vec1;
let vec3 = vec1;
assert_eq!(vec1, vec2);
assert_eq!(vec1, vec3);
assert_eq!(vec2, vec3);
}
#[test]
fn test_equality() {
let arena = Bump::new();
let vec1 = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let vec2 = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let vec3 = ArenaVec::from_slice(&arena, &[1, 2, 4]);
assert_eq!(vec1, vec2);
assert_ne!(vec1, vec3);
assert_eq!(vec1, &[1, 2, 3][..]);
assert_eq!(vec1.as_slice(), &[1, 2, 3]);
assert_eq!(vec1, vec![1, 2, 3]);
assert_ne!(vec1, vec![1, 2, 4]);
}
#[test]
fn test_debug() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let debug = format!("{:?}", vec);
assert_eq!(debug, "[1, 2, 3]");
}
#[test]
fn test_deref() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3, 4, 5]);
assert!(vec.contains(&3));
assert!(!vec.contains(&10));
assert_eq!(vec.binary_search(&3), Ok(2));
}
#[test]
fn test_strings() {
let arena = Bump::new();
let strings = vec!["hello", "world", "test"];
let vec = ArenaVec::from_slice(&arena, &strings);
assert_eq!(vec.len(), 3);
assert_eq!(vec[0], "hello");
assert_eq!(vec[1], "world");
assert_eq!(vec[2], "test");
}
#[test]
fn test_large_vec() {
let arena = Bump::new();
let data: Vec<i32> = (0..1000).collect();
let vec = ArenaVec::from_slice(&arena, &data);
assert_eq!(vec.len(), 1000);
assert_eq!(vec[0], 0);
assert_eq!(vec[999], 999);
let sum: i32 = vec.iter().sum();
assert_eq!(sum, 999 * 1000 / 2); }
#[test]
fn test_multiple_vecs_same_arena() {
let arena = Bump::new();
let vec1 = ArenaVec::from_slice(&arena, &[1, 2, 3]);
let vec2 = ArenaVec::from_slice(&arena, &[4, 5, 6]);
let vec3 = ArenaVec::from_slice(&arena, &[7, 8, 9]);
assert_eq!(vec1.as_slice(), &[1, 2, 3]);
assert_eq!(vec2.as_slice(), &[4, 5, 6]);
assert_eq!(vec3.as_slice(), &[7, 8, 9]);
}
#[test]
fn test_slice_operations() {
let arena = Bump::new();
let vec = ArenaVec::from_slice(&arena, &[1, 2, 3, 4, 5]);
let slice = vec.as_slice();
assert_eq!(&slice[1..4], &[2, 3, 4]);
assert_eq!(&slice[..3], &[1, 2, 3]);
assert_eq!(&slice[2..], &[3, 4, 5]);
}
}