use rtc_hal::datetime::DateTimeError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<I2cError>
where
I2cError: core::fmt::Debug,
{
I2c(I2cError),
InvalidAddress,
UnsupportedSqwFrequency,
DateTime(DateTimeError),
NvramOutOfBounds,
}
impl<I2cError> core::fmt::Display for Error<I2cError>
where
I2cError: core::fmt::Debug + core::fmt::Display,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Error::I2c(e) => write!(f, "I2C communication error: {e}"),
Error::InvalidAddress => write!(f, "Invalid NVRAM address"),
Error::DateTime(e) => write!(f, "Invalid date/time values: {e}"),
Error::UnsupportedSqwFrequency => write!(f, "Unsupported square wave frequency"),
Error::NvramOutOfBounds => write!(f, "NVRAM operation out of bounds"),
}
}
}
impl<I2cError> core::error::Error for Error<I2cError> where
I2cError: core::fmt::Debug + core::fmt::Display
{
}
impl<I2cError> From<I2cError> for Error<I2cError>
where
I2cError: core::fmt::Debug,
{
fn from(value: I2cError) -> Self {
Error::I2c(value)
}
}
impl<I2cError> rtc_hal::error::Error for Error<I2cError>
where
I2cError: core::fmt::Debug,
{
fn kind(&self) -> rtc_hal::error::ErrorKind {
match self {
Error::I2c(_) => rtc_hal::error::ErrorKind::Bus,
Error::InvalidAddress => rtc_hal::error::ErrorKind::InvalidAddress,
Error::DateTime(_) => rtc_hal::error::ErrorKind::InvalidDateTime,
Error::NvramOutOfBounds => rtc_hal::error::ErrorKind::NvramOutOfBounds,
Error::UnsupportedSqwFrequency => rtc_hal::error::ErrorKind::UnsupportedSqwFrequency,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rtc_hal::datetime::DateTimeError;
use rtc_hal::error::{Error as RtcError, ErrorKind};
#[test]
fn test_from_i2c_error() {
#[derive(Debug, PartialEq, Eq)]
struct DummyI2cError(u8);
let e = Error::from(DummyI2cError(42));
assert_eq!(e, Error::I2c(DummyI2cError(42)));
}
#[test]
fn test_error_kind_mappings() {
let e: Error<&str> = Error::I2c("oops");
assert_eq!(e.kind(), ErrorKind::Bus);
let e: Error<&str> = Error::InvalidAddress;
assert_eq!(e.kind(), ErrorKind::InvalidAddress);
let e: Error<&str> = Error::DateTime(DateTimeError::InvalidDay);
assert_eq!(e.kind(), ErrorKind::InvalidDateTime);
let e: Error<&str> = Error::UnsupportedSqwFrequency;
assert_eq!(e.kind(), ErrorKind::UnsupportedSqwFrequency);
let e: Error<&str> = Error::NvramOutOfBounds;
assert_eq!(e.kind(), ErrorKind::NvramOutOfBounds);
}
#[derive(Debug, PartialEq, Eq)]
struct MockI2cError {
code: u8,
message: &'static str,
}
impl core::fmt::Display for MockI2cError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "I2C Error {}: {}", self.code, self.message)
}
}
#[test]
fn test_display_all_variants() {
let errors = vec![
(
Error::I2c(MockI2cError {
code: 1,
message: "test",
}),
"I2C communication error: I2C Error 1: test",
),
(Error::InvalidAddress, "Invalid NVRAM address"),
(
Error::DateTime(DateTimeError::InvalidMonth),
"Invalid date/time values: invalid month",
),
(
Error::UnsupportedSqwFrequency,
"Unsupported square wave frequency",
),
(Error::NvramOutOfBounds, "NVRAM operation out of bounds"),
];
for (error, expected) in errors {
assert_eq!(format!("{error}"), expected);
}
}
}