bluest 0.5.3

A cross-platform Bluetooth Low Energy (BLE) library
Documentation
use objc_foundation::INSString;
use objc_id::ShareId;

use super::types::CBError;
pub use super::types::NSError;
use crate::error::{AttError, ErrorKind};

impl crate::Error {
    pub(super) fn from_recv_error(err: tokio::sync::broadcast::error::RecvError) -> Self {
        crate::Error::new(
            ErrorKind::Internal,
            Some(Box::new(err)),
            "receiving delegate event".to_string(),
        )
    }

    pub(super) fn from_stream_recv_error(err: tokio_stream::wrappers::errors::BroadcastStreamRecvError) -> Self {
        crate::Error::new(
            ErrorKind::Internal,
            Some(Box::new(err)),
            "receiving delegate event".to_string(),
        )
    }

    pub(super) fn from_nserror(err: ShareId<NSError>) -> Self {
        crate::Error::new(
            kind_from_nserror(&*err),
            Some(Box::new(NSErrorError(err))),
            String::new(),
        )
    }

    pub(super) fn from_kind_and_nserror(kind: ErrorKind, err: Option<ShareId<NSError>>) -> Self {
        match err {
            Some(err) => crate::Error::new(kind, Some(Box::new(NSErrorError(err))), String::new()),
            None => kind.into(),
        }
    }
}

fn kind_from_nserror(value: &NSError) -> ErrorKind {
    if value.domain().as_str() == "CBErrorDomain" {
        match CBError(value.code()) {
            CBError::OPERATION_NOT_SUPPORTED => ErrorKind::NotSupported,
            CBError::NOT_CONNECTED | CBError::PERIPHERAL_DISCONNECTED => ErrorKind::NotConnected,
            CBError::CONNECTION_TIMEOUT | CBError::ENCRYPTION_TIMED_OUT => ErrorKind::Timeout,
            CBError::INVALID_PARAMETERS
            | CBError::INVALID_HANDLE
            | CBError::UUID_NOT_ALLOWED
            | CBError::UNKOWN_DEVICE => ErrorKind::InvalidParameter,
            CBError::CONNECTION_FAILED
            | CBError::PEER_REMOVED_PAIRING_INFORMATION
            | CBError::CONNECTION_LIMIT_REACHED
            | CBError::TOO_MANY_LE_PAIRED_DEVICES => ErrorKind::ConnectionFailed,
            CBError::UNKNOWN | CBError::OUT_OF_SPACE | CBError::OPERATION_CANCELLED | CBError::ALREADY_ADVERTISING => {
                ErrorKind::Other
            }
            _ => ErrorKind::Other,
        }
    } else if value.domain().as_str() == "CBATTErrorDomain" {
        let n = value.code();
        if let Ok(n) = u8::try_from(n) {
            ErrorKind::Protocol(AttError::from(n))
        } else {
            ErrorKind::Other
        }
    } else {
        ErrorKind::Other
    }
}

struct NSErrorError(ShareId<NSError>);

impl std::fmt::Debug for NSErrorError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(&self.0, f)
    }
}

impl std::fmt::Display for NSErrorError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.localized_description().as_str())
    }
}

impl std::error::Error for NSErrorError {}

impl std::ops::Deref for NSErrorError {
    type Target = NSError;

    fn deref(&self) -> &Self::Target {
        &*self.0
    }
}