1use super::{config_dir, FilesystemError, Result};
2use serde::{de::DeserializeOwned, Serialize};
3
4use std::fs;
5use std::path::PathBuf;
6
7pub trait PersistentData: DeserializeOwned + Serialize {
10 fn relative_path() -> PathBuf;
13
14 fn path() -> Result<PathBuf> {
17 let path = config_dir().join(Self::relative_path());
18
19 if let Some(dir) = path.parent() {
20 std::fs::create_dir_all(dir)?;
21 }
22
23 Ok(path)
24 }
25
26 fn load() -> Result<Self> {
28 let path = Self::path()?;
29
30 if path.exists() {
31 let file = fs::File::open(&path)?;
32
33 Ok(serde_yaml::from_reader(&file)?)
34 } else {
35 Err(FilesystemError::FileDoesntExist { path })
36 }
37 }
38
39 fn load_or_default<T: PersistentData + Default>() -> Result<T> {
42 let load_result = <T as PersistentData>::load();
43
44 match load_result {
45 Ok(deser) => Ok(deser),
46 _ => Ok(get_default_and_save()?),
47 }
48 }
49
50 fn save(&self) -> Result<()> {
52 let contents = serde_yaml::to_string(&self)?;
53
54 fs::write(Self::path()?, contents)?;
55
56 Ok(())
57 }
58}
59
60fn get_default_and_save<T: PersistentData + Default>() -> Result<T> {
62 let data = Default::default();
63
64 <T as PersistentData>::save(&data)?;
65
66 Ok(data)
67}