arrayset 3.1.1

An array-backed ordered set type.
Documentation
use super::OrdMap;
use core::{
    iter::FusedIterator,
    mem::{ManuallyDrop, MaybeUninit},
    ops::Range,
    ptr,
};

#[derive(Debug)]
pub struct IntoIter<K, V, const N: usize> {
    keys: [MaybeUninit<K>; N],
    values: [MaybeUninit<V>; N],
    range: Range<usize>,
}

impl<K, V, const N: usize> IntoIter<K, V, N> {
    pub(super) fn new(map: OrdMap<K, V, N>) -> Self {
        let map = ManuallyDrop::new(map);

        let keys = unsafe { (&map.keys as *const [MaybeUninit<K>; N]).read() };
        let values = unsafe { (&map.values as *const [MaybeUninit<V>; N]).read() };
        Self {
            keys,
            values,
            range: 0..map.len,
        }
    }

    fn read(&mut self, index: usize) -> (K, V) {
        let maybe_uninit_key = &self.keys[index];
        let key = unsafe { maybe_uninit_key.assume_init_read() };
        let maybe_uninit_value = &self.values[index];
        let value = unsafe { maybe_uninit_value.assume_init_read() };
        (key, value)
    }
}

impl<K, V, const N: usize> Iterator for IntoIter<K, V, N> {
    type Item = (K, V);

    fn next(&mut self) -> Option<Self::Item> {
        self.range.next().map(|index| self.read(index))
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
}

impl<K, V, const N: usize> DoubleEndedIterator for IntoIter<K, V, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.range.next_back().map(|index| self.read(index))
    }
}

impl<K, V, const N: usize> ExactSizeIterator for IntoIter<K, V, N> {}
impl<K, V, const N: usize> FusedIterator for IntoIter<K, V, N> {}

impl<K, V, const N: usize> Drop for IntoIter<K, V, N> {
    fn drop(&mut self) {
        if self.range.is_empty() {
            return;
        }

        let key_slice = {
            let ptr = self.keys.as_mut_ptr() as *mut K;
            let ptr = unsafe { ptr.add(self.range.start) };
            ptr::slice_from_raw_parts_mut(ptr, self.range.len())
        };
        let value_slice = {
            let ptr = self.values.as_mut_ptr() as *mut V;
            let ptr = unsafe { ptr.add(self.range.start) };
            ptr::slice_from_raw_parts_mut(ptr, self.range.len())
        };
        unsafe {
            ptr::drop_in_place(key_slice);
            ptr::drop_in_place(value_slice);
        }
    }
}