prototty_file_storage/
lib.rs1pub use prototty_storage::*;
2use std::env;
3use std::fs::{self, File};
4use std::io::{self, Read, Write};
5use std::path::{Path, PathBuf};
6
7pub struct FileStorage {
8 base_path: PathBuf,
9}
10
11pub enum IfDirectoryMissing {
12 Create,
13 Error,
14}
15
16#[derive(Debug)]
17pub enum Error {
18 FailedToCreateDirectory(io::Error),
19 DirectoryMissing(PathBuf),
20 FailedToFindCurrentExePath(io::Error),
21}
22
23impl FileStorage {
24 pub fn new<P: AsRef<Path>>(path: P, if_directory_missing: IfDirectoryMissing) -> Result<Self, Error> {
25 if !path.as_ref().exists() {
26 match if_directory_missing {
27 IfDirectoryMissing::Create => {
28 fs::create_dir_all(path.as_ref()).map_err(Error::FailedToCreateDirectory)?
29 }
30 IfDirectoryMissing::Error => return Err(Error::DirectoryMissing(path.as_ref().to_path_buf())),
31 }
32 }
33 Ok(Self {
34 base_path: path.as_ref().to_path_buf(),
35 })
36 }
37
38 pub fn next_to_exe<P: AsRef<Path>>(
39 relative_path: P,
40 if_directory_missing: IfDirectoryMissing,
41 ) -> Result<Self, Error> {
42 let mut exe_path = env::current_exe().map_err(Error::FailedToFindCurrentExePath)?;
43 exe_path.pop();
45 Self::new(exe_path.join(relative_path), if_directory_missing)
46 }
47
48 pub fn full_path<S: AsRef<str>>(&self, path: S) -> PathBuf {
49 let relative_path: PathBuf = path.as_ref().into();
50 self.base_path.join(relative_path)
51 }
52}
53
54impl Storage for FileStorage {
55 fn exists<K>(&self, key: K) -> bool
56 where
57 K: AsRef<str>,
58 {
59 self.full_path(key).exists()
60 }
61
62 fn clear(&mut self) {
63 fs::remove_dir_all(&self.base_path).expect("Failed to remove base dir");
64 fs::create_dir_all(&self.base_path).expect("Failed to create base dir");
65 }
66
67 fn remove<K>(&mut self, key: K) -> Result<(), RemoveError>
68 where
69 K: AsRef<str>,
70 {
71 let path = self.full_path(key);
72 fs::remove_file(path).map_err(|_| RemoveError::IoError)
73 }
74
75 fn load_raw<K>(&self, key: K) -> Result<Vec<u8>, LoadRawError>
76 where
77 K: AsRef<str>,
78 {
79 let mut file = File::open(self.full_path(key)).map_err(|_| LoadRawError::NoSuchKey)?;
80 let mut contents = Vec::new();
81 file.read_to_end(&mut contents).map_err(|_| LoadRawError::IoError)?;
82 Ok(contents)
83 }
84
85 fn store_raw<K, V>(&mut self, key: K, value: V) -> Result<(), StoreRawError>
86 where
87 K: AsRef<str>,
88 V: AsRef<[u8]>,
89 {
90 let mut file = File::create(self.full_path(key)).map_err(|_| StoreRawError::IoError)?;
91 file.write_all(value.as_ref()).map_err(|_| StoreRawError::IoError)?;
92 Ok(())
93 }
94}