1use std::{
2 fs,
3 io::{Error, ErrorKind},
4 path::PathBuf,
5};
6
7use crate::json::Jsonable;
8
9pub trait StoragePath {
13 fn storage_file_name() -> &'static str;
15
16 fn storage_dir_name() -> &'static str;
18
19 fn base_dir_path() -> PathBuf {
21 dirs::home_dir().unwrap()
22 }
23
24 fn get_or_create_storage_path() -> Result<PathBuf, Error> {
28 let mut storage_dir_path = PathBuf::new();
29 storage_dir_path.push(Self::base_dir_path());
30 storage_dir_path.push(Self::storage_dir_name());
31 if storage_dir_path.exists() {
32 return Ok(storage_dir_path);
33 }
34 match fs::create_dir_all(&storage_dir_path) {
35 Ok(_) => Ok(storage_dir_path),
36 Err(_) => Err(Error::new(
37 ErrorKind::Unsupported,
38 "Could not create storage directory",
39 )),
40 }
41 }
42
43 fn get_or_create_storage_file_path() -> Result<PathBuf, Error> {
45 let storage_dir_path = match Self::get_or_create_storage_path() {
46 Ok(path) => path,
47 Err(e) => return Err(e),
48 };
49 let storage_file_path = storage_dir_path.join(Self::storage_file_name());
50
51 Ok(storage_file_path)
52 }
53}
54
55pub trait Storable: Jsonable + StoragePath {
61 fn load() -> Result<Self, Error> {
63 let storage_file_path = match Self::get_or_create_storage_file_path() {
64 Ok(path) => path,
65 Err(e) => return Err(e),
66 };
67
68 Self::from_json(&storage_file_path)
69 }
70
71 fn save(&self) -> Result<(), Error> {
73 let storage_file_path = match Self::get_or_create_storage_file_path() {
74 Ok(path) => path,
75 Err(e) => return Err(e),
76 };
77
78 match fs::write(&storage_file_path, self.to_json()) {
79 Ok(_) => Ok(()),
80 Err(err) => Err(Error::new(
81 ErrorKind::Other,
82 format!("Could not save storage. {err:?}, file_name: {storage_file_path:?}"),
83 )),
84 }
85 }
86}