]> git.lizzy.rs Git - rust.git/blobdiff - crates/paths/src/lib.rs
Merge #4676
[rust.git] / crates / paths / src / lib.rs
index 190c509130250c1bc7e285ecf27852fc9fc7c1c1..1b259682d9fa349ebc68ad37f10d37c3f2167850 100644 (file)
@@ -2,7 +2,7 @@
 //! relative paths.
 use std::{
     convert::{TryFrom, TryInto},
-    io, ops,
+    ops,
     path::{Component, Path, PathBuf},
 };
 
@@ -28,6 +28,12 @@ fn as_ref(&self) -> &Path {
     }
 }
 
+impl AsRef<AbsPath> for AbsPathBuf {
+    fn as_ref(&self) -> &AbsPath {
+        self.as_path()
+    }
+}
+
 impl TryFrom<PathBuf> for AbsPathBuf {
     type Error = PathBuf;
     fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
@@ -45,12 +51,19 @@ fn try_from(path: &str) -> Result<AbsPathBuf, PathBuf> {
     }
 }
 
+impl PartialEq<AbsPath> for AbsPathBuf {
+    fn eq(&self, other: &AbsPath) -> bool {
+        self.as_path() == other
+    }
+}
+
 impl AbsPathBuf {
-    pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
-        path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
+    pub fn assert(path: PathBuf) -> AbsPathBuf {
+        AbsPathBuf::try_from(path)
+            .unwrap_or_else(|path| panic!("expected absolute path, got {}", path.display()))
     }
     pub fn as_path(&self) -> &AbsPath {
-        AbsPath::new_unchecked(self.0.as_path())
+        AbsPath::assert(self.0.as_path())
     }
     pub fn pop(&mut self) -> bool {
         self.0.pop()
@@ -80,21 +93,99 @@ fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
         if !path.is_absolute() {
             return Err(path);
         }
-        Ok(AbsPath::new_unchecked(path))
+        Ok(AbsPath::assert(path))
     }
 }
 
 impl AbsPath {
-    fn new_unchecked(path: &Path) -> &AbsPath {
+    pub fn assert(path: &Path) -> &AbsPath {
+        assert!(path.is_absolute());
         unsafe { &*(path as *const Path as *const AbsPath) }
     }
 
+    pub fn parent(&self) -> Option<&AbsPath> {
+        self.0.parent().map(AbsPath::assert)
+    }
     pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
         self.as_ref().join(path).try_into().unwrap()
     }
     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<RelPathBuf> 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<Path> for RelPathBuf {
+    fn as_ref(&self) -> &Path {
+        self.0.as_path()
+    }
+}
+
+impl TryFrom<PathBuf> for RelPathBuf {
+    type Error = PathBuf;
+    fn try_from(path_buf: PathBuf) -> Result<RelPathBuf, PathBuf> {
+        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, PathBuf> {
+        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<Path> 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