Skip to main content

Mountain/IPC/WindServiceHandlers/FileSystem/Native/
FileReaddirNative.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Wire method `file:readdir`. Returns `[[name, fileType]]` matching
4//! VS Code's `ReadDirResult` (`FileType`: File=1, Directory=2,
5//! SymbolicLink=64 - combined via bitflags upstream, but the readdir
6//! callers only care about the per-entry value).
7
8use serde_json::{Value, json};
9
10use crate::{IPC::WindServiceHandlers::Utilities::PathExtraction::extract_path_from_arg, dev_log};
11
12pub async fn FileReaddirNative(Arguments:Vec<Value>) -> Result<Value, String> {
13	let Path = extract_path_from_arg(Arguments.get(0).ok_or("Missing directory path")?)?;
14
15	// Emit at the default-visible `vfs` level instead of
16	// `vfs-verbose`: readdir fires at most once per folder expand
17	// (unlike stat which fires per probe), and it is the primary
18	// observable for "is the Explorer view calling through to
19	// Mountain?" diagnostics. The handler itself stays cheap.
20	dev_log!("vfs", "readdir: {}", Path);
21
22	let mut Entries = tokio::fs::read_dir(&Path)
23		.await
24		.map_err(|E| format!("Failed to readdir: {} ({})", Path, E))?;
25
26	let mut Result = Vec::new();
27
28	while let Some(Entry) = Entries.next_entry().await.map_err(|E| E.to_string())? {
29		let Name = Entry.file_name().to_string_lossy().to_string();
30		let FileType = Entry.file_type().await.map_err(|E| E.to_string())?;
31
32		let TypeValue = if FileType.is_symlink() {
33			64
34		} else if FileType.is_dir() {
35			2
36		} else {
37			1
38		};
39
40		Result.push(json!([Name, TypeValue]));
41	}
42
43	Ok(json!(Result))
44}