blob: 8c84ce7684886200fb660eb513a6688d4b68882c [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::RegistrationDecl,
cm_rust::{
CapabilityDecl, ExposeDecl, ExposeDeclCommon, OfferDecl, OfferDeclCommon, SourceName,
UseDecl, UseDeclCommon,
},
cm_types::Name,
moniker::Moniker,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// Describes a single step taken by the capability routing algorithm.
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(rename_all = "snake_case", tag = "action")
)]
#[derive(Clone, Debug, PartialEq)]
pub enum RouteSegment {
/// The capability was used by a component instance in its manifest.
UseBy { moniker: Moniker, capability: UseDecl },
/// The capability was offered by a component instance in its manifest.
OfferBy { moniker: Moniker, capability: OfferDecl },
/// The capability was exposed by a component instance in its manifest.
ExposeBy { moniker: Moniker, capability: ExposeDecl },
/// The capability was declared by a component instance in its manifest.
DeclareBy { moniker: Moniker, capability: CapabilityDecl },
/// The capability was registered in a component instance's environment in its manifest.
RegisterBy { moniker: Moniker, capability: RegistrationDecl },
/// This is a framework capability served by component manager.
ProvideFromFramework { capability: Name },
/// This is a builtin capability served by component manager.
ProvideAsBuiltin { capability: CapabilityDecl },
/// This is a capability available in component manager's namespace.
ProvideFromNamespace { capability: CapabilityDecl },
}
impl std::fmt::Display for RouteSegment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UseBy { moniker, capability } => {
write!(
f,
"`{}` used `{}` from {}",
moniker,
capability.source_name(),
capability.source()
)
}
Self::OfferBy { moniker, capability } => {
write!(
f,
"`{}` offered `{}` from {} to {}",
moniker,
capability.source_name(),
capability.source(),
capability.target()
)
}
Self::ExposeBy { moniker, capability } => {
write!(
f,
"`{}` exposed `{}` from {} to {}",
moniker,
capability.source_name(),
capability.source(),
capability.target()
)
}
Self::DeclareBy { moniker, capability } => {
write!(f, "`{}` declared capability `{}`", moniker, capability.name())
}
Self::RegisterBy { moniker, capability } => {
write!(f, "`{}` registered capability {:?}", moniker, capability)
}
Self::ProvideAsBuiltin { capability } => {
write!(f, "`{}` is a built-in capability", capability.name())
}
Self::ProvideFromFramework { capability } => {
write!(f, "`{}` is a framework capability", capability)
}
Self::ProvideFromNamespace { capability } => {
write!(f, "`{}` exists in component manager's namespace", capability.name())
}
}
}
}
impl RouteSegment {
/// Get the moniker of the component instance where this segment occurred, if any.
pub fn moniker(&self) -> Option<Moniker> {
match self {
Self::UseBy { moniker, .. }
| Self::DeclareBy { moniker, .. }
| Self::ExposeBy { moniker, .. }
| Self::OfferBy { moniker, .. }
| Self::RegisterBy { moniker, .. } => Some(moniker.clone()),
_ => None,
}
}
}
#[derive(Clone, Debug)]
pub struct RouteMapper {
route: Vec<RouteSegment>,
}
impl RouteMapper {
pub fn new() -> Self {
Self { route: vec![] }
}
pub fn get_route(self) -> Vec<RouteSegment> {
self.route
}
}
impl DebugRouteMapper for RouteMapper {
fn add_use(&mut self, moniker: Moniker, use_decl: &UseDecl) {
self.route.push(RouteSegment::UseBy { moniker: moniker, capability: use_decl.clone() })
}
fn add_offer(&mut self, moniker: Moniker, offer_decl: &OfferDecl) {
self.route.push(RouteSegment::OfferBy { moniker: moniker, capability: offer_decl.clone() })
}
fn add_expose(&mut self, moniker: Moniker, expose_decl: ExposeDecl) {
self.route.push(RouteSegment::ExposeBy { moniker: moniker, capability: expose_decl })
}
fn add_registration(&mut self, moniker: Moniker, registration_decl: &RegistrationDecl) {
self.route.push(RouteSegment::RegisterBy {
moniker: moniker,
capability: registration_decl.clone(),
})
}
fn add_component_capability(&mut self, moniker: Moniker, capability_decl: &CapabilityDecl) {
self.route
.push(RouteSegment::DeclareBy { moniker: moniker, capability: capability_decl.clone() })
}
fn add_framework_capability(&mut self, capability_name: Name) {
self.route.push(RouteSegment::ProvideFromFramework { capability: capability_name })
}
fn add_builtin_capability(&mut self, capability_decl: &CapabilityDecl) {
self.route.push(RouteSegment::ProvideAsBuiltin { capability: capability_decl.clone() })
}
fn add_namespace_capability(&mut self, capability_decl: &CapabilityDecl) {
self.route.push(RouteSegment::ProvideFromNamespace { capability: capability_decl.clone() })
}
}
#[derive(Clone, Debug)]
pub struct NoopRouteMapper;
impl DebugRouteMapper for NoopRouteMapper {}
/// Provides methods to record and retrieve a summary of a capability route.
pub trait DebugRouteMapper: Send + Sync {
#[allow(unused_variables)]
fn add_use(&mut self, moniker: Moniker, use_decl: &UseDecl) {}
#[allow(unused_variables)]
fn add_offer(&mut self, moniker: Moniker, offer_decl: &OfferDecl) {}
#[allow(unused_variables)]
fn add_expose(&mut self, moniker: Moniker, expose_decl: ExposeDecl) {}
#[allow(unused_variables)]
fn add_registration(&mut self, moniker: Moniker, registration_decl: &RegistrationDecl) {}
#[allow(unused_variables)]
fn add_component_capability(&mut self, moniker: Moniker, capability_decl: &CapabilityDecl) {}
#[allow(unused_variables)]
fn add_framework_capability(&mut self, capability_name: Name) {}
#[allow(unused_variables)]
fn add_builtin_capability(&mut self, capability_decl: &CapabilityDecl) {}
#[allow(unused_variables)]
fn add_namespace_capability(&mut self, capability_decl: &CapabilityDecl) {}
}