use core::fmt;
#[derive(Debug)]
pub enum FSError {
DeviceError(alloc::string::String),
FormatError(&'static str),
NoSuchVolume,
#[cfg(target_os = "none")]
FilenameError(embedded_sdmmc::FilenameError),
TooManyOpenVolumes,
TooManyOpenDirs,
TooManyOpenFiles,
BadHandle,
NotFound,
FileAlreadyOpen,
DirAlreadyOpen,
OpenedDirAsFile,
OpenedFileAsDir,
DeleteDirAsFile,
VolumeStillInUse,
VolumeAlreadyOpen,
Unsupported,
EndOfFile,
BadCluster,
ConversionError,
NotEnoughSpace,
AllocationError,
UnterminatedFatChain,
ReadOnly,
FileAlreadyExists,
BadBlockSize(u16),
InvalidOffset,
DiskFull,
DirAlreadyExists,
Deadlock,
PermissionDenied,
ConnectionRefused,
ConnectionReset,
ConnectionAborted,
NotConnected,
AddrInUse,
AddrNotAvailable,
BrokenPipe,
InvalidInput,
InvalidData,
TimedOut,
Interrupted,
WriteZero,
Other,
}
#[cfg(target_os = "none")]
impl<T: fmt::Debug + core::error::Error> From<embedded_sdmmc::Error<T>> for FSError {
fn from(value: embedded_sdmmc::Error<T>) -> Self {
use embedded_sdmmc::Error::*;
match value {
DeviceError(e) => Self::DeviceError(alloc::format!("{e:?}")),
FormatError(e) => Self::FormatError(e),
NoSuchVolume => Self::NoSuchVolume,
FilenameError(e) => Self::FilenameError(e),
TooManyOpenVolumes => Self::TooManyOpenVolumes,
TooManyOpenDirs => Self::TooManyOpenDirs,
TooManyOpenFiles => Self::TooManyOpenFiles,
BadHandle => Self::BadHandle,
NotFound => Self::NotFound,
FileAlreadyOpen => Self::FileAlreadyOpen,
DirAlreadyOpen => Self::DirAlreadyOpen,
OpenedDirAsFile => Self::OpenedDirAsFile,
OpenedFileAsDir => Self::OpenedFileAsDir,
DeleteNonEmptyDir => Self::DeleteDirAsFile,
VolumeStillInUse => Self::VolumeStillInUse,
VolumeAlreadyOpen => Self::VolumeAlreadyOpen,
Unsupported => Self::Unsupported,
EndOfFile => Self::EndOfFile,
BadCluster => Self::BadCluster,
ConversionError => Self::ConversionError,
NotEnoughSpace => Self::NotEnoughSpace,
AllocationError => Self::AllocationError,
UnterminatedFatChain => Self::UnterminatedFatChain,
ReadOnly => Self::ReadOnly,
FileAlreadyExists => Self::FileAlreadyExists,
BadBlockSize(x) => Self::BadBlockSize(x),
InvalidOffset => Self::InvalidOffset,
DiskFull => Self::DiskFull,
DirAlreadyExists => Self::DirAlreadyExists,
LockError => Self::Other,
}
}
}
#[cfg(not(target_os = "none"))]
impl From<std::io::Error> for FSError {
fn from(value: std::io::Error) -> Self {
value.kind().into()
}
}
#[cfg(not(target_os = "none"))]
impl From<std::io::ErrorKind> for FSError {
fn from(value: std::io::ErrorKind) -> Self {
use std::io::ErrorKind::*;
match value {
NotFound => Self::NotFound,
PermissionDenied => Self::PermissionDenied,
ConnectionRefused => Self::ConnectionRefused,
ConnectionReset => Self::ConnectionReset,
ConnectionAborted => Self::ConnectionAborted,
NotConnected => Self::NotConnected,
AddrInUse => Self::AddrInUse,
AddrNotAvailable => Self::AddrNotAvailable,
BrokenPipe => Self::BrokenPipe,
AlreadyExists => Self::FileAlreadyExists,
WouldBlock => Self::Other,
InvalidInput => Self::InvalidInput,
InvalidData => Self::InvalidData,
TimedOut => Self::TimedOut,
WriteZero => Self::WriteZero,
Interrupted => Self::Interrupted,
Unsupported => Self::Unsupported,
UnexpectedEof => Self::EndOfFile,
OutOfMemory => Self::DiskFull,
Other => Self::Other,
_ => Self::Other,
}
}
}
impl From<embedded_io::ErrorKind> for FSError {
fn from(value: embedded_io::ErrorKind) -> Self {
use embedded_io::ErrorKind::*;
match value {
Other => Self::Other,
NotFound => Self::NotFound,
PermissionDenied => Self::PermissionDenied,
ConnectionRefused => Self::ConnectionRefused,
ConnectionReset => Self::ConnectionReset,
ConnectionAborted => Self::ConnectionAborted,
NotConnected => Self::NotConnected,
AddrInUse => Self::AddrInUse,
AddrNotAvailable => Self::AddrNotAvailable,
BrokenPipe => Self::BrokenPipe,
AlreadyExists => Self::FileAlreadyExists,
InvalidInput => Self::InvalidInput,
InvalidData => Self::InvalidData,
TimedOut => Self::TimedOut,
Interrupted => Self::Interrupted,
Unsupported => Self::Unsupported,
OutOfMemory => Self::DiskFull,
WriteZero => Self::WriteZero,
_ => Self::Other,
}
}
}
impl fmt::Display for FSError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use FSError::*;
match self {
DeviceError(e) => write!(f, "device error: {e}"),
FormatError(e) => write!(f, "format error: {e}"),
NoSuchVolume => write!(f, "no such volume"),
#[cfg(target_os = "none")]
FilenameError(e) => write!(f, "filename error: {e:?}"),
TooManyOpenVolumes => write!(f, "too many open volumes"),
TooManyOpenDirs => write!(f, "too many open dirs"),
TooManyOpenFiles => write!(f, "too many open files"),
BadHandle => write!(f, "bad handle"),
NotFound => write!(f, "not found"),
FileAlreadyOpen => write!(f, "file already open"),
DirAlreadyOpen => write!(f, "dir already open"),
OpenedDirAsFile => write!(f, "opened dir as file"),
OpenedFileAsDir => write!(f, "opened file as dir"),
DeleteDirAsFile => write!(f, "delete dir as file"),
VolumeStillInUse => write!(f, "volume still in use"),
VolumeAlreadyOpen => write!(f, "volume already open"),
Unsupported => write!(f, "unsupported"),
EndOfFile => write!(f, "end of file"),
BadCluster => write!(f, "bad cluster"),
ConversionError => write!(f, "conversion error"),
NotEnoughSpace => write!(f, "not enough space"),
AllocationError => write!(f, "allocation error"),
UnterminatedFatChain => write!(f, "unterminated fat chain"),
ReadOnly => write!(f, "read only"),
FileAlreadyExists => write!(f, "file already exists"),
BadBlockSize(_) => write!(f, "bad block size"),
InvalidOffset => write!(f, "invalid offset"),
DiskFull => write!(f, "disk full"),
DirAlreadyExists => write!(f, "dir already exists"),
PermissionDenied => write!(f, "permission denied"),
ConnectionRefused => write!(f, "connection refused"),
ConnectionReset => write!(f, "connection reset"),
ConnectionAborted => write!(f, "connection aborted"),
NotConnected => write!(f, "not connected"),
AddrInUse => write!(f, "addr in use"),
AddrNotAvailable => write!(f, "addr not available"),
BrokenPipe => write!(f, "broken pipe"),
InvalidInput => write!(f, "invalid input"),
InvalidData => write!(f, "invalid data"),
TimedOut => write!(f, "timed out"),
Interrupted => write!(f, "interrupted"),
WriteZero => write!(f, "write zero"),
Deadlock => write!(f, "deadlock"),
Other => write!(f, "other"),
}
}
}
#[derive(Debug)]
pub enum NetworkError {
NotInitialized,
AlreadyInitialized,
UnknownPeer,
CannotBind,
PeerListFull,
RecvError,
SendError,
NetThreadDeallocated,
OutMessageTooBig,
UnexpectedResp,
Decode(postcard::Error),
Uart(&'static str),
Error(&'static str),
OwnedError(alloc::string::String),
Other(u32),
}
impl core::error::Error for NetworkError {}
impl From<postcard::Error> for NetworkError {
fn from(v: postcard::Error) -> Self {
Self::Decode(v)
}
}
#[cfg(target_os = "none")]
impl From<esp_hal::uart::RxError> for NetworkError {
fn from(value: esp_hal::uart::RxError) -> Self {
let msg = match value {
esp_hal::uart::RxError::FifoOverflowed => "RX FIFO overflowed",
esp_hal::uart::RxError::GlitchOccurred => "glitch on RX line",
esp_hal::uart::RxError::FrameFormatViolated => "framing error on RX line",
esp_hal::uart::RxError::ParityMismatch => "parity error on RX line",
_ => "unknown RX error",
};
Self::Uart(msg)
}
}
#[cfg(target_os = "none")]
impl From<esp_hal::uart::TxError> for NetworkError {
fn from(_: esp_hal::uart::TxError) -> Self {
Self::Uart("unknown TX error")
}
}
#[cfg(target_os = "none")]
impl From<esp_hal::uart::IoError> for NetworkError {
fn from(err: esp_hal::uart::IoError) -> Self {
match err {
esp_hal::uart::IoError::Tx(err) => err.into(),
esp_hal::uart::IoError::Rx(err) => err.into(),
_ => Self::Uart("unknown IO error"),
}
}
}
#[cfg(target_os = "none")]
impl From<embedded_io::ReadExactError<esp_hal::uart::IoError>> for NetworkError {
fn from(err: embedded_io::ReadExactError<esp_hal::uart::IoError>) -> Self {
match err {
embedded_io::ReadExactError::UnexpectedEof => Self::Uart("unexpected EoF"),
embedded_io::ReadExactError::Other(err) => err.into(),
}
}
}
impl fmt::Display for NetworkError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use NetworkError::*;
match self {
NotInitialized => write!(f, "cannot send messages with Wi-Fi turned off"),
AlreadyInitialized => write!(f, "tried to initialize networking twice"),
UnknownPeer => write!(f, "cannot send messages to disconnected device"),
CannotBind => write!(f, "cannot find free address for networking"),
PeerListFull => write!(f, "cannot connect more devices"),
RecvError => write!(f, "cannot fetch network message"),
SendError => write!(f, "cannot send network message"),
NetThreadDeallocated => write!(f, "thread handling networking is already deallocated"),
OutMessageTooBig => write!(f, "outgoing message is too big"),
UnexpectedResp => write!(f, "unexpected response"),
Decode(err) => write!(f, "decode message: {err}"),
Uart(err) => write!(f, "SPI error: {err}"),
Error(err) => write!(f, "network error: {err}"),
OwnedError(err) => write!(f, "network error: {err}"),
Other(n) => write!(f, "network error #{n}"),
}
}
}