exfat/io/
std.rs

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}