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.rs70
1 files changed, 67 insertions, 3 deletions
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs
index de5dc0bf3..940f91d0e 100644
--- a/crates/vfs/src/vfs_path.rs
+++ b/crates/vfs/src/vfs_path.rs
@@ -5,13 +5,21 @@ use paths::{AbsPath, AbsPathBuf};
5 5
6/// Long-term, we want to support files which do not reside in the file-system, 6/// Long-term, we want to support files which do not reside in the file-system,
7/// so we treat VfsPaths as opaque identifiers. 7/// so we treat VfsPaths as opaque identifiers.
8#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] 8#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
9pub struct VfsPath(VfsPathRepr); 9pub struct VfsPath(VfsPathRepr);
10 10
11impl VfsPath { 11impl VfsPath {
12 /// Creates an "in-memory" path from `/`-separates string.
13 /// This is most useful for testing, to avoid windows/linux differences
14 pub fn new_virtual_path(path: String) -> VfsPath {
15 assert!(path.starts_with('/'));
16 VfsPath(VfsPathRepr::VirtualPath(VirtualPath(path)))
17 }
18
12 pub fn as_path(&self) -> Option<&AbsPath> { 19 pub fn as_path(&self) -> Option<&AbsPath> {
13 match &self.0 { 20 match &self.0 {
14 VfsPathRepr::PathBuf(it) => Some(it.as_path()), 21 VfsPathRepr::PathBuf(it) => Some(it.as_path()),
22 VfsPathRepr::VirtualPath(_) => None,
15 } 23 }
16 } 24 }
17 pub fn join(&self, path: &str) -> VfsPath { 25 pub fn join(&self, path: &str) -> VfsPath {
@@ -20,23 +28,37 @@ impl VfsPath {
20 let res = it.join(path).normalize(); 28 let res = it.join(path).normalize();
21 VfsPath(VfsPathRepr::PathBuf(res)) 29 VfsPath(VfsPathRepr::PathBuf(res))
22 } 30 }
31 VfsPathRepr::VirtualPath(it) => {
32 let res = it.join(path);
33 VfsPath(VfsPathRepr::VirtualPath(res))
34 }
23 } 35 }
24 } 36 }
25 pub fn pop(&mut self) -> bool { 37 pub fn pop(&mut self) -> bool {
26 match &mut self.0 { 38 match &mut self.0 {
27 VfsPathRepr::PathBuf(it) => it.pop(), 39 VfsPathRepr::PathBuf(it) => it.pop(),
40 VfsPathRepr::VirtualPath(it) => it.pop(),
41 }
42 }
43 pub fn starts_with(&self, other: &VfsPath) -> bool {
44 match (&self.0, &other.0) {
45 (VfsPathRepr::PathBuf(lhs), VfsPathRepr::PathBuf(rhs)) => lhs.starts_with(rhs),
46 (VfsPathRepr::PathBuf(_), _) => false,
47 (VfsPathRepr::VirtualPath(lhs), VfsPathRepr::VirtualPath(rhs)) => lhs.starts_with(rhs),
48 (VfsPathRepr::VirtualPath(_), _) => false,
28 } 49 }
29 } 50 }
30} 51}
31 52
32#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] 53#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
33enum VfsPathRepr { 54enum VfsPathRepr {
34 PathBuf(AbsPathBuf), 55 PathBuf(AbsPathBuf),
56 VirtualPath(VirtualPath),
35} 57}
36 58
37impl From<AbsPathBuf> for VfsPath { 59impl From<AbsPathBuf> for VfsPath {
38 fn from(v: AbsPathBuf) -> Self { 60 fn from(v: AbsPathBuf) -> Self {
39 VfsPath(VfsPathRepr::PathBuf(v)) 61 VfsPath(VfsPathRepr::PathBuf(v.normalize()))
40 } 62 }
41} 63}
42 64
@@ -44,6 +66,48 @@ impl fmt::Display for VfsPath {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match &self.0 { 67 match &self.0 {
46 VfsPathRepr::PathBuf(it) => fmt::Display::fmt(&it.display(), f), 68 VfsPathRepr::PathBuf(it) => fmt::Display::fmt(&it.display(), f),
69 VfsPathRepr::VirtualPath(VirtualPath(it)) => fmt::Display::fmt(it, f),
70 }
71 }
72}
73
74impl fmt::Debug for VfsPath {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 fmt::Debug::fmt(&self.0, f)
77 }
78}
79
80impl fmt::Debug for VfsPathRepr {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 match &self {
83 VfsPathRepr::PathBuf(it) => fmt::Debug::fmt(&it.display(), f),
84 VfsPathRepr::VirtualPath(VirtualPath(it)) => fmt::Debug::fmt(&it, f),
85 }
86 }
87}
88
89#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
90struct VirtualPath(String);
91
92impl VirtualPath {
93 fn starts_with(&self, other: &VirtualPath) -> bool {
94 self.0.starts_with(&other.0)
95 }
96 fn pop(&mut self) -> bool {
97 let pos = match self.0.rfind('/') {
98 Some(pos) => pos,
99 None => return false,
100 };
101 self.0 = self.0[..pos].to_string();
102 true
103 }
104 fn join(&self, mut path: &str) -> VirtualPath {
105 let mut res = self.clone();
106 while path.starts_with("../") {
107 assert!(res.pop());
108 path = &path["../".len()..]
47 } 109 }
110 res.0 = format!("{}/{}", res.0, path);
111 res
48 } 112 }
49} 113}