Skip to main content

hadris_fat/
io.rs

1io_transform! {
2
3// Re-export I/O traits from the parent sync/async module.
4// Other I/O files use `super::io::Read` etc. which resolves through these re-exports.
5pub use super::super::{Read, Write, Seek, ReadExt, Error, ErrorKind, SeekFrom, Parsable, Writable};
6pub use super::super::IoResult;
7
8/// Create an I/O error from an ErrorKind.
9///
10/// This helper works in both std and no-std modes.
11#[cfg(feature = "std")]
12pub fn error_from_kind(kind: ErrorKind) -> Error {
13    Error::new(kind, "")
14}
15
16#[cfg(not(feature = "std"))]
17pub fn error_from_kind(kind: ErrorKind) -> Error {
18    Error::from_kind(kind)
19}
20
21/// A Type Representing a FAT Sector
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
23pub(crate) struct Sector<T = usize>(pub T);
24
25pub trait SectorLike {
26    fn to_bytes(self, bytes_per_sector: usize) -> usize;
27}
28
29macro_rules! sector_impl {
30    ($ty:ty) => {
31        impl SectorLike for Sector<$ty> {
32            fn to_bytes(self, bytes_per_sector: usize) -> usize {
33                (self.0 as usize) * bytes_per_sector
34            }
35        }
36    };
37}
38sector_impl!(u8);
39sector_impl!(u16);
40sector_impl!(u32);
41sector_impl!(u64);
42sector_impl!(usize);
43
44/// Represents a cluster number in a FAT filesystem.
45/// Clusters are the allocation units for file data, starting at cluster 2.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
47pub struct Cluster<T = usize>(pub T);
48
49impl Cluster<usize> {
50    pub fn from_parts(high: u16, low: u16) -> Self {
51        Self((high as usize) << 16 | (low as usize))
52    }
53}
54
55pub(crate) trait ClusterLike {
56    fn to_bytes(self, data_start: usize, bytes_per_cluster: usize) -> usize;
57}
58
59macro_rules! cluster_impl {
60    ($ty:ty) => {
61        impl ClusterLike for Cluster<$ty> {
62            fn to_bytes(self, data_start: usize, bytes_per_cluster: usize) -> usize {
63                data_start + (self.0 as usize - 2) * bytes_per_cluster
64            }
65        }
66    };
67}
68cluster_impl!(u8);
69cluster_impl!(u16);
70cluster_impl!(u32);
71cluster_impl!(u64);
72cluster_impl!(usize);
73
74pub struct SectorCursor<DATA: Seek> {
75    pub(crate) data: DATA,
76    pub(crate) sector_size: usize,
77    pub(crate) cluster_size: usize,
78}
79
80impl<DATA: Seek> SectorCursor<DATA> {
81    pub const fn new(data: DATA, sector_size: usize, cluster_size: usize) -> Self {
82        Self {
83            data,
84            sector_size,
85            cluster_size,
86        }
87    }
88
89    pub async fn seek_sector(&mut self, sector: impl SectorLike) -> hadris_io::Result<u64> {
90        self.seek(SeekFrom::Start(sector.to_bytes(self.sector_size) as u64)).await
91    }
92}
93
94impl<T> Seek for SectorCursor<T>
95where
96    T: Seek,
97{
98    async fn seek(&mut self, pos: hadris_io::SeekFrom) -> hadris_io::Result<u64> {
99        self.data.seek(pos).await
100    }
101
102    async fn stream_position(&mut self) -> hadris_io::Result<u64> {
103        self.data.stream_position().await
104    }
105
106    async fn seek_relative(&mut self, offset: i64) -> hadris_io::Result<()> {
107        self.data.seek_relative(offset).await
108    }
109}
110
111impl<T> Read for SectorCursor<T>
112where
113    T: Read + Seek,
114{
115    async fn read(&mut self, buf: &mut [u8]) -> hadris_io::Result<usize> {
116        self.data.read(buf).await
117    }
118
119    async fn read_exact(&mut self, buf: &mut [u8]) -> hadris_io::Result<()> {
120        self.data.read_exact(buf).await
121    }
122}
123
124#[cfg(feature = "write")]
125impl<T> Write for SectorCursor<T>
126where
127    T: Write + Seek,
128{
129    async fn write(&mut self, buf: &[u8]) -> hadris_io::Result<usize> {
130        self.data.write(buf).await
131    }
132
133    async fn flush(&mut self) -> hadris_io::Result<()> {
134        self.data.flush().await
135    }
136
137    async fn write_all(&mut self, buf: &[u8]) -> hadris_io::Result<()> {
138        self.data.write_all(buf).await
139    }
140}
141
142} // end io_transform!