use std::ops::Range;
use crate::slab::{Index, SecondaryMap};
#[derive(Debug)]
struct Entry {
offset: usize,
last_index: usize,
}
#[derive(Debug)]
pub struct RegionList<const SIZE: usize, K, V> {
values: ValueList<V>,
keys: SecondaryMap<K, Entry>,
next: usize,
}
impl<const SIZE: usize, K, V> RegionList<SIZE, K, V>
where
K: Into<Index>,
K: Copy,
{
pub fn empty() -> Self {
Self {
values: ValueList::empty(),
keys: SecondaryMap::empty(),
next: 0,
}
}
pub fn insert(&mut self, key: K, value: V) {
let insert_at = match self.keys.get_mut(key) {
Some(entry) => {
entry.last_index += 1;
entry.last_index + entry.offset
}
None => {
let entry = Entry {
offset: self.next,
last_index: 0,
};
let offset = entry.offset;
self.next += SIZE;
self.keys.insert(key, entry);
offset
}
};
self.values.insert(insert_at, value);
}
pub fn drain(&mut self, key: K) -> Option<impl Iterator<Item = V> + '_> {
let entry = self.keys.get(key)?;
let start = entry.offset;
let end = entry.offset + entry.last_index + 1;
Some(self.values.drain(start..end))
}
}
#[derive(Debug)]
struct ValueList<T> {
inner: Vec<Option<T>>,
}
impl<T> ValueList<T> {
fn empty() -> Self {
Self { inner: vec![] }
}
fn insert(&mut self, index: usize, value: T) {
if self.inner.len() <= index {
self.inner.resize_with(index + 1, || None);
}
self.inner[index].replace(value);
}
fn drain(&mut self, range: Range<usize>) -> impl Iterator<Item = T> + '_ {
self.inner[range].iter_mut().filter_map(|v| v.take())
}
}