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