wiwi_memory_usage/lib.rs
1#![allow(
2 stable_features,
3 reason = "new_range_api, new_range_from_api, new_range_to_inclusive_api is not stable in msrv"
4)]
5#![cfg_attr(
6 feature = "nightly",
7 feature(
8 const_trait_impl,
9 f16,
10 f128,
11 integer_atomics,
12 new_range_api,
13 new_range_from_api,
14 new_range_to_inclusive_api,
15 phantom_variance_markers
16 )
17)]
18#![cfg_attr(
19 not(feature = "std"),
20 no_std
21)]
22#![deny(
23 unconditional_recursion,
24 clippy::unconditional_recursion
25)]
26
27mod macros;
28
29// the "const" syntax is nightly too, so we can't just
30// use a feature gate on normal code
31macro_rules! const_trait {
32 () => {
33 /// Types that know their own memory usage
34 #[diagnostic::on_unimplemented(
35 message = "Type doesn't know its memory usage"
36 )]
37 pub trait MemoryUsage: MemoryCompaction {
38 /// Get memory usage (including direct, indirect, and compactible memory)
39 fn memory_usage(&self) -> usize;
40 }
41
42 /// Types that always have the same memory usage, regardless of value
43 /// (notably different than [`Sized`])
44 #[diagnostic::on_unimplemented(
45 message = "Type doesn't know its static memory usage"
46 )]
47 pub trait MemoryUsageStatic: MemoryUsage {
48 const MEMORY_USAGE: usize;
49 }
50 };
51
52 (const) => {
53 /// Types that know their own memory usage
54 #[diagnostic::on_unimplemented(
55 message = "Type doesn't know its memory usage"
56 )]
57 pub const trait MemoryUsage: MemoryCompaction {
58 /// Get memory usage (including direct, indirect, and compactible memory)
59 fn memory_usage(&self) -> usize;
60 }
61
62 /// Types that always have the same memory usage, regardless of value
63 /// (notably different than [`Sized`])
64 #[diagnostic::on_unimplemented(
65 message = "Type doesn't know its static memory usage"
66 )]
67 pub const trait MemoryUsageStatic: [const] MemoryUsage {
68 const MEMORY_USAGE: usize;
69 }
70 };
71}
72
73#[cfg(not(feature = "nightly"))]
74const_trait!();
75
76#[cfg(feature = "nightly")]
77const_trait!(const);
78
79pub trait MemoryCompaction {
80 /// Get expected memory usage saved after compaction
81 ///
82 /// Compaction means to remove unnecessary memory usage. This would include,
83 /// for example, removing the unused capacity of a [`Vec`], by calling
84 /// [`shrink_to_fit()`](Vec::shrink_to_fit).
85 ///
86 /// Types like [`Vec`] that support memory compaction _should_ reimplement
87 /// this function.
88 #[inline]
89 fn memory_usage_compacted(&self) -> usize {
90 // default is delegate to ref version of this method, so if someone
91 // implements ref, they get this one for free if they want it
92 // otherwise, no-op
93 self.memory_usage_compacted_ref()
94 }
95
96 /// Perform memory compaction, saving as much memory as possible,
97 /// returning the amount of bytes saved
98 #[inline]
99 fn compact_memory(&mut self) -> usize {
100 // default is delegate to ref version of this method, so if someone
101 // implements ref, they get this one for free if they want it
102 // otherwise, no-op
103 self.compact_memory_ref()
104 }
105
106 /// Get expected memory usage saved after compaction behind a shared reference
107 ///
108 /// This is useful for types with interior mutability. Types that have or
109 /// could have (ie. with generics) should implement this method and
110 /// [`compact_memory_ref()`](MemoryUsage::compact_memory_ref).
111 /// For types that don't, the default implementation is a no-op.
112 ///
113 /// See [`MemoryUsage::memory_usage_compacted`] for more details.
114 #[inline]
115 fn memory_usage_compacted_ref(&self) -> usize {
116 // default is no-op, and no bytes saved
117 0
118 }
119
120 /// Perform memory compaction behind a shared reference, saving as much
121 /// memory as possible, returning the amount of bytes saved
122 ///
123 /// This is useful for types with interior mutability. Types that have or
124 /// could have (ie. with generics) should implement this method and
125 /// [`memory_usage_compacted_ref()`](MemoryUsage::memory_usage_compacted_ref).
126 /// For types that don't, the default implementation is a no-op.
127 ///
128 /// See [`MemoryUsage::compact_memory`] for more details.
129 #[inline]
130 fn compact_memory_ref(&self) -> usize {
131 // default is no-op, and no bytes saved
132 0
133 }
134}
135
136mod impls {
137 // todo primitive types, fn (pointer), closure, tuple (to 16)
138 // todo cells, path, osstr, cstr, rc, arc, types in our lib, other popular libs
139
140 mod array;
141 mod atomic;
142 mod bool;
143 mod char;
144 mod marker;
145 mod nonzero;
146 mod number;
147 mod option;
148 mod pointer;
149 mod range;
150 mod reference;
151 mod result;
152 mod saturating;
153 mod slice;
154 mod string;
155 mod unit;
156 mod vec;
157 mod wrapping;
158}
159
160#[doc(hidden)]
161pub mod __macro_support {
162 pub(crate) use crate::macros::{
163 impl_memory_usage,
164 impl_memory_usage_only_static,
165 impl_memory_usage_static
166 };
167 pub use wiwi_macro_proc::{
168 memory_usage_cfg_nightly as cfg_nightly,
169 memory_usage_cfg_not_nightly as cfg_not_nightly
170 };
171}