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