use std::{mem, num, ops, ptr};
use prefix::Prefix;
use crate::mem::{Lease, lease};
pub mod bits;
mod compact;
pub mod copy;
mod index;
pub use index::Index;
pub mod init;
mod prefix;
pub mod sorted;
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Len<const N: usize>(pub(in crate::depot::array) u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Error {
pub actual: usize,
pub capacity: usize,
}
#[must_use = "a fixed-array vacancy must be committed or abandoned"]
#[repr(transparent)]
#[derive(Debug)]
pub struct Vacancy<const N: usize>(num::NonZero<u32>);
impl<const N: usize> Len<N> {
pub(in crate::depot::array) const VALID: () =
assert!(N <= u32::MAX as usize, "inline array capacity must fit u32");
pub const ZERO: Self = {
let () = Self::VALID;
Self(0)
};
pub const ONE: Self = {
let () = Self::VALID;
assert!(N != 0, "zero-capacity array has no length one");
Self(1)
};
pub const fn exact<const LENGTH: usize>() -> Self {
let () = Self::VALID;
const { assert!(LENGTH <= N, "capacity") };
Self(LENGTH as u32)
}
pub const MAX: Self = {
let () = Self::VALID;
Self(N as u32)
};
pub const fn get(self) -> usize {
self.0 as usize
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
pub const fn is_full(self) -> bool {
self.0 == N as u32
}
pub const fn vacancy(self) -> Option<Vacancy<N>> {
if self.0 >= N as u32 {
return None;
}
Some(Vacancy(unsafe { num::NonZero::new_unchecked(self.0 + 1) }))
}
pub fn prefix<T>(self, values: &[T; N]) -> &[T] {
unsafe { values.get_unchecked(..self.get()) }
}
pub fn prefix_mut<T>(self, values: &mut [T; N]) -> &mut [T] {
unsafe { values.get_unchecked_mut(..self.get()) }
}
}
impl<const N: usize> TryFrom<usize> for Len<N> {
type Error = Error;
fn try_from(len: usize) -> Result<Self, Self::Error> {
let () = Self::VALID;
if len > N {
return Err(Error {
actual: len,
capacity: N,
});
}
Ok(Self(len as u32))
}
}
impl<const N: usize> Vacancy<N> {
pub const fn at<const I: usize>() -> Self {
let () = Len::<N>::VALID;
const { assert!(I < N) };
Self(num::NonZero::<u32>::MIN.saturating_add(I as u32))
}
pub const fn index(&self) -> usize {
(self.0.get() - 1) as usize
}
pub fn get_mut<'a, T>(&self, values: &'a mut [T; N]) -> &'a mut T {
unsafe { values.get_unchecked_mut(self.index()) }
}
pub const fn commit(self) -> Len<N> {
Len(self.0.get())
}
}
const _: () = {
assert!(mem::size_of::<Vacancy<4>>() == mem::size_of::<u32>());
assert!(mem::size_of::<Option<Vacancy<4>>>() == mem::size_of::<u32>());
};
impl<const N: usize> From<Len<N>> for usize {
fn from(len: Len<N>) -> Self {
len.get()
}
}
#[must_use = "a vector vacancy must be filled or abandoned"]
pub struct Vacant<'a, T, const N: usize> {
raw: &'a mut Prefix<T, N>,
slot: Vacancy<N>,
}
impl<T, const N: usize> Vacant<'_, T, N> {
pub fn as_slice(&self) -> &[T] {
self.raw.as_slice()
}
pub fn insert(self, value: T) {
self.slot.get_mut(&mut self.raw.entries).write(value);
self.raw.len = self.slot.commit();
}
}
#[repr(transparent)]
pub struct Vec<T, const N: usize> {
raw: Prefix<T, N>,
}
#[derive(Debug)]
#[repr(transparent)]
pub struct IntoIter<T, const N: usize> {
raw: copy::IntoIter<T, N>,
}
pub struct Withdrawn<'a, T, const N: usize> {
source: &'a mut IntoIter<T, N>,
}
impl<T, const N: usize> Withdrawn<'_, T, N> {
pub fn index(&self) -> usize {
self.source.raw.front.get().wrapping_sub(1)
}
}
impl<T, const N: usize> crate::mem::Return for Withdrawn<'_, T, N> {
type Item = T;
fn return_item(self, item: T) {
let front = Len(self.source.raw.front.0.wrapping_sub(1));
unsafe {
self.source
.raw
.entries
.get_unchecked_mut(front.get())
.write(item)
};
self.source.raw.front = front;
}
}
impl<T, const N: usize> Vec<T, N> {
pub const fn new() -> Self {
Self {
raw: Prefix::empty(),
}
}
pub fn from_one(value: T) -> Self {
Self {
raw: Prefix::single(value),
}
}
pub fn from_fn(len: Len<N>, f: impl FnMut(Vacancy<N>) -> T) -> Self {
Self {
raw: Prefix::fill(len, f),
}
}
pub fn map_from<'a, U: Copy>(
&mut self,
source: &'a copy::Vec<U, N>,
make: impl FnMut(Vacancy<N>, &'a U) -> T,
) {
self.raw.map_from(&source.raw, make);
}
pub fn push(&mut self, value: T) -> Result<(), T> {
let Some(vacant) = self.vacancy() else {
return Err(value);
};
vacant.insert(value);
Ok(())
}
pub fn vacancy(&mut self) -> Option<Vacant<'_, T, N>> {
self.raw.vacancy()
}
pub const fn extent(&self) -> Len<N> {
self.raw.len
}
pub fn drain(&mut self) -> init::IntoIter<'_, T> {
init::IntoIter::drain(&mut self.raw)
}
pub fn as_slice(&self) -> &[T] {
self.raw.as_slice()
}
}
impl<T, const N: usize> Default for Vec<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> From<[T; N]> for Vec<T, N> {
fn from(values: [T; N]) -> Self {
Self {
raw: Prefix::from_array(values),
}
}
}
impl<T, const N: usize> ops::Deref for Vec<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.raw.as_slice()
}
}
impl<T, const N: usize> ops::DerefMut for Vec<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.raw.as_mut_slice()
}
}
impl<T, const N: usize> IntoIterator for Vec<T, N> {
type IntoIter = IntoIter<T, N>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
let owner = mem::ManuallyDrop::new(self);
let prefix = unsafe { ptr::read(&owner.raw) };
IntoIter {
raw: copy::IntoIter::new(prefix),
}
}
}
impl<T, const N: usize> Drop for Vec<T, N> {
fn drop(&mut self) {
self.raw.drop_all();
}
}
impl<T, const N: usize> IntoIter<T, N> {
pub fn remove_front(&mut self) -> Option<Lease<Withdrawn<'_, T, N>, lease::Open>> {
let value = self.raw.next()?;
Some(Lease::open(Withdrawn { source: self }, value))
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.raw.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.raw.size_hint()
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
impl<T, const N: usize> Drop for IntoIter<T, N> {
fn drop(&mut self) {
crate::depot::raw::Drain::destroy::<false>(&mut self.raw);
}
}