Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New io #98

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use crate::dir_entry::{SFN_PADDING, SFN_SIZE};
use crate::error::{Error, IoError};
use crate::file::File;
use crate::fs::{DiskSlice, FileSystem, FsIoAdapter, OemCpConverter, ReadWriteSeek};
use crate::io::{self, IoBase, Read, Seek, SeekFrom, Write};
use crate::io::private::Sealed;
use crate::io::{self, IoBase, Read, ReadFile, Seek, SeekFrom, Write, WriteFile};
use crate::time::TimeProvider;

const LFN_PADDING: u16 = 0xFFFF;
Expand Down Expand Up @@ -51,11 +52,13 @@ impl<IO: ReadWriteSeek, TP, OCC> Clone for DirRawStream<'_, IO, TP, OCC> {
}
}

impl<IO: ReadWriteSeek, TP, OCC> Sealed for DirRawStream<'_, IO, TP, OCC> {}

impl<IO: ReadWriteSeek, TP, OCC> IoBase for DirRawStream<'_, IO, TP, OCC> {
type Error = Error<IO::Error>;
}

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

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP, OCC> {
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for DirRawStream<'_, IO, TP, OCC> {
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
<Self as ReadFile>::read_exact(self, buf)
}
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> WriteFile for DirRawStream<'_, IO, TP, OCC> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
match self {
DirRawStream::File(file) => file.write(buf),
Expand All @@ -73,12 +83,24 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP
}
fn flush(&mut self) -> Result<(), Self::Error> {
match self {
DirRawStream::File(file) => file.flush(),
DirRawStream::Root(raw) => raw.flush(),
DirRawStream::File(file) => <File<_, _, _> as WriteFile>::flush(file),
DirRawStream::Root(raw) => <DiskSlice<_, _> as WriteFile>::flush(raw),
}
}
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for DirRawStream<'_, IO, TP, OCC> {
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
<Self as WriteFile>::write_all(self, buf)
}

#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
<Self as WriteFile>::flush(self)
}
}

impl<IO: ReadWriteSeek, TP, OCC> Seek for DirRawStream<'_, IO, TP, OCC> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
match self {
Expand Down
63 changes: 38 additions & 25 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use core::convert::TryFrom;
use crate::dir_entry::DirEntryEditor;
use crate::error::Error;
use crate::fs::{FileSystem, ReadWriteSeek};
use crate::io::{IoBase, Read, Seek, SeekFrom, Write};
use crate::io::private::Sealed;
use crate::io::{IoBase, Read, ReadFile, Seek, SeekFrom, Write, WriteFile};
use crate::time::{Date, DateTime, TimeProvider};

const MAX_FILE_SIZE: u32 = core::u32::MAX;
Expand Down Expand Up @@ -250,11 +251,13 @@ impl<IO: ReadWriteSeek, TP, OCC> Clone for File<'_, IO, TP, OCC> {
}
}

impl<IO: ReadWriteSeek, TP, OCC> Sealed for File<'_, IO, TP, OCC> {}

impl<IO: ReadWriteSeek, TP, OCC> IoBase for File<'_, IO, TP, OCC> {
type Error = Error<IO::Error>;
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> ReadFile for File<'_, IO, TP, OCC> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
trace!("File::read");
let cluster_size = self.fs.cluster_size();
Expand Down Expand Up @@ -286,15 +289,10 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
}
trace!("read {} bytes in cluster {}", read_size, current_cluster);
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + u64::from(offset_in_cluster);
let read_bytes = {
let mut disk = self.fs.disk.borrow_mut();
disk.seek(SeekFrom::Start(offset_in_fs))?;
disk.read(&mut buf[..read_size])?
};
if read_bytes == 0 {
return Ok(0);
}
self.offset += read_bytes as u32;
let mut disk = self.fs.disk.borrow_mut();
disk.seek(SeekFrom::Start(offset_in_fs))?;
disk.read_exact(&mut buf[..read_size])?;
self.offset += read_size as u32;
self.current_cluster = Some(current_cluster);

if let Some(ref mut e) = self.entry {
Expand All @@ -303,7 +301,14 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
e.set_accessed(now);
}
}
Ok(read_bytes)
Ok(read_size)
}
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Read for File<'_, IO, TP, OCC> {
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
<Self as ReadFile>::read_exact(self, buf)
}
}

