pub struct BlockContext<'reg> { /* private fields */ }
Expand description

A data structure holds contextual data for current block scope.

Implementations§

create a new BlockContext with default data

Examples found in repository?
src/helpers/block_util.rs (line 7)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pub(crate) fn create_block<'reg: 'rc, 'rc>(
    param: &'rc PathAndJson<'reg, 'rc>,
) -> BlockContext<'reg> {
    let mut block = BlockContext::new();

    if let Some(new_path) = param.context_path() {
        *block.base_path_mut() = new_path.clone();
    } else {
        // use clone for now
        block.set_base_value(param.value().clone());
    }

    block
}
More examples
Hide additional examples
src/render.rs (line 69)
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    pub fn new(root_template: Option<&'reg String>) -> RenderContext<'reg, 'rc> {
        let inner = Rc::new(RenderContextInner {
            partials: BTreeMap::new(),
            partial_block_stack: VecDeque::new(),
            partial_block_depth: 0,
            local_helpers: BTreeMap::new(),
            current_template: None,
            root_template,
            disable_escape: false,
            indent_string: None,
        });

        let mut blocks = VecDeque::with_capacity(5);
        blocks.push_front(BlockContext::new());

        let modified_context = None;
        RenderContext {
            inner,
            blocks,
            modified_context,
        }
    }

    pub(crate) fn new_for_block(&self) -> RenderContext<'reg, 'rc> {
        let inner = self.inner.clone();

        let mut blocks = VecDeque::with_capacity(2);
        blocks.push_front(BlockContext::new());

        let modified_context = self.modified_context.clone();

        RenderContext {
            inner,
            blocks,
            modified_context,
        }
    }
src/partial.rs (line 80)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
pub fn expand_partial<'reg: 'rc, 'rc>(
    d: &Decorator<'reg, 'rc>,
    r: &'reg Registry<'reg>,
    ctx: &'rc Context,
    rc: &mut RenderContext<'reg, 'rc>,
    out: &mut dyn Output,
) -> Result<(), RenderError> {
    // try eval inline partials first
    if let Some(t) = d.template() {
        t.eval(r, ctx, rc)?;
    }

    let tname = d.name();
    if rc.is_current_template(tname) {
        return Err(RenderError::new("Cannot include self in >"));
    }

    let partial = find_partial(rc, r, d, tname)?;

    if let Some(t) = partial {
        // clone to avoid lifetime issue
        // FIXME refactor this to avoid
        let mut local_rc = rc.clone();

        // if tname == PARTIAL_BLOCK
        let is_partial_block = tname == PARTIAL_BLOCK;

        // add partial block depth there are consecutive partial
        // blocks in the stack.
        if is_partial_block {
            local_rc.inc_partial_block_depth();
        } else {
            // depth cannot be lower than 0, which is guaranted in the
            // `dec_partial_block_depth` method
            local_rc.dec_partial_block_depth();
        }

        let mut block_created = false;

        // create context if param given
        if let Some(base_path) = d.param(0).and_then(|p| p.context_path()) {
            // path given, update base_path
            let mut block_inner = BlockContext::new();
            *block_inner.base_path_mut() = base_path.to_vec();

            // because block is moved here, we need another bool variable to track
            // its status for later cleanup
            block_created = true;
            // clear blocks to prevent block params from parent
            // template to be leaked into partials
            // see `test_partial_context_issue_495` for the case.
            local_rc.clear_blocks();
            local_rc.push_block(block_inner);
        }

        if !d.hash().is_empty() {
            // hash given, update base_value
            let hash_ctx = d
                .hash()
                .iter()
                .map(|(k, v)| (*k, v.value()))
                .collect::<HashMap<&str, &Json>>();

            // create block if we didn't (no param provided for partial expression)
            if !block_created {
                let block_inner = if let Some(block) = local_rc.block() {
                    // reuse current block information, including base_path and
                    // base_value if any
                    block.clone()
                } else {
                    BlockContext::new()
                };

                local_rc.clear_blocks();
                local_rc.push_block(block_inner);
            }

            // evaluate context within current block, this includes block
            // context provided by partial expression parameter
            let merged_context = merge_json(
                local_rc.evaluate2(ctx, &Path::current())?.as_json(),
                &hash_ctx,
            );

            // update the base value, there must be a block for this so it's
            // also safe to unwrap.
            if let Some(block) = local_rc.block_mut() {
                block.set_base_value(merged_context);
            }
        }

        // @partial-block
        if let Some(pb) = d.template() {
            local_rc.push_partial_block(pb);
        }

        // indent
        local_rc.set_indent_string(d.indent());

        let result = t.render(r, ctx, &mut local_rc, out);

        // cleanup
        if block_created {
            local_rc.pop_block();
        }

        if d.template().is_some() {
            local_rc.pop_partial_block();
        }

        result
    } else {
        Ok(())
    }
}

