use core::hint::unreachable_unchecked;
use core::marker::PhantomData;
use crate::arena::ActiveSlotRef;
use crate::arena::Arena;
use crate::arena::ArenaContainer;
use crate::arena::Links;
#[derive(Debug, Clone, Copy)]
pub struct Iter<'a, K, T> {
pub(crate) forward_ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) reverse_ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) nodes: &'a Arena<K, T>,
}
impl<'a, K, T> Iterator for Iter<'a, K, T> {
type Item = (&'a K, &'a T);
fn next(&mut self) -> Option<Self::Item> {
let ptr = self.forward_ptr?;
if self.forward_ptr == self.reverse_ptr {
self.forward_ptr = None;
self.reverse_ptr = None;
} else {
self.forward_ptr = Some(ptr.next(self.nodes));
}
let data = ptr.data(self.nodes);
Some((&data.key, &data.value))
}
}
impl<'a, K, T> DoubleEndedIterator for Iter<'a, K, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let ptr = self.reverse_ptr?;
if self.reverse_ptr == self.forward_ptr {
self.reverse_ptr = None;
self.forward_ptr = None;
} else {
self.reverse_ptr = Some(ptr.prev(self.nodes));
}
let data = ptr.data(self.nodes);
Some((&data.key, &data.value))
}
}
#[derive(Debug)]
pub struct IntoIter<K, T> {
pub(crate) nodes: ArenaContainer<K, T>,
pub(crate) forward_ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) reverse_ptr: Option<ActiveSlotRef<K, T>>,
}
impl<K, T> Iterator for IntoIter<K, T> {
type Item = (K, T);
fn next(&mut self) -> Option<Self::Item> {
let ptr = self.forward_ptr?;
if self.forward_ptr == self.reverse_ptr {
self.forward_ptr = None;
self.reverse_ptr = None;
} else {
self.forward_ptr = Some(ptr.next(&self.nodes));
}
let data = unsafe { self.nodes.free_and_unlink(ptr).data };
Some((data.key, data.value))
}
}
impl<K, T> DoubleEndedIterator for IntoIter<K, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let ptr = self.reverse_ptr?;
if self.reverse_ptr == self.forward_ptr {
self.reverse_ptr = None;
self.forward_ptr = None;
} else {
self.reverse_ptr = Some(ptr.prev(&self.nodes));
}
let data = unsafe { self.nodes.free_and_unlink(ptr).data };
Some((data.key, data.value))
}
}
#[derive(Debug)]
pub struct IterMut<'a, K, T> {
pub(crate) forward_ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) reverse_ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) _nodes: PhantomData<&'a mut Arena<K, T>>,
}
#[derive(Debug)]
pub struct ValuesMut<'a, K, T> {
pub(crate) iter: IterMut<'a, K, T>,
}
impl<'a, K, T> Iterator for IterMut<'a, K, T> {
type Item = (&'a K, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
let node_mut = unsafe { self.forward_ptr?.as_ptr().as_mut() };
if self.forward_ptr == self.reverse_ptr {
self.forward_ptr = None;
self.reverse_ptr = None;
} else {
self.forward_ptr = unsafe {
Some(match node_mut.links {
Links::Occupied { next, .. } => next,
Links::Vacant { .. } => unreachable_unchecked(),
})
};
}
unsafe {
let data = node_mut.data.assume_init_mut();
Some((&data.key, &mut data.value))
}
}
}
impl<'a, K, T> DoubleEndedIterator for IterMut<'a, K, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let node_mut = unsafe { self.reverse_ptr?.as_ptr().as_mut() };
if self.reverse_ptr == self.forward_ptr {
self.reverse_ptr = None;
self.forward_ptr = None;
} else {
self.reverse_ptr = unsafe {
Some(match node_mut.links {
Links::Occupied { prev, .. } => prev,
Links::Vacant { .. } => unreachable_unchecked(),
})
};
}
unsafe {
let data = node_mut.data.assume_init_mut();
Some((&data.key, &mut data.value))
}
}
}
impl<'a, K, T> Iterator for ValuesMut<'a, K, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(_, v)| v)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K, T> DoubleEndedIterator for ValuesMut<'a, K, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|(_, v)| v)
}
}