o3 0.7.0

shared-nothing primitives
Documentation
use std::marker::PhantomData;

use super::core::{Interior, SlabCore};
use super::pending::Pending;
use super::{SlabGeneration, SlabKey, SlabKeyParts};

pub struct CellSlab<T, Tag = (), const MAX: u32 = { u32::MAX }> {
    core: SlabCore<T, SlabGeneration<MAX>, Interior>,
    tag: PhantomData<fn() -> Tag>,
}

struct Keys<'a, T, Tag, const MAX: u32> {
    slab: &'a CellSlab<T, Tag, MAX>,
    position: usize,
    remaining: usize,
}

impl<T, Tag, const MAX: u32> Iterator for Keys<'_, T, Tag, MAX> {
    type Item = SlabKey<Tag, MAX>;

    fn next(&mut self) -> Option<Self::Item> {
        while self.remaining != 0 {
            let position = self.position;
            self.position += 1;
            self.remaining -= 1;
            if let Some((index, generation)) = self.slab.core.occupied_at(position) {
                return Some(SlabKey::new(index, generation));
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(self.remaining))
    }
}

impl<T, Tag, const MAX: u32> CellSlab<T, Tag, MAX> {
    impl_slab_common!();

    pub fn keys(&self) -> impl Iterator<Item = SlabKey<Tag, MAX>> + '_ {
        Keys {
            slab: self,
            position: 0,
            remaining: self.len(),
        }
    }

    pub fn insert(&self, value: T) -> Result<SlabKey<Tag, MAX>, T> {
        let Some(ticket) = self.core.take_free() else {
            return Err(value);
        };
        let pending = Pending::new(&self.core, ticket);
        let key = SlabKey::new(ticket.index.get(), ticket.generation);
        pending.commit(value);
        Ok(key)
    }

    pub fn update<R>(&self, key: SlabKey<Tag, MAX>, f: impl FnOnce(&mut T) -> R) -> Option<R> {
        self.update_parts(key.parts(), f)
    }

    pub fn update_parts<R>(
        &self,
        parts: SlabKeyParts<MAX>,
        f: impl FnOnce(&mut T) -> R,
    ) -> Option<R> {
        self.core.update(parts.index(), parts.generation(), f)
    }

    pub fn remove(&self, key: SlabKey<Tag, MAX>) -> Option<T> {
        self.remove_parts(key.parts())
    }

    pub fn remove_parts(&self, parts: SlabKeyParts<MAX>) -> Option<T> {
        self.core
            .remove(parts.index(), parts.generation())
            .map(|(value, _)| value)
    }

    pub fn remove_parts_with<R>(
        &self,
        parts: SlabKeyParts<MAX>,
        f: impl FnOnce(&mut T) -> Option<R>,
    ) -> Option<(T, R)> {
        self.core.remove_with(parts.index(), parts.generation(), f)
    }
}