blob: 2aa8d3be288e7472738315bc3f8f366b0903f675 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::format_err, fidl_fuchsia_bluetooth as bt, fidl_fuchsia_bluetooth_sys as sys,
fuchsia_bluetooth::bt_fidl_status,
};
/// Type representing Possible errors raised in the operation of BT-GAP
#[derive(Debug)]
pub enum Error {
/// Internal bt-gap Error
InternalError(anyhow::Error),
/// Host Error
HostError(bt::Error),
/// fuchsia.bluetooth.sys API errors. Used to encapsulate errors that are reported by bt-host
/// and for the fuchsia.bluetooth.sys.Access API.
SysError(sys::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
impl Error {
pub fn as_status(self) -> bt::Status {
match self {
Error::HostError(err) => bt::Status { error: Some(Box::new(err)) },
Error::InternalError(err) => bt_fidl_status!(Failed, format!("{}", err)),
Error::SysError(err) => {
bt::Status { error: Some(Box::new(sys_error_to_deprecated(err))) }
}
}
}
pub fn no_host() -> Error {
Error::HostError(bt::Error {
error_code: bt::ErrorCode::BluetoothNotAvailable,
protocol_error_code: 0,
description: Some("No Host found".to_string()),
})
}
pub fn as_failure(self) -> anyhow::Error {
match self {
Error::InternalError(err) => err,
Error::HostError(err) => format_err!(
"Host Error: {}",
err.description.unwrap_or("Unknown Host Error".to_string())
),
Error::SysError(err) => format_err!("Host Error: {:?}", err),
}
}
}
impl Into<anyhow::Error> for Error {
fn into(self) -> anyhow::Error {
self.as_failure()
}
}
impl From<bt::Error> for Error {
fn from(err: bt::Error) -> Error {
Error::HostError(err)
}
}
impl From<sys::Error> for Error {
fn from(err: sys::Error) -> Error {
Error::SysError(err)
}
}
impl From<anyhow::Error> for Error {
fn from(err: anyhow::Error) -> Error {
Error::InternalError(err)
}
}
impl From<fidl::Error> for Error {
fn from(err: fidl::Error) -> Error {
Error::InternalError(format_err!(format!("Internal FIDL error: {}", err)))
}
}
pub fn from_fidl_status(r: fidl::Result<bt::Status>) -> Result<()> {
match r {
Ok(status) => status.as_result(),
Err(e) => Err(Error::from(e)),
}
}
pub fn from_fidl_result<T>(r: fidl::Result<std::result::Result<T, sys::Error>>) -> Result<T> {
match r {
Ok(r) => r.map_err(Error::from),
Err(e) => Err(Error::from(e)),
}
}
// Maps a fuchsia.bluetooth.sys.Error value to a fuchsia.bluetooth.Error. This is maintained for
// compatibility until fuchsia.bluetooth.control and fuchsia.bluetooth.Status are removed.
fn sys_error_to_deprecated(e: sys::Error) -> bt::Error {
bt::Error {
error_code: match e {
sys::Error::Failed => bt::ErrorCode::Failed,
sys::Error::PeerNotFound => bt::ErrorCode::NotFound,
sys::Error::TimedOut => bt::ErrorCode::TimedOut,
sys::Error::Canceled => bt::ErrorCode::Canceled,
sys::Error::InProgress => bt::ErrorCode::InProgress,
sys::Error::NotSupported => bt::ErrorCode::NotSupported,
sys::Error::InvalidArguments => bt::ErrorCode::InvalidArguments,
},
protocol_error_code: 0,
description: None,
}
}
pub trait StatusExt {
fn as_result(self) -> Result<()>;
}
impl StatusExt for bt::Status {
fn as_result(self) -> Result<()> {
match self.error {
Some(err) => Err((*err).into()),
None => Ok(()),
}
}
}
pub fn status_response(result: Result<()>) -> bt::Status {
match result {
Ok(()) => bt_fidl_status!(),
Err(err) => err.as_status(),
}
}