use cid::Cid;
use derive_more::{From, Into};
pub use get_size2::GetSize;
use num_bigint::BigInt;
#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, From, Into)]
pub struct CidWrapper(pub Cid);
impl GetSize for CidWrapper {}
impl quick_cache::Equivalent<CidWrapper> for Cid {
fn equivalent(&self, other: &CidWrapper) -> bool {
self == &other.0
}
}
macro_rules! impl_vec_alike_heap_size_with_fn_helper {
($name:ident, $tracker:ident, $t:ty, $get_stack_size: expr, $get_heap_size_with_tracker: expr) => {{
let mut heap_size = 0;
let mut tr = $tracker;
for ____v in $name.iter() {
let (_s, _tr) = $get_heap_size_with_tracker(____v, tr);
heap_size += $get_stack_size() + _s;
tr = _tr;
}
let additional = usize::from($name.capacity()) - usize::from($name.len());
heap_size += additional * $get_stack_size();
(heap_size, tr)
}};
}
macro_rules! impl_vec_alike_heap_size_helper {
($name:ident, $tracker:ident, $t:ty) => {
impl_vec_alike_heap_size_with_fn_helper!(
$name,
$tracker,
$t,
<$t>::get_stack_size,
GetSize::get_heap_size_with_tracker
)
};
}
pub fn vec_heap_size_with_fn_helper<T, Tr: get_size2::GetSizeTracker>(
v: &Vec<T>,
tracker: Tr,
get_heap_size_with_tracker: impl Fn(&T, Tr) -> (usize, Tr),
) -> (usize, Tr) {
impl_vec_alike_heap_size_with_fn_helper!(
v,
tracker,
T,
std::mem::size_of::<T>,
get_heap_size_with_tracker
)
}
pub fn nunny_vec_heap_size_helper<T: GetSize, Tr: get_size2::GetSizeTracker>(
v: &nunny::Vec<T>,
tracker: Tr,
) -> (usize, Tr) {
impl_vec_alike_heap_size_helper!(v, tracker, T)
}
pub fn big_int_heap_size_helper(b: &BigInt) -> usize {
b.bits().div_ceil(8) as usize
}
pub fn raw_bytes_heap_size_helper(b: &fvm_ipld_encoding::RawBytes) -> usize {
b.bytes().get_heap_size()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::multihash::MultihashCode;
use fvm_ipld_encoding::DAG_CBOR;
use multihash_derive::MultihashDigest as _;
#[test]
fn test_cid() {
let cid = Cid::new_v1(DAG_CBOR, MultihashCode::Blake2b256.digest(&[0, 1, 2, 3]));
let wrapper = CidWrapper(cid);
assert_eq!(std::mem::size_of_val(&cid), wrapper.get_size());
}
#[test]
fn test_heap_size_helper() {
let keys: nunny::Vec<CidWrapper> = nunny::vec![Cid::default().into(); 3];
println!("keys.capacity() = {}", keys.capacity());
let tracker = get_size2::StandardTracker::new();
assert_eq!(
nunny_vec_heap_size_helper(&keys, tracker).0,
CidWrapper::get_stack_size() * usize::from(keys.capacity())
);
}
#[test]
fn test_derive_macro() {
#[derive(GetSize)]
struct A {
#[get_size(ignore)]
_cid: Cid,
}
#[derive(GetSize)]
struct B {
#[get_size(size = 0)]
_cid: Cid,
}
#[derive(GetSize)]
struct C {
#[get_size(size = 8)]
_cid: Cid,
}
let _cid = Cid::default();
let a = vec![A { _cid }];
assert_eq!(
a.get_heap_size(),
std::mem::size_of_val(&_cid) * a.capacity()
);
let b = vec![B { _cid }];
assert_eq!(
b.get_heap_size(),
std::mem::size_of_val(&_cid) * b.capacity()
);
let c = vec![C { _cid }];
assert_eq!(
c.get_heap_size(),
(std::mem::size_of_val(&_cid) + 8) * c.capacity()
);
}
}