warlock 0.0.3

Arena allocation optimized collections
Documentation
use core::{
	ptr,
	ptr::NonNull,
	slice
};

use crate::{
	util::layout_for_n,
	alloc::{
		Allocator,
		AllocError,
	},
};

#[derive(Debug)]
pub struct Vec<T, A: Allocator> {
	mem: NonNull<T>,
	len: usize,
	cap: usize,
	alloc: A,
}

impl <T, A: Allocator> Vec<T, A> {
	pub fn with_capacity_in(cap: usize, alloc: A) -> Result<Self, AllocError> {
		debug_assert!(cap > 0, "Capacity must be > 0");

		let mem = alloc.allocate(layout_for_n::<T>(cap))?;

		let mem = unsafe { NonNull::new_unchecked(mem.as_ptr() as *mut T) };

		Ok(Self {
			mem,
			cap,
			len: 0,
			alloc,
		})
	}

	pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
		let new_cap = self.cap + additional;
		let old_layout = layout_for_n::<T>(self.cap);
		let new_layout = layout_for_n::<T>(new_cap);
		let mem = unsafe {
			self.alloc.grow(self.mem.cast(), old_layout, new_layout)?
		};

		self.mem = unsafe { NonNull::new_unchecked(mem.as_ptr() as *mut T) };
		self.cap = new_cap;

		Ok(())
	}

	pub fn try_push(&mut self, val: T) -> Result<(), AllocError> {
		if self.len >= self.cap {
			self.try_reserve(self.len)?;
		}

		unsafe {
			let end = self.mem.as_ptr().add(self.len);
			ptr::write(end, val);
		};

		self.len += 1;

		Ok(())
	}

	pub fn as_slice(&self) -> &[T] {
		unsafe {
			slice::from_raw_parts(self.mem.as_ptr(), self.len)
		}
	}

	pub fn as_mut_slice(&mut self) -> &mut [T] {
		unsafe {
			slice::from_raw_parts_mut(self.mem.as_ptr(), self.len)
		}
	}

	pub fn capacity(&self) -> usize {
		self.cap
	}

	pub fn len(&self) -> usize {
		self.len
	}

	pub fn is_empty(&self) -> bool {
		self.len == 0
	}

	/// # Safety
	/// Caller must guarantee all the invariants of this struct are valid
	/// after this call
	pub unsafe fn set_len(&mut self, len: usize) {
		self.len = len;
	}
}

impl <T, A> Drop for Vec<T, A> where A: Allocator {
    fn drop(&mut self) {
		unsafe {
			ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.mem.as_ptr(), self.len))
		}
    }
}