routing/bedrock/
request_metadata.rs1use std::str::FromStr;
6
7use crate::rights::Rights;
8use crate::subdir::SubDir;
9use cm_rust::{Availability, CapabilityTypeName};
10use fidl::{persist, unpersist};
11use sandbox::{Capability, Data, Dict, DictKey};
12use {
13 fidl_fuchsia_component_internal as finternal, fidl_fuchsia_component_sandbox as fsandbox,
14 fidl_fuchsia_io as fio,
15};
16
17pub trait Metadata<T> {
19 const KEY: &'static str;
21
22 fn set_metadata(&self, value: T);
24
25 fn get_metadata(&self) -> Option<T>;
27}
28
29impl Metadata<CapabilityTypeName> for Dict {
30 const KEY: &'static str = "type";
31
32 fn set_metadata(&self, value: CapabilityTypeName) {
33 let key = DictKey::new(<Self as Metadata<CapabilityTypeName>>::KEY)
34 .expect("dict key creation failed unexpectedly");
35 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
36 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
41 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
43 }
44 }
45
46 fn get_metadata(&self) -> Option<CapabilityTypeName> {
47 let key = DictKey::new(<Self as Metadata<CapabilityTypeName>>::KEY)
48 .expect("dict key creation failed unexpectedly");
49 let capability = self.get(&key).ok()??;
50 match capability {
51 Capability::Data(Data::String(capability_type_name)) => {
52 CapabilityTypeName::from_str(&capability_type_name).ok()
53 }
54 _ => None,
55 }
56 }
57}
58
59impl Metadata<Availability> for Dict {
60 const KEY: &'static str = "availability";
61
62 fn set_metadata(&self, value: Availability) {
63 let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
64 .expect("dict key creation failed unexpectedly");
65 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
66 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
71 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
73 }
74 }
75
76 fn get_metadata(&self) -> Option<Availability> {
77 let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
78 .expect("dict key creation failed unexpectedly");
79 let capability = self.get(&key).ok()??;
80 match capability {
81 Capability::Data(Data::String(availability)) => match &*availability {
82 "Optional" => Some(Availability::Optional),
83 "Required" => Some(Availability::Required),
84 "SameAsTarget" => Some(Availability::SameAsTarget),
85 "Transitional" => Some(Availability::Transitional),
86 _ => None,
87 },
88 _ => None,
89 }
90 }
91}
92
93impl Metadata<Rights> for Dict {
94 const KEY: &'static str = "rights";
95
96 fn set_metadata(&self, value: Rights) {
97 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
98 .expect("dict key creation failed unexpectedly");
99 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
100 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
105 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
107 }
108 }
109
110 fn get_metadata(&self) -> Option<Rights> {
111 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
112 .expect("dict key creation failed unexpectedly");
113 let capability = self.get(&key).ok()??;
114 let rights = match capability {
115 Capability::Data(Data::Uint64(rights)) => fio::Operations::from_bits(rights)?,
116 _ => None?,
117 };
118 Some(Rights::from(rights))
119 }
120}
121impl Metadata<finternal::EventStreamRouteMetadata> for Dict {
122 const KEY: &'static str = "event_stream_route_metadata";
123
124 fn set_metadata(&self, esrm: finternal::EventStreamRouteMetadata) {
125 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
126 .expect("dict key creation failed unexpectedly");
127 let value = persist(&esrm).expect("failed to persist event stream route metadata");
128 match self.insert(key, Data::Bytes(value.into()).into()) {
129 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
134 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
136 }
137 }
138
139 fn get_metadata(&self) -> Option<finternal::EventStreamRouteMetadata> {
140 let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
141 .expect("dict key creation failed unexpectedly");
142 let capability = self.get(&key).ok()??;
143 match capability {
144 Capability::Data(Data::Bytes(bytes)) => Some(unpersist(&bytes).ok()?),
145 _ => None,
146 }
147 }
148}
149
150pub struct IntermediateRights(pub Rights);
152
153impl Metadata<IntermediateRights> for Dict {
154 const KEY: &'static str = "intermediate_rights";
155
156 fn set_metadata(&self, value: IntermediateRights) {
157 let key = DictKey::new(<Self as Metadata<IntermediateRights>>::KEY)
158 .expect("dict key creation failed unexpectedly");
159 let IntermediateRights(value) = value;
160 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
161 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
166 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
168 }
169 }
170
171 fn get_metadata(&self) -> Option<IntermediateRights> {
172 let key = DictKey::new(<Self as Metadata<IntermediateRights>>::KEY)
173 .expect("dict key creation failed unexpectedly");
174 let capability = self.get(&key).ok()??;
175 let rights = match capability {
176 Capability::Data(Data::Uint64(rights)) => fio::Operations::from_bits(rights)?,
177 _ => None?,
178 };
179 Some(IntermediateRights(Rights::from(rights)))
180 }
181}
182
183pub struct InheritRights(pub bool);
186
187impl Metadata<InheritRights> for Dict {
188 const KEY: &'static str = "inherit_rights";
189
190 fn set_metadata(&self, value: InheritRights) {
191 let key = DictKey::new(<Self as Metadata<InheritRights>>::KEY)
192 .expect("dict key creation failed unexpectedly");
193 let InheritRights(value) = value;
194 match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
195 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
200 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
202 }
203 }
204
205 fn get_metadata(&self) -> Option<InheritRights> {
206 let key = DictKey::new(<Self as Metadata<InheritRights>>::KEY)
207 .expect("dict key creation failed unexpectedly");
208 let capability = self.get(&key).ok()??;
209 let inherit = match capability {
210 Capability::Data(Data::Uint64(inherit)) => inherit != 0,
211 _ => None?,
212 };
213 Some(InheritRights(inherit))
214 }
215}
216
217impl Metadata<SubDir> for Dict {
218 const KEY: &'static str = "subdir";
219
220 fn set_metadata(&self, value: SubDir) {
221 let key = DictKey::new(<Self as Metadata<SubDir>>::KEY)
222 .expect("dict key creation failed unexpectedly");
223 match self.insert(key, Capability::Data(Data::String(value.to_string().into()))) {
224 Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
229 Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
231 }
232 }
233
234 fn get_metadata(&self) -> Option<SubDir> {
235 let key = DictKey::new(<Self as Metadata<SubDir>>::KEY)
236 .expect("dict key creation failed unexpectedly");
237 let capability = self.get(&key).ok()??;
238 match capability {
239 Capability::Data(Data::String(subdir)) => SubDir::new(subdir).ok(),
240 _ => None,
241 }
242 }
243}
244
245pub fn protocol_metadata(availability: cm_types::Availability) -> sandbox::Dict {
247 let metadata = sandbox::Dict::new();
248 metadata.set_metadata(CapabilityTypeName::Protocol);
249 metadata.set_metadata(availability);
250 metadata
251}
252
253pub fn dictionary_metadata(availability: cm_types::Availability) -> sandbox::Dict {
255 let metadata = sandbox::Dict::new();
256 metadata.set_metadata(CapabilityTypeName::Dictionary);
257 metadata.set_metadata(availability);
258 metadata
259}
260
261pub fn directory_metadata(
263 availability: cm_types::Availability,
264 rights: Option<Rights>,
265 subdir: Option<SubDir>,
266) -> sandbox::Dict {
267 let metadata = sandbox::Dict::new();
268 metadata.set_metadata(CapabilityTypeName::Directory);
269 if let Some(subdir) = subdir {
270 metadata.set_metadata(subdir);
271 }
272 metadata.set_metadata(availability);
273 match rights {
274 Some(rights) => {
275 metadata.set_metadata(rights);
276 metadata.set_metadata(InheritRights(false));
277 }
278 None => {
279 metadata.set_metadata(InheritRights(true));
280 }
281 }
282 metadata
283}
284
285pub fn config_metadata(availability: cm_types::Availability) -> sandbox::Dict {
287 let metadata = sandbox::Dict::new();
288 metadata.set_metadata(CapabilityTypeName::Config);
289 metadata.set_metadata(availability);
290 metadata
291}
292
293pub fn runner_metadata(availability: cm_types::Availability) -> sandbox::Dict {
295 let metadata = sandbox::Dict::new();
296 metadata.set_metadata(CapabilityTypeName::Runner);
297 metadata.set_metadata(availability);
298 metadata
299}
300
301pub fn resolver_metadata(availability: cm_types::Availability) -> sandbox::Dict {
303 let metadata = sandbox::Dict::new();
304 metadata.set_metadata(CapabilityTypeName::Resolver);
305 metadata.set_metadata(availability);
306 metadata
307}
308
309pub fn service_metadata(availability: cm_types::Availability) -> sandbox::Dict {
311 let metadata = sandbox::Dict::new();
312 metadata.set_metadata(CapabilityTypeName::Service);
313 metadata.set_metadata(availability);
314 metadata.set_metadata(Rights::from(fio::R_STAR_DIR));
324 metadata.set_metadata(InheritRights(true));
325 metadata
326}
327
328pub fn event_stream_metadata(
329 availability: cm_types::Availability,
330 route_metadata: finternal::EventStreamRouteMetadata,
331) -> sandbox::Dict {
332 let metadata = sandbox::Dict::new();
333 metadata.set_metadata(CapabilityTypeName::EventStream);
334 metadata.set_metadata(availability);
335 metadata.set_metadata(route_metadata);
336 metadata
337}