use std::path::{Path, PathBuf};
use std::time::SystemTime;
use super::dix_data::DixData;
use super::load_options::DixLoadOptions;
use super::loader::DixLoader;
pub struct HotReloadWatcher {
path: PathBuf,
options: DixLoadOptions,
last_modified: Option<SystemTime>,
}
impl HotReloadWatcher {
pub fn new(path: impl Into<PathBuf>) -> Self {
HotReloadWatcher {
path: path.into(),
options: DixLoadOptions::new(),
last_modified: None,
}
}
pub fn with_options(mut self, options: DixLoadOptions) -> Self {
self.options = options;
self
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn has_loaded(&self) -> bool {
self.last_modified.is_some()
}
fn current_mtime(&self) -> Result<SystemTime, String> {
std::fs::metadata(&self.path)
.and_then(|m| m.modified())
.map_err(|e| format!(
"hot_reload: cannot stat '{}': {}",
self.path.display(), e
))
}
pub fn has_changed(&self) -> Result<bool, String> {
let mtime = self.current_mtime()?;
Ok(match self.last_modified {
Some(prev) => mtime != prev,
None => true,
})
}
pub fn force_reload(&mut self) -> Result<DixData, String> {
let mtime = self.current_mtime()?;
let data = DixLoader::new()
.load_text(self.path.to_string_lossy().as_ref(), &self.options)?;
self.last_modified = Some(mtime);
Ok(data)
}
pub fn check_and_reload(&mut self) -> Result<Option<DixData>, String> {
if self.has_changed()? {
self.force_reload().map(Some)
} else {
Ok(None)
}
}
}