Skip to main content

oxigdal_embedded/
error.rs

1//! Error types for embedded OxiGDAL operations
2//!
3//! This module provides error types optimized for no_std environments with minimal memory overhead.
4
5use core::fmt;
6
7#[cfg(feature = "std")]
8use std::error::Error as StdError;
9
10/// Result type alias for embedded operations
11pub type Result<T> = core::result::Result<T, EmbeddedError>;
12
13/// Error types for embedded OxiGDAL operations
14///
15/// Designed to be lightweight and suitable for no_std environments
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[non_exhaustive]
18pub enum EmbeddedError {
19    /// Memory allocation failed
20    AllocationFailed,
21
22    /// Memory pool exhausted
23    PoolExhausted,
24
25    /// Buffer too small for operation
26    BufferTooSmall {
27        /// Required size
28        required: usize,
29        /// Available size
30        available: usize,
31    },
32
33    /// Invalid buffer alignment
34    InvalidAlignment {
35        /// Required alignment
36        required: usize,
37        /// Actual alignment
38        actual: usize,
39    },
40
41    /// Operation not supported in current configuration
42    UnsupportedOperation,
43
44    /// Invalid parameter provided
45    InvalidParameter,
46
47    /// Out of bounds access
48    OutOfBounds {
49        /// Index attempted
50        index: usize,
51        /// Maximum valid index
52        max: usize,
53    },
54
55    /// Power mode transition failed
56    PowerModeTransitionFailed,
57
58    /// Real-time deadline missed
59    DeadlineMissed {
60        /// Actual time taken (microseconds)
61        actual_us: u64,
62        /// Deadline (microseconds)
63        deadline_us: u64,
64    },
65
66    /// Resource busy
67    ResourceBusy,
68
69    /// Timeout occurred
70    Timeout,
71
72    /// Initialization failed
73    InitializationFailed,
74
75    /// Hardware error
76    HardwareError,
77
78    /// Invalid state for operation
79    InvalidState,
80
81    /// Data format error
82    FormatError,
83
84    /// Checksum mismatch
85    ChecksumMismatch,
86
87    /// Target-specific error
88    TargetSpecific(u8),
89}
90
91impl EmbeddedError {
92    /// Returns true if the error is recoverable
93    pub const fn is_recoverable(&self) -> bool {
94        matches!(
95            self,
96            Self::BufferTooSmall { .. }
97                | Self::ResourceBusy
98                | Self::Timeout
99                | Self::DeadlineMissed { .. }
100        )
101    }
102
103    /// Returns true if the error is a resource exhaustion error
104    pub const fn is_resource_exhaustion(&self) -> bool {
105        matches!(
106            self,
107            Self::AllocationFailed | Self::PoolExhausted | Self::BufferTooSmall { .. }
108        )
109    }
110
111    /// Returns true if the error is a validation error
112    pub const fn is_validation_error(&self) -> bool {
113        matches!(
114            self,
115            Self::InvalidParameter
116                | Self::InvalidAlignment { .. }
117                | Self::OutOfBounds { .. }
118                | Self::FormatError
119                | Self::ChecksumMismatch
120        )
121    }
122
123    /// Returns the error code as a u32 for FFI boundaries
124    pub const fn error_code(&self) -> u32 {
125        match self {
126            Self::AllocationFailed => 1,
127            Self::PoolExhausted => 2,
128            Self::BufferTooSmall { .. } => 3,
129            Self::InvalidAlignment { .. } => 4,
130            Self::UnsupportedOperation => 5,
131            Self::InvalidParameter => 6,
132            Self::OutOfBounds { .. } => 7,
133            Self::PowerModeTransitionFailed => 8,
134            Self::DeadlineMissed { .. } => 9,
135            Self::ResourceBusy => 10,
136            Self::Timeout => 11,
137            Self::InitializationFailed => 12,
138            Self::HardwareError => 13,
139            Self::InvalidState => 14,
140            Self::FormatError => 15,
141            Self::ChecksumMismatch => 16,
142            Self::TargetSpecific(_) => 100,
143        }
144    }
145}
146
147impl fmt::Display for EmbeddedError {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        match self {
150            Self::AllocationFailed => write!(f, "Memory allocation failed"),
151            Self::PoolExhausted => write!(f, "Memory pool exhausted"),
152            Self::BufferTooSmall {
153                required,
154                available,
155            } => write!(
156                f,
157                "Buffer too small: required {} bytes, available {} bytes",
158                required, available
159            ),
160            Self::InvalidAlignment { required, actual } => write!(
161                f,
162                "Invalid alignment: required {}, got {}",
163                required, actual
164            ),
165            Self::UnsupportedOperation => write!(f, "Operation not supported"),
166            Self::InvalidParameter => write!(f, "Invalid parameter"),
167            Self::OutOfBounds { index, max } => {
168                write!(f, "Out of bounds: index {} exceeds max {}", index, max)
169            }
170            Self::PowerModeTransitionFailed => write!(f, "Power mode transition failed"),
171            Self::DeadlineMissed {
172                actual_us,
173                deadline_us,
174            } => write!(
175                f,
176                "Real-time deadline missed: {} us > {} us",
177                actual_us, deadline_us
178            ),
179            Self::ResourceBusy => write!(f, "Resource is busy"),
180            Self::Timeout => write!(f, "Operation timed out"),
181            Self::InitializationFailed => write!(f, "Initialization failed"),
182            Self::HardwareError => write!(f, "Hardware error"),
183            Self::InvalidState => write!(f, "Invalid state"),
184            Self::FormatError => write!(f, "Data format error"),
185            Self::ChecksumMismatch => write!(f, "Checksum mismatch"),
186            Self::TargetSpecific(code) => write!(f, "Target-specific error: {}", code),
187        }
188    }
189}
190
191#[cfg(feature = "std")]
192impl StdError for EmbeddedError {}
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197
198    #[test]
199    fn test_error_categories() {
200        let err = EmbeddedError::BufferTooSmall {
201            required: 100,
202            available: 50,
203        };
204        assert!(err.is_recoverable());
205        assert!(err.is_resource_exhaustion());
206        assert!(!err.is_validation_error());
207
208        let err = EmbeddedError::InvalidParameter;
209        assert!(!err.is_recoverable());
210        assert!(!err.is_resource_exhaustion());
211        assert!(err.is_validation_error());
212    }
213
214    #[test]
215    fn test_error_codes() {
216        assert_eq!(EmbeddedError::AllocationFailed.error_code(), 1);
217        assert_eq!(EmbeddedError::PoolExhausted.error_code(), 2);
218        assert_eq!(EmbeddedError::TargetSpecific(42).error_code(), 100);
219    }
220}