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