summaryrefslogtreecommitdiff
path: root/src/devices/file.rs
blob: f442dd8e0667bf8942573ca61b2fc6ea5f6bd5d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
    }
}