Skip to main content

react_auditor/
cache.rs

1use std::collections::HashMap;
2use std::path::Path;
3
4use serde::{Deserialize, Serialize};
5
6const CACHE_FILE: &str = ".raudit-cache.json";
7
8#[derive(Debug, Serialize, Deserialize)]
9pub struct Cache {
10    version: u32,
11    files: HashMap<String, u128>,
12}
13
14impl Cache {
15    pub fn load() -> Self {
16        let content = match std::fs::read_to_string(CACHE_FILE) {
17            Ok(c) => c,
18            Err(_) => return Self::empty(),
19        };
20        serde_json::from_str(&content).unwrap_or_else(|_| Self::empty())
21    }
22
23    pub fn save(&self) {
24        if let Ok(content) = serde_json::to_string_pretty(self) {
25            let _ = std::fs::write(CACHE_FILE, content);
26        }
27    }
28
29    fn empty() -> Self {
30        Self {
31            version: 1,
32            files: HashMap::new(),
33        }
34    }
35
36    pub fn is_unchanged_clean(&self, path: &Path) -> bool {
37        let path_str = path.to_string_lossy().to_string();
38        match self.files.get(&path_str) {
39            Some(&cached_mtime) => cached_mtime == mtime_nanos(path).unwrap_or(0),
40            None => false,
41        }
42    }
43
44    pub fn mark_clean(&mut self, path: &Path) {
45        if let Some(mtime) = mtime_nanos(path) {
46            self.files.insert(path.to_string_lossy().to_string(), mtime);
47        }
48    }
49
50    pub fn mark_dirty(&mut self, path: &Path) {
51        self.files.remove(&path.to_string_lossy().to_string());
52    }
53}
54
55fn mtime_nanos(path: &Path) -> Option<u128> {
56    let meta = std::fs::metadata(path).ok()?;
57    let mtime = meta.modified().ok()?;
58    Some(mtime.duration_since(std::time::UNIX_EPOCH).ok()?.as_nanos())
59}