Skip to main content

router_error/
lib.rs

1// Copyright 2024 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 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/// The error type returned by bedrock operations.
14#[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
100/// All detailed error objects must implement the [`Explain`] trait, since:
101///
102/// - Some operations are not yet refactored into bedrock.
103/// - Some operations fundamentally are not fit for bedrock.
104///
105/// The detailed errors are hidden, but users may get strings or codes for debugging.
106pub 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}