1use moniker::Moniker;
6use std::fmt::{self, Debug, Display};
7use std::sync::Arc;
8use thiserror::Error;
9use {
10 fidl_fuchsia_component_runtime as fruntime, fidl_fuchsia_component_sandbox as fsandbox,
11 zx_status as zx,
12};
13
14#[derive(Debug, Error, Clone)]
16pub enum RouterError {
17 #[error("{0}")]
18 NotFound(Arc<dyn Explain>),
19
20 #[error("invalid arguments")]
21 InvalidArgs,
22
23 #[error("not supported")]
24 NotSupported,
25
26 #[error("internal")]
27 Internal,
28
29 #[error("unknown")]
30 Unknown,
31
32 #[error("route continues outside of component manager at component {moniker}")]
33 RemotedAt { moniker: Moniker },
34}
35
36impl From<fruntime::RouterError> for RouterError {
37 fn from(router_error: fruntime::RouterError) -> Self {
38 match router_error {
39 fruntime::RouterError::NotFound => Self::NotFound(Arc::new(ExternalNotFoundError {})),
40 fruntime::RouterError::InvalidArgs => RouterError::InvalidArgs,
41 fruntime::RouterError::NotSupported => RouterError::InvalidArgs,
42 fruntime::RouterError::Internal => RouterError::Internal,
43 _ => RouterError::Unknown,
44 }
45 }
46}
47
48impl From<RouterError> for fruntime::RouterError {
49 fn from(router_error: RouterError) -> Self {
50 match router_error {
51 RouterError::NotFound(_) => fruntime::RouterError::NotFound,
52 RouterError::InvalidArgs => fruntime::RouterError::InvalidArgs,
53 RouterError::NotSupported => fruntime::RouterError::InvalidArgs,
54 RouterError::RemotedAt { .. } => fruntime::RouterError::NotSupported,
55 RouterError::Internal => fruntime::RouterError::Internal,
56 RouterError::Unknown => fruntime::RouterError::Unknown,
57 }
58 }
59}
60
61impl From<fsandbox::RouterError> for RouterError {
62 fn from(err: fsandbox::RouterError) -> Self {
63 match err {
64 fsandbox::RouterError::NotFound => Self::NotFound(Arc::new(ExternalNotFoundError {})),
65 fsandbox::RouterError::InvalidArgs => Self::InvalidArgs,
66 fsandbox::RouterError::NotSupported => Self::NotSupported,
67 fsandbox::RouterError::Internal => Self::Internal,
68 fsandbox::RouterErrorUnknown!() => Self::Unknown,
69 }
70 }
71}
72
73impl From<RouterError> for fsandbox::RouterError {
74 fn from(err: RouterError) -> Self {
75 match err {
76 RouterError::NotFound(_) => Self::NotFound,
77 RouterError::InvalidArgs => Self::InvalidArgs,
78 RouterError::NotSupported => Self::NotSupported,
79 RouterError::RemotedAt { .. } => Self::NotSupported,
80 RouterError::Internal => Self::Internal,
81 RouterError::Unknown => Self::unknown(),
82 }
83 }
84}
85
86#[derive(Debug, Error, Clone)]
87struct ExternalNotFoundError {}
88
89impl Explain for ExternalNotFoundError {
90 fn as_zx_status(&self) -> zx::Status {
91 zx::Status::NOT_FOUND
92 }
93}
94
95impl fmt::Display for ExternalNotFoundError {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 write!(f, "external not found error")
98 }
99}
100
101pub trait Explain: std::error::Error + Debug + Display + Send + Sync + sealed::AnyCast {
108 fn as_zx_status(&self) -> zx::Status;
109}
110
111impl Explain for RouterError {
112 fn as_zx_status(&self) -> zx::Status {
113 match self {
114 Self::NotFound(err) => err.as_zx_status(),
115 Self::InvalidArgs => zx::Status::INVALID_ARGS,
116 Self::RemotedAt { .. } => zx::Status::NOT_SUPPORTED,
117 Self::NotSupported => zx::Status::NOT_SUPPORTED,
118 Self::Internal => zx::Status::INTERNAL,
119 Self::Unknown => zx::Status::INTERNAL,
120 }
121 }
122}
123
124pub trait DowncastErrorForTest {
130 fn downcast_for_test<E: Explain>(&self) -> &E;
132}
133
134impl DowncastErrorForTest for dyn Explain {
135 fn downcast_for_test<E: Explain>(&self) -> &E {
136 match self.as_any().downcast_ref::<E>() {
137 Some(value) => value,
138 None => {
139 let expected = std::any::type_name::<E>();
140 panic!("Cannot downcast `{self:?}` to the {expected:?} error type!");
141 }
142 }
143 }
144}
145
146mod sealed {
147 use std::any::Any;
148
149 pub trait AnyCast: Any {
150 fn as_any(&self) -> &dyn Any;
151 }
152
153 impl<T: Any> AnyCast for T {
154 fn as_any(&self) -> &dyn Any {
155 self
156 }
157 }
158}