use super::macros::impl_direct_map_iter;
use crate::direct::oom_id;
use alloc::vec::Vec;
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use intid::{EquivalentId, IntegerId};
#[derive(Clone)]
pub struct DirectIdMap<K: IntegerId, V> {
values: Vec<Option<V>>,
len: usize,
marker: PhantomData<K>,
}
impl<K: IntegerId, V> Default for DirectIdMap<K, V> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<K: IntegerId, V> DirectIdMap<K, V> {
#[inline]
pub const fn new() -> Self {
DirectIdMap {
values: Vec::new(),
len: 0,
marker: PhantomData,
}
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn clear(&mut self) {
self.values.clear();
self.len = 0;
}
pub fn shrink_to_fit(&mut self) {
while matches!(self.values.last(), Some(None)) {
self.values.pop();
}
self.values.shrink_to_fit();
}
#[inline]
pub fn contains_key(&self, id: impl EquivalentId<K>) -> bool {
self.get(id).is_some()
}
#[inline]
pub fn get(&self, id: impl EquivalentId<K>) -> Option<&V> {
let id = id.as_id();
self.values
.get(intid::uint::to_usize_checked(id.to_int())?)?
.as_ref()
}
#[inline]
pub fn get_mut(&mut self, id: impl EquivalentId<K>) -> Option<&mut V> {
let id = id.as_id();
self.values
.get_mut(intid::uint::to_usize_checked(id.to_int())?)?
.as_mut()
}
#[inline]
pub fn insert(&mut self, id: K, value: V) -> Option<V> {
let id = id.to_int();
let id = intid::uint::to_usize_checked(id).unwrap_or_else(|| oom_id(id));
self.grow_to(id);
let old_value = self.values[id].replace(value);
if old_value.is_none() {
self.len += 1;
}
old_value
}
#[inline]
pub fn remove(&mut self, id: impl EquivalentId<K>) -> Option<V> {
let id = id.as_id().to_int();
let id = intid::uint::to_usize_checked(id).unwrap_or_else(|| oom_id(id));
if id >= self.values.len() {
return None;
}
let old_value = self.values[id].take();
if old_value.is_some() {
self.len -= 1;
}
old_value
}
#[inline]
fn grow_to(&mut self, max_id: usize) {
if self.values.len() <= max_id {
self.grow_fallback(max_id);
}
}
#[cold]
fn grow_fallback(&mut self, max_id: usize) {
let new_len = core::cmp::max(
self.len().checked_mul(2).expect("capacity overflow"),
max_id.checked_add(1).unwrap_or_else(|| oom_id(max_id)),
);
assert!(new_len >= self.values.len());
assert!(new_len > max_id);
self.values.resize_with(new_len, || None);
}
#[inline]
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
marker: PhantomData,
len: self.len,
source: self.values.iter().enumerate(),
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut {
marker: PhantomData,
len: self.len,
source: self.values.iter_mut().enumerate(),
}
}
pub fn retain(&mut self, mut func: impl FnMut(K, &mut V) -> bool) {
for (index, entry) in self.values.iter_mut().enumerate() {
let Some(ref mut entry_value) = entry else {
continue;
};
let key = unsafe { K::from_int_unchecked(intid::uint::from_usize_wrapping(index)) };
if !func(key, entry_value) {
*entry = None; self.len -= 1;
}
}
}
}
impl<K: IntegerId, V: PartialEq> PartialEq for DirectIdMap<K, V> {
fn eq(&self, other: &Self) -> bool {
self.len == other.len && self.values == other.values
}
}
impl<K: IntegerId, V: Eq> Eq for DirectIdMap<K, V> {}
impl<K: IntegerId, V> Index<K> for DirectIdMap<K, V> {
type Output = V;
#[inline]
#[track_caller]
fn index(&self, index: K) -> &Self::Output {
self.get(index).expect("index out of bounds")
}
}
impl<K: IntegerId, V> IndexMut<K> for DirectIdMap<K, V> {
#[inline]
#[track_caller]
fn index_mut(&mut self, index: K) -> &mut Self::Output {
self.get_mut(index).expect("index out of bounds")
}
}
impl<'a, K: IntegerId, V> Index<&'a K> for DirectIdMap<K, V> {
type Output = V;
#[inline]
#[track_caller]
fn index(&self, index: &'a K) -> &Self::Output {
self.get(*index).expect("index out of bounds")
}
}
impl<'a, K: IntegerId, V> IndexMut<&'a K> for DirectIdMap<K, V> {
#[inline]
#[track_caller]
fn index_mut(&mut self, index: &'a K) -> &mut Self::Output {
self.get_mut(*index).expect("index out of bounds")
}
}
impl<K: IntegerId, V> Extend<(K, V)> for DirectIdMap<K, V> {
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
for (key, value) in iter {
self.insert(key, value);
}
}
}
impl<'a, K: IntegerId, V: Clone> Extend<(K, &'a V)> for DirectIdMap<K, V> {
fn extend<T: IntoIterator<Item = (K, &'a V)>>(&mut self, iter: T) {
for (key, value) in iter {
self.insert(key, value.clone());
}
}
}
impl<K: IntegerId, V> FromIterator<(K, V)> for DirectIdMap<K, V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut res = Self::new();
res.extend(iter);
res
}
}
impl<'a, K: IntegerId, V: Clone> FromIterator<(K, &'a V)> for DirectIdMap<K, V> {
fn from_iter<I: IntoIterator<Item = (K, &'a V)>>(iter: I) -> Self {
let mut res = Self::new();
res.extend(iter);
res
}
}
impl<K: IntegerId, V> IntoIterator for DirectIdMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
len: self.len,
source: self.values.into_iter().enumerate(),
marker: PhantomData,
}
}
}
impl<'a, K: IntegerId, V> IntoIterator for &'a DirectIdMap<K, V> {
type Item = (K, &'a V);
type IntoIter = Iter<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K: IntegerId, V> IntoIterator for &'a mut DirectIdMap<K, V> {
type Item = (K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K: IntegerId, V: Debug> Debug for DirectIdMap<K, V> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
pub struct IntoIter<K: IntegerId, V> {
source: core::iter::Enumerate<alloc::vec::IntoIter<Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(IntoIter<K: IntegerId, V> {
fn map(key, value) -> (K, V) {
(key, value)
}
});
pub struct Iter<'a, K: IntegerId, V> {
source: core::iter::Enumerate<core::slice::Iter<'a, Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(Iter<'a, K: IntegerId, V> {
fn map(key, value) -> (K, &'a V) {
(key, value)
}
});
pub struct IterMut<'a, K: IntegerId, V> {
source: core::iter::Enumerate<core::slice::IterMut<'a, Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(IterMut<'a, K: IntegerId, V> {
fn map(key, value) -> (K, &'a mut V) {
(key, value)
}
});
pub struct Values<'a, K: IntegerId, V> {
source: core::iter::Enumerate<core::slice::Iter<'a, Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(Values<'a, K: IntegerId, V> {
fn map(_key, value) -> &'a V {
value
}
});
pub struct ValuesMut<'a, K: IntegerId, V> {
source: core::iter::Enumerate<core::slice::IterMut<'a, Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(ValuesMut<'a, K: IntegerId, V> {
fn map(_key, value) -> &'a mut V {
value
}
});
pub struct Keys<'a, K: IntegerId, V> {
source: core::iter::Enumerate<core::slice::IterMut<'a, Option<V>>>,
len: usize,
marker: PhantomData<K>,
}
impl_direct_map_iter!(Keys<'a, K: IntegerId, V> {
fn map(key, _value) -> K {
key
}
});
#[macro_export]
macro_rules! direct_idmap {
() => ($crate::direct::DirectIdMap::new());
($($key:expr => $value:expr),+ $(,)?) => ({
let mut res = $crate::direct::DirectIdMap::new();
$(res.insert($key, $value);)*
res
});
}