use hashbrown::hash_table::HashTable;
use std::mem::size_of;
pub trait VecAllocExt {
type T;
fn push_accounted(&mut self, x: Self::T, accounting: &mut usize);
fn allocated_size(&self) -> usize;
}
impl<T> VecAllocExt for Vec<T> {
type T = T;
fn push_accounted(&mut self, x: Self::T, accounting: &mut usize) {
let prev_capacity = self.capacity();
self.push(x);
let new_capacity = self.capacity();
if new_capacity > prev_capacity {
let bump_size = (new_capacity - prev_capacity) * size_of::<T>();
*accounting = (*accounting).checked_add(bump_size).expect("overflow");
}
}
fn allocated_size(&self) -> usize {
size_of::<T>() * self.capacity()
}
}
pub trait HashTableAllocExt {
type T;
fn insert_accounted(
&mut self,
x: Self::T,
hasher: impl Fn(&Self::T) -> u64,
accounting: &mut usize,
);
}
impl<T> HashTableAllocExt for HashTable<T>
where
T: Eq,
{
type T = T;
fn insert_accounted(
&mut self,
x: Self::T,
hasher: impl Fn(&Self::T) -> u64,
accounting: &mut usize,
) {
let hash = hasher(&x);
if cfg!(debug_assertions) {
debug_assert!(
self.find_entry(hash, |y| y == &x).is_err(),
"attempted to insert duplicate element into HashTableAllocExt::insert_accounted"
);
}
if self.len() == self.capacity() {
let bump_elements = self.capacity().max(16);
let bump_size = bump_elements * size_of::<T>();
*accounting = (*accounting).checked_add(bump_size).expect("overflow");
self.reserve(bump_elements, &hasher);
}
self.insert_unique(hash, x, hasher);
}
}