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
56impl Capability {
57    pub fn to_dictionary(self) -> Option<Arc<crate::Dictionary>> {
58        match self {
59            Self::Dictionary(d) => Some(d),
60            _ => None,
61        }
62    }
63
64    pub fn debug_typename(&self) -> &'static str {
65        match self {
66            Self::Connector(_) => crate::Connector::debug_typename(),
67            Self::DirConnector(_) => crate::DirConnector::debug_typename(),
68            Self::ConnectorRouter(_) => crate::Router::<crate::Connector>::debug_typename(),
69            Self::DictionaryRouter(_) => crate::Router::<crate::Dictionary>::debug_typename(),
70            Self::DirConnectorRouter(_) => crate::Router::<crate::DirConnector>::debug_typename(),
71            Self::DataRouter(_) => crate::Router::<crate::Data>::debug_typename(),
72            Self::Dictionary(_) => crate::Dictionary::debug_typename(),
73            Self::Data(_) => crate::Data::debug_typename(),
74            Self::Handle(_) => crate::Handle::debug_typename(),
75            Self::Instance(_) => "Instance",
76        }
77    }
78}
79
80impl TryFrom<Capability> for Arc<crate::Connector> {
81    type Error = ();
82
83    fn try_from(c: Capability) -> Result<Self, Self::Error> {
84        match c {
85            Capability::Connector(c) => Ok(c),
86            _ => Err(()),
87        }
88    }
89}
90
91impl TryFrom<Capability> for Arc<crate::DirConnector> {
92    type Error = ();
93
94    fn try_from(c: Capability) -> Result<Self, Self::Error> {
95        match c {
96            Capability::DirConnector(c) => Ok(c),
97            _ => Err(()),
98        }
99    }
100}
101
102impl TryFrom<Capability> for Arc<crate::Dictionary> {
103    type Error = ();
104
105    fn try_from(c: Capability) -> Result<Self, Self::Error> {
106        match c {
107            Capability::Dictionary(c) => Ok(c),
108            _ => Err(()),
109        }
110    }
111}
112
113impl TryFrom<Capability> for crate::Data {
114    type Error = ();
115
116    fn try_from(c: Capability) -> Result<Self, Self::Error> {
117        match c {
118            Capability::Data(c) => Ok(c),
119            _ => Err(()),
120        }
121    }
122}
123
124impl TryFrom<Capability> for Arc<Router<crate::Dictionary>> {
125    type Error = ();
126
127    fn try_from(c: Capability) -> Result<Self, Self::Error> {
128        match c {
129            Capability::DictionaryRouter(c) => Ok(c),
130            _ => Err(()),
131        }
132    }
133}
134
135impl TryFrom<Capability> for Arc<Router<crate::DirConnector>> {
136    type Error = ();
137
138    fn try_from(c: Capability) -> Result<Self, Self::Error> {
139        match c {
140            Capability::DirConnectorRouter(c) => Ok(c),
141            _ => Err(()),
142        }
143    }
144}
145
146impl TryFrom<Capability> for Arc<Router<crate::Connector>> {
147    type Error = ();
148
149    fn try_from(c: Capability) -> Result<Self, Self::Error> {
150        match c {
151            Capability::ConnectorRouter(c) => Ok(c),
152            _ => Err(()),
153        }
154    }
155}
156
157impl TryFrom<Capability> for Arc<Router<crate::Data>> {
158    type Error = ();
159
160    fn try_from(c: Capability) -> Result<Self, Self::Error> {
161        match c {
162            Capability::DataRouter(c) => Ok(c),
163            _ => Err(()),
164        }
165    }
166}
167
168impl TryFrom<Capability> for Arc<crate::WeakInstanceToken> {
169    type Error = ();
170
171    fn try_from(c: Capability) -> Result<Self, Self::Error> {
172        match c {
173            Capability::Instance(i) => Ok(i),
174            _ => Err(()),
175        }
176    }
177}
178
179/// Parent trait implemented by all capability types. Useful for defining interfaces that
180/// generic over a capability type.
181pub trait CapabilityBound: Send + Sync + 'static {
182    fn debug_typename() -> &'static str;
183
184    /// Converts this capability into a directory entry.
185    ///
186    /// This is on the "main" capability trait because this is something supported by (almost)
187    /// every capability type, and all capability types are expected to either support this or be
188    /// able to report that they cannot (i.e. return an error when this is called).
189    #[cfg(target_os = "fuchsia")]
190    fn try_into_directory_entry(
191        self: Arc<Self>,
192        _scope: vfs::execution_scope::ExecutionScope,
193        _token: Arc<crate::WeakInstanceToken>,
194    ) -> Result<Arc<dyn vfs::directory::entry::DirectoryEntry>, crate::ConversionError> {
195        Err(ConversionError::NotSupported)
196    }
197}