1use std::fs;
7use std::path::Path;
8use std::time::SystemTime;
9
10pub fn is_cache_fresh(cache_path: &Path, save_path: &Path) -> bool {
16 let cache_mtime = match file_mtime(cache_path) {
17 Some(t) => t,
18 None => return false,
19 };
20 let save_mtime = match file_mtime(save_path) {
21 Some(t) => t,
22 None => return false,
23 };
24 cache_mtime > save_mtime
25}
26
27fn file_mtime(path: &Path) -> Option<SystemTime> {
29 fs::metadata(path).ok()?.modified().ok()
30}
31
32pub fn load_or_rebuild(
37 cache_path: &Path,
38 save_path: &Path,
39 no_cache: bool,
40) -> Result<(nms_graph::GalaxyModel, bool), Box<dyn std::error::Error>> {
41 if !no_cache && is_cache_fresh(cache_path, save_path) {
43 match crate::read_cache(cache_path) {
44 Ok(data) => {
45 let model = crate::rebuild_model(&data);
46 return Ok((model, true));
47 }
48 Err(e) => {
49 eprintln!("Warning: cache read failed ({e}), rebuilding from save");
50 }
51 }
52 }
53
54 let save = nms_save::parse_save_file(save_path)?;
56 let model = nms_graph::GalaxyModel::from_save(&save);
57
58 if !no_cache {
60 let data = crate::extract_cache_data(&model, save.version);
61 if let Err(e) = crate::write_cache(&data, cache_path) {
62 eprintln!("Warning: could not write cache ({e})");
63 }
64 }
65
66 Ok((model, false))
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use std::thread;
73 use std::time::Duration;
74
75 #[test]
76 fn test_fresh_cache_returns_true() {
77 let dir = tempfile::tempdir().unwrap();
78 let save_path = dir.path().join("save.json");
79 let cache_path = dir.path().join("galaxy.rkyv");
80
81 fs::write(&save_path, "save data").unwrap();
82 thread::sleep(Duration::from_millis(50));
83 fs::write(&cache_path, "cache data").unwrap();
84
85 assert!(is_cache_fresh(&cache_path, &save_path));
86 }
87
88 #[test]
89 fn test_stale_cache_returns_false() {
90 let dir = tempfile::tempdir().unwrap();
91 let save_path = dir.path().join("save.json");
92 let cache_path = dir.path().join("galaxy.rkyv");
93
94 fs::write(&cache_path, "cache data").unwrap();
95 thread::sleep(Duration::from_millis(50));
96 fs::write(&save_path, "updated save").unwrap();
97
98 assert!(!is_cache_fresh(&cache_path, &save_path));
99 }
100
101 #[test]
102 fn test_missing_cache_returns_false() {
103 let dir = tempfile::tempdir().unwrap();
104 let save_path = dir.path().join("save.json");
105 let cache_path = dir.path().join("galaxy.rkyv");
106
107 fs::write(&save_path, "save data").unwrap();
108 assert!(!is_cache_fresh(&cache_path, &save_path));
109 }
110
111 #[test]
112 fn test_missing_save_returns_false() {
113 let dir = tempfile::tempdir().unwrap();
114 let save_path = dir.path().join("save.json");
115 let cache_path = dir.path().join("galaxy.rkyv");
116
117 fs::write(&cache_path, "cache data").unwrap();
118 assert!(!is_cache_fresh(&cache_path, &save_path));
119 }
120}