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

Implement core::error::Error for all error types #180

Open
wants to merge 1 commit into
base: develop
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic

- `File` now implements the `embedded-io` `Read`, `Write` and `Seek` traits.
- New `iterate_dir_lfn` method on `VolumeManager` and `Directory` - provides decoded Long File Names as `Option<&str>`
- Implement `core::error::Error` for all error types (behind crate feature `core-error` as this raises the MSRV to 1.81)

### Removed

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ sha2 = "0.10"
default = ["log"]
defmt-log = ["dep:defmt"]
log = ["dep:log"]
core-error = []
47 changes: 47 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
//! * `defmt-log`: By turning off the default features and enabling the
//! `defmt-log` feature you can configure this crate to log messages over defmt
//! instead.
//! * `core-error`: Enables implementations of `core::error::Error` for all error
//! types. This raises the Minimum Supported Rust Version to 1.81.
//!
//! You cannot enable both the `log` feature and the `defmt-log` feature.

Expand Down Expand Up @@ -272,6 +274,51 @@ where
}
}

impl<E> core::fmt::Display for Error<E>
where
E: core::fmt::Debug + core::fmt::Display,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
Error::DeviceError(e) => write!(f, "error from underlying block device: {e}"),
Error::FormatError(s) => write!(f, "filesystem is badly formatted: {s}"),
Error::NoSuchVolume => write!(f, "no such volume"),
Error::FilenameError(_) => write!(f, "bad filename"),
Error::TooManyOpenVolumes => write!(f, "too many open volumes"),
Error::TooManyOpenDirs => write!(f, "too many open directories"),
Error::TooManyOpenFiles => write!(f, "too many open files"),
Error::BadHandle => write!(f, "bad handle"),
Error::NotFound => write!(f, "file or directory does not exist"),
Error::FileAlreadyOpen => write!(f, "file already open"),
Error::DirAlreadyOpen => write!(f, "directory already open"),
Error::OpenedDirAsFile => write!(f, "cannot open directory as file"),
Error::OpenedFileAsDir => write!(f, "cannot open file as directory"),
Error::DeleteDirAsFile => write!(f, "cannot delete directory as file"),
Error::VolumeStillInUse => write!(f, "volume is still in use"),
Error::VolumeAlreadyOpen => write!(f, "cannot open volume twice"),
Error::Unsupported => write!(f, "unsupported operation"),
Error::EndOfFile => write!(f, "end of file"),
Error::BadCluster => write!(f, "bad cluster"),
Error::ConversionError => write!(f, "type conversion failed"),
Error::NotEnoughSpace => write!(f, "not enough space on device"),
Error::AllocationError => write!(f, "cluster not properly allocated"),
Error::UnterminatedFatChain => write!(f, "FAT chain unterminated"),
Error::ReadOnly => write!(f, "file is read-only"),
Error::FileAlreadyExists => write!(f, "file already exists"),
Error::BadBlockSize(size) => {
write!(f, "bad block size: {size} (only 512 byte blocks supported)")
}
Error::InvalidOffset => write!(f, "invalid seek offset"),
Error::DiskFull => write!(f, "disk full"),
Error::DirAlreadyExists => write!(f, "directory already exists"),
Error::LockError => write!(f, "already locked"),
}
}
}

#[cfg(feature = "core-error")]
impl<E> core::error::Error for Error<E> where E: core::fmt::Debug + core::fmt::Display {}

/// A handle to a volume.
///
/// A volume is a partition with a filesystem within it.
Expand Down
27 changes: 27 additions & 0 deletions src/sdcard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,33 @@ pub enum Error {
GpioError,
}

impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
Error::Transport => write!(f, "error from SPI peripheral"),
Error::CantEnableCRC => write!(f, "failed to enable CRC checking"),
Error::TimeoutReadBuffer => write!(f, "timeout when reading data"),
Error::TimeoutWaitNotBusy => write!(f, "timeout when waiting for card to not be busy"),
Error::TimeoutCommand(command) => write!(f, "timeout when executing command {command}"),
Error::TimeoutACommand(command) => write!(
f,
"timeout when executing application-specific command {command}"
),
Error::Cmd58Error => write!(f, "bad response from command 58"),
Error::RegisterReadError => write!(f, "failed to read Card Specific Data register"),
Error::CrcError(_, _) => write!(f, "CRC mismatch"),
Error::ReadError => write!(f, "read error"),
Error::WriteError => write!(f, "write error"),
Error::BadState => write!(f, "cannot perform operation with card in thiis state"),
Error::CardNotFound => write!(f, "card not found"),
Error::GpioError => write!(f, "cannot set GPIO pin"),
}
}
}

#[cfg(feature = "core-error")]
impl core::error::Error for Error {}

/// The different types of card we support.
#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand Down