xvc_walker/
abspath.rs

1//! An absolute path type to ensure that we don't use relative paths.
2use std::ffi::OsString;
3use std::fmt::Display;
4use std::ops::Deref;
5use std::path::{Path, PathBuf};
6
7/// A specialized path type for absolute paths.
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct AbsolutePath(PathBuf);
10
11impl From<PathBuf> for AbsolutePath {
12    fn from(p: PathBuf) -> Self {
13        if p.is_absolute() {
14            Self(p)
15        } else {
16            let current_dir = std::env::current_dir().expect("Cannot determine current dir");
17            let joined = current_dir.join(p);
18            Self(
19                joined
20                    .canonicalize()
21                    .unwrap_or_else(|_| panic!("Cannot canonicalize {:?}", joined)),
22            )
23        }
24    }
25}
26
27impl Display for AbsolutePath {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        write!(f, "{}", self.0.to_string_lossy())
30    }
31}
32
33impl AbsolutePath {
34    /// Convert to OsString by cloning the inner value
35    pub fn into_os_string(&self) -> OsString {
36        self.0.clone().as_os_str().to_os_string()
37    }
38
39    /// Get reference to inner value
40    pub fn as_path(&self) -> &Path {
41        &self.0
42    }
43
44    /// Appends a relative path to this path to get another absolute path
45    pub fn join<T>(&self, p: T) -> AbsolutePath
46    where
47        T: AsRef<Path>,
48    {
49        assert!(!p.as_ref().is_absolute());
50        Self(self.0.join(p))
51    }
52}
53
54impl From<&PathBuf> for AbsolutePath {
55    fn from(p: &PathBuf) -> Self {
56        Self::from(p.to_owned())
57    }
58}
59
60impl From<&Path> for AbsolutePath {
61    fn from(p: &Path) -> Self {
62        Self::from(p.to_path_buf())
63    }
64}
65
66impl From<AbsolutePath> for PathBuf {
67    fn from(a: AbsolutePath) -> Self {
68        a.0
69    }
70}
71
72impl From<&str> for AbsolutePath {
73    fn from(s: &str) -> Self {
74        Self::from(PathBuf::from(s.to_string()))
75    }
76}
77
78impl From<String> for AbsolutePath {
79    fn from(s: String) -> Self {
80        Self::from(PathBuf::from(s))
81    }
82}
83
84impl Deref for AbsolutePath {
85    type Target = Path;
86
87    fn deref(&self) -> &Self::Target {
88        &self.0
89    }
90}
91
92impl AsRef<Path> for AbsolutePath {
93    fn as_ref(&self) -> &Path {
94        self.0.as_path()
95    }
96}