yash_env/variable/
guard.rs1use super::Context;
18use super::VariableSet;
19use crate::Env;
20use std::ops::Deref;
21use std::ops::DerefMut;
22
23#[derive(Debug)]
27#[must_use = "You must retain ContextGuard to keep the context alive"]
28pub struct ContextGuard<'a> {
29 stack: &'a mut VariableSet,
30}
31
32impl VariableSet {
33 #[inline]
43 pub fn push_context(&mut self, context: Context) -> ContextGuard<'_> {
44 self.push_context_impl(context);
45 ContextGuard { stack: self }
46 }
47
48 #[inline]
50 pub fn pop_context(guard: ContextGuard<'_>) {
51 drop(guard)
52 }
53}
54
55impl std::ops::Drop for ContextGuard<'_> {
58 #[inline]
59 fn drop(&mut self) {
60 self.stack.pop_context_impl()
61 }
62}
63
64impl std::ops::Deref for ContextGuard<'_> {
65 type Target = VariableSet;
66 #[inline]
67 fn deref(&self) -> &VariableSet {
68 self.stack
69 }
70}
71
72impl std::ops::DerefMut for ContextGuard<'_> {
73 #[inline]
74 fn deref_mut(&mut self) -> &mut VariableSet {
75 self.stack
76 }
77}
78
79#[derive(Debug)]
83#[must_use = "The context is popped when the guard is dropped"]
84pub struct EnvContextGuard<'a> {
85 env: &'a mut Env,
86}
87
88impl Env {
89 #[inline]
95 pub fn push_context(&mut self, context: Context) -> EnvContextGuard<'_> {
96 self.variables.push_context_impl(context);
97 EnvContextGuard { env: self }
98 }
99
100 #[inline]
102 pub fn pop_context(guard: EnvContextGuard<'_>) {
103 drop(guard)
104 }
105}
106
107impl Drop for EnvContextGuard<'_> {
110 #[inline]
111 fn drop(&mut self) {
112 self.env.variables.pop_context_impl()
113 }
114}
115
116impl Deref for EnvContextGuard<'_> {
117 type Target = Env;
118 #[inline]
119 fn deref(&self) -> &Env {
120 self.env
121 }
122}
123
124impl DerefMut for EnvContextGuard<'_> {
125 #[inline]
126 fn deref_mut(&mut self) -> &mut Env {
127 self.env
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::super::Scope;
134 use super::super::Value;
135 use super::*;
136
137 #[test]
138 fn scope_guard() {
139 let mut env = Env::new_virtual();
140 let mut guard = env.variables.push_context(Context::default());
141 guard
142 .get_or_new("foo", Scope::Global)
143 .assign("", None)
144 .unwrap();
145 guard
146 .get_or_new("bar", Scope::Local)
147 .assign("", None)
148 .unwrap();
149 VariableSet::pop_context(guard);
150
151 let variable = env.variables.get("foo").unwrap();
152 assert_eq!(variable.value, Some(Value::scalar("")));
153 assert_eq!(env.variables.get("bar"), None);
154 }
155
156 #[test]
157 fn env_scope_guard() {
158 let mut env = Env::new_virtual();
159 let mut guard = env.push_context(Context::default());
160 guard
161 .variables
162 .get_or_new("foo", Scope::Global)
163 .assign("", None)
164 .unwrap();
165 guard
166 .variables
167 .get_or_new("bar", Scope::Local)
168 .assign("", None)
169 .unwrap();
170 Env::pop_context(guard);
171
172 let variable = env.variables.get("foo").unwrap();
173 assert_eq!(variable.value, Some(Value::scalar("")));
174 assert_eq!(env.variables.get("bar"), None);
175 }
176}