#![forbid(unsafe_code)]
#[cfg(feature = "serde")]
mod serde;
mod entry;
mod int;
mod int_key;
mod iter;
use core::iter::{IntoIterator, Iterator};
use int::SealedInt;
pub use entry::*;
pub use int::Int;
pub use int_key::IntKey;
pub use iter::*;
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;
#[derive(Clone)]
pub struct IntMap<K, V> {
cache: Vec<Vec<(K, V)>>,
size: u32,
mod_mask: usize,
count: usize,
load_factor: usize,
}
impl<K, V> IntMap<K, V> {
pub const fn new() -> Self {
Self {
cache: Vec::new(),
size: 0,
count: 0,
mod_mask: 0,
load_factor: 909, }
}
}
impl<K: IntKey, V> IntMap<K, V> {
pub fn with_capacity(capacity: usize) -> Self {
let mut map = Self::new();
map.reserve(capacity);
map
}
pub fn set_load_factor(&mut self, load_factor: f32) {
self.load_factor = (load_factor * 1000.) as usize;
self.increase_cache_if_needed();
}
pub fn get_load_factor(&self) -> f32 {
self.load_factor as f32 / 1000.
}
pub fn reserve(&mut self, additional: usize) {
let capacity = self.count + additional;
while self.lim() < capacity {
self.increase_cache();
}
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
self.increase_cache_if_needed();
let k = key.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &mut self.cache[ix];
let pos = vals.iter().position(|kv| kv.0.into_int() == k);
let old = if let Some(pos) = pos {
Some(vals.swap_remove(pos).1)
} else {
self.count += 1;
None
};
vals.push((key, value));
old
}
pub fn insert_checked(&mut self, key: K, value: V) -> bool {
self.increase_cache_if_needed();
let k = key.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &mut self.cache[ix];
if vals.iter().any(|kv| kv.0.into_int() == k) {
return false;
}
self.count += 1;
vals.push((key, value));
true
}
pub fn get(&self, key: K) -> Option<&V> {
if self.is_empty() {
return None;
}
let k = key.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &self.cache[ix];
vals.iter()
.find_map(|kv| (kv.0.into_int() == k).then(|| &kv.1))
}
pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
if self.is_empty() {
return None;
}
let k = key.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &mut self.cache[ix];
vals.iter_mut()
.find_map(|kv| (kv.0.into_int() == k).then(move || &mut kv.1))
}
pub fn remove(&mut self, key: K) -> Option<V> {
if self.is_empty() {
return None;
}
let k = key.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &mut self.cache[ix];
for i in 0..vals.len() {
let peek = &vals[i].0;
if peek.into_int() == k {
self.count -= 1;
let kv = vals.swap_remove(i);
return Some(kv.1);
}
}
None
}
pub fn contains_key(&self, key: K) -> bool {
self.get(key).is_some()
}
pub fn clear(&mut self) {
for vals in &mut self.cache {
vals.clear();
}
self.count = 0;
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(K, &V) -> bool,
{
let mut removed = 0;
for vals in &mut self.cache {
vals.retain(|(k, v)| {
let keep = (f)(*k, v);
if !keep {
removed += 1;
}
keep
});
}
self.count -= removed;
}
pub fn is_empty(&self) -> bool {
self.count == 0
}
pub fn iter(&self) -> Iter<'_, K, V> {
Iter::new(&self.cache)
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut::new(&mut self.cache)
}
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(),
}
}
pub fn drain(&mut self) -> Drain<'_, K, V> {
Drain::new(&mut self.cache, &mut self.count)
}
#[inline(always)]
fn lim(&self) -> usize {
if self.size == 0 {
0
} else {
2usize.pow(self.size)
}
}
fn increase_cache(&mut self) {
self.size += 1;
let new_lim = self.lim();
self.mod_mask = new_lim - 1;
let mut vec: Vec<Vec<(K, V)>> = (0..new_lim).map(|_| Vec::new()).collect();
std::mem::swap(&mut self.cache, &mut vec);
for key in vec.into_iter().flatten() {
let k = key.0.into_int();
let ix = k.calc_index(self.mod_mask, K::PRIME);
let vals = &mut self.cache[ix];
vals.push(key);
}
debug_assert!(
self.cache.len() == self.lim(),
"cache vector the wrong length, lim: {:?} cache: {:?}",
self.lim(),
self.cache.len()
);
}
#[inline]
fn increase_cache_if_needed(&mut self) -> bool {
let initial_cache_len = self.cache.len();
if self.cache.is_empty() {
self.increase_cache();
}
while ((self.count * 1000) / self.cache.len()) > self.load_factor {
self.increase_cache();
}
initial_cache_len != self.cache.len()
}
pub fn len(&self) -> usize {
self.count
}
pub fn load(&self) -> u64 {
self.cache.iter().filter(|vals| !vals.is_empty()).count() as u64
}
pub fn load_rate(&self) -> f64 {
(self.count as f64) / (self.cache.len() as f64) * 100f64
}
pub fn capacity(&self) -> usize {
self.cache.len()
}
#[doc(hidden)]
pub fn assert_count(&self) -> bool {
let count = self.cache.iter().flatten().count();
self.count == count
}
#[doc(hidden)]
pub fn collisions(&self) -> IntMap<u64, u64> {
let mut map = IntMap::new();
for s in self.cache.iter() {
let key = s.len() as u64;
if key > 1 {
if !map.contains_key(key) {
map.insert(key, 1);
} else {
let counter = map.get_mut(key).unwrap();
*counter += 1;
}
}
}
map
}
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
Entry::new(key, self)
}
}
impl<K, V> Default for IntMap<K, V> {
fn default() -> Self {
Self::new()
}
}
impl<K, V> PartialEq for IntMap<K, V>
where
K: IntKey,
V: PartialEq,
{
fn eq(&self, other: &IntMap<K, V>) -> bool {
self.count == other.count && self.iter().all(|(k, a)| other.get(k) == Some(a))
}
}
impl<K: IntKey, V: Eq> Eq for IntMap<K, V> {}
impl<K, V> std::fmt::Debug for IntMap<K, V>
where
K: IntKey + std::fmt::Debug,
V: std::fmt::Debug,
{
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_map().entries(self.iter()).finish()
}
}