/// find_capability_source will walk the component tree to find the originating source of a
/// capability, starting on the given abs_moniker. It returns the absolute moniker of the
/// originating component, a reference to its realm, and the capability exposed or offered at the
/// originating source. If the absolute moniker and realm are None, then the capability originates
/// at the returned path in componentmgr's namespace.
find_capability_source will walk the component tree to find the originating source of a
capability, starting on the given abs_moniker. It returns the absolute moniker of the
originating component, a reference to its realm, and the capability exposed or offered at the
originating source. If the absolute moniker and realm are None, then the capability originates
at the returned path in componentmgr's namespace.
find_capability_source will walk the component tree to find the originating source of a capability starting on the given abs_moniker . It returns the absolute moniker of the originating component a reference to its realm and the capability exposed or offered at the originating source . If the absolute moniker and realm are None then the capability originates at the returned path in componentmgr ' s namespace .
async fn find_capability_source<'a>(
    model: &'a Model,
    used_capability: &'a Capability,
    abs_moniker: AbsoluteMoniker,
) -> Result<CapabilitySource, ModelError> {
    // Holds mutable state as we walk the tree
    struct State {
        // The capability as it's represented in the current component
        capability: Capability,
        // The name of the child we came from
        name: Option<ChildMoniker>,
        // The moniker of the component we are currently looking at
        moniker: AbsoluteMoniker,
    }
    let moniker = match abs_moniker.parent() {
        Some(m) => m,
        None => return Ok(CapabilitySource::ComponentMgrNamespace(used_capability.clone())),
    };
    let mut s = State {
        capability: used_capability.clone(),
        name: abs_moniker.path().last().map(|c| c.clone()),
        moniker: moniker,
    };
    // Walk offer chain
    'offerloop: loop {
        let current_realm = await!(model.look_up_realm(&s.moniker))?;
        let realm_state = await!(current_realm.instance.state.lock());
        // This unwrap is safe because look_up_realm populates this field
        let decl = realm_state.decl.as_ref().expect("missing offer decl");
        if let Some(offer) = decl.find_offer_source(&s.capability, &s.name.unwrap().name()) {
            let source = match offer {
                OfferDecl::Service(s) => &s.source,
                OfferDecl::Directory(d) => &d.source,
            };
            match source {
                OfferSource::Realm => {
                    // The offered capability comes from the realm, so follow the
                    // parent
                    s.capability = offer.clone().into();
                    s.name = s.moniker.path().last().map(|c| c.clone());
                    s.moniker = match s.moniker.parent() {
                        Some(m) => m,
                        None => {
                            return Ok(CapabilitySource::ComponentMgrNamespace(
                                s.capability.clone().into(),
                            ))
                        }
                    };
                    continue 'offerloop;
                }
                OfferSource::Myself => {
                    // The offered capability comes from the current component,
                    // return our current location in the tree.
                    return Ok(CapabilitySource::Component(
                        offer.clone().into(),
                        current_realm.clone(),
                    ));
                }
                OfferSource::Child(child_name) => {
                    // The offered capability comes from a child, break the loop
                    // and begin walking the expose chain.
                    s.capability = offer.clone().into();
                    s.moniker = s.moniker.child(ChildMoniker::new(child_name.to_string()));
                    break 'offerloop;
                }
            }
        } else {
            return Err(ModelError::capability_discovery_error(format_err!(
                "no matching offers found for capability {} from component {}",
                s.capability,
                s.moniker
            )));
        }
    }
    // Walk expose chain
    loop {
        let current_realm = await!(model.look_up_realm(&s.moniker))?;
        let realm_state = await!(current_realm.instance.state.lock());
        // This unwrap is safe because look_up_realm populates this field
        let decl = realm_state.decl.as_ref().expect("missing expose decl");
        if let Some(expose) = decl.find_expose_source(&s.capability) {
            let source = match expose {
                ExposeDecl::Service(s) => &s.source,
                ExposeDecl::Directory(d) => &d.source,
            };
            match source {
                ExposeSource::Myself => {
                    // The offered capability comes from the current component, return our
                    // current location in the tree.
                    return Ok(CapabilitySource::Component(
                        expose.clone().into(),
                        current_realm.clone(),
                    ));
                }
                ExposeSource::Child(child_name) => {
                    // The offered capability comes from a child, so follow the child.
                    s.capability = expose.clone().into();
                    s.moniker = s.moniker.child(ChildMoniker::new(child_name.to_string()));
                    continue;
                }
            }
        } else {
            // We didn't find any matching exposes! Oh no!
            return Err(ModelError::capability_discovery_error(format_err!(
                "no matching exposes found for capability {} from component {}",
                s.capability,
                s.moniker
            )));
        }
    }
}
async fn find_capability_source < ' a > ( model : & ' a Model , used_capability : & ' a Capability , abs_moniker : AbsoluteMoniker , ) -> Result < CapabilitySource , ModelError > { // Holds mutable state as we walk the tree struct State { // The capability as it's represented in the current component capability : Capability , // The name of the child we came from name : Option < ChildMoniker > , // The moniker of the component we are currently looking at moniker : AbsoluteMoniker , } let moniker = match abs_moniker . parent ( ) { Some ( m ) => m , None => return Ok ( CapabilitySource :: ComponentMgrNamespace ( used_capability . clone ( ) ) ) , } ; let mut s = State { capability : used_capability . clone ( ) , name : abs_moniker . path ( ) . last ( ) . map ( | c | c . clone ( ) ) , moniker : moniker , } ; // Walk offer chain ' offerloop : loop { let current_realm = await ! ( model look_up_realm ( s moniker ) ) ? ; let realm_state = await ! ( current_realm instance state lock ( ) ) ; // This unwrap is safe because look_up_realm populates this field let decl = realm_state . decl . as_ref ( ) . expect ( " " ) ; if let Some ( offer ) = decl . find_offer_source ( & s . capability , & s . name . unwrap ( ) . name ( ) ) { let source = match offer { OfferDecl :: Service ( s ) => & s . source , OfferDecl :: Directory ( d ) => & d . source , } ; match source { OfferSource :: Realm => { // The offered capability comes from the realm, so follow the // parent s . capability = offer . clone ( ) . into ( ) ; s . name = s . moniker . path ( ) . last ( ) . map ( | c | c . clone ( ) ) ; s . moniker = match s . moniker . parent ( ) { Some ( m ) => m , None => { return Ok ( CapabilitySource :: ComponentMgrNamespace ( s . capability . clone ( ) . into ( ) , ) ) } } ; continue ' offerloop ; } OfferSource :: Myself => { // The offered capability comes from the current component, // return our current location in the tree. return Ok ( CapabilitySource :: Component ( offer . clone ( ) . into ( ) , current_realm . clone ( ) , ) ) ; } OfferSource :: Child ( child_name ) => { // The offered capability comes from a child, break the loop // and begin walking the expose chain. s . capability = offer . clone ( ) . into ( ) ; s . moniker = s . moniker . child ( ChildMoniker :: new ( child_name . to_string ( ) ) ) ; break ' offerloop ; } } } else { return Err ( ModelError :: capability_discovery_error ( format_err ! ( " " s capability s moniker ) ) ) ; } } // Walk expose chain loop { let current_realm = await ! ( model look_up_realm ( s moniker ) ) ? ; let realm_state = await ! ( current_realm instance state lock ( ) ) ; // This unwrap is safe because look_up_realm populates this field let decl = realm_state . decl . as_ref ( ) . expect ( " " ) ; if let Some ( expose ) = decl . find_expose_source ( & s . capability ) { let source = match expose { ExposeDecl :: Service ( s ) => & s . source , ExposeDecl :: Directory ( d ) => & d . source , } ; match source { ExposeSource :: Myself => { // The offered capability comes from the current component, return our // current location in the tree. return Ok ( CapabilitySource :: Component ( expose . clone ( ) . into ( ) , current_realm . clone ( ) , ) ) ; } ExposeSource :: Child ( child_name ) => { // The offered capability comes from a child, so follow the child. s . capability = expose . clone ( ) . into ( ) ; s . moniker = s . moniker . child ( ChildMoniker :: new ( child_name . to_string ( ) ) ) ; continue ; } } } else { // We didn't find any matching exposes! Oh no! return Err ( ModelError :: capability_discovery_error ( format_err ! ( " " s capability s moniker ) ) ) ; } } }
find_capability_source will walk the component tree to find the originating source of a
capability, starting on the given abs_moniker.
find_capability_source will walk the component tree to find the originating source of a capability starting on the given abs_moniker .
model
&'a Model
used_capability
&'a Capability
abs_moniker
AbsoluteMoniker