drivers/standard_library/
drive_file.rs

1use std::{
2    fs::{File, OpenOptions},
3    io::{Read, Seek, Write},
4    sync::RwLock,
5};
6
7use file_system::{DeviceTrait, Error, Path, Size};
8
9use crate::standard_library::io::map_error;
10
11pub struct FileDriveDevice(RwLock<File>);
12
13impl FileDriveDevice {
14    pub fn new(path: &impl AsRef<Path>) -> Self {
15        let path = path.as_ref().as_str();
16
17        let file = OpenOptions::new()
18            .read(true)
19            .write(true)
20            .create(true)
21            .truncate(false)
22            .open(path)
23            .expect("Error opening file");
24
25        Self(RwLock::new(file))
26    }
27}
28
29impl DeviceTrait for FileDriveDevice {
30    fn read(&self, buffer: &mut [u8]) -> file_system::Result<file_system::Size> {
31        self.0
32            .try_write()
33            .map_err(|_| Error::RessourceBusy)?
34            .read(buffer)
35            .map(|size| file_system::Size::new(size as u64))
36            .map_err(map_error)
37    }
38
39    fn write(&self, buffer: &[u8]) -> file_system::Result<file_system::Size> {
40        self.0
41            .try_write()
42            .map_err(|_| Error::RessourceBusy)?
43            .write(buffer)
44            .map(|size| file_system::Size::new(size as u64))
45            .map_err(map_error)
46    }
47
48    fn get_size(&self) -> file_system::Result<file_system::Size> {
49        Ok((1024 * 1024 * 1024 * 4_usize).into())
50    }
51
52    fn set_position(
53        &self,
54        position: &file_system::Position,
55    ) -> file_system::Result<file_system::Size> {
56        let position = match position {
57            file_system::Position::Start(position) => std::io::SeekFrom::Start(*position),
58            file_system::Position::End(position) => std::io::SeekFrom::End(*position),
59            file_system::Position::Current(position) => std::io::SeekFrom::Current(*position),
60        };
61
62        self.0
63            .try_write()
64            .map_err(|_| Error::RessourceBusy)?
65            .seek(position)
66            .map(Size::new)
67            .map_err(map_error)
68    }
69
70    fn flush(&self) -> file_system::Result<()> {
71        self.0.write().unwrap().flush().map_err(map_error)
72    }
73
74    fn erase(&self) -> file_system::Result<()> {
75        Ok(())
76    }
77
78    fn get_block_size(&self) -> file_system::Result<usize> {
79        Ok(4096)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use file_system::DeviceTrait;
87
88    #[test]
89    fn test_read_write() {
90        let file = FileDriveDevice::new(&"./test.img");
91
92        let data = [1, 2, 3, 4, 5];
93
94        assert_eq!(file.write(&data).unwrap(), Size::new(5));
95
96        file.set_position(&file_system::Position::Start(0)).unwrap();
97
98        let mut buffer = [0; 5];
99
100        assert_eq!(file.read(&mut buffer).unwrap(), Size::new(5));
101        assert_eq!(buffer, data);
102    }
103
104    #[test]
105    fn test_read_write_at_position() {
106        let file = FileDriveDevice::new(&"./test.img");
107
108        file.set_position(&file_system::Position::Start(10))
109            .unwrap();
110
111        let data = [1, 2, 3, 4, 5];
112
113        assert_eq!(file.write(&data).unwrap(), Size::new(5));
114
115        file.set_position(&file_system::Position::Start(10))
116            .unwrap();
117
118        let mut buffer = [0; 5];
119
120        assert_eq!(file.read(&mut buffer).unwrap(), Size::new(5));
121        assert_eq!(buffer, data);
122    }
123}