1use std::io::Error;
2use std::io::SeekFrom;
3use std::path::Path;
4use std::ptr::from_mut;
5use std::slice::from_raw_parts_mut;
6#[cfg(not(feature = "async"))]
7use std::{fs, io::prelude::*};
8
9#[cfg(all(feature = "async", feature = "smol"))]
10use smol::fs;
11#[cfg(all(feature = "async", feature = "smol"))]
12use smol::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt};
13#[cfg(all(feature = "async", feature = "tokio"))]
14use tokio::fs;
15#[cfg(all(feature = "async", feature = "tokio"))]
16use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt};
17
18#[cfg(feature = "async")]
19use async_trait::async_trait;
20
21use super::{BLOCK_SIZE, Block};
22use crate::types::SectorID;
23
24#[derive(Debug)]
25pub struct FileIO {
26 file: fs::File,
27 sector_size_shift: u8,
28}
29
30#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)]
31impl FileIO {
32 pub async fn open<P: AsRef<Path>>(filepath: P) -> std::io::Result<Self> {
33 let mut options = match () {
34 #[cfg(feature = "async")]
35 () => fs::OpenOptions::new(),
36 #[cfg(not(feature = "async"))]
37 () => fs::File::options(),
38 };
39 let file = options.read(true).write(true).open(filepath).await?;
40 Ok(Self { file, sector_size_shift: 9 })
41 }
42}
43
44#[cfg_attr(feature = "async", async_trait)]
45#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)]
46impl super::IO for FileIO {
47 type Block<'a> = heapless::Vec<Block, 8>;
48 type Error = std::io::Error;
49
50 fn set_sector_size_shift(&mut self, shift: u8) -> Result<(), Self::Error> {
51 self.sector_size_shift = shift;
52 Ok(())
53 }
54
55 async fn read<'a>(&mut self, sector: SectorID) -> Result<Self::Block<'a>, Self::Error> {
56 let sector_size: usize = 1 << self.sector_size_shift;
57 let seek = SeekFrom::Start(u64::from(sector) * sector_size as u64);
58
59 self.file.seek(seek).await?;
60 let mut block = heapless::Vec::<Block, 8>::new();
61 unsafe { block.set_len(sector_size / BLOCK_SIZE) };
62 let buf: &mut [u8] = unsafe { from_raw_parts_mut(from_mut(&mut block[0][0]), sector_size) };
63 self.file.read_exact(buf).await?;
64 Ok(block)
65 }
66
67 async fn write(&mut self, sector: SectorID, offset: usize, buf: &[u8]) -> Result<(), Error> {
68 let sector_size = 1 << self.sector_size_shift;
69 let seek = SeekFrom::Start(u64::from(sector) * sector_size + offset as u64);
70 self.file.seek(seek).await?;
71 self.file.write_all(buf).await.map(|_| ())
72 }
73
74 async fn flush(&mut self) -> Result<(), Self::Error> {
75 self.file.flush().await
76 }
77}