use core::fmt::{self, Debug, Formatter};
use core::intrinsics::assume;
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
use core::marker::{PhantomData, Send, Sync};
use core::mem::{replace, size_of, MaybeUninit};
use core::ptr;
use core::slice::{from_raw_parts, from_raw_parts_mut};
use crate::utils::{distance_between, zst_ptr_add, zst_ptr_add_mut};
use crate::StaticVec;
#[cfg(feature = "std")]
use alloc::string::String;
#[cfg(feature = "std")]
use alloc::format;
pub struct StaticVecIterConst<'a, T: 'a, const N: usize> {
pub(crate) start: *const T,
pub(crate) end: *const T,
pub(crate) marker: PhantomData<&'a T>,
}
pub struct StaticVecIterMut<'a, T: 'a, const N: usize> {
pub(crate) start: *mut T,
pub(crate) end: *mut T,
pub(crate) marker: PhantomData<&'a mut T>,
}
pub struct StaticVecIntoIter<T, const N: usize> {
pub(crate) start: usize,
pub(crate) end: usize,
pub(crate) data: MaybeUninit<[T; N]>,
}
pub struct StaticVecDrain<'a, T: 'a, const N: usize> {
pub(crate) start: usize,
pub(crate) length: usize,
pub(crate) iter: StaticVecIterConst<'a, T, N>,
pub(crate) vec: *mut StaticVec<T, N>,
}
pub struct StaticVecSplice<T, I: Iterator<Item = T>, const N: usize> {
pub(crate) start: usize,
pub(crate) end: usize,
pub(crate) replace_with: I,
pub(crate) vec: *mut StaticVec<T, N>,
}
impl<'a, T: 'a, const N: usize> StaticVecIterConst<'a, T, N> {
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline(always)]
pub fn bounds_to_string(&self) -> String
where T: Debug {
match self.len() {
0 => String::from("Empty iterator!"),
_ => unsafe {
format!(
"Current value of element at `start`: {:?}\nCurrent value of element at `end`: {:?}",
&*self.start,
&*self.end.offset(-1)
)
},
}
}
#[inline(always)]
pub const fn as_slice(&self) -> &'a [T] {
unsafe { from_raw_parts(self.start, distance_between(self.end, self.start)) }
}
}
impl<'a, T: 'a, const N: usize> Iterator for StaticVecIterConst<'a, T, N> {
type Item = &'a T;
#[inline(always)]
fn next(&mut self) -> Option<&'a T> {
unsafe {
assume(!self.start.is_null());
if size_of::<T>() != 0 {
assume(!self.end.is_null());
}
match distance_between(self.end, self.start) {
0 => None,
_ => {
let res = Some(&*self.start);
match size_of::<T>() {
0 => self.end = (self.end as *const u8).wrapping_offset(-1) as *const T,
_ => self.start = self.start.offset(1),
}
res
}
}
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = distance_between(self.end, self.start);
(len, Some(len))
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
#[inline(always)]
fn nth(&mut self, n: usize) -> Option<&'a T> {
if n >= distance_between(self.end, self.start) {
None
} else {
unsafe {
match size_of::<T>() {
0 => {
self.end = (self.end as *const u8).wrapping_offset(-(n as isize)) as *const T;
self.start = (self.start as usize + 1) as *const T;
Some(&*self.start)
}
_ => {
let res = self.start.add(n);
self.start = res.offset(1);
Some(&*res)
}
}
}
}
}
#[inline(always)]
fn last(mut self) -> Option<&'a T> {
self.next_back()
}
#[inline(always)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> &'a T {
&*self.start.add(idx)
}
}
impl<'a, T: 'a, const N: usize> DoubleEndedIterator for StaticVecIterConst<'a, T, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<&'a T> {
unsafe {
assume(!self.start.is_null());
if size_of::<T>() != 0 {
assume(!self.end.is_null());
}
match distance_between(self.end, self.start) {
0 => None,
_ => {
self.end = match size_of::<T>() {
0 => (self.end as usize - 1) as *const T,
_ => self.end.offset(-1),
};
Some(&*self.end)
}
}
}
}
#[inline(always)]
fn nth_back(&mut self, n: usize) -> Option<&'a T> {
if n >= distance_between(self.end, self.start) {
None
} else {
unsafe {
self.end = match size_of::<T>() {
0 => (self.end as *const u8).wrapping_offset(-((n as isize) + 1)) as *const T,
_ => self.end.offset(-((n as isize) + 1)),
};
Some(&*self.end)
}
}
}
}
impl<'a, T: 'a, const N: usize> const ExactSizeIterator for StaticVecIterConst<'a, T, N> {
#[inline(always)]
fn len(&self) -> usize {
distance_between(self.end, self.start)
}
#[inline(always)]
fn is_empty(&self) -> bool {
distance_between(self.end, self.start) == 0
}
}
impl<'a, T: 'a, const N: usize> const FusedIterator for StaticVecIterConst<'a, T, N> {}
unsafe impl<'a, T: 'a, const N: usize> const TrustedLen for StaticVecIterConst<'a, T, N> {}
#[doc(hidden)]
unsafe impl<'a, T: 'a, const N: usize> const TrustedRandomAccessNoCoerce
for StaticVecIterConst<'a, T, N>
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
fn size(&self) -> usize {
distance_between(self.end, self.start)
}
}
unsafe impl<'a, T: 'a + Sync, const N: usize> const Sync for StaticVecIterConst<'a, T, N> {}
unsafe impl<'a, T: 'a + Sync, const N: usize> const Send for StaticVecIterConst<'a, T, N> {}
impl<'a, T: 'a, const N: usize> Clone for StaticVecIterConst<'a, T, N> {
#[inline(always)]
fn clone(&self) -> Self {
Self {
start: self.start,
end: self.end,
marker: self.marker,
}
}
}
impl<'a, T: 'a + Debug, const N: usize> Debug for StaticVecIterConst<'a, T, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("StaticVecIterConst")
.field(&self.as_slice())
.finish()
}
}
impl<'a, T: 'a, const N: usize> StaticVecIterMut<'a, T, N> {
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline(always)]
pub fn bounds_to_string(&self) -> String
where T: Debug {
match self.len() {
0 => String::from("Empty iterator!"),
_ => unsafe {
format!(
"Current value of element at `start`: {:?}\nCurrent value of element at `end`: {:?}",
&*self.start,
&*self.end.offset(-1)
)
},
}
}
#[inline(always)]
pub const fn as_slice(&self) -> &[T] {
unsafe { from_raw_parts(self.start, distance_between(self.end, self.start)) }
}
}
impl<'a, T: 'a, const N: usize> Iterator for StaticVecIterMut<'a, T, N> {
type Item = &'a mut T;
#[inline(always)]
fn next(&mut self) -> Option<&'a mut T> {
unsafe {
assume(!self.start.is_null());
if size_of::<T>() != 0 {
assume(!self.end.is_null());
}
match distance_between(self.end, self.start) {
0 => None,
_ => {
let res = Some(&mut *self.start);
match size_of::<T>() {
0 => self.end = (self.end as *mut u8).wrapping_offset(-1) as *mut T,
_ => self.start = self.start.offset(1),
}
res
}
}
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = distance_between(self.end, self.start);
(len, Some(len))
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
#[inline(always)]
fn nth(&mut self, n: usize) -> Option<&'a mut T> {
if n >= distance_between(self.end, self.start) {
None
} else {
unsafe {
match size_of::<T>() {
0 => {
self.end = (self.end as *mut u8).wrapping_offset(-(n as isize)) as *mut T;
self.start = (self.start as usize + 1) as *mut T;
Some(&mut *self.start)
}
_ => {
let res = self.start.add(n);
self.start = res.offset(1);
Some(&mut *res)
}
}
}
}
}
#[inline(always)]
fn last(mut self) -> Option<&'a mut T> {
self.next_back()
}
#[inline(always)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> &'a mut T {
&mut *self.start.add(idx)
}
}
impl<'a, T: 'a, const N: usize> DoubleEndedIterator for StaticVecIterMut<'a, T, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<&'a mut T> {
unsafe {
assume(!self.start.is_null());
if size_of::<T>() != 0 {
assume(!self.end.is_null());
}
match distance_between(self.end, self.start) {
0 => None,
_ => {
self.end = match size_of::<T>() {
0 => (self.end as usize - 1) as *mut T,
_ => self.end.offset(-1),
};
Some(&mut *self.end)
}
}
}
}
#[inline(always)]
fn nth_back(&mut self, n: usize) -> Option<&'a mut T> {
if n >= distance_between(self.end, self.start) {
None
} else {
unsafe {
self.end = match size_of::<T>() {
0 => (self.end as *mut u8).wrapping_offset(-((n as isize) + 1)) as *mut T,
_ => self.end.offset(-((n as isize) + 1)),
};
Some(&mut *self.end)
}
}
}
}
impl<'a, T: 'a, const N: usize> const ExactSizeIterator for StaticVecIterMut<'a, T, N> {
#[inline(always)]
fn len(&self) -> usize {
distance_between(self.end, self.start)
}
#[inline(always)]
fn is_empty(&self) -> bool {
distance_between(self.end, self.start) == 0
}
}
impl<'a, T: 'a, const N: usize> const FusedIterator for StaticVecIterMut<'a, T, N> {}
unsafe impl<'a, T: 'a, const N: usize> const TrustedLen for StaticVecIterMut<'a, T, N> {}
#[doc(hidden)]
unsafe impl<'a, T: 'a, const N: usize> const TrustedRandomAccessNoCoerce
for StaticVecIterMut<'a, T, N>
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
fn size(&self) -> usize {
distance_between(self.end, self.start)
}
}
unsafe impl<'a, T: 'a + Sync, const N: usize> const Sync for StaticVecIterMut<'a, T, N> {}
unsafe impl<'a, T: 'a + Send, const N: usize> const Send for StaticVecIterMut<'a, T, N> {}
impl<'a, T: 'a + Debug, const N: usize> Debug for StaticVecIterMut<'a, T, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("StaticVecIterMut")
.field(&self.as_slice())
.finish()
}
}
impl<T, const N: usize> StaticVecIntoIter<T, N> {
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline(always)]
pub fn bounds_to_string(&self) -> String
where T: Debug {
match self.len() {
0 => String::from("Empty iterator!"),
_ => unsafe {
format!(
"Current value of element at `start`: {:?}\nCurrent value of element at `end`: {:?}",
&*StaticVec::first_ptr(&self.data).add(self.start),
&*StaticVec::first_ptr(&self.data).add(self.end - 1)
)
},
}
}
#[inline(always)]
pub const fn as_slice(&self) -> &[T] {
let start_at = unsafe {
match size_of::<T>() {
0 => zst_ptr_add(StaticVec::first_ptr(&self.data), self.start),
_ => StaticVec::first_ptr(&self.data).add(self.start),
}
};
unsafe { from_raw_parts(start_at, self.end - self.start) }
}
#[inline(always)]
pub const fn as_mut_slice(&mut self) -> &mut [T] {
let start_at = unsafe {
match size_of::<T>() {
0 => zst_ptr_add_mut(StaticVec::first_ptr_mut(&mut self.data), self.start),
_ => StaticVec::first_ptr_mut(&mut self.data).add(self.start),
}
};
unsafe { from_raw_parts_mut(start_at, self.end - self.start) }
}
}
impl<T, const N: usize> Iterator for StaticVecIntoIter<T, N> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
match self.end - self.start {
0 => None,
_ => {
let res = match size_of::<T>() {
0 => Some(unsafe { zst_ptr_add(StaticVec::first_ptr(&self.data), self.start).read() }),
_ => Some(unsafe { StaticVec::first_ptr(&self.data).add(self.start).read() }),
};
self.start += 1;
res
}
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.end - self.start;
(len, Some(len))
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
#[inline(always)]
fn nth(&mut self, n: usize) -> Option<T> {
if n >= self.len() {
None
} else {
unsafe {
let old_start = self.start;
let res_index = old_start + n;
let res = match size_of::<T>() {
0 => zst_ptr_add(StaticVec::first_ptr(&self.data), res_index),
_ => StaticVec::first_ptr(&self.data).add(res_index),
};
let drop_at = match size_of::<T>() {
0 => zst_ptr_add_mut(StaticVec::first_ptr_mut(&mut self.data), old_start),
_ => StaticVec::first_ptr_mut(&mut self.data).add(old_start),
};
ptr::drop_in_place(from_raw_parts_mut(drop_at, res_index - old_start));
self.start = res_index + 1;
Some(res.read())
}
}
}
#[inline(always)]
fn last(mut self) -> Option<T> {
self.next_back()
}
#[inline(always)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
where Self: TrustedRandomAccessNoCoerce {
match size_of::<T>() {
0 => zst_ptr_add(StaticVec::first_ptr(&self.data), idx).read(),
_ => StaticVec::first_ptr(&self.data).add(idx).read(),
}
}
}
impl<T, const N: usize> DoubleEndedIterator for StaticVecIntoIter<T, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<T> {
match self.end - self.start {
0 => None,
_ => {
self.end -= 1;
match size_of::<T>() {
0 => Some(unsafe { zst_ptr_add(StaticVec::first_ptr(&self.data), self.end).read() }),
_ => Some(unsafe { StaticVec::first_ptr(&self.data).add(self.end).read() }),
}
}
}
}
#[inline(always)]
fn nth_back(&mut self, n: usize) -> Option<T> {
if n >= self.len() {
None
} else {
let old_end = self.end;
let res_index = old_end - n;
self.end = res_index - 1;
unsafe {
let drop_at = match size_of::<T>() {
0 => zst_ptr_add_mut(StaticVec::first_ptr_mut(&mut self.data), res_index),
_ => StaticVec::first_ptr_mut(&mut self.data).add(res_index),
};
ptr::drop_in_place(from_raw_parts_mut(drop_at, old_end - res_index));
match size_of::<T>() {
0 => Some(zst_ptr_add(StaticVec::first_ptr(&self.data), self.end).read()),
_ => Some(StaticVec::first_ptr(&self.data).add(self.end).read()),
}
}
}
}
}
impl<T, const N: usize> const ExactSizeIterator for StaticVecIntoIter<T, N> {
#[inline(always)]
fn len(&self) -> usize {
self.end - self.start
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.end - self.start == 0
}
}
impl<T, const N: usize> const FusedIterator for StaticVecIntoIter<T, N> {}
unsafe impl<T, const N: usize> const TrustedLen for StaticVecIntoIter<T, N> {}
#[doc(hidden)]
unsafe impl<T: Copy, const N: usize> const TrustedRandomAccessNoCoerce for StaticVecIntoIter<T, N> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
fn size(&self) -> usize {
self.end - self.start
}
}
unsafe impl<T: Sync, const N: usize> const Sync for StaticVecIntoIter<T, N> {}
unsafe impl<T: Send, const N: usize> const Send for StaticVecIntoIter<T, N> {}
impl<T: Clone, const N: usize> Clone for StaticVecIntoIter<T, N> {
#[inline(always)]
fn clone(&self) -> StaticVecIntoIter<T, N> {
Self {
start: self.start,
end: self.end,
data: {
let mut data = MaybeUninit::<[T; N]>::uninit();
let new_data_ptr = data.as_mut_ptr() as *mut T;
let self_data_ptr = self.data.as_ptr() as *const T;
unsafe {
assume(!new_data_ptr.is_null());
assume(!self_data_ptr.is_null());
for i in self.start..self.end {
new_data_ptr.add(i).write((&*self_data_ptr.add(i)).clone());
}
}
data
},
}
}
}
impl<T: Debug, const N: usize> Debug for StaticVecIntoIter<T, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("StaticVecIntoIter")
.field(&self.as_slice())
.finish()
}
}
impl<T, const N: usize> Drop for StaticVecIntoIter<T, N> {
#[inline(always)]
fn drop(&mut self) {
let item_count = self.end - self.start;
let drop_at = match size_of::<T>() {
0 => zst_ptr_add_mut(StaticVec::first_ptr_mut(&mut self.data), self.start),
_ => unsafe { StaticVec::first_ptr_mut(&mut self.data).add(self.start) },
};
match item_count {
0 => (),
_ => unsafe { ptr::drop_in_place(from_raw_parts_mut(drop_at, item_count)) },
}
}
}
impl<'a, T: 'a, const N: usize> StaticVecDrain<'a, T, N> {
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline(always)]
pub fn bounds_to_string(&self) -> String
where T: Debug {
self.iter.bounds_to_string()
}
#[inline(always)]
pub const fn as_slice(&self) -> &[T] {
self.iter.as_slice()
}
}
impl<'a, T: 'a, const N: usize> Iterator for StaticVecDrain<'a, T, N> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
self
.iter
.next()
.map(|val| unsafe { (val as *const T).read() })
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
#[inline(always)]
fn last(mut self) -> Option<T> {
self.next_back()
}
#[inline(always)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
where Self: TrustedRandomAccessNoCoerce {
match size_of::<T>() {
0 => zst_ptr_add(self.as_slice().as_ptr(), idx).read(),
_ => self.as_slice().as_ptr().add(idx).read(),
}
}
}
impl<'a, T: 'a, const N: usize> DoubleEndedIterator for StaticVecDrain<'a, T, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<T> {
self
.iter
.next_back()
.map(|val| unsafe { (val as *const T).read() })
}
}
impl<'a, T: 'a, const N: usize> const ExactSizeIterator for StaticVecDrain<'a, T, N> {
#[inline(always)]
fn len(&self) -> usize {
self.iter.len()
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}
impl<'a, T: 'a, const N: usize> const FusedIterator for StaticVecDrain<'a, T, N> {}
unsafe impl<'a, T: 'a, const N: usize> const TrustedLen for StaticVecDrain<'a, T, N> {}
#[doc(hidden)]
unsafe impl<'a, T: Copy + 'a, const N: usize> const TrustedRandomAccessNoCoerce
for StaticVecDrain<'a, T, N>
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
fn size(&self) -> usize {
distance_between(self.iter.end, self.iter.start)
}
}
unsafe impl<'a, T: 'a + Sync, const N: usize> const Sync for StaticVecDrain<'a, T, N> {}
unsafe impl<'a, T: 'a + Send, const N: usize> const Send for StaticVecDrain<'a, T, N> {}
impl<'a, T: 'a + Debug, const N: usize> Debug for StaticVecDrain<'a, T, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("StaticVecDrain")
.field(&self.iter.as_slice())
.finish()
}
}
impl<'a, T: 'a, const N: usize> Drop for StaticVecDrain<'a, T, N> {
#[inline]
fn drop(&mut self) {
while let Some(_) = self.next() {}
let total_length = self.length;
if total_length > 0 {
unsafe {
let vec_ref = &mut *self.vec;
let start = vec_ref.length;
let tail = self.start;
vec_ref
.ptr_at_unchecked(tail)
.copy_to(vec_ref.mut_ptr_at_unchecked(start), total_length);
vec_ref.set_len(start + total_length);
}
}
}
}
impl<T, I: Iterator<Item = T>, const N: usize> Iterator for StaticVecSplice<T, I, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.end - self.start {
0 => None,
_ => match self.replace_with.next() {
Some(replace_with) => unsafe {
let removed = replace((&mut *self.vec).get_unchecked_mut(self.start), replace_with);
self.start += 1;
Some(removed)
},
None => unsafe {
let removed = (&mut *self.vec).remove_unchecked(self.start);
self.end -= 1;
Some(removed)
},
},
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
}
impl<T, I: Iterator<Item = T> + DoubleEndedIterator, const N: usize> DoubleEndedIterator
for StaticVecSplice<T, I, N>
{
#[inline]
fn next_back(&mut self) -> Option<T> {
match self.end - self.start {
0 => None,
_ => match self.replace_with.next_back() {
Some(replace_with) => unsafe {
let removed = replace(
(&mut *self.vec).get_unchecked_mut(self.end - 1),
replace_with,
);
self.end -= 1;
Some(removed)
},
None => unsafe {
let removed = (&mut *self.vec).remove_unchecked(self.end - 1);
self.end -= 1;
Some(removed)
},
},
}
}
}
impl<T, I: Iterator<Item = T>, const N: usize> const ExactSizeIterator
for StaticVecSplice<T, I, N>
{
#[inline(always)]
fn len(&self) -> usize {
self.end - self.start
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.end - self.start == 0
}
}
impl<T, I: Iterator<Item = T>, const N: usize> const FusedIterator for StaticVecSplice<T, I, N> {}
unsafe impl<T, I: Iterator<Item = T>, const N: usize> const TrustedLen
for StaticVecSplice<T, I, N>
{
}
unsafe impl<T: Sync, I: Iterator<Item = T>, const N: usize> const Sync
for StaticVecSplice<T, I, N>
{
}
unsafe impl<T: Send, I: Iterator<Item = T>, const N: usize> const Send
for StaticVecSplice<T, I, N>
{
}
impl<T: Debug, I: Iterator<Item = T>, const N: usize> Debug for StaticVecSplice<T, I, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
unsafe {
let items = from_raw_parts(
(&*self.vec).ptr_at_unchecked(self.start),
self.end - self.start,
);
f.debug_tuple("StaticVecSplice").field(&items).finish()
}
}
}
impl<T, I: Iterator<Item = T>, const N: usize> Drop for StaticVecSplice<T, I, N> {
#[inline]
fn drop(&mut self) {
while let Some(_) = self.next() {}
let vec_ref = unsafe { &mut *self.vec };
for replace_with in self.replace_with.by_ref() {
let old_length = vec_ref.length;
if old_length == N {
break;
}
let index = self.end;
unsafe {
let vec_ptr = vec_ref.mut_ptr_at_unchecked(index);
vec_ptr.copy_to(vec_ptr.offset(1), old_length - index);
vec_ptr.write(replace_with);
vec_ref.set_len(old_length + 1);
}
self.end += 1;
}
}
}