Skip to main content

adxl355/
error.rs

1//! Typed ADXL355 driver and adapter errors.
2
3use core::fmt;
4
5/// Device state required by an operation.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum StateRequirement {
8    /// The caller must complete a successful device probe first.
9    Probed,
10}
11
12impl fmt::Display for StateRequirement {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        match self {
15            Self::Probed => write!(f, "a successful probe"),
16        }
17    }
18}
19
20/// Driver error with the underlying transport error preserved as `E`.
21///
22/// This type is allocation-free and remains usable in `no_std` builds. Match on
23/// [`Error::Transport`] or [`Error::Restore`] to inspect and recover the original
24/// bus/backend cause.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub enum Error<E> {
27    /// A read or write failed in the configured transport.
28    Transport(E),
29    /// Probe returned identity bytes that do not identify an ADXL355.
30    InvalidIdentity {
31        /// Analog Devices identifier byte read from `DEVID_AD`.
32        devid_ad: u8,
33        /// MEMS identifier byte read from `DEVID_MST`.
34        devid_mst: u8,
35        /// Part identifier byte read from `PARTID`.
36        partid: u8,
37    },
38    /// A transport returned a payload whose length violated the exact-length contract.
39    InvalidResponseLength {
40        /// First register requested by the driver.
41        register: u8,
42        /// Required payload length.
43        expected: usize,
44        /// Payload length returned by the transport.
45        actual: usize,
46    },
47    /// The device lifecycle does not permit the requested operation.
48    InvalidState {
49        /// State that must be established before retrying.
50        required: StateRequirement,
51    },
52    /// A register value does not represent a supported configuration.
53    InvalidConfiguration {
54        /// Register containing the unsupported value.
55        register: u8,
56        /// Unsupported raw register value.
57        value: u8,
58    },
59    /// Coherent data was not available within the driver's bounded retry sequence.
60    NotReady,
61    /// A bounded operation timed out.
62    Timeout,
63    /// The requested feature is not supported by this implementation.
64    Unsupported,
65    /// Restoring a previously active hardware state failed.
66    Restore(E),
67}
68
69impl<E> Error<E> {
70    /// Return the preserved transport cause when the error came from bus access.
71    pub fn transport_cause(&self) -> Option<&E> {
72        match self {
73            Self::Transport(source) | Self::Restore(source) => Some(source),
74            _ => None,
75        }
76    }
77
78    /// Return `true` when the failure happened while restoring device state.
79    pub const fn is_restore_failure(&self) -> bool {
80        matches!(self, Self::Restore(_))
81    }
82}
83
84impl<E: fmt::Display> fmt::Display for Error<E> {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        match self {
87            Self::Transport(source) => write!(f, "transport error: {source}"),
88            Self::InvalidIdentity {
89                devid_ad,
90                devid_mst,
91                partid,
92            } => write!(
93                f,
94                "invalid ADXL355 identity (DEVID_AD=0x{devid_ad:02X}, DEVID_MST=0x{devid_mst:02X}, PARTID=0x{partid:02X})"
95            ),
96            Self::InvalidResponseLength {
97                register,
98                expected,
99                actual,
100            } => write!(
101                f,
102                "invalid response length at register 0x{register:02X}: expected {expected}, received {actual}"
103            ),
104            Self::InvalidState { required } => {
105                write!(f, "invalid device state; operation requires {required}")
106            }
107            Self::InvalidConfiguration { register, value } => write!(
108                f,
109                "invalid configuration value 0x{value:02X} in register 0x{register:02X}"
110            ),
111            Self::NotReady => write!(f, "data not ready"),
112            Self::Timeout => write!(f, "operation timed out"),
113            Self::Unsupported => write!(f, "unsupported operation"),
114            Self::Restore(source) => write!(f, "failed to restore device state: {source}"),
115        }
116    }
117}
118
119#[cfg(feature = "std")]
120impl<E> std::error::Error for Error<E>
121where
122    E: std::error::Error + 'static,
123{
124    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
125        match self {
126            Self::Transport(source) | Self::Restore(source) => Some(source),
127            _ => None,
128        }
129    }
130}