use core::num::NonZeroUsize;
use std::ops::{Index, IndexMut};
use std::vec::Vec;
use std::{mem, ptr, vec};
use crate::functor::Functor;
use crate::pure::Pure;
use crate::semigroup::Semigroup;
use crate::{
and_then_flat_map, apply_iter, flatmap_iter, higher, invariant_functor, semigroup_extend,
semigroupal_iter,
};
mod from;
mod iter;
mod partial_eq;
#[allow(clippy::len_without_is_empty)]
#[derive(Clone, Debug, Eq, Hash, PartialOrd, Ord)]
pub struct NEVec<T> {
pub head: T,
pub tail: Vec<T>,
}
impl<T> NEVec<T> {
#[inline]
pub const fn new(head: T) -> Self {
Self {
head,
tail: Vec::new(),
}
}
#[inline]
pub fn with_tail_capacity(head: T, tail_capacity: usize) -> Self {
Self {
head,
tail: Vec::with_capacity(tail_capacity),
}
}
#[inline]
pub fn from_elem(elem: T, n: NonZeroUsize) -> Self
where
T: Clone,
{
Self {
head: elem.clone(),
tail: vec![elem; n.get() - 1],
}
}
#[inline]
pub fn from_vec(mut vec: Vec<T>) -> Option<Self> {
if vec.is_empty() {
None
} else {
Some(Self {
head: vec.remove(0),
tail: vec,
})
}
}
#[inline]
pub fn from_slice(slice: &[T]) -> Option<Self>
where
T: Clone,
{
slice.split_first().map(|(h, t)| Self {
head: h.clone(),
tail: t.to_vec(),
})
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("swap_remove index (is {index}) should be < len (is {len})");
}
let dst = if index == 0 {
if self.tail.is_empty() {
non_empty_invariant_failed();
}
&mut self.head
} else {
if index >= self.len() {
assert_failed(index, self.len());
};
unsafe { self.tail.as_mut_ptr().add(index - 1) }
};
unsafe {
let result = ptr::read(dst);
let new_tail_len = self.tail.len() - 1;
ptr::copy(self.tail.as_ptr().add(new_tail_len), dst, 1);
self.tail.set_len(new_tail_len);
result
}
}
#[inline]
pub fn insert(&mut self, index: usize, element: T) {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("insertion index (is {index}) should be <= len (is {len})");
}
if index == 0 {
self.tail.insert(0, mem::replace(&mut self.head, element));
} else if index <= self.len() {
self.tail.insert(index - 1, element);
} else {
assert_failed(index, self.len());
}
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("removal index (is {index}) should be < len (is {len})");
}
if index == 0 {
if self.tail.is_empty() {
non_empty_invariant_failed();
}
mem::replace(&mut self.head, self.tail.remove(0))
} else if index < self.len() {
self.tail.remove(index - 1)
} else {
assert_failed(index, self.len());
}
}
#[inline]
pub fn len(&self) -> usize {
self.tail.len() + 1
}
#[inline]
pub fn first(&self) -> &T {
&self.head
}
#[inline]
pub fn first_mut(&mut self) -> &mut T {
&mut self.head
}
#[inline]
pub fn last(&self) -> &T {
self.tail.last().unwrap_or(&self.head)
}
#[inline]
pub fn last_mut(&mut self) -> &mut T {
self.tail.last_mut().unwrap_or(&mut self.head)
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index == 0 {
Some(&self.head)
} else {
self.tail.get(index - 1)
}
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index == 0 {
Some(&mut self.head)
} else {
self.tail.get_mut(index - 1)
}
}
#[inline]
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
let mut vec = Vec::with_capacity(self.len());
vec.push(self.head.clone());
vec.extend_from_slice(&self.tail);
vec
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
let mut vec = Vec::with_capacity(self.len());
vec.push(self.head);
vec.extend(self.tail);
vec
}
}
impl<T: Default> Default for NEVec<T> {
#[inline]
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T> Extend<T> for NEVec<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.tail.extend(iter);
}
}
impl<T> Index<usize> for NEVec<T> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
if index == 0 {
&self.head
} else {
&self.tail[index - 1]
}
}
}
impl<T> IndexMut<usize> for NEVec<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index == 0 {
&mut self.head
} else {
&mut self.tail[index - 1]
}
}
}
#[cold]
#[inline(never)]
fn non_empty_invariant_failed() -> ! {
panic!("NEVec cannot be empty");
}
#[macro_export]
macro_rules! ne_vec {
($head:expr) => (
$crate::data::ne_vec::NEVec::new($head)
);
($head:expr, $($tail:expr),* $(,)?) => (
$crate::data::ne_vec::NEVec {
head: $head,
tail: vec![$($tail),*],
}
);
($elem:expr; $n:expr) => (
$crate::data::ne_vec::NEVec::from_elem(
$elem,
core::num::NonZeroUsize::new($n).expect("NEVec cannot be empty"))
);
}
higher!(NEVec);
apply_iter!(NEVec);
flatmap_iter!(NEVec);
semigroupal_iter!(NEVec);
semigroup_extend!(NEVec);
invariant_functor!(NEVec<T>);
and_then_flat_map!(NEVec<T>);
impl<A, B> Functor<B> for NEVec<A> {
#[inline]
fn map(self, mut f: impl FnMut(A) -> B) -> NEVec<B> {
NEVec {
head: f(self.head),
tail: self.tail.map(f),
}
}
}
impl<T> Pure for NEVec<T> {
#[inline]
fn pure(x: T) -> Self {
NEVec::new(x)
}
}