use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
use std::mem::size_of;
use std::ops::RangeInclusive;
use std::sync::Arc;
use crate::SizeBytes;
impl SizeBytes for String {
#[inline]
fn heap_size_bytes(&self) -> u64 {
self.capacity() as u64
}
}
#[inline]
pub(crate) fn btree_heap_size(len: usize, entry_size: usize) -> u64 {
if len == 0 {
return 0;
}
const BTREE_B: usize = 6;
const CAPACITY: usize = 2 * BTREE_B - 1;
let avg_entries_per_node = (CAPACITY * 2) / 3;
let num_leaf_nodes = len.div_ceil(avg_entries_per_node.max(1));
const LEAF_OVERHEAD: usize = 16;
let leaf_size = LEAF_OVERHEAD + CAPACITY * entry_size;
let total_leaf_size = num_leaf_nodes * leaf_size;
let num_internal_nodes = num_leaf_nodes.saturating_sub(1) / BTREE_B;
const CHILD_PTR_SIZE: usize = size_of::<usize>(); let internal_node_size = leaf_size + (CAPACITY + 1) * CHILD_PTR_SIZE;
let total_internal_size = num_internal_nodes * internal_node_size;
(total_leaf_size + total_internal_size) as u64
}
impl<K: SizeBytes, V: SizeBytes> SizeBytes for BTreeMap<K, V> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
let base_size = btree_heap_size(self.len(), size_of::<K>() + size_of::<V>());
let heap_in_keys = if K::is_pod() {
0
} else {
self.keys().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
let heap_in_values = if V::is_pod() {
0
} else {
self.values().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
base_size + heap_in_keys + heap_in_values
}
}
impl<K: SizeBytes> SizeBytes for BTreeSet<K> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
let base_size = btree_heap_size(self.len(), size_of::<K>());
let heap_in_keys = if K::is_pod() {
0
} else {
self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
base_size + heap_in_keys
}
}
#[inline]
fn hashbrown_num_slots(capacity: usize) -> usize {
if capacity == 0 {
0
} else if capacity < 4 {
4
} else if capacity < 8 {
8
} else {
(capacity * 8).div_ceil(7)
}
}
impl<K: SizeBytes, V: SizeBytes, S> SizeBytes for HashMap<K, V, S> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
let num_slots = hashbrown_num_slots(self.capacity());
let control_bytes = num_slots as u64;
let entry_size = (num_slots * size_of::<(K, V)>()) as u64;
let heap_in_keys = if K::is_pod() {
0
} else {
self.keys().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
let heap_in_values = if V::is_pod() {
0
} else {
self.values().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
control_bytes + entry_size + heap_in_keys + heap_in_values
}
}
impl<K: SizeBytes, S> SizeBytes for HashSet<K, S> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
let num_slots = hashbrown_num_slots(self.capacity());
let control_bytes = num_slots as u64;
let entry_size = (num_slots * size_of::<K>()) as u64;
let heap_in_keys = if K::is_pod() {
0
} else {
self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
};
control_bytes + entry_size + heap_in_keys
}
}
impl<T: SizeBytes, const N: usize> SizeBytes for [T; N] {
#[inline]
fn heap_size_bytes(&self) -> u64 {
if T::is_pod() {
0 } else {
self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
}
}
}
impl<T: SizeBytes> SizeBytes for Vec<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
if T::is_pod() {
(self.capacity() * size_of::<T>()) as _
} else {
(self.capacity() * size_of::<T>()) as u64
+ self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
}
}
}
impl<T: SizeBytes + Clone> SizeBytes for std::borrow::Cow<'_, [T]> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
match self {
std::borrow::Cow::Borrowed(_) => 0,
std::borrow::Cow::Owned(v) => v.heap_size_bytes(),
}
}
}
impl<T: SizeBytes> SizeBytes for VecDeque<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
if T::is_pod() {
(self.capacity() * size_of::<T>()) as _
} else {
(self.capacity() * size_of::<T>()) as u64
+ self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
}
}
}
impl<T: SizeBytes> SizeBytes for vec1::Vec1<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
self.as_vec().heap_size_bytes()
}
}
impl<T: SizeBytes> SizeBytes for Option<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
self.as_ref().map_or(0, SizeBytes::heap_size_bytes)
}
}
impl<T: SizeBytes, E: SizeBytes> SizeBytes for Result<T, E> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
match self {
Ok(value) => value.heap_size_bytes(),
Err(err) => err.heap_size_bytes(),
}
}
}
impl<T: SizeBytes + ?Sized> SizeBytes for Arc<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
let arc_overhead = 2 * size_of::<usize>() as u64;
(T::total_size_bytes(&**self) + arc_overhead) / Self::strong_count(self) as u64
}
}
impl<T: SizeBytes> SizeBytes for Box<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
T::total_size_bytes(&**self)
}
}
impl<T: SizeBytes> SizeBytes for RangeInclusive<T> {
#[inline]
fn heap_size_bytes(&self) -> u64 {
self.start().heap_size_bytes() + self.end().heap_size_bytes()
}
}