rocket_include_tera/debug/
fairing.rs1use std::sync::{Mutex, MutexGuard, PoisonError};
2
3use rocket::{
4 data::Data,
5 fairing::{Fairing, Info, Kind},
6 request::Request,
7 Build, Rocket,
8};
9
10use super::{ReloadableTera, TeraContextManager, TeraResponse};
11
12const FAIRING_NAME: &str = "Tera (Debug)";
13
14pub struct TeraResponseFairing {
16 #[allow(clippy::type_complexity)]
17 pub(crate) custom_callback:
18 Box<dyn Fn(&mut MutexGuard<ReloadableTera>) -> usize + Send + Sync + 'static>,
19}
20
21#[rocket::async_trait]
22impl Fairing for TeraResponseFairing {
23 #[inline]
24 fn info(&self) -> Info {
25 Info {
26 name: FAIRING_NAME, kind: Kind::Ignite | Kind::Request
27 }
28 }
29
30 #[inline]
31 async fn on_ignite(&self, rocket: Rocket<Build>) -> Result<Rocket<Build>, Rocket<Build>> {
32 let tera = Mutex::new(ReloadableTera::new());
33
34 let cache_capacity =
35 (self.custom_callback)(&mut tera.lock().unwrap_or_else(PoisonError::into_inner));
36
37 let state = TeraContextManager::new(tera, cache_capacity);
38
39 Ok(rocket.manage(state))
40 }
41
42 #[inline]
43 async fn on_request(&self, req: &mut Request<'_>, _data: &mut Data<'_>) {
44 let cm = req
45 .rocket()
46 .state::<TeraContextManager>()
47 .expect("TeraContextManager registered in on_attach");
48
49 cm.tera.lock().unwrap_or_else(PoisonError::into_inner).reload_if_needed().unwrap();
50 }
51}
52
53impl TeraResponse {
54 #[inline]
56 pub fn fairing<F>(f: F) -> impl Fairing
57 where
58 F: Fn(&mut MutexGuard<ReloadableTera>) + Send + Sync + 'static, {
59 let f = Box::new(f);
60
61 TeraResponseFairing {
62 custom_callback: Box::new(move |tera| {
63 f(tera);
64
65 crate::DEFAULT_CACHE_CAPACITY
66 }),
67 }
68 }
69
70 #[inline]
72 pub fn fairing_cache<F>(f: F) -> impl Fairing
73 where
74 F: Fn(&mut MutexGuard<ReloadableTera>) -> usize + Send + Sync + 'static, {
75 TeraResponseFairing {
76 custom_callback: Box::new(f)
77 }
78 }
79}