#![no_std]
#![warn(missing_docs)]
use core::{
mem::{align_of, size_of},
ptr::NonNull,
slice,
};
extern crate alloc;
use alloc::alloc::{alloc, dealloc, handle_alloc_error, Layout};
const fn max_usize(x: usize, y: usize) -> usize {
x ^ ((x ^ y) & ((x < y) as usize).wrapping_neg())
}
#[derive(Debug)]
#[repr(C)]
pub struct OverVec<T, const MIN: usize> {
nn: NonNull<T>,
element_count: usize,
byte_capacity: usize,
}
impl<T, const MIN: usize> Drop for OverVec<T, MIN> {
fn drop(&mut self) {
if core::mem::needs_drop::<T>() {
let mut p = self.nn.as_ptr();
for _ in 0..self.element_count {
unsafe {
core::ptr::drop_in_place(p);
p = p.add(1);
}
}
}
let layout = Layout::from_size_align(self.byte_capacity, Self::ALIGN).expect("layout error!");
unsafe { dealloc(self.nn.as_ptr().cast::<u8>(), layout) }
}
}
impl<T, const MIN: usize> core::ops::Deref for OverVec<T, MIN> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.nn.as_ptr(), self.element_count) }
}
}
impl<T, const MIN: usize> core::ops::DerefMut for OverVec<T, MIN> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.nn.as_ptr(), self.element_count) }
}
}
impl<T, const MIN: usize> OverVec<T, MIN> {
pub const ALIGN: usize = max_usize(align_of::<T>(), MIN);
pub const fn new() -> Self {
OverVec { nn: NonNull::dangling(), element_count: 0, byte_capacity: 0 }
}
pub fn with_capacity(cap: usize) -> Self {
assert!(MIN.is_power_of_two(), "The `MIN` constant must be a power of two.");
if cap == 0 {
return Self::new();
}
if size_of::<T>() == 0 {
OverVec::new()
} else {
let align = Self::ALIGN;
debug_assert!(align > 0);
let mut size = cap.checked_mul(size_of::<T>()).unwrap_or_else(|| {
panic!(
"Requested capacity {cap} times {size} per element exceeds the address space.",
cap = cap,
size = size_of::<T>()
)
});
debug_assert!(size > 0);
let size_slop = size % align;
size = size.saturating_add(size_slop);
debug_assert!(
size % align == 0,
"size not multiple of align! size:{size}, align:{align}",
size = size,
align = align
);
let layout = Layout::from_size_align(size, align).expect("layout error!");
let nn = NonNull::new(unsafe { alloc(layout) }.cast::<T>())
.unwrap_or_else(|| handle_alloc_error(layout));
OverVec { nn, element_count: 0, byte_capacity: size }
}
}
pub const fn len(&self) -> usize {
self.element_count
}
pub const fn capacity(&self) -> usize {
if size_of::<T>() == 0 {
isize::MAX as usize
} else {
self.byte_capacity / size_of::<T>()
}
}
pub fn push(&mut self, t: T) {
let cap = self.capacity();
let len = self.len();
if len >= cap {
todo!("handle how to reallocate the vector to make more space");
} else {
unsafe { self.nn.as_ptr().add(len).write(t) };
self.element_count += 1;
}
}
}