Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/alloc/layout.rs
29266 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Memory layout.
4
//!
5
//! Custom layout types extending or improving [`Layout`].
6
7
use core::{alloc::Layout, marker::PhantomData};
8
9
/// Error when constructing an [`ArrayLayout`].
10
pub struct LayoutError;
11
12
/// A layout for an array `[T; n]`.
13
///
14
/// # Invariants
15
///
16
/// - `len * size_of::<T>() <= isize::MAX`.
17
pub struct ArrayLayout<T> {
18
len: usize,
19
_phantom: PhantomData<fn() -> T>,
20
}
21
22
impl<T> Clone for ArrayLayout<T> {
23
fn clone(&self) -> Self {
24
*self
25
}
26
}
27
impl<T> Copy for ArrayLayout<T> {}
28
29
const ISIZE_MAX: usize = isize::MAX as usize;
30
31
impl<T> ArrayLayout<T> {
32
/// Creates a new layout for `[T; 0]`.
33
pub const fn empty() -> Self {
34
// INVARIANT: `0 * size_of::<T>() <= isize::MAX`.
35
Self {
36
len: 0,
37
_phantom: PhantomData,
38
}
39
}
40
41
/// Creates a new layout for `[T; len]`.
42
///
43
/// # Errors
44
///
45
/// When `len * size_of::<T>()` overflows or when `len * size_of::<T>() > isize::MAX`.
46
///
47
/// # Examples
48
///
49
/// ```
50
/// # use kernel::alloc::layout::{ArrayLayout, LayoutError};
51
/// let layout = ArrayLayout::<i32>::new(15)?;
52
/// assert_eq!(layout.len(), 15);
53
///
54
/// // Errors because `len * size_of::<T>()` overflows.
55
/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize);
56
/// assert!(layout.is_err());
57
///
58
/// // Errors because `len * size_of::<i32>() > isize::MAX`,
59
/// // even though `len < isize::MAX`.
60
/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize / 2);
61
/// assert!(layout.is_err());
62
///
63
/// # Ok::<(), Error>(())
64
/// ```
65
pub const fn new(len: usize) -> Result<Self, LayoutError> {
66
match len.checked_mul(core::mem::size_of::<T>()) {
67
Some(size) if size <= ISIZE_MAX => {
68
// INVARIANT: We checked above that `len * size_of::<T>() <= isize::MAX`.
69
Ok(Self {
70
len,
71
_phantom: PhantomData,
72
})
73
}
74
_ => Err(LayoutError),
75
}
76
}
77
78
/// Creates a new layout for `[T; len]`.
79
///
80
/// # Safety
81
///
82
/// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true.
83
pub const unsafe fn new_unchecked(len: usize) -> Self {
84
// INVARIANT: By the safety requirements of this function
85
// `len * size_of::<T>() <= isize::MAX`.
86
Self {
87
len,
88
_phantom: PhantomData,
89
}
90
}
91
92
/// Returns the number of array elements represented by this layout.
93
pub const fn len(&self) -> usize {
94
self.len
95
}
96
97
/// Returns `true` when no array elements are represented by this layout.
98
pub const fn is_empty(&self) -> bool {
99
self.len == 0
100
}
101
102
/// Returns the size of the [`ArrayLayout`] in bytes.
103
pub const fn size(&self) -> usize {
104
self.len() * core::mem::size_of::<T>()
105
}
106
}
107
108
impl<T> From<ArrayLayout<T>> for Layout {
109
fn from(value: ArrayLayout<T>) -> Self {
110
let res = Layout::array::<T>(value.len);
111
// SAFETY: By the type invariant of `ArrayLayout` we have
112
// `len * size_of::<T>() <= isize::MAX` and thus the result must be `Ok`.
113
unsafe { res.unwrap_unchecked() }
114
}
115
}
116
117