re_byte_size/
std_sizes.rs

1//! Implement [`SizeBytes`] for things in the standard library.
2
3use std::{
4    collections::{BTreeMap, BTreeSet, HashMap, VecDeque},
5    sync::Arc,
6};
7
8use crate::SizeBytes;
9
10impl SizeBytes for String {
11    #[inline]
12    fn heap_size_bytes(&self) -> u64 {
13        self.capacity() as u64
14    }
15}
16
17impl<K: SizeBytes, V: SizeBytes> SizeBytes for BTreeMap<K, V> {
18    #[inline]
19    fn heap_size_bytes(&self) -> u64 {
20        // NOTE: It's all on the heap at this point.
21
22        let keys_size_bytes = if K::is_pod() {
23            (self.len() * std::mem::size_of::<K>()) as _
24        } else {
25            self.keys().map(SizeBytes::total_size_bytes).sum::<u64>()
26        };
27
28        let values_size_bytes = if V::is_pod() {
29            (self.len() * std::mem::size_of::<V>()) as _
30        } else {
31            self.values().map(SizeBytes::total_size_bytes).sum::<u64>()
32        };
33
34        keys_size_bytes + values_size_bytes
35    }
36}
37
38impl<K: SizeBytes> SizeBytes for BTreeSet<K> {
39    #[inline]
40    fn heap_size_bytes(&self) -> u64 {
41        // NOTE: It's all on the heap at this point.
42
43        if K::is_pod() {
44            (self.len() * std::mem::size_of::<K>()) as _
45        } else {
46            self.iter().map(SizeBytes::total_size_bytes).sum::<u64>()
47        }
48    }
49}
50
51impl<K: SizeBytes, V: SizeBytes, S> SizeBytes for HashMap<K, V, S> {
52    #[inline]
53    fn heap_size_bytes(&self) -> u64 {
54        // NOTE: It's all on the heap at this point.
55
56        let keys_size_bytes = if K::is_pod() {
57            (self.len() * std::mem::size_of::<K>()) as _
58        } else {
59            self.keys().map(SizeBytes::total_size_bytes).sum::<u64>()
60        };
61
62        let values_size_bytes = if V::is_pod() {
63            (self.len() * std::mem::size_of::<V>()) as _
64        } else {
65            self.values().map(SizeBytes::total_size_bytes).sum::<u64>()
66        };
67
68        keys_size_bytes + values_size_bytes
69    }
70}
71
72// NOTE: Do _not_ implement `SizeBytes` for slices: we cannot know whether they point to the stack
73// or the heap!
74
75impl<T: SizeBytes, const N: usize> SizeBytes for [T; N] {
76    #[inline]
77    fn heap_size_bytes(&self) -> u64 {
78        if T::is_pod() {
79            0 // it's a const-sized array
80        } else {
81            self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
82        }
83    }
84}
85
86impl<T: SizeBytes> SizeBytes for Vec<T> {
87    #[inline]
88    fn heap_size_bytes(&self) -> u64 {
89        // NOTE: It's all on the heap at this point.
90        if T::is_pod() {
91            (self.capacity() * std::mem::size_of::<T>()) as _
92        } else {
93            (self.capacity() * std::mem::size_of::<T>()) as u64
94                + self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
95        }
96    }
97}
98
99impl<T: SizeBytes> SizeBytes for VecDeque<T> {
100    #[inline]
101    fn heap_size_bytes(&self) -> u64 {
102        // NOTE: It's all on the heap at this point.
103        if T::is_pod() {
104            (self.capacity() * std::mem::size_of::<T>()) as _
105        } else {
106            (self.capacity() * std::mem::size_of::<T>()) as u64
107                + self.iter().map(SizeBytes::heap_size_bytes).sum::<u64>()
108        }
109    }
110}
111
112impl<T: SizeBytes> SizeBytes for Option<T> {
113    #[inline]
114    fn heap_size_bytes(&self) -> u64 {
115        self.as_ref().map_or(0, SizeBytes::heap_size_bytes)
116    }
117}
118
119impl<T: SizeBytes> SizeBytes for Arc<T> {
120    #[inline]
121    fn heap_size_bytes(&self) -> u64 {
122        0 // assume it's amortized
123    }
124}
125
126impl<T: SizeBytes> SizeBytes for Box<T> {
127    #[inline]
128    fn heap_size_bytes(&self) -> u64 {
129        T::total_size_bytes(&**self)
130    }
131}