1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
use std::fs; use std::os::unix::fs::MetadataExt; use ::Result; use ::Error; pub struct AutoLoader<T>{ paths: Vec<String>, times: Vec<i64>, load_function: Box<Fn() -> Result<T>>, } fn file_time(file: &str) -> Result<i64>{ let meta = fs::metadata(file).map_err(|err| Error::with_cause("IO error", err))?; let time = meta.atime(); Ok(time) } impl<T> AutoLoader<T>{ pub fn new<F:'static + Fn()->Result<T>>(files: Vec<String>, load_function: F) -> AutoLoader<T>{ let times = files.iter().map(|file| file_time(file).unwrap()).collect(); AutoLoader{ paths: files, times: times, load_function: Box::new(load_function), } } pub fn update(&mut self) -> Result<Option<T>>{ let times: Vec<i64> = self.paths.iter().map(|path| file_time(path).unwrap_or(0)).collect(); let changed = self.times.is_empty () || self.paths.iter() .zip(self.times.iter()) .zip(times.iter()) .any(|((_path, time), new_time)| *time < *new_time); if changed{ self.load().map(|v| Some(v)) }else{ Ok(None) } } pub fn load(&mut self) -> Result<T>{ self.times = self.paths.iter().map(|path| file_time(path).unwrap_or(0)).collect(); (self.load_function)() } }