use std::mem::{self, MaybeUninit};
use std::ptr;
use crate::indexer::IntoOccupied;
use crate::Key;
#[derive(Debug)]
pub struct IntoIter<T> {
occupied: IntoOccupied,
entries: Vec<MaybeUninit<T>>,
}
impl<T> IntoIter<T> {
pub(crate) fn new(slab: crate::Slab<T>) -> Self {
let slab = MaybeUninit::new(slab);
let slab = slab.as_ptr();
unsafe {
Self {
occupied: ptr::read(&(*slab).index).into_occupied(),
entries: ptr::read(&(*slab).entries),
}
}
}
}
impl<T> Iterator for IntoIter<T> {
type Item = (Key, T);
fn next(&mut self) -> Option<Self::Item> {
let index = self.occupied.next()?;
let output = mem::replace(&mut self.entries[index], MaybeUninit::uninit());
Some((index.into(), unsafe { output.assume_init() }))
}
}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
for index in &mut self.occupied {
unsafe { self.entries[index].assume_init_drop() }
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn into_iter() {
let mut slab = crate::Slab::new();
slab.insert(1);
let key = slab.insert(2);
slab.insert(3);
slab.remove(key);
let mut iter = IntoIter::new(slab);
assert_eq!(iter.next(), Some((0.into(), 1)));
assert_eq!(iter.next(), Some((2.into(), 3)));
assert_eq!(iter.next(), None);
}
}