summaryrefslogtreecommitdiff
path: root/src/devices/file/buffered_file.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2024-01-31 07:38:50 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2024-01-31 07:39:07 +1300
commit28101de56231252ca0cfa6a9f107b75112c9acad (patch)
treef5c82a6894562bfb8ed8ab94e9345cefaa6fb96b /src/devices/file/buffered_file.rs
parent30d2f099c9edf4f59fbbdd6686988ae7b0622ba2 (diff)
downloadbedrock-pc-28101de56231252ca0cfa6a9f107b75112c9acad.zip
Implement new file device interface
This is a complete redesign of the file device. The most notable addition is the ability to ascend and descend the file tree.
Diffstat (limited to 'src/devices/file/buffered_file.rs')
-rw-r--r--src/devices/file/buffered_file.rs127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/devices/file/buffered_file.rs b/src/devices/file/buffered_file.rs
new file mode 100644
index 0000000..091b5d9
--- /dev/null
+++ b/src/devices/file/buffered_file.rs
@@ -0,0 +1,127 @@
+use std::fs::File;
+use std::io::{BufReader, BufWriter};
+use std::io::{Read, Write};
+use std::io::{ErrorKind, Seek, SeekFrom};
+
+enum AccessMode {
+ Read(BufReader<File>),
+ Write(BufWriter<File>),
+ None,
+}
+
+impl AccessMode {
+ pub fn unwrap(self) -> File {
+ match self {
+ Self::Read(reader) => reader.into_inner(),
+ Self::Write(writer) => writer.into_inner().unwrap(),
+ Self::None => unreachable!(),
+ }
+ }
+}
+
+impl Default for AccessMode {
+ fn default() -> Self {
+ Self::None
+ }
+}
+
+pub struct BufferedFile {
+ file: AccessMode,
+}
+
+impl BufferedFile {
+ pub fn new(file: File) -> Self {
+ Self {
+ file: AccessMode::Read(BufReader::new(file)),
+ }
+ }
+
+ pub fn read_byte(&mut self) -> u8 {
+ let mut buffer = [0u8; 1];
+
+ let read_result = match &mut self.file {
+ AccessMode::Read(reader) => reader.read_exact(&mut buffer),
+ AccessMode::Write(writer) => {
+ let address = writer.stream_position().unwrap();
+ let file = std::mem::take(&mut self.file).unwrap();
+ let mut reader = BufReader::new(file);
+ reader.seek(SeekFrom::Start(address)).unwrap();
+ let read_result = reader.read_exact(&mut buffer);
+ self.file = AccessMode::Read(reader);
+ read_result
+ }
+ AccessMode::None => unreachable!(),
+ };
+
+ match read_result {
+ Ok(_) => buffer[0],
+ Err(error) => match error.kind() {
+ ErrorKind::UnexpectedEof => 0,
+ _ => panic!("{error:?}"),
+ }
+ }
+ }
+
+ pub fn write_byte(&mut self, byte: u8) {
+ let mut buffer = [byte; 1];
+
+ let write_result = match &mut self.file {
+ AccessMode::Write(writer) => writer.write_all(&mut buffer),
+ AccessMode::Read(reader) => {
+ let address = reader.stream_position().unwrap();
+ let file = std::mem::take(&mut self.file).unwrap();
+ let mut writer = BufWriter::new(file);
+ writer.seek(SeekFrom::Start(address)).unwrap();
+ let write_result = writer.write_all(&mut buffer);
+ self.file = AccessMode::Write(writer);
+ write_result
+ }
+ AccessMode::None => unreachable!(),
+ };
+
+ write_result.unwrap();
+ }
+
+ pub fn pointer(&mut self) -> u32 {
+ let position = match &mut self.file {
+ AccessMode::Read(reader) => reader.stream_position(),
+ AccessMode::Write(writer) => writer.stream_position(),
+ AccessMode::None => unreachable!(),
+ };
+ u32::try_from(position.unwrap()).unwrap_or(u32::MAX)
+ }
+
+ pub fn set_pointer(&mut self, pointer: u32) {
+ let position = SeekFrom::Start(pointer as u64);
+ match &mut self.file {
+ AccessMode::Read(reader) => reader.seek(position).unwrap(),
+ AccessMode::Write(writer) => writer.seek(position).unwrap(),
+ AccessMode::None => unreachable!(),
+ };
+ }
+
+ pub fn length(&mut self) -> u32 {
+ let length = match &mut self.file {
+ AccessMode::Read(reader) => reader.stream_len(),
+ AccessMode::Write(writer) => writer.stream_len(),
+ AccessMode::None => unreachable!(),
+ };
+ u32::try_from(length.unwrap()).unwrap_or(u32::MAX)
+ }
+
+ pub fn set_length(&mut self, length: u32) {
+ match &mut self.file {
+ AccessMode::Read(_) => {
+ let file = std::mem::take(&mut self.file).unwrap();
+ file.set_len(length as u64).unwrap();
+ self.file = AccessMode::Read(BufReader::new(file));
+ }
+ AccessMode::Write(_) => {
+ let file = std::mem::take(&mut self.file).unwrap();
+ file.set_len(length as u64).unwrap();
+ self.file = AccessMode::Read(BufReader::new(file));
+ }
+ AccessMode::None => unreachable!(),
+ };
+ }
+}