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
}
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))
}
}
}