set a local variable into current scope

Examples found in repository?
src/helpers/helper_each.rs (line 99)
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
    fn call<'reg: 'rc, 'rc>(
        &self,
        h: &Helper<'reg, 'rc>,
        r: &'reg Registry<'reg>,
        ctx: &'rc Context,
        rc: &mut RenderContext<'reg, 'rc>,
        out: &mut dyn Output,
    ) -> HelperResult {
        let value = h
            .param(0)
            .ok_or_else(|| RenderError::new("Param not found for helper \"each\""))?;

        let template = h.template();

        match template {
            Some(t) => match *value.value() {
                Json::Array(ref list)
                    if !list.is_empty() || (list.is_empty() && h.inverse().is_none()) =>
                {
                    let block_context = create_block(value);
                    rc.push_block(block_context);

                    let len = list.len();

                    let array_path = value.context_path();

                    for (i, v) in list.iter().enumerate().take(len) {
                        if let Some(ref mut block) = rc.block_mut() {
                            let is_first = i == 0usize;
                            let is_last = i == len - 1;

                            let index = to_json(i);
                            block.set_local_var("first", to_json(is_first));
                            block.set_local_var("last", to_json(is_last));
                            block.set_local_var("index", index.clone());

                            update_block_context(block, array_path, i.to_string(), is_first, v);
                            set_block_param(block, h, array_path, &index, v)?;
                        }

                        t.render(r, ctx, rc, out)?;
                    }

                    rc.pop_block();
                    Ok(())
                }
                Json::Object(ref obj)
                    if !obj.is_empty() || (obj.is_empty() && h.inverse().is_none()) =>
                {
                    let block_context = create_block(value);
                    rc.push_block(block_context);

                    let len = obj.len();

                    let obj_path = value.context_path();

                    for (i, (k, v)) in obj.iter().enumerate() {
                        if let Some(ref mut block) = rc.block_mut() {
                            let is_first = i == 0usize;
                            let is_last = i == len - 1;

                            let key = to_json(k);
                            block.set_local_var("first", to_json(is_first));
                            block.set_local_var("last", to_json(is_last));
                            block.set_local_var("key", key.clone());

                            update_block_context(block, obj_path, k.to_string(), is_first, v);
                            set_block_param(block, h, obj_path, &key, v)?;
                        }

                        t.render(r, ctx, rc, out)?;
                    }

                    rc.pop_block();
                    Ok(())
                }
                _ => {
                    if let Some(else_template) = h.inverse() {
                        else_template.render(r, ctx, rc, out)
                    } else if r.strict_mode() {
                        Err(RenderError::strict_error(value.relative_path()))
                    } else {
                        Ok(())
                    }
                }
            },
            None => Ok(()),
        }
    }

get a local variable from current scope

Examples found in repository?
src/render.rs (line 222)
219
220
221
222
223
    fn get_local_var(&self, level: usize, name: &str) -> Option<&Json> {
        self.blocks
            .get(level)
            .and_then(|blk| blk.get_local_var(name))
    }

borrow a reference to current scope’s base path all paths inside this block will be relative to this path

