memapi2/
unstable_util.rs

1use crate::{
2    Layout,
3    data::type_props::USIZE_HIGH_BIT,
4    error::{AlignErr, LayoutErr}
5};
6
7#[cfg(feature = "metadata")]
8/// Alternative to `*mut T`'s `with_metadata_of`, because it's unstable.
9#[must_use = "this returns a new pointer"]
10pub const fn with_meta<T: ?Sized, U: ?Sized>(ptr: *mut T, meta: *const U) -> *mut U {
11    core::ptr::from_raw_parts_mut(ptr.cast::<()>(), core::ptr::metadata(meta))
12}
13
14#[cfg(feature = "metadata")]
15/// Alternative to `*mut T`'s `with_metadata_of`, because it's unstable.
16#[must_use = "this returns a new pointer"]
17pub const fn with_meta_const<T: ?Sized, U: ?Sized>(ptr: *const T, meta: *const U) -> *const U {
18    core::ptr::from_raw_parts(ptr.cast::<()>(), core::ptr::metadata(meta))
19}
20
21/// Creates a [`Layout`] from the given size and alignment after checking their validity.
22///
23/// # Errors
24///
25/// See [`check_lay`].
26#[cfg_attr(not(feature = "dev"), doc(hidden))]
27pub const fn lay_from_size_align(size: usize, align: usize) -> Result<Layout, LayoutErr> {
28    tri!(do check_lay(size, align));
29
30    // SAFETY: we just validated the parameters
31    Ok(unsafe { Layout::from_size_align_unchecked(size, align) })
32}
33
34/// Checks the validity of a size and alignment for being used in a [`Layout`]
35///
36/// # Errors
37///
38/// - <code>[LayoutErr::Align]([AlignErr::ZeroAlign])</code> if `align == 0`.
39/// - <code>[LayoutErr::Align]([AlignErr::NonPowerOfTwoAlign])</code> if `!align.is_power_of_two`.
40/// - [`LayoutErr::ExceedsMax`] if `size` rounded up to the nearest multiple of `align` would be
41///   greater than [`USIZE_MAX_NO_HIGH_BIT`](crate::data::type_props::USIZE_MAX_NO_HIGH_BIT).
42#[cfg_attr(not(feature = "dev"), doc(hidden))]
43pub const fn check_lay(size: usize, align: usize) -> Result<(), LayoutErr> {
44    if align == 0 {
45        return Err(LayoutErr::Align(AlignErr::ZeroAlign));
46    } else if !align.is_power_of_two() {
47        return Err(LayoutErr::Align(AlignErr::NonPowerOfTwoAlign(align)));
48    } else if size > USIZE_HIGH_BIT - align {
49        return Err(LayoutErr::ExceedsMax);
50    }
51    Ok(())
52}