Coverage Report

Created: 2026-03-28 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tinytemplate-1.2.1/src/instruction.rs
Line
Count
Source
1
use std::ops::Deref;
2
3
/// TinyTemplate implements a simple bytecode interpreter for its template engine. Instructions
4
/// for this interpreter are represented by the Instruction enum and typically contain various
5
/// parameters such as the path to context values or name strings.
6
///
7
/// In TinyTemplate, the template string itself is assumed to be statically available (or at least
8
/// longer-lived than the TinyTemplate instance) so paths and instructions simply borrow string
9
/// slices from the template text. These string slices can then be appended directly to the output
10
/// string.
11
12
/// Enum for a step in a path which optionally contains a parsed index.
13
#[derive(Eq, PartialEq, Debug, Clone)]
14
pub(crate) enum PathStep<'template> {
15
    Name(&'template str),
16
    Index(&'template str, usize),
17
}
18
impl<'template> Deref for PathStep<'template> {
19
    type Target = str;
20
21
0
    fn deref(&self) -> &Self::Target {
22
0
        match self {
23
0
            PathStep::Name(s) => s,
24
0
            PathStep::Index(s, _) => s,
25
        }
26
0
    }
27
}
28
29
/// Sequence of named steps used for looking up values in the context
30
pub(crate) type Path<'template> = Vec<PathStep<'template>>;
31
32
/// Path, but as a slice.
33
pub(crate) type PathSlice<'a, 'template> = &'a [PathStep<'template>];
34
35
/// Enum representing the bytecode instructions.
36
#[derive(Eq, PartialEq, Debug, Clone)]
37
pub(crate) enum Instruction<'template> {
38
    /// Emit a literal string into the output buffer
39
    Literal(&'template str),
40
41
    /// Look up the value for the given path and render it into the output buffer using the default
42
    /// formatter
43
    Value(Path<'template>),
44
45
    /// Look up the value for the given path and pass it to the formatter with the given name
46
    FormattedValue(Path<'template>, &'template str),
47
48
    /// Look up the value at the given path and jump to the given instruction index if that value
49
    /// is truthy (if the boolean is true) or falsy (if the boolean is false)
50
    Branch(Path<'template>, bool, usize),
51
52
    /// Push a named context on the stack, shadowing only that name.
53
    PushNamedContext(Path<'template>, &'template str),
54
55
    /// Push an iteration context on the stack, shadowing the given name with the current value from
56
    /// the vec pointed to by the path. The current value will be updated by the Iterate instruction.
57
    /// This is always generated before an Iterate instruction which actually starts the iterator.
58
    PushIterationContext(Path<'template>, &'template str),
59
60
    /// Pop a context off the stack
61
    PopContext,
62
63
    /// Advance the topmost iterator on the context stack by one and update that context. If the
64
    /// iterator is empty, jump to the given instruction.
65
    Iterate(usize),
66
67
    /// Unconditionally jump to the given instruction. Used to skip else blocks and repeat loops.
68
    Goto(usize),
69
70
    /// Look up the named template and render it into the output buffer with the value pointed to
71
    /// by the path as its context.
72
    Call(&'template str, Path<'template>),
73
}
74
75
/// Convert a path back into a dotted string.
76
0
pub(crate) fn path_to_str(path: PathSlice) -> String {
77
0
    let mut path_str = "".to_string();
78
0
    for (i, step) in path.iter().enumerate() {
79
0
        if i > 0 {
80
0
            path_str.push('.');
81
0
        }
82
0
        path_str.push_str(step);
83
    }
84
0
    path_str
85
0
}