Improve reify syntax.
This commit is contained in:
@@ -46,11 +46,13 @@ impl<'a> ArgBackup<'a> {
|
||||
/// This function replaces the first argument of a method call with a clone copy.
|
||||
/// This is to prevent a pure function unintentionally consuming the first argument.
|
||||
///
|
||||
/// `restore_first_arg` must be called before the end of the scope to prevent the shorter lifetime from leaking.
|
||||
/// `restore_first_arg` must be called before the end of the scope to prevent the shorter
|
||||
/// lifetime from leaking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This method blindly casts a reference to another lifetime, which saves allocation and string cloning.
|
||||
/// This method blindly casts a reference to another lifetime, which saves allocation and
|
||||
/// string cloning.
|
||||
///
|
||||
/// As long as `restore_first_arg` is called before the end of the scope, the shorter lifetime
|
||||
/// will not leak.
|
||||
@@ -71,8 +73,8 @@ impl<'a> ArgBackup<'a> {
|
||||
// Blindly casting a reference to another lifetime saves allocation and string cloning,
|
||||
// but must be used with the utmost care.
|
||||
//
|
||||
// We can do this here because, before the end of this scope, we'd restore the original reference
|
||||
// via `restore_first_arg`. Therefore this shorter lifetime does not leak.
|
||||
// We can do this here because, before the end of this scope, we'd restore the original
|
||||
// reference via `restore_first_arg`. Therefore this shorter lifetime does not leak.
|
||||
self.orig_mut = Some(mem::replace(&mut args[0], unsafe {
|
||||
mem::transmute(&mut self.value_copy)
|
||||
}));
|
||||
@@ -81,8 +83,8 @@ impl<'a> ArgBackup<'a> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// If `change_first_arg_to_copy` has been called, this function **MUST** be called _BEFORE_ exiting
|
||||
/// the current scope. Otherwise it is undefined behavior as the shorter lifetime will leak.
|
||||
/// If `change_first_arg_to_copy` has been called, this function **MUST** be called _BEFORE_
|
||||
/// exiting the current scope. Otherwise it is undefined behavior as the shorter lifetime will leak.
|
||||
#[inline(always)]
|
||||
fn restore_first_arg(mut self, args: &mut FnCallArgs<'a>) {
|
||||
if let Some(p) = self.orig_mut.take() {
|
||||
|
@@ -38,25 +38,26 @@ pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<T> {
|
||||
}
|
||||
|
||||
/// Dereference into value.
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
|
||||
if TypeId::of::<T>() == TypeId::of::<&str>() {
|
||||
// If T is `&str`, data must be `ImmutableString`, so map directly to it
|
||||
data.flatten_in_place();
|
||||
let ref_str = data.as_str_ref().expect("&str");
|
||||
//let ref_t = reify!(&ref_str, |ref_t: &T| ref_t, || unreachable!());
|
||||
let ref_t = unsafe { mem::transmute::<_, &T>(&ref_str) };
|
||||
ref_t.clone()
|
||||
} else if TypeId::of::<T>() == TypeId::of::<String>() {
|
||||
// If T is `String`, data must be `ImmutableString`, so map directly to it
|
||||
let t = mem::take(data).into_string().expect("`ImmutableString`");
|
||||
reify!(t, |t: T| t, || unreachable!())
|
||||
} else {
|
||||
// We consume the argument and then replace it with () - the argument is not supposed to be used again.
|
||||
// This way, we avoid having to clone the argument again, because it is already a clone when passed here.
|
||||
mem::take(data).cast::<T>()
|
||||
// # Safety
|
||||
//
|
||||
// We already checked that `T` is `&str`, so it is safe to cast here.
|
||||
return unsafe { std::mem::transmute_copy::<_, T>(&ref_str) };
|
||||
}
|
||||
if TypeId::of::<T>() == TypeId::of::<String>() {
|
||||
// If T is `String`, data must be `ImmutableString`, so map directly to it
|
||||
return reify!(mem::take(data).into_string().expect("`ImmutableString`") => T);
|
||||
}
|
||||
|
||||
// We consume the argument and then replace it with () - the argument is not supposed to be used again.
|
||||
// This way, we avoid having to clone the argument again, because it is already a clone when passed here.
|
||||
return mem::take(data).cast::<T>();
|
||||
}
|
||||
|
||||
/// Trait to register custom Rust functions.
|
||||
|
Reference in New Issue
Block a user