1use any_cache::{Cache, HashCache};
6use notify::{self, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
7use std::collections::{HashMap, HashSet};
8use std::fmt::{self, Display};
9use std::ops::{Deref, DerefMut};
10use std::path::{Path, PathBuf};
11use std::sync::mpsc::{channel, Receiver};
12use std::time::Duration;
13
14use crate::key::{Key, PrivateKey};
15use crate::res::Res;
16
17pub trait Load<C, K, Method = ()>: 'static + Sized
35where K: Key,
36 Method: ?Sized {
37 type Error: Display + 'static;
39
40 fn load(
47 key: K,
48 storage: &mut Storage<C, K>,
49 ctx: &mut C,
50 ) -> Result<Loaded<Self, K>, Self::Error>;
51
52 fn reload(
57 &self,
58 key: K,
59 storage: &mut Storage<C, K>,
60 ctx: &mut C,
61 ) -> Result<Self, Self::Error> {
62 Self::load(key, storage, ctx).map(|lr| lr.res)
63 }
64}
65
66pub struct Loaded<T, K> {
73 pub res: T,
75 pub deps: Vec<K>,
77}
78
79impl<T, K> Loaded<T, K> {
80 pub fn without_dep(res: T) -> Self {
82 Loaded {
83 res,
84 deps: Vec::new(),
85 }
86 }
87
88 pub fn with_deps(res: T, deps: Vec<K>) -> Self {
90 Loaded { res, deps }
91 }
92}
93
94impl<T, K> From<T> for Loaded<T, K> {
95 fn from(res: T) -> Self {
96 Loaded::without_dep(res)
97 }
98}
99
100struct ResMetaData<C, K> {
102 on_reload: Box<dyn Fn(&mut Storage<C, K>, &mut C) -> Result<(), Box<dyn Display>>>,
104}
105
106impl<C, K> ResMetaData<C, K> {
107 fn new<F>(f: F) -> Self
108 where F: 'static + Fn(&mut Storage<C, K>, &mut C) -> Result<(), Box<dyn Display>> {
109 ResMetaData {
110 on_reload: Box::new(f),
111 }
112 }
113}
114
115pub struct Storage<C, K> {
120 canon_root: PathBuf,
122 cache: HashCache,
124 deps: HashMap<K, Vec<K>>,
126 metadata: HashMap<K, ResMetaData<C, K>>,
128}
129
130impl<C, K> Storage<C, K> where K: Key {
131 fn new(canon_root: PathBuf) -> Self{
132 Storage {
133 canon_root,
134 cache: HashCache::new(),
135 deps: HashMap::new(),
136 metadata: HashMap::new(),
137 }
138 }
139
140 pub fn root(&self) -> &Path {
142 &self.canon_root
143 }
144
145 fn inject<T, M>(
150 &mut self,
151 key: K,
152 resource: T,
153 deps: Vec<K>,
154 ) -> Result<Res<T>, StoreError<K>>
155 where T: Load<C, K, M> {
156 if self.metadata.contains_key(&key) {
158 return Err(StoreError::AlreadyRegisteredKey(key.clone()));
159 }
160
161 let res = Res::new(resource);
163
164 let res_ = res.clone();
166 let key_ = key.clone();
167 let metadata = ResMetaData::new(move |storage, ctx| {
168 let reloaded = <T as Load<C, K, M>>::reload(&res_.borrow(), key_.clone(), storage, ctx);
169
170 match reloaded {
171 Ok(r) => {
172 *res_.borrow_mut() = r;
174 Ok(())
175 }
176 Err(e) => Err(Box::new(e)),
177 }
178 });
179
180 self.metadata.insert(key.clone(), metadata);
181
182 let root = &self.canon_root;
184 for dep in deps {
185 self
186 .deps
187 .entry(dep.clone().prepare_key(root))
188 .or_insert(Vec::new())
189 .push(key.clone());
190 }
191
192 let pkey = PrivateKey::new(key);
194
195 self.cache.save(pkey, res.clone());
197
198 Ok(res)
199 }
200
201 pub fn get<T>(&mut self, key: &K, ctx: &mut C) -> Result<Res<T>, StoreErrorOr<T, C, K>>
205 where T: Load<C, K> {
206 self.get_by(key, ctx, ())
207 }
208
209 pub fn get_by<T, M>(
212 &mut self,
213 key: &K,
214 ctx: &mut C,
215 _: M,
216 ) -> Result<Res<T>, StoreErrorOr<T, C, K, M>>
217 where T: Load<C, K, M> {
218 let key = key.clone().prepare_key(self.root());
219
220 let pkey = PrivateKey::<K, T>::new(key);
222 let x: Option<Res<T>> = self.cache.get(&pkey).cloned();
223 let key = pkey.0;
224
225 match x {
226 Some(resource) => Ok(resource),
227 None => {
228 let loaded =
229 <T as Load<C, K, M>>::load(key.clone(), self, ctx).map_err(StoreErrorOr::ResError)?;
230 self
231 .inject::<T, M>(key, loaded.res, loaded.deps)
232 .map_err(StoreErrorOr::StoreError)
233 }
234 }
235 }
236
237 pub fn get_proxied<T, P>(
242 &mut self,
243 key: &K,
244 proxy: P,
245 ctx: &mut C,
246 ) -> Result<Res<T>, StoreError<K>>
247 where T: Load<C, K>,
248 P: FnOnce() -> T {
249 self
250 .get(key, ctx)
251 .or_else(|_| self.inject::<T, ()>(key.clone().into(), proxy(), Vec::new()))
252 }
253
254 pub fn get_proxied_by<T, M, P>(
258 &mut self,
259 key: &K,
260 proxy: P,
261 ctx: &mut C,
262 method: M,
263 ) -> Result<Res<T>, StoreError<K>>
264 where T: Load<C, K, M>,
265 P: FnOnce() -> T {
266 self
267 .get_by(key, ctx, method)
268 .or_else(|_| self.inject::<T, M>(key.clone().into(), proxy(), Vec::new()))
269 }
270}
271
272#[derive(Clone, Debug, Eq, PartialEq)]
274pub enum StoreError<K> {
275 RootDoesNotExist(PathBuf),
277 AlreadyRegisteredKey(K),
282}
283
284impl<K> Display for StoreError<K> where K: Display {
285 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
286 match *self {
287 StoreError::RootDoesNotExist(ref path) => write!(f, "root {} doesn’t exist", path.display()),
288 StoreError::AlreadyRegisteredKey(ref dk) => write!(f, "already registered key: {}", dk),
289 }
290 }
291}
292
293pub enum StoreErrorOr<T, C, K, M = ()> where T: Load<C, K, M>, K: Key {
295 StoreError(StoreError<K>),
297 ResError(T::Error),
299}
300
301impl<T, C, K, M> Clone for StoreErrorOr<T, C, K, M>
302where T: Load<C, K, M>,
303 T::Error: Clone,
304 K: Key {
305 fn clone(&self) -> Self {
306 match *self {
307 StoreErrorOr::StoreError(ref e) => StoreErrorOr::StoreError(e.clone()),
308 StoreErrorOr::ResError(ref e) => StoreErrorOr::ResError(e.clone()),
309 }
310 }
311}
312
313impl<T, C, K, M> Eq for StoreErrorOr<T, C, K, M>
314where T: Load<C, K, M>,
315 T::Error: Eq,
316 K: Key {
317}
318
319impl<T, C, K, M> PartialEq for StoreErrorOr<T, C, K, M>
320where T: Load<C, K, M>,
321 T::Error: PartialEq,
322 K: Key {
323 fn eq(&self, rhs: &Self) -> bool {
324 match (self, rhs) {
325 (&StoreErrorOr::StoreError(ref a), &StoreErrorOr::StoreError(ref b)) => a == b,
326 (&StoreErrorOr::ResError(ref a), &StoreErrorOr::ResError(ref b)) => a == b,
327 _ => false,
328 }
329 }
330}
331
332impl<T, C, K, M> fmt::Debug for StoreErrorOr<T, C, K, M>
333where T: Load<C, K, M>,
334 T::Error: fmt::Debug,
335 K: Key + fmt::Debug {
336 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
337 match *self {
338 StoreErrorOr::StoreError(ref e) => f.debug_tuple("StoreError").field(e).finish(),
339 StoreErrorOr::ResError(ref e) => f.debug_tuple("ResError").field(e).finish(),
340 }
341 }
342}
343
344impl<T, C, K, M> Display for StoreErrorOr<T, C, K, M>
345where T: Load<C, K, M>,
346 T::Error: fmt::Debug,
347 K: Key + Display {
348 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
349 match *self {
350 StoreErrorOr::StoreError(ref e) => e.fmt(f),
351 StoreErrorOr::ResError(ref e) => e.fmt(f),
352 }
353 }
354}
355
356struct Synchronizer<C, K> {
361 dirties: HashSet<K>,
363 #[allow(dead_code)]
365 watcher: RecommendedWatcher,
366 watcher_rx: Receiver<DebouncedEvent>,
368 discovery: Discovery<C, K>
370}
371
372impl<C, K> Synchronizer<C, K> where K: Key {
373 fn new(
374 watcher: RecommendedWatcher,
375 watcher_rx: Receiver<DebouncedEvent>,
376 discovery: Discovery<C, K>
377 ) -> Self {
378 Synchronizer {
379 dirties: HashSet::new(),
380 watcher,
381 watcher_rx,
382 discovery
383 }
384 }
385
386 fn dequeue_fs_events(&mut self, storage: &mut Storage<C, K>, ctx: &mut C) where K: for<'a> From<&'a Path> {
388 for event in self.watcher_rx.try_iter() {
389 match event {
390 DebouncedEvent::Write(ref path) | DebouncedEvent::Create(ref path) => {
391 let key = path.as_path().into();
392
393 if storage.metadata.contains_key(&key) {
394 self.dirties.insert(key);
395 } else {
396 self.discovery.discover(path, storage, ctx);
397 }
398 }
399
400 _ => (),
401 }
402 }
403 }
404
405 fn reload_dirties(&mut self, storage: &mut Storage<C, K>, ctx: &mut C) {
407 self.dirties.retain(|dep_key| {
408 if let Some(metadata) = storage.metadata.remove(&dep_key) {
409 if (metadata.on_reload)(storage, ctx).is_ok() {
410 if let Some(deps) = storage.deps.get(&dep_key).cloned() {
413 for dep in deps {
414 if let Some(obs_metadata) = storage.metadata.remove(&dep) {
415 let _ = (obs_metadata.on_reload)(storage, ctx);
417
418 storage.metadata.insert(dep, obs_metadata);
420 }
421 }
422 }
423 }
424
425 storage.metadata.insert(dep_key.clone(), metadata);
426 }
427
428 false
429 });
430 }
431
432 fn sync(&mut self, storage: &mut Storage<C, K>, ctx: &mut C) where K: for<'a> From<&'a Path> {
434 self.dequeue_fs_events(storage, ctx);
435 self.reload_dirties(storage, ctx);
436 }
437}
438
439pub struct Store<C, K> {
441 storage: Storage<C, K>,
442 synchronizer: Synchronizer<C, K>,
443}
444
445impl<C, K> Store<C, K> where K: Key {
446 pub fn new(opt: StoreOpt<C, K>) -> Result<Self, StoreError<K>> {
453 let root = &opt.root;
455 let canon_root = root
456 .canonicalize()
457 .map_err(|_| StoreError::RootDoesNotExist(root.to_owned()))?;
458
459 let (wsx, wrx) = channel();
461 let mut watcher = notify::watcher(wsx, opt.debounce_duration).unwrap();
462
463 let _ = watcher.watch(&canon_root, RecursiveMode::Recursive);
465
466 let storage = Storage::new(canon_root);
468
469 let synchronizer = Synchronizer::new(watcher, wrx, opt.discovery);
471
472 let store = Store {
473 storage,
474 synchronizer,
475 };
476
477 Ok(store)
478 }
479
480 pub fn sync(&mut self, ctx: &mut C) where K: for<'a> From<&'a Path> {
482 self.synchronizer.sync(&mut self.storage, ctx);
483 }
484}
485
486impl<C, K> Deref for Store<C, K> {
487 type Target = Storage<C, K>;
488
489 fn deref(&self) -> &Self::Target {
490 &self.storage
491 }
492}
493
494impl<C, K> DerefMut for Store<C, K> {
495 fn deref_mut(&mut self) -> &mut Self::Target {
496 &mut self.storage
497 }
498}
499
500pub struct StoreOpt<C, K> {
504 root: PathBuf,
505 debounce_duration: Duration,
506 discovery: Discovery<C, K>
507}
508
509impl<C, K> Default for StoreOpt<C, K> {
510 fn default() -> Self {
511 StoreOpt {
512 root: PathBuf::from("."),
513 debounce_duration: Duration::from_millis(50),
514 discovery: Discovery::default()
515 }
516 }
517}
518
519impl<C, K> StoreOpt<C, K> {
520 #[inline]
531 pub fn set_debounce_duration(self, duration: Duration) -> Self {
532 StoreOpt {
533 debounce_duration: duration,
534 ..self
535 }
536 }
537
538 #[inline]
540 pub fn debounce_duration(&self) -> Duration {
541 self.debounce_duration
542 }
543
544 #[inline]
550 pub fn set_root<P>(self, root: P) -> Self
551 where P: AsRef<Path> {
552 StoreOpt {
553 root: root.as_ref().to_owned(),
554 ..self
555 }
556 }
557
558 #[inline]
560 pub fn root(&self) -> &Path {
561 &self.root
562 }
563
564 #[inline]
570 pub fn set_discovery(self, discovery: Discovery<C, K>) -> Self {
571 StoreOpt {
572 discovery,
573 ..self
574 }
575 }
576
577 #[inline]
579 pub fn discovery(&self) -> &Discovery<C, K> {
580 &self.discovery
581 }
582}
583
584pub struct Discovery<C, K> {
591 closure: Box<dyn FnMut(&Path, &mut Storage<C, K>, &mut C)>,
592}
593
594impl<C, K> Discovery<C, K> {
595 pub fn new<F>(f: F) -> Self where F: 'static + FnMut(&Path, &mut Storage<C, K>, &mut C) {
606 Discovery {
607 closure: Box::new(f)
608 }
609 }
610
611 fn discover(&mut self, path: &Path, storage: &mut Storage<C, K>, ctx: &mut C) {
613 (self.closure)(path, storage, ctx)
614 }
615}
616
617impl<C, K> Default for Discovery<C, K> {
621 fn default() -> Self {
622 Discovery::new(|_, _, _| {})
623 }
624}