rocket_dyn_templates/engine/
mod.rs
1use std::path::Path;
2use std::collections::HashMap;
3
4use rocket::serde::Serialize;
5
6use crate::template::TemplateInfo;
7
8#[cfg(feature = "tera")]
9mod tera;
10#[cfg(feature = "tera")]
11use ::tera::Tera;
12
13#[cfg(feature = "handlebars")]
14mod handlebars;
15#[cfg(feature = "handlebars")]
16use ::handlebars::Handlebars;
17
18#[cfg(feature = "minijinja")]
19mod minijinja;
20#[cfg(feature = "minijinja")]
21use ::minijinja::Environment;
22
23pub(crate) trait Engine: Send + Sync + Sized + 'static {
24 const EXT: &'static str;
25
26 fn init<'a>(templates: impl Iterator<Item = (&'a str, &'a Path)>) -> Option<Self>;
27 fn render<C: Serialize>(&self, name: &str, context: C) -> Option<String>;
28}
29
30pub struct Engines {
67 #[cfg(feature = "tera")]
73 pub tera: Tera,
74
75 #[cfg(feature = "handlebars")]
82 pub handlebars: Handlebars<'static>,
83
84 #[cfg(feature = "minijinja")]
91 pub minijinja: Environment<'static>,
92}
93
94impl Engines {
95 pub(crate) const ENABLED_EXTENSIONS: &'static [&'static str] = &[
96 #[cfg(feature = "tera")] Tera::EXT,
97 #[cfg(feature = "handlebars")] Handlebars::EXT,
98 #[cfg(feature = "minijinja")] Environment::EXT,
99 ];
100
101 pub(crate) fn init(templates: &HashMap<String, TemplateInfo>) -> Option<Engines> {
102 fn inner<E: Engine>(templates: &HashMap<String, TemplateInfo>) -> Option<E> {
103 let named_templates = templates.iter()
104 .filter(|&(_, i)| i.engine_ext == E::EXT)
105 .filter_map(|(k, i)| Some((k.as_str(), i.path.as_ref()?)))
106 .map(|(k, p)| (k, p.as_path()));
107
108 E::init(named_templates)
109 }
110
111 Some(Engines {
112 #[cfg(feature = "tera")]
113 tera: match inner::<Tera>(templates) {
114 Some(tera) => tera,
115 None => return None
116 },
117 #[cfg(feature = "handlebars")]
118 handlebars: match inner::<Handlebars<'static>>(templates) {
119 Some(hb) => hb,
120 None => return None
121 },
122 #[cfg(feature = "minijinja")]
123 minijinja: match inner::<Environment<'static>>(templates) {
124 Some(hb) => hb,
125 None => return None
126 },
127 })
128 }
129
130 pub(crate) fn render<C: Serialize>(
131 &self,
132 name: &str,
133 info: &TemplateInfo,
134 context: C,
135 ) -> Option<String> {
136 #[cfg(feature = "tera")] {
137 if info.engine_ext == Tera::EXT {
138 return Engine::render(&self.tera, name, context);
139 }
140 }
141
142 #[cfg(feature = "handlebars")] {
143 if info.engine_ext == Handlebars::EXT {
144 return Engine::render(&self.handlebars, name, context);
145 }
146 }
147
148 #[cfg(feature = "minijinja")] {
149 if info.engine_ext == Environment::EXT {
150 return Engine::render(&self.minijinja, name, context);
151 }
152 }
153
154 None
155 }
156
157 pub(crate) fn templates(&self) -> impl Iterator<Item = (&str, &'static str)> {
159 #[cfg(feature = "tera")]
160 let tera = self.tera.get_template_names().map(|name| (name, Tera::EXT));
161
162 #[cfg(feature = "handlebars")]
163 let handlebars = self.handlebars.get_templates().keys()
164 .map(|name| (name.as_str(), Handlebars::EXT));
165
166 #[cfg(feature = "minijinja")]
167 let minijinja = self.minijinja.templates()
168 .map(|(name, _)| (name, Environment::EXT));
169
170 #[cfg(not(feature = "tera"))] let tera = std::iter::empty();
171 #[cfg(not(feature = "handlebars"))] let handlebars = std::iter::empty();
172 #[cfg(not(feature = "minijinja"))] let minijinja = std::iter::empty();
173
174 tera.chain(handlebars).chain(minijinja)
175 }
176}