Examples found in repository?
src/context.rs (line 89)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn parse_json_visitor<'a, 'reg>(
    relative_path: &[PathSeg],
    block_contexts: &'a VecDeque<BlockContext<'reg>>,
    always_for_absolute_path: bool,
) -> ResolvedPath<'a> {
    let mut path_context_depth: i64 = 0;
    let mut with_block_param = None;
    let mut from_root = false;

    // peek relative_path for block param, @root and  "../../"
    for path_seg in relative_path {
        match path_seg {
            PathSeg::Named(the_path) => {
                if let Some((holder, base_path)) = get_in_block_params(block_contexts, the_path) {
                    with_block_param = Some((holder, base_path));
                }
                break;
            }
            PathSeg::Ruled(the_rule) => match the_rule {
                Rule::path_root => {
                    from_root = true;
                    break;
                }
                Rule::path_up => path_context_depth += 1,
                _ => break,
            },
        }
    }

    let mut path_stack = Vec::with_capacity(relative_path.len() + 5);
    match with_block_param {
        Some((BlockParamHolder::Value(ref value), _)) => {
            merge_json_path(&mut path_stack, &relative_path[1..]);
            ResolvedPath::BlockParamValue(path_stack, value)
        }
        Some((BlockParamHolder::Path(ref paths), base_path)) => {
            extend(&mut path_stack, base_path);
            if !paths.is_empty() {
                extend(&mut path_stack, paths);
            }
            merge_json_path(&mut path_stack, &relative_path[1..]);

            ResolvedPath::AbsolutePath(path_stack)
        }
        None => {
            if path_context_depth > 0 {
                let blk = block_contexts
                    .get(path_context_depth as usize)
                    .or_else(|| block_contexts.front());

                if let Some(base_value) = blk.and_then(|blk| blk.base_value()) {
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::LocalValue(path_stack, base_value)
                } else {
                    if let Some(base_path) = blk.map(|blk| blk.base_path()) {
                        extend(&mut path_stack, base_path);
                    }
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::AbsolutePath(path_stack)
                }
            } else if from_root {
                merge_json_path(&mut path_stack, relative_path);
                ResolvedPath::AbsolutePath(path_stack)
            } else if always_for_absolute_path {
                if let Some(base_value) = block_contexts.front().and_then(|blk| blk.base_value()) {
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::LocalValue(path_stack, base_value)
                } else {
                    if let Some(base_path) = block_contexts.front().map(|blk| blk.base_path()) {
                        extend(&mut path_stack, base_path);
                    }
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::AbsolutePath(path_stack)
                }
            } else {
                merge_json_path(&mut path_stack, relative_path);
                ResolvedPath::RelativePath(path_stack)
            }
        }
    }
}

fn get_data<'a>(d: Option<&'a Json>, p: &str) -> Result<Option<&'a Json>, RenderError> {
    let result = match d {
        Some(&Json::Array(ref l)) => p.parse::<usize>().map(|idx_u| l.get(idx_u))?,
        Some(&Json::Object(ref m)) => m.get(p),
        Some(_) => None,
        None => None,
    };
    Ok(result)
}

fn get_in_block_params<'a, 'reg>(
    block_contexts: &'a VecDeque<BlockContext<'reg>>,
    p: &str,
) -> Option<(&'a BlockParamHolder, &'a Vec<String>)> {
    for bc in block_contexts {
        let v = bc.get_block_param(p);
        if v.is_some() {
            return v.map(|v| (v, bc.base_path()));
        }
    }

    None
}

borrow a mutable reference to the base path

