use super::{is_older_version, Key, KeyData};
use std;
use std::collections::hash_map;
use std::collections::hash_map::HashMap;
use std::iter::{Extend, FromIterator, FusedIterator};
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
#[derive(Debug)]
struct Slot<T> {
version: u32,
value: T,
}
#[derive(Debug)]
pub struct SparseSecondaryMap<K: Key, V> {
slots: HashMap<u32, Slot<V>>,
_k: PhantomData<fn(K) -> K>,
}
impl<K: Key, V> SparseSecondaryMap<K, V> {
pub fn new() -> Self {
Self::with_capacity(0)
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
slots: HashMap::with_capacity(capacity),
_k: PhantomData,
}
}
pub fn len(&self) -> usize {
self.slots.len()
}
pub fn is_empty(&self) -> bool {
self.slots.is_empty()
}
pub fn capacity(&self) -> usize {
self.slots.capacity()
}
pub fn reserve(&mut self, additional: usize) {
self.slots.reserve(additional);
}
pub fn contains_key(&self, key: K) -> bool {
let key = key.into();
self.slots
.get(&key.idx)
.map_or(false, |slot| slot.version == key.version.get())
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
let key = key.into();
if let Some(slot) = self.slots.get_mut(&key.idx) {
if slot.version == key.version.get() {
return Some(std::mem::replace(&mut slot.value, value));
}
if is_older_version(key.version.get(), slot.version) {
return None;
}
*slot = Slot {
version: key.version.get(),
value,
};
return None;
}
self.slots.insert(
key.idx,
Slot {
version: key.version.get(),
value,
},
);
None
}
pub fn remove(&mut self, key: K) -> Option<V> {
let key = key.into();
if let hash_map::Entry::Occupied(entry) = self.slots.entry(key.idx) {
if entry.get().version == key.version.get() {
return Some(entry.remove_entry().1.value);
}
}
None
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(K, &mut V) -> bool,
{
self.slots.retain(|&idx, slot| {
let key = KeyData::new(idx, slot.version);
f(key.into(), &mut slot.value)
})
}
pub fn clear(&mut self) {
self.slots.clear();
}
pub fn drain(&mut self) -> Drain<K, V> {
Drain {
inner: self.slots.drain(),
_k: PhantomData,
}
}
pub fn get(&self, key: K) -> Option<&V> {
let key = key.into();
self.slots
.get(&key.idx)
.filter(|slot| slot.version == key.version.get())
.map(|slot| &slot.value)
}
pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
let key = key.into();
self.slots
.get_mut(&key.idx)
.filter(|slot| slot.version == key.version.get())
.map(|slot| &mut slot.value)
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
inner: self.slots.iter(),
_k: PhantomData,
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
IterMut {
inner: self.slots.iter_mut(),
_k: PhantomData,
}
}
pub fn keys(&self) -> Keys<K, V> {
Keys { inner: self.iter() }
}
pub fn values(&self) -> Values<K, V> {
Values { inner: self.iter() }
}
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
ValuesMut {
inner: self.iter_mut(),
}
}
}
impl<K: Key, V> Default for SparseSecondaryMap<K, V> {
fn default() -> Self {
Self::new()
}
}
impl<K: Key, V> Index<K> for SparseSecondaryMap<K, V> {
type Output = V;
fn index(&self, key: K) -> &V {
match self.get(key) {
Some(r) => r,
None => panic!("invalid SparseSecondaryMap key used"),
}
}
}
impl<K: Key, V> IndexMut<K> for SparseSecondaryMap<K, V> {
fn index_mut(&mut self, key: K) -> &mut V {
match self.get_mut(key) {
Some(r) => r,
None => panic!("invalid SparseSecondaryMap key used"),
}
}
}
impl<K: Key, V: PartialEq> PartialEq for SparseSecondaryMap<K, V> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
self.iter().all(|(key, value)| {
other
.get(key)
.map_or(false, |other_value| *value == *other_value)
})
}
}
impl<K: Key, V: Eq> Eq for SparseSecondaryMap<K, V> {}
impl<K: Key, V> FromIterator<(K, V)> for SparseSecondaryMap<K, V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut sec = Self::new();
sec.extend(iter);
sec
}
}
impl<K: Key, V> Extend<(K, V)> for SparseSecondaryMap<K, V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
let iter = iter.into_iter();
for (k, v) in iter {
self.insert(k, v);
}
}
}
impl<'a, K: Key, V: 'a + Copy> Extend<(K, &'a V)> for SparseSecondaryMap<K, V> {
fn extend<I: IntoIterator<Item = (K, &'a V)>>(&mut self, iter: I) {
let iter = iter.into_iter();
for (k, v) in iter {
self.insert(k, *v);
}
}
}
#[derive(Debug)]
pub struct Drain<'a, K: Key + 'a, V: 'a> {
inner: hash_map::Drain<'a, u32, Slot<V>>,
_k: PhantomData<fn(K) -> K>,
}
#[derive(Debug)]
pub struct IntoIter<K: Key, V> {
inner: hash_map::IntoIter<u32, Slot<V>>,
_k: PhantomData<fn(K) -> K>,
}
#[derive(Debug)]
pub struct Iter<'a, K: Key + 'a, V: 'a> {
inner: hash_map::Iter<'a, u32, Slot<V>>,
_k: PhantomData<fn(K) -> K>,
}
#[derive(Debug)]
pub struct IterMut<'a, K: Key + 'a, V: 'a> {
inner: hash_map::IterMut<'a, u32, Slot<V>>,
_k: PhantomData<fn(K) -> K>,
}
#[derive(Debug)]
pub struct Keys<'a, K: Key + 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
#[derive(Debug)]
pub struct Values<'a, K: Key + 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
#[derive(Debug)]
pub struct ValuesMut<'a, K: Key + 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
impl<'a, K: Key, V> Iterator for Drain<'a, K, V> {
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
self.inner.next().map(|(idx, slot)| {
let key = KeyData::new(idx, slot.version).into();
(key, slot.value)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Drop for Drain<'a, K, V> {
fn drop(&mut self) {
self.for_each(|_drop| {});
}
}
impl<K: Key, V> Iterator for IntoIter<K, V> {
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
self.inner.next().map(|(idx, slot)| {
let key = KeyData::new(idx, slot.version).into();
(key, slot.value)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Iterator for Iter<'a, K, V> {
type Item = (K, &'a V);
fn next(&mut self) -> Option<(K, &'a V)> {
self.inner.next().map(|(&idx, slot)| {
let key = KeyData::new(idx, slot.version).into();
(key, &slot.value)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
type Item = (K, &'a mut V);
fn next(&mut self) -> Option<(K, &'a mut V)> {
self.inner.next().map(|(&idx, slot)| {
let key = KeyData::new(idx, slot.version).into();
(key, &mut slot.value)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Iterator for Keys<'a, K, V> {
type Item = K;
fn next(&mut self) -> Option<K> {
self.inner.next().map(|(key, _)| key)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
fn next(&mut self) -> Option<&'a V> {
self.inner.next().map(|(_, value)| value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;
fn next(&mut self) -> Option<&'a mut V> {
self.inner.next().map(|(_, value)| value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K: Key, V> IntoIterator for &'a SparseSecondaryMap<K, V> {
type Item = (K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K: Key, V> IntoIterator for &'a mut SparseSecondaryMap<K, V> {
type Item = (K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K: Key, V> IntoIterator for SparseSecondaryMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.slots.into_iter(),
_k: PhantomData,
}
}
}
impl<'a, K: Key, V> FusedIterator for Iter<'a, K, V> {}
impl<'a, K: Key, V> FusedIterator for IterMut<'a, K, V> {}
impl<'a, K: Key, V> FusedIterator for Keys<'a, K, V> {}
impl<'a, K: Key, V> FusedIterator for Values<'a, K, V> {}
impl<'a, K: Key, V> FusedIterator for ValuesMut<'a, K, V> {}
impl<'a, K: Key, V> FusedIterator for Drain<'a, K, V> {}
impl<K: Key, V> FusedIterator for IntoIter<K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for Iter<'a, K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for IterMut<'a, K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for Keys<'a, K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for Values<'a, K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for ValuesMut<'a, K, V> {}
impl<'a, K: Key, V> ExactSizeIterator for Drain<'a, K, V> {}
impl<K: Key, V> ExactSizeIterator for IntoIter<K, V> {}
#[cfg(feature = "serde")]
mod serialize {
use super::*;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use SecondaryMap;
impl<K: Key, V: Serialize> Serialize for SparseSecondaryMap<K, V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut serde_sec = SecondaryMap::new();
for (k, v) in self {
serde_sec.insert(k, v);
}
serde_sec.serialize(serializer)
}
}
impl<'de, K: Key, V: Deserialize<'de>> Deserialize<'de> for SparseSecondaryMap<K, V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let serde_sec: SecondaryMap<K, V> = Deserialize::deserialize(deserializer)?;
let mut sec = Self::new();
for (k, v) in serde_sec {
sec.insert(k, v);
}
Ok(sec)
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use *;
#[cfg(feature = "serde")]
use serde_json;
quickcheck! {
fn qc_secmap_equiv_hashmap(operations: Vec<(u8, u32)>) -> bool {
let mut hm = HashMap::new();
let mut hm_keys = Vec::new();
let mut unique_key = 0u32;
let mut sm = SlotMap::new();
let mut sec = SparseSecondaryMap::new();
let mut sm_keys = Vec::new();
#[cfg(not(feature = "serde"))]
let num_ops = 3;
#[cfg(feature = "serde")]
let num_ops = 4;
for (op, val) in operations {
match op % num_ops {
0 => {
hm.insert(unique_key, val);
hm_keys.push(unique_key);
unique_key += 1;
let k = sm.insert(val);
sec.insert(k, val);
sm_keys.push(k);
}
1 => {
if hm_keys.len() == 0 { continue; }
let idx = val as usize % hm_keys.len();
sm.remove(sm_keys[idx]);
if hm.remove(&hm_keys[idx]) != sec.remove(sm_keys[idx]) {
return false;
}
}
2 => {
if hm_keys.len() == 0 { continue; }
let idx = val as usize % hm_keys.len();
let (hm_key, sm_key) = (&hm_keys[idx], sm_keys[idx]);
if hm.contains_key(hm_key) != sec.contains_key(sm_key) ||
hm.get(hm_key) != sec.get(sm_key) {
return false;
}
}
#[cfg(feature = "serde")]
3 => {
let ser = serde_json::to_string(&sec).unwrap();
sec = serde_json::from_str(&ser).unwrap();
}
_ => unreachable!(),
}
}
let mut secv: Vec<_> = sec.values().collect();
let mut hmv: Vec<_> = hm.values().collect();
secv.sort();
hmv.sort();
secv == hmv
}
}
}