1#![doc = include_str!("./lib.md")]
2
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5
6
7use std::sync::{Arc, Mutex, RwLock};
8use std::sync::atomic::{
9 AtomicBool,
10 AtomicI8,
11 AtomicI16,
12 AtomicI32,
13 AtomicI64,
14 AtomicIsize,
15 AtomicU8,
16 AtomicU16,
17 AtomicU32,
18 AtomicU64,
19 AtomicUsize,
20 Ordering,
21};
22use std::collections::{
23 BTreeMap,
24 BTreeSet,
25 BinaryHeap,
26 HashMap,
27 HashSet,
28 LinkedList,
29 VecDeque,
30};
31use std::num::{
32 NonZeroI8,
33 NonZeroI16,
34 NonZeroI32,
35 NonZeroI64,
36 NonZeroI128,
37 NonZeroIsize,
38 NonZeroU8,
39 NonZeroU16,
40 NonZeroU32,
41 NonZeroU64,
42 NonZeroU128,
43 NonZeroUsize,
44};
45use std::convert::Infallible;
46use std::borrow::Cow;
47use std::rc::Rc;
48use std::marker::{PhantomData, PhantomPinned};
49use std::time::{Instant, Duration, SystemTime};
50
51
52
53#[cfg(feature = "derive")]
54#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
55pub use get_size_derive::*;
56
57
58
59
60#[cfg(test)]
61mod tests;
62
63
64
65pub trait GetSize: Sized {
67 fn get_stack_size() -> usize {
71 std::mem::size_of::<Self>()
72 }
73
74 fn get_heap_size(&self) -> usize {
79 0
80 }
81
82 fn get_size(&self) -> usize {
87 Self::get_stack_size() + GetSize::get_heap_size(self)
88 }
89}
90
91
92
93impl GetSize for () {}
94impl GetSize for bool {}
95impl GetSize for u8 {}
96impl GetSize for u16 {}
97impl GetSize for u32 {}
98impl GetSize for u64 {}
99impl GetSize for u128 {}
100impl GetSize for usize {}
101impl GetSize for NonZeroU8 {}
102impl GetSize for NonZeroU16 {}
103impl GetSize for NonZeroU32 {}
104impl GetSize for NonZeroU64 {}
105impl GetSize for NonZeroU128 {}
106impl GetSize for NonZeroUsize {}
107impl GetSize for i8 {}
108impl GetSize for i16 {}
109impl GetSize for i32 {}
110impl GetSize for i64 {}
111impl GetSize for i128 {}
112impl GetSize for isize {}
113impl GetSize for NonZeroI8 {}
114impl GetSize for NonZeroI16 {}
115impl GetSize for NonZeroI32 {}
116impl GetSize for NonZeroI64 {}
117impl GetSize for NonZeroI128 {}
118impl GetSize for NonZeroIsize {}
119impl GetSize for f32 {}
120impl GetSize for f64 {}
121impl GetSize for char {}
122
123impl GetSize for AtomicBool {}
124impl GetSize for AtomicI8 {}
125impl GetSize for AtomicI16 {}
126impl GetSize for AtomicI32 {}
127impl GetSize for AtomicI64 {}
128impl GetSize for AtomicIsize {}
129impl GetSize for AtomicU8 {}
130impl GetSize for AtomicU16 {}
131impl GetSize for AtomicU32 {}
132impl GetSize for AtomicU64 {}
133impl GetSize for AtomicUsize {}
134impl GetSize for Ordering {}
135
136impl GetSize for std::cmp::Ordering {}
137
138impl GetSize for Infallible {}
139impl<T> GetSize for PhantomData<T> {}
140impl GetSize for PhantomPinned {}
141
142impl GetSize for Instant {}
143impl GetSize for Duration {}
144impl GetSize for SystemTime {}
145
146
147
148impl<'a, T> GetSize for Cow<'a, T>
149where
150 T: ToOwned,
151 <T as ToOwned>::Owned: GetSize,
152{
153 fn get_heap_size(&self) -> usize {
154 match self {
155 Self::Borrowed(_borrowed) => 0,
156 Self::Owned(owned) => GetSize::get_heap_size(owned),
157 }
158 }
159}
160
161
162
163macro_rules! impl_size_set {
164 ($name:ident) => {
165 impl<T> GetSize for $name<T> where T: GetSize {
166 fn get_heap_size(&self) -> usize {
167 let mut total = 0;
168
169 for v in self.iter() {
170 total += GetSize::get_size(v);
172 }
173
174 let additional: usize = self.capacity() - self.len();
175 total += additional * T::get_stack_size();
176
177 total
178 }
179 }
180 }
181}
182
183macro_rules! impl_size_set_no_capacity {
184 ($name:ident) => {
185 impl<T> GetSize for $name<T> where T: GetSize {
186 fn get_heap_size(&self) -> usize {
187 let mut total = 0;
188
189 for v in self.iter() {
190 total += GetSize::get_size(v);
192 }
193
194 total
195 }
196 }
197 }
198}
199
200macro_rules! impl_size_map {
201 ($name:ident) => {
202 impl<K, V> GetSize for $name<K, V> where K: GetSize, V: GetSize {
203 fn get_heap_size(&self) -> usize {
204 let mut total = 0;
205
206 for (k, v) in self.iter() {
207 total += GetSize::get_size(k);
209 total += GetSize::get_size(v);
210 }
211
212 let additional: usize = self.capacity() - self.len();
213 total += additional * K::get_stack_size();
214 total += additional * V::get_stack_size();
215
216 total
217 }
218 }
219 }
220}
221
222macro_rules! impl_size_map_no_capacity {
223 ($name:ident) => {
224 impl<K, V> GetSize for $name<K, V> where K: GetSize, V: GetSize {
225 fn get_heap_size(&self) -> usize {
226 let mut total = 0;
227
228 for (k, v) in self.iter() {
229 total += GetSize::get_size(k);
231 total += GetSize::get_size(v);
232 }
233
234 total
235 }
236 }
237 }
238}
239
240impl_size_map_no_capacity!(BTreeMap);
241impl_size_set_no_capacity!(BTreeSet);
242impl_size_set!(BinaryHeap);
243impl_size_map!(HashMap);
244impl_size_set!(HashSet);
245impl_size_set_no_capacity!(LinkedList);
246impl_size_set!(VecDeque);
247
248impl_size_set!(Vec);
249
250
251
252macro_rules! impl_size_tuple {
253 ($($t:ident, $T:ident),+) => {
254 impl<$($T,)*> GetSize for ($($T,)*)
255 where
256 $(
257 $T: GetSize,
258 )*
259 {
260 fn get_heap_size(&self) -> usize {
261 let mut total = 0;
262
263 let ($($t,)*) = self;
264 $(
265 total += GetSize::get_heap_size($t);
266 )*
267
268 total
269 }
270 }
271 }
272}
273
274macro_rules! execute_tuple_macro_16 {
275 ($name:ident) => {
276 $name!(v1,V1);
277 $name!(v1,V1,v2,V2);
278 $name!(v1,V1,v2,V2,v3,V3);
279 $name!(v1,V1,v2,V2,v3,V3,v4,V4);
280 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5);
281 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6);
282 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7);
283 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8);
284 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9);
285 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10);
286 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11);
287 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11,v12,V12);
288 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11,v12,V12,v13,V13);
289 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11,v12,V12,v13,V13,v14,V14);
290 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11,v12,V12,v13,V13,v14,V14,v15,V15);
291 $name!(v1,V1,v2,V2,v3,V3,v4,V4,v5,V5,v6,V6,v7,V7,v8,V8,v9,V9,v10,V10,v11,V11,v12,V12,v13,V13,v14,V14,v15,V15,v16,V16);
292 }
293}
294
295execute_tuple_macro_16!(impl_size_tuple);
296
297
298
299impl<T, const SIZE: usize> GetSize for [T; SIZE] where T: GetSize {
300 fn get_heap_size(&self) -> usize {
301 let mut total = 0;
302
303 for element in self.iter() {
304 total += GetSize::get_heap_size(element);
306 }
307
308 total
309 }
310}
311
312impl<T> GetSize for &[T] where T: GetSize {}
313
314impl<T> GetSize for &T {}
315impl<T> GetSize for &mut T {}
316impl<T> GetSize for *const T {}
317impl<T> GetSize for *mut T {}
318
319impl<T> GetSize for Box<T> where T: GetSize {
320 fn get_heap_size(&self) -> usize {
321 GetSize::get_size(&**self)
322 }
323}
324
325impl<T> GetSize for Rc<T> where T: GetSize {
326 fn get_heap_size(&self) -> usize {
327 GetSize::get_size(&**self)
328 }
329}
330
331impl<T> GetSize for Arc<T> where T: GetSize {
332 fn get_heap_size(&self) -> usize {
333 GetSize::get_size(&**self)
334 }
335}
336
337impl<T> GetSize for Option<T> where T: GetSize {
338 fn get_heap_size(&self) -> usize {
339 match self {
340 Some(t) => GetSize::get_heap_size(t),
342 None => 0
343 }
344 }
345}
346
347impl<T, E> GetSize for Result<T, E> where T: GetSize, E: GetSize {
348 fn get_heap_size(&self) -> usize {
349 match self {
350 Ok(t) => GetSize::get_heap_size(t),
352 Err(e) => GetSize::get_heap_size(e),
353 }
354 }
355}
356
357impl<T> GetSize for Mutex<T> where T: GetSize {
358 fn get_heap_size(&self) -> usize {
359 GetSize::get_heap_size(&*(self.lock().unwrap()))
361 }
362}
363
364impl<T> GetSize for RwLock<T> where T: GetSize {
365 fn get_heap_size(&self) -> usize {
366 GetSize::get_heap_size(&*(self.read().unwrap()))
368 }
369}
370
371
372impl GetSize for String {
373 fn get_heap_size(&self) -> usize {
374 self.capacity()
375 }
376}
377
378impl GetSize for &str {}
379
380impl GetSize for std::ffi::CString {
381 fn get_heap_size(&self) -> usize {
382 self.as_bytes_with_nul().len()
383 }
384}
385
386impl GetSize for &std::ffi::CStr {
387 fn get_heap_size(&self) -> usize {
388 self.to_bytes_with_nul().len()
389 }
390}
391
392impl GetSize for std::ffi::OsString {
393 fn get_heap_size(&self) -> usize {
394 self.len()
395 }
396}
397
398impl GetSize for &std::ffi::OsStr {
399 fn get_heap_size(&self) -> usize {
400 self.len()
401 }
402}
403
404impl GetSize for std::fs::DirBuilder {}
405impl GetSize for std::fs::DirEntry {}
406impl GetSize for std::fs::File {}
407impl GetSize for std::fs::FileType {}
408impl GetSize for std::fs::Metadata {}
409impl GetSize for std::fs::OpenOptions {}
410impl GetSize for std::fs::Permissions {}
411impl GetSize for std::fs::ReadDir {}
412
413impl<T> GetSize for std::io::BufReader<T> where T: GetSize {
414 fn get_heap_size(&self) -> usize {
415 let mut total = GetSize::get_heap_size(self.get_ref());
416
417 total += self.capacity();
418
419 total
420 }
421}
422
423impl<T> GetSize for std::io::BufWriter<T> where T: GetSize + std::io::Write {
424 fn get_heap_size(&self) -> usize {
425 let mut total = GetSize::get_heap_size(self.get_ref());
426
427 total += self.capacity();
428
429 total
430 }
431}
432
433impl GetSize for std::path::PathBuf {
434 fn get_heap_size(&self) -> usize {
435 self.capacity()
436 }
437}
438
439impl GetSize for &std::path::Path {}
440
441impl<T> GetSize for Box<[T]> {
442 fn get_heap_size(&self) -> usize {
443 let mut total = 0;
444 for item in self.iter() {
445 total += item.get_size()
446 }
447
448 total
449 }
450}