rtc_hal/
error.rs

1//! # RTC Error Types and Classification
2//!
3//! This module provides a standardized error handling framework for RTC drivers,
4//! allowing consistent error categorization across different RTC hardware implementations.
5
6/// Common categories of errors for RTC drivers
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9#[non_exhaustive]
10pub enum ErrorKind {
11    // Errors related to core traits
12    /// Underlying bus error (I2C, SPI, etc.)
13    Bus,
14    /// Invalid date/time value provided
15    InvalidDateTime,
16
17    // Errors related to extended
18    /// Invalid alarm configuration
19    InvalidAlarmConfig,
20    /// The specified square wave frequency is not supported by the RTC
21    UnsupportedSqwFrequency,
22    /// Invalid register address
23    InvalidAddress,
24    /// NVRAM address out of bounds
25    NvramOutOfBounds,
26    /// NVRAM is write protected
27    NvramWriteProtected,
28
29    /// Any other error not covered above
30    Other,
31}
32
33/// Trait that RTC driver error types should implement.
34///
35/// Allows converting driver-specific errors into standard categories.
36/// Drivers can either define custom error types or use `ErrorKind` directly.
37pub trait Error: core::fmt::Debug {
38    /// Map a driver-specific error into a general category
39    fn kind(&self) -> ErrorKind;
40}
41
42/// RTC error type trait.
43///
44/// This just defines the error type, to be used by the other traits.
45pub trait ErrorType {
46    /// Error type
47    type Error: Error;
48}
49
50/// Allows `ErrorKind` to be used directly as an error type.
51///
52/// Simple drivers can use `type Error = ErrorKind` instead of defining custom errors.
53impl Error for ErrorKind {
54    #[inline]
55    fn kind(&self) -> ErrorKind {
56        *self
57    }
58}
59
60// blanket impl for all `&mut T`
61impl<T: ErrorType + ?Sized> ErrorType for &mut T {
62    type Error = T::Error;
63}
64
65impl core::fmt::Display for ErrorKind {
66    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
67        match self {
68            Self::Bus => write!(f, "Underlying bus error occurred"),
69            Self::InvalidDateTime => write!(f, "Invalid datetime value provided"),
70            Self::InvalidAlarmConfig => write!(f, "Invalid alarm configuration"),
71            Self::UnsupportedSqwFrequency => write!(
72                f,
73                "The specified square wave frequency is not supported by the RTC"
74            ),
75            Self::InvalidAddress => write!(f, "Invalid register address"),
76            Self::NvramOutOfBounds => write!(f, "NVRAM address out of bounds"),
77            Self::NvramWriteProtected => write!(f, "NVRAM is write protected"),
78            Self::Other => write!(
79                f,
80                "A different error occurred. The original error may contain more information"
81            ),
82        }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    // Mock error type for testing
91    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
92    enum MockRtcError {
93        I2cError,
94        InvalidDateTime,
95        InvalidAlarmTime,
96        UnsupportedSqwFrequency,
97        InvalidRegisterAddress,
98        NvramAddressOutOfBounds,
99        NvramWriteProtected,
100        UnknownError,
101    }
102
103    impl Error for MockRtcError {
104        fn kind(&self) -> ErrorKind {
105            match self {
106                MockRtcError::I2cError => ErrorKind::Bus,
107                MockRtcError::InvalidDateTime => ErrorKind::InvalidDateTime,
108                MockRtcError::InvalidAlarmTime => ErrorKind::InvalidAlarmConfig,
109                MockRtcError::UnsupportedSqwFrequency => ErrorKind::UnsupportedSqwFrequency,
110                MockRtcError::InvalidRegisterAddress => ErrorKind::InvalidAddress,
111                MockRtcError::NvramAddressOutOfBounds => ErrorKind::NvramOutOfBounds,
112                MockRtcError::NvramWriteProtected => ErrorKind::NvramWriteProtected,
113                _ => ErrorKind::Other,
114            }
115        }
116    }
117
118    #[test]
119    fn test_error_kind_mapping() {
120        assert_eq!(MockRtcError::I2cError.kind(), ErrorKind::Bus);
121        assert_eq!(
122            MockRtcError::InvalidDateTime.kind(),
123            ErrorKind::InvalidDateTime
124        );
125        assert_eq!(
126            MockRtcError::InvalidAlarmTime.kind(),
127            ErrorKind::InvalidAlarmConfig
128        );
129        assert_eq!(
130            MockRtcError::UnsupportedSqwFrequency.kind(),
131            ErrorKind::UnsupportedSqwFrequency
132        );
133        assert_eq!(
134            MockRtcError::InvalidRegisterAddress.kind(),
135            ErrorKind::InvalidAddress
136        );
137        assert_eq!(
138            MockRtcError::NvramAddressOutOfBounds.kind(),
139            ErrorKind::NvramOutOfBounds
140        );
141        assert_eq!(
142            MockRtcError::NvramWriteProtected.kind(),
143            ErrorKind::NvramWriteProtected
144        );
145        assert_eq!(MockRtcError::UnknownError.kind(), ErrorKind::Other);
146    }
147
148    #[test]
149    fn test_error_kind_equality() {
150        assert_eq!(ErrorKind::Bus, ErrorKind::Bus);
151        assert_ne!(ErrorKind::Bus, ErrorKind::InvalidDateTime);
152        assert_ne!(
153            ErrorKind::InvalidAlarmConfig,
154            ErrorKind::UnsupportedSqwFrequency
155        );
156        assert_ne!(ErrorKind::NvramOutOfBounds, ErrorKind::NvramWriteProtected);
157    }
158
159    #[test]
160    fn test_error_kind_returns_self() {
161        let error = ErrorKind::Other;
162        assert_eq!(error.kind(), ErrorKind::Other);
163    }
164
165    #[test]
166    fn test_error_kind_display_messages() {
167        assert_eq!(
168            format!("{}", ErrorKind::Bus),
169            "Underlying bus error occurred"
170        );
171
172        assert_eq!(
173            format!("{}", ErrorKind::InvalidDateTime),
174            "Invalid datetime value provided"
175        );
176
177        assert_eq!(
178            format!("{}", ErrorKind::InvalidAlarmConfig),
179            "Invalid alarm configuration"
180        );
181
182        assert_eq!(
183            format!("{}", ErrorKind::UnsupportedSqwFrequency),
184            "The specified square wave frequency is not supported by the RTC"
185        );
186
187        assert_eq!(
188            format!("{}", ErrorKind::InvalidAddress),
189            "Invalid register address"
190        );
191
192        assert_eq!(
193            format!("{}", ErrorKind::NvramOutOfBounds),
194            "NVRAM address out of bounds"
195        );
196
197        assert_eq!(
198            format!("{}", ErrorKind::NvramWriteProtected),
199            "NVRAM is write protected"
200        );
201
202        assert_eq!(
203            format!("{}", ErrorKind::Other),
204            "A different error occurred. The original error may contain more information"
205        );
206    }
207}