use super::Context;
use super::VariableSet;
use crate::Env;
use std::ops::Deref;
use std::ops::DerefMut;
#[derive(Debug)]
#[must_use = "You must retain ContextGuard to keep the context alive"]
pub struct ContextGuard<'a> {
stack: &'a mut VariableSet,
}
impl VariableSet {
#[inline]
pub fn push_context(&mut self, context: Context) -> ContextGuard<'_> {
self.push_context_impl(context);
ContextGuard { stack: self }
}
#[inline]
pub fn pop_context(guard: ContextGuard<'_>) {
drop(guard)
}
}
impl std::ops::Drop for ContextGuard<'_> {
#[inline]
fn drop(&mut self) {
self.stack.pop_context_impl()
}
}
impl std::ops::Deref for ContextGuard<'_> {
type Target = VariableSet;
#[inline]
fn deref(&self) -> &VariableSet {
self.stack
}
}
impl std::ops::DerefMut for ContextGuard<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut VariableSet {
self.stack
}
}
#[derive(Debug)]
#[must_use = "The context is popped when the guard is dropped"]
pub struct EnvContextGuard<'a, S> {
env: &'a mut Env<S>,
}
impl<S> Env<S> {
#[inline]
pub fn push_context(&mut self, context: Context) -> EnvContextGuard<'_, S> {
self.variables.push_context_impl(context);
EnvContextGuard { env: self }
}
#[inline]
pub fn pop_context(guard: EnvContextGuard<'_, S>) {
drop(guard)
}
}
impl<S> Drop for EnvContextGuard<'_, S> {
#[inline]
fn drop(&mut self) {
self.env.variables.pop_context_impl()
}
}
impl<S> Deref for EnvContextGuard<'_, S> {
type Target = Env<S>;
#[inline]
fn deref(&self) -> &Env<S> {
self.env
}
}
impl<S> DerefMut for EnvContextGuard<'_, S> {
#[inline]
fn deref_mut(&mut self) -> &mut Env<S> {
self.env
}
}
#[cfg(test)]
mod tests {
use super::super::Scope;
use super::super::Value;
use super::*;
#[test]
fn scope_guard() {
let mut env = Env::new_virtual();
let mut guard = env.variables.push_context(Context::default());
guard
.get_or_new("foo", Scope::Global)
.assign("", None)
.unwrap();
guard
.get_or_new("bar", Scope::Local)
.assign("", None)
.unwrap();
VariableSet::pop_context(guard);
let variable = env.variables.get("foo").unwrap();
assert_eq!(variable.value, Some(Value::scalar("")));
assert_eq!(env.variables.get("bar"), None);
}
#[test]
fn env_scope_guard() {
let mut env = Env::new_virtual();
let mut guard = env.push_context(Context::default());
guard
.variables
.get_or_new("foo", Scope::Global)
.assign("", None)
.unwrap();
guard
.variables
.get_or_new("bar", Scope::Local)
.assign("", None)
.unwrap();
Env::pop_context(guard);
let variable = env.variables.get("foo").unwrap();
assert_eq!(variable.value, Some(Value::scalar("")));
assert_eq!(env.variables.get("bar"), None);
}
}