bracket/render/scope.rs
1//! Scopes define the evaluation context for variable paths.
2use serde_json::{Map, Value};
3
4/// A scope encapsulates a base value (lookup object) used when
5/// resolving variable paths and a collection of local variables
6/// which are prefixed using the `@` symbol.
7///
8/// Helpers can create scopes and push and pop them from the scope
9/// stack to create new variable evaluation contexts.
10#[derive(Debug, Clone)]
11pub struct Scope {
12 value: Option<Value>,
13 locals: Value,
14}
15
16impl Scope {
17 /// Create a new scope.
18 pub fn new() -> Self {
19 Self {
20 locals: Value::Object(Map::new()),
21 value: None,
22 }
23 }
24
25 /// Get the underlying locals value.
26 pub fn locals(&self) -> &Value {
27 &self.locals
28 }
29
30 /// Set a named local variable.
31 ///
32 /// The name does not need an `@` prefix it is automatically
33 /// prepended to the key.
34 pub fn set_local(&mut self, name: &str, value: Value) {
35 self.locals
36 .as_object_mut()
37 .unwrap()
38 .insert(format!("@{}", name), value);
39 }
40
41 /// Get a named local.
42 ///
43 /// Locals should have the `@` prefix.
44 pub fn local(&self, name: &str) -> Option<&Value> {
45 self.locals.as_object().unwrap().get(name)
46 }
47
48 /// Set the base value for the scope.
49 ///
50 /// When the renderer resolves variables if they
51 /// can be resolved using this value they are preferred
52 /// over the root object.
53 pub fn set_base_value(&mut self, value: Value) {
54 self.value = Some(value);
55 }
56
57 /// Get the base value for this scope.
58 pub fn base_value(&self) -> &Option<Value> {
59 &self.value
60 }
61}
62
63/// Create a scope from hash parameters.
64impl From<Map<String, Value>> for Scope {
65 fn from(map: Map<String, Value>) -> Self {
66 let mut scope = Scope::new();
67 scope.value = Some(Value::Object(map));
68 scope
69 }
70}
71
72/// Create a scope from a context and hash parameters.
73impl From<(Value, Map<String, Value>)> for Scope {
74 fn from(value: (Value, Map<String, Value>)) -> Self {
75 let mut scope = Scope::new();
76 scope.value = Some(value.0);
77 scope.locals = Value::Object(value.1);
78 scope
79 }
80}