minijinja/vm/
closure_object.rsuse std::collections::BTreeMap;
use std::sync::{Arc, Mutex};
use crate::value::{Enumerator, Object, Value};
#[derive(Default)]
pub(crate) struct ClosureTracker {
closures: Mutex<Vec<Arc<Closure>>>,
}
impl ClosureTracker {
pub(crate) fn track_closure(&self, closure: Arc<Closure>) {
self.closures.lock().unwrap().push(closure);
}
}
impl Drop for ClosureTracker {
fn drop(&mut self) {
for closure in self.closures.lock().unwrap().iter() {
closure.clear();
}
}
}
#[derive(Debug, Default)]
pub(crate) struct Closure {
values: Mutex<BTreeMap<Arc<str>, Value>>,
}
impl Closure {
pub fn store(&self, key: &str, value: Value) {
self.values.lock().unwrap().insert(Arc::from(key), value);
}
#[cfg(feature = "macros")]
pub fn store_if_missing<F: FnOnce() -> Value>(&self, key: &str, f: F) {
let mut values = self.values.lock().unwrap();
if !values.contains_key(key) {
values.insert(Arc::from(key), f());
}
}
pub fn clear(&self) {
self.values.lock().unwrap().clear();
}
}
impl Object for Closure {
fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
self.values.lock().unwrap().get(key.as_str()?).cloned()
}
fn enumerate(self: &Arc<Self>) -> Enumerator {
let values = self.values.lock().unwrap();
let keys = values.keys().cloned().map(Value::from);
Enumerator::Values(keys.collect())
}
}