rocket_include_tera/debug/
manager.rs

1use std::sync::{Mutex, PoisonError};
2
3use serde::Serialize;
4use tera::Context;
5
6use super::{ReloadableTera, TeraResponse};
7use crate::{functions::compute_data_etag, EtagIfNoneMatch};
8
9/// To monitor the state of Tera.
10#[derive(Educe)]
11#[educe(Debug)]
12pub struct TeraContextManager {
13    pub tera: Mutex<ReloadableTera>,
14}
15
16impl TeraContextManager {
17    #[inline]
18    pub(crate) fn new(tera: Mutex<ReloadableTera>, _cache_capacity: usize) -> TeraContextManager {
19        TeraContextManager {
20            tera,
21        }
22    }
23
24    /// Build a `TeraResponse`.
25    #[inline]
26    pub fn build<S: AsRef<str>, V: Serialize>(
27        &self,
28        etag_if_none_match: &EtagIfNoneMatch<'_>,
29        minify: bool,
30        name: S,
31        context: V,
32    ) -> TeraResponse {
33        self.tera
34            .lock()
35            .unwrap_or_else(PoisonError::into_inner)
36            .render(name.as_ref(), &Context::from_serialize(context).unwrap())
37            .map(|html| {
38                let etag = compute_data_etag(html.as_bytes());
39
40                if etag_if_none_match.weak_eq(&etag) {
41                    TeraResponse::not_modified()
42                } else {
43                    let html = if minify { html_minifier::minify(html).unwrap() } else { html };
44
45                    TeraResponse::build_not_cache(html, &etag)
46                }
47            })
48            .unwrap()
49    }
50
51    /// Render a template.
52    #[inline]
53    pub fn render<S: AsRef<str>, V: Serialize>(&self, name: S, context: V) -> String {
54        self.tera
55            .lock()
56            .unwrap_or_else(PoisonError::into_inner)
57            .render(name.as_ref(), &Context::from_serialize(context).unwrap())
58            .unwrap()
59    }
60}