use {
crate::client::ScanError,
fuchsia_zircon as zx,
thiserror::Error,
wlan_common::{
appendable::BufferTooSmall,
error::{FrameParseError, FrameWriteError},
},
};
#[derive(Debug, Error)]
pub enum Error {
#[error("provided buffer to small")]
BufferTooSmall,
#[error("error parsing frame: {}", _0)]
ParsingFrame(FrameParseError),
#[error("error writing frame: {}", _0)]
WritingFrame(FrameWriteError),
#[error("scan error: {}", _0)]
ScanError(ScanError),
#[error("{}", _0)]
Internal(anyhow::Error),
#[error("{}", _0)]
Fidl(fidl::Error),
#[error("{}", _0)]
Allocator(wlan_ffi_transport::Error),
#[error("{}; {}", _0, _1)]
Status(String, zx::Status),
}
impl From<Error> for zx::Status {
fn from(e: Error) -> Self {
match e {
Error::BufferTooSmall => zx::Status::BUFFER_TOO_SMALL,
Error::Internal(_) => zx::Status::INTERNAL,
Error::ParsingFrame(_) => zx::Status::IO_INVALID,
Error::WritingFrame(_) => zx::Status::IO_REFUSED,
Error::ScanError(e) => e.into(),
Error::Fidl(e) => match e {
fidl::Error::ClientRead(status)
| fidl::Error::ClientWrite(status)
| fidl::Error::ServerResponseWrite(status)
| fidl::Error::ServerRequestRead(status) => status,
_ => zx::Status::IO,
},
Error::Allocator(e) => match e {
wlan_ffi_transport::Error::NoResources { .. } => zx::Status::NO_RESOURCES,
wlan_ffi_transport::Error::InvalidFfiBuffer(..) => zx::Status::INTERNAL,
},
Error::Status(_, status) => status,
}
}
}
pub trait ResultExt {
fn into_raw_zx_status(self) -> zx::sys::zx_status_t;
}
impl ResultExt for Result<(), Error> {
fn into_raw_zx_status(self) -> zx::sys::zx_status_t {
match self {
Ok(()) | Err(Error::Status(_, zx::Status::OK)) => zx::sys::ZX_OK,
Err(e) => {
eprintln!("{}", e);
Into::<zx::Status>::into(e).into_raw()
}
}
}
}
impl From<anyhow::Error> for Error {
fn from(e: anyhow::Error) -> Self {
Error::Internal(e)
}
}
impl From<FrameParseError> for Error {
fn from(e: FrameParseError) -> Self {
Error::ParsingFrame(e)
}
}
impl From<FrameWriteError> for Error {
fn from(e: FrameWriteError) -> Self {
Error::WritingFrame(e)
}
}
impl From<ScanError> for Error {
fn from(e: ScanError) -> Self {
Error::ScanError(e)
}
}
impl From<BufferTooSmall> for Error {
fn from(_: BufferTooSmall) -> Self {
Error::BufferTooSmall
}
}
impl From<fidl::Error> for Error {
fn from(e: fidl::Error) -> Self {
Error::Fidl(e)
}
}
impl From<wlan_ffi_transport::Error> for Error {
fn from(e: wlan_ffi_transport::Error) -> Self {
Error::Allocator(e)
}
}
#[cfg(test)]
mod tests {
use {super::*, anyhow::format_err};
#[test]
fn test_error_into_status() {
let status = zx::Status::from(Error::Status("foo".to_string(), zx::Status::OK));
assert_eq!(status, zx::Status::OK);
let status = zx::Status::from(Error::Status("foo".to_string(), zx::Status::NOT_SUPPORTED));
assert_eq!(status, zx::Status::NOT_SUPPORTED);
let status = zx::Status::from(Error::Internal(format_err!("lorem")));
assert_eq!(status, zx::Status::INTERNAL);
let status = zx::Status::from(Error::WritingFrame(FrameWriteError::BufferTooSmall));
assert_eq!(status, zx::Status::IO_REFUSED);
let status = zx::Status::from(Error::BufferTooSmall);
assert_eq!(status, zx::Status::BUFFER_TOO_SMALL);
let status = zx::Status::from(Error::Allocator(wlan_ffi_transport::Error::NoResources {
requested_capacity: 42,
}));
assert_eq!(status, zx::Status::NO_RESOURCES);
let status =
zx::Status::from(Error::Allocator(wlan_ffi_transport::Error::InvalidFfiBuffer(
wlan_ffi_transport::InvalidFfiBuffer::NullCtx,
)));
assert_eq!(status, zx::Status::INTERNAL);
let status =
zx::Status::from(Error::Fidl(fidl::Error::ClientWrite(zx::Status::NOT_SUPPORTED)));
assert_eq!(status, zx::Status::NOT_SUPPORTED);
}
#[test]
fn test_result_into_status() {
let status = Err(Error::Status("foo".to_string(), zx::Status::OK));
assert_eq!(status.into_raw_zx_status(), zx::sys::ZX_OK);
let status = Err(Error::Status("foo".to_string(), zx::Status::NOT_SUPPORTED));
assert_eq!(status.into_raw_zx_status(), zx::sys::ZX_ERR_NOT_SUPPORTED);
let status = Err(Error::Internal(format_err!("lorem")));
assert_eq!(status.into_raw_zx_status(), zx::sys::ZX_ERR_INTERNAL);
let status = Ok(());
assert_eq!(status.into_raw_zx_status(), zx::sys::ZX_OK);
}
}