diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index 190c509130..32267f2e6e 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs @@ -95,6 +95,80 @@ impl AbsPath { pub fn normalize(&self) -> AbsPathBuf { AbsPathBuf(normalize_path(&self.0)) } + pub fn to_path_buf(&self) -> AbsPathBuf { + AbsPathBuf::try_from(self.0.to_path_buf()).unwrap() + } + pub fn strip_prefix(&self, base: &AbsPath) -> Option<&RelPath> { + self.0.strip_prefix(base).ok().map(RelPath::new_unchecked) + } +} + +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct RelPathBuf(PathBuf); + +impl From for PathBuf { + fn from(RelPathBuf(path_buf): RelPathBuf) -> PathBuf { + path_buf + } +} + +impl ops::Deref for RelPathBuf { + type Target = RelPath; + fn deref(&self) -> &RelPath { + self.as_path() + } +} + +impl AsRef for RelPathBuf { + fn as_ref(&self) -> &Path { + self.0.as_path() + } +} + +impl TryFrom for RelPathBuf { + type Error = PathBuf; + fn try_from(path_buf: PathBuf) -> Result { + if !path_buf.is_relative() { + return Err(path_buf); + } + Ok(RelPathBuf(path_buf)) + } +} + +impl TryFrom<&str> for RelPathBuf { + type Error = PathBuf; + fn try_from(path: &str) -> Result { + RelPathBuf::try_from(PathBuf::from(path)) + } +} + +impl RelPathBuf { + pub fn as_path(&self) -> &RelPath { + RelPath::new_unchecked(self.0.as_path()) + } +} + +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] +#[repr(transparent)] +pub struct RelPath(Path); + +impl ops::Deref for RelPath { + type Target = Path; + fn deref(&self) -> &Path { + &self.0 + } +} + +impl AsRef for RelPath { + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl RelPath { + pub fn new_unchecked(path: &Path) -> &RelPath { + unsafe { &*(path as *const Path as *const RelPath) } + } } // https://github.com/rust-lang/cargo/blob/79c769c3d7b4c2cf6a93781575b7f592ef974255/src/cargo/util/paths.rs#L60-L85