1#![doc = include_str!("./lib.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4use std::borrow::Cow;
5use std::cell::RefCell;
6use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
7use std::convert::Infallible;
8use std::marker::{PhantomData, PhantomPinned};
9use std::num::{
10 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
11 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
12};
13use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
14use std::rc::{Rc, Weak as RcWeak};
15use std::sync::atomic::{
16 AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicU8, AtomicU16,
17 AtomicU32, AtomicU64, AtomicUsize, Ordering,
18};
19use std::sync::{Arc, Mutex, OnceLock, RwLock, Weak as ArcWeak};
20use std::time::{Duration, Instant, SystemTime};
21
22#[cfg(feature = "derive")]
23#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
24pub use get_size_derive2::*;
25
26mod tracker;
27pub use tracker::*;
28#[cfg(test)]
29mod test;
30
31pub fn heap_size<T: GetSize>(value: &T) -> usize {
33 value.get_heap_size()
34}
35
36pub trait GetSize: Sized {
38 #[must_use]
42 fn get_stack_size() -> usize {
43 std::mem::size_of::<Self>()
44 }
45
46 fn get_heap_size(&self) -> usize {
51 let tracker = NoTracker::new(true);
52 Self::get_heap_size_with_tracker(self, tracker).0
53 }
54
55 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
60 (0, tracker)
61 }
62
63 fn get_size(&self) -> usize {
68 Self::get_stack_size() + GetSize::get_heap_size(self)
69 }
70
71 fn get_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
77 let stack_size = Self::get_stack_size();
78 let (heap_size, tracker) = Self::get_heap_size_with_tracker(self, tracker);
79 (stack_size + heap_size, tracker)
80 }
81}
82
83impl GetSize for () {}
84impl GetSize for bool {}
85impl GetSize for u8 {}
86impl GetSize for u16 {}
87impl GetSize for u32 {}
88impl GetSize for u64 {}
89impl GetSize for u128 {}
90impl GetSize for usize {}
91impl GetSize for NonZeroU8 {}
92impl GetSize for NonZeroU16 {}
93impl GetSize for NonZeroU32 {}
94impl GetSize for NonZeroU64 {}
95impl GetSize for NonZeroU128 {}
96impl GetSize for NonZeroUsize {}
97impl GetSize for i8 {}
98impl GetSize for i16 {}
99impl GetSize for i32 {}
100impl GetSize for i64 {}
101impl GetSize for i128 {}
102impl GetSize for isize {}
103impl GetSize for NonZeroI8 {}
104impl GetSize for NonZeroI16 {}
105impl GetSize for NonZeroI32 {}
106impl GetSize for NonZeroI64 {}
107impl GetSize for NonZeroI128 {}
108impl GetSize for NonZeroIsize {}
109impl GetSize for f32 {}
110impl GetSize for f64 {}
111impl GetSize for char {}
112
113impl GetSize for AtomicBool {}
114impl GetSize for AtomicI8 {}
115impl GetSize for AtomicI16 {}
116impl GetSize for AtomicI32 {}
117impl GetSize for AtomicI64 {}
118impl GetSize for AtomicIsize {}
119impl GetSize for AtomicU8 {}
120impl GetSize for AtomicU16 {}
121impl GetSize for AtomicU32 {}
122impl GetSize for AtomicU64 {}
123impl GetSize for AtomicUsize {}
124impl GetSize for Ordering {}
125
126impl GetSize for std::cmp::Ordering {}
127
128impl GetSize for Infallible {}
129impl<T> GetSize for PhantomData<T> {}
130impl GetSize for PhantomPinned {}
131
132impl GetSize for Instant {}
133impl GetSize for Duration {}
134impl GetSize for SystemTime {}
135
136macro_rules! impl_sum_of_fields {
147 ($name:ident, $($field:ident),+) => {
148 impl<I: GetSize> GetSize for $name<I> {
149 #[allow(unused_mut, reason = "the macro supports a variadic number of elements")]
150 #[expect(clippy::allow_attributes, reason = "the macro supports a variadic number of elements")]
151 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, mut tracker: Tr) -> (usize, Tr) {
152 let mut size = 0;
153 let mut elem_size;
154
155 $(
156 (elem_size, tracker) = self.$field.get_heap_size_with_tracker(tracker);
157 size += elem_size;
158 )+
159
160 (size, tracker)
161 }
162 }
163 };
164}
165
166impl_sum_of_fields!(Range, start, end);
167impl_sum_of_fields!(RangeFrom, start);
168impl_sum_of_fields!(RangeTo, end);
169impl_sum_of_fields!(RangeToInclusive, end);
170
171impl GetSize for RangeFull {}
172
173impl<I: GetSize> GetSize for RangeInclusive<I> {
174 #[inline]
175 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
176 let (start_size, tracker) = (*self.start()).get_heap_size_with_tracker(tracker);
177 let (end_size, tracker) = (*self.end()).get_heap_size_with_tracker(tracker);
178 (start_size + end_size, tracker)
179 }
180}
181
182impl<T> GetSize for Cow<'_, T>
183where
184 T: ToOwned + ?Sized,
185 T::Owned: GetSize,
186{
187 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
188 match self {
189 Self::Borrowed(_borrowed) => (0, tracker),
190 Self::Owned(owned) => <T::Owned>::get_heap_size_with_tracker(owned, tracker),
191 }
192 }
193}
194
195macro_rules! impl_size_set {
196 ($name:ident) => {
197 impl<T> GetSize for $name<T>
198 where
199 T: GetSize,
200 {
201 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
202 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
203 let (elem_size, tracker) = T::get_heap_size_with_tracker(elem, tracker);
204 (size + elem_size, tracker)
205 });
206
207 let allocation_size = self.capacity() * T::get_stack_size();
208 (size + allocation_size, tracker)
209 }
210 }
211 };
212}
213
214macro_rules! impl_size_set_no_capacity {
215 ($name:ident) => {
216 impl<T> GetSize for $name<T>
217 where
218 T: GetSize,
219 {
220 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
221 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
222 let (elem_size, tracker) = T::get_size_with_tracker(elem, tracker);
224 (size + elem_size, tracker)
225 });
226
227 (size, tracker)
228 }
229 }
230 };
231}
232
233impl_size_set_no_capacity!(BTreeSet);
234impl_size_set!(BinaryHeap);
235impl_size_set_no_capacity!(LinkedList);
236impl_size_set!(VecDeque);
237
238impl<K, V> GetSize for BTreeMap<K, V>
239where
240 K: GetSize,
241 V: GetSize,
242{
243 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
244 self.iter()
245 .fold((0, tracker), |(size, tracker), (key, value)| {
246 let (key_size, tracker) = K::get_size_with_tracker(key, tracker);
247 let (value_size, tracker) = V::get_size_with_tracker(value, tracker);
248 (size + key_size + value_size, tracker)
249 })
250 }
251}
252
253impl<K, V, S: ::std::hash::BuildHasher> GetSize for HashMap<K, V, S>
254where
255 K: GetSize,
256 V: GetSize,
257{
258 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
259 let (size, tracker) = self
260 .iter()
261 .fold((0, tracker), |(size, tracker), (key, value)| {
262 let (key_size, tracker) = K::get_heap_size_with_tracker(key, tracker);
263 let (value_size, tracker) = V::get_heap_size_with_tracker(value, tracker);
264 (size + key_size + value_size, tracker)
265 });
266
267 let allocation_size = self.capacity() * <(K, V)>::get_stack_size();
268 (size + allocation_size, tracker)
269 }
270}
271
272impl<T, S: ::std::hash::BuildHasher> GetSize for HashSet<T, S>
273where
274 T: GetSize,
275{
276 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
277 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
278 let (elem_size, tracker) = T::get_heap_size_with_tracker(elem, tracker);
279 (size + elem_size, tracker)
280 });
281
282 let allocation_size = self.capacity() * T::get_stack_size();
283 (size + allocation_size, tracker)
284 }
285}
286
287impl_size_set!(Vec);
288
289macro_rules! impl_size_tuple {
290 ($($t:ident, $T:ident),+) => {
291 impl<$($T,)*> GetSize for ($($T,)*)
292 where
293 $(
294 $T: GetSize,
295 )*
296 {
297 #[allow(unused_mut, reason = "the macro supports a variadic number of elements")]
298 #[expect(clippy::allow_attributes, reason = "the macro supports a variadic number of elements")]
299 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, mut tracker: Tr) -> (usize, Tr) {
300 let mut total = 0;
301 let mut elem_size;
302
303 let ($($t,)*) = self;
304 $(
305 (elem_size, tracker) = <$T>::get_heap_size_with_tracker($t, tracker);
306 total += elem_size;
307 )*
308
309 (total, tracker)
310 }
311 }
312 }
313}
314
315macro_rules! execute_tuple_macro_16 {
316 ($name:ident) => {
317 $name!(v1, V1);
318 $name!(v1, V1, v2, V2);
319 $name!(v1, V1, v2, V2, v3, V3);
320 $name!(v1, V1, v2, V2, v3, V3, v4, V4);
321 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5);
322 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6);
323 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7);
324 $name!(
325 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8
326 );
327 $name!(
328 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9
329 );
330 $name!(
331 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10
332 );
333 $name!(
334 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
335 V11
336 );
337 $name!(
338 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
339 V11, v12, V12
340 );
341 $name!(
342 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
343 V11, v12, V12, v13, V13
344 );
345 $name!(
346 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
347 V11, v12, V12, v13, V13, v14, V14
348 );
349 $name!(
350 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
351 V11, v12, V12, v13, V13, v14, V14, v15, V15
352 );
353 $name!(
354 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
355 V11, v12, V12, v13, V13, v14, V14, v15, V15, v16, V16
356 );
357 };
358}
359
360execute_tuple_macro_16!(impl_size_tuple);
361
362impl<T, const SIZE: usize> GetSize for [T; SIZE]
363where
364 T: GetSize,
365{
366 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
367 self.iter().fold((0, tracker), |(size, tracker), element| {
368 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
370 (size + elem_size, tracker)
371 })
372 }
373}
374
375impl<T> GetSize for &[T] where T: GetSize {}
376
377impl<T> GetSize for &T {}
378impl<T> GetSize for &mut T {}
379impl<T> GetSize for *const T {}
380impl<T> GetSize for *mut T {}
381
382impl<T> GetSize for Box<T>
383where
384 T: GetSize,
385{
386 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
387 T::get_size_with_tracker(&**self, tracker)
388 }
389}
390
391impl<T> GetSize for Rc<T>
392where
393 T: GetSize,
394{
395 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, mut tracker: Tr) -> (usize, Tr) {
396 if tracker.track(Rc::as_ptr(self)) {
397 T::get_size_with_tracker(&**self, tracker)
398 } else {
399 (0, tracker)
400 }
401 }
402}
403
404impl<T> GetSize for RcWeak<T> {}
405
406impl<T> GetSize for Arc<T>
407where
408 T: GetSize,
409{
410 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, mut tracker: Tr) -> (usize, Tr) {
411 if tracker.track(Arc::as_ptr(self)) {
412 T::get_size_with_tracker(&**self, tracker)
413 } else {
414 (0, tracker)
415 }
416 }
417}
418
419impl<T> GetSize for ArcWeak<T> {}
420
421impl<T> GetSize for Option<T>
422where
423 T: GetSize,
424{
425 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
426 match self {
427 None => (0, tracker),
428 Some(value) => T::get_heap_size_with_tracker(value, tracker),
429 }
430 }
431}
432
433impl<T, E> GetSize for Result<T, E>
434where
435 T: GetSize,
436 E: GetSize,
437{
438 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
439 match self {
441 Ok(value) => T::get_heap_size_with_tracker(value, tracker),
442 Err(err) => E::get_heap_size_with_tracker(err, tracker),
443 }
444 }
445}
446
447impl<T> GetSize for Mutex<T>
448where
449 T: GetSize,
450{
451 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
452 T::get_heap_size_with_tracker(&*(self.lock().expect("Mutex is poisoned")), tracker)
454 }
455}
456
457impl<T> GetSize for RwLock<T>
458where
459 T: GetSize,
460{
461 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
462 T::get_heap_size_with_tracker(&*(self.read().expect("RwLock is poisoned")), tracker)
464 }
465}
466
467impl<T> GetSize for RefCell<T>
468where
469 T: GetSize,
470{
471 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
472 match self.try_borrow() {
475 Ok(borrowed) => T::get_heap_size_with_tracker(&*borrowed, tracker),
476 Err(_) => {
477 (0, tracker)
480 }
481 }
482 }
483}
484
485impl<T> GetSize for OnceLock<T>
486where
487 T: GetSize,
488{
489 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
490 match self.get() {
492 None => (0, tracker),
493 Some(value) => T::get_heap_size_with_tracker(value, tracker),
494 }
495 }
496}
497
498impl GetSize for String {
499 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
500 (self.capacity(), tracker)
501 }
502}
503
504impl GetSize for &str {}
505
506impl GetSize for std::ffi::CString {
507 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
508 (self.as_bytes_with_nul().len(), tracker)
509 }
510}
511
512impl GetSize for &std::ffi::CStr {
513 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
514 (self.to_bytes_with_nul().len(), tracker)
515 }
516}
517
518impl GetSize for std::ffi::OsString {
519 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
520 (self.len(), tracker)
521 }
522}
523
524impl GetSize for &std::ffi::OsStr {
525 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
526 (self.len(), tracker)
527 }
528}
529
530impl GetSize for std::fs::DirBuilder {}
531impl GetSize for std::fs::DirEntry {}
532impl GetSize for std::fs::File {}
533impl GetSize for std::fs::FileType {}
534impl GetSize for std::fs::Metadata {}
535impl GetSize for std::fs::OpenOptions {}
536impl GetSize for std::fs::Permissions {}
537impl GetSize for std::fs::ReadDir {}
538
539impl<T> GetSize for std::io::BufReader<T>
540where
541 T: GetSize,
542{
543 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
544 let (total, tracker) = T::get_heap_size_with_tracker(self.get_ref(), tracker);
545 (total + self.capacity(), tracker)
546 }
547}
548
549impl<T> GetSize for std::io::BufWriter<T>
550where
551 T: GetSize + std::io::Write,
552{
553 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
554 let (total, tracker) = T::get_heap_size_with_tracker(self.get_ref(), tracker);
555 (total + self.capacity(), tracker)
556 }
557}
558
559impl GetSize for std::path::PathBuf {
560 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
561 (self.capacity(), tracker)
562 }
563}
564
565impl GetSize for &std::path::Path {}
566
567impl<T> GetSize for Box<[T]>
568where
569 T: GetSize,
570{
571 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
572 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
573 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
574 (size + elem_size, tracker)
575 });
576
577 let allocation_size = self.len() * T::get_stack_size();
578 (size + allocation_size, tracker)
579 }
580}
581
582impl GetSize for Box<str> {
583 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
584 (self.len(), tracker)
585 }
586}
587
588impl<T> GetSize for Rc<[T]>
589where
590 T: GetSize,
591{
592 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
593 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
594 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
595 (size + elem_size, tracker)
596 });
597
598 let allocation_size = self.len() * T::get_stack_size();
599 (size + allocation_size, tracker)
600 }
601}
602
603impl GetSize for Rc<str> {
604 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
605 (self.len(), tracker)
606 }
607}
608
609impl<T> GetSize for Arc<[T]>
610where
611 T: GetSize,
612{
613 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
614 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
615 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
616 (size + elem_size, tracker)
617 });
618
619 let allocation_size = self.len() * T::get_stack_size();
620 (size + allocation_size, tracker)
621 }
622}
623
624impl GetSize for Arc<str> {
625 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
626 (self.len(), tracker)
627 }
628}
629
630#[cfg(feature = "chrono")]
631mod chrono {
632 use crate::{GetSize, GetSizeTracker};
633
634 impl GetSize for chrono::NaiveDate {}
635 impl GetSize for chrono::NaiveTime {}
636 impl GetSize for chrono::NaiveDateTime {}
637 impl GetSize for chrono::Utc {}
638 impl GetSize for chrono::FixedOffset {}
639 impl GetSize for chrono::TimeDelta {}
640
641 impl<Tz: chrono::TimeZone> GetSize for chrono::DateTime<Tz>
642 where
643 Tz::Offset: GetSize,
644 {
645 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
646 <Tz::Offset>::get_heap_size_with_tracker(self.offset(), tracker)
647 }
648 }
649}
650
651#[cfg(feature = "chrono-tz")]
652impl GetSize for chrono_tz::TzOffset {}
653
654#[cfg(feature = "url")]
655impl GetSize for url::Url {
656 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
657 (self.as_str().len(), tracker)
658 }
659}
660
661#[cfg(feature = "bytes")]
662impl GetSize for bytes::Bytes {
663 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
664 (self.len(), tracker)
665 }
666}
667
668#[cfg(feature = "bytes")]
669impl GetSize for bytes::BytesMut {
670 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
671 (self.len(), tracker)
672 }
673}
674
675#[cfg(feature = "hashbrown")]
676impl<K, V, H> GetSize for hashbrown::HashMap<K, V, H>
677where
678 K: GetSize + Eq + std::hash::Hash,
679 V: GetSize,
680 H: std::hash::BuildHasher,
681{
682 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
683 let (size, tracker) = self
684 .iter()
685 .fold((0, tracker), |(size, tracker), (key, value)| {
686 let (key_size, tracker) = K::get_heap_size_with_tracker(key, tracker);
687 let (value_size, tracker) = V::get_heap_size_with_tracker(value, tracker);
688 (size + key_size + value_size, tracker)
689 });
690
691 (size + self.allocation_size(), tracker)
692 }
693}
694
695#[cfg(feature = "hashbrown")]
696impl<T, H> GetSize for hashbrown::HashSet<T, H>
697where
698 T: GetSize + Eq + std::hash::Hash,
699 H: std::hash::BuildHasher,
700{
701 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
702 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
703 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
704 (size + elem_size, tracker)
705 });
706
707 (size + self.allocation_size(), tracker)
708 }
709}
710
711#[cfg(feature = "hashbrown")]
712impl<T> GetSize for hashbrown::HashTable<T>
713where
714 T: GetSize,
715{
716 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
717 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
718 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
719 (size + elem_size, tracker)
720 });
721
722 (size + self.allocation_size(), tracker)
723 }
724}
725
726#[cfg(feature = "smallvec")]
727impl<A: smallvec::Array> GetSize for smallvec::SmallVec<A>
728where
729 A::Item: GetSize,
730{
731 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
732 let (mut size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
733 let (elem_size, tracker) = <A::Item>::get_heap_size_with_tracker(element, tracker);
734 (size + elem_size, tracker)
735 });
736
737 if self.len() > self.inline_size() {
738 size += self.capacity() * <A::Item>::get_stack_size();
739 }
740
741 (size, tracker)
742 }
743}
744
745#[cfg(feature = "thin-vec")]
746impl<T> GetSize for thin_vec::ThinVec<T>
747where
748 T: GetSize,
749{
750 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
751 if self.capacity() == 0 {
752 return (0, tracker);
754 }
755
756 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
757 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
758 (size + elem_size, tracker)
759 });
760
761 let metadata_size = std::mem::size_of::<usize>() * 2; let allocation_size = self.capacity() * T::get_stack_size();
763 (size + metadata_size + allocation_size, tracker)
764 }
765}
766
767#[cfg(feature = "compact-str")]
768impl GetSize for compact_str::CompactString {
769 fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
770 let size = if self.is_heap_allocated() {
771 self.capacity()
772 } else {
773 0
774 };
775
776 (size, tracker)
777 }
778}
779
780#[cfg(feature = "indexmap")]
781impl<K, V, S> GetSize for indexmap::IndexMap<K, V, S>
782where
783 K: GetSize,
784 V: GetSize,
785 S: std::hash::BuildHasher,
786{
787 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
788 let (size, tracker) = self
789 .iter()
790 .fold((0, tracker), |(size, tracker), (key, value)| {
791 let (key_size, tracker) = K::get_heap_size_with_tracker(key, tracker);
792 let (value_size, tracker) = V::get_heap_size_with_tracker(value, tracker);
793 (size + key_size + value_size, tracker)
794 });
795
796 let allocation_size = self.capacity() * <(K, V)>::get_stack_size();
797 (size + allocation_size, tracker)
798 }
799}
800
801#[cfg(feature = "indexmap")]
802impl<T, S> GetSize for indexmap::IndexSet<T, S>
803where
804 T: GetSize,
805{
806 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
807 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), element| {
808 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
809 (size + elem_size, tracker)
810 });
811
812 let allocation_size = self.capacity() * T::get_stack_size();
813 (size + allocation_size, tracker)
814 }
815}