summaryrefslogtreecommitdiff
path: root/src/devices/file/directory_listing.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2024-08-07 17:09:14 +1200
committerBen Bridle <ben@derelict.engineering>2024-08-07 17:09:14 +1200
commit38d40a2c5d4b553f524d87755b8e2e0e47928b8a (patch)
tree01fd01820be4219ca9f3dc7ad6e61eb183ade963 /src/devices/file/directory_listing.rs
parent65b53003e8de9543ba25a3b3d3cace399b92dc1d (diff)
downloadbedrock-pc-38d40a2c5d4b553f524d87755b8e2e0e47928b8a.zip
Refactor the file device
This is the Windows side of the refactoring job. The windows crate has been added as a dependency in order to get a list of available drives by drive letter, and a virtual top-level root directory has been implemented in the Windows code to make it possible for programs to hierarchically navigate between available drives.
Diffstat (limited to 'src/devices/file/directory_listing.rs')
-rw-r--r--src/devices/file/directory_listing.rs76
1 files changed, 49 insertions, 27 deletions
diff --git a/src/devices/file/directory_listing.rs b/src/devices/file/directory_listing.rs
index 0cbbde9..febc5c2 100644
--- a/src/devices/file/directory_listing.rs
+++ b/src/devices/file/directory_listing.rs
@@ -2,12 +2,13 @@ use super::*;
pub struct DirectoryListing {
- children: Vec<DirectoryChild>,
+ children: Vec<BedrockFilePath>,
length: u32,
selected: Option<u32>,
name_buffer: CircularPathBuffer,
}
+
impl DirectoryListing {
pub fn from_path(path: &BedrockFilePath) -> Option<Self> {
macro_rules! unres {
@@ -17,32 +18,29 @@ impl DirectoryListing {
($option:expr) => { match $option { Some(v) => v, None => continue} };
}
- let mut children = Vec::new();
- let dir_listing = std::fs::read_dir(path.as_path()).ok()?;
- for (i, entry_result) in dir_listing.enumerate() {
- // Firebreak to prevent emulator from consuming an absurd amount
- // of memory when opening too large of a directory.
- if i == (u16::MAX as usize) {
- break;
+ #[cfg(target_family = "windows")] {
+ if path.as_path().components().count() == 0 {
+ return Some(Self::construct_virtual_root())
}
+ }
- let entry = unres!(entry_result);
- let entry_path = unopt!(BedrockFilePath::from_path(&entry.path(), path.base()));
- if entry_path.filename_is_dot_prefixed() {
- continue;
- }
- let metadata = unres!(std::fs::metadata(&entry.path()));
- let entry_type =
- if metadata.is_file() {
- EntryType::File
- } else if metadata.is_dir() {
- EntryType::Directory
- } else {
+ let mut children = Vec::new();
+ if let Ok(dir_listing) = std::fs::read_dir(path.as_path()) {
+ for (i, entry_result) in dir_listing.enumerate() {
+ // Firebreak to prevent emulator from consuming an absurd amount
+ // of memory when opening too large of a directory.
+ if i == (u16::MAX as usize) {
+ break;
+ }
+
+ let entry = unres!(entry_result);
+ let entry_path = unopt!(BedrockFilePath::from_path(&entry.path(), path.base()));
+ if entry_path.is_hidden() {
continue;
- };
+ }
- let child = DirectoryChild { path: entry_path, entry_type };
- children.push(child);
+ children.push(entry_path);
+ }
}
children.sort();
@@ -52,8 +50,32 @@ impl DirectoryListing {
Some( Self { children, length, selected, name_buffer } )
}
+ /// Generate entries for a virtual root directory.
+ #[cfg(target_family = "windows")]
+ fn construct_virtual_root() -> Self {
+ let mut children = Vec::new();
+ let base = PathBuf::from("");
+ let drive_bits = unsafe {
+ windows::Win32::Storage::FileSystem::GetLogicalDrives()
+ };
+ for i in 0..26 {
+ if drive_bits & (0x1 << i) != 0 {
+ let letter: char = (b'A' + i).into();
+ let path = PathBuf::from(format!("{letter}:/"));
+ if let Some(drive) = BedrockFilePath::from_path(&path, &base) {
+ children.push(drive);
+ }
+ }
+ }
+
+ let length = children.len() as u32;
+ let selected = None;
+ let name_buffer = CircularPathBuffer::new();
+ Self { children, length, selected, name_buffer }
+ }
+
/// Attempts to return a directory child by index.
- pub fn get(&self, index: u32) -> Option<&DirectoryChild> {
+ pub fn get(&self, index: u32) -> Option<&BedrockFilePath> {
self.children.get(index as usize)
}
@@ -69,7 +91,7 @@ impl DirectoryListing {
/// Attempts to select a child by index.
pub fn set_selected(&mut self, index: u32) {
if let Some(child) = self.get(index) {
- let buffer = child.path.as_buffer();
+ let buffer = child.as_buffer();
self.name_buffer.populate(buffer);
self.selected = Some(index);
} else {
@@ -83,11 +105,11 @@ impl DirectoryListing {
}
pub fn child_type(&self) -> Option<EntryType> {
- self.selected.and_then(|s| self.get(s).and_then(|i| Some(i.entry_type)))
+ self.selected.and_then(|s| self.get(s).and_then(|i| i.entry_type()))
}
pub fn child_path(&self) -> Option<BedrockFilePath> {
- self.selected.and_then(|s| self.get(s).and_then(|i| Some(i.path.clone())))
+ self.selected.and_then(|s| self.get(s).and_then(|i| Some(i.clone())))
}
}