drivers/standard_library/
drive_file.rs1use 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}