genarena 0.1.0

A slot-reservable arena with generational keys
Documentation
use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;

/// A reservation for a slot in the arena.
///
/// The key that will be used for that slot after claiming the reservation can
/// be obtained using [`Reservation::key`].
pub struct Reservation<K> {
    pub(crate) key: Key,
    _marker: PhantomData<K>,
}

impl<K> Reservation<K> {
    pub(crate) fn new(key: Key) -> Self {
        Self { key, _marker: PhantomData }
    }
}

impl<K> Reservation<K>
where
    K: From<Key>,
{
    /// The key for the slot that this reservation reserves.
    pub fn key(&self) -> K {
        K::from(self.key)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct Generation(NonZeroUsize);

impl Generation {
    pub(crate) const FIRST: Self = Self(NonZeroUsize::MIN);

    pub(crate) fn next(&self) -> Option<Self> {
        let n = self.0.get().checked_add(1)?;
        Some(Self(NonZeroUsize::new(n).unwrap()))
    }
}

/// A generational key.
///
/// The key type maintains the same size even when inside an [`Option`]:
///
/// ```
/// # use std::mem::size_of;
/// # use genarena::key::Key;
/// #
/// assert_eq!(size_of::<Key>(), size_of::<Option<Key>>());
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Key {
    pub(crate) index: usize,
    pub(crate) generation: Generation,
}

const _NON_ZERO_OPTION_SIZE_OPTIMIZATION: () = {
    assert!(mem::size_of::<Key>() == mem::size_of::<Option<Key>>());
};