wlan_mlme/
error.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::client::ScanError;
6
7use thiserror::Error;
8use wlan_common::append::BufferTooSmall;
9use wlan_common::error::{FrameParseError, FrameWriteError};
10
11#[derive(Debug, Error)]
12pub enum Error {
13    #[error("provided buffer to small")]
14    BufferTooSmall,
15    #[error("error parsing frame: {}", _0)]
16    ParsingFrame(FrameParseError),
17    #[error("error writing frame: {}", _0)]
18    WritingFrame(FrameWriteError),
19    #[error("scan error: {}", _0)]
20    ScanError(ScanError),
21    #[error("{}", _0)]
22    Internal(anyhow::Error),
23    #[error("{}", _0)]
24    Fidl(fidl::Error),
25    #[error("{}; {}", _0, _1)]
26    Status(String, zx::Status),
27}
28
29impl From<Error> for zx::Status {
30    fn from(e: Error) -> Self {
31        match e {
32            Error::BufferTooSmall => zx::Status::BUFFER_TOO_SMALL,
33            Error::Internal(_) => zx::Status::INTERNAL,
34            Error::ParsingFrame(_) => zx::Status::IO_INVALID,
35            Error::WritingFrame(_) => zx::Status::IO_REFUSED,
36            Error::ScanError(e) => e.into(),
37            Error::Fidl(e) => match e {
38                fidl::Error::ClientRead(fidl::TransportError::Status(status))
39                | fidl::Error::ClientWrite(fidl::TransportError::Status(status))
40                | fidl::Error::ServerResponseWrite(fidl::TransportError::Status(status))
41                | fidl::Error::ServerRequestRead(fidl::TransportError::Status(status)) => status,
42                _ => zx::Status::IO,
43            },
44            Error::Status(_, status) => status,
45        }
46    }
47}
48
49pub trait ResultExt {
50    /// Returns ZX_OK if Self is Ok, otherwise, prints an error and turns Self into a corresponding
51    /// ZX_ERR_*.
52    fn into_raw_zx_status(self) -> zx::sys::zx_status_t;
53}
54
55impl ResultExt for Result<(), Error> {
56    fn into_raw_zx_status(self) -> zx::sys::zx_status_t {
57        match self {
58            Ok(()) | Err(Error::Status(_, zx::Status::OK)) => zx::sys::ZX_OK,
59            Err(e) => {
60                eprintln!("{}", e);
61                Into::<zx::Status>::into(e).into_raw()
62            }
63        }
64    }
65}
66
67impl From<anyhow::Error> for Error {
68    fn from(e: anyhow::Error) -> Self {
69        Error::Internal(e)
70    }
71}
72
73impl From<FrameParseError> for Error {
74    fn from(e: FrameParseError) -> Self {
75        Error::ParsingFrame(e)
76    }
77}
78
79impl From<FrameWriteError> for Error {
80    fn from(e: FrameWriteError) -> Self {
81        Error::WritingFrame(e)
82    }
83}
84
85impl From<ScanError> for Error {
86    fn from(e: ScanError) -> Self {
87        Error::ScanError(e)
88    }
89}
90
91impl From<BufferTooSmall> for Error {
92    fn from(_: BufferTooSmall) -> Self {
93        Error::BufferTooSmall
94    }
95}
96
97impl From<fidl::Error> for Error {
98    fn from(e: fidl::Error) -> Self {
99        Error::Fidl(e)
100    }
101}
102
103impl From<zx::Status> for Error {
104    fn from(e: zx::Status) -> Self {
105        Error::Status(e.to_string(), e)
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use anyhow::format_err;
113
114    #[test]
115    fn test_error_into_status() {
116        let status = zx::Status::from(Error::Status("foo".to_string(), zx::Status::OK));
117        assert_eq!(status, zx::Status::OK);
118
119        let status = zx::Status::from(Error::Status("foo".to_string(), zx::Status::NOT_SUPPORTED));
120        assert_eq!(status, zx::Status::NOT_SUPPORTED);
121
122        let status = zx::Status::from(Error::Internal(format_err!("lorem")));
123        assert_eq!(status, zx::Status::INTERNAL);
124
125        let status = zx::Status::from(Error::WritingFrame(FrameWriteError::BufferTooSmall));
126        assert_eq!(status, zx::Status::IO_REFUSED);
127
128        let status = zx::Status::from(Error::BufferTooSmall);
129        assert_eq!(status, zx::Status::BUFFER_TOO_SMALL);
130
131        let status = zx::Status::from(Error::Fidl(fidl::Error::ClientWrite(
132            zx::Status::NOT_SUPPORTED.into(),
133        )));
134        assert_eq!(status, zx::Status::NOT_SUPPORTED);
135    }
136}