#[cfg(feature = "serde")]
mod serde;
use std::ops::Index;
pub use hashbrown::HashTable;
use hashbrown::TryReserveError;
pub struct IntTable<V> {
inner: HashTable<(u64, V)>,
}
impl<V> IntTable<V> {
pub const fn new() -> Self {
Self {
inner: HashTable::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: HashTable::with_capacity(capacity),
}
}
pub fn remove(&mut self, key: u64) -> Option<V> {
self.inner
.find_entry(key, eq(key))
.ok()
.map(|v| v.remove().0 .1)
}
pub fn shrink_to(&mut self, min_capacity: usize) {
self.inner.shrink_to(min_capacity, hasher)
}
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit(hasher)
}
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional, hasher)
}
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
pub fn clear(&mut self) {
self.inner.clear()
}
pub fn insert(&mut self, key: u64, value: V) -> Option<V> {
use hashbrown::hash_table::Entry;
match self.inner.entry(key, eq(key), hasher) {
Entry::Occupied(o) => {
let ((_, old_val), empty) = o.remove();
empty.insert((key, value));
Some(old_val)
}
Entry::Vacant(v) => {
v.insert((key, value));
None
}
}
}
pub fn try_insert(&mut self, key: u64, value: V) -> Result<&mut V, V> {
use hashbrown::hash_table::Entry;
match self.inner.entry(key, eq(key), hasher) {
Entry::Occupied(_) => Err(value),
Entry::Vacant(v) => {
let entry = v.insert((key, value));
Ok(&mut entry.into_mut().1)
}
}
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve(additional, hasher)
}
pub fn get(&self, key: u64) -> Option<&V> {
self.inner.find(key, eq(key)).map(|(_, v)| v)
}
pub fn get_mut(&mut self, key: u64) -> Option<&mut V> {
self.inner.find_mut(key, eq(key)).map(|(_, v)| v)
}
pub fn get_many_mut<const N: usize>(&mut self, ks: [u64; N]) -> Option<[&mut V; N]> {
self.inner
.get_many_mut(ks, |idx, (k, _)| ks[idx] == *k)
.map(|a| a.map(|(_, v)| v))
}
pub unsafe fn get_many_unchecked_mut<const N: usize>(
&mut self,
ks: [u64; N],
) -> Option<[&mut V; N]> {
self.inner
.get_many_unchecked_mut(ks, |idx, (k, _)| ks[idx] == *k)
.map(|a| a.map(|(_, v)| v))
}
pub fn retain<F>(&mut self, mut p: F)
where
F: FnMut(&u64, &mut V) -> bool,
{
self.inner.retain(|(key, val)| p(&*key, val))
}
pub fn keys(&self) -> impl Iterator<Item = &u64> {
self.inner.iter().map(|(key, _)| key)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.inner.iter().map(|(_, val)| val)
}
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.inner.iter_mut().map(|(_, val)| val)
}
pub fn contains_key(&self, key: u64) -> bool {
self.get(key).is_some()
}
pub fn entry(&mut self, key: u64) -> Entry<V> {
match self.inner.entry(key, eq(key), hasher) {
hashbrown::hash_table::Entry::Occupied(o) => Entry::Occupied(OccupiedEntry(o)),
hashbrown::hash_table::Entry::Vacant(v) => Entry::Vacant(VacantEntry(v, key)),
}
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner().len() == 0
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&u64, &mut V)> {
self.inner.iter_mut().map(|(key, val)| (&*key, val))
}
pub fn drain(&mut self) -> impl Iterator<Item = (u64, V)> + '_ {
self.inner.drain()
}
pub fn iter(&self) -> impl Iterator<Item = (&u64, &V)> {
self.inner().iter().map(|(k, v)| (k, v))
}
pub fn extract_if<F>(&mut self, mut f: F) -> ExtractIf<'_, V, impl FnMut(&mut (u64, V)) -> bool>
where
F: FnMut(&u64, &mut V) -> bool,
{
ExtractIf(self.inner.extract_if(move |(k, v)| f(&*k, v)))
}
pub fn into_keys(self) -> impl Iterator<Item = u64> {
self.into_iter().map(|(k, _)| k)
}
pub fn into_values(self) -> impl Iterator<Item = V> {
self.into_iter().map(|(_, v)| v)
}
}
impl<V> FromIterator<(u64, V)> for IntTable<V> {
fn from_iter<T: IntoIterator<Item = (u64, V)>>(iter: T) -> Self {
let mut res = Self::new();
res.extend(iter);
res
}
}
impl<V> Default for IntTable<V> {
fn default() -> Self {
Self::new()
}
}
impl<V> IntoIterator for IntTable<V> {
type Item = (u64, V);
type IntoIter = IntTableIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
let it = self.inner.into_iter();
IntTableIter(it)
}
}
impl<V> Index<u64> for IntTable<V> {
type Output = V;
fn index(&self, index: u64) -> &Self::Output {
self.get(index).expect("Key not in map")
}
}
impl<V> IntTable<V> {
pub fn inner(&self) -> &HashTable<(u64, V)> {
&self.inner
}
pub fn into_inner(self) -> HashTable<(u64, V)> {
self.inner
}
}
pub struct ExtractIf<'a, T, F: FnMut(&mut (u64, T)) -> bool>(
::hashbrown::hash_table::ExtractIf<'a, (u64, T), F>,
);
impl<V, F> Iterator for ExtractIf<'_, V, F>
where
F: FnMut(&mut (u64, V)) -> bool,
{
type Item = (u64, V);
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
#[derive(Debug)]
pub enum Entry<'a, V> {
Occupied(OccupiedEntry<'a, V>),
Vacant(VacantEntry<'a, V>),
}
impl<'a, V> Entry<'a, V> {
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(default),
}
}
pub fn or_insert_with<F>(self, default: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(default()),
}
}
pub fn or_insert_with_key<F>(self, default: F) -> &'a mut V
where
F: FnOnce(&u64) -> V,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => {
let key = v.1;
v.insert(default(&key))
}
}
}
pub fn key(&self) -> &u64 {
match self {
Entry::Occupied(o) => &o.0.get().0,
Entry::Vacant(v) => &v.1,
}
}
pub fn and_modify<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
if let Entry::Occupied(o) = &mut self {
f(o.get_mut())
};
self
}
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, V> {
match self {
Entry::Occupied(mut o) => {
o.insert(value);
o
}
Entry::Vacant(v) => v.insert_entry(value),
}
}
}
impl<'a, V> Entry<'a, V>
where
V: Default,
{
pub fn or_default(self) -> &'a mut V {
#[allow(clippy::unwrap_or_default)] self.or_insert(V::default())
}
}
#[derive(Debug)]
pub struct OccupiedEntry<'a, V>(::hashbrown::hash_table::OccupiedEntry<'a, (u64, V)>);
#[derive(Debug)]
pub struct VacantEntry<'a, V>(::hashbrown::hash_table::VacantEntry<'a, (u64, V)>, u64);
impl<'a, V> OccupiedEntry<'a, V> {
pub fn get(&self) -> &V {
&self.0.get().1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.0.get_mut().1
}
pub fn insert(&mut self, new_val: V) -> V {
std::mem::replace(self.get_mut(), new_val)
}
pub fn into_mut(self) -> &'a mut V {
&mut self.0.into_mut().1
}
pub fn remove(self) -> V {
self.0.remove().0 .1
}
pub fn remove_entry(self) -> (u64, V) {
self.0.remove().0
}
pub fn key(&self) -> &u64 {
&self.0.get().0
}
}
impl<'a, V> VacantEntry<'a, V> {
pub fn insert(self, value: V) -> &'a mut V {
let key = self.1;
&mut self.0.insert((key, value)).into_mut().1
}
fn insert_entry(self, value: V) -> OccupiedEntry<'a, V> {
OccupiedEntry(self.0.insert((self.1, value)))
}
pub fn key(&self) -> &u64 {
&self.1
}
}
fn eq<V>(key: u64) -> impl Fn(&(u64, V)) -> bool {
move |(other_key, _)| *other_key == key
}
fn hasher<V>((key, _value): &(u64, V)) -> u64 {
*key
}
pub struct IntTableIter<V>(::hashbrown::hash_table::IntoIter<V>);
impl<V> ExactSizeIterator for IntTableIter<V> {}
impl<V> Iterator for IntTableIter<V> {
fn size_hint(&self) -> (usize, Option<usize>) {
let l = self.0.len();
(l, Some(l))
}
fn count(self) -> usize
where
Self: Sized,
{
self.len()
}
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl<V> Extend<(u64, V)> for IntTable<V> {
fn extend<T: IntoIterator<Item = (u64, V)>>(&mut self, iter: T) {
let iter = iter.into_iter();
let (min, max) = iter.size_hint();
self.reserve(max.unwrap_or(min));
for (k, v) in iter {
self.insert(k, v);
}
}
}
impl<V> PartialEq for IntTable<V>
where
V: PartialEq,
{
fn eq(&self, other: &IntTable<V>) -> bool {
self.iter().eq(other.iter())
}
}
impl<V> std::fmt::Debug for IntTable<V>
where
V: std::fmt::Debug,
{
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut map_debug = fmt.debug_map();
for (k, v) in self.iter() {
map_debug.key(k);
map_debug.value(v);
}
map_debug.finish()
}
}