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
use std::mem::MaybeUninit;
use std::slice::from_raw_parts;
#[cfg(feature = "async")]
use async_std as std_;
#[cfg(not(feature = "async"))]
use std as std_;
use std_::{fs::File, io::prelude::*, io::SeekFrom, path::Path};
#[cfg(feature = "async")]
use async_trait::async_trait;
use crate::types::SectorID;
const MAX_SECTOR_SIZE: usize = 4096;
#[derive(Debug)]
pub struct FileIO {
file: File,
sector_size_shift: u8,
buffer: MaybeUninit<[u8; MAX_SECTOR_SIZE]>,
}
#[cfg_attr(not(feature = "async"), deasync::deasync)]
impl FileIO {
pub async fn open<P: AsRef<Path>>(filepath: P) -> std::io::Result<Self> {
let mut options = match () {
#[cfg(feature = "async")]
() => async_std::fs::OpenOptions::new(),
#[cfg(not(feature = "async"))]
() => File::options(),
};
let result = options.read(true).write(true).open(filepath).await;
result.map(|file| Self { file, sector_size_shift: 9, buffer: MaybeUninit::uninit() })
}
}
#[cfg_attr(feature = "async", async_trait)]
#[cfg_attr(not(feature = "async"), deasync::deasync)]
impl super::IO for FileIO {
type Error = std::io::Error;
fn set_sector_size_shift(&mut self, shift: u8) -> Result<(), Self::Error> {
self.sector_size_shift = shift;
Ok(())
}
async fn read<'a>(&'a mut self, sector: SectorID) -> Result<&'a [[u8; 512]], Self::Error> {
let sector_size: usize = 1 << self.sector_size_shift;
let seek = SeekFrom::Start(u64::from(sector) * sector_size as u64);
self.file.seek(seek).await?;
let buffer = unsafe { self.buffer.assume_init_mut() };
self.file.read_exact(&mut buffer[..sector_size]).await?;
Ok(unsafe { from_raw_parts(buffer.as_ptr() as *const _, sector_size / 512) })
}
async fn write(
&mut self,
sector: SectorID,
offset: usize,
buf: &[u8],
) -> Result<(), Self::Error> {
let sector_size = 1 << self.sector_size_shift;
let seek = SeekFrom::Start(u64::from(sector) * sector_size + offset as u64);
self.file.seek(seek).await?;
self.file.write_all(buf).await.map(|_| ())
}
async fn flush(&mut self) -> Result<(), Self::Error> {
self.file.flush().await
}
}