blob: e29a9961f9fb6c084c447bdb249ec569a19b6001 [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 {
crate::client::ScanError,
fuchsia_zircon as zx,
thiserror::{self, Error},
wlan_common::{
appendable::BufferTooSmall,
error::{FrameParseError, FrameWriteError},
},
};
#[derive(Debug, Error)]
pub enum Error {
#[error("out of buffers; requested {} bytes", _0)]
NoResources(usize),
#[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, _1)]
Status(String, zx::Status),
}
impl From<Error> for zx::Status {
fn from(e: Error) -> Self {
match e {
Error::NoResources(_) => zx::Status::NO_RESOURCES,
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)
| fidl::Error::ChannelPairCreate(status) => status,
_ => zx::Status::IO,
},
Error::Status(_, status) => status,
}
}
}
pub trait ResultExt {
/// Returns ZX_OK if Self is Ok, otherwise, prints an error and turns Self into a corresponding
/// ZX_ERR_*.
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)
}
}
#[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::NoResources(42));
assert_eq!(status, zx::Status::NO_RESOURCES);
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);
}
}