minijinja/vm/
closure_object.rs1use std::collections::BTreeMap;
2use std::sync::{Arc, Mutex};
3
4use crate::value::{Enumerator, Object, Value};
5
6#[derive(Default)]
12pub(crate) struct ClosureTracker {
13 closures: Mutex<Vec<Arc<Closure>>>,
14}
15
16impl ClosureTracker {
17 pub(crate) fn track_closure(&self, closure: Arc<Closure>) {
20 self.closures.lock().unwrap().push(closure);
21 }
22}
23
24impl Drop for ClosureTracker {
25 fn drop(&mut self) {
26 for closure in self.closures.lock().unwrap().iter() {
27 closure.clear();
28 }
29 }
30}
31
32#[derive(Debug, Default)]
36pub(crate) struct Closure {
37 values: Mutex<BTreeMap<Arc<str>, Value>>,
38}
39
40impl Closure {
41 pub fn store(&self, key: &str, value: Value) {
43 self.values.lock().unwrap().insert(Arc::from(key), value);
44 }
45
46 #[cfg(feature = "macros")]
48 pub fn store_if_missing<F: FnOnce() -> Value>(&self, key: &str, f: F) {
49 let mut values = self.values.lock().unwrap();
50 if !values.contains_key(key) {
51 values.insert(Arc::from(key), f());
52 }
53 }
54
55 pub fn clear(&self) {
59 self.values.lock().unwrap().clear();
60 }
61}
62
63impl Object for Closure {
64 fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
65 self.values.lock().unwrap().get(key.as_str()?).cloned()
66 }
67
68 fn enumerate(self: &Arc<Self>) -> Enumerator {
69 let values = self.values.lock().unwrap();
70 let keys = values.keys().cloned().map(Value::from);
71 Enumerator::Values(keys.collect())
72 }
73}