ds3231_rtc/
error.rs

1//! Error type definitions for the DS3231 RTC driver.
2//!
3//! This module defines the `Error` enum and helper functions
4//! for classifying and handling DS3231-specific failures.
5
6use rtc_hal::datetime::DateTimeError;
7
8/// DS3231 driver errors
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum Error<I2cError>
12where
13    I2cError: core::fmt::Debug,
14{
15    /// I2C communication error
16    I2c(I2cError),
17    /// Invalid register address
18    InvalidAddress,
19    /// The specified square wave frequency is not supported by the RTC
20    UnsupportedSqwFrequency,
21    /// Invalid date/time parameters provided by user
22    DateTime(DateTimeError),
23    /// Invalid Base Century (It should be either 19,20,21)
24    InvalidBaseCentury,
25}
26
27impl<I2cError> core::fmt::Display for Error<I2cError>
28where
29    I2cError: core::fmt::Debug + core::fmt::Display,
30{
31    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32        match self {
33            Error::I2c(e) => write!(f, "I2C communication error: {e}"),
34            Error::InvalidAddress => write!(f, "Invalid register address"),
35            Error::DateTime(e) => write!(f, "Invalid date/time values: {e}"),
36            Error::UnsupportedSqwFrequency => write!(f, "Unsupported square wave frequency"),
37            Error::InvalidBaseCentury => write!(f, "Base century must be 19 or greater"),
38        }
39    }
40}
41
42impl<I2cError> core::error::Error for Error<I2cError> where
43    I2cError: core::fmt::Debug + core::fmt::Display
44{
45}
46
47// /// Converts an [`I2cError`] into an [`Error`] by wrapping it in the
48// /// [`Error::I2c`] variant.
49// ///
50impl<I2cError> From<I2cError> for Error<I2cError>
51where
52    I2cError: core::fmt::Debug,
53{
54    fn from(value: I2cError) -> Self {
55        Error::I2c(value)
56    }
57}
58
59impl<I2cError> rtc_hal::error::Error for Error<I2cError>
60where
61    I2cError: core::fmt::Debug,
62{
63    fn kind(&self) -> rtc_hal::error::ErrorKind {
64        match self {
65            Error::I2c(_) => rtc_hal::error::ErrorKind::Bus,
66            Error::InvalidAddress => rtc_hal::error::ErrorKind::InvalidAddress,
67            Error::DateTime(_) => rtc_hal::error::ErrorKind::InvalidDateTime,
68            Error::UnsupportedSqwFrequency => rtc_hal::error::ErrorKind::UnsupportedSqwFrequency,
69            Error::InvalidBaseCentury => rtc_hal::error::ErrorKind::InvalidDateTime,
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use rtc_hal::datetime::DateTimeError;
78    use rtc_hal::error::{Error as RtcError, ErrorKind};
79
80    #[test]
81    fn test_from_i2c_error() {
82        #[derive(Debug, PartialEq, Eq)]
83        struct DummyI2cError(u8);
84
85        let e = Error::from(DummyI2cError(42));
86        assert_eq!(e, Error::I2c(DummyI2cError(42)));
87    }
88
89    #[test]
90    fn test_error_kind_mappings() {
91        // I2c variant
92        let e: Error<&str> = Error::I2c("oops");
93        assert_eq!(e.kind(), ErrorKind::Bus);
94
95        // InvalidAddress
96        let e: Error<&str> = Error::InvalidAddress;
97        assert_eq!(e.kind(), ErrorKind::InvalidAddress);
98
99        // DateTime
100        let e: Error<&str> = Error::DateTime(DateTimeError::InvalidDay);
101        assert_eq!(e.kind(), ErrorKind::InvalidDateTime);
102
103        // UnsupportedSqwFrequency
104        let e: Error<&str> = Error::UnsupportedSqwFrequency;
105        assert_eq!(e.kind(), ErrorKind::UnsupportedSqwFrequency);
106
107        // InvalidBaseCentury
108        let e: Error<&str> = Error::InvalidBaseCentury;
109        assert_eq!(e.kind(), ErrorKind::InvalidDateTime);
110    }
111
112    #[derive(Debug, PartialEq, Eq)]
113    struct MockI2cError {
114        code: u8,
115        message: &'static str,
116    }
117
118    impl core::fmt::Display for MockI2cError {
119        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120            write!(f, "I2C Error {}: {}", self.code, self.message)
121        }
122    }
123
124    #[test]
125    fn test_display_all_variants() {
126        let errors = vec![
127            (
128                Error::I2c(MockI2cError {
129                    code: 1,
130                    message: "test",
131                }),
132                "I2C communication error: I2C Error 1: test",
133            ),
134            (Error::InvalidAddress, "Invalid register address"),
135            (
136                Error::DateTime(DateTimeError::InvalidMonth),
137                "Invalid date/time values: invalid month",
138            ),
139            (
140                Error::UnsupportedSqwFrequency,
141                "Unsupported square wave frequency",
142            ),
143            (
144                Error::InvalidBaseCentury,
145                "Base century must be 19 or greater",
146            ),
147        ];
148
149        for (error, expected) in errors {
150            assert_eq!(format!("{error}"), expected);
151        }
152    }
153}