use std::{
iter::{Enumerate, FusedIterator},
marker::PhantomData,
mem::{self, MaybeUninit},
ops::{Index, IndexMut},
slice,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::SecondaryMap;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct UnmanagedDenseMap<K, V> {
data: Vec<V>,
phantom: PhantomData<K>,
default: V,
}
impl<K: PartialEq, V: PartialEq> PartialEq for UnmanagedDenseMap<K, V> {
fn eq(&self, other: &Self) -> bool {
if self.default != other.default {
return false;
}
let common_len = std::cmp::min(self.data.len(), other.data.len());
self.data[..common_len] == other.data[..common_len]
&& self.data[common_len..].iter().all(|v| v == &self.default)
&& other.data[common_len..].iter().all(|v| v == &other.default)
}
}
impl<K, V> UnmanagedDenseMap<K, V>
where
K: Into<usize> + Copy,
V: Clone,
{
#[inline]
pub fn new() -> Self
where
V: Default,
{
Self::with_default(Default::default())
}
#[inline]
pub const fn with_default(default: V) -> Self {
Self {
data: Vec::new(),
phantom: PhantomData,
default,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self
where
V: Default,
{
Self::with_capacity_and_default(capacity, Default::default())
}
#[inline]
pub fn with_capacity_and_default(capacity: usize, default: V) -> Self {
Self {
data: Vec::with_capacity(capacity),
phantom: PhantomData,
default,
}
}
pub fn ensure_capacity(&mut self, capacity: usize) {
if capacity > self.data.capacity() {
self.data.reserve(capacity - self.data.capacity());
self.data.resize(capacity, self.default.clone());
}
}
pub fn shrink_to(&mut self, capacity: usize) {
self.data.truncate(capacity);
self.data.shrink_to_fit();
}
#[inline]
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn rekey(&mut self, old: K, new: Option<K>)
where
V: Default,
{
if old.into() < self.data.len() {
let val = mem::take(self.get_mut(old));
let Some(new) = new else { return };
if new.into() >= self.data.len() {
self.resize_for_get_mut(new.into() + 1);
}
self.data[new.into()] = val;
} else {
let Some(new) = new else { return };
if new.into() < self.data.len() {
self.data[new.into()] = Default::default();
}
}
}
#[inline]
pub fn get(&self, key: K) -> &V {
self.data.get(key.into()).unwrap_or(&self.default)
}
#[inline]
pub fn get_mut(&mut self, key: K) -> &mut V {
let index = key.into();
if index >= self.data.len() {
self.resize_for_get_mut(index + 1);
}
&mut self.data[index]
}
#[inline]
pub fn try_get_mut(&mut self, key: K) -> Option<&mut V> {
self.data.get_mut(key.into())
}
pub fn get_disjoint_mut<const N: usize>(&mut self, keys: [K; N]) -> Option<[&mut V; N]>
where
K: Eq,
{
if let Some(max_index) = keys.iter().map(|i| (*i).into()).max() {
if max_index >= self.data.len() {
self.resize_for_get_mut(max_index + 1);
}
};
let mut ptrs: [MaybeUninit<*mut V>; N] = [MaybeUninit::uninit(); N];
let data = self.data.as_mut_ptr();
for (i, key) in keys.iter().enumerate() {
if keys[(i + 1)..].iter().any(|other| key == other) {
return None;
}
let offset = (*key).into();
if offset >= self.data.len() {
return None;
}
let ptr: *mut V = unsafe { data.add(offset) };
ptrs[i].write(ptr);
}
let refs = unsafe { ptrs.map(|p| &mut *p.assume_init()) };
Some(refs)
}
#[cold]
fn resize_for_get_mut(&mut self, len: usize) {
self.data.resize(len, self.default.clone());
}
#[inline]
pub fn swap(&mut self, key0: K, key1: K) {
let index0 = key0.into();
let index1 = key1.into();
let max_index = std::cmp::max(index0, index1);
if max_index >= self.data.len() {
self.resize_for_get_mut(max_index + 1);
}
self.data.swap(index0, index1);
}
}
impl<K, V> Default for UnmanagedDenseMap<K, V>
where
K: Into<usize> + Copy,
V: Clone + Default,
{
fn default() -> Self {
Self::new()
}
}
impl<K, V> Index<K> for UnmanagedDenseMap<K, V>
where
K: Into<usize> + Copy,
V: Clone,
{
type Output = V;
fn index(&self, key: K) -> &Self::Output {
self.get(key)
}
}
impl<K, V> IndexMut<K> for UnmanagedDenseMap<K, V>
where
K: Into<usize> + Copy,
V: Clone,
{
fn index_mut(&mut self, key: K) -> &mut Self::Output {
self.get_mut(key)
}
}
impl<K, V> SecondaryMap<K, V> for UnmanagedDenseMap<K, V>
where
K: Into<usize> + TryFrom<usize> + Copy,
V: Clone + Default,
{
type Iter<'a>
= UnmanagedIter<'a, K, V>
where
Self: 'a,
K: 'a,
V: 'a;
#[inline]
fn new() -> Self {
Self::with_default(Default::default())
}
#[inline]
fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_default(capacity, Default::default())
}
#[inline]
fn default_value(&self) -> V {
self.default.clone()
}
#[inline]
fn ensure_capacity(&mut self, capacity: usize) {
UnmanagedDenseMap::ensure_capacity(self, capacity)
}
#[inline]
fn capacity(&self) -> usize {
UnmanagedDenseMap::capacity(self)
}
#[inline]
fn get(&self, key: K) -> &V {
UnmanagedDenseMap::get(self, key)
}
#[inline]
fn set(&mut self, key: K, val: V) {
self[key] = val;
}
#[inline]
fn take(&mut self, key: K) -> V {
let default = self.default.clone();
match self.try_get_mut(key) {
Some(val) => mem::replace(val, default),
None => default,
}
}
#[inline]
fn rekey(&mut self, old: K, new: Option<K>) {
UnmanagedDenseMap::rekey(self, old, new)
}
#[inline]
fn swap(&mut self, key0: K, key1: K) {
UnmanagedDenseMap::swap(self, key0, key1)
}
fn iter<'a>(&'a self) -> Self::Iter<'a>
where
K: 'a,
V: 'a,
{
UnmanagedIter {
iter: self.data.iter().enumerate(),
phantom: std::marker::PhantomData,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct UnmanagedIter<'a, K, V> {
iter: Enumerate<slice::Iter<'a, V>>,
phantom: std::marker::PhantomData<K>,
}
impl<'a, K, V> Iterator for UnmanagedIter<'a, K, V>
where
K: TryFrom<usize>,
{
type Item = (K, &'a V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|(key, value)| (key.try_into().ok().unwrap(), value))
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter
.nth(n)
.map(|(key, value)| (key.try_into().ok().unwrap(), value))
}
#[inline]
fn count(self) -> usize {
self.iter.count()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<K, V> DoubleEndedIterator for UnmanagedIter<'_, K, V>
where
K: TryFrom<usize>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|(key, value)| (key.try_into().ok().unwrap(), value))
}
}
impl<K, V> FusedIterator for UnmanagedIter<'_, K, V> where K: TryFrom<usize> {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_capacity() {
let mut map: UnmanagedDenseMap<usize, usize> = UnmanagedDenseMap::new();
assert_eq!(map.capacity(), 0);
map.ensure_capacity(10);
assert!(map.capacity() >= 10);
let prev_capacity = map.capacity();
map.ensure_capacity(5);
assert_eq!(map.capacity(), prev_capacity);
map.ensure_capacity(15);
assert!(map.capacity() >= 15);
map.shrink_to(5);
assert!(map.capacity() >= 5);
let prev_capacity = map.capacity();
map.shrink_to(10);
assert_eq!(map.capacity(), prev_capacity);
}
#[test]
fn test_get_mut() {
let mut map: UnmanagedDenseMap<usize, i32> = UnmanagedDenseMap::with_default(4);
let value = map.get_mut(0);
assert_eq!(value, &4);
*value = 1;
assert_eq!(map.get_mut(0), &1);
let value = map.try_get_mut(10);
assert_eq!(value, None);
let value = map.get_mut(10);
assert_eq!(value, &mut 4);
*value = 2;
assert_eq!(map.try_get_mut(10), Some(&mut 2));
}
#[test]
fn test_get_disjoint_mut() {
let mut map: UnmanagedDenseMap<usize, i32> = UnmanagedDenseMap::new();
let values = map.get_disjoint_mut([0, 1, 2]);
assert_eq!(values, Some([&mut 0, &mut 0, &mut 0]));
let values = values.unwrap();
*values[0] = 1;
*values[1] = 2;
*values[2] = 3;
assert_eq!(
map.get_disjoint_mut([0, 1, 2]),
Some([&mut 1, &mut 2, &mut 3])
);
let values = map.get_disjoint_mut([0, 1, 0]);
assert_eq!(values, None);
}
#[test]
fn test_swap() {
let mut map: UnmanagedDenseMap<usize, i32> = UnmanagedDenseMap::new();
map[0] = 0x10;
map[1] = 0x11;
map[3] = 0x13;
map.swap(0, 1);
assert_eq!(map[0], 0x11);
assert_eq!(map[1], 0x10);
map.swap(10, 3);
assert_eq!(map[3], 0);
assert_eq!(map[10], 0x13);
}
#[cfg(feature = "serde")]
#[test]
fn secondary_serialize() {
let mut map: UnmanagedDenseMap<usize, i32> = UnmanagedDenseMap::new();
assert_eq!(crate::portgraph::test::ser_roundtrip(&map), map);
map[0] = 0x10;
map[1] = 0x11;
map[3] = 0x13;
assert_eq!(crate::portgraph::test::ser_roundtrip(&map), map);
}
#[test]
fn eq_ignores_defaults() {
let mut a = UnmanagedDenseMap::<usize, usize>::new();
let mut b = UnmanagedDenseMap::<usize, usize>::new();
a[4] = 0;
assert_eq!(a, b);
b[42] = 0;
assert_eq!(a, b);
b[40] = 24;
assert_ne!(a, b);
}
}