use core::marker::PhantomPinned;
use core::num::*;
use core::{marker::PhantomData, sync::atomic::*};
use crate::{DbgFlags, FlatType, HashSet, MemDbgImpl, RefDisplay};
#[cfg(not(feature = "std"))]
use alloc::borrow::{Cow, ToOwned};
#[cfg(not(feature = "std"))]
use alloc::collections::{BinaryHeap, LinkedList, VecDeque};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::String, vec::Vec};
#[cfg(feature = "std")]
use std::borrow::{Cow, ToOwned};
#[cfg(feature = "std")]
use std::collections::{BinaryHeap, LinkedList, VecDeque};
macro_rules! impl_mem_dbg {
($($ty:ty),*) => {$(
impl MemDbgImpl for $ty {}
)*};
}
macro_rules! impl_mem_dbg_for_deref {
($flag:ident, |$self:ident| $get_ptr:expr) => {
fn _mem_dbg_depth_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
field_name: Option<&str>,
is_last: bool,
padded_size: usize,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
if prefix.chars().count() / 2 > max_depth {
return Ok(());
}
if flags.contains(DbgFlags::$flag) {
let $self = self;
let ptr: usize = $get_ptr;
if dbg_refs.contains(&ptr) {
self._mem_dbg_depth_on_impl(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags,
dbg_refs,
RefDisplay::BackReference(ptr),
)
} else {
dbg_refs.insert(ptr);
self._mem_dbg_depth_on_impl(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags,
dbg_refs,
RefDisplay::FirstEncounter(ptr),
)
}
} else {
self._mem_dbg_depth_on_impl(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags,
dbg_refs,
RefDisplay::None,
)
}
}
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
if flags.contains(DbgFlags::$flag) {
let inner = &**self;
let padded_size = core::mem::size_of_val(inner);
inner._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
None,
true,
padded_size,
flags,
dbg_refs,
)
} else {
Ok(())
}
}
};
}
impl_mem_dbg! {
(), 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, str, String
}
#[cfg(target_has_atomic = "64")]
impl_mem_dbg! { AtomicI64, AtomicU64 }
impl<T: ?Sized> MemDbgImpl for PhantomData<T> {}
impl<T: ?Sized + MemDbgImpl> MemDbgImpl for &'_ T {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| *s as *const T as *const () as usize);
}
impl<T: ?Sized + MemDbgImpl> MemDbgImpl for &'_ mut T {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| *s as *const T as *const () as usize);
}
impl<T: ?Sized> MemDbgImpl for *const T {}
impl<T: ?Sized> MemDbgImpl for *mut T {}
impl<T: MemDbgImpl> MemDbgImpl for Option<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
Some(t) => t._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Some"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
),
None => Ok(()),
}
}
}
impl<T: MemDbgImpl, E: MemDbgImpl> MemDbgImpl for Result<T, E> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
Ok(t) => t._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Ok"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
),
Err(e) => e._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Err"),
true,
core::mem::size_of::<E>(),
flags,
dbg_refs,
),
}
}
}
impl<B: MemDbgImpl, C: MemDbgImpl> MemDbgImpl for core::ops::ControlFlow<B, C> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
core::ops::ControlFlow::Break(b) => b._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Break"),
true,
core::mem::size_of::<B>(),
flags,
dbg_refs,
),
core::ops::ControlFlow::Continue(c) => c._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Continue"),
true,
core::mem::size_of::<C>(),
flags,
dbg_refs,
),
}
}
}
impl<T: MemDbgImpl> MemDbgImpl for core::task::Poll<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
core::task::Poll::Ready(t) => t._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Ready"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
),
core::task::Poll::Pending => Ok(()),
}
}
}
impl<T: MemDbgImpl> MemDbgImpl for core::ops::Bound<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
core::ops::Bound::Included(t) => t._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Included"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
),
core::ops::Bound::Excluded(t) => t._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("Excluded"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
),
core::ops::Bound::Unbounded => Ok(()),
}
}
}
impl<T: MemDbgImpl> MemDbgImpl for core::cmp::Reverse<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.0._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("0"),
true,
core::mem::size_of::<T>(),
flags,
dbg_refs,
)
}
}
impl<T: ?Sized + MemDbgImpl> MemDbgImpl for Box<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.as_ref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
impl<B> MemDbgImpl for Cow<'_, B>
where
B: ToOwned + MemDbgImpl + ?Sized,
B::Owned: MemDbgImpl,
{
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self {
Cow::Borrowed(borrowed) if flags.contains(DbgFlags::FOLLOW_REFS) => {
<&B as MemDbgImpl>::_mem_dbg_depth_on(
borrowed,
writer,
total_size,
max_depth,
prefix,
None,
true,
core::mem::size_of::<&B>(),
flags,
dbg_refs,
)
}
Cow::Borrowed(_) => Ok(()),
Cow::Owned(owned) => <B::Owned as MemDbgImpl>::_mem_dbg_rec_on(
owned, writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
),
}
}
}
impl<P: MemDbgImpl> MemDbgImpl for core::pin::Pin<P> {
fn _mem_dbg_depth_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
field_name: Option<&str>,
is_last: bool,
padded_size: usize,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
let pointer = unsafe { &*(self as *const core::pin::Pin<P> as *const P) };
pointer._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags,
dbg_refs,
)
}
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
let pointer = unsafe { &*(self as *const core::pin::Pin<P> as *const P) };
pointer._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::rc::Rc<T> {
impl_mem_dbg_for_deref!(FOLLOW_RCS, |s| std::rc::Rc::as_ptr(s) as usize);
}
#[cfg(not(feature = "std"))]
impl<T: MemDbgImpl> MemDbgImpl for alloc::rc::Rc<T> {
impl_mem_dbg_for_deref!(FOLLOW_RCS, |s| {
alloc::rc::Rc::as_ptr(s) as usize
});
}
#[cfg(feature = "std")]
impl<T: ?Sized> MemDbgImpl for std::rc::Weak<T> {}
#[cfg(not(feature = "std"))]
impl<T: ?Sized> MemDbgImpl for alloc::rc::Weak<T> {}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::Arc<T> {
impl_mem_dbg_for_deref!(FOLLOW_RCS, |s| std::sync::Arc::as_ptr(s) as usize);
}
#[cfg(all(not(feature = "std"), target_has_atomic = "ptr"))]
impl<T: MemDbgImpl> MemDbgImpl for alloc::sync::Arc<T> {
impl_mem_dbg_for_deref!(FOLLOW_RCS, |s| {
alloc::sync::Arc::as_ptr(s) as usize
});
}
#[cfg(feature = "std")]
impl<T: ?Sized> MemDbgImpl for std::sync::Weak<T> {}
#[cfg(all(not(feature = "std"), target_has_atomic = "ptr"))]
impl<T: ?Sized> MemDbgImpl for alloc::sync::Weak<T> {}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for [T] {}
impl<T: FlatType + MemDbgImpl, const N: usize> MemDbgImpl for [T; N] {}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for Vec<T> {}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for BinaryHeap<T> {}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for VecDeque<T> {}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for LinkedList<T> {}
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_tuples_muncher!([($idx => $ty); $(($nidx => $nty);)* ], ($ty, $($nty,)*));
};
([($idx:tt => $ty:ident); $( ($nidx:tt => $nty:ident); )*], $tty:ty) => {
impl<$ty: crate::MemSize + MemDbgImpl, $($nty: crate::MemSize + MemDbgImpl,)*> MemDbgImpl for ($ty, $($nty,)*) {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
let mut _max_idx = $idx;
$(_max_idx = _max_idx.max($nidx);)*
let mut id_sizes = [
($idx, core::mem::offset_of!($tty, $idx), core::mem::size_of::<$ty>()),
$(($nidx, core::mem::offset_of!($tty, $nidx), core::mem::size_of::<$nty>()),)*
];
let n = id_sizes.len();
let total_size_self = core::mem::size_of::<Self>();
id_sizes.sort_unstable_by(|a, b| {
a.1.cmp(&b.1).then(a.2.cmp(&b.2)).then(a.0.cmp(&b.0))
});
for i in 0..n - 1 {
id_sizes[i].1 = id_sizes[i + 1].1 - id_sizes[i].1;
}
id_sizes[n - 1].1 = total_size_self - id_sizes[n - 1].1;
id_sizes.sort_unstable_by_key(|x| x.0);
self.$idx._mem_dbg_depth_on(writer, total_size, max_depth, prefix, Some(stringify!($idx)), $idx == _max_idx, id_sizes[$idx].1, flags, dbg_refs)?;
$(
self.$nidx._mem_dbg_depth_on(writer, total_size, max_depth, prefix, Some(stringify!($nidx)), $nidx == _max_idx, id_sizes[$nidx].1, flags, dbg_refs)?;
)*
Ok(())
}
}
};
}
impl_tuples_muncher!(
(9 => T9),
(8 => T8),
(7 => T7),
(6 => T6),
(5 => T5),
(4 => T4),
(3 => T3),
(2 => T2),
(1 => T1),
(0 => T0),
);
macro_rules! impl_mem_dbg_fn {
() => {
impl<R> MemDbgImpl for fn() -> R {}
};
($first:ident $(, $rest:ident)*) => {
impl<$first, $($rest,)* R> MemDbgImpl for fn($first, $($rest,)*) -> R {}
impl_mem_dbg_fn!($($rest),*);
};
}
impl_mem_dbg_fn!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
#[cfg(feature = "std")]
impl<K: FlatType> MemDbgImpl for std::collections::HashSet<K> where
std::collections::HashSet<K>: crate::MemSize
{
}
#[cfg(feature = "std")]
impl<K: FlatType, V: FlatType> MemDbgImpl for std::collections::HashMap<K, V> where
std::collections::HashMap<K, V>: crate::MemSize
{
}
#[cfg(feature = "std")]
impl<T: FlatType> MemDbgImpl for std::collections::BTreeSet<T> where
std::collections::BTreeSet<T>: crate::MemSize
{
}
#[cfg(feature = "std")]
impl<K: FlatType, V: FlatType> MemDbgImpl for std::collections::BTreeMap<K, V> where
std::collections::BTreeMap<K, V>: crate::MemSize
{
}
#[cfg(feature = "mmap-rs")]
impl_mem_dbg!(mmap_rs::Mmap, mmap_rs::MmapMut);
impl<H> MemDbgImpl for core::hash::BuildHasherDefault<H> {
}
#[cfg(feature = "std")]
impl MemDbgImpl for std::hash::DefaultHasher {
}
#[cfg(feature = "std")]
impl MemDbgImpl for std::collections::hash_map::RandomState {
}
impl MemDbgImpl for core::alloc::Layout {
}
impl<Idx: MemDbgImpl> MemDbgImpl for core::ops::Range<Idx> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.start._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("start"),
false,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)?;
self.end._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("end"),
true,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)
}
}
impl<Idx: MemDbgImpl> MemDbgImpl for core::ops::RangeFrom<Idx> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.start._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("start"),
true,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)
}
}
impl<Idx: MemDbgImpl> MemDbgImpl for core::ops::RangeInclusive<Idx> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.start()._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("start"),
false,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)?;
self.end()._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("end"),
true,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)
}
}
impl<Idx: MemDbgImpl> MemDbgImpl for core::ops::RangeTo<Idx> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.end._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("end"),
true,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)
}
}
impl<Idx: MemDbgImpl> MemDbgImpl for core::ops::RangeToInclusive<Idx> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
_is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.end._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("end"),
true,
core::mem::size_of::<Idx>(),
flags,
dbg_refs,
)
}
}
impl<T: ?Sized> MemDbgImpl for core::ptr::NonNull<T> {
}
#[cfg(feature = "rand")]
impl_mem_dbg!(
rand::rngs::SmallRng,
rand::rngs::StdRng,
rand::rngs::ThreadRng
);
struct MutablyBorrowed;
impl crate::FlatType for MutablyBorrowed {
type Flat = crate::True;
}
impl crate::MemSize for MutablyBorrowed {
fn mem_size_rec(
&self,
_flags: crate::SizeFlags,
_refs: &mut crate::HashMap<usize, usize>,
) -> usize {
0
}
}
impl MemDbgImpl for MutablyBorrowed {
fn _mem_dbg_depth_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
field_name: Option<&str>,
is_last: bool,
padded_size: usize,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self._mem_dbg_depth_on_impl(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags & !DbgFlags::TYPE_NAME,
dbg_refs,
RefDisplay::None,
)
}
}
#[cfg(feature = "std")]
struct Locked;
#[cfg(feature = "std")]
impl crate::FlatType for Locked {
type Flat = crate::True;
}
#[cfg(feature = "std")]
impl crate::MemSize for Locked {
fn mem_size_rec(
&self,
_flags: crate::SizeFlags,
_refs: &mut crate::HashMap<usize, usize>,
) -> usize {
0
}
}
#[cfg(feature = "std")]
impl MemDbgImpl for Locked {
fn _mem_dbg_depth_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
field_name: Option<&str>,
is_last: bool,
padded_size: usize,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self._mem_dbg_depth_on_impl(
writer,
total_size,
max_depth,
prefix,
field_name,
is_last,
padded_size,
flags & !DbgFlags::TYPE_NAME,
dbg_refs,
RefDisplay::None,
)
}
}
impl<T: MemDbgImpl> MemDbgImpl for core::cell::RefCell<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
if let Ok(borrow) = self.try_borrow() {
borrow._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
} else {
MutablyBorrowed._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("<mutably borrowed>"),
true,
0,
flags,
dbg_refs,
)
}
}
}
impl<T: ?Sized> MemDbgImpl for core::cell::Cell<T> {}
impl<T: ?Sized> MemDbgImpl for core::cell::UnsafeCell<T> {}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::Mutex<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self.try_lock() {
Ok(guard) => <T as MemDbgImpl>::_mem_dbg_rec_on(
&*guard, writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
),
Err(std::sync::TryLockError::Poisoned(err)) => {
let guard = err.into_inner();
<T as MemDbgImpl>::_mem_dbg_rec_on(
&*guard, writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
Err(std::sync::TryLockError::WouldBlock) => Locked._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("<locked>"),
true,
0,
flags,
dbg_refs,
),
}
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::RwLock<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
match self.try_read() {
Ok(guard) => <T as MemDbgImpl>::_mem_dbg_rec_on(
&*guard, writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
),
Err(std::sync::TryLockError::Poisoned(err)) => {
let guard = err.into_inner();
<T as MemDbgImpl>::_mem_dbg_rec_on(
&*guard, writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
Err(std::sync::TryLockError::WouldBlock) => Locked._mem_dbg_depth_on(
writer,
total_size,
max_depth,
prefix,
Some("<locked>"),
true,
0,
flags,
dbg_refs,
),
}
}
}
impl<T: MemDbgImpl> MemDbgImpl for core::cell::OnceCell<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
if let Some(inner) = self.get() {
inner._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
} else {
Ok(())
}
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::OnceLock<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
if let Some(inner) = self.get() {
inner._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
} else {
Ok(())
}
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::MutexGuard<'_, T> {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| {
core::ops::Deref::deref(s) as *const T as *const () as usize
});
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::RwLockReadGuard<'_, T> {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| {
core::ops::Deref::deref(s) as *const T as *const () as usize
});
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::sync::RwLockWriteGuard<'_, T> {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| {
core::ops::Deref::deref(s) as *const T as *const () as usize
});
}
impl_mem_dbg!(
core::net::Ipv4Addr,
core::net::Ipv6Addr,
core::net::IpAddr,
core::net::SocketAddrV4,
core::net::SocketAddrV6,
core::net::SocketAddr,
core::time::Duration
);
#[cfg(feature = "std")]
impl_mem_dbg!(
std::time::Instant,
std::time::SystemTime,
std::time::SystemTimeError
);
#[cfg(feature = "std")]
impl_mem_dbg!(
std::path::Path,
std::path::PathBuf,
std::ffi::OsStr,
std::ffi::OsString,
std::fs::File,
std::fs::OpenOptions,
std::fs::Metadata,
std::fs::FileTimes,
std::fs::FileType,
std::fs::Permissions
);
#[cfg(feature = "std")]
impl<T: MemDbgImpl + std::io::Read> MemDbgImpl for std::io::BufReader<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.get_ref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl + std::io::Write> MemDbgImpl for std::io::BufWriter<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.get_ref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
#[cfg(feature = "std")]
impl<T: MemDbgImpl> MemDbgImpl for std::io::Cursor<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.get_ref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
#[cfg(feature = "maligned")]
impl_mem_dbg!(
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: MemDbgImpl> MemDbgImpl for maligned::Aligned<A, T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
use core::ops::Deref;
self.deref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
#[cfg(feature = "half")]
impl_mem_dbg!(half::f16, half::bf16);
#[cfg(feature = "aliasable")]
mod aliasable {
use super::*;
use ::aliasable::AliasableMut;
use ::aliasable::boxed::AliasableBox;
use ::aliasable::string::AliasableString;
use ::aliasable::vec::AliasableVec;
use core::ops::Deref;
impl<T: ?Sized + MemDbgImpl> MemDbgImpl for AliasableBox<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
self.deref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}
impl<T: FlatType + MemDbgImpl> MemDbgImpl for AliasableVec<T> {}
impl MemDbgImpl for AliasableString {}
impl<T: ?Sized + MemDbgImpl> MemDbgImpl for AliasableMut<'_, T> {
impl_mem_dbg_for_deref!(FOLLOW_REFS, |s| s.deref() as *const T as *const () as usize);
}
}
#[cfg(feature = "maybe-dangling")]
impl<T: MemDbgImpl> MemDbgImpl for maybe_dangling::MaybeDangling<T> {
fn _mem_dbg_rec_on(
&self,
writer: &mut impl core::fmt::Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
is_last: bool,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
) -> core::fmt::Result {
use core::ops::Deref;
self.deref()._mem_dbg_rec_on(
writer, total_size, max_depth, prefix, is_last, flags, dbg_refs,
)
}
}