1 /*! Descriptions of integer types
2
3 This module describes the integer types used to hold bare data. This module
4 governs the way the processor manipulates integer regions of memory, without
5 concern for interaction with specifics of register or bus behavior.
6 !*/
7
8 use core::mem;
9
10 use funty::IsUnsigned;
11
12 /** Description of an integer type.
13
14 This trait provides information used to describe integer-typed regions of memory
15 and enables other parts of the crate to adequately describe the memory bus. This
16 trait has **no** bearing on the processor instructions or registers used to
17 interact with memory.
18
19 This trait cannot be implemented outside this crate.
20 **/
21 pub trait BitMemory: IsUnsigned + seal::Sealed {
22 /// The bit width of the integer.
23 ///
24 /// `mem::size_of` returns the size in bytes, and bytes are always eight
25 /// bits on architectures Rust targets.
26 ///
27 /// Issue #76904 will place this constant on the fundamentals directly, as a
28 /// `u32`.
29 const BITS: u8 = mem::size_of::<Self>() as u8 * 8;
30 /// The number of bits required to store an index in the range `0 .. BITS`.
31 const INDX: u8 = Self::BITS.trailing_zeros() as u8;
32 /// A mask over all bits that can be used as an index within the element.
33 const MASK: u8 = Self::BITS - 1;
34
35 /// The value with only its least significant bit set to `1`.
36 const ONE: Self;
37 /// The value with all of its bits set to `1`.
38 const ALL: Self;
39 }
40
41 macro_rules! memory {
42 ($($t:ty),+ $(,)?) => { $(
43 impl BitMemory for $t {
44 const ONE: Self = 1;
45 const ALL: Self = !0;
46 }
47 impl seal::Sealed for $t {}
48 )+ };
49 }
50
51 memory!(u8, u16, u32, u64, u128, usize);
52
53 /** Computes the number of elements required to store some number of bits.
54
55 # Parameters
56
57 - `bits`: The number of bits to store in a `[T]` array.
58
59 # Returns
60
61 The number of elements `T` required to store `bits`.
62
63 As this is a const function, when `bits` is a constant expression, this can be
64 used to compute the size of an array type `[T; elts(bits)]`.
65 **/
66 #[doc(hidden)]
elts<T>(bits: usize) -> usize67 pub const fn elts<T>(bits: usize) -> usize {
68 let width = mem::size_of::<T>() * 8;
69 bits / width + (bits % width != 0) as usize
70 }
71
72 /** Tests that a type is aligned to its size.
73
74 This property is not necessarily true for all integers; for instance, `u64` on
75 32-bit x86 is permitted to be 4-byte-aligned. `bitvec` requires this property to
76 hold for the pointer representation to correctly function.
77
78 # Type Parameters
79
80 - `T`: A type whose alignment and size are to be compared
81
82 # Returns
83
84 `0` if the alignment matches the size; `1` if they differ
85 **/
86 #[doc(hidden)]
aligned_to_size<T>() -> usize87 pub(crate) const fn aligned_to_size<T>() -> usize {
88 (mem::align_of::<T>() != mem::size_of::<T>()) as usize
89 }
90
91 /** Tests whether two types have compatible layouts.
92
93 # Type Parameters
94
95 - `A`
96 - `B`
97
98 # Returns
99
100 Zero if `A` and `B` have equal alignments and sizes, non-zero if they do not.
101
102 # Uses
103
104 This function is designed to be used in the expression
105 `const CHECK: [(): 0] = [(); cmp_layout::<A, B>()];`. It will cause a compiler
106 error if the conditions do not hold.
107 **/
108 #[doc(hidden)]
cmp_layout<A, B>() -> usize109 pub(crate) const fn cmp_layout<A, B>() -> usize {
110 (mem::align_of::<A>() != mem::align_of::<B>()) as usize
111 + (mem::size_of::<A>() != mem::size_of::<B>()) as usize
112 }
113
114 #[doc(hidden)]
115 mod seal {
116 #[doc(hidden)]
117 pub trait Sealed {}
118 }
119