extern crate self as mm0_deepsize;
use std::mem::{size_of, size_of_val};
use std::sync::Arc;
use std::rc::Rc;
use std::collections::HashSet;
use mm0_deepsize_derive::DeepSizeOf;
pub trait DeepSizeOf {
fn deep_size_of(&self) -> usize {
self.deep_size_of_with(&mut Context::default())
}
fn deep_size_of_with(&self, context: &mut Context) -> usize {
size_of_val(self) + self.deep_size_of_children(context)
}
fn deep_size_of_children(&self, context: &mut Context) -> usize;
}
#[derive(Debug, Default)]
pub struct Context {
arcs: HashSet<usize>,
rcs: HashSet<usize>,
}
impl Context {
fn add_arc<T: ?Sized>(&mut self, arc: &Arc<T>) {
let pointer: usize = unsafe { *<*const _>::cast(arc) };
self.arcs.insert(pointer);
}
fn contains_arc<T: ?Sized>(&self, arc: &Arc<T>) -> bool {
let pointer: usize = unsafe { *<*const _>::cast(arc) };
self.arcs.contains(&pointer)
}
fn add_rc<T: ?Sized>(&mut self, rc: &Rc<T>) {
let pointer: usize = unsafe { *<*const _>::cast(rc) };
self.rcs.insert(pointer);
}
fn contains_rc<T: ?Sized>(&self, rc: &Rc<T>) -> bool {
let pointer: usize = unsafe { *<*const _>::cast(rc) };
self.rcs.contains(&pointer)
}
fn deep_size_of_arc<T: ?Sized>(&mut self, arc: &Arc<T>, f: impl FnOnce(&T, &mut Self) -> usize) -> usize {
if self.contains_arc(arc) {
0
} else {
self.add_arc(arc);
f(&*arc, self)
}
}
fn deep_size_of_rc<T: ?Sized>(&mut self, rc: &Rc<T>, f: impl FnOnce(&T, &mut Self) -> usize) -> usize {
if self.contains_rc(rc) {
0
} else {
self.add_rc(rc);
f(&*rc, self)
}
}
}
impl<T: DeepSizeOf> DeepSizeOf for Vec<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.iter().map(|child| child.deep_size_of_children(context)).sum::<usize>()
+ self.capacity() * size_of::<T>()
}
}
impl<T: DeepSizeOf> DeepSizeOf for std::collections::VecDeque<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.iter().map(|child| child.deep_size_of_children(context)).sum::<usize>()
+ self.capacity() * size_of::<T>()
}
}
impl<K: DeepSizeOf, V: DeepSizeOf, S> DeepSizeOf for std::collections::HashMap<K, V, S> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.iter()
.fold(0, |sum, (key, val)| {
sum + key.deep_size_of_children(context)
+ val.deep_size_of_children(context)
})
+ self.capacity() * size_of::<Option<(u64, K, V)>>()
}
}
impl<T: DeepSizeOf, S> DeepSizeOf for std::collections::HashSet<T, S> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.iter()
.fold(0, |sum, item| sum + item.deep_size_of_children(context))
+ self.capacity() * size_of::<Option<(u64, T, ())>>()
}
}
impl<K: Ord + DeepSizeOf, V: DeepSizeOf> DeepSizeOf for std::collections::BTreeMap<K, V> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
const B: usize = 6;
const MIN: usize = 2 * B - 1;
const MAX: usize = B - 1;
let node_overhead = size_of::<(usize, u32, [(K, V); MAX], [usize; B])>();
let internal: usize = self.iter().map(|(key, val)|
key.deep_size_of_children(context) +
val.deep_size_of_children(context)).sum();
#[allow(clippy::integer_division)]
{ internal + self.len() * node_overhead * 2 / (MAX + MIN) }
}
}
impl<T: DeepSizeOf + ?Sized> DeepSizeOf for Box<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
let val: &T = &*self;
size_of_val(val) + val.deep_size_of_children(context)
}
}
impl<T: DeepSizeOf + ?Sized> DeepSizeOf for Arc<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
context.deep_size_of_arc(self, |val, context| val.deep_size_of_with(context))
}
}
impl<T: DeepSizeOf + ?Sized> DeepSizeOf for Rc<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
context.deep_size_of_rc(self, |val, context| val.deep_size_of_with(context))
}
}
impl<T: DeepSizeOf> DeepSizeOf for [T] {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.iter().map(|child| child.deep_size_of_children(context)).sum()
}
}
impl<O: DeepSizeOf, T: ?Sized> DeepSizeOf for owning_ref::OwningRef<O, T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.as_owner().deep_size_of_children(context)
}
}
#[macro_export]
macro_rules! deep_size_0 {
($($({$($gen:tt)*})? $type:ty),+) => {
$($crate::deep_size_0!(@IMPL $({$($gen)*})? $type);)+
};
(@IMPL $type:ty) => {
$crate::deep_size_0!(@GO {} $type);
};
(@IMPL {$($gen:tt)*} $type:ty) => {
$crate::deep_size_0!(@GO {$($gen)*} $type);
};
(@GO {!Copy $($($gen:tt)+)?} $type:ty) => {
impl$(<$($gen)+>)? $crate::DeepSizeOf for $type {
#[inline(always)]
fn deep_size_of_children(&self, _: &mut $crate::Context) -> usize { 0 }
}
};
(@GO {$($($gen:tt)+)?} $type:ty) => {
const _: fn() = || {
fn assert_copy<T: ?Sized + Copy>() {}
fn go$(<$($gen)+>)?() {assert_copy::<$type>()}
};
$crate::deep_size_0!(@GO {!Copy $($($gen)+)?} $type);
};
}
use std::sync::atomic;
deep_size_0!(
u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,
bool, char, f32, f64, (), {!Copy} str,
{!Copy} atomic::AtomicBool, {!Copy} atomic::AtomicIsize, {!Copy} atomic::AtomicUsize,
{T: ?Sized} &T,
{!Copy T} std::cell::Cell<T>,
{!Copy T} std::rc::Weak<T>,
{!Copy T} std::mem::MaybeUninit<T>,
{T: ?Sized} core::marker::PhantomData<T>,
{!Copy} dyn std::error::Error + Send + Sync,
{!Copy T} futures::channel::oneshot::Sender<T>
);
impl DeepSizeOf for String {
fn deep_size_of_children(&self, _: &mut Context) -> usize { self.capacity() }
}
impl<T: DeepSizeOf> DeepSizeOf for Option<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
match self {
Some(t) => t.deep_size_of_children(context),
None => 0,
}
}
}
impl<R: DeepSizeOf, E: DeepSizeOf> DeepSizeOf for core::result::Result<R, E> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
match self {
Ok(r) => r.deep_size_of_children(context),
Err(e) => e.deep_size_of_children(context),
}
}
}
macro_rules! deep_size_array {
($($num:tt)*) => {
$(
impl<T: DeepSizeOf> DeepSizeOf for [T; $num] {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.as_ref().deep_size_of_children(context)
}
}
)*
};
}
deep_size_array!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
macro_rules! deep_size_tuple {
(@TUPLE $($n:tt $T:ident)+) => {
impl<$($T: DeepSizeOf,)+> DeepSizeOf for ($($T,)+) {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
0 $( + self.$n.deep_size_of_children(context))+
}
}
};
(($($args:tt)*)) => {};
(($($args:tt)*) $n0:tt $T0:ident $($rest:tt)*) => {
deep_size_tuple!(@TUPLE $($args)* $n0 $T0);
deep_size_tuple!(($($args)* $n0 $T0) $($rest)*);
};
}
deep_size_tuple!(() 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J);
impl DeepSizeOf for std::path::PathBuf {
fn deep_size_of_children(&self, _: &mut Context) -> usize { self.capacity() }
}
impl DeepSizeOf for num::BigUint {
fn deep_size_of_children(&self, _: &mut Context) -> usize {
unsafe { &*<*const _>::cast::<Vec<u32>>(self) }.capacity()
}
}
impl DeepSizeOf for num::BigInt {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
self.magnitude().deep_size_of_children(context)
}
}
impl DeepSizeOf for lsp_types::Url {
fn deep_size_of_children(&self, _: &mut Context) -> usize {
self.as_str().len()
}
}
impl<T: DeepSizeOf> DeepSizeOf for std::cell::RefCell<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
if let Ok(g) = self.try_borrow() {
(*g).deep_size_of_with(context)
} else {0}
}
}
impl<T: DeepSizeOf> DeepSizeOf for std::sync::Mutex<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
if let Ok(g) = self.try_lock() {
(*g).deep_size_of_with(context)
} else {0}
}
}
impl<T: DeepSizeOf> DeepSizeOf for futures::lock::Mutex<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
if let Some(g) = self.try_lock() {
(*g).deep_size_of_with(context)
} else {0}
}
}
impl<T: DeepSizeOf> DeepSizeOf for typed_arena::Arena<T> {
fn deep_size_of_children(&self, context: &mut Context) -> usize {
#[derive(DeepSizeOf)]
struct Arena<T> {
_chunks: std::cell::RefCell<ChunkList<T>>,
}
#[derive(DeepSizeOf)]
struct ChunkList<T> {
_current: Vec<T>,
_rest: Vec<Vec<T>>,
}
#[allow(clippy::transmute_ptr_to_ptr)]
let this: &Arena<T> = unsafe {std::mem::transmute(self)};
this.deep_size_of_children(context)
}
}
impl DeepSizeOf for memmap::Mmap {
fn deep_size_of_children(&self, _: &mut Context) -> usize { size_of_val(&**self) }
}