wiwi/
mem_use.rs

1extern crate cfg_if;
2
3use crate::prelude::*;
4use self::private::SealedStruct;
5use cfg_if::cfg_if;
6
7#[cfg_attr(feature = "nightly", const_trait)]
8pub trait MemUse {
9	/// Unsure the use case, but let's check that these are dyn compatible for now?
10	#[doc(hidden)]
11	#[inline]
12	fn __assert_dyn_compat(&self, _: &dyn MemUse, _: SealedStruct) {}
13
14	/// Calculates total memory usage, including inline and indirect,
15	#[inline]
16	fn mem_use(&self) -> usize {
17		self.mem_use_inline() + self.mem_use_indirect()
18	}
19
20	/// Calculates inline memory usage (ex. heap usage of a [`Vec`], always 24
21	/// bytes on 64-bit architextures)
22	fn mem_use_inline(&self) -> usize;
23
24	/// Calculates indirect memory usage (ex. heap usage of a [`Vec`])
25	fn mem_use_indirect(&self) -> usize;
26}
27
28// todo: trying to remove the sized bound (remove me when done)
29// const _: usize = <() as MemUseConst>::MEM_USE;
30pub trait MemUseConst
31where
32	Self: MemUse
33{
34	/// The constant memory usage for this type, if this value is always the same
35	const MEM_USE_MAYBE: Option<usize> = add_maybe_const(
36		Self::MEM_USE_INLINE_MAYBE,
37		Self::MEM_USE_INDIRECT_MAYBE
38	);
39
40	/// The constant inline memory usage for this type, if this value is always the same
41	const MEM_USE_INLINE_MAYBE: Option<usize>;
42
43	/// The constant indirect memory usage for this type, if this value is always the same
44	const MEM_USE_INDIRECT_MAYBE: Option<usize>;
45
46	/// The constant memory usage for this type
47	const MEM_USE: usize = Self::MEM_USE_MAYBE.unwrap();
48
49	/// The constant memory usage for this type
50	const MEM_USE_INLINE: usize = Self::MEM_USE_INLINE_MAYBE.unwrap();
51
52	/// The constant memory usage for this type
53	const MEM_USE_INDIRECT: usize = Self::MEM_USE_INDIRECT_MAYBE.unwrap();
54}
55
56cfg_if! {
57	if #[cfg(feature = "nightly")] {
58		#[inline]
59		pub const fn mem_use<T>(val: &T) -> usize
60		where
61			T: ~const MemUse
62		{
63			val.mem_use()
64		}
65	} else {
66		#[inline]
67		pub fn mem_use<T>(val: &T) -> usize
68		where
69			T: MemUse
70		{
71			val.mem_use()
72		}
73	}
74}
75
76cfg_if! {
77	if #[cfg(feature = "nightly")] {
78		#[inline]
79		pub const fn mem_use_inline<T>(val: &T) -> usize
80		where
81			T: ~const MemUse
82		{
83			val.mem_use_inline()
84		}
85	} else {
86		#[inline]
87		pub fn mem_use_inline<T>(val: &T) -> usize
88		where
89			T: MemUse
90		{
91			val.mem_use_inline()
92		}
93	}
94}
95
96cfg_if! {
97	if #[cfg(feature = "nightly")] {
98		#[inline]
99		pub const fn mem_use_indirect<T>(val: &T) -> usize
100		where
101			T: ~const MemUse
102		{
103			val.mem_use_indirect()
104		}
105	} else {
106		#[inline]
107		pub fn mem_use_indirect<T>(val: &T) -> usize
108		where
109			T: MemUse
110		{
111			val.mem_use_indirect()
112		}
113	}
114}
115
116#[inline]
117pub const fn mem_use_const<T>() -> usize
118where
119	T: ?Sized + MemUseConst
120{
121	T::MEM_USE
122}
123
124#[inline]
125pub const fn mem_use_const_inline<T>() -> usize
126where
127	T: ?Sized + MemUseConst
128{
129	T::MEM_USE_INLINE
130}
131
132#[inline]
133pub const fn mem_use_const_indirect<T>() -> usize
134where
135	T: ?Sized + MemUseConst
136{
137	T::MEM_USE_INDIRECT
138}
139
140#[inline]
141pub const fn mem_use_const_maybe<T>() -> Option<usize>
142where
143	T: ?Sized + MemUseConst
144{
145	T::MEM_USE_MAYBE
146}
147
148#[inline]
149pub const fn mem_use_const_inline_maybe<T>() -> Option<usize>
150where
151	T: ?Sized + MemUseConst
152{
153	T::MEM_USE_INLINE_MAYBE
154}
155
156#[inline]
157pub const fn mem_use_const_indirect_maybe<T>() -> Option<usize>
158where
159	T: ?Sized + MemUseConst
160{
161	T::MEM_USE_INDIRECT_MAYBE
162}
163
164const fn add_maybe_const(a1: Option<usize>, a2: Option<usize>) -> Option<usize> {
165	if let (Some(a1), Some(a2)) = (a1, a2) {
166		Some(a1 + a2)
167	} else {
168		None
169	}
170}
171
172mod private {
173	pub struct SealedStruct {
174		__private: ()
175	}
176}
177
178// stack_only_impl! { () }
179// stack_only_impl! { bool }
180// stack_only_impl! { char }
181// stack_only_impl! { u8 }
182// stack_only_impl! { u16 }
183// stack_only_impl! { u32 }
184// stack_only_impl! { u64 }
185// stack_only_impl! { u128 }
186// stack_only_impl! { usize }
187// stack_only_impl! { i8 }
188// stack_only_impl! { i16 }
189// stack_only_impl! { i32 }
190// stack_only_impl! { i64 }
191// stack_only_impl! { i128 }
192// stack_only_impl! { isize }
193// stack_only_impl! { #[cfg(feature = "nightly")] [] f16 }
194// stack_only_impl! { f32 }
195// stack_only_impl! { f64 }
196// stack_only_impl! { #[cfg(feature = "nightly")] [] f128 }
197// // stack_only_impl! { [T: ?Sized] *const T }
198// // stack_only_impl! { [T: ?Sized] *mut T }
199// stack_only_impl! { NonZero<u8> }
200// stack_only_impl! { NonZero<u16> }
201// stack_only_impl! { NonZero<u32> }
202// stack_only_impl! { NonZero<u64> }
203// stack_only_impl! { NonZero<u128> }
204// stack_only_impl! { NonZero<usize> }
205// stack_only_impl! { NonZero<i8> }
206// stack_only_impl! { NonZero<i16> }
207// stack_only_impl! { NonZero<i32> }
208// stack_only_impl! { NonZero<i64> }
209// stack_only_impl! { NonZero<i128> }
210// stack_only_impl! { NonZero<isize> }
211// stack_only_impl! { Saturating<u8> }
212// stack_only_impl! { Saturating<u16> }
213// stack_only_impl! { Saturating<u32> }
214// stack_only_impl! { Saturating<u64> }
215// stack_only_impl! { Saturating<u128> }
216// stack_only_impl! { Saturating<usize> }
217// stack_only_impl! { Saturating<i8> }
218// stack_only_impl! { Saturating<i16> }
219// stack_only_impl! { Saturating<i32> }
220// stack_only_impl! { Saturating<i64> }
221// stack_only_impl! { Saturating<i128> }
222// stack_only_impl! { Saturating<isize> }
223// stack_only_impl! { Wrapping<u8> }
224// stack_only_impl! { Wrapping<u16> }
225// stack_only_impl! { Wrapping<u32> }
226// stack_only_impl! { Wrapping<u64> }
227// stack_only_impl! { Wrapping<u128> }
228// stack_only_impl! { Wrapping<usize> }
229// stack_only_impl! { Wrapping<i8> }
230// stack_only_impl! { Wrapping<i16> }
231// stack_only_impl! { Wrapping<i32> }
232// stack_only_impl! { Wrapping<i64> }
233// stack_only_impl! { Wrapping<i128> }
234// stack_only_impl! { Wrapping<isize> }
235// stack_only_impl! { AtomicBool }
236// stack_only_impl! { AtomicU8 }
237// stack_only_impl! { AtomicU16 }
238// stack_only_impl! { AtomicU32 }
239// stack_only_impl! { AtomicU64 }
240// stack_only_impl! { #[cfg(feature = "nightly")] [] atomic::AtomicU128 }
241// stack_only_impl! { AtomicUsize }
242// stack_only_impl! { AtomicI8 }
243// stack_only_impl! { AtomicI16 }
244// stack_only_impl! { AtomicI32 }
245// stack_only_impl! { AtomicI64 }
246// stack_only_impl! { #[cfg(feature = "nightly")] [] atomic::AtomicI128 }
247// stack_only_impl! { AtomicIsize }
248// stack_only_impl! { [T] AtomicPtr<T> }
249// stack_only_impl! { [T: ?Sized] PhantomData<T> }
250// stack_only_impl! { PhantomPinned }
251
252// impl_mem_use! {
253// 	[T] [&T]
254// 	where { T: ?Sized + MemUse }
255// 	where const { T: ?Sized + ~const MemUse }
256// 	where const maybe { T: ?Sized + MemUseConstMaybe }
257// 	const { map_maybe_const(Some(size_of::<&T>()), T::MEM_USE_MAYBE) }
258// 	const inline { map_maybe_const(Some(size_of::<&T>()), T::MEM_USE_MAYBE) }
259// 	const indirect { map_maybe_const(Some(size_of::<&T>()), T::MEM_USE_MAYBE) }
260// 	// mem_use_inline(&self) { size_of::<&T>() }
261// 	// mem_use_indirect(&self) { T::mem_use(self) }
262// }
263
264// impl_mem_use! {
265// 	[T] [&mut T]
266// 	where { T: ?Sized + MemUseConstMaybe }
267// 	where const { T: ?Sized + ~const MemUse }
268// 	where const maybe { T: ?Sized + MemUseConstMaybe }
269// 	const = map_maybe_const(Some(size_of::<&mut T>()), T::MEM_USE_MAYBE);
270// 	mem_use_inline(&self) { size_of::<&T>() }
271// 	mem_use_indirect(&self) { T::mem_use(self) }
272// }
273
274// impl_mem_use! {
275// 	[T] [Option<T>]
276// 	where { T: MemUse }
277// 	where const { T: ~const MemUse }
278// 	where const maybe { T: MemUseConstMaybe }
279// 	const = None;
280// 	mem_use_inline(&self) { size_of::<Option<T>>() }
281// 	mem_use_indirect(&self) {
282// 		match self {
283// 			Some(v) => { T::mem_use_indirect(v) }
284// 			None => { 0 }
285// 		}
286// 	}
287// }
288
289// // cfg_if! {
290// // 	if #[cfg(feature = "nightly")] {
291// // 		impl<T, E> const MemUse for Result<T, E>
292// // 		where
293// // 			T: ~const MemUse,
294// // 			E: ~const MemUse
295// // 		{
296// // 			#[inline]
297// // 			fn mem_use_inline(&self) -> usize {
298// // 				size_of::<Result<T, E>>()
299// // 			}
300
301// // 			#[inline]
302// // 			fn mem_use_indirect(&self) -> usize {
303// // 				match self {
304// // 					Ok(v) => { T::mem_use_indirect(v) }
305// // 					Err(e) => { E::mem_use_indirect(e) }
306// // 				}
307// // 			}
308// // 		}
309// // 	} else {
310// // 		impl<T, E> MemUse for Result<T, E>
311// // 		where
312// // 			T: MemUse,
313// // 			E: MemUse
314// // 		{
315// // 			#[inline]
316// // 			fn mem_use_inline(&self) -> usize {
317// // 				size_of::<Result<T, E>>()
318// // 			}
319
320// // 			#[inline]
321// // 			fn mem_use_indirect(&self) -> usize {
322// // 				match self {
323// // 					Ok(v) => { T::mem_use_indirect(v) }
324// // 					Err(e) => { E::mem_use_indirect(e) }
325// // 				}
326// // 			}
327// // 		}
328// // 	}
329// // }
330
331// // impl<T, E> MemUseConst for Result<T, E>
332// // where
333// // 	T: MemUseConst,
334// // 	E: MemUseConst
335// // {
336// // 	const MEM_USE: usize = size_of::<Result<T, E>>();
337// // }
338
339// // impl<T> MemUse for [T]
340// // where
341// // 	T: MemUse
342// // {
343// // 	#[inline]
344// // 	fn mem_use(&self) -> usize {
345// // 		self.iter().map(T::mem_use).sum()
346// // 	}
347
348// // 	#[inline]
349// // 	fn mem_use_inline(&self) -> usize {
350// // 		size_of_val(self)
351// // 	}
352
353// // 	#[inline]
354// // 	fn mem_use_indirect(&self) -> usize {
355// // 		self.iter().map(T::mem_use_indirect).sum()
356// // 	}
357// // }
358
359// // impl<T> MemUseStatic for [T]
360// // where
361// // 	T: MemUseStatic
362// // {
363// // 	#[inline]
364// // 	fn mem_use_static(&self) -> usize {
365// // 		let mut i = 0;
366// // 		let mut mem_use = 0;
367
368// // 		while i < self.len() {
369// // 			mem_use += self[i].mem_use_static();
370// // 			i += 1;
371// // 		}
372
373// // 		mem_use
374// // 	}
375// // }
376
377// // impl MemUse for str {
378// // 	#[inline]
379// // 	fn mem_use(&self) -> usize {
380// // 		self.len()
381// // 	}
382
383// // 	#[inline]
384// // 	fn mem_use_inline(&self) -> usize {
385// // 		self.len()
386// // 	}
387
388// // 	#[inline]
389// // 	fn mem_use_indirect(&self) -> usize {
390// // 		0
391// // 	}
392// // }
393
394// // impl MemUseStatic for str {
395// // 	#[inline]
396// // 	fn mem_use_static(&self) -> usize {
397// // 		self.len()
398// // 	}
399// // }
400
401// // TODO: Option, tuples, Result, Vec, String, [T; N], the ranges, cells, path, osstr, cstr, rc, arc, types in this crate
402// // TODO: go through std's list of types lol
403
404// macro_rules! impl_mem_use {
405// 	{
406// 		[$($generics:tt)*] [$($type:tt)*]
407
408// 		$(#[$impl_meta:meta])*
409// 		where { $($where:tt)* }
410// 		$(#[$impl_const_meta:meta])*
411// 		where const { $($where_const:tt)* }
412// 		$(#[$impl_const_maybe_meta:meta])*
413// 		where const maybe { $($where_const_maybe:tt)* }
414
415// 		$self:ident
416
417// 		$(#[$fn_meta:meta])*
418// 		fn { $($fn:tt)* }
419// 		$(#[$fn_inline_meta:meta])*
420// 		fn inline { $($fn_inline:tt)* }
421// 		$(#[$fn_indirect_meta:meta])*
422// 		fn indirect { $($fn_indirect:tt)* }
423
424// 		$(#[$const_meta:meta])*
425// 		const { $($const_maybe:tt)* }
426// 		$(#[$const_inline_meta:meta])*
427// 		const inline { $($const_inline_maybe:tt)* }
428// 		$(#[$const_indirect_meta:meta])*
429// 		const indirect { $($const_indirect_maybe:tt)* }
430// 	} => {
431// 		cfg_if! {
432// 			if #[cfg(not(feature = "nightly"))] {
433// 				$(#[$impl_const_meta])*
434// 				impl<$($generics)*> MemUse for $($type)*
435// 				where $($where)*
436// 				{
437// 					$(#[$fn_meta])*
438// 					#[inline]
439// 					fn mem_use(&$self) -> usize {
440// 						impl_mem_use! {
441// 							@process_default
442// 							{ $($fn)* }
443// 							{ $self.mem_use_inline() + $self.mem_use_indirect() }
444// 						}
445// 					}
446
447// 					$(#[$fn_inline_meta])*
448// 					fn mem_use_inline(&$self) -> usize {
449// 						$($fn_inline)*
450// 					}
451
452// 					$(#[$fn_indirect_meta])*
453// 					fn mem_use_indirect(&$self) -> usize {
454// 						$($fn_indirect)*
455// 					}
456// 				}
457// 			} else {
458// 				$(#[$impl_meta])*
459// 				impl<$($generics)*> const MemUse for $($type)*
460// 				where $($where_const)*
461// 				{
462// 					$(#[$fn_meta])*
463// 					#[inline]
464// 					fn mem_use(&$self) -> usize {
465// 						impl_mem_use! {
466// 							@process_default
467// 							{ $($fn)* }
468// 							{ $self.mem_use_inline() + $self.mem_use_indirect() }
469// 						}
470// 					}
471
472// 					$(#[$fn_inline_meta])*
473// 					#[inline]
474// 					fn mem_use_inline(&$self) -> usize {
475// 						$($fn_inline)*
476// 					}
477
478// 					$(#[$fn_indirect_meta])*
479// 					#[inline]
480// 					fn mem_use_indirect(&$self) -> usize {
481// 						$($fn_indirect)*
482// 					}
483// 				}
484// 			}
485// 		}
486
487// 		$(#[$impl_const_maybe_meta])*
488// 		impl<$($generics)*> MemUseConstMaybe for $($type)*
489// 		where $($where_const_maybe)*
490// 		{
491// 			$(#[$const_meta])*
492// 			const MEM_USE_MAYBE: Option<usize> = impl_mem_use! { @process_default { $($const_maybe)* } {
493// 				map_maybe_const(
494// 					<Self as MemUseConstMaybe>::MEM_USE_INLINE_MAYBE,
495// 					<Self as MemUseConstMaybe>::MEM_USE_INDIRECT_MAYBE
496// 				)
497// 			} };
498
499// 			$(#[$const_inline_meta])*
500// 			const MEM_USE_INLINE_MAYBE: Option<usize> = $($const_inline_maybe)*;
501
502// 			$(#[$const_indirect_meta])*
503// 			const MEM_USE_INDIRECT_MAYBE: Option<usize> = $($const_indirect_maybe)*;
504// 		}
505// 	};
506
507// 	{ @process_default { _ } { $($default:tt)* } } => { $($default)* };
508// 	{ @process_default { $($stuff:tt)* } { $($unused:tt)* } } => { $($stuff)* };
509// }
510// use impl_mem_use;
511
512// macro_rules! stack_only_impl {
513// 	{ $(#[$meta:meta])* [$($generics:tt)*] $($type:tt)* } => {
514// 		impl_mem_use! {
515// 			$(#[$meta])*
516// 			[$($generics)*] [$($type)*]
517// 			where {}
518// 			where const {}
519// 			where const maybe {}
520
521// 			self
522
523// 			fn { _ }
524// 			fn inline { size_of::<$($type)*>() }
525// 			fn indirect { 0 }
526
527// 			const { _ }
528// 			const inline { Some(size_of::<$($type)*>()) }
529// 			const indirect { Some(0) }
530// 		}
531// 	};
532
533// 	{ $(#[$meta:meta])* $($ty:tt)* } => { stack_only_impl! { $(#[$meta])* [] $($ty)* } };
534// }
535// use stack_only_impl;