mod convert;
mod cmp;
mod fmt;
mod iter;
mod oct;
mod ops;
mod serde;
mod test;
use core::borrow::{Borrow, BorrowMut};
use core::hash::{Hash, Hasher};
use core::hint::assert_unchecked;
use core::mem::MaybeUninit;
use core::ptr::drop_in_place;
use core::slice;
use nvec::n_vec::TryReserveError;
#[cfg(feature = "std")]
use std::io::{self, Write};
pub struct NVec<T, const N: usize> {
len: usize,
data: [MaybeUninit<T>; N],
}
impl<T, const N: usize> NVec<T, N> {
const MAX_LEN: usize = {
if size_of::<T>() > 0 {
let max_size = isize::MAX as usize;
max_size / size_of::<T>()
} else {
usize::MAX
}
};
#[inline]
#[must_use]
pub const fn new() -> Self {
let data = [const { MaybeUninit::uninit() }; N];
unsafe { Self::from_raw_parts(data, 0) }
}
#[inline]
pub const fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
if capacity <= N {
Ok(Self::new())
} else {
Err(TryReserveError)
}
}
pub const fn try_reserve(&self, extra: usize) -> Result<(), TryReserveError> {
if extra <= self.remaining_capacity() {
Ok(())
} else {
Err(TryReserveError)
}
}
pub fn try_push(&mut self, elem: T) -> Result<(), TryReserveError> {
self.try_push_mut(elem).map(|_| ())
}
pub fn try_push_mut(&mut self, elem: T) -> Result<&mut T, TryReserveError> {
if self.remaining_capacity() < 1 {
return Err(TryReserveError);
}
let slot = unsafe { self.push_unchecked_mut(elem) };
Ok(slot)
}
#[inline]
pub const unsafe fn push_unchecked_mut(&mut self, elem: T) -> &mut T {
debug_assert!(self.remaining_capacity() >= 1);
let slot = unsafe { self.as_mut_ptr().add(self.len()) };
unsafe { slot.write(elem) };
self.len += 1;
unsafe { &mut *slot }
}
pub fn try_resize(&mut self, len: usize, value: T) -> Result<(), TryReserveError>
where
T: Clone,
{
if len > self.len() {
let diff = self.len().abs_diff(len);
let slots = self.spare_capacity_mut()
.get_mut(..diff)
.ok_or(TryReserveError)?;
for slot in slots {
slot.write(value.clone());
}
unsafe { self.set_len(len) };
} else if len < self.len() {
self.truncate(len);
}
Ok(())
}
#[inline]
pub fn truncate(&mut self, len: usize) {
if len >= self.len() {
return;
}
let to_drop: *mut _ = unsafe { self.get_unchecked_mut(len..) };
self.len = len;
unsafe { drop_in_place(to_drop) };
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0)
}
#[inline(always)]
#[must_use]
pub const fn capacity(&self) -> usize {
N
}
#[inline]
#[must_use]
pub const fn remaining_capacity(&self) -> usize {
unsafe{ self.capacity().unchecked_sub(self.len()) }
}
#[inline(always)]
#[track_caller]
pub const unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= self.capacity());
self.len = len;
}
#[inline(always)]
#[must_use]
pub const fn len(&self) -> usize {
let len = self.len;
unsafe { assert_unchecked(len <= N) };
unsafe { assert_unchecked(len <= Self::MAX_LEN) };
len
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub const fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
let len = self.remaining_capacity();
let data = {
let base = self.as_mut_ptr().cast::<MaybeUninit<T>>();
unsafe { base.add(self.len()) }
};
unsafe { slice::from_raw_parts_mut(data, len) }
}
#[inline]
#[must_use]
pub const fn copied(&self) -> Self
where
T: Copy,
{
let len = self.len;
let data = self.data;
unsafe { Self::from_raw_parts(data, len) }
}
#[inline]
#[must_use]
pub fn map<F: FnMut(T) -> U, U>(self, mut op: F) -> NVec<U, N> {
let len = self.len();
let mut data = [const { MaybeUninit::<U>::uninit() }; N];
for (index, value) in self.into_iter().enumerate() {
let slot = &mut data[index];
let value = op(value);
slot.write(value);
}
unsafe { NVec::from_raw_parts(data, len) }
}
}
impl<T, const N: usize> Borrow<[T]> for NVec<T, N> {
#[inline]
fn borrow(&self) -> &[T] {
self
}
}
impl<T, const N: usize> BorrowMut<[T]> for NVec<T, N> {
#[inline]
fn borrow_mut(&mut self) -> &mut [T] {
self
}
}
impl<T: Clone, const N: usize> Clone for NVec<T, N> {
#[inline]
fn clone(&self) -> Self {
let mut new = Self::new();
for i in 0..self.len() {
new.data[i].write(self[i].clone());
}
unsafe { new.set_len(self.len()) };
new
}
}
impl<T, const N: usize> Default for NVec<T, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Drop for NVec<T, N> {
#[inline]
fn drop(&mut self) {
let to_drop = self.as_mut_slice();
unsafe { drop_in_place(to_drop) };
}
}
impl<T: Hash, const N: usize> Hash for NVec<T, N> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
#[cfg(feature = "std")]
impl<const N: usize> Write for NVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let len = self.remaining_capacity().min(buf.len());
let buf = &buf[..len];
self.write_all(buf)?;
Ok(len)
}
#[inline(always)]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
let slot = self.spare_capacity_mut()
.get_mut(..buf.len())
.ok_or(TryReserveError)?;
{
let len = buf.len();
let dst: *mut u8 = slot.as_mut_ptr().cast::<u8>();
let src: *const u8 = buf.as_ptr();
unsafe { dst.copy_from_nonoverlapping(src, len) };
}
Ok(())
}
}