summaryrefslogtreecommitdiff
path: root/src/devices/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/file.rs')
-rw-r--r--src/devices/file.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/devices/file.rs b/src/devices/file.rs
new file mode 100644
index 0000000..f442dd8
--- /dev/null
+++ b/src/devices/file.rs
@@ -0,0 +1,90 @@
+use std::io::{ErrorKind, Read, Seek, SeekFrom};
+use std::fs::{File, OpenOptions};
+
+pub struct FileDevice {
+ pub name: Vec<u8>,
+ pub rename: Vec<u8>,
+
+ pub file: Option<File>,
+ pub operation_state: bool,
+ pub pointer: u32,
+ pub file_size: u32,
+}
+
+impl FileDevice {
+ pub fn new() -> Self {
+ Self {
+ name: Vec::new(),
+ rename: Vec::new(),
+
+ file: None,
+ operation_state: false,
+ pointer: 0,
+ file_size: 0,
+ }
+ }
+
+ pub fn push_name_byte(&mut self, byte: u8) {
+ if byte != 0 { self.name.push(byte); return }
+ // If char was null, attempt to open the file and read file size.
+ let path: std::ffi::OsString = std::os::unix::ffi::OsStringExt::from_vec(
+ std::mem::take(&mut self.name));
+ let try_open = OpenOptions::new().read(true).write(true).open(path);
+ if let Ok(file) = try_open {
+ if let Ok(metadata) = file.metadata() {
+ // Success.
+ self.file = Some(file);
+ match u32::try_from(metadata.len()) {
+ Ok(len) => self.file_size = len,
+ Err(_) => self.file_size = u32::MAX,
+ }
+ return;
+ }
+ }
+ // Failure.
+ self.close();
+ }
+
+ pub fn set_file_size(&mut self) {
+ if let Some(file) = &self.file {
+ if let Ok(()) = file.set_len(self.file_size.into()) {
+ return;
+ };
+ }
+ self.close();
+ }
+
+ pub fn read(&mut self) -> u8 {
+ if let Some(file) = &mut self.file {
+ let mut buffer: [u8; 1] = [0; 1];
+ match file.read_exact(&mut buffer) {
+ Ok(()) => return buffer[0],
+ Err(err) => match err.kind() {
+ ErrorKind::UnexpectedEof => return 0,
+ _ => unimplemented!("File read error: ErrorKind::{:?}", err.kind()),
+ }
+ }
+ }
+ self.close();
+ return 0;
+ }
+
+ pub fn seek(&mut self) {
+ if let Some(file) = &mut self.file {
+ let point = SeekFrom::Start(self.pointer.into());
+ if let Ok(pointer) = file.seek(point) {
+ if let Ok(pointer_u32) = pointer.try_into() {
+ self.pointer = pointer_u32;
+ return;
+ }
+ };
+ }
+ self.close();
+ }
+
+ pub fn close(&mut self) {
+ self.file = None;
+ self.pointer = 0;
+ self.file_size = 0;
+ }
+}