hive_btle/
error.rs

1// Copyright (c) 2025-2026 (r)evolve - Revolve Team LLC
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Error types for HIVE-BTLE
17//!
18//! Provides a comprehensive error enum for all BLE operations including
19//! adapter initialization, discovery, GATT operations, and connectivity.
20
21#[cfg(not(feature = "std"))]
22use alloc::string::String;
23#[cfg(not(feature = "std"))]
24use core::fmt;
25
26/// Result type alias for BLE operations
27pub type Result<T> = core::result::Result<T, BleError>;
28
29/// Errors that can occur during BLE operations
30#[derive(Debug)]
31#[cfg_attr(feature = "std", derive(thiserror::Error))]
32pub enum BleError {
33    /// Bluetooth adapter not available on this device
34    #[cfg_attr(feature = "std", error("Bluetooth adapter not available"))]
35    AdapterNotAvailable,
36
37    /// Bluetooth is powered off
38    #[cfg_attr(feature = "std", error("Bluetooth is powered off"))]
39    NotPowered,
40
41    /// Bluetooth permissions not granted
42    #[cfg_attr(feature = "std", error("Bluetooth permissions not granted: {0}"))]
43    PermissionDenied(String),
44
45    /// Feature not supported by this adapter or platform
46    #[cfg_attr(feature = "std", error("Feature not supported: {0}"))]
47    NotSupported(String),
48
49    /// Connection to peer failed
50    #[cfg_attr(feature = "std", error("Connection failed: {0}"))]
51    ConnectionFailed(String),
52
53    /// Connection was lost
54    #[cfg_attr(feature = "std", error("Connection lost: {0}"))]
55    ConnectionLost(String),
56
57    /// Discovery operation failed
58    #[cfg_attr(feature = "std", error("Discovery failed: {0}"))]
59    DiscoveryFailed(String),
60
61    /// GATT operation failed
62    #[cfg_attr(feature = "std", error("GATT error: {0}"))]
63    GattError(String),
64
65    /// Characteristic not found
66    #[cfg_attr(feature = "std", error("Characteristic not found: {0}"))]
67    CharacteristicNotFound(String),
68
69    /// Service not found
70    #[cfg_attr(feature = "std", error("Service not found: {0}"))]
71    ServiceNotFound(String),
72
73    /// MTU negotiation failed
74    #[cfg_attr(
75        feature = "std",
76        error("MTU negotiation failed: requested {requested}, got {actual}")
77    )]
78    MtuNegotiationFailed {
79        /// Requested MTU size
80        requested: u16,
81        /// Actual negotiated MTU
82        actual: u16,
83    },
84
85    /// Security/pairing error
86    #[cfg_attr(feature = "std", error("Security error: {0}"))]
87    SecurityError(String),
88
89    /// Pairing failed
90    #[cfg_attr(feature = "std", error("Pairing failed: {0}"))]
91    PairingFailed(String),
92
93    /// Sync operation failed
94    #[cfg_attr(feature = "std", error("Sync error: {0}"))]
95    SyncError(String),
96
97    /// Platform-specific error
98    #[cfg_attr(feature = "std", error("Platform error: {0}"))]
99    PlatformError(String),
100
101    /// Operation timed out
102    #[cfg_attr(feature = "std", error("Operation timed out"))]
103    Timeout,
104
105    /// Invalid configuration
106    #[cfg_attr(feature = "std", error("Invalid configuration: {0}"))]
107    InvalidConfig(String),
108
109    /// Invalid state for this operation
110    #[cfg_attr(feature = "std", error("Invalid state: {0}"))]
111    InvalidState(String),
112
113    /// Resource exhausted (e.g., max connections reached)
114    #[cfg_attr(feature = "std", error("Resource exhausted: {0}"))]
115    ResourceExhausted(String),
116
117    /// I/O error
118    #[cfg_attr(feature = "std", error("I/O error: {0}"))]
119    Io(String),
120}
121
122// Manual Display implementation for no_std
123#[cfg(not(feature = "std"))]
124impl fmt::Display for BleError {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        match self {
127            BleError::AdapterNotAvailable => write!(f, "Bluetooth adapter not available"),
128            BleError::NotPowered => write!(f, "Bluetooth is powered off"),
129            BleError::PermissionDenied(msg) => write!(f, "Permission denied: {}", msg),
130            BleError::NotSupported(msg) => write!(f, "Not supported: {}", msg),
131            BleError::ConnectionFailed(msg) => write!(f, "Connection failed: {}", msg),
132            BleError::ConnectionLost(msg) => write!(f, "Connection lost: {}", msg),
133            BleError::DiscoveryFailed(msg) => write!(f, "Discovery failed: {}", msg),
134            BleError::GattError(msg) => write!(f, "GATT error: {}", msg),
135            BleError::CharacteristicNotFound(uuid) => {
136                write!(f, "Characteristic not found: {}", uuid)
137            }
138            BleError::ServiceNotFound(uuid) => write!(f, "Service not found: {}", uuid),
139            BleError::MtuNegotiationFailed { requested, actual } => {
140                write!(
141                    f,
142                    "MTU negotiation failed: requested {}, got {}",
143                    requested, actual
144                )
145            }
146            BleError::SecurityError(msg) => write!(f, "Security error: {}", msg),
147            BleError::PairingFailed(msg) => write!(f, "Pairing failed: {}", msg),
148            BleError::SyncError(msg) => write!(f, "Sync error: {}", msg),
149            BleError::PlatformError(msg) => write!(f, "Platform error: {}", msg),
150            BleError::Timeout => write!(f, "Operation timed out"),
151            BleError::InvalidConfig(msg) => write!(f, "Invalid config: {}", msg),
152            BleError::InvalidState(msg) => write!(f, "Invalid state: {}", msg),
153            BleError::ResourceExhausted(msg) => write!(f, "Resource exhausted: {}", msg),
154            BleError::Io(msg) => write!(f, "I/O error: {}", msg),
155        }
156    }
157}
158
159#[cfg(feature = "std")]
160impl From<std::io::Error> for BleError {
161    fn from(err: std::io::Error) -> Self {
162        BleError::Io(err.to_string())
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    #[test]
171    fn test_error_display() {
172        let err = BleError::ConnectionFailed("peer unreachable".to_string());
173        assert!(err.to_string().contains("Connection failed"));
174        assert!(err.to_string().contains("peer unreachable"));
175    }
176
177    #[test]
178    fn test_mtu_error() {
179        let err = BleError::MtuNegotiationFailed {
180            requested: 512,
181            actual: 23,
182        };
183        let msg = err.to_string();
184        assert!(msg.contains("512"));
185        assert!(msg.contains("23"));
186    }
187}