use crate::EnumIndex;
use crate::base::EnumArrayHelper;
use crate::base::EnumSetHelper;
use crate::base::EnumSize;
use crate::iter::EnumSliceIter;
use crate::iter::EnumSliceIterMut;
use crate::opt_map::EnumOptionMap;
use crate::sub_base::RawSizeWord;
use std::convert::TryFrom;
use std::fmt;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter;
use std::mem;
use std::ops::{Index, IndexMut};
use std::ptr;
pub struct EnumVec<T: EnumArrayHelper<V>, V> {
pub(crate) len: T::Word,
pub(crate) data: T::PartialArray,
}
impl<T: EnumArrayHelper<V>, V> EnumVec<T, V> {
pub fn new() -> Self {
EnumVec {
len: T::Word::ZERO,
data: T::new_partial(),
}
}
pub fn new_with<F>(size: EnumSize<T>, mut f: F) -> Self
where
F: FnMut(T) -> V,
{
let mut vec = Self::new();
for key in size.iter() {
let _ = vec.try_push(f(key));
}
vec
}
#[inline]
pub fn as_slice(&self) -> &[V] {
unsafe {
hint_assert!(
self.len <= T::SIZE_WORD,
"Length out of bounds: {:?} > {:?}",
self.len,
T::SIZE
);
let inited =
T::partial_slice(&self.data).get_unchecked(0..self.len.as_());
&*(inited as *const [std::mem::MaybeUninit<V>] as *const [V])
}
}
#[inline]
pub fn as_slice_mut(&mut self) -> &mut [V] {
unsafe {
hint_assert!(
self.len <= T::SIZE_WORD,
"Length out of bounds: {:?} > {:?}",
self.len,
T::SIZE
);
let inited = T::partial_slice_mut(&mut self.data)
.get_unchecked_mut(0..self.len.as_());
&mut *(inited as *mut [std::mem::MaybeUninit<V>] as *mut [V])
}
}
#[inline]
pub fn get_by_index(&self, index: EnumIndex<T>) -> Option<&V> {
self.as_slice().get(index.into_usize())
}
#[inline]
pub fn get(&self, key: T) -> Option<&V> {
self.get_by_index(key.into())
}
#[inline]
pub fn get_by_index_mut(&mut self, index: EnumIndex<T>) -> Option<&mut V> {
self.as_slice_mut().get_mut(index.into_usize())
}
#[inline]
pub fn get_mut(&mut self, key: T) -> Option<&mut V> {
self.get_by_index_mut(key.into())
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == T::Word::ZERO
}
#[inline]
pub fn is_full(&self) -> bool {
self.len == T::SIZE_WORD
}
#[inline]
pub fn contains_index(&self, index: EnumIndex<T>) -> bool {
index.into_word() < self.len
}
#[inline]
pub fn contains(&self, value: T) -> bool {
value.into_word() < self.len
}
#[inline]
pub fn size(&self) -> EnumSize<T> {
unsafe { EnumSize::from_word_unchecked(self.len) }
}
#[inline]
pub fn swap_by_index(&mut self, a: EnumIndex<T>, b: EnumIndex<T>) {
self.as_slice_mut().swap(a.into_usize(), b.into_usize())
}
#[inline]
pub fn swap(&mut self, a: T, b: T) {
self.swap_by_index(a.into(), b.into())
}
pub fn swap_remove_at_index(&mut self, index: EnumIndex<T>) -> Option<V> {
if index.into_word() < self.len {
let slice = T::partial_slice_mut(&mut self.data);
self.len = self.len.dec();
let idx = index.into_usize();
unsafe {
let value = slice[idx].assume_init_read();
if idx != self.len.as_() {
slice[idx].write(slice[self.len.as_()].assume_init_read());
}
Some(value)
}
} else {
None
}
}
pub fn swap_remove(&mut self, key: T) -> Option<V> {
self.swap_remove_at_index(key.into())
}
pub fn remove_at_index(&mut self, index: EnumIndex<T>) -> Option<V> {
if index.into_word() < self.len {
let slice = T::partial_slice_mut(&mut self.data);
let idx = index.into_usize();
let value = unsafe {
let value = slice[idx].assume_init_read();
let ptr = slice.as_mut_ptr().add(idx);
ptr::copy(ptr.add(1), ptr, self.len.as_() - idx - 1);
value
};
self.len = self.len.dec();
Some(value)
} else {
None
}
}
pub fn remove(&mut self, key: T) -> Option<V> {
self.remove_at_index(key.into())
}
pub fn clear(&mut self) {
for cell in
T::partial_slice_mut(&mut self.data)[0..self.len.as_()].iter_mut()
{
unsafe { cell.assume_init_drop() };
}
self.len = T::Word::ZERO;
}
pub fn try_push(&mut self, value: V) -> Result<(), V> {
let len = self.len.as_();
if len >= T::SIZE {
return Err(value);
}
T::partial_slice_mut(&mut self.data)[len] =
mem::MaybeUninit::<V>::new(value);
self.len = self.len.inc();
Ok(())
}
pub fn pop(&mut self) -> Option<V> {
if self.len == T::Word::ZERO {
None
} else {
let i = self.len.as_() - 1;
let cell = &T::partial_slice_mut(&mut self.data)[i];
self.len = self.len.dec();
Some(unsafe { cell.assume_init_read() })
}
}
#[inline]
pub fn iter(&self) -> EnumSliceIter<'_, T, V> {
EnumSliceIter {
_phantom: Default::default(),
word: T::Word::ZERO,
iter: self.as_slice().iter(),
}
}
#[inline]
pub fn iter_mut(&mut self) -> EnumSliceIterMut<'_, T, V> {
EnumSliceIterMut {
_phantom: Default::default(),
word: T::Word::ZERO,
iter: self.as_slice_mut().iter_mut(),
}
}
}
impl<T: EnumArrayHelper<V> + Debug, V: Debug> Debug for EnumVec<T, V> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_map().entries(self.iter()).finish()
}
}
impl<T: EnumArrayHelper<V>, V> Default for EnumVec<T, V> {
fn default() -> Self {
Self::new()
}
}
impl<T: EnumArrayHelper<V>, V> Drop for EnumVec<T, V> {
fn drop(&mut self) {
self.clear()
}
}
impl<T: EnumArrayHelper<V>, V: Clone> Clone for EnumVec<T, V> {
fn clone(&self) -> Self {
let mut clone = Self::new();
for value in self.as_slice() {
let _ = clone.try_push(value.clone());
}
clone
}
}
impl<T: EnumArrayHelper<V>, V: PartialEq> PartialEq for EnumVec<T, V> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: EnumArrayHelper<V>, V: Eq> Eq for EnumVec<T, V> {}
impl<T: EnumArrayHelper<V>, V: Hash> Hash for EnumVec<T, V> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl<T: EnumArrayHelper<V>, V> Index<EnumIndex<T>> for EnumVec<T, V> {
type Output = V;
#[inline]
fn index(&self, index: EnumIndex<T>) -> &V {
&self.as_slice()[index.into_usize()]
}
}
impl<T: EnumArrayHelper<V>, V> Index<T> for EnumVec<T, V> {
type Output = V;
#[inline]
fn index(&self, key: T) -> &V {
&self[EnumIndex::from_value(key)]
}
}
impl<T: EnumArrayHelper<V>, V> IndexMut<EnumIndex<T>> for EnumVec<T, V> {
#[inline]
fn index_mut(&mut self, index: EnumIndex<T>) -> &mut V {
&mut self.as_slice_mut()[index.into_usize()]
}
}
impl<T: EnumArrayHelper<V>, V> IndexMut<T> for EnumVec<T, V> {
#[inline]
fn index_mut(&mut self, key: T) -> &mut V {
&mut self[EnumIndex::from_value(key)]
}
}
impl<T: EnumArrayHelper<V>, V> iter::FromIterator<V> for EnumVec<T, V> {
fn from_iter<I: iter::IntoIterator<Item = V>>(iter: I) -> Self {
let mut c = EnumVec::<T, V>::new();
for i in iter {
if c.try_push(i).is_err() {
break;
}
}
c
}
}
impl<T: EnumArrayHelper<V>, V> iter::Extend<V> for EnumVec<T, V> {
fn extend<I: iter::IntoIterator<Item = V>>(&mut self, iter: I) {
for i in iter {
if self.try_push(i).is_err() {
break;
}
}
}
}
impl<'a, T: EnumArrayHelper<V>, V> iter::IntoIterator for &'a EnumVec<T, V> {
type Item = (T, &'a V);
type IntoIter = EnumSliceIter<'a, T, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T: EnumArrayHelper<V>, V> iter::IntoIterator
for &'a mut EnumVec<T, V>
{
type Item = (T, &'a mut V);
type IntoIter = EnumSliceIterMut<'a, T, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T: EnumArrayHelper<V>, V> iter::IntoIterator for EnumVec<T, V> {
type Item = V;
type IntoIter = EnumVecIntoIter<T, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
let mut this = mem::ManuallyDrop::new(self);
let len = this.len;
let data = mem::replace(&mut this.data, T::new_partial());
EnumVecIntoIter {
data,
front: T::Word::ZERO,
back: len,
}
}
}
pub struct EnumVecIntoIter<T: EnumArrayHelper<V>, V> {
data: T::PartialArray,
front: T::Word,
back: T::Word,
}
impl<T: EnumArrayHelper<V>, V> Iterator for EnumVecIntoIter<T, V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
if self.front == self.back {
return None;
}
let value = unsafe {
T::partial_slice_mut(&mut self.data)[self.front.as_()].assume_init_read()
};
self.front = self.front.inc();
Some(value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.back.as_() - self.front.as_();
(remaining, Some(remaining))
}
}
impl<T: EnumArrayHelper<V>, V> DoubleEndedIterator for EnumVecIntoIter<T, V> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.front == self.back {
return None;
}
self.back = self.back.dec();
let value = unsafe {
T::partial_slice_mut(&mut self.data)[self.back.as_()].assume_init_read()
};
Some(value)
}
}
impl<T: EnumArrayHelper<V>, V> ExactSizeIterator for EnumVecIntoIter<T, V> {}
impl<T: EnumArrayHelper<V>, V> iter::FusedIterator for EnumVecIntoIter<T, V> {}
impl<T: EnumArrayHelper<V>, V> Drop for EnumVecIntoIter<T, V> {
fn drop(&mut self) {
let slice = T::partial_slice_mut(&mut self.data);
for cell in slice[self.front.as_()..self.back.as_()].iter_mut() {
unsafe { cell.assume_init_drop() };
}
}
}
impl<T: EnumArrayHelper<V> + EnumSetHelper<u8>, V> TryFrom<EnumOptionMap<T, V>>
for EnumVec<T, V>
{
type Error = ();
fn try_from(from: EnumOptionMap<T, V>) -> Result<Self, Self::Error> {
match from.is_vec() {
Some(size) => Ok(EnumVec {
len: size.into_word(),
data: from.into_partial(),
}),
None => Err(()),
}
}
}