#![forbid(unsafe_code)]
pub(super) struct Slots<T, const LIMIT: usize>(Vec<Option<T>>);
impl<T, const LIMIT: usize> Slots<T, LIMIT> {
pub(super) const fn new() -> Self {
Self(Vec::new())
}
pub(super) fn insert(&mut self, value: T) -> Result<usize, T> {
let index = self
.0
.iter()
.position(Option::is_none)
.unwrap_or(self.0.len());
if index == LIMIT {
return Err(value);
}
if index == self.0.len() {
self.0.push(Some(value));
} else {
self.0[index] = Some(value);
}
Ok(index)
}
pub(super) fn take(&mut self, index: usize) -> Option<T> {
self.0.get_mut(index).and_then(Option::take)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn saturation_preserves_owners_and_only_returned_slots_are_reused() {
let mut slots = Slots::<_, 128>::new();
for value in 0..128 {
assert_eq!(slots.insert(value), Ok(value));
}
assert_eq!(slots.insert(999), Err(999));
assert_eq!(slots.take(usize::MAX), None);
assert_eq!(slots.take(17), Some(17));
assert_eq!(slots.take(17), None);
assert_eq!(slots.insert(999), Ok(17));
for index in 0..128 {
assert_eq!(
slots.take(index),
Some(if index == 17 { 999 } else { index })
);
}
assert_eq!(slots.insert(1000), Ok(0));
assert_eq!(slots.0.len(), 128);
}
}