rustbasic_core/template/
mod.rs1pub mod lexer;
2pub mod parser;
3pub mod evaluator;
4
5use lexer::Lexer;
6use parser::Parser;
7use evaluator::{Evaluator, FilterFn};
8use serde_json::Value;
9use std::collections::HashMap;
10use std::sync::Arc;
11
12pub struct TemplateEngine {
13 filters: HashMap<String, FilterFn>,
14}
15
16impl Default for TemplateEngine {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl TemplateEngine {
23 pub fn new() -> Self {
24 let mut filters = HashMap::new();
25
26 filters.insert(
28 "safe".to_string(),
29 Arc::new(|val: &Value, _args: &[Value]| val.clone()) as FilterFn,
30 );
31 filters.insert(
32 "tojson".to_string(),
33 Arc::new(|val: &Value, _args: &[Value]| {
34 let s = serde_json::to_string(val).unwrap_or_default();
36 Value::String(s)
37 }) as FilterFn,
38 );
39
40 Self { filters }
41 }
42
43 pub fn add_filter<F>(&mut self, name: &str, filter: F)
44 where
45 F: Fn(&Value, &[Value]) -> Value + Send + Sync + 'static,
46 {
47 self.filters.insert(name.to_string(), Arc::new(filter));
48 }
49
50 pub fn render(&self, template_str: &str, context: &Value) -> Result<String, String> {
51 let mut lexer = Lexer::new(template_str);
52 let tokens = lexer.tokenize()?;
53 let mut parser = Parser::new(tokens);
54 let nodes = parser.parse()?;
55 let evaluator = Evaluator::new(self.filters.clone());
56 evaluator.render_nodes(&nodes, context)
57 }
58}