devpage_design/ids/
remembering.rs1use std::collections::HashMap;
7use std::sync::{Arc, Mutex, MutexGuard};
8
9use crate::Problem;
10use crate::fonts::FontFile;
11use crate::parse::{self, File};
12use crate::scene::{Files, ImageFile};
13
14#[derive(Clone, Default)]
17pub struct Parses(Arc<Mutex<HashMap<String, Arc<File>>>>);
18
19impl Parses {
20 fn lock(&self) -> MutexGuard<'_, HashMap<String, Arc<File>>> {
21 self.0
22 .lock()
23 .unwrap_or_else(|poisoned| poisoned.into_inner())
24 }
25
26 pub fn holds(&self, path: &str) -> bool {
28 self.lock().contains_key(path)
29 }
30
31 pub fn forget(&self, path: &str) {
33 self.lock().remove(path);
34 }
35}
36
37pub struct Remembering<F> {
40 pub files: F,
41 parses: Parses,
42}
43
44impl<F> Remembering<F> {
45 pub fn new(files: F) -> Remembering<F> {
47 Remembering::with(files, &Parses::default())
48 }
49
50 pub fn with(files: F, parses: &Parses) -> Remembering<F> {
52 Remembering {
53 files,
54 parses: parses.clone(),
55 }
56 }
57}
58
59impl<F: Files> Files for Remembering<F> {
60 fn bytes(&self, path: &str) -> Option<Vec<u8>> {
61 self.files.bytes(path)
62 }
63
64 fn list(&self, path: &str) -> Option<Vec<String>> {
65 self.files.list(path)
66 }
67
68 fn read(&self, path: &str) -> Option<String> {
69 self.files.read(path)
70 }
71
72 fn parse(&self, path: &str, source: &str) -> Result<Arc<File>, Problem> {
75 let fresh = parse::parse(source)?;
76 let mut last = self.parses.lock();
77 let file = Arc::new(match last.get(path) {
78 Some(last) => super::matched(fresh, last),
79 None => fresh,
80 });
81 last.insert(path.to_string(), file.clone());
82 Ok(file)
83 }
84
85 fn image(&self, path: &str) -> Option<Result<Arc<ImageFile>, String>> {
86 self.files.image(path)
87 }
88
89 fn font(&self, path: &str) -> Option<Result<Arc<FontFile>, String>> {
90 self.files.font(path)
91 }
92}