project_dirs/
proj_dirs.rs1use crate::Directory;
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5pub type MissingError = Vec<Directory>;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12pub struct ProjectDirs(pub HashMap<Directory, PathBuf>);
13
14impl ProjectDirs {
15 pub fn get(&self, dir: &Directory) -> Option<&PathBuf> {
16 self.0.get(dir)
17 }
18}
19
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct FullProjectDirs {
25 pub bin: PathBuf,
27 pub cache: PathBuf,
29 pub config: PathBuf,
31 pub data: PathBuf,
33 pub include: PathBuf,
35 pub lib: PathBuf,
37 pub log: PathBuf,
39 pub project_root: Option<PathBuf>,
41 pub runtime: Option<PathBuf>,
44 pub state: PathBuf,
46}
47
48impl ProjectDirs {
49 pub fn new(dirs: HashMap<Directory, PathBuf>) -> Self {
50 Self(dirs)
51 }
52
53 pub fn empty() -> Self {
54 Self(HashMap::new())
55 }
56}
57
58impl From<FullProjectDirs> for ProjectDirs {
59 fn from(value: FullProjectDirs) -> Self {
60 let mut result = ProjectDirs::new(HashMap::from([
61 (Directory::Cache, value.cache),
62 (Directory::Config, value.config),
63 (Directory::Data, value.data),
64 (Directory::State, value.state),
65 (Directory::Log, value.log),
66 (Directory::Bin, value.bin),
67 (Directory::Lib, value.lib),
68 (Directory::Include, value.include),
69 ]));
70
71 if let Some(runtime) = value.runtime {
72 result.0.insert(Directory::Runtime, runtime);
73 }
74
75 if let Some(project_root) = value.project_root {
76 result.0.insert(Directory::ProjectRoot, project_root);
77 }
78
79 result
80 }
81}
82
83impl TryFrom<ProjectDirs> for FullProjectDirs {
84 type Error = MissingError;
85
86 fn try_from(mut value: ProjectDirs) -> Result<Self, Self::Error> {
87 let mut errors = Vec::<Directory>::new();
88
89 for dir in [
90 Directory::Cache,
91 Directory::Config,
92 Directory::Data,
93 Directory::State,
94 Directory::Log,
95 Directory::Bin,
96 Directory::Lib,
97 ] {
98 if !value.0.contains_key(&dir) {
99 errors.push(dir);
100 }
101 }
102
103 if errors.is_empty() {
104 Ok(FullProjectDirs {
105 cache: value.0.remove(&Directory::Cache).unwrap(),
106 config: value.0.remove(&Directory::Config).unwrap(),
107 data: value.0.remove(&Directory::Data).unwrap(),
108 state: value.0.remove(&Directory::State).unwrap(),
109 log: value.0.remove(&Directory::Log).unwrap(),
110 bin: value.0.remove(&Directory::Bin).unwrap(),
111 include: value.0.remove(&Directory::Include).unwrap(),
112 lib: value.0.remove(&Directory::Lib).unwrap(),
113 runtime: value.0.remove(&Directory::Runtime),
114 project_root: value.0.remove(&Directory::ProjectRoot),
115 })
116 } else {
117 Err(errors)
118 }
119 }
120}