Examples found in repository?
src/helpers/block_util.rs (line 10)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pub(crate) fn create_block<'reg: 'rc, 'rc>(
    param: &'rc PathAndJson<'reg, 'rc>,
) -> BlockContext<'reg> {
    let mut block = BlockContext::new();

    if let Some(new_path) = param.context_path() {
        *block.base_path_mut() = new_path.clone();
    } else {
        // use clone for now
        block.set_base_value(param.value().clone());
    }

    block
}
More examples
Hide additional examples
src/helpers/helper_each.rs (line 23)
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
fn update_block_context<'reg>(
    block: &mut BlockContext<'reg>,
    base_path: Option<&Vec<String>>,
    relative_path: String,
    is_first: bool,
    value: &Json,
) {
    if let Some(p) = base_path {
        if is_first {
            *block.base_path_mut() = copy_on_push_vec(p, relative_path);
        } else if let Some(ptr) = block.base_path_mut().last_mut() {
            *ptr = relative_path;
        }
    } else {
        block.set_base_value(value.clone());
    }
}
src/partial.rs (line 81)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
pub fn expand_partial<'reg: 'rc, 'rc>(
    d: &Decorator<'reg, 'rc>,
    r: &'reg Registry<'reg>,
    ctx: &'rc Context,
    rc: &mut RenderContext<'reg, 'rc>,
    out: &mut dyn Output,
) -> Result<(), RenderError> {
    // try eval inline partials first
    if let Some(t) = d.template() {
        t.eval(r, ctx, rc)?;
    }

    let tname = d.name();
    if rc.is_current_template(tname) {
        return Err(RenderError::new("Cannot include self in >"));
    }

    let partial = find_partial(rc, r, d, tname)?;

    if let Some(t) = partial {
        // clone to avoid lifetime issue
        // FIXME refactor this to avoid
        let mut local_rc = rc.clone();

        // if tname == PARTIAL_BLOCK
        let is_partial_block = tname == PARTIAL_BLOCK;

        // add partial block depth there are consecutive partial
        // blocks in the stack.
        if is_partial_block {
            local_rc.inc_partial_block_depth();
        } else {
            // depth cannot be lower than 0, which is guaranted in the
            // `dec_partial_block_depth` method
            local_rc.dec_partial_block_depth();
        }

        let mut block_created = false;

        // create context if param given
        if let Some(base_path) = d.param(0).and_then(|p| p.context_path()) {
            // path given, update base_path
            let mut block_inner = BlockContext::new();
            *block_inner.base_path_mut() = base_path.to_vec();

            // because block is moved here, we need another bool variable to track
            // its status for later cleanup
            block_created = true;
            // clear blocks to prevent block params from parent
            // template to be leaked into partials
            // see `test_partial_context_issue_495` for the case.
            local_rc.clear_blocks();
            local_rc.push_block(block_inner);
        }

        if !d.hash().is_empty() {
            // hash given, update base_value
            let hash_ctx = d
                .hash()
                .iter()
                .map(|(k, v)| (*k, v.value()))
                .collect::<HashMap<&str, &Json>>();

            // create block if we didn't (no param provided for partial expression)
            if !block_created {
                let block_inner = if let Some(block) = local_rc.block() {
                    // reuse current block information, including base_path and
                    // base_value if any
                    block.clone()
                } else {
                    BlockContext::new()
                };

                local_rc.clear_blocks();
                local_rc.push_block(block_inner);
            }

            // evaluate context within current block, this includes block
            // context provided by partial expression parameter
            let merged_context = merge_json(
                local_rc.evaluate2(ctx, &Path::current())?.as_json(),
                &hash_ctx,
            );

            // update the base value, there must be a block for this so it's
            // also safe to unwrap.
            if let Some(block) = local_rc.block_mut() {
                block.set_base_value(merged_context);
            }
        }

        // @partial-block
        if let Some(pb) = d.template() {
            local_rc.push_partial_block(pb);
        }

        // indent
        local_rc.set_indent_string(d.indent());

        let result = t.render(r, ctx, &mut local_rc, out);

        // cleanup
        if block_created {
            local_rc.pop_block();
        }

        if d.template().is_some() {
            local_rc.pop_partial_block();
        }

        result
    } else {
        Ok(())
    }
}

borrow the base value

Examples found in repository?
src/context.rs (line 85)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
fn parse_json_visitor<'a, 'reg>(
    relative_path: &[PathSeg],
    block_contexts: &'a VecDeque<BlockContext<'reg>>,
    always_for_absolute_path: bool,
) -> ResolvedPath<'a> {
    let mut path_context_depth: i64 = 0;
    let mut with_block_param = None;
    let mut from_root = false;

    // peek relative_path for block param, @root and  "../../"
    for path_seg in relative_path {
        match path_seg {
            PathSeg::Named(the_path) => {
                if let Some((holder, base_path)) = get_in_block_params(block_contexts, the_path) {
                    with_block_param = Some((holder, base_path));
                }
                break;
            }
            PathSeg::Ruled(the_rule) => match the_rule {
                Rule::path_root => {
                    from_root = true;
                    break;
                }
                Rule::path_up => path_context_depth += 1,
                _ => break,
            },
        }
    }

    let mut path_stack = Vec::with_capacity(relative_path.len() + 5);
    match with_block_param {
        Some((BlockParamHolder::Value(ref value), _)) => {
            merge_json_path(&mut path_stack, &relative_path[1..]);
            ResolvedPath::BlockParamValue(path_stack, value)
        }
        Some((BlockParamHolder::Path(ref paths), base_path)) => {
            extend(&mut path_stack, base_path);
            if !paths.is_empty() {
                extend(&mut path_stack, paths);
            }
            merge_json_path(&mut path_stack, &relative_path[1..]);

            ResolvedPath::AbsolutePath(path_stack)
        }
        None => {
            if path_context_depth > 0 {
                let blk = block_contexts
                    .get(path_context_depth as usize)
                    .or_else(|| block_contexts.front());

                if let Some(base_value) = blk.and_then(|blk| blk.base_value()) {
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::LocalValue(path_stack, base_value)
                } else {
                    if let Some(base_path) = blk.map(|blk| blk.base_path()) {
                        extend(&mut path_stack, base_path);
                    }
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::AbsolutePath(path_stack)
                }
            } else if from_root {
                merge_json_path(&mut path_stack, relative_path);
                ResolvedPath::AbsolutePath(path_stack)
            } else if always_for_absolute_path {
                if let Some(base_value) = block_contexts.front().and_then(|blk| blk.base_value()) {
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::LocalValue(path_stack, base_value)
                } else {
                    if let Some(base_path) = block_contexts.front().map(|blk| blk.base_path()) {
                        extend(&mut path_stack, base_path);
                    }
                    merge_json_path(&mut path_stack, relative_path);
                    ResolvedPath::AbsolutePath(path_stack)
                }
            } else {
                merge_json_path(&mut path_stack, relative_path);
                ResolvedPath::RelativePath(path_stack)
            }
        }
    }
}

