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 std::sync::Arc;
10use thiserror::Error;
11use zx_status;
12
13#[derive(Error, Debug, Clone)]
14pub enum ConversionError {
15    #[error("conversion to type is not supported")]
16    NotSupported,
17}
18
19/// Errors arising from conversion between Rust and FIDL types.
20#[derive(Error, Debug)]
21pub enum RemoteError {
22    #[error("unknown FIDL variant")]
23    UnknownVariant,
24
25    #[error("unregistered capability; only capabilities created by sandbox are allowed")]
26    Unregistered,
27
28    #[error("registered capability had the wrong type")]
29    BadCapability,
30}
31
32impl Explain for RemoteError {
33    fn as_zx_status(&self) -> zx_status::Status {
34        match self {
35            RemoteError::UnknownVariant => zx_status::Status::NOT_SUPPORTED,
36            RemoteError::Unregistered => zx_status::Status::INVALID_ARGS,
37            RemoteError::BadCapability => zx_status::Status::INVALID_ARGS,
38        }
39    }
40}
41
42#[derive(FromEnum, Debug, Clone)]
43pub enum Capability {
44    Connector(Arc<crate::Connector>),
45    DirConnector(Arc<crate::DirConnector>),
46    Dictionary(Arc<crate::Dictionary>),
47    Data(crate::Data),
48    Handle(Arc<crate::Handle>),
49    ConnectorRouter(Arc<crate::Router<crate::Connector>>),
50    DictionaryRouter(Arc<crate::Router<crate::Dictionary>>),
51    DirConnectorRouter(Arc<crate::Router<crate::DirConnector>>),
52    DataRouter(Arc<crate::Router<crate::Data>>),
53    Instance(Arc<crate::WeakInstanceToken>),
54}
55
56// Every `Dictionary` entry across all component sandboxes stores `(DictKey, Capability)`.
57// Guard against accidental enum size regressions; all `Capability` variants must remain <= 16B
58// so that `Capability` stays 16 bytes and `(DictKey, Capability)` stays 24 bytes.
59#[cfg(target_pointer_width = "64")]
60const _: () = {
61    assert!(std::mem::size_of::<crate::Data>() == 16);
62    assert!(std::mem::size_of::<Capability>() == 16);
63    assert!(std::mem::size_of::<(crate::DictKey, Capability)>() == 24);
64};
65
66impl Capability {
67    pub fn to_dictionary(self) -> Option<Arc<crate::Dictionary>> {
68        match self {
69            Self::Dictionary(d) => Some(d),
70            _ => None,
71        }
72    }
73
74    pub fn debug_typename(&self) -> &'static str {
75        match self {
76            Self::Connector(_) => crate::Connector::debug_typename(),
77            Self::DirConnector(_) => crate::DirConnector::debug_typename(),
78            Self::ConnectorRouter(_) => crate::Router::<crate::Connector>::debug_typename(),
79            Self::DictionaryRouter(_) => crate::Router::<crate::Dictionary>::debug_typename(),
80            Self::DirConnectorRouter(_) => crate::Router::<crate::DirConnector>::debug_typename(),
81            Self::DataRouter(_) => crate::Router::<crate::Data>::debug_typename(),
82            Self::Dictionary(_) => crate::Dictionary::debug_typename(),
83            Self::Data(_) => crate::Data::debug_typename(),
84            Self::Handle(_) => crate::Handle::debug_typename(),
85            Self::Instance(_) => "Instance",
86        }
87    }
88
89    /// Returns information about the capability which is useful to an [`ErrorLoggingRouter`].
90    pub fn error_info(&self) -> Option<crate::RouterErrorInfo> {
91        match self {
92            Self::ConnectorRouter(r) => r.error_info(),
93            Self::DictionaryRouter(r) => r.error_info(),
94            Self::DirConnectorRouter(r) => r.error_info(),
95            Self::DataRouter(r) => r.error_info(),
96            _ => None,
97        }
98    }
99}
100
101impl TryFrom<Capability> for Arc<crate::Connector> {
102    type Error = ();
103
104    fn try_from(c: Capability) -> Result<Self, Self::Error> {
105        match c {
106            Capability::Connector(c) => Ok(c),
107            _ => Err(()),
108        }
109    }
110}
111
112impl TryFrom<Capability> for Arc<crate::DirConnector> {
113    type Error = ();
114
115    fn try_from(c: Capability) -> Result<Self, Self::Error> {
116        match c {
117            Capability::DirConnector(c) => Ok(c),
118            _ => Err(()),
119        }
120    }
121}
122
123impl TryFrom<Capability> for Arc<crate::Dictionary> {
124    type Error = ();
125
126    fn try_from(c: Capability) -> Result<Self, Self::Error> {
127        match c {
128            Capability::Dictionary(c) => Ok(c),
129            _ => Err(()),
130        }
131    }
132}
133
134impl TryFrom<Capability> for crate::Data {
135    type Error = ();
136
137    fn try_from(c: Capability) -> Result<Self, Self::Error> {
138        match c {
139            Capability::Data(c) => Ok(c),
140            _ => Err(()),
141        }
142    }
143}
144
145impl TryFrom<Capability> for Arc<Router<crate::Dictionary>> {
146    type Error = ();
147
148    fn try_from(c: Capability) -> Result<Self, Self::Error> {
149        match c {
150            Capability::DictionaryRouter(c) => Ok(c),
151            _ => Err(()),
152        }
153    }
154}
155
156impl TryFrom<Capability> for Arc<Router<crate::DirConnector>> {
157    type Error = ();
158
159    fn try_from(c: Capability) -> Result<Self, Self::Error> {
160        match c {
161            Capability::DirConnectorRouter(c) => Ok(c),
162            _ => Err(()),
163        }
164    }
165}
166
167impl TryFrom<Capability> for Arc<Router<crate::Connector>> {
168    type Error = ();
169
170    fn try_from(c: Capability) -> Result<Self, Self::Error> {
171        match c {
172            Capability::ConnectorRouter(c) => Ok(c),
173            _ => Err(()),
174        }
175    }
176}
177
178impl TryFrom<Capability> for Arc<Router<crate::Data>> {
179    type Error = ();
180
181    fn try_from(c: Capability) -> Result<Self, Self::Error> {
182        match c {
183            Capability::DataRouter(c) => Ok(c),
184            _ => Err(()),
185        }
186    }
187}
188
189impl TryFrom<Capability> for Arc<crate::WeakInstanceToken> {
190    type Error = ();
191
192    fn try_from(c: Capability) -> Result<Self, Self::Error> {
193        match c {
194            Capability::Instance(i) => Ok(i),
195            _ => Err(()),
196        }
197    }
198}
199
200/// Parent trait implemented by all capability types. Useful for defining interfaces that
201/// generic over a capability type.
202pub trait CapabilityBound: Send + Sync + 'static {
203    fn debug_typename() -> &'static str;
204
205    /// Converts this capability into a directory entry.
206    ///
207    /// This is on the "main" capability trait because this is something supported by (almost)
208    /// every capability type, and all capability types are expected to either support this or be
209    /// able to report that they cannot (i.e. return an error when this is called).
210    #[cfg(target_os = "fuchsia")]
211    fn try_into_directory_entry(
212        self: Arc<Self>,
213        _scope: vfs::execution_scope::ExecutionScope,
214        _token: Arc<crate::WeakInstanceToken>,
215    ) -> Result<Arc<dyn vfs::directory::entry::DirectoryEntry>, crate::ConversionError> {
216        Err(ConversionError::NotSupported)
217    }
218}