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("not supported")]
20 NotSupported,
21
22 #[error("internal")]
23 Internal,
24
25 #[error("unknown")]
26 Unknown,
27
28 #[error("route continues outside of component manager at component {moniker}")]
29 RemotedAt { moniker: Moniker },
30}
31
32impl From<fruntime::RouterError> for RouterError {
33 fn from(router_error: fruntime::RouterError) -> Self {
34 match router_error {
35 fruntime::RouterError::NotFound => Self::NotFound(Arc::new(ExternalNotFoundError {})),
36 fruntime::RouterError::NotSupported => RouterError::NotSupported,
37 fruntime::RouterError::Internal => RouterError::Internal,
38 _ => RouterError::Unknown,
39 }
40 }
41}
42
43impl From<RouterError> for fruntime::RouterError {
44 fn from(router_error: RouterError) -> Self {
45 match router_error {
46 RouterError::NotFound(_) => fruntime::RouterError::NotFound,
47 RouterError::NotSupported => fruntime::RouterError::NotSupported,
48 RouterError::RemotedAt { .. } => fruntime::RouterError::NotSupported,
49 RouterError::Internal => fruntime::RouterError::Internal,
50 RouterError::Unknown => fruntime::RouterError::Unknown,
51 }
52 }
53}
54
55impl From<fsandbox::RouterError> for RouterError {
56 fn from(err: fsandbox::RouterError) -> Self {
57 match err {
58 fsandbox::RouterError::NotFound => Self::NotFound(Arc::new(ExternalNotFoundError {})),
59 fsandbox::RouterError::NotSupported => Self::NotSupported,
60 fsandbox::RouterError::Internal => Self::Internal,
61 fsandbox::RouterErrorUnknown!() => Self::Unknown,
62 }
63 }
64}
65
66impl From<RouterError> for fsandbox::RouterError {
67 fn from(err: RouterError) -> Self {
68 match err {
69 RouterError::NotFound(_) => Self::NotFound,
70 RouterError::NotSupported => Self::NotSupported,
71 RouterError::RemotedAt { .. } => Self::NotSupported,
72 RouterError::Internal => Self::Internal,
73 RouterError::Unknown => Self::unknown(),
74 }
75 }
76}
77
78#[derive(Debug, Error, Clone)]
79struct ExternalNotFoundError {}
80
81impl Explain for ExternalNotFoundError {
82 fn as_zx_status(&self) -> zx::Status {
83 zx::Status::NOT_FOUND
84 }
85}
86
87impl fmt::Display for ExternalNotFoundError {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 write!(f, "external not found error")
90 }
91}
92
93pub trait Explain: std::error::Error + Debug + Display + Send + Sync + sealed::AnyCast {
100 fn as_zx_status(&self) -> zx::Status;
101}
102
103impl Explain for RouterError {
104 fn as_zx_status(&self) -> zx::Status {
105 match self {
106 Self::NotFound(err) => err.as_zx_status(),
107 Self::RemotedAt { .. } => zx::Status::NOT_SUPPORTED,
108 Self::NotSupported => zx::Status::NOT_SUPPORTED,
109 Self::Internal => zx::Status::INTERNAL,
110 Self::Unknown => zx::Status::INTERNAL,
111 }
112 }
113}
114
115mod sealed {
116 use std::any::Any;
117
118 pub trait AnyCast: Any {
119 fn as_any(&self) -> &dyn Any;
120 }
121
122 impl<T: Any> AnyCast for T {
123 fn as_any(&self) -> &dyn Any {
124 self
125 }
126 }
127}