Skip to main content

get_size2/impls/
collections.rs

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                    // We assume that values are held inside the heap.
34                    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            // The array stack size already accounts for the stack size of the elements of the array.
180            let (elem_size, tracker) = T::get_heap_size_with_tracker(element, tracker);
181            (size + elem_size, tracker)
182        })
183    }
184}