use core::marker::{PhantomData, PhantomPinned};
use core::num::*;
use core::sync::atomic::*;
#[cfg(feature = "std")]
use core::ops::Deref;
use crate::{Boolean, False, FlatType, MemSize, SizeFlags, True};
use hashbrown::HashMap;
#[cfg(not(feature = "std"))]
use alloc::collections::VecDeque;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::String, vec::Vec};
#[cfg(feature = "std")]
use std::collections::VecDeque;
macro_rules! impl_size_of {
($flat:ty; $($ty:ty),*) => {$(
impl FlatType for $ty {
type Flat = $flat;
}
impl MemSize for $ty {
#[inline(always)]
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
)*};
}
impl_size_of! {True;
(), bool, char, f32, f64,
u8, u16, u32, u64, u128, usize,
i8, i16, i32, i64, i128, isize,
AtomicBool,
AtomicI8, AtomicI16, AtomicI32, AtomicIsize,
AtomicU8, AtomicU16, AtomicU32, AtomicUsize,
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
PhantomPinned
}
#[cfg(target_has_atomic = "64")]
impl_size_of! {True; AtomicI64, AtomicU64}
impl FlatType for str {
type Flat = False;
}
impl MemSize for str {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
self.len()
}
}
impl FlatType for String {
type Flat = False;
}
impl MemSize for String {
fn mem_size_rec(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::CAPACITY) {
self.capacity()
} else {
self.len()
}
}
}
impl<T: ?Sized> FlatType for PhantomData<T> {
type Flat = True;
}
impl<T: ?Sized> MemSize for PhantomData<T> {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
0
}
}
impl<T: ?Sized + MemSize> FlatType for &'_ T {
type Flat = False;
}
impl<T: ?Sized + MemSize> MemSize for &'_ T {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
if flags.contains(SizeFlags::FOLLOW_REFS) {
let ptr = *self as *const T as *const () as usize;
if !refs.contains_key(&ptr) {
let inner_size = <T as MemSize>::mem_size_rec(*self, flags, refs);
refs.insert(ptr, inner_size);
}
}
core::mem::size_of::<Self>()
}
}
impl<T: ?Sized + MemSize> FlatType for &'_ mut T {
type Flat = False;
}
impl<T: ?Sized + MemSize> MemSize for &'_ mut T {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<&'_ T as MemSize>::mem_size_rec(&&**self, flags, refs)
}
}
impl<T: FlatType> FlatType for Option<T> {
type Flat = T::Flat;
}
impl<T: MemSize> MemSize for Option<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ self.as_ref().map_or(0, |x| {
<T as MemSize>::mem_size_rec(x, flags, refs) - core::mem::size_of::<T>()
})
}
}
impl<T: FlatType, E: FlatType> FlatType for Result<T, E> {
type Flat = <T::Flat as Boolean>::And<E::Flat>;
}
impl<T: MemSize, E: MemSize> MemSize for Result<T, E> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ match self {
Ok(t) => <T as MemSize>::mem_size_rec(t, flags, refs) - core::mem::size_of::<T>(),
Err(e) => <E as MemSize>::mem_size_rec(e, flags, refs) - core::mem::size_of::<E>(),
}
}
}
impl<T: ?Sized> FlatType for Box<T> {
type Flat = False;
}
impl<T: ?Sized + MemSize> MemSize for Box<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() + <T as MemSize>::mem_size_rec(self.as_ref(), flags, refs)
}
}
#[cfg(feature = "std")]
#[repr(C, align(2))]
struct RcInner<T: ?Sized> {
_strong: std::cell::Cell<usize>,
_weak: std::cell::Cell<usize>,
_data: T,
}
#[cfg(feature = "std")]
impl<T> FlatType for std::rc::Rc<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::rc::Rc<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
if flags.contains(SizeFlags::FOLLOW_RCS) {
let ptr = std::rc::Rc::as_ptr(self) as usize;
if !refs.contains_key(&ptr) {
let inner_size = core::mem::size_of::<RcInner<T>>()
+ <T as MemSize>::mem_size_rec(self.as_ref(), flags, refs)
- core::mem::size_of::<T>();
refs.insert(ptr, inner_size);
}
}
core::mem::size_of::<Self>()
}
}
#[cfg(feature = "std")]
impl<T> FlatType for std::sync::Arc<T> {
type Flat = False;
}
#[cfg(feature = "std")]
#[repr(C, align(2))]
struct ArcInner<T: ?Sized> {
_strong: core::sync::atomic::AtomicUsize,
_weak: core::sync::atomic::AtomicUsize,
_data: T,
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::Arc<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
if flags.contains(SizeFlags::FOLLOW_RCS) {
let ptr = std::sync::Arc::as_ptr(self) as usize;
if !refs.contains_key(&ptr) {
let inner_size = core::mem::size_of::<ArcInner<T>>()
+ <T as MemSize>::mem_size_rec(self.as_ref(), flags, refs)
- core::mem::size_of::<T>();
refs.insert(ptr, inner_size);
}
}
core::mem::size_of::<Self>()
}
}
pub trait MemSizeHelper<T: Boolean> {
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize;
}
impl<T: FlatType> FlatType for [T] {
type Flat = False;
}
impl<T: FlatType> MemSize for [T]
where
[T]: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<[T] as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(self, flags, refs)
}
}
impl<T: FlatType + MemSize> MemSizeHelper<True> for [T] {
#[inline(always)]
fn mem_size_impl(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of_val(self)
}
}
impl<T: FlatType + MemSize> MemSizeHelper<False> for [T] {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
self.iter()
.map(|x| <T as MemSize>::mem_size_rec(x, flags, refs))
.sum::<usize>()
}
}
impl<T: FlatType, const N: usize> FlatType for [T; N] {
type Flat = T::Flat;
}
impl<T: FlatType, const N: usize> MemSize for [T; N]
where
[T; N]: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<[T; N] as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(self, flags, refs)
}
}
impl<T: MemSize, const N: usize> MemSizeHelper<True> for [T; N] {
#[inline(always)]
fn mem_size_impl(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
impl<T: MemSize, const N: usize> MemSizeHelper<False> for [T; N] {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ self
.iter()
.map(|x| <T as MemSize>::mem_size_rec(x, flags, refs) - core::mem::size_of::<T>())
.sum::<usize>()
}
}
impl<T> FlatType for Vec<T> {
type Flat = False;
}
impl<T: FlatType> MemSize for Vec<T>
where
Vec<T>: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<Vec<T> as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(self, flags, refs)
}
}
impl<T: FlatType + MemSize> MemSizeHelper<True> for Vec<T> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::CAPACITY) {
self.capacity()
} else {
self.len()
} * core::mem::size_of::<T>()
}
}
impl<T: FlatType + MemSize> MemSizeHelper<False> for Vec<T> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ self
.iter()
.map(|x| <T as MemSize>::mem_size_rec(x, flags, refs))
.sum::<usize>()
+ if flags.contains(SizeFlags::CAPACITY) {
(self.capacity() - self.len()) * core::mem::size_of::<T>()
} else {
0
}
}
}
impl<T> FlatType for VecDeque<T> {
type Flat = False;
}
impl<T: FlatType> MemSize for VecDeque<T>
where
VecDeque<T>: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<VecDeque<T> as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(self, flags, refs)
}
}
impl<T: FlatType + MemSize> MemSizeHelper<True> for VecDeque<T> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::CAPACITY) {
self.capacity()
} else {
self.len()
} * core::mem::size_of::<T>()
}
}
impl<T: FlatType + MemSize> MemSizeHelper<False> for VecDeque<T> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ self
.iter()
.map(|x| <T as MemSize>::mem_size_rec(x, flags, refs))
.sum::<usize>()
+ if flags.contains(SizeFlags::CAPACITY) {
(self.capacity() - self.len()) * core::mem::size_of::<T>()
} else {
0
}
}
}
macro_rules! and_chain {
($single:ty) => { $single };
($first:ty, $($rest:ty),+) => { <$first as Boolean>::And<and_chain!($($rest),+)> };
}
macro_rules! impl_tuples_muncher {
() => {};
(($idx:tt => $ty:ident), $(($i:tt => $t:ident),)*) => {
impl_tuples_muncher!([($idx => $ty);] $(($i => $t),)*);
impl_tuples_muncher!($(($i => $t),)*);
};
([$(($accIdx: tt => $accTyp: ident);)+] ($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
impl_tuples_muncher!([($idx => $typ); $(($accIdx => $accTyp); )*] $( ($nidx => $ntyp), ) *);
};
([($idx:tt => $ty:ident); $( ($nidx:tt => $nty:ident); )*]) => {
impl<$ty: FlatType, $($nty: FlatType,)*> FlatType for ($ty, $($nty,)*) {
type Flat = and_chain!(<$ty as FlatType>::Flat $(, <$nty as FlatType>::Flat)*);
}
impl<$ty: MemSize, $($nty: MemSize,)*> MemSize for ($ty, $($nty,)*) {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let mut bytes = ::core::mem::size_of::<Self>();
bytes += <$ty as MemSize>::mem_size_rec(&self.$idx, flags, refs) - ::core::mem::size_of::<$ty>();
$( bytes += <$nty as MemSize>::mem_size_rec(&self.$nidx, flags, refs) - ::core::mem::size_of::<$nty>(); )*
bytes
}
}
impl<$ty, $($nty,)* R> FlatType for fn($ty, $($nty,)*) -> R {
type Flat = True;
}
impl<$ty, $($nty,)* R> MemSize for fn($ty, $($nty,)*) -> R {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
::core::mem::size_of::<Self>()
}
}
}
}
impl_tuples_muncher!(
(9 => T9),
(8 => T8),
(7 => T7),
(6 => T6),
(5 => T5),
(4 => T4),
(3 => T3),
(2 => T2),
(1 => T1),
(0 => T0),
);
impl<R> FlatType for fn() -> R {
type Flat = True;
}
impl<R> MemSize for fn() -> R {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
impl<Idx: FlatType> FlatType for core::ops::Range<Idx> {
type Flat = Idx::Flat;
}
impl<Idx: MemSize> MemSize for core::ops::Range<Idx> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ <Idx as MemSize>::mem_size_rec(&self.start, flags, refs)
+ <Idx as MemSize>::mem_size_rec(&self.end, flags, refs)
- 2 * core::mem::size_of::<Idx>()
}
}
impl<Idx: FlatType> FlatType for core::ops::RangeFrom<Idx> {
type Flat = Idx::Flat;
}
impl<Idx: MemSize> MemSize for core::ops::RangeFrom<Idx> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() + <Idx as MemSize>::mem_size_rec(&self.start, flags, refs)
- core::mem::size_of::<Idx>()
}
}
impl<Idx: FlatType> FlatType for core::ops::RangeInclusive<Idx> {
type Flat = Idx::Flat;
}
impl<Idx: MemSize> MemSize for core::ops::RangeInclusive<Idx> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ <Idx as MemSize>::mem_size_rec(self.start(), flags, refs)
+ <Idx as MemSize>::mem_size_rec(self.end(), flags, refs)
- 2 * core::mem::size_of::<Idx>()
}
}
impl<Idx: FlatType> FlatType for core::ops::RangeTo<Idx> {
type Flat = Idx::Flat;
}
impl<Idx: MemSize> MemSize for core::ops::RangeTo<Idx> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() + <Idx as MemSize>::mem_size_rec(&self.end, flags, refs)
- core::mem::size_of::<Idx>()
}
}
impl<Idx: FlatType> FlatType for core::ops::RangeToInclusive<Idx> {
type Flat = Idx::Flat;
}
impl<Idx: MemSize> MemSize for core::ops::RangeToInclusive<Idx> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() + <Idx as MemSize>::mem_size_rec(&self.end, flags, refs)
- core::mem::size_of::<Idx>()
}
}
#[cfg(feature = "rand")]
impl_size_of!(True;
rand::rngs::SmallRng,
rand::rngs::ThreadRng,
rand::rngs::StdRng
);
impl<T: FlatType> FlatType for core::cell::RefCell<T> {
type Flat = T::Flat;
}
impl<T: MemSize> MemSize for core::cell::RefCell<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
if let Ok(borrow) = self.try_borrow() {
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ <T as MemSize>::mem_size_rec(&*borrow, flags, refs)
} else {
core::mem::size_of::<Self>()
}
}
}
impl<T: FlatType> FlatType for core::cell::Cell<T> {
type Flat = T::Flat;
}
impl<T: MemSize> MemSize for core::cell::Cell<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let borrow = unsafe { &*self.as_ptr() };
<T as MemSize>::mem_size_rec(borrow, flags, refs)
}
}
impl<T: FlatType> FlatType for core::cell::OnceCell<T> {
type Flat = T::Flat;
}
impl<T: MemSize> MemSize for core::cell::OnceCell<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let mut size = core::mem::size_of::<Self>();
if let Some(t) = self.get() {
size += <T as MemSize>::mem_size_rec(t, flags, refs) - core::mem::size_of::<T>();
}
size
}
}
impl<T: FlatType> FlatType for core::cell::UnsafeCell<T> {
type Flat = T::Flat;
}
impl<T: MemSize> MemSize for core::cell::UnsafeCell<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let borrow = unsafe { &*self.get() };
<T as MemSize>::mem_size_rec(borrow, flags, refs)
}
}
#[cfg(feature = "std")]
impl<T: FlatType> FlatType for std::sync::Mutex<T> {
type Flat = T::Flat;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::Mutex<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let guard = self.lock().unwrap_or_else(|e| e.into_inner());
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ <T as MemSize>::mem_size_rec(&guard, flags, refs)
}
}
#[cfg(feature = "std")]
impl<T: FlatType> FlatType for std::sync::RwLock<T> {
type Flat = T::Flat;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::RwLock<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
let guard = self.read().unwrap_or_else(|e| e.into_inner());
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ <T as MemSize>::mem_size_rec(&guard, flags, refs)
}
}
#[cfg(feature = "std")]
#[inline(always)]
fn deref_pointer_size<M>(obj: &M, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize
where
M: Deref<Target: MemSize + Sized>,
{
core::mem::size_of::<M>()
+ if flags.contains(SizeFlags::FOLLOW_REFS) {
<M::Target as MemSize>::mem_size_rec(obj.deref(), flags, refs)
- core::mem::size_of::<M::Target>()
} else {
0
}
}
#[cfg(feature = "std")]
impl<T> FlatType for std::sync::MutexGuard<'_, T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::MutexGuard<'_, T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
deref_pointer_size(self, flags, refs)
}
}
#[cfg(feature = "std")]
impl<T> FlatType for std::sync::RwLockReadGuard<'_, T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::RwLockReadGuard<'_, T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
deref_pointer_size(self, flags, refs)
}
}
#[cfg(feature = "std")]
impl<T> FlatType for std::sync::RwLockWriteGuard<'_, T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::sync::RwLockWriteGuard<'_, T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
deref_pointer_size(self, flags, refs)
}
}
#[cfg(feature = "std")]
impl FlatType for std::path::Path {
type Flat = False;
}
#[cfg(feature = "std")]
impl MemSize for std::path::Path {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<std::ffi::OsStr as MemSize>::mem_size_rec(self.as_os_str(), flags, refs)
}
}
#[cfg(feature = "std")]
impl FlatType for std::path::PathBuf {
type Flat = False;
}
#[cfg(feature = "std")]
impl MemSize for std::path::PathBuf {
fn mem_size_rec(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::CAPACITY) {
self.capacity()
} else {
self.as_os_str().len()
}
}
}
#[cfg(feature = "std")]
impl FlatType for std::ffi::OsStr {
type Flat = False;
}
#[cfg(feature = "std")]
impl MemSize for std::ffi::OsStr {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
self.as_encoded_bytes().len()
}
}
#[cfg(feature = "std")]
impl FlatType for std::ffi::OsString {
type Flat = False;
}
#[cfg(feature = "std")]
impl MemSize for std::ffi::OsString {
fn mem_size_rec(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::CAPACITY) {
self.capacity()
} else {
self.len()
}
}
}
#[cfg(feature = "std")]
impl_size_of!(False;
std::fs::File,
std::fs::OpenOptions,
std::fs::Metadata,
std::fs::FileType,
std::fs::FileTimes,
std::fs::Permissions
);
#[cfg(feature = "std")]
impl<T> FlatType for std::io::BufReader<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize + std::io::Read> MemSize for std::io::BufReader<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ self.capacity()
+ <T as MemSize>::mem_size_rec(self.get_ref(), flags, refs)
}
}
#[cfg(feature = "std")]
impl<T: std::io::Write> FlatType for std::io::BufWriter<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize + std::io::Write> MemSize for std::io::BufWriter<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ self.capacity()
+ <T as MemSize>::mem_size_rec(self.get_ref(), flags, refs)
}
}
#[cfg(feature = "std")]
impl<T> FlatType for std::io::Cursor<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: MemSize> MemSize for std::io::Cursor<T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ <T as MemSize>::mem_size_rec(self.get_ref(), flags, refs)
}
}
#[cfg(feature = "std")]
impl_size_of!(True;
std::net::Ipv4Addr,
std::net::Ipv6Addr,
std::net::IpAddr,
std::net::SocketAddrV4,
std::net::SocketAddrV6,
std::net::SocketAddr
);
#[cfg(feature = "std")]
impl_size_of!(True;
std::time::Duration,
std::time::Instant,
std::time::SystemTime,
std::time::SystemTimeError
);
#[cfg(feature = "mmap-rs")]
impl FlatType for mmap_rs::Mmap {
type Flat = False;
}
#[cfg(feature = "mmap-rs")]
impl MemSize for mmap_rs::Mmap {
fn mem_size_rec(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::FOLLOW_REFS) {
self.len()
} else {
0
}
}
}
#[cfg(feature = "mmap-rs")]
impl FlatType for mmap_rs::MmapMut {
type Flat = False;
}
#[cfg(feature = "mmap-rs")]
impl MemSize for mmap_rs::MmapMut {
fn mem_size_rec(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
+ if flags.contains(SizeFlags::FOLLOW_REFS) {
self.len()
} else {
0
}
}
}
#[cfg(feature = "std")]
#[cfg(all(
any(target_arch = "x86_64", target_arch = "x86"),
any(target_feature = "sse2", target_env = "msvc")
))]
const GROUP_WIDTH: usize = 16;
#[cfg(feature = "std")]
#[cfg(not(all(
any(target_arch = "x86_64", target_arch = "x86"),
any(target_feature = "sse2", target_env = "msvc")
)))]
const GROUP_WIDTH: usize = 8;
#[cfg(feature = "std")]
fn capacity_to_buckets(cap: usize) -> Option<usize> {
if cap == 0 {
return Some(0);
}
if cap < 8 {
return Some(if cap < 4 { 4 } else { 8 });
}
let adjusted_cap = cap.checked_mul(8)? / 7;
Some(adjusted_cap.next_power_of_two())
}
#[cfg(feature = "std")]
impl<T> FlatType for std::collections::HashSet<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: FlatType> MemSize for std::collections::HashSet<T>
where
std::collections::HashSet<T>: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<std::collections::HashSet<T> as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(
self, flags, refs,
)
}
}
#[cfg(feature = "std")]
fn fix_set_for_capacity<K>(
hash_set: &std::collections::HashSet<K>,
size: usize,
flags: SizeFlags,
) -> usize {
let capacity = if flags.contains(SizeFlags::CAPACITY) {
hash_set.capacity()
} else {
hash_set.len()
};
let buckets = capacity_to_buckets(capacity).unwrap_or(usize::MAX);
core::mem::size_of::<std::collections::HashSet<K>>()
+ size
+ (buckets - hash_set.len()) * core::mem::size_of::<K>()
+ buckets * core::mem::size_of::<u8>()
+ if buckets > 0 { GROUP_WIDTH } else { 0 }
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize> MemSizeHelper<True> for std::collections::HashSet<K> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
fix_set_for_capacity(self, core::mem::size_of::<K>() * self.len(), flags)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize> MemSizeHelper<False> for std::collections::HashSet<K> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
fix_set_for_capacity(
self,
self.iter()
.map(|x| <K as MemSize>::mem_size_rec(x, flags, refs))
.sum::<usize>(),
flags,
)
}
}
#[cfg(feature = "std")]
pub trait MemSizeHelper2<K: Boolean, V: Boolean> {
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize;
}
#[cfg(feature = "std")]
impl<K, V> FlatType for std::collections::HashMap<K, V> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<K: FlatType, V: FlatType> MemSize for std::collections::HashMap<K, V>
where
std::collections::HashMap<K, V>: MemSizeHelper2<<K as FlatType>::Flat, <V as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<std::collections::HashMap<K, V> as MemSizeHelper2<
<K as FlatType>::Flat,
<V as FlatType>::Flat,
>>::mem_size_impl(self, flags, refs)
}
}
#[cfg(feature = "std")]
fn fix_map_for_capacity<K, V>(
hash_map: &std::collections::HashMap<K, V>,
size: usize,
flags: SizeFlags,
) -> usize {
let capacity = if flags.contains(SizeFlags::CAPACITY) {
hash_map.capacity()
} else {
hash_map.len()
};
let buckets = capacity_to_buckets(capacity).unwrap_or(usize::MAX);
core::mem::size_of::<std::collections::HashMap<K, V>>()
+ size
+ (buckets - hash_map.len()) * (core::mem::size_of::<K>() + core::mem::size_of::<V>())
+ buckets * core::mem::size_of::<u8>()
+ if buckets > 0 { GROUP_WIDTH } else { 0 }
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<True, True>
for std::collections::HashMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
fix_map_for_capacity(
self,
(core::mem::size_of::<K>() + core::mem::size_of::<V>()) * self.len(),
flags,
)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<True, False>
for std::collections::HashMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
fix_map_for_capacity(
self,
(core::mem::size_of::<K>()) * self.len()
+ self
.values()
.map(|v| <V as MemSize>::mem_size_rec(v, flags, refs))
.sum::<usize>(),
flags,
)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<False, True>
for std::collections::HashMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
fix_map_for_capacity(
self,
self.keys()
.map(|k| <K as MemSize>::mem_size_rec(k, flags, refs))
.sum::<usize>()
+ (core::mem::size_of::<V>()) * self.len(),
flags,
)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<False, False>
for std::collections::HashMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
fix_map_for_capacity(
self,
self.iter()
.map(|(k, v)| {
<K as MemSize>::mem_size_rec(k, flags, refs)
+ <V as MemSize>::mem_size_rec(v, flags, refs)
})
.sum::<usize>(),
flags,
)
}
}
#[cfg(feature = "std")]
fn estimate_btree_size<K, V>(len: usize, item_heap_size: usize) -> usize {
if len == 0 {
return 0;
}
const B: usize = 6;
const CAPACITY: usize = 2 * B - 1;
let ptr_size = core::mem::size_of::<usize>();
let header_size = 2 * core::mem::size_of::<usize>();
let align_up = |size: usize, align: usize| -> usize { (size + align - 1) & !(align - 1) };
let k_size = core::mem::size_of::<K>();
let v_size = core::mem::size_of::<V>();
let mut leaf_size = header_size;
leaf_size = align_up(leaf_size, core::mem::align_of::<K>());
leaf_size += k_size * CAPACITY;
leaf_size = align_up(leaf_size, core::mem::align_of::<V>());
leaf_size += v_size * CAPACITY;
let mut internal_size = leaf_size;
internal_size = align_up(internal_size, core::mem::align_of::<usize>());
internal_size += ptr_size * (CAPACITY + 1);
let avg_node_size = (leaf_size * B + internal_size) / (B + 1);
let heap_size = if len <= CAPACITY {
leaf_size
} else {
(len / B) * avg_node_size
};
heap_size + item_heap_size
}
#[cfg(feature = "std")]
impl<T> FlatType for std::collections::BTreeSet<T> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<T: FlatType> MemSize for std::collections::BTreeSet<T>
where
std::collections::BTreeSet<T>: MemSizeHelper<<T as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<std::collections::BTreeSet<T> as MemSizeHelper<<T as FlatType>::Flat>>::mem_size_impl(
self, flags, refs,
)
}
}
#[cfg(feature = "std")]
impl<T: FlatType + MemSize> MemSizeHelper<True> for std::collections::BTreeSet<T> {
#[inline(always)]
fn mem_size_impl(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeSet<T>>()
+ estimate_btree_size::<T, ()>(self.len(), 0)
}
}
#[cfg(feature = "std")]
impl<T: FlatType + MemSize> MemSizeHelper<False> for std::collections::BTreeSet<T> {
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeSet<T>>()
+ estimate_btree_size::<T, ()>(
self.len(),
self.iter()
.map(|x| {
<T as MemSize>::mem_size_rec(x, flags, refs) - core::mem::size_of::<T>()
})
.sum::<usize>(),
)
}
}
#[cfg(feature = "std")]
impl<K, V> FlatType for std::collections::BTreeMap<K, V> {
type Flat = False;
}
#[cfg(feature = "std")]
impl<K: FlatType, V: FlatType> MemSize for std::collections::BTreeMap<K, V>
where
std::collections::BTreeMap<K, V>: MemSizeHelper2<<K as FlatType>::Flat, <V as FlatType>::Flat>,
{
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
<std::collections::BTreeMap<K, V> as MemSizeHelper2<
<K as FlatType>::Flat,
<V as FlatType>::Flat,
>>::mem_size_impl(self, flags, refs)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<True, True>
for std::collections::BTreeMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeMap<K, V>>()
+ estimate_btree_size::<K, V>(self.len(), 0)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<True, False>
for std::collections::BTreeMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeMap<K, V>>()
+ estimate_btree_size::<K, V>(
self.len(),
self.values()
.map(|v| {
<V as MemSize>::mem_size_rec(v, flags, refs) - core::mem::size_of::<V>()
})
.sum::<usize>(),
)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<False, True>
for std::collections::BTreeMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeMap<K, V>>()
+ estimate_btree_size::<K, V>(
self.len(),
self.keys()
.map(|k| {
<K as MemSize>::mem_size_rec(k, flags, refs) - core::mem::size_of::<K>()
})
.sum::<usize>(),
)
}
}
#[cfg(feature = "std")]
impl<K: FlatType + MemSize, V: FlatType + MemSize> MemSizeHelper2<False, False>
for std::collections::BTreeMap<K, V>
{
#[inline(always)]
fn mem_size_impl(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<std::collections::BTreeMap<K, V>>()
+ estimate_btree_size::<K, V>(
self.len(),
self.iter()
.map(|(k, v)| {
<K as MemSize>::mem_size_rec(k, flags, refs) - core::mem::size_of::<K>()
+ <V as MemSize>::mem_size_rec(v, flags, refs)
- core::mem::size_of::<V>()
})
.sum::<usize>(),
)
}
}
impl<H> FlatType for core::hash::BuildHasherDefault<H> {
type Flat = True;
}
impl<H> MemSize for core::hash::BuildHasherDefault<H> {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
debug_assert_eq!(core::mem::size_of::<Self>(), 0);
0
}
}
#[cfg(feature = "std")]
impl FlatType for std::hash::DefaultHasher {
type Flat = True;
}
#[cfg(feature = "std")]
impl MemSize for std::hash::DefaultHasher {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
#[cfg(feature = "std")]
impl FlatType for std::collections::hash_map::RandomState {
type Flat = True;
}
#[cfg(feature = "std")]
impl MemSize for std::collections::hash_map::RandomState {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
impl_size_of!(True; core::alloc::Layout);
impl<T: ?Sized> FlatType for core::ptr::NonNull<T> {
type Flat = True;
}
impl<T: ?Sized> MemSize for core::ptr::NonNull<T> {
fn mem_size_rec(&self, _flags: SizeFlags, _refs: &mut HashMap<usize, usize>) -> usize {
core::mem::size_of::<Self>()
}
}
#[cfg(feature = "maligned")]
impl_size_of!(True;
maligned::A2,
maligned::A4,
maligned::A8,
maligned::A16,
maligned::A32,
maligned::A64,
maligned::A128,
maligned::A256,
maligned::A512
);
#[cfg(feature = "maligned")]
impl<A: maligned::Alignment, T: MemSize + FlatType> FlatType for maligned::Aligned<A, T> {
type Flat = T::Flat;
}
#[cfg(feature = "maligned")]
impl<A: maligned::Alignment, T: MemSize> MemSize for maligned::Aligned<A, T> {
fn mem_size_rec(&self, flags: SizeFlags, refs: &mut HashMap<usize, usize>) -> usize {
use core::ops::Deref;
core::mem::size_of::<Self>() - core::mem::size_of::<T>()
+ <T as MemSize>::mem_size_rec(self.deref(), flags, refs)
}
}
#[cfg(feature = "half")]
impl_size_of!(True; half::f16, half::bf16);