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    /// A self-sourcing sleepy watch was requested but no advert source was set.
43    #[error("no advert source set for sleepy events")]
44    NoAdvertSource,
45}
46
47/// The crate result alias.
48pub type Result<T> = core::result::Result<T, BleError>;
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn tlv8_error_converts_via_from() {
56        // A lower-crate error must convert into BleError through `?`.
57        fn inner() -> Result<()> {
58            let _ = hap_tlv8::Tlv8Map::parse(&[0x01])?; // truncated TLV -> Tlv8Error
59            Ok(())
60        }
61        #[allow(clippy::unwrap_used)] // test code: error path is the whole point
62        let err = inner().unwrap_err();
63        assert!(matches!(err, BleError::Tlv8(_)));
64    }
65
66    #[test]
67    fn char_not_found_displays_ids() {
68        let e = BleError::CharacteristicNotFound { aid: 1, iid: 9 };
69        assert_eq!(e.to_string(), "characteristic (aid=1, iid=9) not found");
70    }
71}