rhai/src/unsafe.rs

58 lines
2.1 KiB
Rust
Raw Normal View History

//! A helper module containing unsafe utility functions.
2021-04-17 09:15:54 +02:00
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
use std::{
any::{Any, TypeId},
mem, ptr,
};
/// Cast a type into another type.
2020-07-22 07:05:24 +02:00
#[inline(always)]
2021-03-22 04:18:09 +01:00
pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Result<B, A> {
if TypeId::of::<B>() == a.type_id() {
// SAFETY: Just checked we have the right type. We explicitly forget the
// value immediately after moving out, removing any chance of a destructor
// running or value otherwise being used again.
unsafe {
let ret: B = ptr::read(&a as *const _ as *const B);
mem::forget(a);
2021-03-22 04:18:09 +01:00
Ok(ret)
}
} else {
2021-03-22 04:18:09 +01:00
Err(a)
}
}
/// Cast a Boxed type into another type.
2020-07-22 07:05:24 +02:00
#[inline(always)]
2021-04-19 12:08:29 +02:00
pub fn unsafe_cast_box<X: Any, T: Any>(item: Box<X>) -> Result<Box<T>, Box<X>> {
// 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>);
Ok(Box::from_raw(raw as *mut T))
}
} else {
// Return the consumed item for chaining.
Err(item)
}
}
2020-05-22 07:08:57 +02:00
/// # DANGEROUS!!!
///
2020-10-28 12:11:17 +01:00
/// A dangerous function that blindly casts a `&str` from one lifetime to a `&str` of
/// another lifetime. This is mainly used to let us push a block-local variable into the
2020-11-20 09:52:28 +01:00
/// current [`Scope`][crate::Scope] without cloning the variable name. Doing this is safe because all local
/// variables in the [`Scope`][crate::Scope] are cleared out before existing the block.
///
2020-11-20 09:52:28 +01:00
/// Force-casting a local variable's lifetime to the current [`Scope`][crate::Scope]'s larger lifetime saves
/// on allocations and string cloning, thus avoids us having to maintain a chain of [`Scope`][crate::Scope]'s.
2021-03-04 11:13:47 +01:00
#[inline(always)]
2020-10-28 12:11:17 +01:00
pub fn unsafe_cast_var_name_to_lifetime<'s>(name: &str) -> &'s str {
// WARNING - force-cast the variable name into the scope's lifetime to avoid cloning it
// this is safe because all local variables are cleared at the end of the block
unsafe { mem::transmute(name) }
}