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.rs51
1 files changed, 50 insertions, 1 deletions
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs
index de5dc0bf3..0a8a86c62 100644
--- a/crates/vfs/src/vfs_path.rs
+++ b/crates/vfs/src/vfs_path.rs
@@ -9,9 +9,17 @@ use paths::{AbsPath, AbsPathBuf};
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,11 +28,24 @@ 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}
@@ -32,11 +53,12 @@ impl VfsPath {
32#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] 53#[derive(Debug, 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,33 @@ 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
74#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
75struct VirtualPath(String);
76
77impl VirtualPath {
78 fn starts_with(&self, other: &VirtualPath) -> bool {
79 self.0.starts_with(&other.0)
80 }
81 fn pop(&mut self) -> bool {
82 let pos = match self.0.rfind('/') {
83 Some(pos) => pos,
84 None => return false,
85 };
86 self.0 = self.0[..pos].to_string();
87 true
88 }
89 fn join(&self, mut path: &str) -> VirtualPath {
90 let mut res = self.clone();
91 while path.starts_with("../") {
92 assert!(res.pop());
93 path = &path["../".len()..]
47 } 94 }
95 res.0 = format!("{}/{}", res.0, path);
96 res
48 } 97 }
49} 98}