routing/bedrock/
request_metadata.rsuse crate::rights::Rights;
use cm_rust::Availability;
use sandbox::{Capability, Data, Dict, DictKey};
use {fidl_fuchsia_component_sandbox as fsandbox, fidl_fuchsia_io as fio};
pub const METADATA_KEY_TYPE: &'static str = "type";
pub const TYPE_PROTOCOL: &'static str = "protocol";
pub const TYPE_DICTIONARY: &'static str = "dictionary";
pub const TYPE_CONFIG: &'static str = "configuration";
pub trait Metadata<T> {
const KEY: &'static str;
fn set_metadata(&self, value: T);
fn get_metadata(&self) -> Option<T>;
}
impl Metadata<Availability> for Dict {
const KEY: &'static str = "availability";
fn set_metadata(&self, value: Availability) {
let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
.expect("dict key creation failed unexpectedly");
match self.insert(key, Capability::Data(Data::String(value.to_string()))) {
Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
}
}
fn get_metadata(&self) -> Option<Availability> {
let key = DictKey::new(<Self as Metadata<Availability>>::KEY)
.expect("dict key creation failed unexpectedly");
let capability = self.get(&key).ok()??;
match capability {
Capability::Data(Data::String(availability)) => match availability.as_str() {
"Optional" => Some(Availability::Optional),
"Required" => Some(Availability::Required),
"SameAsTarget" => Some(Availability::SameAsTarget),
"Transitional" => Some(Availability::Transitional),
_ => None,
},
_ => None,
}
}
}
impl Metadata<Rights> for Dict {
const KEY: &'static str = "rights";
fn set_metadata(&self, value: Rights) {
let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
.expect("dict key creation failed unexpectedly");
match self.insert(key, Capability::Data(Data::Uint64(value.into()))) {
Ok(()) | Err(fsandbox::CapabilityStoreError::ItemAlreadyExists) => (),
Err(e) => panic!("unexpected error variant returned from Dict::insert(): {e:?}"),
}
}
fn get_metadata(&self) -> Option<Rights> {
let key = DictKey::new(<Self as Metadata<Rights>>::KEY)
.expect("dict key creation failed unexpectedly");
let capability = self.get(&key).ok()??;
let rights = match capability {
Capability::Data(Data::Uint64(rights)) => fio::Operations::from_bits(rights)?,
_ => None?,
};
Some(Rights::from(rights))
}
}
pub fn protocol_metadata(availability: cm_types::Availability) -> sandbox::Dict {
let metadata = sandbox::Dict::new();
metadata
.insert(
cm_types::Name::new(METADATA_KEY_TYPE).unwrap(),
sandbox::Capability::Data(sandbox::Data::String(String::from(TYPE_PROTOCOL))),
)
.unwrap();
metadata.set_metadata(availability);
metadata
}
pub fn dictionary_metadata(availability: cm_types::Availability) -> sandbox::Dict {
let metadata = sandbox::Dict::new();
metadata
.insert(
cm_types::Name::new(METADATA_KEY_TYPE).unwrap(),
sandbox::Capability::Data(sandbox::Data::String(String::from(TYPE_DICTIONARY))),
)
.unwrap();
metadata.set_metadata(availability);
metadata
}
pub fn config_metadata(availability: cm_types::Availability) -> sandbox::Dict {
let metadata = sandbox::Dict::new();
metadata
.insert(
cm_types::Name::new(METADATA_KEY_TYPE).unwrap(),
sandbox::Capability::Data(sandbox::Data::String(String::from(TYPE_CONFIG))),
)
.unwrap();
metadata.set_metadata(availability);
metadata
}
pub fn runner_metadata(availability: cm_types::Availability) -> sandbox::Dict {
let metadata = sandbox::Dict::new();
metadata
.insert(
cm_types::Name::new(METADATA_KEY_TYPE).unwrap(),
sandbox::Capability::Data(sandbox::Data::String(
cm_rust::CapabilityTypeName::Runner.to_string(),
)),
)
.unwrap();
metadata.set_metadata(availability);
metadata
}
pub fn resolver_metadata(availability: cm_types::Availability) -> sandbox::Dict {
let metadata = sandbox::Dict::new();
metadata
.insert(
cm_types::Name::new(METADATA_KEY_TYPE).unwrap(),
sandbox::Capability::Data(sandbox::Data::String(
cm_rust::CapabilityTypeName::Resolver.to_string(),
)),
)
.unwrap();
metadata.set_metadata(availability);
metadata
}