use core::mem::{self, MaybeUninit};
use core::ptr::NonNull;
use core::{fmt, slice};
use alloc::boxed::Box;
use alloc::vec::Vec;
use crate::{Bounded, Contiguous, Cursed, CursedExt, Cursor, Sequence};
pub struct CurVec<T> {
head: NonNull<T>,
tail: NonNull<T>,
}
impl<T> CurVec<T> {
pub fn new_with_init<F>(len: usize, mut init_fn: F) -> Self
where
F: FnMut() -> T,
{
match Self::try_new_with_init::<_, ()>(len, || Ok(init_fn())) {
Ok(this) => this,
Err(()) => unreachable!(),
}
}
pub fn try_new_with_init<F, E>(len: usize, mut init_fn: F) -> Result<Self, E>
where
F: FnMut() -> Result<T, E>,
{
assert_ne!(len, 0);
assert_ne!(mem::size_of::<T>(), 0);
let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len);
unsafe { vec.set_len(len) }
for i in 0..len {
match init_fn() {
Ok(elem_val) => vec[i] = MaybeUninit::new(elem_val),
Err(err) if i == 0 => {
unsafe { vec.set_len(0) };
return Err(err);
}
Err(err) => {
unsafe {
vec.set_len(i - 1);
mem::transmute::<_, Vec<T>>(vec);
};
return Err(err);
}
}
}
let mut vec = unsafe { mem::transmute::<_, Vec<T>>(vec) };
let ptr = vec.as_mut_ptr();
mem::forget(vec);
unsafe {
let ptr = NonNull::new_unchecked(ptr);
Ok(Self::from_raw_parts(ptr, len))
}
}
#[inline]
pub unsafe fn from_raw_parts(head: NonNull<T>, len: usize) -> Self {
assert_ne!(len, 0);
assert!(len <= isize::max_value() as usize);
let tail = NonNull::new_unchecked(head.as_ptr().add(len - 1));
Self { head, tail }
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.head.as_ptr() as _, self.len()) }
}
#[inline]
pub fn as_slice_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.head.as_ptr(), self.len()) }
}
#[inline]
pub fn into_boxed_slice(mut self) -> Box<[T]> {
let boxed = unsafe { Box::from_raw(self.as_slice_mut()) };
mem::forget(self);
boxed
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
self.into_boxed_slice().into()
}
}
impl<T: Default> CurVec<T> {
pub fn new_with_default(len: usize) -> Self {
Self::new_with_init(len, T::default)
}
}
unsafe impl<T> Cursed<T> for CurVec<T> {
#[inline]
fn is_owner(&self, cursor: Cursor<T>) -> bool {
(self.head..=self.tail).contains(&cursor.ptr())
}
}
impl<T> Sequence<T> for CurVec<T> {
#[inline]
fn next(&self, cursor: Cursor<T>) -> Option<Cursor<T>> {
if cursor.ptr() == self.tail {
None
} else {
let next_cursor = unsafe { cursor.unchecked_add(1) };
assert!(self.is_owner(cursor));
Some(next_cursor)
}
}
#[inline]
fn prev(&self, cursor: Cursor<T>) -> Option<Cursor<T>> {
if cursor.ptr() == self.head {
None
} else {
let prev_cursor = unsafe { cursor.unchecked_sub(1) };
assert!(self.is_owner(cursor));
Some(prev_cursor)
}
}
fn remaining(&self, cursor: Cursor<T>) -> (usize, Option<usize>) {
let remaining = if cursor.ptr() == self.head {
self.len()
} else {
self.len() - self.offset(cursor)
};
(remaining, Some(remaining))
}
}
impl<T> Bounded<T> for CurVec<T> {
#[inline]
fn len(&self) -> usize {
self.tail().offset_from(self.head()) + 1
}
#[inline]
fn head(&self) -> Cursor<T> {
Cursor::new(self.head)
}
#[inline]
fn tail(&self) -> Cursor<T> {
Cursor::new(self.tail)
}
#[inline]
fn at(&self, offset: usize) -> Option<Cursor<T>> {
if offset < self.len() {
Some(unsafe { self.head().unchecked_add(offset) })
} else {
None
}
}
}
unsafe impl<T> Contiguous<T> for CurVec<T> {}
impl<T: Clone> Clone for CurVec<T> {
fn clone(&self) -> Self {
self.as_slice().to_vec().into()
}
}
impl<T> Drop for CurVec<T> {
fn drop(&mut self) {
unsafe { mem::drop(Box::from_raw(self.as_slice_mut())) }
}
}
impl<L, R> PartialEq<CurVec<R>> for CurVec<L>
where
L: PartialEq<R>,
{
fn eq(&self, other: &CurVec<R>) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl<T> From<Vec<T>> for CurVec<T> {
fn from(value: Vec<T>) -> Self {
value.into_boxed_slice().into()
}
}
impl<T> From<Box<[T]>> for CurVec<T> {
fn from(value: Box<[T]>) -> Self {
let ptr = NonNull::new(value.as_ptr() as _).expect("non-null box ptr");
let len = value.len();
mem::forget(value);
unsafe { Self::from_raw_parts(ptr, len) }
}
}
impl<T> AsRef<[T]> for CurVec<T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> AsMut<[T]> for CurVec<T> {
fn as_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
impl<T: fmt::Debug> fmt::Debug for CurVec<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CurVec({:?})", self.as_slice())
}
}