1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
use std::path::PathBuf;
use std::collections::HashMap;
use crate::evaluator::{Function, Context};
use crate::template::Template;
use crate::evaluator::engine::SimpleEvaluationEngine;
use crate::compiler::{TemplateCompiler, Compiler, CompilationError};
use std::error::Error;
pub mod template;
pub mod evaluator;
pub mod compiler;
pub mod functions;
pub fn compile_template_from_file(file: PathBuf, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>) -> Result<String, Box<dyn Error>> {
let template = Template::read_from(&file)?;
compile_template_from(template, variables, functions)
.map_err(|error| Box::new(error) as Box<dyn Error>)
}
pub fn compile_template_from_string(template: String, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>) -> Result<String, CompilationError> {
compile_template_from(Template::from(template), variables, functions)
}
pub fn compile_template_from(template: Template, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>) -> Result<String, CompilationError> {
let engine = SimpleEvaluationEngine::from(functions);
let compiler = TemplateCompiler::new(engine);
compiler.compile(&template, Context::with_variables(variables))
}
#[cfg(test)]
mod tests {
use crate::compile_template_from_file;
use std::path::PathBuf;
use std::collections::HashMap;
use crate::evaluator::Function;
use crate::evaluator::functions::SimpleFunction;
#[test]
fn should_compile_template() {
let file = PathBuf::from("test-assets/complex-template");
let mut functions: HashMap<String, Box<dyn Function>> = HashMap::new();
functions.insert("plus".to_string(), SimpleFunction::new(plus_function));
let mut variables: HashMap<String, String> = HashMap::new();
variables.insert("hello".to_string(), "Hello world!".to_string());
let result = compile_template_from_file(file, variables, functions);
assert_eq!(result.ok(), Some("Some template. Hello world!.\n\nThis shows a function evaluation usage example:\n2 + 2 = 4".to_string()));
}
fn plus_function(parameters: &[String]) -> String {
parameters.iter()
.map(|param|
param.parse::<i32>().unwrap()
)
.sum::<i32>()
.to_string()
}
}