#[allow(unused_imports)]
use crate::StaticMap;
use {
crate::Linearize,
core::{iter::Enumerate, marker::PhantomData, ops::Range},
};
pub struct Iter<'a, L, T>
where
L: Linearize,
{
iter: Range<usize>,
storage: *const T,
_phantom: PhantomData<fn() -> (L, &'a T)>,
}
impl<'a, L, T> Iter<'a, L, T>
where
L: Linearize,
T: 'a,
{
pub(super) fn new(storage: &'a L::Storage<T>) -> Self {
Self {
iter: 0..L::LENGTH,
storage: <L::Storage<T> as AsRef<[T]>>::as_ref(storage).as_ptr(),
_phantom: Default::default(),
}
}
unsafe fn item(storage: *const T, i: usize) -> (L, &'a T) {
let k = L::from_linear_unchecked(i);
let v = &*storage.add(i);
(k, v)
}
}
impl<'a, L, T> Clone for Iter<'a, L, T>
where
L: Linearize,
T: 'a,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
storage: self.storage,
_phantom: Default::default(),
}
}
}
macro_rules! impl_iter {
($name:ident, $ref_type:ty) => {
impl<'a, L, T> Iterator for $name<'a, L, T>
where
L: Linearize,
T: 'a,
{
type Item = (L, $ref_type);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|i| unsafe {
Self::item(self.storage, i)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
self.iter.last().map(|i| unsafe {
Self::item(self.storage, i)
})
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(|i| unsafe {
Self::item(self.storage, i)
})
}
}
impl<'a, L, T> ExactSizeIterator for $name<'a, L, T>
where
L: Linearize,
T: 'a,
{
}
impl<'a, L, T> DoubleEndedIterator for $name<'a, L, T>
where
L: Linearize,
T: 'a,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|i| unsafe {
Self::item(self.storage, i)
})
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth_back(n).map(|i| unsafe {
Self::item(self.storage, i)
})
}
}
};
}
impl_iter!(Iter, &'a T);
pub struct IterMut<'a, L, T>
where
L: Linearize,
{
iter: Range<usize>,
storage: *mut T,
_phantom: PhantomData<fn() -> (L, &'a mut T)>,
}
impl<'a, L, T> IterMut<'a, L, T>
where
L: Linearize,
T: 'a,
{
pub(super) fn new(storage: &'a mut L::Storage<T>) -> Self {
Self {
iter: 0..L::LENGTH,
storage: <L::Storage<T> as AsMut<[T]>>::as_mut(storage).as_mut_ptr(),
_phantom: Default::default(),
}
}
unsafe fn item(storage: *mut T, i: usize) -> (L, &'a mut T) {
let k = L::from_linear_unchecked(i);
let v = &mut *storage.add(i);
(k, v)
}
}
impl_iter!(IterMut, &'a mut T);
pub struct IntoIter<L, T>
where
L: Linearize,
{
iter: Enumerate<<<L as Linearize>::Storage<T> as IntoIterator>::IntoIter>,
}
impl<L, T> IntoIter<L, T>
where
L: Linearize,
{
pub(super) fn new(storage: L::Storage<T>) -> Self {
Self {
iter: <L::Storage<T> as IntoIterator>::into_iter(storage).enumerate(),
}
}
unsafe fn key(i: usize) -> L {
unsafe {
L::from_linear_unchecked(i)
}
}
}
impl<L, T> Iterator for IntoIter<L, T>
where
L: Linearize,
{
type Item = (L, T);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(i, v)| {
let k = unsafe {
Self::key(i)
};
(k, v)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
#[expect(clippy::double_ended_iterator_last)]
self.iter.last().map(|(i, v)| {
let k = unsafe {
Self::key(i)
};
(k, v)
})
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(|(i, v)| {
let k = unsafe {
Self::key(i)
};
(k, v)
})
}
}
impl<L, T> ExactSizeIterator for IntoIter<L, T> where L: Linearize {}
impl<L, T> DoubleEndedIterator for IntoIter<L, T>
where
L: Linearize,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|(i, v)| {
let k = unsafe {
Self::key(i)
};
(k, v)
})
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth_back(n).map(|(i, v)| {
let k = unsafe {
Self::key(i)
};
(k, v)
})
}
}
pub struct IntoValues<L, T>
where
L: Linearize,
{
iter: <<L as Linearize>::Storage<T> as IntoIterator>::IntoIter,
}
impl<L, T> IntoValues<L, T>
where
L: Linearize,
{
pub(super) fn new(storage: L::Storage<T>) -> Self {
Self {
iter: <L::Storage<T> as IntoIterator>::into_iter(storage),
}
}
}
impl<L, T> Iterator for IntoValues<L, T>
where
L: Linearize,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
self.iter.last()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n)
}
}
impl<L, T> ExactSizeIterator for IntoValues<L, T> where L: Linearize {}
impl<L, T> DoubleEndedIterator for IntoValues<L, T>
where
L: Linearize,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth_back(n)
}
}