#!/usr/bin/env -S rust-script -c --debug
#![cfg_attr(feature = "_docs_examples", allow(unexpected_cfgs, reason = "example script"))]
use ::devela::{Deref, DerefMut};
::devela::_use_or_shim![_doc_location, _doc_vendor, _tags];
#[doc = _tags!(guard)]
#[doc = _doc_location!("code")]
#[doc = _doc_vendor!("stated-scope-guard")]
#[derive(Debug)]
pub struct ScopeGuard<T, F: FnOnce(T, &S), S> {
value: Option<T>,
callback: Option<F>,
state: S,
}
impl<T> ScopeGuard<T, fn(T, &bool), bool> {
pub fn new<F: FnOnce(T)>(value: T, callback: F) -> ScopeGuard<T, impl FnOnce(T, &bool), bool> {
ScopeGuard::with(value, true, move |value, state: &bool| {
if *state {
callback(value);
}
})
}
}
impl<T, F: FnOnce(T, &bool)> ScopeGuard<T, F, bool> {
pub fn dismiss(&mut self) {
self.set_state(false);
}
}
impl<T, F: FnOnce(T, &S), S> ScopeGuard<T, F, S> {
pub fn with(value: T, state: S, callback: F) -> Self {
Self {
value: Some(value),
state,
callback: Some(callback),
}
}
pub fn set_state(&mut self, state: S) {
self.state = state;
}
}
#[rustfmt::skip]
impl<T, F: FnOnce(T, &S), S> Deref for ScopeGuard<T, F, S> {
type Target = T;
fn deref(&self) -> &Self::Target {
cfg_select! { all(feature = "unsafe_layout", not(feature = "safe_code")) => {
unsafe { self.value.as_ref().unwrap_unchecked() }
} _ => {
self.value.as_ref().unwrap()
}}
}
}
#[rustfmt::skip]
impl<T, F: FnOnce(T, &S), S> DerefMut for ScopeGuard<T, F, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
cfg_select! { all(feature = "unsafe_layout", not(feature = "safe_code")) => {
unsafe { self.value.as_mut().unwrap_unchecked() }
} _ => {
self.value.as_mut().unwrap()
}}
}
}
impl<T, F: FnOnce(T, &S), S> Drop for ScopeGuard<T, F, S> {
fn drop(&mut self) {
let (value, callback) = {
cfg_select! { all(feature = "unsafe_layout", not(feature = "safe_code")) => {
let value = unsafe { self.value.take().unwrap_unchecked() };
let callback = unsafe { self.callback.take().unwrap_unchecked() };
(value, callback)
} _ => {
let value = self.value.take().unwrap();
let callback = self.callback.take().unwrap();
(value, callback)
}}
};
callback(value, &self.state);
}
}
#[allow(unused, reason = "example script")]
#[cfg(feature = "std")]
fn main() {
use ::devela::{Cell, cdbg};
let result = Cell::new(0);
{
cdbg![3@ &result];
let _guard = ScopeGuard::new(10, |value| {
result.set(value + 5);
});
}
assert_eq!(result.get(), 15);
cdbg![3@ &result];
}