aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_vfs/src/io.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_vfs/src/io.rs')
-rw-r--r--crates/ra_vfs/src/io.rs76
1 files changed, 76 insertions, 0 deletions
diff --git a/crates/ra_vfs/src/io.rs b/crates/ra_vfs/src/io.rs
new file mode 100644
index 000000000..be400bae9
--- /dev/null
+++ b/crates/ra_vfs/src/io.rs
@@ -0,0 +1,76 @@
1use std::{
2 fmt,
3 fs,
4 path::{Path, PathBuf},
5};
6
7use walkdir::{DirEntry, WalkDir};
8use thread_worker::{WorkerHandle};
9use relative_path::RelativePathBuf;
10
11use crate::VfsRoot;
12
13pub(crate) struct Task {
14 pub(crate) root: VfsRoot,
15 pub(crate) path: PathBuf,
16 pub(crate) filter: Box<Fn(&DirEntry) -> bool + Send>,
17}
18
19pub struct TaskResult {
20 pub(crate) root: VfsRoot,
21 pub(crate) files: Vec<(RelativePathBuf, String)>,
22}
23
24impl fmt::Debug for TaskResult {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 f.write_str("TaskResult { ... }")
27 }
28}
29
30pub(crate) type Worker = thread_worker::Worker<Task, TaskResult>;
31
32pub(crate) fn start() -> (Worker, WorkerHandle) {
33 thread_worker::spawn("vfs", 128, |input_receiver, output_sender| {
34 input_receiver
35 .map(handle_task)
36 .for_each(|it| output_sender.send(it))
37 })
38}
39
40fn handle_task(task: Task) -> TaskResult {
41 let Task { root, path, filter } = task;
42 log::debug!("loading {} ...", path.as_path().display());
43 let files = load_root(path.as_path(), &*filter);
44 log::debug!("... loaded {}", path.as_path().display());
45 TaskResult { root, files }
46}
47
48fn load_root(root: &Path, filter: &dyn Fn(&DirEntry) -> bool) -> Vec<(RelativePathBuf, String)> {
49 let mut res = Vec::new();
50 for entry in WalkDir::new(root).into_iter().filter_entry(filter) {
51 let entry = match entry {
52 Ok(entry) => entry,
53 Err(e) => {
54 log::warn!("watcher error: {}", e);
55 continue;
56 }
57 };
58 if !entry.file_type().is_file() {
59 continue;
60 }
61 let path = entry.path();
62 if path.extension().and_then(|os| os.to_str()) != Some("rs") {
63 continue;
64 }
65 let text = match fs::read_to_string(path) {
66 Ok(text) => text,
67 Err(e) => {
68 log::warn!("watcher error: {}", e);
69 continue;
70 }
71 };
72 let path = RelativePathBuf::from_path(path.strip_prefix(root).unwrap()).unwrap();
73 res.push((path.to_owned(), text))
74 }
75 res
76}