use hashbrown::raw::{Bucket, RawTable};
pub trait VecAllocExt {
type T;
fn push_accounted(&mut self, x: Self::T, accounting: &mut usize);
}
impl<T> VecAllocExt for Vec<T> {
type T = T;
fn push_accounted(&mut self, x: Self::T, accounting: &mut usize) {
if self.capacity() == self.len() {
let bump_elements = (self.capacity() * 2).max(2);
let bump_size = std::mem::size_of::<u32>() * bump_elements;
self.reserve(bump_elements);
*accounting = (*accounting).checked_add(bump_size).expect("overflow");
}
self.push(x);
}
}
pub trait RawTableAllocExt {
type T;
fn insert_accounted(
&mut self,
x: Self::T,
hasher: impl Fn(&Self::T) -> u64,
accounting: &mut usize,
) -> Bucket<Self::T>;
}
impl<T> RawTableAllocExt for RawTable<T> {
type T = T;
fn insert_accounted(
&mut self,
x: Self::T,
hasher: impl Fn(&Self::T) -> u64,
accounting: &mut usize,
) -> Bucket<Self::T> {
let hash = hasher(&x);
match self.try_insert_no_grow(hash, x) {
Ok(bucket) => bucket,
Err(x) => {
let bump_elements = (self.capacity() * 2).max(16);
let bump_size = bump_elements * std::mem::size_of::<T>();
*accounting = (*accounting).checked_add(bump_size).expect("overflow");
self.reserve(bump_elements, hasher);
match self.try_insert_no_grow(hash, x) {
Ok(bucket) => bucket,
Err(_) => panic!("just grew the container"),
}
}
}
}
}