#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum ErrorKind {
Bus,
InvalidDateTime,
InvalidAlarmConfig,
UnsupportedSqwFrequency,
InvalidAddress,
NvramOutOfBounds,
NvramWriteProtected,
Other,
}
pub trait Error: core::fmt::Debug {
fn kind(&self) -> ErrorKind;
}
pub trait ErrorType {
type Error: Error;
}
impl Error for ErrorKind {
#[inline]
fn kind(&self) -> ErrorKind {
*self
}
}
impl<T: ErrorType + ?Sized> ErrorType for &mut T {
type Error = T::Error;
}
impl core::fmt::Display for ErrorKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Bus => write!(f, "Underlying bus error occurred"),
Self::InvalidDateTime => write!(f, "Invalid datetime value provided"),
Self::InvalidAlarmConfig => write!(f, "Invalid alarm configuration"),
Self::UnsupportedSqwFrequency => write!(
f,
"The specified square wave frequency is not supported by the RTC"
),
Self::InvalidAddress => write!(f, "Invalid register address"),
Self::NvramOutOfBounds => write!(f, "NVRAM address out of bounds"),
Self::NvramWriteProtected => write!(f, "NVRAM is write protected"),
Self::Other => write!(
f,
"A different error occurred. The original error may contain more information"
),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MockRtcError {
I2cError,
InvalidDateTime,
InvalidAlarmTime,
UnsupportedSqwFrequency,
InvalidRegisterAddress,
NvramAddressOutOfBounds,
NvramWriteProtected,
UnknownError,
}
impl Error for MockRtcError {
fn kind(&self) -> ErrorKind {
match self {
MockRtcError::I2cError => ErrorKind::Bus,
MockRtcError::InvalidDateTime => ErrorKind::InvalidDateTime,
MockRtcError::InvalidAlarmTime => ErrorKind::InvalidAlarmConfig,
MockRtcError::UnsupportedSqwFrequency => ErrorKind::UnsupportedSqwFrequency,
MockRtcError::InvalidRegisterAddress => ErrorKind::InvalidAddress,
MockRtcError::NvramAddressOutOfBounds => ErrorKind::NvramOutOfBounds,
MockRtcError::NvramWriteProtected => ErrorKind::NvramWriteProtected,
_ => ErrorKind::Other,
}
}
}
#[test]
fn test_error_kind_mapping() {
assert_eq!(MockRtcError::I2cError.kind(), ErrorKind::Bus);
assert_eq!(
MockRtcError::InvalidDateTime.kind(),
ErrorKind::InvalidDateTime
);
assert_eq!(
MockRtcError::InvalidAlarmTime.kind(),
ErrorKind::InvalidAlarmConfig
);
assert_eq!(
MockRtcError::UnsupportedSqwFrequency.kind(),
ErrorKind::UnsupportedSqwFrequency
);
assert_eq!(
MockRtcError::InvalidRegisterAddress.kind(),
ErrorKind::InvalidAddress
);
assert_eq!(
MockRtcError::NvramAddressOutOfBounds.kind(),
ErrorKind::NvramOutOfBounds
);
assert_eq!(
MockRtcError::NvramWriteProtected.kind(),
ErrorKind::NvramWriteProtected
);
assert_eq!(MockRtcError::UnknownError.kind(), ErrorKind::Other);
}
#[test]
fn test_error_kind_equality() {
assert_eq!(ErrorKind::Bus, ErrorKind::Bus);
assert_ne!(ErrorKind::Bus, ErrorKind::InvalidDateTime);
assert_ne!(
ErrorKind::InvalidAlarmConfig,
ErrorKind::UnsupportedSqwFrequency
);
assert_ne!(ErrorKind::NvramOutOfBounds, ErrorKind::NvramWriteProtected);
}
#[test]
fn test_error_kind_returns_self() {
let error = ErrorKind::Other;
assert_eq!(error.kind(), ErrorKind::Other);
}
#[test]
fn test_error_kind_display_messages() {
assert_eq!(
format!("{}", ErrorKind::Bus),
"Underlying bus error occurred"
);
assert_eq!(
format!("{}", ErrorKind::InvalidDateTime),
"Invalid datetime value provided"
);
assert_eq!(
format!("{}", ErrorKind::InvalidAlarmConfig),
"Invalid alarm configuration"
);
assert_eq!(
format!("{}", ErrorKind::UnsupportedSqwFrequency),
"The specified square wave frequency is not supported by the RTC"
);
assert_eq!(
format!("{}", ErrorKind::InvalidAddress),
"Invalid register address"
);
assert_eq!(
format!("{}", ErrorKind::NvramOutOfBounds),
"NVRAM address out of bounds"
);
assert_eq!(
format!("{}", ErrorKind::NvramWriteProtected),
"NVRAM is write protected"
);
assert_eq!(
format!("{}", ErrorKind::Other),
"A different error occurred. The original error may contain more information"
);
}
}