1use dirs;
29use std::{
30 fs, io,
31 path::{Path, PathBuf},
32};
33
34#[derive(Debug, PartialEq, Eq)]
35enum StoreType {
36 Home,
37 Config,
38 ConfigLocal,
39 Executable,
40 Audio,
41 Cache,
42 Data,
43 DataLocal,
44 Desktop,
45 Download,
46 Document,
47 Font,
48 Picture,
49 Preference,
50 Public,
51 Runtime,
52 State,
53 Template,
54 Video,
55}
56
57impl StoreType {
58 pub fn path(&self) -> fn() -> Option<PathBuf> {
59 match *self {
60 Self::Home => dirs::home_dir,
61 Self::Config => dirs::config_dir,
62 Self::ConfigLocal => dirs::config_local_dir,
63 Self::Executable => dirs::executable_dir,
64 Self::Audio => dirs::audio_dir,
65 Self::Cache => dirs::cache_dir,
66 Self::Data => dirs::data_dir,
67 Self::DataLocal => dirs::data_local_dir,
68 Self::Desktop => dirs::desktop_dir,
69 Self::Download => dirs::download_dir,
70 Self::Document => dirs::document_dir,
71 Self::Font => dirs::font_dir,
72 Self::Picture => dirs::picture_dir,
73 Self::Preference => dirs::preference_dir,
74 Self::Public => dirs::public_dir,
75 Self::Runtime => dirs::runtime_dir,
76 Self::State => dirs::state_dir,
77 Self::Template => dirs::template_dir,
78 Self::Video => dirs::video_dir,
79 }
80 }
81}
82
83fn create_dir(path: &PathBuf) -> io::Result<()> {
84 if !path.exists() {
85 fs::create_dir_all(&path)?;
86 }
87
88 Ok(())
89}
90
91fn create_store(store: StoreType, path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
92 let dir_fn = store.path();
93 if let Some(root) = dir_fn() {
94 let store_dir = root.join(format!(".{}", path.as_ref().display()));
95 create_dir(&store_dir)?;
96
97 Ok(Some(store_dir))
98 } else {
99 Ok(None)
100 }
101}
102
103pub fn audio_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
105 create_store(StoreType::Audio, path)
106}
107
108pub fn cache_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
110 create_store(StoreType::Cache, path)
111}
112
113pub fn config_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
115 create_store(StoreType::Config, path)
116}
117
118pub fn local_config_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
120 create_store(StoreType::ConfigLocal, path)
121}
122
123pub fn data_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
125 create_store(StoreType::Data, path)
126}
127
128pub fn local_data_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
130 create_store(StoreType::DataLocal, path)
131}
132
133pub fn desktop_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
135 create_store(StoreType::Desktop, path)
136}
137
138pub fn document_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
140 create_store(StoreType::Document, path)
141}
142
143pub fn download_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
145 create_store(StoreType::Download, path)
146}
147
148pub fn executable_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
150 create_store(StoreType::Executable, path)
151}
152
153pub fn font_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
155 create_store(StoreType::Font, path)
156}
157
158pub fn home_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
160 create_store(StoreType::Home, path)
161}
162
163pub fn picture_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
165 create_store(StoreType::Picture, path)
166}
167
168pub fn preference_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
170 create_store(StoreType::Preference, path)
171}
172
173pub fn public_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
175 create_store(StoreType::Public, path)
176}
177
178pub fn runtime_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
180 create_store(StoreType::Runtime, path)
181}
182
183pub fn state_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
185 create_store(StoreType::State, path)
186}
187
188pub fn template_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
190 create_store(StoreType::Template, path)
191}
192
193pub fn video_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
195 create_store(StoreType::Video, path)
196}
197
198pub fn custom_store(
220 root_path: impl AsRef<Path>,
221 target: impl AsRef<Path>,
222) -> io::Result<Option<PathBuf>> {
223 let root = PathBuf::from(root_path.as_ref());
224 let store_dir = root.join(format!(".{}", target.as_ref().display()));
225 create_dir(&store_dir)?;
226
227 Ok(Some(store_dir))
228}