use {
crate::{
capability_source::{BuiltinCapabilities, NamespaceCapabilities},
environment,
error::ComponentInstanceError,
policy::GlobalPolicyChecker,
resolving::{ComponentAddress, ComponentResolutionContext},
},
async_trait::async_trait,
cm_moniker::InstancedMoniker,
cm_rust::{CapabilityDecl, CollectionDecl, ExposeDecl, OfferDecl, OfferSource, UseDecl},
cm_types::{Name, Url},
derivative::Derivative,
moniker::{ChildName, ExtendedMoniker, Moniker, MonikerBase},
std::{
clone::Clone,
sync::{Arc, Weak},
},
};
#[async_trait]
pub trait ComponentInstanceInterface: Sized + Send + Sync {
type TopInstance: TopInstanceInterface + Send + Sync;
fn as_weak(self: &Arc<Self>) -> WeakComponentInstanceInterface<Self> {
WeakComponentInstanceInterface::new(self)
}
fn child_moniker(&self) -> Option<&ChildName>;
fn instanced_moniker(&self) -> &InstancedMoniker;
fn moniker(&self) -> &Moniker;
fn url(&self) -> &Url;
fn environment(&self) -> &environment::Environment<Self>;
fn config_parent_overrides(&self) -> Option<&Vec<cm_rust::ConfigOverride>>;
fn policy_checker(&self) -> &GlobalPolicyChecker;
fn component_id_index(&self) -> &component_id_index::Index;
fn try_get_parent(&self) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError>;
async fn lock_resolved_state<'a>(
self: &'a Arc<Self>,
) -> Result<Box<dyn ResolvedInstanceInterface<Component = Self> + 'a>, ComponentInstanceError>;
}
pub trait ResolvedInstanceInterface: Send + Sync {
type Component;
fn uses(&self) -> Vec<UseDecl>;
fn exposes(&self) -> Vec<ExposeDecl>;
fn offers(&self) -> Vec<OfferDecl>;
fn capabilities(&self) -> Vec<CapabilityDecl>;
fn collections(&self) -> Vec<CollectionDecl>;
fn get_child(&self, moniker: &ChildName) -> Option<Arc<Self::Component>>;
fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)>;
fn address(&self) -> ComponentAddress;
fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext>;
}
pub trait ResolvedInstanceInterfaceExt: ResolvedInstanceInterface {
fn offer_source_exists(&self, source: &OfferSource) -> bool {
match source {
OfferSource::Framework
| OfferSource::Self_
| OfferSource::Parent
| OfferSource::Void => true,
OfferSource::Child(cm_rust::ChildRef { name, collection }) => {
let child_moniker = match ChildName::try_new(
name.as_str(),
collection.as_ref().map(|c| c.as_str()),
) {
Ok(m) => m,
Err(_) => return false,
};
self.get_child(&child_moniker).is_some()
}
OfferSource::Collection(collection_name) => {
self.collections().into_iter().any(|collection| collection.name == *collection_name)
}
OfferSource::Capability(capability_name) => self
.capabilities()
.into_iter()
.any(|capability| capability.name() == capability_name),
}
}
}
impl<T: ResolvedInstanceInterface> ResolvedInstanceInterfaceExt for T {}
impl<T> ResolvedInstanceInterface for T
where
T: std::ops::Deref + Send + Sync,
T::Target: ResolvedInstanceInterface,
{
type Component = <T::Target as ResolvedInstanceInterface>::Component;
fn uses(&self) -> Vec<UseDecl> {
T::Target::uses(&*self)
}
fn exposes(&self) -> Vec<ExposeDecl> {
T::Target::exposes(&*self)
}
fn offers(&self) -> Vec<cm_rust::OfferDecl> {
T::Target::offers(&*self)
}
fn capabilities(&self) -> Vec<cm_rust::CapabilityDecl> {
T::Target::capabilities(&*self)
}
fn collections(&self) -> Vec<cm_rust::CollectionDecl> {
T::Target::collections(&*self)
}
fn get_child(&self, moniker: &ChildName) -> Option<Arc<Self::Component>> {
T::Target::get_child(&*self, moniker)
}
fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)> {
T::Target::children_in_collection(&*self, collection)
}
fn address(&self) -> ComponentAddress {
T::Target::address(&*self)
}
fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext> {
T::Target::context_to_resolve_children(&*self)
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Default(bound = ""), Debug)]
pub struct WeakComponentInstanceInterface<C: ComponentInstanceInterface> {
#[derivative(Debug = "ignore")]
inner: Weak<C>,
pub moniker: Moniker,
}
impl<C: ComponentInstanceInterface> WeakComponentInstanceInterface<C> {
pub fn new(component: &Arc<C>) -> Self {
Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
}
pub fn invalid() -> Self {
Self { inner: Weak::new(), moniker: Moniker::new(vec![]) }
}
pub fn upgrade(&self) -> Result<Arc<C>, ComponentInstanceError> {
self.inner
.upgrade()
.ok_or_else(|| ComponentInstanceError::instance_not_found(self.moniker.clone()))
}
}
impl<C: ComponentInstanceInterface> From<&Arc<C>> for WeakComponentInstanceInterface<C> {
fn from(component: &Arc<C>) -> Self {
Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
}
}
#[derive(Debug, Clone)]
pub enum ExtendedInstanceInterface<C: ComponentInstanceInterface> {
Component(Arc<C>),
AboveRoot(Arc<C::TopInstance>),
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Debug(bound = ""))]
pub enum WeakExtendedInstanceInterface<C: ComponentInstanceInterface> {
Component(WeakComponentInstanceInterface<C>),
AboveRoot(Weak<C::TopInstance>),
}
impl<C: ComponentInstanceInterface> WeakExtendedInstanceInterface<C> {
pub fn upgrade(&self) -> Result<ExtendedInstanceInterface<C>, ComponentInstanceError> {
match self {
WeakExtendedInstanceInterface::Component(p) => {
Ok(ExtendedInstanceInterface::Component(p.upgrade()?))
}
WeakExtendedInstanceInterface::AboveRoot(p) => {
Ok(ExtendedInstanceInterface::AboveRoot(
p.upgrade().ok_or(ComponentInstanceError::cm_instance_unavailable())?,
))
}
}
}
pub fn extended_moniker(&self) -> ExtendedMoniker {
match self {
Self::Component(p) => ExtendedMoniker::ComponentInstance(p.moniker.clone()),
Self::AboveRoot(_) => ExtendedMoniker::ComponentManager,
}
}
}
impl<C: ComponentInstanceInterface> From<&ExtendedInstanceInterface<C>>
for WeakExtendedInstanceInterface<C>
{
fn from(extended: &ExtendedInstanceInterface<C>) -> Self {
match extended {
ExtendedInstanceInterface::Component(component) => {
WeakExtendedInstanceInterface::Component(WeakComponentInstanceInterface::new(
component,
))
}
ExtendedInstanceInterface::AboveRoot(top_instance) => {
WeakExtendedInstanceInterface::AboveRoot(Arc::downgrade(top_instance))
}
}
}
}
pub trait TopInstanceInterface: Sized + std::fmt::Debug {
fn namespace_capabilities(&self) -> &NamespaceCapabilities;
fn builtin_capabilities(&self) -> &BuiltinCapabilities;
}
#[cfg(test)]
pub mod tests {
use super::*;
#[derive(Debug)]
pub struct TestTopInstance {}
impl TopInstanceInterface for TestTopInstance {
fn namespace_capabilities(&self) -> &NamespaceCapabilities {
todo!()
}
fn builtin_capabilities(&self) -> &BuiltinCapabilities {
todo!()
}
}
pub struct TestComponent {}
#[async_trait]
impl ComponentInstanceInterface for TestComponent {
type TopInstance = TestTopInstance;
fn child_moniker(&self) -> Option<&ChildName> {
todo!()
}
fn instanced_moniker(&self) -> &InstancedMoniker {
todo!()
}
fn moniker(&self) -> &Moniker {
todo!()
}
fn url(&self) -> &Url {
todo!()
}
fn environment(&self) -> &crate::environment::Environment<Self> {
todo!()
}
fn config_parent_overrides(&self) -> Option<&Vec<cm_rust::ConfigOverride>> {
todo!()
}
fn policy_checker(&self) -> &GlobalPolicyChecker {
todo!()
}
fn component_id_index(&self) -> &component_id_index::Index {
todo!()
}
fn try_get_parent(
&self,
) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
todo!()
}
async fn lock_resolved_state<'a>(
self: &'a Arc<Self>,
) -> Result<Box<dyn ResolvedInstanceInterface<Component = Self> + 'a>, ComponentInstanceError>
{
todo!()
}
}
}