#![allow(clippy::module_name_repetitions)]
#![allow(clippy::let_unit_value)]
#![allow(clippy::let_underscore_untyped)]
#![allow(clippy::ptr_as_ptr)]
use crate::{AnyBitPattern, NoUninit};
use core::mem::{align_of, size_of};
struct Cast<A, B>((A, B));
impl<A, B> Cast<A, B> {
const ASSERT_ALIGN_GREATER_THAN_EQUAL: () =
assert!(align_of::<A>() >= align_of::<B>());
const ASSERT_SIZE_EQUAL: () = assert!(size_of::<A>() == size_of::<B>());
const ASSERT_SIZE_MULTIPLE_OF_OR_INPUT_ZST: () = assert!(
(size_of::<A>() == 0)
|| (size_of::<B>() != 0 && size_of::<A>() % size_of::<B>() == 0)
);
}
#[inline]
pub const fn must_cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
let _ = Cast::<A, B>::ASSERT_SIZE_EQUAL;
unsafe { transmute!(A; B; a) }
}
#[inline]
pub const fn must_cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
let _ = Cast::<A, B>::ASSERT_SIZE_EQUAL;
let _ = Cast::<A, B>::ASSERT_ALIGN_GREATER_THAN_EQUAL;
unsafe { &*(a as *const A as *const B) }
}
maybe_const_fn! {
#[cfg(feature = "must_cast_extra")]
#[inline]
pub fn must_cast_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + AnyBitPattern,
>(
a: &mut A,
) -> &mut B {
let _ = Cast::<A, B>::ASSERT_SIZE_EQUAL;
let _ = Cast::<A, B>::ASSERT_ALIGN_GREATER_THAN_EQUAL;
unsafe { &mut *(a as *mut A as *mut B) }
}
}
#[inline]
pub const fn must_cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
let _ = Cast::<A, B>::ASSERT_SIZE_MULTIPLE_OF_OR_INPUT_ZST;
let _ = Cast::<A, B>::ASSERT_ALIGN_GREATER_THAN_EQUAL;
let new_len = if size_of::<A>() == size_of::<B>() {
a.len()
} else {
a.len() * (size_of::<A>() / size_of::<B>())
};
unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, new_len) }
}
maybe_const_fn! {
#[cfg(feature = "must_cast_extra")]
#[inline]
pub fn must_cast_slice_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + AnyBitPattern,
>(
a: &mut [A],
) -> &mut [B] {
let _ = Cast::<A, B>::ASSERT_SIZE_MULTIPLE_OF_OR_INPUT_ZST;
let _ = Cast::<A, B>::ASSERT_ALIGN_GREATER_THAN_EQUAL;
let new_len = if size_of::<A>() == size_of::<B>() {
a.len()
} else {
a.len() * (size_of::<A>() / size_of::<B>())
};
unsafe { core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, new_len) }
}
}