use core::any::TypeId;
use core::intrinsics::transmute_unchecked;
use core::marker::Destruct;
#[expect(unused)]
const fn type_eq<T: 'static, U: 'static>() -> bool {
TypeId::of::<T>() == TypeId::of::<U>()
}
const fn type_ne<T: 'static, U: 'static>() -> bool {
TypeId::of::<T>() != TypeId::of::<U>()
}
#[expect(unused)]
fn try_transmute<Src: 'static, Dst: 'static>(src: Src) -> Result<Dst, Src> {
match type_eq::<Src, Dst>() {
true => Ok(
unsafe { transmute_unchecked::<Src, Dst>(src) },
),
false => Err(src),
}
}
#[rustfmt::skip]
pub(crate) const fn try_fn_once<
GenericInput: 'static,
GenericOutput: 'static,
ConcreteInput: 'static,
ConcreteOutput: 'static,
>(
generic_input: GenericInput,
f: impl [const] FnOnce(ConcreteInput) -> ConcreteOutput + [const] Destruct,
) -> Result<GenericOutput, GenericInput> {
if const { type_ne::<GenericInput, ConcreteInput>() || type_ne::<GenericOutput, ConcreteOutput>() } {
return Err(generic_input);
}
let concrete_input: ConcreteInput = unsafe { transmute_unchecked::<GenericInput, ConcreteInput>(generic_input) };
let concrete_output: ConcreteOutput = f(concrete_input);
let generic_output: GenericOutput = unsafe { transmute_unchecked::<ConcreteOutput, GenericOutput>(concrete_output) };
Ok(generic_output)
}
#[expect(unused)]
#[rustfmt::skip]
pub(crate) fn try_fn_mut<
GenericInput: 'static,
ConcreteInput: 'static,
>(
generic_input: GenericInput,
mut f: impl FnMut(&mut ConcreteInput),
) -> Result<GenericInput, GenericInput> {
if const { type_ne::<GenericInput, ConcreteInput>() } {
return Err(generic_input);
}
let mut concrete_input: ConcreteInput = unsafe { transmute_unchecked::<GenericInput, ConcreteInput>(generic_input) };
f(&mut concrete_input);
let generic_input: GenericInput = unsafe { transmute_unchecked::<ConcreteInput, GenericInput>(concrete_input) };
Ok(generic_input)
}