Skip to main content

priority_lfu/deepsize/
default_impls.rs

1use crate::deepsize::{Context, DeepSizeOf};
2
3/// A macro to generate an impl for types with known inner allocation sizes.
4///
5/// Repurposed from the `heapsize` crate
6///
7/// Usage:
8/// ```rust
9/// use priority_lfu::known_deep_size;
10///
11/// struct A(u32);
12/// struct B(A, char);
13/// struct C(Box<u32>);
14///
15/// known_deep_size!(0; A, B); // A and B do not have any allocation
16/// known_deep_size!(4; C); // C will always have an allocation of 4 bytes
17/// ```
18#[macro_export]
19macro_rules! known_deep_size (
20    ($size:expr; $($({$($gen:tt)*})? $type:ty,)+) => (
21        known_deep_size!($size; $($({$($gen)*})? $type),*);
22    );
23    ($size:expr; $($({$($gen:tt)*})? $type:ty),+) => (
24        $(
25            impl$(<$($gen)*>)? $crate::DeepSizeOf for $type {
26                #[inline(always)]
27                fn deep_size_of_children(&self, _: &mut $crate::Context) -> usize {
28                    $size
29                }
30            }
31        )+
32    );
33);
34
35use core::num;
36use core::sync::atomic;
37
38known_deep_size!(0;
39	(), bool, char, str,
40	u8, u16, u32, u64, u128, usize,
41	i8, i16, i32, i64, i128, isize,
42	f32, f64,
43);
44known_deep_size!(0;
45	atomic::AtomicBool,
46	atomic::AtomicI8,
47	atomic::AtomicI16,
48	atomic::AtomicI32,
49	atomic::AtomicI64,
50	atomic::AtomicIsize,
51	atomic::AtomicU8,
52	atomic::AtomicU16,
53	atomic::AtomicU32,
54	atomic::AtomicU64,
55	atomic::AtomicUsize,
56
57	num::NonZeroI8,
58	num::NonZeroI16,
59	num::NonZeroI32,
60	num::NonZeroI64,
61	num::NonZeroI128,
62	num::NonZeroIsize,
63	num::NonZeroU8,
64	num::NonZeroU16,
65	num::NonZeroU32,
66	num::NonZeroU64,
67	num::NonZeroU128,
68	num::NonZeroUsize,
69);
70
71known_deep_size!(0;
72	{T} core::ops::Bound<T>
73);
74
75known_deep_size!(0;
76	{T: ?Sized} core::marker::PhantomData<T>,
77	{T} core::mem::MaybeUninit<T>,
78	// In theory this could be incorrect, but it's unlikely
79	{T: Copy} core::cell::Cell<T>,
80
81	// Weak reference counted pointers do not own their contents
82	{T} std::sync::Weak<T>,
83	{T} std::rc::Weak<T>,
84);
85
86mod strings {
87	use std::ffi::{CStr, CString, OsStr, OsString};
88	use std::path::{Path, PathBuf};
89
90	use super::{Context, DeepSizeOf};
91
92	known_deep_size!(0; Path, OsStr, CStr);
93
94	impl DeepSizeOf for PathBuf {
95		fn deep_size_of_children(&self, _: &mut Context) -> usize {
96			self.capacity()
97		}
98	}
99	impl DeepSizeOf for OsString {
100		fn deep_size_of_children(&self, _: &mut Context) -> usize {
101			self.capacity()
102		}
103	}
104	impl DeepSizeOf for CString {
105		fn deep_size_of_children(&self, _: &mut Context) -> usize {
106			// This may cause a length check at runtime, but that
107			// doesn't seem avoidable.  This assumes that the allocation
108			// is the exact length of the string and the added null
109			// terminator.
110			self.as_bytes().len() + 1
111		}
112	}
113}
114
115impl DeepSizeOf for std::string::String {
116	fn deep_size_of_children(&self, _: &mut Context) -> usize {
117		self.capacity()
118	}
119}
120
121impl<T: DeepSizeOf> DeepSizeOf for core::option::Option<T> {
122	fn deep_size_of_children(&self, context: &mut Context) -> usize {
123		match &self {
124			Some(t) => t.deep_size_of_children(context),
125			None => 0,
126		}
127	}
128}
129
130impl<R: DeepSizeOf, E: DeepSizeOf> DeepSizeOf for core::result::Result<R, E> {
131	fn deep_size_of_children(&self, context: &mut Context) -> usize {
132		match &self {
133			Ok(r) => r.deep_size_of_children(context),
134			Err(e) => e.deep_size_of_children(context),
135		}
136	}
137}
138
139impl<T: DeepSizeOf> DeepSizeOf for core::cell::RefCell<T> {
140	fn deep_size_of_children(&self, context: &mut Context) -> usize {
141		self.borrow().deep_size_of_children(context)
142	}
143}
144
145mod std_net {
146	use std::net::{
147		AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4,
148		SocketAddrV6, TcpListener, TcpStream, UdpSocket,
149	};
150
151	known_deep_size!(0;
152		// structs
153		AddrParseError, Ipv4Addr,
154		Ipv6Addr, SocketAddrV4, SocketAddrV6,
155		TcpListener, TcpStream, UdpSocket,
156		// enums
157		IpAddr, Shutdown, SocketAddr
158	);
159}
160
161mod std_time {
162	use std::time::{Duration, Instant, SystemTime, SystemTimeError};
163
164	known_deep_size!(0;
165		Instant, Duration, SystemTime, SystemTimeError
166	);
167}
168
169mod std_sync {
170	use crate::deepsize::{Context, DeepSizeOf};
171
172	impl<T: DeepSizeOf> DeepSizeOf for std::sync::Mutex<T> {
173		/// This locks the `Mutex`, so it may deadlock; If the mutex is
174		/// poisoned, this returns 0
175		fn deep_size_of_children(&self, context: &mut Context) -> usize {
176			self.lock().map(|s| s.deep_size_of_children(context)).unwrap_or(0)
177		}
178	}
179
180	impl<T: DeepSizeOf> DeepSizeOf for std::sync::RwLock<T> {
181		/// This reads the `RwLock`, so it may deadlock; If the lock is
182		/// poisoned, this returns 0
183		fn deep_size_of_children(&self, context: &mut Context) -> usize {
184			self.read().map(|s| s.deep_size_of_children(context)).unwrap_or(0)
185		}
186	}
187}
188
189impl<T: DeepSizeOf, const N: usize> DeepSizeOf for [T; N] {
190	fn deep_size_of_children(&self, context: &mut Context) -> usize {
191		self.as_ref().deep_size_of_children(context)
192	}
193}
194
195macro_rules! deep_size_tuple {
196    ($(($n:tt, $T:ident)),+ ) => {
197        impl<$($T,)+> DeepSizeOf for ($($T,)+)
198            where $($T: DeepSizeOf,)+
199        {
200            fn deep_size_of_children(&self, context: &mut Context) -> usize {
201                0 $( + self.$n.deep_size_of_children(context))+
202            }
203        }
204    };
205}
206
207deep_size_tuple!((0, A));
208deep_size_tuple!((0, A), (1, B));
209deep_size_tuple!((0, A), (1, B), (2, C));
210deep_size_tuple!((0, A), (1, B), (2, C), (3, D));
211deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
212deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
213deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
214deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
215deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
216deep_size_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));