Skip to main content

runtime_capabilities/
capability.rs

1// Copyright 2023 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 crate::Router;
6use from_enum::FromEnum;
7use router_error::Explain;
8use std::fmt::Debug;
9use thiserror::Error;
10use zx_status;
11
12#[derive(Error, Debug, Clone)]
13pub enum ConversionError {
14    #[error("invalid `fuchsia.io` node name: name `{0}` is too long")]
15    ParseNameErrorTooLong(String),
16
17    #[error("invalid `fuchsia.io` node name: name cannot be empty")]
18    ParseNameErrorEmpty,
19
20    #[error("invalid `fuchsia.io` node name: name cannot be `.`")]
21    ParseNameErrorDot,
22
23    #[error("invalid `fuchsia.io` node name: name cannot be `..`")]
24    ParseNameErrorDotDot,
25
26    #[error("invalid `fuchsia.io` node name: name cannot contain `/`")]
27    ParseNameErrorSlash,
28
29    #[error("invalid `fuchsia.io` node name: name cannot contain embedded NUL")]
30    ParseNameErrorEmbeddedNul,
31
32    #[error("conversion to type is not supported")]
33    NotSupported,
34
35    #[error("conversion failed because a capability could not be cloned")]
36    NotCloneable,
37
38    #[error("value at `{key}` could not be converted: {err}")]
39    Nested {
40        key: String,
41        #[source]
42        err: Box<ConversionError>,
43    },
44}
45
46#[cfg(target_os = "fuchsia")]
47impl From<vfs::name::ParseNameError> for ConversionError {
48    fn from(parse_name_error: vfs::name::ParseNameError) -> Self {
49        match parse_name_error {
50            vfs::name::ParseNameError::TooLong(s) => ConversionError::ParseNameErrorTooLong(s),
51            vfs::name::ParseNameError::Empty => ConversionError::ParseNameErrorEmpty,
52            vfs::name::ParseNameError::Dot => ConversionError::ParseNameErrorDot,
53            vfs::name::ParseNameError::DotDot => ConversionError::ParseNameErrorDotDot,
54            vfs::name::ParseNameError::Slash => ConversionError::ParseNameErrorSlash,
55            vfs::name::ParseNameError::EmbeddedNul => ConversionError::ParseNameErrorEmbeddedNul,
56        }
57    }
58}
59
60/// Errors arising from conversion between Rust and FIDL types.
61#[derive(Error, Debug)]
62pub enum RemoteError {
63    #[error("unknown FIDL variant")]
64    UnknownVariant,
65
66    #[error("unregistered capability; only capabilities created by sandbox are allowed")]
67    Unregistered,
68
69    #[error("registered capability had the wrong type")]
70    BadCapability,
71}
72
73impl Explain for RemoteError {
74    fn as_zx_status(&self) -> zx_status::Status {
75        match self {
76            RemoteError::UnknownVariant => zx_status::Status::NOT_SUPPORTED,
77            RemoteError::Unregistered => zx_status::Status::INVALID_ARGS,
78            RemoteError::BadCapability => zx_status::Status::INVALID_ARGS,
79        }
80    }
81}
82
83#[derive(FromEnum, Debug, Clone)]
84pub enum Capability {
85    Connector(crate::Connector),
86    DirConnector(crate::DirConnector),
87    Dictionary(crate::Dictionary),
88    Data(crate::Data),
89    Handle(crate::Handle),
90    ConnectorRouter(crate::Router<crate::Connector>),
91    DictionaryRouter(crate::Router<crate::Dictionary>),
92    DirConnectorRouter(crate::Router<crate::DirConnector>),
93    DataRouter(crate::Router<crate::Data>),
94    Instance(crate::WeakInstanceToken),
95}
96
97impl Capability {
98    pub fn to_dictionary(self) -> Option<crate::Dictionary> {
99        match self {
100            Self::Dictionary(d) => Some(d),
101            _ => None,
102        }
103    }
104
105    pub fn debug_typename(&self) -> &'static str {
106        match self {
107            Self::Connector(_) => crate::Connector::debug_typename(),
108            Self::DirConnector(_) => crate::DirConnector::debug_typename(),
109            Self::ConnectorRouter(_) => crate::Router::<crate::Connector>::debug_typename(),
110            Self::DictionaryRouter(_) => crate::Router::<crate::Dictionary>::debug_typename(),
111            Self::DirConnectorRouter(_) => crate::Router::<crate::DirConnector>::debug_typename(),
112            Self::DataRouter(_) => crate::Router::<crate::Data>::debug_typename(),
113            Self::Dictionary(_) => crate::Dictionary::debug_typename(),
114            Self::Data(_) => crate::Data::debug_typename(),
115            Self::Handle(_) => crate::Handle::debug_typename(),
116            Self::Instance(_) => "Instance",
117        }
118    }
119}
120
121impl TryFrom<Capability> for crate::Connector {
122    type Error = ();
123
124    fn try_from(c: Capability) -> Result<Self, Self::Error> {
125        match c {
126            Capability::Connector(c) => Ok(c),
127            _ => Err(()),
128        }
129    }
130}
131
132impl TryFrom<Capability> for crate::DirConnector {
133    type Error = ();
134
135    fn try_from(c: Capability) -> Result<Self, Self::Error> {
136        match c {
137            Capability::DirConnector(c) => Ok(c),
138            _ => Err(()),
139        }
140    }
141}
142
143impl TryFrom<Capability> for crate::Dictionary {
144    type Error = ();
145
146    fn try_from(c: Capability) -> Result<Self, Self::Error> {
147        match c {
148            Capability::Dictionary(c) => Ok(c),
149            _ => Err(()),
150        }
151    }
152}
153
154impl TryFrom<Capability> for crate::Data {
155    type Error = ();
156
157    fn try_from(c: Capability) -> Result<Self, Self::Error> {
158        match c {
159            Capability::Data(c) => Ok(c),
160            _ => Err(()),
161        }
162    }
163}
164
165impl TryFrom<Capability> for crate::Handle {
166    type Error = ();
167
168    fn try_from(c: Capability) -> Result<Self, Self::Error> {
169        match c {
170            Capability::Handle(r) => Ok(r),
171            _ => Err(()),
172        }
173    }
174}
175
176impl TryFrom<Capability> for Router<crate::Dictionary> {
177    type Error = ();
178
179    fn try_from(c: Capability) -> Result<Self, Self::Error> {
180        match c {
181            Capability::DictionaryRouter(c) => Ok(c),
182            _ => Err(()),
183        }
184    }
185}
186
187impl TryFrom<Capability> for Router<crate::DirConnector> {
188    type Error = ();
189
190    fn try_from(c: Capability) -> Result<Self, Self::Error> {
191        match c {
192            Capability::DirConnectorRouter(c) => Ok(c),
193            _ => Err(()),
194        }
195    }
196}
197
198impl TryFrom<Capability> for Router<crate::Connector> {
199    type Error = ();
200
201    fn try_from(c: Capability) -> Result<Self, Self::Error> {
202        match c {
203            Capability::ConnectorRouter(c) => Ok(c),
204            _ => Err(()),
205        }
206    }
207}
208
209impl TryFrom<Capability> for Router<crate::Data> {
210    type Error = ();
211
212    fn try_from(c: Capability) -> Result<Self, Self::Error> {
213        match c {
214            Capability::DataRouter(c) => Ok(c),
215            _ => Err(()),
216        }
217    }
218}
219
220impl TryFrom<Capability> for crate::WeakInstanceToken {
221    type Error = ();
222
223    fn try_from(c: Capability) -> Result<Self, Self::Error> {
224        match c {
225            Capability::Instance(i) => Ok(i),
226            _ => Err(()),
227        }
228    }
229}
230
231/// Parent trait implemented by all capability types. Useful for defining interfaces that
232/// generic over a capability type.
233pub trait CapabilityBound: Into<Capability> + TryFrom<Capability> + Send + Sync + 'static {
234    fn debug_typename() -> &'static str;
235}