set the base value

Examples found in repository?
src/helpers/block_util.rs (line 13)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pub(crate) fn create_block<'reg: 'rc, 'rc>(
    param: &'rc PathAndJson<'reg, 'rc>,
) -> BlockContext<'reg> {
    let mut block = BlockContext::new();

    if let Some(new_path) = param.context_path() {
        *block.base_path_mut() = new_path.clone();
    } else {
        // use clone for now
        block.set_base_value(param.value().clone());
    }

    block
}
More examples
Hide additional examples
src/helpers/helper_each.rs (line 28)
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
fn update_block_context<'reg>(
    block: &mut BlockContext<'reg>,
    base_path: Option<&Vec<String>>,
    relative_path: String,
    is_first: bool,
    value: &Json,
) {
    if let Some(p) = base_path {
        if is_first {
            *block.base_path_mut() = copy_on_push_vec(p, relative_path);
        } else if let Some(ptr) = block.base_path_mut().last_mut() {
            *ptr = relative_path;
        }
    } else {
        block.set_base_value(value.clone());
    }
}
src/partial.rs (line 125)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
pub fn expand_partial<'reg: 'rc, 'rc>(
    d: &Decorator<'reg, 'rc>,
    r: &'reg Registry<'reg>,
    ctx: &'rc Context,
    rc: &mut RenderContext<'reg, 'rc>,
    out: &mut dyn Output,
) -> Result<(), RenderError> {
    // try eval inline partials first
    if let Some(t) = d.template() {
        t.eval(r, ctx, rc)?;
    }

    let tname = d.name();
    if rc.is_current_template(tname) {
        return Err(RenderError::new("Cannot include self in >"));
    }

    let partial = find_partial(rc, r, d, tname)?;

    if let Some(t) = partial {
        // clone to avoid lifetime issue
        // FIXME refactor this to avoid
        let mut local_rc = rc.clone();

        // if tname == PARTIAL_BLOCK
        let is_partial_block = tname == PARTIAL_BLOCK;

        // add partial block depth there are consecutive partial
        // blocks in the stack.
        if is_partial_block {
            local_rc.inc_partial_block_depth();
        } else {
            // depth cannot be lower than 0, which is guaranted in the
            // `dec_partial_block_depth` method
            local_rc.dec_partial_block_depth();
        }

        let mut block_created = false;

        // create context if param given
        if let Some(base_path) = d.param(0).and_then(|p| p.context_path()) {
            // path given, update base_path
            let mut block_inner = BlockContext::new();
            *block_inner.base_path_mut() = base_path.to_vec();

            // because block is moved here, we need another bool variable to track
            // its status for later cleanup
            block_created = true;
            // clear blocks to prevent block params from parent
            // template to be leaked into partials
            // see `test_partial_context_issue_495` for the case.
            local_rc.clear_blocks();
            local_rc.push_block(block_inner);
        }

        if !d.hash().is_empty() {
            // hash given, update base_value
            let hash_ctx = d
                .hash()
                .iter()
                .map(|(k, v)| (*k, v.value()))
                .collect::<HashMap<&str, &Json>>();

            // create block if we didn't (no param provided for partial expression)
            if !block_created {
                let block_inner = if let Some(block) = local_rc.block() {
                    // reuse current block information, including base_path and
                    // base_value if any
                    block.clone()
                } else {
                    BlockContext::new()
                };

                local_rc.clear_blocks();
                local_rc.push_block(block_inner);
            }

            // evaluate context within current block, this includes block
            // context provided by partial expression parameter
            let merged_context = merge_json(
                local_rc.evaluate2(ctx, &Path::current())?.as_json(),
                &hash_ctx,
            );

            // update the base value, there must be a block for this so it's
            // also safe to unwrap.
            if let Some(block) = local_rc.block_mut() {
                block.set_base_value(merged_context);
            }
        }

        // @partial-block
        if let Some(pb) = d.template() {
            local_rc.push_partial_block(pb);
        }

        // indent
        local_rc.set_indent_string(d.indent());

        let result = t.render(r, ctx, &mut local_rc, out);

        // cleanup
        if block_created {
            local_rc.pop_block();
        }

        if d.template().is_some() {
            local_rc.pop_partial_block();
        }

        result
    } else {
        Ok(())
    }
}

