Skip to content

Commit d7e774f

Browse files
committed
A new IO-Layer
1 parent 4eccb50 commit d7e774f

File tree

4 files changed

+154
-48
lines changed

4 files changed

+154
-48
lines changed

src/dir.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::dir_entry::{SFN_PADDING, SFN_SIZE};
1414
use crate::error::{Error, IoError};
1515
use crate::file::File;
1616
use crate::fs::{DiskSlice, FileSystem, FsIoAdapter, OemCpConverter, ReadWriteSeek};
17-
use crate::io::{self, IoBase, Read, Seek, SeekFrom, Write};
17+
use crate::io::{self, IoBase, Read, ReadFile, Seek, SeekFrom, Write, WriteFile};
1818
use crate::time::TimeProvider;
1919

2020
const LFN_PADDING: u16 = 0xFFFF;
@@ -61,7 +61,7 @@ impl<IO: ReadWriteSeek, TP, OCC> IoBase for DirRawStream<'_, IO, TP, OCC> {
6161
type Error = Error<IO::Error>;
6262
}
6363

64-
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for DirRawStream<'_, IO, TP, OCC> {
64+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> ReadFile for DirRawStream<'_, IO, TP, OCC> {
6565
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
6666
match self {
6767
DirRawStream::File(file) => file.read(buf),
@@ -70,7 +70,14 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for DirRawStream<'_, IO, TP,
7070
}
7171
}
7272

73-
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP, OCC> {
73+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for DirRawStream<'_, IO, TP, OCC> {
74+
#[inline]
75+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
76+
<Self as ReadFile>::read_exact(self, buf)
77+
}
78+
}
79+
80+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> WriteFile for DirRawStream<'_, IO, TP, OCC> {
7481
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
7582
match self {
7683
DirRawStream::File(file) => file.write(buf),
@@ -79,12 +86,24 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP
7986
}
8087
fn flush(&mut self) -> Result<(), Self::Error> {
8188
match self {
82-
DirRawStream::File(file) => file.flush(),
83-
DirRawStream::Root(raw) => raw.flush(),
89+
DirRawStream::File(file) => <File<_, _, _> as WriteFile>::flush(file),
90+
DirRawStream::Root(raw) => <DiskSlice<_, _> as WriteFile>::flush(raw),
8491
}
8592
}
8693
}
8794

95+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP, OCC> {
96+
#[inline]
97+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
98+
<Self as WriteFile>::write_all(self, buf)
99+
}
100+
101+
#[inline]
102+
fn flush(&mut self) -> Result<(), Self::Error> {
103+
<Self as WriteFile>::flush(self)
104+
}
105+
}
106+
88107
impl<IO: ReadWriteSeek, TP, OCC> Seek for DirRawStream<'_, IO, TP, OCC> {
89108
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
90109
match self {

src/file.rs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use core::convert::TryFrom;
33
use crate::dir_entry::DirEntryEditor;
44
use crate::error::Error;
55
use crate::fs::{FileSystem, ReadWriteSeek};
6-
use crate::io::{IoBase, Read, Seek, SeekFrom, Write};
6+
use crate::io::{IoBase, Read, ReadFile, Seek, SeekFrom, Write, WriteFile};
77
use crate::time::{Date, DateTime, TimeProvider};
88

99
const MAX_FILE_SIZE: u32 = u32::MAX;
@@ -255,7 +255,7 @@ impl<IO: ReadWriteSeek, TP, OCC> IoBase for File<'_, IO, TP, OCC> {
255255
type Error = Error<IO::Error>;
256256
}
257257

258-
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
258+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> ReadFile for File<'_, IO, TP, OCC> {
259259
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
260260
trace!("File::read");
261261
let cluster_size = self.fs.cluster_size();
@@ -287,15 +287,10 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
287287
}
288288
trace!("read {} bytes in cluster {}", read_size, current_cluster);
289289
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + u64::from(offset_in_cluster);
290-
let read_bytes = {
291-
let mut disk = self.fs.disk.borrow_mut();
292-
disk.seek(SeekFrom::Start(offset_in_fs))?;
293-
disk.read(&mut buf[..read_size])?
294-
};
295-
if read_bytes == 0 {
296-
return Ok(0);
297-
}
298-
self.offset += read_bytes as u32;
290+
let mut disk = self.fs.disk.borrow_mut();
291+
disk.seek(SeekFrom::Start(offset_in_fs))?;
292+
disk.read_exact(&mut buf[..read_size])?;
293+
self.offset += read_size as u32;
299294
self.current_cluster = Some(current_cluster);
300295

301296
if let Some(ref mut e) = self.entry {
@@ -304,7 +299,14 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
304299
e.set_accessed(now);
305300
}
306301
}
307-
Ok(read_bytes)
302+
Ok(read_size)
303+
}
304+
}
305+
306+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
307+
#[inline]
308+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
309+
<Self as ReadFile>::read_exact(self, buf)
308310
}
309311
}
310312

