1use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
2use std::hash::BuildHasher;
3
4use crate::{GetSize, GetSizeTracker};
5
6macro_rules! impl_size_set {
7 ($name:ident) => {
8 impl<T> GetSize for $name<T>
9 where
10 T: GetSize,
11 {
12 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
13 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
14 let (elem_size, tracker) = T::get_heap_size_with_tracker(elem, tracker);
15 (size + elem_size, tracker)
16 });
17
18 let allocation_size = self.capacity() * T::get_stack_size();
19 (size + allocation_size, tracker)
20 }
21 }
22 };
23}
24
25macro_rules! impl_size_set_no_capacity {
26 ($name:ident) => {
27 impl<T> GetSize for $name<T>
28 where
29 T: GetSize,
30 {
31 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
32 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
33 let (elem_size, tracker) = T::get_size_with_tracker(elem, tracker);
35 (size + elem_size, tracker)
36 });
37
38 (size, tracker)
39 }
40 }
41 };
42}
43
44impl_size_set_no_capacity!(BTreeSet);
45impl_size_set!(BinaryHeap);
46impl_size_set_no_capacity!(LinkedList);
47impl_size_set!(VecDeque);
48
49impl<K, V> GetSize for BTreeMap<K, V>
50where
51 K: GetSize,
52 V: GetSize,
53{
54 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
55 self.iter()
56 .fold((0, tracker), |(size, tracker), (key, value)| {
57 let (key_size, tracker) = K::get_size_with_tracker(key, tracker);
58 let (value_size, tracker) = V::get_size_with_tracker(value, tracker);
59 (size + key_size + value_size, tracker)
60 })
61 }
62}
63
64impl<K, V, S: BuildHasher> GetSize for HashMap<K, V, S>
65where
66 K: GetSize,
67 V: GetSize,
68{
69 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
70 let (size, tracker) = self
71 .iter()
72 .fold((0, tracker), |(size, tracker), (key, value)| {
73 let (key_size, tracker) = K::get_heap_size_with_tracker(key, tracker);
74 let (value_size, tracker) = V::get_heap_size_with_tracker(value, tracker);
75 (size + key_size + value_size, tracker)
76 });
77
78 let allocation_size = self.capacity() * <(K, V)>::get_stack_size();
79 (size + allocation_size, tracker)
80 }
81}
82
83impl<T, S: BuildHasher> GetSize for HashSet<T, S>
84where
85 T: GetSize,
86{
87 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
88 let (size, tracker) = self.iter().fold((0, tracker), |(size, tracker), elem| {
89 let (elem_size, tracker) = T::get_heap_size_with_tracker(elem, tracker);
90 (size + elem_size, tracker)
91 });
92
93 let allocation_size = self.capacity() * T::get_stack_size();
94 (size + allocation_size, tracker)
95 }
96}
97
98impl_size_set!(Vec);
99
100macro_rules! impl_size_tuple {
101 ($($t:ident, $T:ident),+) => {
102 impl<$($T,)*> GetSize for ($($T,)*)
103 where
104 $(
105 $T: GetSize,
106 )*
107 {
108 #[allow(unused_mut, reason = "the macro supports a variadic number of elements")]
109 #[expect(clippy::allow_attributes, reason = "the macro supports a variadic number of elements")]
110 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, mut tracker: Tr) -> (usize, Tr) {
111 let mut total = 0;
112 let mut elem_size;
113
114 let ($($t,)*) = self;
115 $(
116 (elem_size, tracker) = <$T>::get_heap_size_with_tracker($t, tracker);
117 total += elem_size;
118 )*
119
120 (total, tracker)
121 }
122 }
123 }
124}
125
126macro_rules! execute_tuple_macro_16 {
127 ($name:ident) => {
128 $name!(v1, V1);
129 $name!(v1, V1, v2, V2);
130 $name!(v1, V1, v2, V2, v3, V3);
131 $name!(v1, V1, v2, V2, v3, V3, v4, V4);
132 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5);
133 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6);
134 $name!(v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7);
135 $name!(
136 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8
137 );
138 $name!(
139 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9
140 );
141 $name!(
142 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10
143 );
144 $name!(
145 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
146 V11
147 );
148 $name!(
149 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
150 V11, v12, V12
151 );
152 $name!(
153 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
154 V11, v12, V12, v13, V13
155 );
156 $name!(
157 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
158 V11, v12, V12, v13, V13, v14, V14
159 );
160 $name!(
161 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
162 V11, v12, V12, v13, V13, v14, V14, v15, V15
163 );
164 $name!(
165 v1, V1, v2, V2, v3, V3, v4, V4, v5, V5, v6, V6, v7, V7, v8, V8, v9, V9, v10, V10, v11,
166 V11, v12, V12, v13, V13, v14, V14, v15, V15, v16, V16
167 );
168 };
169}
170
171execute_tuple_macro_16!(impl_size_tuple);
172
173impl<T, const SIZE: usize> GetSize for [T; SIZE]
174where
175 T: GetSize,
176{
177 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
178 self.iter().fold((0, tracker), |(size, tracker), element| {
179 let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
181 (size + elem_size, tracker)
182 })
183 }
184}