Get a block parameter from this block. Block parameters needed to be supported by the block helper. The typical syntax for block parameter is:

{{#myblock param1 as |block_param1|}}
   ...
{{/myblock}}
Examples found in repository?
src/context.rs (line 132)
127
128
129
130
131
132
133
134
135
136
137
138
139
fn get_in_block_params<'a, 'reg>(
    block_contexts: &'a VecDeque<BlockContext<'reg>>,
    p: &str,
) -> Option<(&'a BlockParamHolder, &'a Vec<String>)> {
    for bc in block_contexts {
        let v = bc.get_block_param(p);
        if v.is_some() {
            return v.map(|v| (v, bc.base_path()));
        }
    }

    None
}

Set a block parameter into this block.

Examples found in repository?
src/helpers/helper_each.rs (line 47)
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
fn set_block_param<'reg: 'rc, 'rc>(
    block: &mut BlockContext<'reg>,
    h: &Helper<'reg, 'rc>,
    base_path: Option<&Vec<String>>,
    k: &Json,
    v: &Json,
) -> Result<(), RenderError> {
    if let Some(bp_val) = h.block_param() {
        let mut params = BlockParams::new();
        if base_path.is_some() {
            params.add_path(bp_val, Vec::with_capacity(0))?;
        } else {
            params.add_value(bp_val, v.clone())?;
        }

        block.set_block_params(params);
    } else if let Some((bp_val, bp_key)) = h.block_param_pair() {
        let mut params = BlockParams::new();
        if base_path.is_some() {
            params.add_path(bp_val, Vec::with_capacity(0))?;
        } else {
            params.add_value(bp_val, v.clone())?;
        }
        params.add_value(bp_key, k.clone())?;

        block.set_block_params(params);
    }

    Ok(())
}
More examples
Hide additional examples
src/helpers/helper_with.rs (line 38)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    fn call<'reg: 'rc, 'rc>(
        &self,
        h: &Helper<'reg, 'rc>,
        r: &'reg Registry<'reg>,
        ctx: &'rc Context,
        rc: &mut RenderContext<'reg, 'rc>,
        out: &mut dyn Output,
    ) -> HelperResult {
        let param = h
            .param(0)
            .ok_or_else(|| RenderError::new("Param not found for helper \"with\""))?;

        if param.value().is_truthy(false) {
            let mut block = create_block(param);

            if let Some(block_param) = h.block_param() {
                let mut params = BlockParams::new();
                if param.context_path().is_some() {
                    params.add_path(block_param, Vec::with_capacity(0))?;
                } else {
                    params.add_value(block_param, param.value().clone())?;
                }

                block.set_block_params(params);
            }

            rc.push_block(block);

            if let Some(t) = h.template() {
                t.render(r, ctx, rc, out)?;
            };

            rc.pop_block();
            Ok(())
        } else if let Some(t) = h.inverse() {
            t.render(r, ctx, rc, out)
        } else if r.strict_mode() {
            Err(RenderError::strict_error(param.relative_path()))
        } else {
            Ok(())
        }
    }

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Should always be Self
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.