summaryrefslogtreecommitdiff
path: root/src/devices/file.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2024-10-28 20:25:01 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2024-10-28 20:29:12 +1300
commit1a830a3d1b9d99653322d5ae49ea8165de7ed9d0 (patch)
tree798e77b6fcf2438b1c2538a67efe856a2f7cb979 /src/devices/file.rs
parent03c4b069e1806af256730639cefdae115b24401a (diff)
downloadbedrock-pc-01ba3901441af778d473f44acaee953d185245e7.zip
Rewrite emulatorv1.0.0-alpha1
This is a complete rewrite and restructure of the entire emulator project, as part of the effort in locking down the Bedrock specification and in creating much better tooling for creating and using Bedrock programs. This commit adds a command-line argument scheme, an embedded assembler, a headless emulator for use in non-graphical environments, deferred window creation for programs that do not access the screen device, and new versions of phosphor and bedrock-core. The new version of phosphor supports multi-window programs, which will make it possible to implement program forking in the system device later on, and the new version of bedrock-core implements the final core specification.
Diffstat (limited to 'src/devices/file.rs')
-rw-r--r--src/devices/file.rs288
1 files changed, 0 insertions, 288 deletions
diff --git a/src/devices/file.rs b/src/devices/file.rs
deleted file mode 100644
index 0bea2f4..0000000
--- a/src/devices/file.rs
+++ /dev/null
@@ -1,288 +0,0 @@
-mod bedrock_file_path;
-mod buffered_file;
-mod circular_path_buffer;
-mod directory_listing;
-mod entry;
-mod operations;
-
-pub use bedrock_file_path::*;
-pub use buffered_file::*;
-pub use circular_path_buffer::*;
-pub use directory_listing::*;
-pub use entry::*;
-use operations::*;
-
-use std::path::{Component, Path, PathBuf};
-use std::mem::take;
-
-
-pub struct FileDevice {
- pub base_path: PathBuf,
- pub default_path: PathBuf,
-
- pub open_buffer: CircularPathBuffer,
- pub move_buffer: CircularPathBuffer,
- pub name_buffer: CircularPathBuffer,
-
- pub entry: Option<(Entry, BedrockFilePath)>,
- pub cached_dir: Option<(Entry, BedrockFilePath)>,
-
- pub success: bool,
- pub pointer: u32,
- pub length: u32,
-
- pub enable_read: bool,
- pub enable_write: bool,
- pub enable_create: bool,
- pub enable_move: bool,
- pub enable_delete: bool,
-}
-
-impl FileDevice {
- pub fn new() -> Self {
- #[cfg(target_family = "unix")]
- let default_base: PathBuf = PathBuf::from("/");
- #[cfg(target_family = "windows")]
- let default_base: PathBuf = PathBuf::from("");
-
- Self {
- base_path: default_base,
- default_path: match std::env::current_dir() {
- Ok(dir) => PathBuf::from(dir),
- Err(_) => PathBuf::from(""),
- },
-
- open_buffer: CircularPathBuffer::new(),
- move_buffer: CircularPathBuffer::new(),
- name_buffer: CircularPathBuffer::new(),
-
- entry: None,
- cached_dir: None,
-
- success: false,
- pointer: 0,
- length: 0,
-
- enable_read: true,
- enable_write: true,
- enable_create: true,
- enable_move: true,
- enable_delete: false,
- }
- }
-
- /// Commit any pending writes to the currently-open file.
- pub fn flush_entry(&mut self) {
- if let Some((Entry::File(buffered_file), _)) = &mut self.entry {
- buffered_file.flush();
- }
- }
-
- /// Safely close the currently-open entry, cleaning up entry variables.
- pub fn close_entry(&mut self) {
- self.open_buffer.clear();
- self.move_buffer.clear();
- self.name_buffer.clear();
- self.flush_entry();
- self.pointer = 0;
- self.length = 0;
- if let Some((Entry::Directory(dir), path)) = take(&mut self.entry) {
- self.cached_dir = Some((Entry::Directory(dir), path));
- }
- }
-
- /// Process a byte received from the OPEN port.
- pub fn write_to_open_port(&mut self, byte: u8) {
- if let Some(buffer) = self.open_buffer.push_byte(byte) {
- self.close_entry();
- if let Some(path) = BedrockFilePath::from_buffer(buffer, &self.base_path) {
- self.success = self.open_entry(path).is_ok();
- }
- }
- }
-
- /// Opens the entry at the given path.
- pub fn open_entry(&mut self, path: BedrockFilePath) -> Result<(), ()> {
- match path.entry_type() {
- Some(EntryType::File) => {
- let open_result = std::fs::OpenOptions::new()
- .read(self.enable_read)
- .write(self.enable_write)
- .open(path.as_path());
- // Keep the current entry open if we can't open the new path.
- if let Ok(file) = open_result {
- self.close_entry();
- self.name_buffer.populate(path.as_buffer());
- self.entry = Some((Entry::File(BufferedFile::new(file)), path));
- return Ok(());
- };
- }
- Some(EntryType::Directory) => {
- // Attempt to use the cached directory.
- if let Some((dir, cached_path)) = take(&mut self.cached_dir) {
- if cached_path == path {
- self.close_entry();
- self.name_buffer.populate(cached_path.as_buffer());
- self.entry = Some((dir, cached_path));
- return Ok(());
- }
- }
- // Keep the current entry open if we can't open the new path.
- if let Some(listing) = DirectoryListing::from_path(&path) {
- self.close_entry();
- self.name_buffer.populate(path.as_buffer());
- self.entry = Some((Entry::Directory(listing), path));
- return Ok(());
- };
- }
- // The entry either doesn't exist or is not a file or directory.
- None => (),
- }
- return Err(());
- }
-
- pub fn write_to_move_port(&mut self, byte: u8) {
- if let Some(buffer) = self.move_buffer.push_byte(byte) {
- let blank_destination = buffer[0] == 0x00;
- let destination = BedrockFilePath::from_buffer(buffer, &self.base_path);
- self.success = false;
-
- if let Some((_, source)) = &self.entry {
- if blank_destination {
- if self.enable_delete {
- self.success = delete_entry(&source.as_path());
- }
- } else if let Some(dest) = destination {
- if self.enable_move {
- self.success = move_entry(&source.as_path(), &dest.as_path());
- }
- }
- } else if let Some(dest) = destination {
- if self.enable_create {
- self.success = create_file(&dest.as_path());
- }
- }
-
- self.close_entry();
- }
- }
-
- /// Attempt to open the parent directory of the current entry.
- pub fn ascend_to_parent(&mut self) {
- self.success = false;
- if let Some((_, path)) = &self.entry {
- if let Some(parent_path) = path.parent() {
- self.success = self.open_entry(parent_path).is_ok();
- }
- } else {
- if let Some(default) = BedrockFilePath::from_path(&self.default_path, &self.base_path) {
- self.success = self.open_entry(default).is_ok();
- }
- }
- }
-
- /// Attempt to open the currently-selected child of the current directory.
- pub fn descend_to_child(&mut self) {
- self.success = false;
- if let Some((Entry::Directory(listing), _)) = &self.entry {
- if let Some(child_path) = listing.child_path() {
- self.success = self.open_entry(child_path).is_ok();
- };
- }
- }
-
- pub fn set_name_pointer(&mut self, value: u8) {
- self.name_buffer.set_pointer(value);
- }
-
- /// Returns true if the currently-open entry is a directory.
- pub fn entry_type(&self) -> bool {
- match self.entry {
- Some((Entry::Directory(_), _)) => true,
- _ => false,
- }
- }
-
- /// Reads a byte from the name buffer of the currently-selected child.
- pub fn read_child_name(&mut self) -> u8 {
- if let Some((Entry::Directory(listing), _)) = &mut self.entry {
- listing.child_name().read_byte()
- } else {
- 0
- }
- }
-
- pub fn set_child_name_pointer(&mut self, byte: u8) {
- if let Some((Entry::Directory(listing), _)) = &mut self.entry {
- listing.child_name().set_pointer(byte);
- }
- }
-
- /// Returns true if the currently-selected child is a directory.
- pub fn child_type(&self) -> bool {
- if let Some((Entry::Directory(listing), _)) = &self.entry {
- match listing.child_type() {
- Some(EntryType::Directory) => true,
- Some(EntryType::File) => false,
- None => false,
- }
- } else {
- false
- }
- }
-
- /// Reads a byte from the currently-open file.
- pub fn read_byte(&mut self) -> u8 {
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.read_byte(),
- _ => 0,
- }
- }
-
- /// Writes a byte to the currently-open file.
- pub fn write_byte(&mut self, byte: u8) {
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.write_byte(byte),
- _ => (),
- }
- }
-
- pub fn pointer(&mut self) -> u32 {
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.pointer(),
- Some((Entry::Directory(listing), _)) => listing.selected(),
- _ => 0,
- }
- }
-
- pub fn commit_pointer(&mut self) {
- let pointer = take(&mut self.pointer);
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.set_pointer(pointer),
- Some((Entry::Directory(listing), _)) => listing.set_selected(pointer),
- _ => (),
- }
- }
-
- pub fn length(&mut self) -> u32 {
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.length(),
- Some((Entry::Directory(listing), _)) => listing.length(),
- _ => 0,
- }
- }
-
- pub fn commit_length(&mut self) {
- let length = take(&mut self.length);
- match &mut self.entry {
- Some((Entry::File(buffered_file), _)) => buffered_file.set_length(length),
- _ => (),
- }
- }
-}
-
-impl Drop for FileDevice {
- fn drop(&mut self) {
- self.close_entry();
- }
-}