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 = home_dir.clone();
99 history_file.push("history.txt");
100 let mut pkg_config_file = home_dir.clone();
101 pkg_config_file.push("pkg.toml");
102 let bin_path = Self::path_from(bin_path, "UNLAB_GPU_BIN_PATH", "UNLAB_GPU_WORK_BIN_PATH", &home_dir, "bin", is_work_dir);
103 let lib_path = Self::path_from(lib_path, "UNLAB_GPU_LIB_PATH", "UNLAB_GPU_WORK_LIB_PATH", &home_dir, "lib", is_work_dir);
104 let doc_path = Self::path_from(doc_path, "UNLAB_GPU_DOC_PATH", "UNLAB_GPU_WORK_DOC_PATH", &home_dir, "doc", is_work_dir);
105 Some(Home {
106 home_dir,
107 backend_config_file,
108 history_file,
109 pkg_config_file,
110 bin_path,
111 lib_path,
112 doc_path,
113 })
114 }
115
116 pub fn home_dir(&self) -> &Path
118 { self.home_dir.as_path() }
119
120 pub fn backend_config_file(&self) -> &Path
122 { self.backend_config_file.as_path() }
123
124 pub fn history_file(&self) -> &Path
126 { self.history_file.as_path() }
127
128 pub fn pkg_config_file(&self) -> &Path
130 { self.pkg_config_file.as_path() }
131
132 pub fn bin_path(&self) -> &OsStr
134 { self.bin_path.as_os_str() }
135
136 pub fn lib_path(&self) -> &OsStr
138 { self.lib_path.as_os_str() }
139
140 pub fn doc_path(&self) -> &OsStr
142 { self.doc_path.as_os_str() }
143
144 fn add_dirs_to_path(path: &mut OsString, dirs: &[String]) -> Result<(), JoinPathsError>
145 {
146 if !dirs.is_empty() {
147 let mut tmp_dirs: Vec<OsString> = dirs.iter().map(|d| OsString::from(d)).collect();
148 let mut tmp_dirs_from_path: Vec<OsString> = split_paths(path).map(|d| d.into_os_string()).collect();
149 tmp_dirs.reverse();
150 tmp_dirs.append(&mut tmp_dirs_from_path);
151 *path = join_paths(tmp_dirs)?;
152 }
153 Ok(())
154 }
155
156 pub fn add_dirs_to_bin_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
161 { Self::add_dirs_to_path(&mut self.bin_path, dirs) }
162
163 pub fn add_dirs_to_lib_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
167 { Self::add_dirs_to_path(&mut self.lib_path, dirs) }
168
169 pub fn add_dirs_to_doc_path(&mut self, dirs: &[String]) -> Result<(), JoinPathsError>
173 { Self::add_dirs_to_path(&mut self.doc_path, dirs) }
174}