/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 | } |