routing/bedrock/
request_metadata.rs1use std::path::PathBuf;
6use std::str::FromStr;
7
8use crate::rights::Rights;
9use crate::subdir::SubDir;
10use cm_rust::{Availability, CapabilityTypeName};
11use cm_types::RelativePath;
12use fidl::{persist, unpersist};
13use moniker::Moniker;
14use sandbox::{Capability, Data, Dict, DictKey};
15use {
16 fidl_fuchsia_component_internal as finternal, fidl_fuchsia_component_sandbox as fsandbox,
17 fidl_fuchsia_io as fio,
18};
19
20pub trait Metadata<T> {
22 const KEY: &'static str;
24
25 fn set_metadata(&self, value: T);
27
28 fn get_metadata(&self) -> Option<T>;
30}
31
32impl Metadata<CapabilityTypeName> for Dict {
33 const KEY: &'static str = "type";
34
35 fn set_metadata(&self, value: CapabilityTypeName) {
36 let key = DictKey::new(<Self as Metadata<CapabilityTypeName>>::KEY)
37 .expect("dict key creation failed unexpectedly");
38 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
39 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
44 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
46 }
47 }
48
49 fn get_metadata(&self) -> Option<CapabilityTypeName> {
50 let key = DictKey::new(<Self as Metadata<CapabilityTypeName>>::KEY)
51 .expect("dict key creation failed unexpectedly");
52 let capability = self.get(&key).ok()??;
53 match capability {
54 Capability::Data(Data::String(capability_type_name)) => {
55 CapabilityTypeName::from_str(&capability_type_name).ok()
56 }
57 _ => None,
58 }
59 }
60}
61
62impl Metadata<Availability> for Dict {
63 const KEY: &'static str = "availability";
64
65 fn set_metadata(&self, value: Availability) {
66 let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
67 .expect("dict key creation failed unexpectedly");
68 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
69 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
74 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
76 }
77 }
78
79 fn get_metadata(&self) -> Option<Availability> {
80 let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
81 .expect("dict key creation failed unexpectedly");
82 let capability = self.get(&key).ok()??;
83 match capability {
84 Capability::Data(Data::String(availability)) => match &*availability {
85 "Optional" => Some(Availability::Optional),
86 "Required" => Some(Availability::Required),
87 "SameAsTarget" => Some(Availability::SameAsTarget),
88 "Transitional" => Some(Availability::Transitional),
89 _ => None,
90 },
91 _ => None,
92 }
93 }
94}
95
96impl Metadata<Rights> for Dict {
97 const KEY: &'static str = "rights";
98
99 fn set_metadata(&self, value: Rights) {
100 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
101 .expect("dict key creation failed unexpectedly");
102 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
103 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
108 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
110 }
111 }
112
113 fn get_metadata(&self) -> Option<Rights> {
114 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
115 .expect("dict key creation failed unexpectedly");
116 let capability = self.get(&key).ok()??;
117 let rights = match capability {
118 Capability::Data(Data::Uint64(rights)) => fio::Operations::from_bits(rights)?,
119 _ => None?,
120 };
121 Some(Rights::from(rights))
122 }
123}
124impl Metadata<finternal::EventStreamRouteMetadata> for Dict {
125 const KEY: &'static str = "event_stream_route_metadata";
126
127 fn set_metadata(&self, esrm: finternal::EventStreamRouteMetadata) {
128 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
129 .expect("dict key creation failed unexpectedly");
130 let value = persist(&esrm).expect("failed to persist event stream route metadata");
131 match self.insert(key, Data::Bytes(value.into()).into()) {
132 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
137 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
139 }
140 }
141
142 fn get_metadata(&self) -> Option<finternal::EventStreamRouteMetadata> {
143 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
144 .expect("dict key creation failed unexpectedly");
145 let capability = self.get(&key).ok()??;
146 match capability {
147 Capability::Data(Data::Bytes(bytes)) => Some(unpersist(&bytes).ok()?),
148 _ => None,
149 }
150 }
151}
152
153pub struct IntermediateRights(pub Rights);
155
156impl Metadata<IntermediateRights> for Dict {
157 const KEY: &'static str = "intermediate_rights";
158
159 fn set_metadata(&self, value: IntermediateRights) {
160 let key = DictKey::new(<Self as Metadata<IntermediateRights>>::KEY)
161 .expect("dict key creation failed unexpectedly");
162 let IntermediateRights(value) = value;
163 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
164 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
169 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
171 }
172 }
173
174 fn get_metadata(&self) -> Option<IntermediateRights> {
175 let key = DictKey::new(<Self as Metadata<IntermediateRights>>::KEY)
176 .expect("dict key creation failed unexpectedly");
177 let capability = self.get(&key).ok()??;
178 let rights = match capability {
179 Capability::Data(Data::Uint64(rights)) => fio::Operations::from_bits(rights)?,
180 _ => None?,
181 };
182 Some(IntermediateRights(Rights::from(rights)))
183 }
184}
185
186pub struct InheritRights(pub bool);
189
190impl Metadata<InheritRights> for Dict {
191 const KEY: &'static str = "inherit_rights";
192
193 fn set_metadata(&self, value: InheritRights) {
194 let key = DictKey::new(<Self as Metadata<InheritRights>>::KEY)
195 .expect("dict key creation failed unexpectedly");
196 let InheritRights(value) = value;
197 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
198 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
203 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
205 }
206 }
207
208 fn get_metadata(&self) -> Option<InheritRights> {
209 let key = DictKey::new(<Self as Metadata<InheritRights>>::KEY)
210 .expect("dict key creation failed unexpectedly");
211 let capability = self.get(&key).ok()??;
212 let inherit = match capability {
213 Capability::Data(Data::Uint64(inherit)) => inherit != 0,
214 _ => None?,
215 };
216 Some(InheritRights(inherit))
217 }
218}
219
220impl Metadata<SubDir> for Dict {
221 const KEY: &'static str = "subdir";
222
223 fn set_metadata(&self, value: SubDir) {
224 let key = DictKey::new(<Self as Metadata<SubDir>>::KEY)
225 .expect("dict key creation failed unexpectedly");
226 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
227 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
232 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
234 }
235 }
236
237 fn get_metadata(&self) -> Option<SubDir> {
238 let key = DictKey::new(<Self as Metadata<SubDir>>::KEY)
239 .expect("dict key creation failed unexpectedly");
240 let capability = self.get(&key).ok()??;
241 match capability {
242 Capability::Data(Data::String(subdir)) => SubDir::new(subdir).ok(),
243 _ => None,
244 }
245 }
246}
247
248pub struct IsolatedStoragePath(pub PathBuf);
251
252impl Metadata<IsolatedStoragePath> for Dict {
253 const KEY: &'static str = "isolated_storage_path";
254
255 fn set_metadata(&self, value: IsolatedStoragePath) {
256 let key = DictKey::new(<Self as Metadata<IsolatedStoragePath>>::KEY)
257 .expect("dict key creation failed unexpectedly");
258 match self.insert(
259 key,
260 Capability::Data(Data::String(value.0.to_string_lossy().into_owned().into())),
261 ) {
262 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
267 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
269 }
270 }
271
272 fn get_metadata(&self) -> Option<IsolatedStoragePath> {
273 let key = DictKey::new(<Self as Metadata<IsolatedStoragePath>>::KEY)
274 .expect("dict key creation failed unexpectedly");
275 let capability = self.get(&key).ok()??;
276 match capability {
277 Capability::Data(Data::String(isolated_storage_path)) => {
278 Some(IsolatedStoragePath(PathBuf::from(isolated_storage_path.to_string())))
279 }
280 _ => None,
281 }
282 }
283}
284
285pub struct StorageSubdir(pub RelativePath);
294
295impl Metadata<StorageSubdir> for Dict {
296 const KEY: &'static str = "storage_subdir";
297
298 fn set_metadata(&self, value: StorageSubdir) {
299 let key = DictKey::new(<Self as Metadata<StorageSubdir>>::KEY)
300 .expect("dict key creation failed unexpectedly");
301 match self.insert(key, Capability::Data(Data::String(value.0.to_string().into()))) {
302 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
307 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
309 }
310 }
311
312 fn get_metadata(&self) -> Option<StorageSubdir> {
313 let key = DictKey::new(<Self as Metadata<StorageSubdir>>::KEY)
314 .expect("dict key creation failed unexpectedly");
315 let capability = self.get(&key).ok()??;
316 match capability {
317 Capability::Data(Data::String(subdir)) => {
318 Some(StorageSubdir(RelativePath::new(subdir).unwrap()))
319 }
320 _ => None,
321 }
322 }
323}
324
325pub struct StorageSourceMoniker(pub Moniker);
327
328impl Metadata<StorageSourceMoniker> for Dict {
329 const KEY: &'static str = "storage_source_moniker";
330
331 fn set_metadata(&self, value: StorageSourceMoniker) {
332 let key = DictKey::new(<Self as Metadata<StorageSourceMoniker>>::KEY)
333 .expect("dict key creation failed unexpectedly");
334 match self.insert(key, Capability::Data(Data::String(value.0.to_string().into()))) {
335 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
340 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
342 }
343 }
344
345 fn get_metadata(&self) -> Option<StorageSourceMoniker> {
346 let key = DictKey::new(<Self as Metadata<StorageSourceMoniker>>::KEY)
347 .expect("dict key creation failed unexpectedly");
348 let capability = self.get(&key).ok()??;
349 match capability {
350 Capability::Data(Data::String(moniker)) => {
351 Some(StorageSourceMoniker(Moniker::parse_str(&moniker).unwrap()))
352 }
353 _ => None,
354 }
355 }
356}
357
358pub fn protocol_metadata(availability: cm_types::Availability) -> sandbox::Dict {
360 let metadata = sandbox::Dict::new();
361 metadata.set_metadata(CapabilityTypeName::Protocol);
362 metadata.set_metadata(availability);
363 metadata
364}
365
366pub fn dictionary_metadata(availability: cm_types::Availability) -> sandbox::Dict {
368 let metadata = sandbox::Dict::new();
369 metadata.set_metadata(CapabilityTypeName::Dictionary);
370 metadata.set_metadata(availability);
371 metadata
372}
373
374pub fn directory_metadata(
376 availability: cm_types::Availability,
377 rights: Option<Rights>,
378 subdir: Option<SubDir>,
379) -> sandbox::Dict {
380 let metadata = sandbox::Dict::new();
381 metadata.set_metadata(CapabilityTypeName::Directory);
382 if let Some(subdir) = subdir {
383 metadata.set_metadata(subdir);
384 }
385 metadata.set_metadata(availability);
386 match rights {
387 Some(rights) => {
388 metadata.set_metadata(rights);
389 metadata.set_metadata(InheritRights(false));
390 }
391 None => {
392 metadata.set_metadata(InheritRights(true));
393 }
394 }
395 metadata
396}
397
398pub fn config_metadata(availability: cm_types::Availability) -> sandbox::Dict {
400 let metadata = sandbox::Dict::new();
401 metadata.set_metadata(CapabilityTypeName::Config);
402 metadata.set_metadata(availability);
403 metadata
404}
405
406pub fn runner_metadata(availability: cm_types::Availability) -> sandbox::Dict {
408 let metadata = sandbox::Dict::new();
409 metadata.set_metadata(CapabilityTypeName::Runner);
410 metadata.set_metadata(availability);
411 metadata
412}
413
414pub fn resolver_metadata(availability: cm_types::Availability) -> sandbox::Dict {
416 let metadata = sandbox::Dict::new();
417 metadata.set_metadata(CapabilityTypeName::Resolver);
418 metadata.set_metadata(availability);
419 metadata
420}
421
422pub fn service_metadata(availability: cm_types::Availability) -> sandbox::Dict {
424 let metadata = sandbox::Dict::new();
425 metadata.set_metadata(CapabilityTypeName::Service);
426 metadata.set_metadata(availability);
427 metadata.set_metadata(Rights::from(fio::R_STAR_DIR));
437 metadata.set_metadata(InheritRights(true));
438 metadata
439}
440
441pub fn event_stream_metadata(
442 availability: cm_types::Availability,
443 route_metadata: finternal::EventStreamRouteMetadata,
444) -> sandbox::Dict {
445 let metadata = sandbox::Dict::new();
446 metadata.set_metadata(CapabilityTypeName::EventStream);
447 metadata.set_metadata(availability);
448 metadata.set_metadata(route_metadata);
449 metadata
450}
451
452pub fn storage_metadata(availability: cm_types::Availability) -> sandbox::Dict {
454 let metadata = sandbox::Dict::new();
455 metadata.set_metadata(CapabilityTypeName::Storage);
456 metadata.set_metadata(availability);
457 metadata.set_metadata(Rights::from(fio::RW_STAR_DIR));
458 metadata.set_metadata(InheritRights(false));
459 metadata
460}