diff options
Diffstat (limited to 'crates/vfs/src/vfs_path.rs')
-rw-r--r-- | crates/vfs/src/vfs_path.rs | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs index bd14911c9..74b6333e2 100644 --- a/crates/vfs/src/vfs_path.rs +++ b/crates/vfs/src/vfs_path.rs | |||
@@ -3,25 +3,37 @@ use std::fmt; | |||
3 | 3 | ||
4 | use paths::{AbsPath, AbsPathBuf}; | 4 | use paths::{AbsPath, AbsPathBuf}; |
5 | 5 | ||
6 | /// Path in [`Vfs`]. | ||
7 | /// | ||
6 | /// Long-term, we want to support files which do not reside in the file-system, | 8 | /// Long-term, we want to support files which do not reside in the file-system, |
7 | /// so we treat VfsPaths as opaque identifiers. | 9 | /// so we treat `VfsPath`s as opaque identifiers. |
10 | /// | ||
11 | /// [`Vfs`]: crate::Vfs | ||
8 | #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] | 12 | #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] |
9 | pub struct VfsPath(VfsPathRepr); | 13 | pub struct VfsPath(VfsPathRepr); |
10 | 14 | ||
11 | impl VfsPath { | 15 | impl VfsPath { |
12 | /// Creates an "in-memory" path from `/`-separates string. | 16 | /// Creates an "in-memory" path from `/`-separated string. |
17 | /// | ||
13 | /// This is most useful for testing, to avoid windows/linux differences | 18 | /// This is most useful for testing, to avoid windows/linux differences |
19 | /// | ||
20 | /// # Panics | ||
21 | /// | ||
22 | /// Panics if `path` does not start with `'/'`. | ||
14 | pub fn new_virtual_path(path: String) -> VfsPath { | 23 | pub fn new_virtual_path(path: String) -> VfsPath { |
15 | assert!(path.starts_with('/')); | 24 | assert!(path.starts_with('/')); |
16 | VfsPath(VfsPathRepr::VirtualPath(VirtualPath(path))) | 25 | VfsPath(VfsPathRepr::VirtualPath(VirtualPath(path))) |
17 | } | 26 | } |
18 | 27 | ||
28 | /// Returns the `AbsPath` representation of `self` if `self` is on the file system. | ||
19 | pub fn as_path(&self) -> Option<&AbsPath> { | 29 | pub fn as_path(&self) -> Option<&AbsPath> { |
20 | match &self.0 { | 30 | match &self.0 { |
21 | VfsPathRepr::PathBuf(it) => Some(it.as_path()), | 31 | VfsPathRepr::PathBuf(it) => Some(it.as_path()), |
22 | VfsPathRepr::VirtualPath(_) => None, | 32 | VfsPathRepr::VirtualPath(_) => None, |
23 | } | 33 | } |
24 | } | 34 | } |
35 | |||
36 | /// Creates a new `VfsPath` with `path` adjoined to `self`. | ||
25 | pub fn join(&self, path: &str) -> Option<VfsPath> { | 37 | pub fn join(&self, path: &str) -> Option<VfsPath> { |
26 | match &self.0 { | 38 | match &self.0 { |
27 | VfsPathRepr::PathBuf(it) => { | 39 | VfsPathRepr::PathBuf(it) => { |
@@ -34,12 +46,30 @@ impl VfsPath { | |||
34 | } | 46 | } |
35 | } | 47 | } |
36 | } | 48 | } |
49 | |||
50 | /// Remove the last component of `self` if there is one. | ||
51 | /// | ||
52 | /// If `self` has no component, returns `false`; else returns `true`. | ||
53 | /// | ||
54 | /// # Example | ||
55 | /// | ||
56 | /// ``` | ||
57 | /// # use vfs::{AbsPathBuf, VfsPath}; | ||
58 | /// let mut path = VfsPath::from(AbsPathBuf::assert("/foo/bar".into())); | ||
59 | /// assert!(path.pop()); | ||
60 | /// assert_eq!(path, VfsPath::from(AbsPathBuf::assert("/foo".into()))); | ||
61 | /// assert!(path.pop()); | ||
62 | /// assert_eq!(path, VfsPath::from(AbsPathBuf::assert("/".into()))); | ||
63 | /// assert!(!path.pop()); | ||
64 | /// ``` | ||
37 | pub fn pop(&mut self) -> bool { | 65 | pub fn pop(&mut self) -> bool { |
38 | match &mut self.0 { | 66 | match &mut self.0 { |
39 | VfsPathRepr::PathBuf(it) => it.pop(), | 67 | VfsPathRepr::PathBuf(it) => it.pop(), |
40 | VfsPathRepr::VirtualPath(it) => it.pop(), | 68 | VfsPathRepr::VirtualPath(it) => it.pop(), |
41 | } | 69 | } |
42 | } | 70 | } |
71 | |||
72 | /// Returns `true` if `other` is a prefix of `self`. | ||
43 | pub fn starts_with(&self, other: &VfsPath) -> bool { | 73 | pub fn starts_with(&self, other: &VfsPath) -> bool { |
44 | match (&self.0, &other.0) { | 74 | match (&self.0, &other.0) { |
45 | (VfsPathRepr::PathBuf(lhs), VfsPathRepr::PathBuf(rhs)) => lhs.starts_with(rhs), | 75 | (VfsPathRepr::PathBuf(lhs), VfsPathRepr::PathBuf(rhs)) => lhs.starts_with(rhs), |
@@ -48,6 +78,10 @@ impl VfsPath { | |||
48 | (VfsPathRepr::VirtualPath(_), _) => false, | 78 | (VfsPathRepr::VirtualPath(_), _) => false, |
49 | } | 79 | } |
50 | } | 80 | } |
81 | |||
82 | /// Returns the `VfsPath` without its final component, if there is one. | ||
83 | /// | ||
84 | /// Returns [`None`] if the path is a root or prefix. | ||
51 | pub fn parent(&self) -> Option<VfsPath> { | 85 | pub fn parent(&self) -> Option<VfsPath> { |
52 | let mut parent = self.clone(); | 86 | let mut parent = self.clone(); |
53 | if parent.pop() { | 87 | if parent.pop() { |
@@ -57,6 +91,7 @@ impl VfsPath { | |||
57 | } | 91 | } |
58 | } | 92 | } |
59 | 93 | ||
94 | /// Returns `self`'s base name and file extension. | ||
60 | pub fn name_and_extension(&self) -> Option<(&str, Option<&str>)> { | 95 | pub fn name_and_extension(&self) -> Option<(&str, Option<&str>)> { |
61 | match &self.0 { | 96 | match &self.0 { |
62 | VfsPathRepr::PathBuf(p) => Some(( | 97 | VfsPathRepr::PathBuf(p) => Some(( |