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