1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use core::num::NonZero;
/// A type compactly storing a `usize` which is a power of two, and thus
/// represents a possible alignment in the Rust abstract machine.
///
/// To avoid confusion, values of this type shall be referred to as an
/// "alignment", while alignment represented as a `usize` shall be referred to
/// as an "absolute alignment".
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Align(u8);
impl Align {
/// Creates a new alignment from an absolute alignment.
///
/// Returns `None` if the `align` is not a power of two.
pub const fn new(align: usize) -> Option<Self> {
let n = align.trailing_zeros();
if align >> n == 1 {
Self::new_exp(n as u8)
} else {
None
}
}
/// Creates a new alignment from an absolute alignment, bypassing the checks
/// in [`new`](Self::new).
///
/// This should usually not be necessary, as Rust can easily elide the
/// checks if `new` is called with a compile-time-known value.
///
/// # Safety
///
/// Exactly one bit of `align` must be set. In other words, it must be a
/// power of two (not zero).
pub const unsafe fn new_unchecked(align: usize) -> Self {
Self(align.trailing_zeros() as u8)
}
/// Creates a new alignment from the exponent in the equation `align =
/// 2^exp`, where `align` is the absolute alignment.
///
/// Returns `None` if `exp` is too large (if it's greater than
/// [`usize::BITS`].
pub const fn new_exp(exp: u8) -> Option<Self> {
if exp < usize::BITS as u8 {
Some(Self(exp))
} else {
None
}
}
/// Creates a new alignment from the exponent in the equation `align =
/// 2^exp`, where `align` is the absolute alignment, bypassing the checks in
/// [`new_exp`](Self::new_exp).
///
/// This should usually not be necessary, as Rust can easily elide the
/// checks if `new_exp` is called with a compile-time-known value.
///
/// # Safety
///
/// This value must be < `usize::BITS`.
pub const unsafe fn new_exp_unchecked(exp: u8) -> Self {
Self(exp)
}
/// Returns the exponent in the equation `align = 2^exp`, where `align` is
/// the absolute alignment.
pub const fn exp(&self) -> u8 {
self.0
}
/// Returns the absolute alignment.
pub const fn align(&self) -> usize {
1 << self.0 as usize
}
/// Returns the absolute alignment as a non-zero integer.
pub const fn align_nonzero(&self) -> NonZero<usize> {
// Rust elides this check in release mode
NonZero::new(1 << self.0 as usize).unwrap()
}
/// Returns the alignment of a concrete type.
///
/// Uses [`core::mem::align_of`].
pub const fn of<T>() -> Self {
// SAFETY: Rust won't give an invalid alignment
unsafe { Self::new_unchecked(core::mem::align_of::<T>()) }
}
}
/// Layout of a block of memory.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Layout {
/// The minimum size in bytes for a memory block of this layout.
pub size: usize,
/// The minimum byte alignment for a memory block of this layout.
pub align: Align,
}
impl Layout {
/// Returns the layout of a concrete type.
///
/// Uses [`core::mem::size_of`] and [`core::mem::align_of`].
pub const fn of<T>() -> Self {
Self {
size: core::mem::size_of::<T>(),
align: Align::of::<T>(),
}
}
/// Creates a layout describing a list of `T` that is `len` elements long.
pub const fn list<T>(len: usize) -> Self {
let size = size_of::<T>();
let align = Align::of::<T>();
let gap = size % align.align();
Self {
size: (size + gap) * len - gap,
align,
}
}
}