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 { value(v: Json) -> BlockParamHolder17 pub fn value(v: Json) -> BlockParamHolder { 18 BlockParamHolder::Value(v) 19 } 20 path(r: Vec<String>) -> BlockParamHolder21 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. new() -> BlockParams<'reg>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. add_path(&mut self, k: &'reg str, path: Vec<String>) -> Result<(), RenderError>40 pub fn add_path(&mut self, k: &'reg str, path: Vec<String>) -> Result<(), RenderError> { 41 self.data.insert(k, BlockParamHolder::path(path)); 42 Ok(()) 43 } 44 45 /// Add a value as parameter. add_value(&mut self, k: &'reg str, v: Json) -> Result<(), RenderError>46 pub fn add_value(&mut self, k: &'reg str, v: Json) -> Result<(), RenderError> { 47 self.data.insert(k, BlockParamHolder::value(v)); 48 Ok(()) 49 } 50 51 /// Get a block parameter by its name. get(&self, k: &str) -> Option<&BlockParamHolder>52 pub fn get(&self, k: &str) -> Option<&BlockParamHolder> { 53 self.data.get(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 new() -> BlockContext<'reg>73 pub fn new() -> BlockContext<'reg> { 74 BlockContext::default() 75 } 76 77 /// set a local variable into current scope set_local_var(&mut self, name: &str, value: Json)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 get_local_var(&self, name: &str) -> Option<&Json>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 base_path(&self) -> &Vec<String>89 pub fn base_path(&self) -> &Vec<String> { 90 &self.base_path 91 } 92 93 /// borrow a mutable reference to the base path base_path_mut(&mut self) -> &mut Vec<String>94 pub fn base_path_mut(&mut self) -> &mut Vec<String> { 95 &mut self.base_path 96 } 97 98 /// borrow the base value base_value(&self) -> Option<&Json>99 pub fn base_value(&self) -> Option<&Json> { 100 self.base_value.as_ref() 101 } 102 103 /// set the base value set_base_value(&mut self, value: Json)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 /// get_block_param(&self, block_param_name: &str) -> Option<&BlockParamHolder>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. set_block_params(&mut self, block_params: BlockParams<'reg>)123 pub fn set_block_params(&mut self, block_params: BlockParams<'reg>) { 124 self.block_params = block_params; 125 } 126 } 127