aboutsummaryrefslogtreecommitdiff
path: root/crates/vfs/src/file_set.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/vfs/src/file_set.rs')
-rw-r--r--crates/vfs/src/file_set.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 49ca593ac..0a4590c8d 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -9,6 +9,7 @@ use rustc_hash::FxHashMap;
9 9
10use crate::{AnchoredPath, FileId, Vfs, VfsPath}; 10use crate::{AnchoredPath, FileId, Vfs, VfsPath};
11 11
12/// A set of [`VfsPath`]s identified by [`FileId`]s.
12#[derive(Default, Clone, Eq, PartialEq)] 13#[derive(Default, Clone, Eq, PartialEq)]
13pub struct FileSet { 14pub struct FileSet {
14 files: FxHashMap<VfsPath, FileId>, 15 files: FxHashMap<VfsPath, FileId>,
@@ -16,9 +17,15 @@ pub struct FileSet {
16} 17}
17 18
18impl FileSet { 19impl FileSet {
20 /// Returns the number of stored paths.
19 pub fn len(&self) -> usize { 21 pub fn len(&self) -> usize {
20 self.files.len() 22 self.files.len()
21 } 23 }
24
25 /// Get the id of the file corresponding to `path`.
26 ///
27 /// If either `path`'s [`anchor`](AnchoredPath::anchor) or the resolved path is not in
28 /// the set, returns [`None`].
22 pub fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> { 29 pub fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
23 let mut base = self.paths[&path.anchor].clone(); 30 let mut base = self.paths[&path.anchor].clone();
24 base.pop(); 31 base.pop();
@@ -26,19 +33,26 @@ impl FileSet {
26 self.files.get(&path).copied() 33 self.files.get(&path).copied()
27 } 34 }
28 35
36 /// Get the id corresponding to `path` if it exists in the set.
29 pub fn file_for_path(&self, path: &VfsPath) -> Option<&FileId> { 37 pub fn file_for_path(&self, path: &VfsPath) -> Option<&FileId> {
30 self.files.get(path) 38 self.files.get(path)
31 } 39 }
32 40
41 /// Get the path corresponding to `file` if it exists in the set.
33 pub fn path_for_file(&self, file: &FileId) -> Option<&VfsPath> { 42 pub fn path_for_file(&self, file: &FileId) -> Option<&VfsPath> {
34 self.paths.get(file) 43 self.paths.get(file)
35 } 44 }
36 45
46 /// Insert the `file_id, path` pair into the set.
47 ///
48 /// # Note
49 /// Multiple [`FileId`] can be mapped to the same [`VfsPath`], and vice-versa.
37 pub fn insert(&mut self, file_id: FileId, path: VfsPath) { 50 pub fn insert(&mut self, file_id: FileId, path: VfsPath) {
38 self.files.insert(path.clone(), file_id); 51 self.files.insert(path.clone(), file_id);
39 self.paths.insert(file_id, path); 52 self.paths.insert(file_id, path);
40 } 53 }
41 54
55 /// Iterate over this set's ids.
42 pub fn iter(&self) -> impl Iterator<Item = FileId> + '_ { 56 pub fn iter(&self) -> impl Iterator<Item = FileId> + '_ {
43 self.paths.keys().copied() 57 self.paths.keys().copied()
44 } 58 }
@@ -50,9 +64,31 @@ impl fmt::Debug for FileSet {
50 } 64 }
51} 65}
52 66
67/// This contains path prefixes to partition a [`Vfs`] into [`FileSet`]s.
68///
69/// # Example
70/// ```rust
71/// # use vfs::{file_set::FileSetConfigBuilder, VfsPath, Vfs};
72/// let mut builder = FileSetConfigBuilder::default();
73/// builder.add_file_set(vec![VfsPath::new_virtual_path("/src".to_string())]);
74/// let config = builder.build();
75/// let mut file_system = Vfs::default();
76/// file_system.set_file_contents(VfsPath::new_virtual_path("/src/main.rs".to_string()), Some(vec![]));
77/// file_system.set_file_contents(VfsPath::new_virtual_path("/src/lib.rs".to_string()), Some(vec![]));
78/// file_system.set_file_contents(VfsPath::new_virtual_path("/build.rs".to_string()), Some(vec![]));
79/// // contains the sets :
80/// // { "/src/main.rs", "/src/lib.rs" }
81/// // { "build.rs" }
82/// let sets = config.partition(&file_system);
83/// ```
53#[derive(Debug)] 84#[derive(Debug)]
54pub struct FileSetConfig { 85pub struct FileSetConfig {
86 /// Number of sets that `self` can partition a [`Vfs`] into.
87 ///
88 /// This should be the number of sets in `self.map` + 1 for files that don't fit in any
89 /// defined set.
55 n_file_sets: usize, 90 n_file_sets: usize,
91 /// Map from encoded paths to the set they belong to.
56 map: fst::Map<Vec<u8>>, 92 map: fst::Map<Vec<u8>>,
57} 93}
58 94
@@ -63,9 +99,14 @@ impl Default for FileSetConfig {
63} 99}
64 100
65impl FileSetConfig { 101impl FileSetConfig {
102 /// Returns a builder for `FileSetConfig`.
66 pub fn builder() -> FileSetConfigBuilder { 103 pub fn builder() -> FileSetConfigBuilder {
67 FileSetConfigBuilder::default() 104 FileSetConfigBuilder::default()
68 } 105 }
106
107 /// Partition `vfs` into `FileSet`s.
108 ///
109 /// Creates a new [`FileSet`] for every set of prefixes in `self`.
69 pub fn partition(&self, vfs: &Vfs) -> Vec<FileSet> { 110 pub fn partition(&self, vfs: &Vfs) -> Vec<FileSet> {
70 let mut scratch_space = Vec::new(); 111 let mut scratch_space = Vec::new();
71 let mut res = vec![FileSet::default(); self.len()]; 112 let mut res = vec![FileSet::default(); self.len()];
@@ -75,9 +116,15 @@ impl FileSetConfig {
75 } 116 }
76 res 117 res
77 } 118 }
119
120 /// Number of sets that `self` can partition a [`Vfs`] into.
78 fn len(&self) -> usize { 121 fn len(&self) -> usize {
79 self.n_file_sets 122 self.n_file_sets
80 } 123 }
124
125 /// Returns the set index for the given `path`.
126 ///
127 /// `scratch_space` is used as a buffer and will be entirely replaced.
81 fn classify(&self, path: &VfsPath, scratch_space: &mut Vec<u8>) -> usize { 128 fn classify(&self, path: &VfsPath, scratch_space: &mut Vec<u8>) -> usize {
82 scratch_space.clear(); 129 scratch_space.clear();
83 path.encode(scratch_space); 130 path.encode(scratch_space);
@@ -91,6 +138,7 @@ impl FileSetConfig {
91 } 138 }
92} 139}
93 140
141/// Builder for [`FileSetConfig`].
94pub struct FileSetConfigBuilder { 142pub struct FileSetConfigBuilder {
95 roots: Vec<Vec<VfsPath>>, 143 roots: Vec<Vec<VfsPath>>,
96} 144}
@@ -102,12 +150,17 @@ impl Default for FileSetConfigBuilder {
102} 150}
103 151
104impl FileSetConfigBuilder { 152impl FileSetConfigBuilder {
153 /// Returns the number of sets currently held.
105 pub fn len(&self) -> usize { 154 pub fn len(&self) -> usize {
106 self.roots.len() 155 self.roots.len()
107 } 156 }
157
158 /// Add a new set of paths prefixes.
108 pub fn add_file_set(&mut self, roots: Vec<VfsPath>) { 159 pub fn add_file_set(&mut self, roots: Vec<VfsPath>) {
109 self.roots.push(roots) 160 self.roots.push(roots)
110 } 161 }
162
163 /// Build the `FileSetConfig`.
111 pub fn build(self) -> FileSetConfig { 164 pub fn build(self) -> FileSetConfig {
112 let n_file_sets = self.roots.len() + 1; 165 let n_file_sets = self.roots.len() + 1;
113 let map = { 166 let map = {
@@ -127,11 +180,15 @@ impl FileSetConfigBuilder {
127 } 180 }
128} 181}
129 182
183/// Implements [`fst::Automaton`]
184///
185/// It will match if `prefix_of` is a prefix of the given data.
130struct PrefixOf<'a> { 186struct PrefixOf<'a> {
131 prefix_of: &'a [u8], 187 prefix_of: &'a [u8],
132} 188}
133 189
134impl<'a> PrefixOf<'a> { 190impl<'a> PrefixOf<'a> {
191 /// Creates a new `PrefixOf` from the given slice.
135 fn new(prefix_of: &'a [u8]) -> Self { 192 fn new(prefix_of: &'a [u8]) -> Self {
136 Self { prefix_of } 193 Self { prefix_of }
137 } 194 }