1use std::env::JoinPathsError;
10use std::env::join_paths;
11use std::env::split_paths;
12use std::env::var_os;
13use std::ffi::OsStr;
14use std::ffi::OsString;
15use std::path::Path;
16use std::path::PathBuf;
17
18#[derive(Clone, Debug)]
26pub struct Home
27{
28 home_dir: PathBuf,
29 backend_config_file: PathBuf,
30 history_file: PathBuf,
31 pkg_config_file: PathBuf,
32 bin_path: OsString,
33 lib_path: OsString,
34 doc_path: OsString,
35}
36
37impl Home
38{
39 fn path_from<K: AsRef<OsStr>, L: AsRef<OsStr>, D: AsRef<Path>>(path: &Option<String>, path_var_name: K, work_path_var_name: L, home_dir: &PathBuf, dir: D, is_work_dir: bool) -> OsString
40 {
41 match path {
42 Some(path) => OsString::from(path.as_str()),
43 None => {
44 if !is_work_dir {
45 match var_os(path_var_name) {
46 Some(tmp_lib_path) => tmp_lib_path,
47 None => {
48 let mut tmp_lib_path = home_dir.clone();
49 tmp_lib_path.push(dir);
50 tmp_lib_path.into_os_string()
51 },
52 }
53 } else {
54 match var_os(work_path_var_name) {
55 Some(tmp_lib_path) => tmp_lib_path,
56 None => {
57 let mut tmp_lib_path = PathBuf::from("work");
58 tmp_lib_path.push(dir);
59 tmp_lib_path.into_os_string()
60 },
61 }
62 }
63 },
64 }
65 }
66
67 pub fn new(home_dir: &Option<String>, bin_path: &Option<String>, lib_path: &Option<String>, doc_path: &Option<String>, is_work_dir: bool) -> Option<Self>
74 {
75 let home_dir = match home_dir {
76 Some(home_dir) => PathBuf::from(home_dir.as_str()),
77 None => {
78 match home::home_dir() {
79 Some(user_home_dir) => {
80 let mut tmp_home_dir = user_home_dir.clone();
81 match var_os("UNLAB_GPU_HOME") {
82 Some(tmp_home_dir2) => tmp_home_dir.push(tmp_home_dir2.as_os_str()),
83 None => tmp_home_dir.push(".unlab-gpu"),
84 }
85 tmp_home_dir
86 },
87 None => {
88 match var_os("UNLAB_GPU_HOME") {
89 Some(tmp_home_dir) => PathBuf::from(tmp_home_dir.as_os_str()),
90 None => return None,
91 }
92 },
93 }
94 },
95 };
96 let mut backend_config_file = home_dir.clone();
97 backend_config_file.push("backend.toml");
98 let mut history_file = if !is_work_dir {
99 home_dir.clone()
100 } else {
101 PathBuf::from("work")
102 };
103 history_file.push("history.txt");
104 let mut pkg_config_file = home_dir.clone();
105 pkg_config_file.push("pkg.toml");
106 let bin_path = Self::path_from(bin_path, "UNLAB_GPU_BIN_PATH", "UNLAB_GPU_WORK_BIN_PATH", &home_dir, "bin", is_work_dir);
107 let lib_path = Self::path_from(lib_path, "UNLAB_GPU_LIB_PATH", "UNLAB_GPU_WORK_LIB_PATH", &home_dir, "lib", is_work_dir);
108 let doc_path = Self::path_from(doc_path, "UNLAB_GPU_DOC_PATH", "UNLAB_GPU_WORK_DOC_PATH", &home_dir, "doc", is_work_dir);
109 Some(Home {
110 home_dir,
111 backend_config_file,
112 history_file,
113 pkg_config_file,
114 bin_path,
115 lib_path,
116 doc_path,
117 })
118 }
119
120 pub fn home_dir(&self) -> &Path
122 { self.home_dir.as_path() }
123
124 pub fn backend_config_file(&self) -> &Path
126 { self.backend_config_file.as_path() }
127
128 pub fn history_file(&self) -> &Path
130 { self.history_file.as_path() }
131
132 pub fn pkg_config_file(&self) -> &Path
134 { self.pkg_config_file.as_path() }
135
136 pub fn bin_path(&self) -> &OsStr
138 { self.bin_path.as_os_str() }
139
140 pub fn lib_path(&self) -> &OsStr
142 { self.lib_path.as_os_str() }
143
144 pub fn doc_path(&self) -> &OsStr
146 { self.doc_path.as_os_str() }
147
148 fn add_dirs_to_path(path: &mut OsString, dirs: &[String]) -> Result<(), JoinPathsError>
149 {
150 if !dirs.is_empty() {
151 let mut tmp_dirs: Vec<OsString> = dirs.iter().map(|d| OsString::from(d)).collect();
152 let mut tmp_dirs_from_path: Vec<OsString> = split_paths(path).map(|d| d.into_os_string()).collect();
153 tmp_dirs.reverse();
154 tmp_dirs.append(&mut tmp_dirs_from_path);
155 *path = join_paths(tmp_dirs)?;
156 }
157 Ok(())
158 }
159
160 pub fn add_dirs_to_bin_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
165 { Self::add_dirs_to_path(&mut self.bin_path, dirs) }
166
167 pub fn add_dirs_to_lib_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
171 { Self::add_dirs_to_path(&mut self.lib_path, dirs) }
172
173 pub fn add_dirs_to_doc_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
177 { Self::add_dirs_to_path(&mut self.doc_path, dirs) }
178}