exfat/io/
std.rs

1use std::mem::MaybeUninit;
2use std::slice::from_raw_parts;
3
4use std::io::SeekFrom;
5use std::path::Path;
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 crate::types::SectorID;
22
23const MAX_SECTOR_SIZE: usize = 4096;
24
25#[derive(Debug)]
26pub struct FileIO {
27    file: fs::File,
28    sector_size_shift: u8,
29    buffer: MaybeUninit<[u8; MAX_SECTOR_SIZE]>,
30}
31
32#[cfg_attr(not(feature = "async"), deasync::deasync)]
33impl FileIO {
34    pub async fn open<P: AsRef<Path>>(filepath: P) -> std::io::Result<Self> {
35        let mut options = match () {
36            #[cfg(feature = "async")]
37            () => fs::OpenOptions::new(),
38            #[cfg(not(feature = "async"))]
39            () => fs::File::options(),
40        };
41        let file = options.read(true).write(true).open(filepath).await?;
42        Ok(Self { file, sector_size_shift: 9, buffer: MaybeUninit::uninit() })
43    }
44}
45
46#[cfg_attr(feature = "async", async_trait)]
47#[cfg_attr(not(feature = "async"), deasync::deasync)]
48impl super::IO for FileIO {
49    type Error = std::io::Error;
50
51    fn set_sector_size_shift(&mut self, shift: u8) -> Result<(), Self::Error> {
52        self.sector_size_shift = shift;
53        Ok(())
54    }
55
56    async fn read<'a>(&'a mut self, sector: SectorID) -> Result<&'a [[u8; 512]], Self::Error> {
57        let sector_size: usize = 1 << self.sector_size_shift;
58        let seek = SeekFrom::Start(u64::from(sector) * sector_size as u64);
59
60        self.file.seek(seek).await?;
61        let buffer = unsafe { self.buffer.assume_init_mut() };
62        self.file.read_exact(&mut buffer[..sector_size]).await?;
63
64        Ok(unsafe { from_raw_parts(buffer.as_ptr() as *const _, sector_size / 512) })
65    }
66
67    async fn write(
68        &mut self,
69        sector: SectorID,
70        offset: usize,
71        buf: &[u8],
72    ) -> Result<(), Self::Error> {
73        let sector_size = 1 << self.sector_size_shift;
74        let seek = SeekFrom::Start(u64::from(sector) * sector_size + offset as u64);
75        self.file.seek(seek).await?;
76        self.file.write_all(buf).await.map(|_| ())
77    }
78
79    async fn flush(&mut self) -> Result<(), Self::Error> {
80        self.file.flush().await
81    }
82}