use etcetera::{AppStrategy, AppStrategyArgs, app_strategy::Xdg}; use smol::unblock; pub struct StorageManager { xdg: Xdg, data: Option>, } impl StorageManager { pub fn load(app: AppStrategyArgs) -> std::io::Result { let xdg = etcetera::choose_app_strategy(app).map_err(std::io::Error::other)?; let data = std::fs::read(xdg.in_data_dir("save")) .or_else(|_| std::fs::read(xdg.in_data_dir("save.tmp"))) .map(|data| data.into_boxed_slice()) .ok(); Ok(Self { data, xdg }) } pub fn get(&self) -> Option<&[u8]> { self.data.as_deref() } pub fn background_save(&mut self, data: Box<[u8]>) { let tmp_file = self.xdg.in_data_dir("save.tmp"); let save_file = self.xdg.in_data_dir("save"); self.data = Some(data.clone()); unblock(move || { std::fs::write(&tmp_file, &data)?; let saved_data = std::fs::read(&tmp_file)?; if *saved_data != *data { return Err(std::io::Error::other("Failed to verify file integrity")); } std::fs::rename(tmp_file, save_file)?; Ok(()) }); } }