1use std::collections::BTreeMap;
2
3use serde_json::value::Value as Json;
4
5use crate::error::RenderError;
6use crate::local_vars::LocalVars;
7
8#[derive(Clone, Debug)]
9pub enum BlockParamHolder {
10 // a reference to certain context value
11 Path(Vec<String>),
12 // an actual value holder
13 Value(Json),
14}
15
16impl BlockParamHolder {
17 pub fn value(v: Json) -> BlockParamHolder {
18 BlockParamHolder::Value(v)
19 }
20
21 pub fn path(r: Vec<String>) -> BlockParamHolder {
22 BlockParamHolder::Path(r)
23 }
24}
25
26/// A map holds block parameters. The parameter can be either a value or a reference
27#[derive(Clone, Debug, Default)]
28pub struct BlockParams<'reg> {
29 data: BTreeMap<&'reg str, BlockParamHolder>,
30}
31
32impl<'reg> BlockParams<'reg> {
33 /// Create a empty block parameter map.
34 pub fn new() -> BlockParams<'reg> {
35 BlockParams::default()
36 }
37
38 /// Add a path reference as the parameter. The `path` is a vector of path
39 /// segments the relative to current block's base path.
40 pub fn add_path(&mut self, k: &'reg str, path: Vec<String>) -> Result<(), RenderError> {
41 self.data.insert(key:k, value:BlockParamHolder::path(path));
42 Ok(())
43 }
44
45 /// Add a value as parameter.
46 pub fn add_value(&mut self, k: &'reg str, v: Json) -> Result<(), RenderError> {
47 self.data.insert(key:k, BlockParamHolder::value(v));
48 Ok(())
49 }
50
51 /// Get a block parameter by its name.
52 pub fn get(&self, k: &str) -> Option<&BlockParamHolder> {
53 self.data.get(key:k)
54 }
55}
56
57/// A data structure holds contextual data for current block scope.
58#[derive(Debug, Clone, Default)]
59pub struct BlockContext<'reg> {
60 /// the base_path of current block scope
61 base_path: Vec<String>,
62 /// the base_value of current block scope, when the block is using a
63 /// constant or derived value as block base
64 base_value: Option<Json>,
65 /// current block context variables
66 block_params: BlockParams<'reg>,
67 /// local variables in current context
68 local_variables: LocalVars,
69}
70
71impl<'reg> BlockContext<'reg> {
72 /// create a new `BlockContext` with default data
73 pub fn new() -> BlockContext<'reg> {
74 BlockContext::default()
75 }
76
77 /// set a local variable into current scope
78 pub fn set_local_var(&mut self, name: &str, value: Json) {
79 self.local_variables.put(name, value);
80 }
81
82 /// get a local variable from current scope
83 pub fn get_local_var(&self, name: &str) -> Option<&Json> {
84 self.local_variables.get(name)
85 }
86
87 /// borrow a reference to current scope's base path
88 /// all paths inside this block will be relative to this path
89 pub fn base_path(&self) -> &Vec<String> {
90 &self.base_path
91 }
92
93 /// borrow a mutable reference to the base path
94 pub fn base_path_mut(&mut self) -> &mut Vec<String> {
95 &mut self.base_path
96 }
97
98 /// borrow the base value
99 pub fn base_value(&self) -> Option<&Json> {
100 self.base_value.as_ref()
101 }
102
103 /// set the base value
104 pub fn set_base_value(&mut self, value: Json) {
105 self.base_value = Some(value);
106 }
107
108 /// Get a block parameter from this block.
109 /// Block parameters needed to be supported by the block helper.
110 /// The typical syntax for block parameter is:
111 ///
112 /// ```skip
113 /// {{#myblock param1 as |block_param1|}}
114 /// ...
115 /// {{/myblock}}
116 /// ```
117 ///
118 pub fn get_block_param(&self, block_param_name: &str) -> Option<&BlockParamHolder> {
119 self.block_params.get(block_param_name)
120 }
121
122 /// Set a block parameter into this block.
123 pub fn set_block_params(&mut self, block_params: BlockParams<'reg>) {
124 self.block_params = block_params;
125 }
126}
127