summaryrefslogtreecommitdiff
path: root/src/storage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/storage.rs')
-rw-r--r--src/storage.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/storage.rs b/src/storage.rs
new file mode 100644
index 0000000..90abf05
--- /dev/null
+++ b/src/storage.rs
@@ -0,0 +1,41 @@
+use etcetera::{AppStrategy, AppStrategyArgs, app_strategy::Xdg};
+use smol::unblock;
+
+pub struct StorageManager {
+ xdg: Xdg,
+ data: Option<Box<[u8]>>,
+}
+
+impl StorageManager {
+ pub fn load(app: AppStrategyArgs) -> std::io::Result<Self> {
+ 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(())
+ });
+ }
+}