// SPDX-License-Identifier: GPL-2.012//! Memory layout.3//!4//! Custom layout types extending or improving [`Layout`].56use core::{alloc::Layout, marker::PhantomData};78/// Error when constructing an [`ArrayLayout`].9pub struct LayoutError;1011/// A layout for an array `[T; n]`.12///13/// # Invariants14///15/// - `len * size_of::<T>() <= isize::MAX`.16pub struct ArrayLayout<T> {17len: usize,18_phantom: PhantomData<fn() -> T>,19}2021impl<T> Clone for ArrayLayout<T> {22fn clone(&self) -> Self {23*self24}25}26impl<T> Copy for ArrayLayout<T> {}2728const ISIZE_MAX: usize = isize::MAX as usize;2930impl<T> ArrayLayout<T> {31/// Creates a new layout for `[T; 0]`.32pub const fn empty() -> Self {33// INVARIANT: `0 * size_of::<T>() <= isize::MAX`.34Self {35len: 0,36_phantom: PhantomData,37}38}3940/// Creates a new layout for `[T; len]`.41///42/// # Errors43///44/// When `len * size_of::<T>()` overflows or when `len * size_of::<T>() > isize::MAX`.45///46/// # Examples47///48/// ```49/// # use kernel::alloc::layout::{ArrayLayout, LayoutError};50/// let layout = ArrayLayout::<i32>::new(15)?;51/// assert_eq!(layout.len(), 15);52///53/// // Errors because `len * size_of::<T>()` overflows.54/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize);55/// assert!(layout.is_err());56///57/// // Errors because `len * size_of::<i32>() > isize::MAX`,58/// // even though `len < isize::MAX`.59/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize / 2);60/// assert!(layout.is_err());61///62/// # Ok::<(), Error>(())63/// ```64pub const fn new(len: usize) -> Result<Self, LayoutError> {65match len.checked_mul(core::mem::size_of::<T>()) {66Some(size) if size <= ISIZE_MAX => {67// INVARIANT: We checked above that `len * size_of::<T>() <= isize::MAX`.68Ok(Self {69len,70_phantom: PhantomData,71})72}73_ => Err(LayoutError),74}75}7677/// Creates a new layout for `[T; len]`.78///79/// # Safety80///81/// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true.82pub const unsafe fn new_unchecked(len: usize) -> Self {83// INVARIANT: By the safety requirements of this function84// `len * size_of::<T>() <= isize::MAX`.85Self {86len,87_phantom: PhantomData,88}89}9091/// Returns the number of array elements represented by this layout.92pub const fn len(&self) -> usize {93self.len94}9596/// Returns `true` when no array elements are represented by this layout.97pub const fn is_empty(&self) -> bool {98self.len == 099}100101/// Returns the size of the [`ArrayLayout`] in bytes.102pub const fn size(&self) -> usize {103self.len() * core::mem::size_of::<T>()104}105}106107impl<T> From<ArrayLayout<T>> for Layout {108fn from(value: ArrayLayout<T>) -> Self {109let res = Layout::array::<T>(value.len);110// SAFETY: By the type invariant of `ArrayLayout` we have111// `len * size_of::<T>() <= isize::MAX` and thus the result must be `Ok`.112unsafe { res.unwrap_unchecked() }113}114}115116117