rocket_include_handlebars/debug/
reloadable.rs1use std::{
2 collections::HashMap,
3 ops::{Deref, DerefMut},
4 path::PathBuf,
5 time::SystemTime,
6};
7
8use handlebars::{Handlebars, TemplateError};
9
10use crate::functions::add_helpers;
11
12#[derive(Debug)]
13pub struct ReloadableHandlebars {
15 handlebars: Handlebars<'static>,
16 files: HashMap<&'static str, (PathBuf, Option<SystemTime>)>,
17}
18
19impl ReloadableHandlebars {
20 #[inline]
22 pub fn new() -> ReloadableHandlebars {
23 let mut handlebars = Handlebars::new();
24
25 add_helpers(&mut handlebars);
26
27 ReloadableHandlebars {
28 handlebars,
29 files: HashMap::new(),
30 }
31 }
32
33 #[inline]
35 pub fn register_template_file<P: Into<PathBuf>>(
36 &mut self,
37 name: &'static str,
38 file_path: P,
39 ) -> Result<(), Box<TemplateError>> {
40 let file_path = file_path.into();
41
42 let metadata =
43 file_path.metadata().map_err(|err| TemplateError::from((err, String::from(name))))?;
44
45 let mtime = metadata.modified().ok();
46
47 self.handlebars.register_template_file(name, &file_path)?;
48
49 self.files.insert(name, (file_path, mtime));
50
51 Ok(())
52 }
53
54 #[inline]
56 pub fn unregister_template_file<S: AsRef<str>>(&mut self, name: S) -> Option<PathBuf> {
57 let name = name.as_ref();
58
59 match self.files.remove(name) {
60 Some((file_path, _)) => {
61 self.handlebars.unregister_template(name);
62
63 Some(file_path)
64 },
65 None => None,
66 }
67 }
68
69 #[inline]
71 pub fn reload_if_needed(&mut self) -> Result<(), Box<TemplateError>> {
72 for (&name, (file_path, mtime)) in &mut self.files {
73 let metadata = file_path
74 .metadata()
75 .map_err(|err| TemplateError::from((err, String::from(name))))?;
76
77 let (reload, new_mtime) = match mtime {
78 Some(mtime) => match metadata.modified() {
79 Ok(new_mtime) => (new_mtime > *mtime, Some(new_mtime)),
80 Err(_) => (true, None),
81 },
82 None => match metadata.modified() {
83 Ok(new_mtime) => (true, Some(new_mtime)),
84 Err(_) => (true, None),
85 },
86 };
87
88 if reload {
89 self.handlebars.register_template_file(name, &file_path)?;
90
91 *mtime = new_mtime;
92 }
93 }
94
95 Ok(())
96 }
97}
98
99impl Default for ReloadableHandlebars {
100 #[inline]
101 fn default() -> Self {
102 ReloadableHandlebars::new()
103 }
104}
105
106impl Deref for ReloadableHandlebars {
107 type Target = Handlebars<'static>;
108
109 #[inline]
110 fn deref(&self) -> &Self::Target {
111 &self.handlebars
112 }
113}
114
115impl DerefMut for ReloadableHandlebars {
116 #[inline]
117 fn deref_mut(&mut self) -> &mut Self::Target {
118 &mut self.handlebars
119 }
120}