1use std::{
2 env::{current_dir, current_exe},
3 path::{MAIN_SEPARATOR, Path, PathBuf},
4 sync::{Arc, LazyLock},
5};
6
7use path_clean::PathClean;
8
9static CWD: LazyLock<Arc<Path>> = LazyLock::new(create_cwd);
10static EXE: LazyLock<Arc<Path>> = LazyLock::new(create_exe);
11
12fn create_cwd() -> Arc<Path> {
13 let mut cwd = current_dir()
14 .expect("failed to find current working directory")
15 .to_str()
16 .expect("current working directory is not valid UTF-8")
17 .to_string();
18 if !cwd.ends_with(MAIN_SEPARATOR) {
19 cwd.push(MAIN_SEPARATOR);
20 }
21 dunce::canonicalize(cwd)
22 .expect("failed to canonicalize current working directory")
23 .into()
24}
25
26fn create_exe() -> Arc<Path> {
27 let exe = current_exe()
28 .expect("failed to find current executable")
29 .to_str()
30 .expect("current executable path is not valid UTF-8")
31 .to_string();
32 dunce::canonicalize(exe)
33 .expect("failed to canonicalize current executable path")
34 .into()
35}
36
37#[must_use]
49pub fn get_current_dir() -> Arc<Path> {
50 Arc::clone(&CWD)
51}
52
53#[must_use]
64pub fn get_current_exe() -> Arc<Path> {
65 Arc::clone(&EXE)
66}
67
68pub fn clean_path(path: impl AsRef<Path>) -> PathBuf {
74 path.as_ref().clean()
75}
76
77pub fn clean_path_and_make_absolute(path: impl AsRef<Path>) -> PathBuf {
85 let path = path.as_ref();
86 if path.is_relative() {
87 CWD.join(path).clean()
88 } else {
89 path.clean()
90 }
91}