use alloc::vec::Vec;
use alloc::collections::TryReserveError;
use core::fmt;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::num::NonZeroUsize;
use core::ptr::NonNull;
use crate::error::EmptyCollectionError;
use crate::NonEmpty;
#[cfg(doc)]
use alloc::borrow::ToOwned;
pub struct NonEmptyVec<T> {
ptr: NonNull<T>,
len: NonZeroUsize,
capacity: NonZeroUsize,
}
impl<T> NonEmptyVec<T> {
pub fn from_vec(vec: Vec<T>) -> Option<Self> {
NonEmpty::new(vec).map(Into::into)
}
pub fn with_first_element(element: T) -> Self {
NonEmpty::<Vec<T>>::with_first_element(element).into()
}
pub fn with_first_element_and_extra_capacity(item: T, additional_capacity: usize) -> Self {
NonEmpty::<Vec<T>>::with_first_element_and_extra_capacity(item, additional_capacity)
.into()
}
pub fn reserve(&mut self, additional: usize) {
self.with_vec(move |vec| vec.reserve(additional))
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
unsafe { self.with_vec_unchecked(move |vec| vec.try_reserve(additional)) }
}
pub unsafe fn from_vec_unchecked(vec: Vec<T>) -> Self {
let mut vec = ManuallyDrop::new(vec);
NonEmptyVec {
ptr: NonNull::new_unchecked(vec.as_mut_ptr()),
len: NonZeroUsize::new_unchecked(vec.len()),
capacity: NonZeroUsize::new_unchecked(vec.capacity()),
}
}
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
pub fn as_non_null(&mut self) -> NonNull<T> {
self.ptr
}
pub fn len(&self) -> NonZeroUsize {
self.len
}
pub unsafe fn set_len(&mut self, new_len: NonZeroUsize) {
self.len = new_len;
}
pub fn capacity(&self) -> NonZeroUsize {
self.capacity
}
pub fn into_vec(self) -> Vec<T> {
let this = ManuallyDrop::new(self);
unsafe {
Vec::from_raw_parts(this.ptr.as_ptr(), this.len.into(), this.capacity.into())
}
}
pub fn into_non_empty(self) -> NonEmpty<Vec<T>> {
unsafe { NonEmpty::new_unchecked(self.into_vec()) }
}
pub fn as_non_empty_slice(&self) -> &NonEmpty<[T]> {
unsafe { NonEmpty::new_ref_unchecked(self.as_slice()) }
}
pub fn as_mut_non_empty_slice(&mut self) -> &mut NonEmpty<[T]> {
unsafe { NonEmpty::new_mut_unchecked(self.as_mut_slice()) }
}
pub fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len().into()) }
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
let len = self.len().into();
unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), len) }
}
unsafe fn with_vec_unchecked<R>(&mut self, f: impl FnOnce(&mut Vec<T>) -> R) -> R {
struct PutBack<'a, T> {
original: &'a mut NonEmptyVec<T>,
temp: ManuallyDrop<Vec<T>>,
}
impl<'a, T> Drop for PutBack<'a, T> {
fn drop(&mut self) {
unsafe {
core::ptr::write(self.original, NonEmptyVec::from_vec_unchecked(ManuallyDrop::take(&mut self.temp)));
}
}
}
let vec = ManuallyDrop::new(Vec::from_raw_parts(self.ptr.as_ptr(), self.len.into(), self.capacity.into()));
let mut guard = PutBack {
original: self,
temp: vec,
};
f(&mut guard.temp)
}
pub(crate) fn with_vec<R>(&mut self, f: impl FnOnce(&mut NonEmpty<Vec<T>>) -> R) -> R {
unsafe {
self.with_vec_unchecked(move |vec| f(NonEmpty::new_mut_unchecked(vec)))
}
}
pub fn append(&mut self, other: &mut Vec<T>) {
unsafe { self.with_vec_unchecked(move |vec| vec.append(other)) }
}
pub fn resize_with<F>(&mut self, new_len: NonZeroUsize, f: F) where F: FnMut() -> T {
unsafe { self.with_vec_unchecked(move |vec| vec.resize_with(new_len.into(), f)) }
}
pub fn leak<'a>(self) -> &'a mut NonEmpty<[T]> {
unsafe { NonEmpty::new_mut_unchecked(self.into_vec().leak()) }
}
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
unsafe {
let len = usize::from(self.capacity()) - usize::from(self.len());
core::slice::from_raw_parts_mut(self.as_mut_ptr().add(self.len.into()) as *mut _, len)
}
}
pub fn push(&mut self, element: T) {
unsafe { self.with_vec_unchecked(move |vec| vec.push(element)) }
}
pub fn insert(&mut self, index: usize, element: T) {
unsafe { self.with_vec_unchecked(move |vec| vec.insert(index, element)) }
}
pub fn pop(self) -> (T, Vec<T>) {
self.into_non_empty().pop_last()
}
pub fn try_pop(&mut self) -> Option<T> {
self.with_vec(|vec| vec.try_pop_last())
}
pub fn swap_remove(self, index: usize) -> (T, Vec<T>) {
let mut vec = self.into_vec();
let element = vec.swap_remove(index);
(element, vec)
}
pub fn swap_remove_first(self) -> (T, Vec<T>) {
self.swap_remove(0)
}
pub fn try_remove(&mut self, index: usize) -> Result<T, RemoveError> {
self.try_remove_inner(index, move |vec| unsafe { vec.inner_mut().remove(index) })
}
pub fn try_swap_remove(&mut self, index: usize) -> Result<T, RemoveError> {
self.try_remove_inner(index, |vec| unsafe { vec.inner_mut().swap_remove(index) })
}
fn try_remove_inner(&mut self, index: usize, f: impl FnOnce(&mut NonEmpty<Vec<T>>) -> T) -> Result<T, RemoveError> {
match (self.len().if_less_than(index), usize::from(self.len()) == 1) {
(None, false) => {
Ok(self.with_vec(f))
},
(None, true) => Err(RemoveError::WouldBecomeEmpty),
(Some(index), false) => {
Err(RemoveError::IndexOutOfBounds {
index,
len: self.len()
})
},
(Some(index), true) => {
Err(RemoveError::Both {
index,
len: self.len()
})
},
}
}
pub fn truncate(&mut self, len: NonZeroUsize) {
unsafe { self.with_vec_unchecked(move |vec| { vec.truncate(len.into()) }) }
}
pub fn split_off(&mut self, at: NonZeroUsize) -> Vec<T> {
unsafe { self.with_vec_unchecked(move |vec| { vec.split_off(at.into()) }) }
}
pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
unsafe { self.with_vec_unchecked(move |vec| vec.dedup_by(same_bucket)) }
}
pub fn dedup_by_key<F, K>(&mut self, key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
unsafe { self.with_vec_unchecked(move |vec| vec.dedup_by_key(key)) }
}
pub fn shrink_to_fit(&mut self) {
unsafe { self.with_vec_unchecked(move |vec| vec.shrink_to_fit()) }
}
}
impl<T: Clone> NonEmptyVec<T> {
pub fn resize(&mut self, new_len: NonZeroUsize, value: T) {
unsafe { self.with_vec_unchecked(move |vec| vec.resize(new_len.into(), value)) }
}
pub fn extend_from_slice(&mut self, other: &[T]) {
unsafe { self.with_vec_unchecked(move |vec| vec.extend_from_slice(other)) }
}
}
impl<const N: usize, T> NonEmptyVec<[T; N]> {
const CHECK: () = assert!(N != 0);
pub fn into_non_empty_flattened(self) -> NonEmptyVec<T> {
let _ = Self::CHECK;
unsafe { NonEmptyVec::from_vec_unchecked(self.into_vec().into_flattened()) }
}
}
impl<T: PartialEq> NonEmptyVec<T> {
pub fn dedup(&mut self) {
unsafe { self.with_vec_unchecked(move |vec| vec.dedup()) }
}
}
impl<T> core::ops::Deref for NonEmptyVec<T> {
type Target = NonEmpty<[T]>;
fn deref(&self) -> &Self::Target {
self.as_non_empty_slice()
}
}
impl<T> AsRef<NonEmpty<[T]>> for NonEmptyVec<T> {
fn as_ref(&self) -> &NonEmpty<[T]> {
self.as_non_empty_slice()
}
}
impl<T> AsMut<NonEmpty<[T]>> for NonEmptyVec<T> {
fn as_mut(&mut self) -> &mut NonEmpty<[T]> {
self.as_mut_non_empty_slice()
}
}
impl<T> core::borrow::Borrow<NonEmpty<[T]>> for NonEmptyVec<T> {
fn borrow(&self) -> &NonEmpty<[T]> {
self.as_non_empty_slice()
}
}
impl<T> core::borrow::BorrowMut<NonEmpty<[T]>> for NonEmptyVec<T> {
fn borrow_mut(&mut self) -> &mut NonEmpty<[T]> {
self.as_mut_non_empty_slice()
}
}
impl<T> core::borrow::Borrow<[T]> for NonEmptyVec<T> {
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<T> core::borrow::BorrowMut<[T]> for NonEmptyVec<T> {
fn borrow_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T> From<NonEmpty<Vec<T>>> for NonEmptyVec<T> {
fn from(value: NonEmpty<Vec<T>>) -> Self {
unsafe { Self::from_vec_unchecked(value.into_inner()) }
}
}
impl<T> From<NonEmptyVec<T>> for NonEmpty<Vec<T>> {
fn from(value: NonEmptyVec<T>) -> Self {
value.into_non_empty()
}
}
impl<T> From<NonEmptyVec<T>> for Vec<T> {
fn from(value: NonEmptyVec<T>) -> Self {
value.into_vec()
}
}
impl<T> TryFrom<Vec<T>> for NonEmptyVec<T> {
type Error = EmptyCollectionError;
fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
Self::from_vec(value).ok_or(EmptyCollectionError)
}
}
impl<T> crate::traits::FromInner for NonEmptyVec<T> {
type Inner = Vec<T>;
unsafe fn from_inner(inner: Self::Inner) -> Self {
Self::from_vec_unchecked(inner)
}
}
impl<T> crate::iter::FromNonEmptyIterator<T> for NonEmptyVec<T> {
fn from_non_empty_iter<I: crate::iter::NonEmptyIntoIter<Item = T>>(iter: I) -> Self {
crate::iter::from_iter_spec(iter)
}
}
impl<T> IntoIterator for NonEmptyVec<T> {
type Item = T;
type IntoIter = alloc::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.into_vec().into_iter()
}
}
impl<T> crate::iter::NonEmptyIntoIter for NonEmptyVec<T> {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
let mut iter = self.into_iter();
let first = unsafe { iter.next().unwrap_unchecked() };
(first, iter)
}
}
impl<'a, T> IntoIterator for &'a NonEmptyVec<T> {
type Item = &'a T;
type IntoIter = core::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().into_iter()
}
}
impl<'a, T> crate::iter::NonEmptyIntoIter for &'a NonEmptyVec<T> {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
unsafe { crate::iter::into_first_and_remaining(self) }
}
}
impl<'a, T> IntoIterator for &'a mut NonEmptyVec<T> {
type Item = &'a mut T;
type IntoIter = core::slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().into_iter()
}
}
impl<'a, T> crate::iter::NonEmptyIntoIter for &'a mut NonEmptyVec<T> {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
unsafe { crate::iter::into_first_and_remaining(self) }
}
}
unsafe impl<T> crate::WellBehavedCollection for NonEmptyVec<T> {}
trait NonZeroUsizeExt: Sized {
fn if_less_than(self, rhs: usize) -> Option<NonZeroUsize>;
}
impl NonZeroUsizeExt for NonZeroUsize {
fn if_less_than(self, rhs: usize) -> Option<NonZeroUsize> {
if usize::from(self) < rhs {
Some(unsafe { NonZeroUsize::new_unchecked(rhs) })
} else {
None
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum RemoveError {
IndexOutOfBounds {
index: NonZeroUsize,
len: NonZeroUsize,
},
WouldBecomeEmpty,
Both {
index: NonZeroUsize,
len: NonZeroUsize,
},
}
impl RemoveError {
pub fn is_oob(&self) -> bool {
matches!(self, RemoveError::IndexOutOfBounds { .. } | RemoveError::Both { .. })
}
pub fn is_would_become_empty(&self) -> bool {
matches!(self, RemoveError::WouldBecomeEmpty | RemoveError::Both { .. })
}
}
impl fmt::Display for RemoveError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RemoveError::IndexOutOfBounds { index, len } => {
write!(f, "the index {} is not smaller than length {}", index, len)
},
RemoveError::Both { index, len } => {
write!(f, "the collection would become empty and the index {} is not smaller than length {}", index, len)
},
RemoveError::WouldBecomeEmpty => {
write!(f, "the collection would become empty")
}
}
}
}
crate::error::if_std_error! {
impl crate::error::StdError for RemoveError {}
}