aboutsummaryrefslogtreecommitdiff
path: root/crates/vfs/src/vfs_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/vfs/src/vfs_path.rs')
-rw-r--r--crates/vfs/src/vfs_path.rs39
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
4use paths::{AbsPath, AbsPathBuf}; 4use 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)]
9pub struct VfsPath(VfsPathRepr); 13pub struct VfsPath(VfsPathRepr);
10 14
11impl VfsPath { 15impl 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((