fhttp_core/
path_utils.rs

1use std::fmt::Display;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6
7pub fn canonicalize(p: &Path) -> Result<CanonicalizedPathBuf> {
8    fs::canonicalize(p)
9        .with_context(|| format!("error opening file {}", p.to_str().unwrap()))
10        .map(CanonicalizedPathBuf)
11}
12
13#[derive(Debug, Eq, PartialEq, Hash, Clone, Default)]
14pub struct CanonicalizedPathBuf(PathBuf);
15
16impl CanonicalizedPathBuf {
17    pub fn to_str(&self) -> &str {
18        self.0
19            .to_str()
20            .expect("encountered a non-utf8 character in file path!")
21    }
22
23    /// This function may panic, it's intended for test purposes!
24    pub fn join<P: AsRef<Path>>(&self, path: P) -> Self {
25        canonicalize(&self.0.join(path)).unwrap()
26    }
27
28    #[cfg(test)]
29    pub fn path_buf(self) -> PathBuf {
30        self.0
31    }
32
33    pub fn file_name(&self) -> &str {
34        self.0
35            .file_name()
36            .unwrap()
37            .to_str()
38            .expect("encountered a non-utf8 character in file path!")
39    }
40}
41
42impl Display for CanonicalizedPathBuf {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        self.0.display().fmt(f)
45    }
46}
47
48impl AsRef<Path> for CanonicalizedPathBuf {
49    fn as_ref(&self) -> &Path {
50        &self.0
51    }
52}
53
54impl From<CanonicalizedPathBuf> for PathBuf {
55    fn from(cpb: CanonicalizedPathBuf) -> Self {
56        cpb.0
57    }
58}
59
60pub fn get_dependency_path<O: AsRef<Path>>(
61    origin_path: O,
62    path: &str,
63) -> Result<CanonicalizedPathBuf> {
64    let origin_path = origin_path.as_ref();
65    let path = Path::new(path);
66    let ret = if path.is_absolute() {
67        path.to_path_buf()
68    } else if origin_path.is_dir() {
69        origin_path.join(path)
70    } else {
71        origin_path.parent().unwrap().join(path)
72    };
73
74    canonicalize(&ret)
75}
76
77pub trait RelativePath {
78    fn get_dependency_path(&self, path: &str) -> Result<CanonicalizedPathBuf>;
79}
80
81impl<T: AsRef<Path>> RelativePath for T {
82    fn get_dependency_path(&self, path: &str) -> Result<CanonicalizedPathBuf> {
83        get_dependency_path(self.as_ref(), path)
84    }
85}