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;