1use std::fmt::{self, Debug, Display};
6use std::sync::Arc;
7use thiserror::Error;
8use {fidl_fuchsia_component_sandbox as fsandbox, zx_status as zx};
9
10#[derive(Debug, Error, Clone)]
12pub enum RouterError {
13 #[error("{0}")]
14 NotFound(Arc<dyn Explain>),
15
16 #[error("invalid arguments")]
17 InvalidArgs,
18
19 #[error("not supported")]
20 NotSupported,
21
22 #[error("internal")]
23 Internal,
24
25 #[error("unknown")]
26 Unknown,
27}
28
29impl From<fsandbox::RouterError> for RouterError {
30 fn from(err: fsandbox::RouterError) -> Self {
31 match err {
32 fsandbox::RouterError::NotFound => Self::NotFound(Arc::new(ExternalNotFoundError {})),
33 fsandbox::RouterError::InvalidArgs => Self::InvalidArgs,
34 fsandbox::RouterError::NotSupported => Self::NotSupported,
35 fsandbox::RouterError::Internal => Self::Internal,
36 fsandbox::RouterErrorUnknown!() => Self::Unknown,
37 }
38 }
39}
40
41impl From<RouterError> for fsandbox::RouterError {
42 fn from(err: RouterError) -> Self {
43 match err {
44 RouterError::NotFound(_) => Self::NotFound,
45 RouterError::InvalidArgs => Self::InvalidArgs,
46 RouterError::NotSupported => Self::NotSupported,
47 RouterError::Internal => Self::Internal,
48 RouterError::Unknown => Self::unknown(),
49 }
50 }
51}
52
53#[derive(Debug, Error, Clone)]
54struct ExternalNotFoundError {}
55
56impl Explain for ExternalNotFoundError {
57 fn as_zx_status(&self) -> zx::Status {
58 zx::Status::NOT_FOUND
59 }
60}
61
62impl fmt::Display for ExternalNotFoundError {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "external not found error")
65 }
66}
67
68pub trait Explain: std::error::Error + Debug + Display + Send + Sync + sealed::AnyCast {
75 fn as_zx_status(&self) -> zx::Status;
76}
77
78impl Explain for RouterError {
79 fn as_zx_status(&self) -> zx::Status {
80 match self {
81 Self::NotFound(err) => err.as_zx_status(),
82 Self::InvalidArgs => zx::Status::INVALID_ARGS,
83 Self::NotSupported => zx::Status::NOT_SUPPORTED,
84 Self::Internal => zx::Status::INTERNAL,
85 Self::Unknown => zx::Status::INTERNAL,
86 }
87 }
88}
89
90pub trait DowncastErrorForTest {
96 fn downcast_for_test<E: Explain>(&self) -> &E;
98}
99
100impl DowncastErrorForTest for dyn Explain {
101 fn downcast_for_test<E: Explain>(&self) -> &E {
102 match self.as_any().downcast_ref::<E>() {
103 Some(value) => value,
104 None => {
105 let expected = std::any::type_name::<E>();
106 panic!("Cannot downcast `{self:?}` to the {expected:?} error type!");
107 }
108 }
109 }
110}
111
112mod sealed {
113 use std::any::Any;
114
115 pub trait AnyCast: Any {
116 fn as_any(&self) -> &dyn Any;
117 }
118
119 impl<T: Any> AnyCast for T {
120 fn as_any(&self) -> &dyn Any {
121 self
122 }
123 }
124}