@@ -314,11 +316,11 @@ where
314316
std::io::Error: From<Error<IO::Error>>,
315317
{
316318
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
317-
Ok(Read::read(self, buf)?)
319+
Ok(ReadFile::read(self, buf)?)
318320
}
319321
}
320322

321-
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
323+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> WriteFile for File<'_, IO, TP, OCC> {
322324
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
323325
trace!("File::write");
324326
let cluster_size = self.fs.cluster_size();
@@ -366,33 +368,41 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
366368
};
367369
trace!("write {} bytes in cluster {}", write_size, current_cluster);
368370
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + u64::from(offset_in_cluster);
369-
let written_bytes = {
370-
let mut disk = self.fs.disk.borrow_mut();
371-
disk.seek(SeekFrom::Start(offset_in_fs))?;
372-
disk.write(&buf[..write_size])?
373-
};
374-
if written_bytes == 0 {
375-
return Ok(0);
376-
}
371+
let mut disk = self.fs.disk.borrow_mut();
372+
disk.seek(SeekFrom::Start(offset_in_fs))?;
373+
disk.write_all(&buf[..write_size])?;
377374
// some bytes were writter - update position and optionally size
378-
self.offset += written_bytes as u32;
375+
self.offset += write_size as u32;
379376
self.current_cluster = Some(current_cluster);
380377
self.update_dir_entry_after_write();
381-
Ok(written_bytes)
378+
Ok(write_size)
382379
}
383380

384381
fn flush(&mut self) -> Result<(), Self::Error> {
385382
Self::flush(self)
386383
}
387384
}
388385

386+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
387+
#[inline]
388+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
389+
<Self as WriteFile>::write_all(self, buf)
390+
}
391+
392+
#[inline]
393+
fn flush(&mut self) -> Result<(), Self::Error> {
394+
<Self as WriteFile>::flush(self)
395+
}
396+
}
397+
389398
#[cfg(feature = "std")]
390399
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> std::io::Write for File<'_, IO, TP, OCC>
391400
where
392401
std::io::Error: From<Error<IO::Error>>,
393402
{
394403
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
395-
Ok(Write::write(self, buf)?)
404+
Write::write_all(self, buf)?;
405+
Ok(buf.len())
396406
}
397407

398408
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
@@ -476,3 +486,9 @@ where
476486
Ok(Seek::seek(self, pos.into())?)
477487
}
478488
}
489+
490+
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> core::fmt::Write for File<'_, IO, TP, OCC> {
491+
fn write_str(&mut self, s: &str) -> core::fmt::Result {
492+
<Self as WriteFile>::write_all(self, s.as_bytes()).map_err(|_| core::fmt::Error)
493+
}
494+
}

src/fs.rs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::dir::{Dir, DirRawStream};
1111
use crate::dir_entry::{DirFileEntryData, FileAttributes, SFN_PADDING, SFN_SIZE};
1212
use crate::error::Error;
1313
use crate::file::File;
14-
use crate::io::{self, IoBase, Read, ReadLeExt, Seek, SeekFrom, Write, WriteLeExt};
14+
use crate::io::{self, IoBase, Read, ReadFile, ReadLeExt, Seek, SeekFrom, Write, WriteFile, WriteLeExt};
1515
use crate::table::{
1616
alloc_cluster, count_free_clusters, format_fat, read_fat_flags, ClusterIterator, RESERVED_FAT_ENTRIES,
1717
};
@@ -711,18 +711,19 @@ impl<IO: ReadWriteSeek, TP, OCC> IoBase for FsIoAdapter<'_, IO, TP, OCC> {
711711
}
712712

713713
impl<IO: ReadWriteSeek, TP, OCC> Read for FsIoAdapter<'_, IO, TP, OCC> {
714-
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
715-
self.fs.disk.borrow_mut().read(buf)
714+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
715+
self.fs.disk.borrow_mut().read_exact(buf)
716716
}
717717
}
718718

719719
impl<IO: ReadWriteSeek, TP, OCC> Write for FsIoAdapter<'_, IO, TP, OCC> {
720-
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
721-
let size = self.fs.disk.borrow_mut().write(buf)?;
722-
if size > 0 {
723-
self.fs.set_dirty_flag(true)?;
720+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
721+
if buf.is_empty() {
722+
Ok(())
723+
} else {
724+
self.fs.disk.borrow_mut().write_all(buf)?;
725+
self.fs.set_dirty_flag(true)
724726
}
725-
Ok(size)
726727
}
727728