Expand All @@ -313,11 +318,11 @@ where
std::io::Error: From<Error<IO::Error>>,
{
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
Ok(Read::read(self, buf)?)
Ok(ReadFile::read(self, buf)?)
}
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> WriteFile for File<'_, IO, TP, OCC> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
trace!("File::write");
let cluster_size = self.fs.cluster_size();
Expand Down Expand Up @@ -365,33 +370,41 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
};
trace!("write {} bytes in cluster {}", write_size, current_cluster);
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + u64::from(offset_in_cluster);
let written_bytes = {
let mut disk = self.fs.disk.borrow_mut();
disk.seek(SeekFrom::Start(offset_in_fs))?;
disk.write(&buf[..write_size])?
};
if written_bytes == 0 {
return Ok(0);
}
let mut disk = self.fs.disk.borrow_mut();
disk.seek(SeekFrom::Start(offset_in_fs))?;
disk.write_all(&buf[..write_size])?;
// some bytes were writter - update position and optionally size
self.offset += written_bytes as u32;
self.offset += write_size as u32;
self.current_cluster = Some(current_cluster);
self.update_dir_entry_after_write();
Ok(written_bytes)
Ok(write_size)
}

fn flush(&mut self) -> Result<(), Self::Error> {
Self::flush(self)
}
}

impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> Write for File<'_, IO, TP, OCC> {
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
<Self as WriteFile>::write_all(self, buf)
}

#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
<Self as WriteFile>::flush(self)
}
}

#[cfg(feature = "std")]
impl<IO: ReadWriteSeek, TP: TimeProvider, OCC> std::io::Write for File<'_, IO, TP, OCC>
where
std::io::Error: From<Error<IO::Error>>,
{
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(Write::write(self, buf)?)
Write::write_all(self, buf)?;
Ok(buf.len())
}

fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
Expand Down
51 changes: 38 additions & 13 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use crate::dir::{Dir, DirRawStream};
use crate::dir_entry::{DirFileEntryData, FileAttributes, SFN_PADDING, SFN_SIZE};
use crate::error::Error;
use crate::file::File;
use crate::io::{self, IoBase, Read, ReadLeExt, Seek, SeekFrom, Write, WriteLeExt};
use crate::io::private::Sealed;
use crate::io::{self, IoBase, Read, ReadFile, ReadLeExt, Seek, SeekFrom, Write, WriteFile, WriteLeExt};
use crate::table::{
alloc_cluster, count_free_clusters, format_fat, read_fat_flags, ClusterIterator, RESERVED_FAT_ENTRIES,
};
Expand Down Expand Up @@ -694,23 +695,26 @@ pub(crate) struct FsIoAdapter<'a, IO: ReadWriteSeek, TP, OCC> {
fs: &'a FileSystem<IO, TP, OCC>,
}

impl<IO: ReadWriteSeek, TP, OCC> Sealed for FsIoAdapter<'_, IO, TP, OCC> {}

impl<IO: ReadWriteSeek, TP, OCC> IoBase for FsIoAdapter<'_, IO, TP, OCC> {
type Error = IO::Error;
}

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

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

fn flush(&mut self) -> Result<(), Self::Error> {
Expand Down Expand Up @@ -797,22 +801,31 @@ impl<B: Clone, S> Clone for DiskSlice<B, S> {
}
}

impl<B, S: IoBase> Sealed for DiskSlice<B, S> {}

impl<B, S: IoBase> IoBase for DiskSlice<B, S> {
type Error = Error<S::Error>;
}

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

impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
impl<B: BorrowMut<S>, S: Read + Seek> Read for DiskSlice<B, S> {
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
<Self as ReadFile>::read_exact(self, buf)
}
}

impl<B: BorrowMut<S>, S: Write + Seek> WriteFile for DiskSlice<B, S> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
let offset = self.begin + self.offset;
let write_size = (buf.len() as u64).min(self.size - self.offset) as usize;
Expand All @@ -834,6 +847,18 @@ impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
}
}

impl<B: BorrowMut<S>, S: Write + Seek> Write for DiskSlice<B, S> {
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
<Self as WriteFile>::write_all(self, buf)
}

#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
<Self as WriteFile>::flush(self)
}
}

impl<B, S: IoBase> Seek for DiskSlice<B, S> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
let new_offset_opt: Option<u64> = match pos {
Expand Down
Loading