Skip to content

Commit

Permalink
Merge pull request #140 from qwandor/embedded-io
Browse files Browse the repository at this point in the history
Implement embedded-io traits for File.
  • Loading branch information
thejpster authored Aug 7, 2024
2 parents 6bd9b92 + 7951b76 commit 011726b
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic

### Added

- None
- `File` now implements the `embedded-io` `Read`, `Write` and `Seek` traits.

### Removed

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ version = "0.8.0"
byteorder = {version = "1", default-features = false}
defmt = {version = "0.3", optional = true}
embedded-hal = "1.0.0"
embedded-io = "0.6.1"
heapless = "^0.8"
log = {version = "0.4", default-features = false, optional = true}

Expand Down
78 changes: 77 additions & 1 deletion src/filesystem/files.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::TimeSource;
use crate::{
filesystem::{ClusterId, DirEntry, SearchId},
Error, RawVolume, VolumeManager,
BlockDevice, Error, RawVolume, VolumeManager,
};
use embedded_io::{ErrorType, Read, Seek, SeekFrom, Write};

/// A handle for an open file on disk.
///
Expand Down Expand Up @@ -165,6 +167,80 @@ where
}
}

impl<
D: BlockDevice,
T: TimeSource,
const MAX_DIRS: usize,
const MAX_FILES: usize,
const MAX_VOLUMES: usize,
> ErrorType for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
{
type Error = crate::Error<D::Error>;
}

impl<
D: BlockDevice,
T: TimeSource,
const MAX_DIRS: usize,
const MAX_FILES: usize,
const MAX_VOLUMES: usize,
> Read for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
Ok(0)
} else {
self.read(buf)
}
}
}

impl<
D: BlockDevice,
T: TimeSource,
const MAX_DIRS: usize,
const MAX_FILES: usize,
const MAX_VOLUMES: usize,
> Write for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
Ok(0)
} else {
self.write(buf)?;
Ok(buf.len())
}
}

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

impl<
D: BlockDevice,
T: TimeSource,
const MAX_DIRS: usize,
const MAX_FILES: usize,
const MAX_VOLUMES: usize,
> Seek for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
{
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
match pos {
SeekFrom::Start(offset) => {
self.seek_from_start(offset.try_into().map_err(|_| Error::InvalidOffset)?)?
}
SeekFrom::End(offset) => {
self.seek_from_end((-offset).try_into().map_err(|_| Error::InvalidOffset)?)?
}
SeekFrom::Current(offset) => {
self.seek_from_current(offset.try_into().map_err(|_| Error::InvalidOffset)?)?
}
}
Ok(self.offset().into())
}
}

#[cfg(feature = "defmt-log")]
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
defmt::Format for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
Expand Down
36 changes: 36 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub mod fat;
pub mod filesystem;
pub mod sdcard;

use core::fmt::Debug;
use embedded_io::ErrorKind;
use filesystem::SearchId;

#[doc(inline)]
Expand Down Expand Up @@ -202,6 +204,40 @@ where
DirAlreadyExists,
}

impl<E: Debug> embedded_io::Error for Error<E> {
fn kind(&self) -> ErrorKind {
match self {
Error::DeviceError(_)
| Error::FormatError(_)
| Error::FileAlreadyOpen
| Error::DirAlreadyOpen
| Error::VolumeStillInUse
| Error::VolumeAlreadyOpen
| Error::EndOfFile
| Error::DiskFull
| Error::NotEnoughSpace
| Error::AllocationError => ErrorKind::Other,
Error::NoSuchVolume
| Error::FilenameError(_)
| Error::BadHandle
| Error::InvalidOffset => ErrorKind::InvalidInput,
Error::TooManyOpenVolumes | Error::TooManyOpenDirs | Error::TooManyOpenFiles => {
ErrorKind::OutOfMemory
}
Error::NotFound => ErrorKind::NotFound,
Error::OpenedDirAsFile
| Error::OpenedFileAsDir
| Error::DeleteDirAsFile
| Error::BadCluster
| Error::ConversionError
| Error::UnterminatedFatChain => ErrorKind::InvalidData,
Error::Unsupported | Error::BadBlockSize(_) => ErrorKind::Unsupported,
Error::ReadOnly => ErrorKind::PermissionDenied,
Error::FileAlreadyExists | Error::DirAlreadyExists => ErrorKind::AlreadyExists,
}
}
}

impl<E> From<E> for Error<E>
where
E: core::fmt::Debug,
Expand Down

0 comments on commit 011726b

Please sign in to comment.