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))]
9pub enum ErrorKind {
10    // Errors related to core traits
11    /// Underlying bus error (I2C, SPI, etc.)
12    Bus,
13    /// Invalid date/time value provided
14    InvalidDateTime,
15
16    // Errors related to extended
17    /// Invalid alarm configuration
18    InvalidAlarmConfig,
19    /// The specified square wave frequency is not supported by the RTC
20    UnsupportedSqwFrequency,
21    /// Invalid register address
22    InvalidAddress,
23    /// NVRAM address out of bounds
24    NvramOutOfBounds,
25    /// NVRAM is write protected
26    NvramWriteProtected,
27
28    /// Any other error not covered above
29    Other,
30}
31
32/// Trait that RTC driver error types should implement.
33///
34/// Allows converting driver-specific errors into standard categories.
35/// Drivers can either define custom error types or use `ErrorKind` directly.
36pub trait Error: core::fmt::Debug {
37    /// Map a driver-specific error into a general category
38    fn kind(&self) -> ErrorKind;
39}
40
41/// RTC error type trait.
42///
43/// This just defines the error type, to be used by the other traits.
44pub trait ErrorType {
45    /// Error type
46    type Error: Error;
47}
48
49/// Allows `ErrorKind` to be used directly as an error type.
50///
51/// Simple drivers can use `type Error = ErrorKind` instead of defining custom errors.
52impl Error for ErrorKind {
53    #[inline]
54    fn kind(&self) -> ErrorKind {
55        *self
56    }
57}
58
59// blanket impl for all `&mut T`
60impl<T: ErrorType + ?Sized> ErrorType for &mut T {
61    type Error = T::Error;
62}
63
64impl core::fmt::Display for ErrorKind {
65    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66        match self {
67            Self::Bus => write!(f, "Underlying bus error occurred"),
68            Self::InvalidDateTime => write!(f, "Invalid datetime value provided"),
69            Self::InvalidAlarmConfig => write!(f, "Invalid alarm configuration"),
70            Self::UnsupportedSqwFrequency => write!(
71                f,
72                "The specified square wave frequency is not supported by the RTC"
73            ),
74            Self::InvalidAddress => write!(f, "Invalid register address"),
75            Self::NvramOutOfBounds => write!(f, "NVRAM address out of bounds"),
76            Self::NvramWriteProtected => write!(f, "NVRAM is write protected"),
77            Self::Other => write!(
78                f,
79                "A different error occurred. The original error may contain more information"
80            ),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    // Mock error type for testing
90    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
91    enum MockRtcError {
92        I2cError,
93        InvalidDateTime,
94        InvalidAlarmTime,
95        UnsupportedSqwFrequency,
96        InvalidRegisterAddress,
97        NvramAddressOutOfBounds,
98        NvramWriteProtected,
99        UnknownError,
100    }
101
102    impl Error for MockRtcError {
103        fn kind(&self) -> ErrorKind {
104            match self {
105                MockRtcError::I2cError => ErrorKind::Bus,
106                MockRtcError::InvalidDateTime => ErrorKind::InvalidDateTime,
107                MockRtcError::InvalidAlarmTime => ErrorKind::InvalidAlarmConfig,
108                MockRtcError::UnsupportedSqwFrequency => ErrorKind::UnsupportedSqwFrequency,
109                MockRtcError::InvalidRegisterAddress => ErrorKind::InvalidAddress,
110                MockRtcError::NvramAddressOutOfBounds => ErrorKind::NvramOutOfBounds,
111                MockRtcError::NvramWriteProtected => ErrorKind::NvramWriteProtected,
112                MockRtcError::UnknownError => ErrorKind::Other,
113            }
114        }
115    }
116
117    #[test]
118    fn test_error_kind_mapping() {
119        assert_eq!(MockRtcError::I2cError.kind(), ErrorKind::Bus);
120        assert_eq!(
121            MockRtcError::InvalidDateTime.kind(),
122            ErrorKind::InvalidDateTime
123        );
124        assert_eq!(
125            MockRtcError::InvalidAlarmTime.kind(),
126            ErrorKind::InvalidAlarmConfig
127        );
128        assert_eq!(
129            MockRtcError::UnsupportedSqwFrequency.kind(),
130            ErrorKind::UnsupportedSqwFrequency
131        );
132        assert_eq!(
133            MockRtcError::InvalidRegisterAddress.kind(),
134            ErrorKind::InvalidAddress
135        );
136        assert_eq!(
137            MockRtcError::NvramAddressOutOfBounds.kind(),
138            ErrorKind::NvramOutOfBounds
139        );
140        assert_eq!(
141            MockRtcError::NvramWriteProtected.kind(),
142            ErrorKind::NvramWriteProtected
143        );
144        assert_eq!(MockRtcError::UnknownError.kind(), ErrorKind::Other);
145    }
146
147    #[test]
148    fn test_error_kind_equality() {
149        assert_eq!(ErrorKind::Bus, ErrorKind::Bus);
150        assert_ne!(ErrorKind::Bus, ErrorKind::InvalidDateTime);
151        assert_ne!(
152            ErrorKind::InvalidAlarmConfig,
153            ErrorKind::UnsupportedSqwFrequency
154        );
155        assert_ne!(ErrorKind::NvramOutOfBounds, ErrorKind::NvramWriteProtected);
156    }
157}