devela/sys/mem/size/
bit.rs

1// devela::sys::mem::size::bit
2//
3//! Functionality related to memory bit size.
4//
5// TOC
6// - imports
7// - fn definitions
8// - trait definition
9// - trait impls
10
11#[cfg(feature = "std")]
12use crate::{Arc, HashMap, HashSet, Mutex, Rc, SystemInstant, SystemTime};
13use crate::{
14    BareBox, ByteSized, Duration, Infallible, Mem, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64,
15    NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8,
16    NonZeroUsize, Ordering, PhantomData, PhantomPinned,
17};
18
19// WAIT: [generic_const_exprs](https://github.com/rust-lang/rust/issues/76560#issuecomment-1202124275)
20// use crate::{StringU16, StringU32, GraphemeU8, StringU8};
21#[cfg(feature = "alloc")]
22use crate::GraphemeString;
23#[cfg(feature = "alloc")]
24use crate::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, String, Vec, VecDeque};
25#[cfg(feature = "_str_nonul")]
26use crate::{GraphemeNonul, StringNonul};
27
28#[cfg(feature = "dep_portable_atomic")]
29use crate::_dep::portable_atomic::{AtomicF32, AtomicF64, AtomicI128, AtomicU128};
30#[cfg(feature = "work")]
31use crate::{AtomicBool, AtomicOrdering};
32#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "16")))]
33use crate::{AtomicI16, AtomicU16};
34#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "32")))]
35use crate::{AtomicI32, AtomicU32};
36#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "64")))]
37use crate::{AtomicI64, AtomicU64};
38#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "8")))]
39use crate::{AtomicI8, AtomicU8};
40#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "ptr")))]
41use crate::{AtomicIsize, AtomicPtr, AtomicUsize};
42
43/* trait definition */
44
45/// Type size information in bits.
46///
47/// Indicates a size of exactly `LEN` bits for the relevant data part of this type.
48///
49/// E.g. a `bool` has a BitSized of 1 bit.
50pub trait BitSized<const LEN: usize>: ByteSized {
51    /// The bit size of this type (only the relevant data part, without padding).
52    ///
53    /// # Panics
54    /// Panics if `MIN_BYTE_SIZE > `[`BYTE_SIZE`][ByteSized::BYTE_SIZE],
55    const BIT_SIZE: usize = {
56        let min_byte_size = Mem::bytes_from_bits(LEN);
57        if min_byte_size > Self::BYTE_SIZE {
58            panic!["BitSized::MIN_BYTE_SIZE > ByteSized::BYTE_SIZE"];
59        }
60        LEN
61    };
62
63    /// The rounded up byte size for this type.
64    ///
65    /// This is the minimum number of full bytes needed to represent this type.
66    /// Basically `(LEN + 7) / 8`.
67    ///
68    /// # Panics
69    /// Panics if `MIN_BYTE_SIZE > `[`BYTE_SIZE`][ByteSized::BYTE_SIZE],
70    const MIN_BYTE_SIZE: usize = {
71        let min_byte_size = Mem::bytes_from_bits(LEN);
72        if min_byte_size > Self::BYTE_SIZE {
73            panic!["BitSized::MIN_BYTE_SIZE > ByteSized::BYTE_SIZE"];
74        }
75        min_byte_size
76    };
77
78    /// Returns the bit size of this type (only the relevant data part, without padding).
79    ///
80    /// # Panics
81    /// Panics if `MIN_BYTE_SIZE > `[`BYTE_SIZE`][ByteSized::BYTE_SIZE],
82    #[must_use]
83    fn bit_size(&self) -> usize {
84        Self::BIT_SIZE
85    }
86
87    /// Returns the rounded up byte size for this type.
88    ///
89    /// This is the minimum number of full bytes needed to represent this type.
90    /// Basically `(LEN + 7) / 8`.
91    ///
92    /// # Panics
93    /// Panics if `MIN_BYTE_SIZE > `[`BYTE_SIZE`][ByteSized::BYTE_SIZE],
94    #[must_use]
95    fn min_byte_size(&self) -> usize {
96        Self::MIN_BYTE_SIZE
97    }
98}
99
100// Implement BitSized
101macro_rules! bit_sized {
102    /* primitives */
103
104    (= $bits:expr; for $($t:ty),+) => { $( impl $crate::BitSized<$bits> for $t {} )+ };
105
106    /* primitives generic on $T */
107
108    (<$T:ident> = $bits:expr; for $($t:ty),+) => {
109        $( impl<$T> $crate::BitSized<$bits> for $t {} )+
110    };
111    (<const $T:ident: $Tt:ty> = $bits:expr; for $($t:ty),+) => {
112        $( impl<const $T: $Tt> $crate::BitSized<$bits> for $t {} )+
113    };
114
115    /* primitives generic on $K, $V */
116
117    (<$K:ident, $V:ident> = $bits:expr; for $($t:ty),+) => {
118        $( impl<$K, $V> $crate::BitSized<$bits> for $t {} )+
119    };
120    (<const $K:ident: $Kt:ty, const $V:ident: $Vt:ty> = $bits:expr; for $($t:ty),+) => {
121        $( impl<const $K: $Kt, const $V: $Vt> $crate::BitSized<$bits> for $t {} )+
122    };
123
124    /* pointer primitives */
125
126    // implements BitSized<$PTR_BITS> for pointer-sized related types.
127    (pointer = $PTR_BITS:literal) => {
128        bit_sized![= $PTR_BITS; for isize, usize];
129
130        bit_sized![= $PTR_BITS; for NonZeroIsize, NonZeroUsize];
131
132        #[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "ptr")))]
133        bit_sized![= $PTR_BITS; for AtomicIsize, AtomicUsize];
134        #[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "ptr")))]
135        bit_sized![<T> = $PTR_BITS; for AtomicPtr<T>];
136
137        #[cfg(feature = "std")]
138        bit_sized![<T> = {$PTR_BITS * 1}; for Rc<T>, Arc<T>];
139
140        bit_sized![= {$PTR_BITS * 2}; for &str];
141        bit_sized![<T> = {$PTR_BITS * 2}; for &[T], &mut [T]];
142
143        #[cfg(feature = "alloc")]
144        bit_sized![= {$PTR_BITS * 3}; for String];
145
146        #[cfg(feature = "alloc")]
147        bit_sized![= {$PTR_BITS * 3}; for GraphemeString];
148
149        #[cfg(feature = "alloc")]
150        bit_sized![<T> = {$PTR_BITS * 3};
151            for Vec<T>, LinkedList<T>, VecDeque<T>, BTreeSet<T>, BinaryHeap<T>];
152        #[cfg(feature = "std")]
153        bit_sized![<T> = {$PTR_BITS * 3}; for HashSet<T>, Mutex<T>];
154
155        // K, V
156        #[cfg(feature = "alloc")]
157        bit_sized![<K, V> = {$PTR_BITS * 3}; for BTreeMap<K, V>];
158        #[cfg(feature = "std")]
159        bit_sized![<K, V> = {$PTR_BITS * 3}; for HashMap<K, V>];
160    };
161
162    /* arrays */
163
164    (array = $bits:literal * len for T: $tsize:literal * len: $($len:literal),+) => {
165        $(
166        impl<T: $crate::BitSized<$tsize>> $crate::BitSized<{$bits*$len}> for [T; $len] {}
167        )+
168    };
169}
170#[allow(unused_imports)] // TEMP
171pub(crate) use bit_sized;
172
173/* impl BitSized */
174
175impl<T: BitSized<LEN>, const LEN: usize> BitSized<LEN> for BareBox<T> {}
176
177bit_sized![<T> = 0; for PhantomData<T>];
178bit_sized![= 0; for (), Infallible, PhantomPinned];
179bit_sized![= 1; for bool];
180bit_sized![= 8; for i8, u8, Ordering];
181bit_sized![= 16; for i16, u16];
182bit_sized![= 32; for i32, u32, f32, char];
183bit_sized![= 64; for i64, u64, f64];
184bit_sized![= 128; for i128, u128, Duration];
185#[cfg(feature = "std")]
186bit_sized![= 128; for SystemInstant, SystemTime];
187
188#[cfg(feature = "_char7")]
189bit_sized![= 7; for crate::char7];
190#[cfg(feature = "_char8")]
191bit_sized![= 8; for crate::char8];
192#[cfg(feature = "_char16")]
193bit_sized![= 16; for crate::char16];
194
195bit_sized![= 8; for NonZeroI8, NonZeroU8];
196bit_sized![= 16; for NonZeroI16, NonZeroU16];
197bit_sized![= 32; for NonZeroI32, NonZeroU32];
198bit_sized![= 64; for NonZeroI64, NonZeroU64];
199bit_sized![= 128; for NonZeroI128, NonZeroU128];
200
201#[cfg(feature = "work")]
202bit_sized![= 1; for AtomicBool];
203#[cfg(feature = "work")]
204bit_sized![= 8; for AtomicOrdering];
205#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "8")))]
206bit_sized![= 8; for AtomicI8, AtomicU8];
207#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "16")))]
208bit_sized![= 16; for AtomicI16, AtomicU16];
209#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "32")))]
210bit_sized![= 32; for AtomicI32, AtomicU32];
211#[cfg(all(feature = "work", any(feature = "dep_portable_atomic", target_has_atomic = "64")))]
212bit_sized![= 64; for AtomicI64, AtomicU64];
213#[cfg(feature = "dep_portable_atomic")]
214bit_sized![= 32; for AtomicF32];
215#[cfg(feature = "dep_portable_atomic")]
216bit_sized![= 64; for AtomicF64];
217#[cfg(feature = "dep_portable_atomic")]
218bit_sized![= 128; for AtomicI128, AtomicU128];
219
220#[cfg(feature = "_str_nonul")]
221bit_sized![<const LEN: usize> = LEN; for GraphemeNonul<LEN>, StringNonul<LEN>];
222// WAIT: [generic_const_exprs](https://github.com/rust-lang/rust/issues/76560#issuecomment-1202124275)
223// bit_sized![<const LEN: usize> = { LEN + 8 }; for StringU8<LEN>, GraphemeU8<LEN>];
224// bit_sized![<const LEN: usize> = { LEN + 16 }; for StringU16<LEN>];
225// bit_sized![<const LEN: usize> = { LEN + 32 }; for StringU32<LEN>];
226
227#[cfg(target_pointer_width = "8")]
228bit_sized![pointer = 8];
229#[cfg(target_pointer_width = "16")]
230bit_sized![pointer = 16];
231#[cfg(target_pointer_width = "32")]
232bit_sized![pointer = 32];
233#[cfg(target_pointer_width = "64")]
234bit_sized![pointer = 64];
235#[cfg(target_pointer_width = "128")]
236bit_sized![pointer = 128];
237
238// THINK: IMPROVE use const generics?
239bit_sized![array = 8 * len for T: 8 * len: 1, 2, 4, 8, 16];
240bit_sized![array = 16 * len for T: 16 * len: 1, 2, 4, 8, 16];
241bit_sized![array = 24 * len for T: 24 * len: 1, 2, 4, 8, 16]; // *
242bit_sized![array = 32 * len for T: 32 * len: 1, 2, 4, 8, 16];
243bit_sized![array = 40 * len for T: 40 * len: 1, 2, 4, 8, 16]; // *
244bit_sized![array = 48 * len for T: 48 * len: 1, 2, 4, 8, 16]; // *
245bit_sized![array = 56 * len for T: 56 * len: 1, 2, 4, 8, 16]; // *
246bit_sized![array = 64 * len for T: 64 * len: 1, 2, 4, 8, 16];
247bit_sized![array = 72 * len for T: 72 * len: 1, 2, 4, 8, 16]; // *
248bit_sized![array = 80 * len for T: 80 * len: 1, 2, 4, 8, 16]; // *
249bit_sized![array = 88 * len for T: 88 * len: 1, 2, 4, 8, 16]; // *
250bit_sized![array = 96 * len for T: 96 * len: 1, 2, 4, 8, 16]; // *
251bit_sized![array = 104 * len for T: 104 * len: 1, 2, 4, 8, 16]; // *
252bit_sized![array = 112 * len for T: 112 * len: 1, 2, 4, 8, 16]; // *
253bit_sized![array = 120 * len for T: 120 * len: 1, 2, 4, 8, 16]; // *
254bit_sized![array = 128 * len for T: 128 * len: 1, 2, 4, 8, 16];