1 | use std::collections::BTreeMap; |
2 | |
3 | use serde_json::value::Value as Json; |
4 | |
5 | use crate::error::RenderError; |
6 | use crate::local_vars::LocalVars; |
7 | |
8 | #[derive (Clone, Debug)] |
9 | pub enum BlockParamHolder { |
10 | // a reference to certain context value |
11 | Path(Vec<String>), |
12 | // an actual value holder |
13 | Value(Json), |
14 | } |
15 | |
16 | impl 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)] |
28 | pub struct BlockParams<'reg> { |
29 | data: BTreeMap<&'reg str, BlockParamHolder>, |
30 | } |
31 | |
32 | impl<'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)] |
59 | pub 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 | |
71 | impl<'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 | |