Skip to main content

deepsize/
default_impls.rs

1use crate::{Context, DeepSizeOf};
2
3/// A macro to generate an impl for types with known inner allocation sizes.
4///
5/// Repurposed from the `heapsize` crate
6///
7/// Usage:
8/// ```rust
9/// # #[macro_use] extern crate deepsize; fn main() {
10/// struct A(u32);
11/// struct B(A, char);
12/// struct C(Box<u32>);
13///
14/// known_deep_size!(0; A, B); // A and B do not have any allocation
15/// known_deep_size!(4; C); // C will always have an allocation of 4 bytes
16/// # }
17/// ```
18#[macro_export]
19macro_rules! known_deep_size (
20    ($size:expr; $($({$($gen:tt)*})? $type:ty,)+) => (
21        known_deep_size!($size; $($({$($gen)*})? $type),*);
22    );
23    ($size:expr; $($({$($gen:tt)*})? $type:ty),+) => (
24        $(
25            impl$(<$($gen)*>)? $crate::DeepSizeOf for $type {
26                #[inline(always)]
27                fn deep_size_of_children(&self, _: &mut $crate::Context) -> usize {
28                    $size
29                }
30            }
31        )+
32    );
33);
34
35use core::num;
36use core::sync::atomic;
37
38known_deep_size!(0;
39    (), bool, char, str,
40    u8, u16, u32, u64, u128, usize,
41    i8, i16, i32, i64, i128, isize,
42    f32, f64,
43);
44known_deep_size!(0;
45    atomic::AtomicBool,
46    atomic::AtomicI8,
47    atomic::AtomicI16,
48    atomic::AtomicI32,
49    atomic::AtomicI64,
50    atomic::AtomicIsize,
51    atomic::AtomicU8,
52    atomic::AtomicU16,
53    atomic::AtomicU32,
54    atomic::AtomicU64,
55    atomic::AtomicUsize,
56
57    num::NonZeroI8,
58    num::NonZeroI16,
59    num::NonZeroI32,
60    num::NonZeroI64,
61    num::NonZeroI128,
62    num::NonZeroIsize,
63    num::NonZeroU8,
64    num::NonZeroU16,
65    num::NonZeroU32,
66    num::NonZeroU64,
67    num::NonZeroU128,
68    num::NonZeroUsize,
69);
70
71known_deep_size!(0;
72    {T: ?Sized} core::marker::PhantomData<T>,
73    {T} core::mem::MaybeUninit<T>,
74    // In theory this could be incorrect, but it's unlikely
75    {T: Copy} core::cell::Cell<T>,
76
77    // Weak reference counted pointers do not own their contents
78    {T} alloc::sync::Weak<T>,
79    {T} alloc::rc::Weak<T>,
80);
81
82#[cfg(feature = "std")]
83mod strings {
84    use super::{DeepSizeOf, Context};
85    use std::ffi::{OsString, OsStr, CString, CStr};
86    use std::path::{PathBuf, Path};
87
88    known_deep_size!(0; Path, OsStr, CStr);
89
90    impl DeepSizeOf for PathBuf {
91        fn deep_size_of_children(&self, _: &mut Context) -> usize {
92            self.capacity()
93        }
94    }
95    impl DeepSizeOf for OsString {
96        fn deep_size_of_children(&self, _: &mut Context) -> usize {
97            self.capacity()
98        }
99    }
100    impl DeepSizeOf for CString {
101        fn deep_size_of_children(&self, _: &mut Context) -> usize {
102            // This may cause a length check at runtime, but that
103            // doesn't seem avoidable.  This assumes that the allocation
104            // is the exact length of the string and the added null
105            // terminator.
106            self.as_bytes().len() + 1
107        }
108    }
109}
110
111
112impl DeepSizeOf for alloc::string::String {
113    fn deep_size_of_children(&self, _: &mut Context) -> usize {
114        self.capacity()
115    }
116}
117
118impl<T: DeepSizeOf> DeepSizeOf for core::option::Option<T> {
119    fn deep_size_of_children(&self, context: &mut Context) -> usize {
120        match &self {
121            Some(t) => t.deep_size_of_children(context),
122            None => 0,
123        }
124    }
125}
126
127impl<R: DeepSizeOf, E: DeepSizeOf> DeepSizeOf for core::result::Result<R, E> {
128    fn deep_size_of_children(&self, context: &mut Context) -> usize {
129        match &self {
130            Ok(r) => r.deep_size_of_children(context),
131            Err(e) => e.deep_size_of_children(context),
132        }
133    }
134}
135
136impl<T: DeepSizeOf> DeepSizeOf for core::cell::RefCell<T> {
137    fn deep_size_of_children(&self, context: &mut Context) -> usize {
138        self.borrow().deep_size_of_children(context)
139    }
140}
141
142#[cfg(feature = "std")]
143mod std_sync {
144    use crate::{Context, DeepSizeOf};
145
146    impl<T: DeepSizeOf> DeepSizeOf for std::sync::Mutex<T> {
147        /// This locks the `Mutex`, so it may deadlock; If the mutex is
148        /// poisoned, this returns 0
149        fn deep_size_of_children(&self, context: &mut Context) -> usize {
150            self.lock()
151                .map(|s| s.deep_size_of_children(context))
152                .unwrap_or(0)
153        }
154    }
155
156    impl<T: DeepSizeOf> DeepSizeOf for std::sync::RwLock<T> {
157        /// This reads the `RwLock`, so it may deadlock; If the lock is
158        /// poisoned, this returns 0
159        fn deep_size_of_children(&self, context: &mut Context) -> usize {
160            self.read()
161                .map(|s| s.deep_size_of_children(context))
162                .unwrap_or(0)
163        }
164    }
165}
166
167macro_rules! deep_size_array {
168    ($($num:expr,)+) => {
169        deep_size_array!($($num),+);
170    };
171    ($($num:expr),+) => {
172        $(
173            impl<T: DeepSizeOf> DeepSizeOf for [T; $num] {
174                fn deep_size_of_children(&self, context: &mut Context) -> usize {
175                    self.as_ref().deep_size_of_children(context)
176                }
177            }
178        )+
179    };
180}
181
182// Can't wait for const generics
183// A year and a half later, still waiting
184deep_size_array!(
185    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,
186    26, 27, 28, 29, 30, 31, 32
187);
188
189macro_rules! deep_size_tuple {
190    ($(($n:tt, $T:ident)),+ ) => {
191        impl<$($T,)+> DeepSizeOf for ($($T,)+)
192            where $($T: DeepSizeOf,)+
193        {
194            fn deep_size_of_children(&self, context: &mut Context) -> usize {
195                0 $( + self.$n.deep_size_of_children(context))+
196            }
197        }
198    };
199}
200
201deep_size_tuple!((0, A));
202deep_size_tuple!((0, A), (1, B));
203deep_size_tuple!((0, A), (1, B), (2, C));
204deep_size_tuple!((0, A), (1, B), (2, C), (3, D));
205deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
206deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
207deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
208deep_size_tuple!(
209    (0, A),
210    (1, B),
211    (2, C),
212    (3, D),
213    (4, E),
214    (5, F),
215    (6, G),
216    (7, H)
217);
218deep_size_tuple!(
219    (0, A),
220    (1, B),
221    (2, C),
222    (3, D),
223    (4, E),
224    (5, F),
225    (6, G),
226    (7, H),
227    (8, I)
228);
229deep_size_tuple!(
230    (0, A),
231    (1, B),
232    (2, C),
233    (3, D),
234    (4, E),
235    (5, F),
236    (6, G),
237    (7, H),
238    (8, I),
239    (9, J)
240);