rhai/src/defer.rs

109 lines
3.4 KiB
Rust
Raw Normal View History

2022-11-08 04:52:46 +01:00
//! Facility to run state restoration logic at the end of scope.
use std::ops::{Deref, DerefMut};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
2022-12-04 07:06:54 +01:00
/// Automatically restore state at the end of the scope.
2023-03-25 14:13:34 +01:00
macro_rules! defer {
2022-12-04 07:06:54 +01:00
(let $temp:ident = $var:ident . $prop:ident; $code:stmt) => {
2023-03-25 14:13:34 +01:00
defer!(let $temp = $var.$prop; $code => move |v| v.$prop = $temp);
2022-12-04 07:06:54 +01:00
};
(let $temp:ident = $var:ident . $prop:ident; $code:stmt => $restore:expr) => {
let $temp = $var.$prop;
$code
2023-03-25 14:13:34 +01:00
defer!($var => $restore);
2022-12-04 07:06:54 +01:00
};
2022-12-04 15:47:10 +01:00
($var:ident => $restore:ident; let $temp:ident = $save:expr;) => {
2023-03-25 14:13:34 +01:00
defer!($var => $restore; let $temp = $save; {});
2022-12-04 15:47:10 +01:00
};
($var:ident if $guard:expr => $restore:ident; let $temp:ident = $save:expr;) => {
2023-03-25 14:13:34 +01:00
defer!($var if $guard => $restore; let $temp = $save; {});
2022-12-04 15:47:10 +01:00
};
($var:ident => $restore:ident; let $temp:ident = $save:expr; $code:stmt) => {
let $temp = $save;
$code
2023-03-25 14:13:34 +01:00
defer!($var => move |v| { v.$restore($temp); });
2022-12-04 15:47:10 +01:00
};
($var:ident if $guard:expr => $restore:ident; let $temp:ident = $save:expr; $code:stmt) => {
let $temp = $save;
$code
2023-03-25 14:13:34 +01:00
defer!($var if $guard => move |v| { v.$restore($temp); });
2022-12-04 15:47:10 +01:00
};
($var:ident => $restore:expr) => {
2023-03-25 14:13:34 +01:00
defer!($var = $var => $restore);
2022-12-04 07:06:54 +01:00
};
2022-12-04 15:47:10 +01:00
($var:ident = $value:expr => $restore:expr) => {
2023-03-25 14:13:34 +01:00
let $var = &mut *crate::Deferred::lock($value, $restore);
2022-12-04 07:06:54 +01:00
};
2022-12-10 15:37:13 +01:00
($var:ident if Some($guard:ident) => $restore:expr) => {
2023-03-25 14:13:34 +01:00
defer!($var = ($var) if Some($guard) => $restore);
2022-12-10 15:37:13 +01:00
};
($var:ident = ( $value:expr ) if Some($guard:ident) => $restore:expr) => {
let mut __rx__;
let $var = if let Some($guard) = $guard {
2023-03-25 14:13:34 +01:00
__rx__ = crate::Deferred::lock($value, $restore);
2022-12-10 15:37:13 +01:00
&mut *__rx__
} else {
&mut *$value
};
};
2022-12-04 15:47:10 +01:00
($var:ident if $guard:expr => $restore:expr) => {
2023-03-25 14:13:34 +01:00
defer!($var = ($var) if $guard => $restore);
2022-12-04 07:06:54 +01:00
};
2022-12-04 15:47:10 +01:00
($var:ident = ( $value:expr ) if $guard:expr => $restore:expr) => {
2022-12-04 07:06:54 +01:00
let mut __rx__;
let $var = if $guard {
2023-03-25 14:13:34 +01:00
__rx__ = crate::Deferred::lock($value, $restore);
2022-12-04 07:06:54 +01:00
&mut *__rx__
} else {
&mut *$value
};
};
}
2022-11-08 04:52:46 +01:00
/// Run custom restoration logic upon the end of scope.
#[must_use]
2023-03-25 14:13:34 +01:00
pub struct Deferred<'a, T: ?Sized, R: FnOnce(&mut T)> {
2023-04-05 17:15:55 +02:00
lock: &'a mut T,
defer: Option<R>,
2022-11-08 04:52:46 +01:00
}
2023-03-25 14:13:34 +01:00
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deferred<'a, T, R> {
/// Create a new [`Deferred`] that locks a mutable reference and runs restoration logic at
2022-11-08 08:01:40 +01:00
/// the end of scope.
///
/// Beware that the end of scope means the end of its lifetime, not necessarily waiting until
/// the current block scope is exited.
2022-11-08 04:52:46 +01:00
#[inline(always)]
2022-11-08 08:01:40 +01:00
pub fn lock(value: &'a mut T, restore: R) -> Self {
2022-11-08 04:52:46 +01:00
Self {
2023-04-05 17:15:55 +02:00
lock: value,
defer: Some(restore),
2022-11-08 04:52:46 +01:00
}
}
}
2023-03-25 14:13:34 +01:00
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Drop for Deferred<'a, T, R> {
2022-11-08 04:52:46 +01:00
#[inline(always)]
fn drop(&mut self) {
2023-04-05 17:15:55 +02:00
self.defer.take().unwrap()(self.lock);
2022-11-08 04:52:46 +01:00
}
}
2023-03-25 14:13:34 +01:00
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deref for Deferred<'a, T, R> {
2022-11-08 04:52:46 +01:00
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
2023-04-05 17:15:55 +02:00
self.lock
2022-11-08 04:52:46 +01:00
}
}
2023-03-25 14:13:34 +01:00
impl<'a, T: ?Sized, R: FnOnce(&mut T)> DerefMut for Deferred<'a, T, R> {
2022-11-08 04:52:46 +01:00
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
2023-04-05 17:15:55 +02:00
self.lock
2022-11-08 04:52:46 +01:00
}
}