Skip to main content

hap_ble/
error.rs

1//! The crate-wide error type.
2
3/// Errors from the BLE transport.
4#[derive(Debug, thiserror::Error)]
5#[non_exhaustive]
6pub enum BleError {
7    /// Malformed TLV8 in a PDU body or pairing message.
8    #[error("TLV8 error: {0}")]
9    Tlv8(#[from] hap_tlv8::Tlv8Error),
10    /// A pairing or AEAD crypto operation failed.
11    #[error("crypto error: {0}")]
12    Crypto(#[from] hap_crypto::CryptoError),
13    /// The accessory attribute model could not be built or coerced.
14    #[error("model error: {0}")]
15    Model(#[from] hap_model::ModelError),
16    /// No accessory matched the discovery filter.
17    #[error("accessory not found")]
18    AccessoryNotFound,
19    /// The requested characteristic is not in the accessory's database.
20    #[error("characteristic (aid={aid}, iid={iid}) not found")]
21    CharacteristicNotFound {
22        /// Accessory instance id.
23        aid: u64,
24        /// Characteristic instance id.
25        iid: u64,
26    },
27    /// A received HAP-BLE PDU was malformed.
28    #[error("malformed HAP-BLE PDU: {0}")]
29    MalformedPdu(&'static str),
30    /// The accessory rejected a pairing step with a non-zero status.
31    #[error("accessory rejected pairing (status {0})")]
32    PairingRejected(u8),
33    /// The accessory answered a request PDU with a non-zero status.
34    #[error("accessory rejected the request (PDU status {0})")]
35    RequestRejected(u8),
36    /// The BLE link dropped mid-operation.
37    #[error("the accessory disconnected")]
38    Disconnected,
39    /// An error from the BLE backend (transport-library specific).
40    #[error("BLE backend error: {0}")]
41    Backend(String),
42}
43
44/// The crate result alias.
45pub type Result<T> = core::result::Result<T, BleError>;
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn tlv8_error_converts_via_from() {
53        // A lower-crate error must convert into BleError through `?`.
54        fn inner() -> Result<()> {
55            let _ = hap_tlv8::Tlv8Map::parse(&[0x01])?; // truncated TLV -> Tlv8Error
56            Ok(())
57        }
58        #[allow(clippy::unwrap_used)] // test code: error path is the whole point
59        let err = inner().unwrap_err();
60        assert!(matches!(err, BleError::Tlv8(_)));
61    }
62
63    #[test]
64    fn char_not_found_displays_ids() {
65        let e = BleError::CharacteristicNotFound { aid: 1, iid: 9 };
66        assert_eq!(e.to_string(), "characteristic (aid=1, iid=9) not found");
67    }
68}