#[cfg(test)]
mod tests;
pub(crate) mod wrapping;
use std::{alloc::{Layout, alloc, dealloc}, fmt::{Debug, Write}, ptr::null_mut};
use wrapping::Wrapping;
unsafe fn malloc<T>(size: usize) -> *mut T {
alloc(Layout::array::<T>(size).unwrap()) as *mut T
}
unsafe fn demalloc<T>(ptr: *mut T, size: usize) {
dealloc(ptr as *mut u8, Layout::array::<T>(size).unwrap());
}
pub struct VecDep<T> {
content: *mut T,
capacity: usize,
head: Wrapping,
tail: Wrapping,
len: usize,
}
impl<T> VecDep<T> {
#[inline]
pub const fn new(capacity: usize) -> Self {
Self {
content: null_mut(),
capacity,
head: Wrapping::new(0, capacity - 1),
tail: Wrapping::new(0, capacity - 1),
len: 0,
}
}
#[inline]
pub fn push(&mut self, item: T) {
if self.content.is_null() { unsafe {
self.content = malloc::<T>(self.capacity);
if cfg!(test) { self.content.write_bytes(0, self.capacity) }; } }
if self.is_full() {
self.tail += 1;
}
else {
self.len += 1;
};
unsafe { *self.content.add(*self.head) = item };
self.head += 1;
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() { return None };
let item = unsafe { self.content.add(*self.tail).read() };
self.tail += 1;
self.len -= 1;
Some(item)
}
#[inline]
pub fn peek<'d>(&'d self) -> Option<&'d T> {
if self.is_empty() { return None };
let item = unsafe { self.content.add(*self.tail).as_ref().unwrap() };
Some(item)
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
self.capacity
}
#[inline(always)]
pub fn is_full(&self) -> bool {
self.len == self.capacity
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
impl<T> Drop for VecDep<T> {
fn drop(&mut self) {
unsafe { demalloc(self.content, self.capacity) };
}
}
impl<T: Debug> Debug for VecDep<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.content.is_null() {
f.write_str("[unallocated]")
} else {
f.write_char('[')?;
for idx in 0..self.capacity {
unsafe { f.write_fmt(format_args!("{:?}", *self.content.add(idx)))? };
if idx == *self.tail { f.write_str(" (T)")? };
if idx == *self.head { f.write_str(" (H)")? };
if idx + 1 < self.capacity { f.write_str(", ")? };
}
f.write_char(']')
}
}
}