2020-07-23 12:40:42 +02:00
|
|
|
//! A helper module containing unsafe utility functions.
|
2020-05-14 12:27:22 +02:00
|
|
|
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
|
|
|
use std::{
|
2020-05-14 12:27:22 +02:00
|
|
|
any::{Any, TypeId},
|
|
|
|
mem, ptr,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Cast a type into another type.
|
2022-01-02 13:47:03 +01:00
|
|
|
///
|
|
|
|
/// # Undefined Behavior
|
|
|
|
///
|
|
|
|
/// It is UB if the types are not compatible.
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub fn unsafe_cast<A: Any, B: Any>(a: A) -> B {
|
|
|
|
unsafe {
|
|
|
|
let ret: B = ptr::read(&a as *const _ as *const B);
|
|
|
|
// We explicitly forget the value immediately after moving out,
|
|
|
|
// removing any chance of a destructor running or value otherwise
|
|
|
|
// being used again.
|
|
|
|
mem::forget(a);
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Cast a type into another type.
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Option<B> {
|
2020-05-14 12:27:22 +02:00
|
|
|
if TypeId::of::<B>() == a.type_id() {
|
2022-01-02 13:47:03 +01:00
|
|
|
// SAFETY: Just checked we have the right type.
|
|
|
|
Some(unsafe_cast(a))
|
2020-05-14 12:27:22 +02:00
|
|
|
} else {
|
2022-01-02 13:47:03 +01:00
|
|
|
None
|
2020-05-14 12:27:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Cast a Boxed type into another type.
|
2022-01-02 13:47:03 +01:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
2022-01-03 16:11:06 +01:00
|
|
|
pub fn unsafe_cast_box<X: Any, T: Any>(item: Box<X>) -> Option<T> {
|
2020-05-14 12:27:22 +02:00
|
|
|
// Only allow casting to the exact same type
|
|
|
|
if TypeId::of::<X>() == TypeId::of::<T>() {
|
|
|
|
// SAFETY: just checked whether we are pointing to the correct type
|
|
|
|
unsafe {
|
|
|
|
let raw: *mut dyn Any = Box::into_raw(item as Box<dyn Any>);
|
2022-01-03 16:11:06 +01:00
|
|
|
Some(*Box::from_raw(raw as *mut T))
|
2020-05-14 12:27:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-01-02 13:47:03 +01:00
|
|
|
None
|
2020-05-14 12:27:22 +02:00
|
|
|
}
|
|
|
|
}
|