728729
fn flush(&mut self) -> Result<(), Self::Error> {
@@ -813,18 +814,25 @@ impl<B, S: IoBase> IoBase for DiskSlice<B, S> {
813814
type Error = Error<S::Error>;
814815
}
815816

816-
impl<B: BorrowMut<S>, S: Read + Seek> Read for DiskSlice<B, S> {
817+
impl<B: BorrowMut<S>, S: Read + Seek> ReadFile for DiskSlice<B, S> {
817818
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
818819
let offset = self.begin + self.offset;
819820
let read_size = (buf.len() as u64).min(self.size - self.offset) as usize;
820821
self.inner.borrow_mut().seek(SeekFrom::Start(offset))?;
821-
let size = self.inner.borrow_mut().read(&mut buf[..read_size])?;
822-
self.offset += size as u64;
823-
Ok(size)
822+
self.inner.borrow_mut().read_exact(&mut buf[..read_size])?;
823+
self.offset += read_size as u64;
824+
Ok(read_size)
824825
}
825826
}
826827

827-
impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
828+
impl<B: BorrowMut<S>, S: Read + Seek> Read for DiskSlice<B, S> {
829+
#[inline]
830+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
831+
<Self as ReadFile>::read_exact(self, buf)
832+
}
833+
}
834+
835+
impl<B: BorrowMut<S>, S: Write + Seek> WriteFile for DiskSlice<B, S> {
828836
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
829837
let offset = self.begin + self.offset;
830838
let write_size = (buf.len() as u64).min(self.size - self.offset) as usize;
@@ -846,6 +854,18 @@ impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
846854
}
847855
}
848856

857+
impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
858+
#[inline]
859+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
860+
<Self as WriteFile>::write_all(self, buf)
861+
}
862+
863+
#[inline]
864+
fn flush(&mut self) -> Result<(), Self::Error> {
865+
<Self as WriteFile>::flush(self)
866+
}
867+
}
868+
849869
impl<B, S: IoBase> Seek for DiskSlice<B, S> {
850870
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
851871
let new_offset_opt: Option<u64> = match pos {

src/io.rs

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,28 @@ pub trait IoBase {
1313
///
1414
/// It is based on the `std::io::Read` trait.
1515
pub trait Read: IoBase {
16+
/// Read the exact number of bytes required to fill `buf`.
17+
///
18+
/// This function reads as many bytes as necessary to completely fill the specified buffer `buf`.
19+
///
20+
/// # Errors
21+
///
22+
/// If this function encounters an error for which `IoError::is_interrupted` returns true then the error is ignored
23+
/// and the operation will continue.
24+
///
25+
/// If this function encounters an end of file before completely filling the buffer, it returns an error
26+
/// instantiated by a call to `IoError::new_unexpected_eof_error`. The contents of `buf` are unspecified in this
27+
/// case.
28+
///
29+
/// If this function returns an error, it is unspecified how many bytes it has read, but it will never read more
30+
/// than would be necessary to completely fill the buffer.
31+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>;
32+
}
33+
34+
/// The `ReadFile` trait allows for reading bytes from a source.
35+
///
36+
/// It is based on the `std::io::Read` trait.
37+
pub trait ReadFile: Read {
1638
/// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
1739
///
1840
/// This function does not provide any guarantees about whether it blocks waiting for data, but if an object needs
@@ -78,6 +100,32 @@ pub trait Read: IoBase {
78100
///
79101
/// It is based on the `std::io::Write` trait.
80102
pub trait Write: IoBase {
103+
/// Attempts to write an entire buffer into this writer.
104+
///
105+
/// This method will continuously call `write` until there is no more data to be written or an error is returned.
106+
/// Errors for which `IoError::is_interrupted` method returns true are being skipped. This method will not return
107+
/// until the entire buffer has been successfully written or such an error occurs.
108+
/// If `write` returns 0 before the entire buffer has been written this method will return an error instantiated by
109+
/// a call to `IoError::new_write_zero_error`.
110+
///
111+
/// # Errors
112+
///
113+
/// This function will return the first error for which `IoError::is_interrupted` method returns false that `write`
114+
/// returns.
115+
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
116+
117+
/// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
118+
///
119+
/// # Errors
120+
///
121+
/// It is considered an error if not all bytes could be written due to I/O errors or EOF being reached.
122+
fn flush(&mut self) -> Result<(), Self::Error>;
123+
}
124+
125+
/// The `WriteFile` trait allows for writing bytes into the sink.
126+
///
127+
/// It is based on the `std::io::Write` trait.
128+
pub trait WriteFile: Write {
81129
/// Write a buffer into this writer, returning how many bytes were written.
82130
///
83131
/// # Errors
@@ -201,7 +249,7 @@ impl<T> IoBase for StdIoWrapper<T> {
201249
}
202250

203251
#[cfg(feature = "std")]
204-
impl<T: std::io::Read> Read for StdIoWrapper<T> {
252+
impl<T: std::io::Read> ReadFile for StdIoWrapper<T> {
205253
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
206254
self.inner.read(buf)
207255
}
@@ -211,11 +259,14 @@ impl<T: std::io::Read> Read for StdIoWrapper<T> {
211259
}
212260

213261
#[cfg(feature = "std")]
214-
impl<T: std::io::Write> Write for StdIoWrapper<T> {
215-
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
216-
self.inner.write(buf)
262+
impl<T: std::io::Read> Read for StdIoWrapper<T> {
263+
#[inline]
264+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
265+
<Self as ReadFile>::read_exact(self, buf)
217266
}
218-
267+
}
268+
#[cfg(feature = "std")]
269+
impl<T: std::io::Write> Write for StdIoWrapper<T> {
219270
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
220271
self.inner.write_all(buf)
221272
}

0 commit comments

Comments
 (0)