// Copyright 2019 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.

pub mod error;
pub use error::RoutingError;

use {
    crate::{
        capability::{
            CapabilityProvider, CapabilitySource, ComponentCapability, EnvironmentCapability,
            InternalCapability,
        },
        channel,
        model::{
            error::ModelError,
            events::{filter::EventFilter, mode_set::EventModeSet},
            hooks::{Event, EventPayload},
            logging::{FmtArgsLogger, LOGGER as MODEL_LOGGER},
            realm::{BindReason, ComponentManagerRealm, ExtendedRealm, Realm, WeakRealm},
            rights::{Rights, READ_RIGHTS, WRITE_RIGHTS},
            storage,
            walk_state::WalkState,
        },
        path::PathBufExt,
    },
    async_trait::async_trait,
    cm_rust::{
        self, CapabilityDecl, CapabilityName, CapabilityPath, ComponentDecl, ExposeDecl,
        ExposeDirectoryDecl, ExposeSource, ExposeTarget, OfferDecl, OfferDirectoryDecl,
        OfferDirectorySource, OfferEventDecl, OfferEventSource, OfferResolverSource,
        OfferRunnerSource, OfferServiceSource, OfferStorageSource, StorageDecl,
        StorageDirectorySource, UseDecl, UseDirectoryDecl, UseEventDecl, UseProtocolDecl,
        UseSource, UseStorageDecl,
    },
    fidl::{endpoints::ServerEnd, epitaph::ChannelEpitaphExt},
    fidl_fuchsia_io as fio, fuchsia_zircon as zx,
    futures::lock::Mutex,
    log::*,
    moniker::{AbsoluteMoniker, ChildMoniker, ExtendedMoniker, PartialMoniker, RelativeMoniker},
    std::{path::PathBuf, sync::Arc},
};

const SERVICE_OPEN_FLAGS: u32 =
    fio::OPEN_FLAG_DESCRIBE | fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE;

/// Describes the source of a capability, for any type of capability.
#[derive(Debug)]
enum OfferSource<'a> {
    // TODO(fxbug.dev/4776): Enable this once unified services are implemented.
    #[allow(dead_code)]
    Service(&'a OfferServiceSource),
    Protocol(&'a OfferServiceSource),
    Directory(&'a OfferDirectorySource),
    Storage(&'a OfferStorageSource),
    Runner(&'a OfferRunnerSource),
    Event(&'a OfferEventSource),
    Resolver(&'a OfferResolverSource),
}

/// Describes the source of a capability, for any type of capability.
#[derive(Debug)]
enum CapabilityExposeSource<'a> {
    Protocol(&'a ExposeSource),
    Directory(&'a ExposeSource),
    Runner(&'a ExposeSource),
    Resolver(&'a ExposeSource),
}

/// Finds the source of the `capability` used by `absolute_moniker`, and pass along the
/// `server_chan` to the hosting component's out directory (or componentmgr's namespace, if
/// applicable) using an open request with `open_mode`.
pub(super) async fn route_use_capability<'a>(
    flags: u32,
    open_mode: u32,
    relative_path: String,
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
    server_chan: &mut zx::Channel,
) -> Result<(), ModelError> {
    match use_decl {
        UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Directory(_) | UseDecl::Runner(_) => {
            let (source, cap_state) = find_used_capability_source(use_decl, target_realm).await?;
            let relative_path = cap_state.make_relative_path(relative_path);
            open_capability_at_source(
                flags,
                open_mode,
                relative_path,
                source,
                target_realm,
                server_chan,
            )
            .await
        }
        UseDecl::Storage(storage_decl) => {
            // TODO(fxbug.dev/50716): This BindReason is wrong. We need to refactor the Storage
            // capability to plumb through the correct BindReason.
            route_and_open_storage_capability(
                storage_decl,
                open_mode,
                target_realm,
                server_chan,
                &BindReason::Eager,
            )
            .await
        }
        UseDecl::Event(_) | UseDecl::EventStream(_) => {
            // Events are logged separately through route_use_event_capability.
            Ok(())
        }
    }
}

pub(super) async fn route_use_event_capability<'a>(
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<CapabilitySource, ModelError> {
    let (source, _cap_state) = find_used_capability_source(use_decl, target_realm).await?;
    target_realm
        .try_get_context()?
        .policy()
        .can_route_capability(&source, &target_realm.abs_moniker)?;
    Ok(source)
}

/// Finds the source of a capability that is registered with an environment, and
/// opens the capability with the given server-side channel.
/// TODO(61304): Make runner capability routing use this method.
pub(super) async fn route_capability_from_environment<'a>(
    flags: u32,
    open_mode: u32,
    relative_path: String,
    capability: EnvironmentCapability,
    target_realm: &'a Arc<Realm>,
    server_chan: &mut zx::Channel,
) -> Result<(), ModelError> {
    let source = capability.registration_source().clone();
    let capability = ComponentCapability::Environment(capability);
    let cap_state = CapabilityState::Other;
    let (cap_source, cap_state) =
        find_environment_component_capability_source(&target_realm, capability, cap_state, &source)
            .await?;

    let relative_path = cap_state.make_relative_path(relative_path);
    open_capability_at_source(
        flags,
        open_mode,
        relative_path,
        cap_source,
        target_realm,
        server_chan,
    )
    .await
}

/// Finds the source of the expose capability used at `source_path` by `target_realm`, and pass
/// along the `server_chan` to the hosting component's out directory (or componentmgr's namespace,
/// if applicable)
pub(super) async fn route_expose_capability<'a>(
    flags: u32,
    open_mode: u32,
    relative_path: String,
    expose_decl: &'a ExposeDecl,
    target_realm: &'a Arc<Realm>,
    server_chan: &mut zx::Channel,
) -> Result<(), ModelError> {
    let capability = ComponentCapability::UsedExpose(expose_decl.clone());
    let cap_state = CapabilityState::new(&capability);
    let mut pos = WalkPosition {
        capability,
        cap_state,
        last_child_moniker: None,
        realm: ExtendedRealm::Component(target_realm.clone()),
    };
    let source = walk_expose_chain(&mut pos).await?;
    let relative_path = pos.cap_state.make_relative_path(relative_path);
    open_capability_at_source(flags, open_mode, relative_path, source, target_realm, server_chan)
        .await
}

/// The default provider for a ComponentCapability.
/// This provider will bind to the source moniker's realm and then open the service
/// from the realm's outgoing directory.
struct DefaultComponentCapabilityProvider {
    target_realm: WeakRealm,
    source_realm: WeakRealm,
    name: CapabilityName,
    path: CapabilityPath,
}

#[async_trait]
impl CapabilityProvider for DefaultComponentCapabilityProvider {
    async fn open(
        self: Box<Self>,
        flags: u32,
        open_mode: u32,
        relative_path: PathBuf,
        server_end: &mut zx::Channel,
    ) -> Result<(), ModelError> {
        let capability = Arc::new(Mutex::new(Some(channel::take_channel(server_end))));
        // Start the source component, if necessary
        let path = self.path.to_path_buf().attach(relative_path);
        let source_realm = self
            .source_realm
            .upgrade()?
            .bind(&BindReason::AccessCapability {
                target: ExtendedMoniker::ComponentInstance(self.target_realm.moniker.clone()),
                path: self.path.clone(),
            })
            .await?;

        let event = Event::new(
            &self.target_realm.upgrade()?,
            Ok(EventPayload::CapabilityRequested {
                source_moniker: source_realm.abs_moniker.clone(),
                name: self.name.to_string(),
                capability: capability.clone(),
            }),
        );
        source_realm.hooks.dispatch(&event).await?;

        // If the capability transported through the event above wasn't transferred
        // out, then we can open the capability through the realm's outgoing directory.
        // If some hook consumes the capability, then we don't bother looking in the outgoing
        // directory.
        let capability = capability.lock().await.take();
        if let Some(mut server_end_for_event) = capability {
            if let Err(e) =
                source_realm.open_outgoing(flags, open_mode, path, &mut server_end_for_event).await
            {
                // Pass back the channel to propagate the epitaph.
                *server_end = channel::take_channel(&mut server_end_for_event);
                return Err(e);
            }
        }
        Ok(())
    }
}

/// This method gets an optional default capability provider based on the
/// capability source.
fn get_default_provider(
    target_realm: WeakRealm,
    source: &CapabilitySource,
) -> Option<Box<dyn CapabilityProvider>> {
    match source {
        CapabilitySource::Component { capability, realm } => {
            // Route normally for a component capability with a source path
            match capability.source_path() {
                Some(path) => Some(Box::new(DefaultComponentCapabilityProvider {
                    target_realm,
                    source_realm: realm.clone(),
                    name: capability
                        .source_name()
                        .expect("capability with source path should have a name")
                        .clone(),
                    path: path.clone(),
                })),
                _ => None,
            }
        }
        CapabilitySource::Framework { .. }
        | CapabilitySource::Capability { .. }
        | CapabilitySource::Builtin { .. }
        | CapabilitySource::Namespace { .. } => {
            // There is no default provider for a framework or builtin capability
            None
        }
    }
}

/// Open the capability at the given source, binding to its component instance if necessary.
pub async fn open_capability_at_source(
    flags: u32,
    open_mode: u32,
    relative_path: PathBuf,
    source: CapabilitySource,
    target_realm: &Arc<Realm>,
    server_chan: &mut zx::Channel,
) -> Result<(), ModelError> {
    target_realm
        .try_get_context()?
        .policy()
        .can_route_capability(&source, &target_realm.abs_moniker)?;
    let capability_provider =
        Arc::new(Mutex::new(get_default_provider(target_realm.as_weak(), &source)));

    let event = Event::new(
        &target_realm,
        Ok(EventPayload::CapabilityRouted {
            source: source.clone(),
            capability_provider: capability_provider.clone(),
        }),
    );
    // Get a capability provider from the tree
    target_realm.hooks.dispatch(&event).await?;

    // This hack changes the flags for a scoped framework service
    let mut flags = flags;
    if let CapabilitySource::Framework { .. } = source {
        flags = SERVICE_OPEN_FLAGS;
    }

    let capability_provider = capability_provider.lock().await.take();

    // If a hook in the component tree gave a capability provider, then use it.
    if let Some(capability_provider) = capability_provider {
        capability_provider.open(flags, open_mode, relative_path, server_chan).await?;
        Ok(())
    } else {
        // TODO(fsamuel): This is a temporary hack. If a global path-based framework capability
        // is not provided by a hook in the component tree, then attempt to connect to the service
        // in component manager's namespace. We could have modeled this as a default provider,
        // but several hooks (such as WorkScheduler) require that a provider is not set.
        let namespace_path = match &source {
            CapabilitySource::Component { .. } => {
                unreachable!(
                    "Capability source is a component, which should have been caught by \
                    default_capability_provider: {:?}",
                    source
                );
            }
            CapabilitySource::Framework { capability, scope_moniker: m } => {
                return Err(RoutingError::capability_from_framework_not_found(
                    &m,
                    capability.source_name().to_string(),
                )
                .into());
            }
            CapabilitySource::Capability { source_capability, realm } => {
                return Err(RoutingError::capability_from_capability_not_found(
                    &realm.moniker,
                    source_capability.to_string(),
                )
                .into());
            }
            CapabilitySource::Builtin { capability } => {
                return Err(ModelError::from(
                    RoutingError::capability_from_component_manager_not_found(
                        capability.source_name().to_string(),
                    ),
                ));
            }
            CapabilitySource::Namespace { capability } => match capability.source_path() {
                Some(p) => p.clone(),
                _ => {
                    return Err(ModelError::from(
                        RoutingError::capability_from_component_manager_not_found(
                            capability.source_id(),
                        ),
                    ));
                }
            },
        };
        let namespace_path = namespace_path.to_path_buf().attach(relative_path);
        let namespace_path = namespace_path
            .to_str()
            .ok_or_else(|| ModelError::path_is_not_utf8(namespace_path.clone()))?;
        let server_chan = channel::take_channel(server_chan);
        io_util::connect_in_namespace(namespace_path, server_chan, flags).map_err(|e| {
            RoutingError::open_component_manager_namespace_failed(namespace_path, e).into()
        })
    }
}

/// Routes a `UseDecl::Storage` to the component instance providing the backing directory and
/// opens its isolated storage with `server_chan`.
pub async fn route_and_open_storage_capability<'a>(
    use_decl: &'a UseStorageDecl,
    open_mode: u32,
    target_realm: &'a Arc<Realm>,
    server_chan: &mut zx::Channel,
    bind_reason: &BindReason,
) -> Result<(), ModelError> {
    let (storage_source_info, relative_moniker) =
        route_storage_capability(use_decl, target_realm).await?;
    let dir_source_realm = storage_source_info.storage_provider.clone();
    let relative_moniker_2 = relative_moniker.clone();
    let storage_dir_proxy = storage::open_isolated_storage(
        storage_source_info,
        relative_moniker,
        open_mode,
        bind_reason,
    )
    .await
    .map_err(|e| ModelError::from(e))?;

    // clone the final connection to connect the channel we're routing to its destination
    let server_chan = channel::take_channel(server_chan);
    storage_dir_proxy.clone(fio::CLONE_FLAG_SAME_RIGHTS, ServerEnd::new(server_chan)).map_err(
        |e| {
            let moniker = match &dir_source_realm {
                Some(r) => ExtendedMoniker::ComponentInstance(r.abs_moniker.clone()),
                None => ExtendedMoniker::ComponentManager,
            };
            ModelError::from(RoutingError::open_storage_failed(
                &moniker,
                &relative_moniker_2,
                "",
                e,
            ))
        },
    )?;
    Ok(())
}

/// Routes a `UseDecl::Storage` to the component instance providing the backing directory and
/// deletes its isolated storage.
pub(super) async fn route_and_delete_storage<'a>(
    use_decl: &'a UseStorageDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<(), ModelError> {
    let (storage_source_info, relative_moniker) =
        route_storage_capability(use_decl, target_realm).await?;
    storage::delete_isolated_storage(storage_source_info, relative_moniker)
        .await
        .map_err(|e| ModelError::from(e))?;
    Ok(())
}

/// Follows the capability routing for the given use declaration from the target realm to the
/// storage capability declaration, and then on to the backing directory provider, and returns a
/// `StorageCapabilitySource` containing information discovered durng the routing.
async fn route_storage_capability<'a>(
    use_decl: &'a UseStorageDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<(storage::StorageCapabilitySource, RelativeMoniker), ModelError> {
    // Walk the offer chain to find the storage decl
    let parent_realm = match target_realm.try_get_parent()? {
        ExtendedRealm::Component(p) => p,
        ExtendedRealm::AboveRoot(_) => {
            return Err(ModelError::from(RoutingError::storage_source_is_not_component(
                "component manager's namespace",
            )));
        }
    };

    let capability = ComponentCapability::Use(UseDecl::Storage(use_decl.clone()));
    let cap_state = CapabilityState::new(&capability);
    let mut pos = WalkPosition {
        capability,
        cap_state,
        last_child_moniker: target_realm.abs_moniker.path().last().map(|c| c.clone()),
        realm: ExtendedRealm::Component(parent_realm),
    };

    let source = walk_offer_chain(&mut pos).await?;

    let (storage_decl, source_realm) = match source {
        Some(capability_source) => {
            target_realm
                .try_get_context()?
                .policy()
                .can_route_capability(&capability_source, &target_realm.abs_moniker)?;
            match capability_source {
                CapabilitySource::Component {
                    capability: ComponentCapability::Storage(decl),
                    realm,
                } => (decl, realm.upgrade()?),
                _ => {
                    unreachable!("Storage capability must come from a storage declaration.");
                }
            }
        }
        _ => {
            unreachable!("Storage capability must come from a storage declaration.");
        }
    };

    let relative_moniker =
        RelativeMoniker::from_absolute(&source_realm.abs_moniker, &target_realm.abs_moniker);

    Ok((
        route_storage_backing_directory(storage_decl, source_realm, pos.cap_state).await?,
        relative_moniker,
    ))
}

pub async fn route_storage_backing_directory(
    storage_decl: StorageDecl,
    source_realm: Arc<Realm>,
    mut cap_state: CapabilityState,
) -> Result<storage::StorageCapabilitySource, ModelError> {
    // Find the path and source of the directory consumed by the storage capability.
    let storage_subdir = storage_decl.subdir.clone();
    let (dir_source_path, mut dir_subdir, dir_source_realm) = match storage_decl.source {
        StorageDirectorySource::Self_ => {
            let realm_state = source_realm.lock_resolved_state().await?;
            let decl = realm_state.decl();
            let capability = ComponentCapability::Storage(storage_decl.clone());
            let capability =
                cap_state.finalize_directory_from_component(&capability, decl, None, None)?;
            let source_path =
                capability.source_path().expect("directory has no source path?").clone();
            drop(realm_state); // We can't be holding a reference into source_realm when we move it
            (source_path, None, Some(source_realm))
        }
        StorageDirectorySource::Parent => {
            let capability = ComponentCapability::Storage(storage_decl);
            let (source, cap_state) = find_capability_source(capability, &source_realm).await?;
            match source {
                CapabilitySource::Component { capability, realm } => {
                    let source_path =
                        capability.source_path().expect("directory has no source path?").clone();
                    let dir_subdir = cap_state.get_subdir().map(Clone::clone);

                    (source_path, dir_subdir, Some(realm.upgrade()?))
                }
                CapabilitySource::Framework { .. } => {
                    return Err(RoutingError::storage_directory_source_invalid(
                        "framework",
                        &source_realm.abs_moniker,
                    )
                    .into());
                }
                CapabilitySource::Builtin { .. } => {
                    return Err(RoutingError::storage_directory_source_invalid(
                        "component manager builtin",
                        &source_realm.abs_moniker,
                    )
                    .into());
                }
                CapabilitySource::Capability { .. } => {
                    return Err(RoutingError::storage_directory_source_invalid(
                        "capability",
                        &source_realm.abs_moniker,
                    )
                    .into());
                }
                CapabilitySource::Namespace { capability } => {
                    let source_path =
                        capability.source_path().expect("directory has no source path?").clone();
                    let dir_subdir = cap_state.get_subdir().map(Clone::clone);

                    (source_path, dir_subdir, None)
                }
            }
        }
        StorageDirectorySource::Child(ref name) => {
            let mut pos = {
                let partial = PartialMoniker::new(name.to_string(), None);
                let realm_state = source_realm.lock_resolved_state().await?;
                let child_realm = realm_state.get_live_child_realm(&partial).ok_or_else(|| {
                    ModelError::from(RoutingError::storage_directory_source_child_not_found(
                        &source_realm.abs_moniker,
                        &partial,
                    ))
                })?;
                let capability = ComponentCapability::Storage(storage_decl);
                WalkPosition {
                    capability,
                    cap_state,
                    last_child_moniker: None,
                    realm: ExtendedRealm::Component(child_realm),
                }
            };
            let source = walk_expose_chain(&mut pos).await?;
            match source {
                CapabilitySource::Component { capability, realm } => {
                    let source_path =
                        capability.source_path().expect("directory has no source path?").clone();
                    let dir_subdir = pos.cap_state.get_subdir().map(Clone::clone);
                    (source_path, dir_subdir, Some(realm.upgrade()?))
                }
                CapabilitySource::Framework { .. } => {
                    return Err(RoutingError::storage_directory_source_invalid(
                        "framework",
                        &source_realm.abs_moniker,
                    )
                    .into());
                }
                CapabilitySource::Capability { .. } => {
                    return Err(RoutingError::storage_directory_source_invalid(
                        "capability",
                        &source_realm.abs_moniker,
                    )
                    .into());
                }
                CapabilitySource::Builtin { .. } | CapabilitySource::Namespace { .. } => {
                    unreachable!(
                        "Invalid capability source for storage with backing dir from child"
                    );
                }
            }
        }
    };
    if dir_subdir == Some(PathBuf::from("")) {
        dir_subdir = None;
    }
    Ok(storage::StorageCapabilitySource {
        storage_provider: dir_source_realm,
        backing_directory_path: dir_source_path,
        backing_directory_subdir: dir_subdir,
        storage_subdir,
    })
}

/// Check if a used capability is from the framework, and if so return a framework
/// `CapabilitySource`.
async fn find_scoped_framework_capability_source<'a>(
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<Option<CapabilitySource>, ModelError> {
    if let Ok(capability) = InternalCapability::framework_from_use_decl(use_decl) {
        return Ok(Some(CapabilitySource::Framework {
            capability,
            scope_moniker: target_realm.abs_moniker.clone(),
        }));
    }
    return Ok(None);
}

async fn find_use_from_capability_source<'a>(
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<Option<CapabilitySource>, ModelError> {
    if let UseDecl::Protocol(UseProtocolDecl { source: UseSource::Capability(_), .. }) = use_decl {
        return Ok(Some(CapabilitySource::Capability {
            source_capability: ComponentCapability::Use(use_decl.clone()),
            realm: target_realm.as_weak(),
        }));
    }
    Ok(None)
}

/// Holds state about the current position when walking the tree.
#[derive(Debug)]
struct WalkPosition {
    /// The capability declaration as it's represented in the current component.
    capability: ComponentCapability,
    /// Holds any capability-specific state.
    cap_state: CapabilityState,
    /// The moniker of the child we came from.
    last_child_moniker: Option<ChildMoniker>,
    /// The realm of the component we are currently looking at. `None` for component manager's
    /// realm.
    realm: ExtendedRealm,
}

impl WalkPosition {
    fn realm(&self) -> &Arc<Realm> {
        match &self.realm {
            ExtendedRealm::Component(r) => &r,
            ExtendedRealm::AboveRoot(_) => {
                panic!("no Realm in WalkPosition");
            }
        }
    }

    fn moniker(&self) -> &AbsoluteMoniker {
        match &self.realm {
            ExtendedRealm::Component(r) => &r.abs_moniker,
            ExtendedRealm::AboveRoot(_) => {
                panic!("no moniker in WalkPosition");
            }
        }
    }

    fn abs_last_child_moniker(&self) -> AbsoluteMoniker {
        self.moniker().child(self.last_child_moniker.as_ref().expect("no child moniker").clone())
    }

    fn component_manager_realm(&self) -> Option<&Arc<ComponentManagerRealm>> {
        match &self.realm {
            ExtendedRealm::Component(_) => None,
            ExtendedRealm::AboveRoot(r) => Some(r),
        }
    }
}

/// Holds state related to a capability when walking the tree
#[derive(Debug, Clone)]
pub enum CapabilityState {
    Directory {
        /// Holds the state of the rights. This is used to enforce directory rights.
        rights_state: WalkState<Rights>,
        /// Holds the subdirectory path to open.
        subdir: PathBuf,
    },
    Event {
        filter_state: WalkState<EventFilter>,
        modes_state: WalkState<EventModeSet>,
    },
    Other,
}

impl CapabilityState {
    pub fn new(cap: &ComponentCapability) -> Self {
        match cap {
            ComponentCapability::Use(UseDecl::Directory(UseDirectoryDecl {
                subdir,
                rights,
                ..
            })) => CapabilityState::Directory {
                rights_state: WalkState::at(Rights::from(*rights)),
                subdir: subdir.as_ref().map_or(PathBuf::new(), |s| PathBuf::from(s)),
            },
            ComponentCapability::Expose(ExposeDecl::Directory(ExposeDirectoryDecl {
                subdir,
                rights,
                ..
            }))
            | ComponentCapability::Offer(OfferDecl::Directory(OfferDirectoryDecl {
                subdir,
                rights,
                ..
            })) => {
                let rights_state = match rights {
                    Some(rights) => WalkState::at(Rights::from(*rights)),
                    None => WalkState::new(),
                };
                CapabilityState::Directory {
                    rights_state,
                    subdir: subdir.as_ref().map_or(PathBuf::new(), |s| PathBuf::from(s)),
                }
            }
            ComponentCapability::Use(UseDecl::Event(UseEventDecl { mode, filter, .. }))
            | ComponentCapability::Offer(OfferDecl::Event(OfferEventDecl {
                mode, filter, ..
            })) => CapabilityState::Event {
                filter_state: WalkState::at(EventFilter::new(filter.clone())),
                modes_state: WalkState::at(EventModeSet::new(mode.clone())),
            },
            ComponentCapability::UsedExpose(ExposeDecl::Directory(ExposeDirectoryDecl {
                ..
            })) => CapabilityState::Directory {
                rights_state: WalkState::new(),
                subdir: PathBuf::new(),
            },
            // Directories backing storage must provide read and write rights.
            ComponentCapability::Use(UseDecl::Storage { .. }) => CapabilityState::Directory {
                rights_state: WalkState::at(Rights::from(*READ_RIGHTS | *WRITE_RIGHTS)),
                subdir: PathBuf::new(),
            },
            ComponentCapability::Storage(_) => CapabilityState::Directory {
                rights_state: WalkState::at(Rights::from(*READ_RIGHTS | *WRITE_RIGHTS)),
                subdir: PathBuf::new(),
            },
            _ => CapabilityState::Other,
        }
    }

    /// Finalize the directory state according to `capability`. Returns a `ComponentCapability` for
    /// the end of routing, or an error if rights did not match.
    ///
    /// REQUIRES: `capability` is a directory expose or offer from `self`.
    fn finalize_directory_from_component(
        &mut self,
        capability: &ComponentCapability,
        decl: &ComponentDecl,
        dir_rights: Option<Rights>,
        subdir_decl: Option<PathBuf>,
    ) -> Result<ComponentCapability, ModelError> {
        if let CapabilityState::Directory { rights_state, subdir } = self {
            *rights_state = rights_state.advance(dir_rights)?;
            CapabilityState::update_subdir(subdir, subdir_decl);
        }

        let directory_decl = capability
            .find_directory_source(decl)
            .expect("directory offer references nonexistent section")
            .clone();
        let dir_rights = Some(Rights::from(directory_decl.rights));
        let capability = ComponentCapability::Directory(directory_decl);
        if let CapabilityState::Directory { rights_state, subdir: _subdir } = self {
            *rights_state = rights_state.finalize(dir_rights)?;
        }
        Ok(capability)
    }

    /// Finalize the directory state for a directory that component from the framework.
    fn finalize_directory_from_framework(
        &mut self,
        subdir_decl: Option<PathBuf>,
    ) -> Result<(), ModelError> {
        if let CapabilityState::Directory { rights_state, subdir } = self {
            *rights_state = rights_state.finalize(Some(Rights::from(*READ_RIGHTS)))?;
            CapabilityState::update_subdir(subdir, subdir_decl);
        }
        Ok(())
    }

    fn make_relative_path(&self, in_relative_path: String) -> PathBuf {
        match self {
            Self::Directory { subdir, .. } => subdir.clone().attach(in_relative_path),
            _ => PathBuf::from(in_relative_path),
        }
    }

    fn update_subdir(subdir: &mut PathBuf, subdir_decl: Option<PathBuf>) {
        let subdir_decl = subdir_decl.unwrap_or(PathBuf::new());
        let old_subdir = subdir.clone();
        *subdir = subdir_decl.attach(old_subdir);
    }

    /// Returns the subdir for the given capability, or None if the subdir is empty. Panics if this
    /// is not a Directory.
    fn get_subdir(&self) -> Option<&PathBuf> {
        match &self {
            CapabilityState::Directory { subdir, .. } if subdir != &PathBuf::new() => Some(subdir),
            CapabilityState::Directory { .. } => None,
            _ => panic!(
                "get_subdir called on a ComponentCapability that is not a Directory: {:?}",
                self
            ),
        }
    }
}

async fn find_used_capability_source<'a>(
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<(CapabilitySource, CapabilityState), ModelError> {
    let capability = ComponentCapability::Use(use_decl.clone());
    if let Some(framework_capability) =
        find_scoped_framework_capability_source(use_decl, target_realm).await?
    {
        let mut cap_state = CapabilityState::new(&capability);
        match use_decl {
            UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Event(_) => {}
            UseDecl::Directory(_) => {
                cap_state.finalize_directory_from_framework(None)?;
            }
            _ => {
                unreachable!("Invalid framework capability: {:?}", use_decl);
            }
        }
        return Ok((framework_capability, cap_state));
    }
    if let Some((cap_source, cap_state)) =
        find_environment_capability_source(use_decl, target_realm).await?
    {
        return Ok((cap_source, cap_state));
    }
    if let Some(cap_source) = find_use_from_capability_source(use_decl, target_realm).await? {
        let cap_state = CapabilityState::new(&capability);
        return Ok((cap_source, cap_state));
    }
    find_capability_source(capability, target_realm).await
}

/// Attempts to perform capability routing starting from a `use` of a capability that could be
/// provided by an environment.  Returns `None` if `use_decl` is not the type of capability
/// provided by an environment.
async fn find_environment_capability_source<'a>(
    use_decl: &'a UseDecl,
    target_realm: &'a Arc<Realm>,
) -> Result<Option<(CapabilitySource, CapabilityState)>, ModelError> {
    let cap_state = CapabilityState::new(&ComponentCapability::Use(use_decl.clone()));
    match use_decl {
        UseDecl::Runner(cm_rust::UseRunnerDecl { source_name }) => {
            match target_realm.environment.get_registered_runner(source_name)? {
                Some((Some(env_realm), reg)) => {
                    let capability =
                        ComponentCapability::Environment(EnvironmentCapability::Runner {
                            source_name: reg.source_name,
                            source: reg.source.clone(),
                        });
                    Ok(Some(
                        find_environment_component_capability_source(
                            &env_realm,
                            capability,
                            cap_state,
                            &reg.source,
                        )
                        .await?,
                    ))
                }
                Some((None, reg)) => {
                    // Root environment.
                    let cap_source = CapabilitySource::Builtin {
                        capability: InternalCapability::Runner(reg.source_name.clone()),
                    };
                    Ok(Some((cap_source, cap_state)))
                }
                None => Err(ModelError::from(RoutingError::use_from_environment_not_found(
                    &target_realm.abs_moniker,
                    "runner",
                    source_name.to_string(),
                ))),
            }
        }
        _ => Ok(None),
    }
}

async fn find_environment_component_capability_source<'a>(
    env_realm: &Arc<Realm>,
    capability: ComponentCapability,
    cap_state: CapabilityState,
    source: &cm_rust::RegistrationSource,
) -> Result<(CapabilitySource, CapabilityState), ModelError> {
    let env_realm_state = env_realm.lock_resolved_state().await?;
    let decl = env_realm_state.decl();
    match &source {
        cm_rust::RegistrationSource::Self_ => {
            let cap_source = find_capability_source_from_self(&env_realm, &capability, decl);
            Ok((cap_source, cap_state))
        }
        cm_rust::RegistrationSource::Parent => {
            let starting_realm = env_realm.try_get_parent()?;
            let mut pos = WalkPosition {
                capability,
                cap_state,
                last_child_moniker: env_realm.abs_moniker.leaf().cloned(),
                realm: starting_realm,
            };
            if let Some(cap_source) = walk_offer_chain(&mut pos).await? {
                return Ok((cap_source, pos.cap_state));
            }
            let cap_source = walk_expose_chain(&mut pos).await?;
            Ok((cap_source, pos.cap_state))
        }
        cm_rust::RegistrationSource::Child(child_name) => {
            let partial = PartialMoniker::new(child_name.into(), None);
            let realm = ExtendedRealm::Component(
                env_realm_state.get_live_child_realm(&partial).ok_or_else(|| {
                    ModelError::from(RoutingError::environment_from_child_expose_not_found(
                        &partial,
                        &env_realm.abs_moniker,
                        capability.type_name().to_string(),
                        capability.source_id(),
                    ))
                })?,
            );
            let mut pos = WalkPosition { capability, cap_state, last_child_moniker: None, realm };
            let cap_source = walk_expose_chain(&mut pos).await?;
            Ok((cap_source, pos.cap_state))
        }
    }
}

fn find_capability_source_from_self(
    env_realm: &Arc<Realm>,
    capability: &ComponentCapability,
    decl: &cm_rust::ComponentDecl,
) -> CapabilitySource {
    match capability {
        ComponentCapability::Environment(env_cap) => match env_cap {
            EnvironmentCapability::Runner { .. } => {
                let runner_decl =
                    capability.find_runner_source(decl).expect("missing runner").clone();
                CapabilitySource::Component {
                    capability: ComponentCapability::Runner(runner_decl),
                    realm: env_realm.as_weak(),
                }
            }
            EnvironmentCapability::Resolver { .. } => {
                let resolver_decl =
                    capability.find_resolver_source(decl).expect("missing resolver").clone();
                CapabilitySource::Component {
                    capability: ComponentCapability::Resolver(resolver_decl),
                    realm: env_realm.as_weak(),
                }
            }
        },
        _ => {
            panic!("Capability has invalid type: {:?}", capability);
        }
    }
}

/// Walks the component tree to return the originating source of a capability, starting on the given
/// abs_moniker, as well as the final capability state.
async fn find_capability_source<'a>(
    capability: ComponentCapability,
    target_realm: &'a Arc<Realm>,
) -> Result<(CapabilitySource, CapabilityState), ModelError> {
    let starting_realm = target_realm.try_get_parent()?;
    let cap_state = CapabilityState::new(&capability);
    let mut pos = WalkPosition {
        capability,
        cap_state,
        last_child_moniker: target_realm.abs_moniker.leaf().cloned(),
        realm: starting_realm,
    };
    if let Some(source) = walk_offer_chain(&mut pos).await? {
        return Ok((source, pos.cap_state));
    }
    let source = walk_expose_chain(&mut pos).await?;
    Ok((source, pos.cap_state))
}

/// Follows `offer` declarations up the component tree, starting at `pos`. The algorithm looks
/// for a matching `offer` in the parent, as long as the `offer` is from `realm`.
///
/// Returns the source of the capability if found, or `None` if `expose` declarations must be
/// walked.
async fn walk_offer_chain<'a>(
    pos: &'a mut WalkPosition,
) -> Result<Option<CapabilitySource>, ModelError> {
    'offerloop: loop {
        if let Some(cm_realm) = pos.component_manager_realm() {
            // This is a built-in or namespace capability because the routing path was traced to
            // the component manager's realm.
            match pos.capability.find_namespace_source(&cm_realm.namespace_capabilities) {
                Some(CapabilityDecl::Protocol(p)) => {
                    let capability = ComponentCapability::Protocol(p.clone());
                    return Ok(Some(CapabilitySource::Namespace { capability }));
                }
                Some(CapabilityDecl::Directory(d)) => {
                    let dir_rights = Some(Rights::from(d.rights));
                    let capability = ComponentCapability::Directory(d.clone());
                    if let CapabilityState::Directory { rights_state, subdir: _subdir } =
                        &mut pos.cap_state
                    {
                        *rights_state = rights_state.finalize(dir_rights)?;
                    }
                    return Ok(Some(CapabilitySource::Namespace { capability }));
                }
                Some(_) => {
                    return Err(ModelError::unsupported(format!(
                        "Namespace capability not supported: {:?}",
                        pos.capability,
                    )));
                }
                None => (),
            }

            // Not a namespace capability, fallback to builtin.
            let capability = match &pos.capability {
                ComponentCapability::Use(use_decl) => {
                    InternalCapability::builtin_from_use_decl(use_decl).map_err(|_| {
                        ModelError::from(RoutingError::use_from_component_manager_not_found(
                            pos.capability.source_id(),
                        ))
                    })
                }
                ComponentCapability::Offer(offer_decl) => {
                    InternalCapability::builtin_from_offer_decl(offer_decl).map_err(|_| {
                        ModelError::from(RoutingError::offer_from_component_manager_not_found(
                            pos.capability.source_id(),
                        ))
                    })
                }
                ComponentCapability::Storage(storage_decl) => {
                    InternalCapability::builtin_from_storage_decl(storage_decl).map_err(|_| {
                        ModelError::from(RoutingError::storage_from_component_manager_not_found(
                            pos.capability.source_id(),
                        ))
                    })
                }
                _ => Err(ModelError::unsupported(format!(
                    "Built-in capability not supported: {:?}",
                    pos.capability,
                ))),
            }?;
            return Ok(Some(CapabilitySource::Builtin { capability }));
        }

        let cur_realm = pos.realm().clone();
        let cur_realm_state = cur_realm.lock_resolved_state().await?;
        let decl = cur_realm_state.decl();
        let last_child_moniker = pos.last_child_moniker.as_ref().expect("no child moniker");
        let offer =
            pos.capability.find_offer_source(decl, last_child_moniker).ok_or_else(|| match pos
                .capability
            {
                ComponentCapability::Use(_) => {
                    ModelError::from(RoutingError::use_from_parent_not_found(
                        &pos.abs_last_child_moniker(),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Environment(_) => {
                    ModelError::from(RoutingError::environment_from_parent_not_found(
                        &pos.abs_last_child_moniker(),
                        pos.capability.type_name().to_string(),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Offer(_) => {
                    ModelError::from(RoutingError::offer_from_parent_not_found(
                        &pos.abs_last_child_moniker(),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Storage(_) => {
                    ModelError::from(RoutingError::storage_from_parent_not_found(
                        &pos.abs_last_child_moniker(),
                        pos.capability.source_id(),
                    ))
                }
                _ => {
                    panic!("Invalid offer target: {:?}", pos.capability);
                }
            })?;
        let source = match offer {
            OfferDecl::Service(_) => return Err(ModelError::unsupported("Service capability")),
            OfferDecl::Protocol(s) => OfferSource::Protocol(&s.source),
            OfferDecl::Directory(d) => OfferSource::Directory(&d.source),
            OfferDecl::Storage(s) => OfferSource::Storage(&s.source),
            OfferDecl::Runner(r) => OfferSource::Runner(&r.source),
            OfferDecl::Resolver(r) => OfferSource::Resolver(&r.source),
            OfferDecl::Event(e) => OfferSource::Event(&e.source),
        };
        let (dir_rights, subdir_decl) = match offer {
            OfferDecl::Directory(OfferDirectoryDecl { rights, subdir, .. }) => {
                (rights.map(Rights::from), subdir.clone())
            }
            _ => (None, None),
        };
        let event_filter = Some(EventFilter::new(match offer {
            OfferDecl::Event(OfferEventDecl { filter, .. }) => filter.clone(),
            _ => None,
        }));
        let event_mode = Some(EventModeSet::new(match offer {
            OfferDecl::Event(OfferEventDecl { mode, .. }) => mode.clone(),
            _ => cm_rust::EventMode::Async,
        }));
        match source {
            OfferSource::Service(_) => {
                return Err(ModelError::unsupported("Service capability"));
            }
            OfferSource::Directory(OfferDirectorySource::Framework) => {
                // Directories coming from the framework are limited to
                // read-only rights.
                pos.cap_state.finalize_directory_from_framework(subdir_decl)?;
                let capability = InternalCapability::framework_from_offer_decl(offer)
                    .expect("not a framework offer declaration");
                return Ok(Some(CapabilitySource::Framework {
                    capability,
                    scope_moniker: pos.moniker().clone(),
                }));
            }
            OfferSource::Event(OfferEventSource::Framework) => {
                // An event offered from framework is scoped to the current realm.
                if let CapabilityState::Event { modes_state, filter_state } = &mut pos.cap_state {
                    *modes_state = modes_state.finalize(event_mode)?;
                    *filter_state = filter_state.finalize(event_filter)?;
                }
                let capability = InternalCapability::framework_from_offer_decl(offer)
                    .expect("not a framework offer declaration");
                return Ok(Some(CapabilitySource::Framework {
                    capability,
                    scope_moniker: pos.moniker().clone(),
                }));
            }
            OfferSource::Protocol(OfferServiceSource::Parent)
            | OfferSource::Storage(OfferStorageSource::Parent)
            | OfferSource::Runner(OfferRunnerSource::Parent)
            | OfferSource::Resolver(OfferResolverSource::Parent) => {
                // The offered capability comes from the parent, so follow the
                // parent
                pos.capability = ComponentCapability::Offer(offer.clone());
                pos.last_child_moniker = pos.moniker().path().last().map(|c| c.clone());
                pos.realm = cur_realm.try_get_parent()?;
                continue 'offerloop;
            }
            OfferSource::Event(OfferEventSource::Parent) => {
                // The offered capability comes from the parent, so follow the
                // parent
                if let CapabilityState::Event { modes_state, filter_state } = &mut pos.cap_state {
                    *modes_state = modes_state.advance(event_mode)?;
                    *filter_state = filter_state.advance(event_filter)?;
                }
                pos.capability = ComponentCapability::Offer(offer.clone());
                pos.last_child_moniker = pos.moniker().path().last().map(|c| c.clone());
                pos.realm = cur_realm.try_get_parent()?;
                continue 'offerloop;
            }
            OfferSource::Directory(OfferDirectorySource::Parent) => {
                if let CapabilityState::Directory { rights_state, subdir } = &mut pos.cap_state {
                    *rights_state = rights_state.advance(dir_rights)?;
                    CapabilityState::update_subdir(subdir, subdir_decl);
                }
                pos.capability = ComponentCapability::Offer(offer.clone());
                pos.last_child_moniker = pos.moniker().path().last().map(|c| c.clone());
                pos.realm = cur_realm.try_get_parent()?;
                continue 'offerloop;
            }
            OfferSource::Protocol(OfferServiceSource::Self_) => {
                match pos.capability.source_path() {
                    None => {
                        // The offered capability comes from the current component.
                        // Find the current component's Protocol declaration.
                        let cap = ComponentCapability::Offer(offer.clone());
                        return Ok(Some(CapabilitySource::Component {
                            capability: ComponentCapability::Protocol(
                                cap.find_protocol_source(decl)
                                    .expect("protocol offer references nonexistent section")
                                    .clone(),
                            ),
                            realm: cur_realm.as_weak(),
                        }));
                    }
                    Some(_) => {
                        // Legacy path: protocol is offered by path, get its info from the
                        // OfferDecl.
                        return Ok(Some(CapabilitySource::Component {
                            capability: ComponentCapability::Offer(offer.clone()),
                            realm: cur_realm.as_weak(),
                        }));
                    }
                }
            }
            OfferSource::Protocol(OfferServiceSource::Capability(_)) => {
                return Ok(Some(CapabilitySource::Capability {
                    source_capability: ComponentCapability::Offer(offer.clone()),
                    realm: cur_realm.as_weak(),
                }));
            }
            OfferSource::Directory(OfferDirectorySource::Self_) => {
                match pos.capability.source_path() {
                    None => {
                        // The offered capability comes from the current component.  Update state
                        // and return a capability corresponding to the current component's
                        // Directory declaration.
                        let capability = ComponentCapability::Offer(offer.clone());
                        let capability = pos.cap_state.finalize_directory_from_component(
                            &capability,
                            decl,
                            dir_rights,
                            subdir_decl,
                        )?;
                        return Ok(Some(CapabilitySource::Component {
                            capability,
                            realm: cur_realm.as_weak(),
                        }));
                    }
                    Some(_) => {
                        // Legacy path: directory is offered by path, get its info from the
                        // OfferDecl.
                        if let CapabilityState::Directory { rights_state, subdir } =
                            &mut pos.cap_state
                        {
                            *rights_state = rights_state.finalize(dir_rights)?;
                            CapabilityState::update_subdir(subdir, subdir_decl);
                        }
                        return Ok(Some(CapabilitySource::Component {
                            capability: ComponentCapability::Offer(offer.clone()),
                            realm: cur_realm.as_weak(),
                        }));
                    }
                }
            }
            OfferSource::Runner(OfferRunnerSource::Self_) => {
                // The offered capability comes from the current component.
                // Find the current component's Runner declaration.
                let cap = ComponentCapability::Offer(offer.clone());
                return Ok(Some(CapabilitySource::Component {
                    capability: ComponentCapability::Runner(
                        cap.find_runner_source(decl)
                            .expect("runner offer references nonexistent section")
                            .clone(),
                    ),
                    realm: cur_realm.as_weak(),
                }));
            }
            OfferSource::Resolver(OfferResolverSource::Self_) => {
                // The offered capability comes from the current component.
                // Find the current component's Resolver declaration.
                let cap = ComponentCapability::Offer(offer.clone());
                return Ok(Some(CapabilitySource::Component {
                    capability: ComponentCapability::Resolver(
                        cap.find_resolver_source(decl)
                            .expect("resolver offer references nonexistent section")
                            .clone(),
                    ),
                    realm: cur_realm.as_weak(),
                }));
            }
            OfferSource::Protocol(OfferServiceSource::Child(child_name))
            | OfferSource::Runner(OfferRunnerSource::Child(child_name))
            | OfferSource::Resolver(OfferResolverSource::Child(child_name)) => {
                // The offered capability comes from a child, break the loop
                // and begin walking the expose chain.
                pos.capability = ComponentCapability::Offer(offer.clone());
                let partial = PartialMoniker::new(child_name.to_string(), None);
                pos.realm = ExtendedRealm::Component(
                    cur_realm_state.get_live_child_realm(&partial).ok_or_else(|| {
                        ModelError::from(RoutingError::offer_from_child_expose_not_found(
                            &partial,
                            pos.moniker(),
                            pos.capability.source_id(),
                        ))
                    })?,
                );
                return Ok(None);
            }
            OfferSource::Directory(OfferDirectorySource::Child(child_name)) => {
                if let CapabilityState::Directory { rights_state, subdir } = &mut pos.cap_state {
                    *rights_state = rights_state.advance(dir_rights)?;
                    CapabilityState::update_subdir(subdir, subdir_decl);
                }
                pos.capability = ComponentCapability::Offer(offer.clone());
                let partial = PartialMoniker::new(child_name.to_string(), None);
                pos.realm = ExtendedRealm::Component(
                    cur_realm_state.get_live_child_realm(&partial).ok_or(ModelError::from(
                        RoutingError::offer_from_child_instance_not_found(
                            &partial,
                            pos.moniker(),
                            pos.capability.source_id(),
                        ),
                    ))?,
                );
                return Ok(None);
            }
            OfferSource::Storage(OfferStorageSource::Self_) => {
                let storage_name = match &offer {
                    OfferDecl::Storage(s) => &s.source_name,
                    _ => panic!(
                        "OfferSource::Storage on a non-storage OfferDecl should be impossible"
                    ),
                };
                let storage = decl
                    .find_storage_source(storage_name)
                    .expect("storage offer references nonexistent section");
                let capability = ComponentCapability::Storage(storage.clone());
                pos.cap_state = CapabilityState::new(&capability);
                return Ok(Some(CapabilitySource::Component {
                    capability,
                    realm: cur_realm.as_weak(),
                }));
            }
        }
    }
}

/// Follows `expose` declarations down the component tree, starting at `pos`. The algorithm looks
/// for a matching `expose` in the child, as long as the `expose` is not from `self`.
///
/// Returns the source of the capability.
async fn walk_expose_chain<'a>(pos: &'a mut WalkPosition) -> Result<CapabilitySource, ModelError> {
    loop {
        // TODO(xbhatnag): See if the locking needs to be over the entire loop
        // Consider -> let current_decl = { .. };
        let cur_realm = pos.realm().clone();
        let cur_realm_state = cur_realm.lock_resolved_state().await?;
        let decl = cur_realm_state.decl();
        let expose =
            pos.capability.find_expose_source(decl).ok_or_else(|| match pos.capability {
                ComponentCapability::UsedExpose(_) => ModelError::from(
                    RoutingError::used_expose_not_found(pos.moniker(), pos.capability.source_id()),
                ),
                ComponentCapability::Environment(_) => {
                    let partial =
                        pos.moniker().leaf().expect("impossible source above root").to_partial();
                    ModelError::from(RoutingError::environment_from_child_expose_not_found(
                        &partial,
                        pos.moniker().parent().as_ref().expect("impossible source above root"),
                        pos.capability.type_name().to_string(),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Expose(_) => {
                    let partial =
                        pos.moniker().leaf().expect("impossible source above root").to_partial();
                    ModelError::from(RoutingError::expose_from_child_expose_not_found(
                        &partial,
                        pos.moniker().parent().as_ref().expect("impossible source above root"),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Offer(_) => {
                    let partial =
                        pos.moniker().leaf().expect("impossible source above root").to_partial();
                    ModelError::from(RoutingError::offer_from_child_expose_not_found(
                        &partial,
                        pos.moniker().parent().as_ref().expect("impossible source above root"),
                        pos.capability.source_id(),
                    ))
                }
                ComponentCapability::Storage(_) => {
                    let partial =
                        pos.moniker().leaf().expect("impossible source above root").to_partial();
                    ModelError::from(RoutingError::storage_from_child_expose_not_found(
                        &partial,
                        pos.moniker().parent().as_ref().expect("impossible source above root"),
                        pos.capability.source_id(),
                    ))
                }
                _ => {
                    unreachable!(
                        "Searched for an expose declaration at `{}` for `{}`, but the \
                            source doesn't seem like it should map to an expose declaration",
                        pos.moniker().parent().expect("impossible source above root"),
                        pos.capability.source_id()
                    );
                }
            })?;
        let (source, target) = match expose {
            ExposeDecl::Service(_) => return Err(ModelError::unsupported("Service capability")),
            ExposeDecl::Protocol(ls) => (CapabilityExposeSource::Protocol(&ls.source), &ls.target),
            ExposeDecl::Directory(d) => (CapabilityExposeSource::Directory(&d.source), &d.target),
            ExposeDecl::Runner(r) => (CapabilityExposeSource::Runner(&r.source), &r.target),
            ExposeDecl::Resolver(r) => (CapabilityExposeSource::Resolver(&r.source), &r.target),
        };
        if target != &ExposeTarget::Parent {
            let partial = pos.moniker().leaf().expect("impossible source above root").to_partial();
            return Err(RoutingError::expose_from_child_expose_not_found(
                &partial,
                pos.moniker().parent().as_ref().expect("impossible source above root"),
                pos.capability.source_id(),
            )
            .into());
        }
        let (dir_rights, subdir_decl) = match expose {
            ExposeDecl::Directory(ExposeDirectoryDecl { rights, subdir, .. }) => {
                (rights.map(Rights::from), subdir.clone())
            }
            _ => (None, None),
        };
        match source {
            CapabilityExposeSource::Protocol(ExposeSource::Self_) => {
                match pos.capability.source_path() {
                    None => {
                        // The exposed capability comes from the current component.
                        // Find the current component's Protocol declaration.
                        let cap = ComponentCapability::Expose(expose.clone());
                        return Ok(CapabilitySource::Component {
                            capability: ComponentCapability::Protocol(
                                cap.find_protocol_source(decl)
                                    .expect("protocol offer references nonexistent section")
                                    .clone(),
                            ),
                            realm: cur_realm.as_weak(),
                        });
                    }
                    Some(_) => {
                        // Legacy path: protocol is exposed by path, get its info from the
                        // ExposeDecl.
                        return Ok(CapabilitySource::Component {
                            capability: ComponentCapability::Expose(expose.clone()),
                            realm: cur_realm.as_weak(),
                        });
                    }
                }
            }
            CapabilityExposeSource::Protocol(ExposeSource::Capability(_)) => {
                return Ok(CapabilitySource::Capability {
                    source_capability: ComponentCapability::Expose(expose.clone()),
                    realm: cur_realm.as_weak(),
                });
            }
            CapabilityExposeSource::Directory(ExposeSource::Self_) => {
                match pos.capability.source_path() {
                    None => {
                        // The offered capability comes from the current component.  Update state
                        // and return a capability corresponding to the current component's
                        // Directory declaration.
                        let capability = ComponentCapability::Expose(expose.clone());
                        let capability = pos.cap_state.finalize_directory_from_component(
                            &capability,
                            decl,
                            dir_rights,
                            subdir_decl,
                        )?;
                        return Ok(CapabilitySource::Component {
                            capability,
                            realm: cur_realm.as_weak(),
                        });
                    }
                    Some(_) => {
                        // Legacy path: directory is exposed by path, get its info from the
                        // ExposeDecl.
                        if let CapabilityState::Directory { rights_state, subdir } =
                            &mut pos.cap_state
                        {
                            *rights_state = rights_state.finalize(dir_rights)?;
                            CapabilityState::update_subdir(subdir, subdir_decl);
                        }
                        return Ok(CapabilitySource::Component {
                            capability: ComponentCapability::Expose(expose.clone()),
                            realm: cur_realm.as_weak(),
                        });
                    }
                }
            }
            CapabilityExposeSource::Runner(ExposeSource::Self_) => {
                // The exposed capability comes from the current component.
                // Find the current component's Runner declaration.
                let cap = ComponentCapability::Expose(expose.clone());
                return Ok(CapabilitySource::Component {
                    capability: ComponentCapability::Runner(
                        cap.find_runner_source(decl)
                            .expect(&format!(
                                "An `expose from runner` declaration was found at `{}` for `{}`
                                with no corresponding runner declaration. This ComponentDecl should
                                not have passed validation.",
                                pos.moniker(),
                                cap.source_id()
                            ))
                            .clone(),
                    ),
                    realm: cur_realm.as_weak(),
                });
            }
            CapabilityExposeSource::Resolver(ExposeSource::Self_) => {
                // The exposed capability comes from the current component.
                // Find the current component's Resolver declaration.
                let cap = ComponentCapability::Expose(expose.clone());
                return Ok(CapabilitySource::Component {
                    capability: ComponentCapability::Resolver(
                        cap.find_resolver_source(decl)
                            .expect(&format!(
                                "An `expose from resolver` declaration was found at `{}` for `{}`
                            with no corresponding resolver declaration. This ComponentDecl should
                            not have passed validation.",
                                pos.moniker(),
                                cap.source_id()
                            ))
                            .clone(),
                    ),
                    realm: cur_realm.as_weak(),
                });
            }
            CapabilityExposeSource::Protocol(ExposeSource::Child(child_name))
            | CapabilityExposeSource::Runner(ExposeSource::Child(child_name))
            | CapabilityExposeSource::Resolver(ExposeSource::Child(child_name)) => {
                // The offered capability comes from a child, so follow the child.
                pos.capability = ComponentCapability::Expose(expose.clone());
                let partial = PartialMoniker::new(child_name.to_string(), None);
                pos.realm = ExtendedRealm::Component(
                    cur_realm_state.get_live_child_realm(&partial).ok_or(ModelError::from(
                        RoutingError::expose_from_child_instance_not_found(
                            &partial,
                            pos.moniker(),
                            pos.capability.source_id(),
                        ),
                    ))?,
                );
                continue;
            }
            CapabilityExposeSource::Directory(ExposeSource::Child(child_name)) => {
                if let CapabilityState::Directory { rights_state, subdir } = &mut pos.cap_state {
                    *rights_state = rights_state.advance(dir_rights)?;
                    CapabilityState::update_subdir(subdir, subdir_decl);
                }
                // The offered capability comes from a child, so follow the child.
                pos.capability = ComponentCapability::Expose(expose.clone());
                let partial = PartialMoniker::new(child_name.to_string(), None);
                pos.realm = ExtendedRealm::Component(
                    cur_realm_state.get_live_child_realm(&partial).ok_or(ModelError::from(
                        RoutingError::expose_from_child_instance_not_found(
                            &partial,
                            pos.moniker(),
                            pos.capability.source_id(),
                        ),
                    ))?,
                );
                continue;
            }
            CapabilityExposeSource::Protocol(ExposeSource::Framework) => {
                let capability =
                    InternalCapability::framework_from_expose_decl(expose).map_err(|_| {
                        ModelError::from(RoutingError::expose_from_framework_not_found(
                            pos.moniker(),
                            pos.capability.source_id(),
                        ))
                    })?;
                return Ok(CapabilitySource::Framework {
                    capability,
                    scope_moniker: pos.moniker().clone(),
                });
            }
            CapabilityExposeSource::Directory(ExposeSource::Framework) => {
                // Directories offered or exposed directly from the framework are limited to
                // read-only rights.
                if let CapabilityState::Directory { rights_state, subdir } = &mut pos.cap_state {
                    *rights_state = rights_state.finalize(Some(Rights::from(*READ_RIGHTS)))?;
                    CapabilityState::update_subdir(subdir, subdir_decl);
                }
                let capability =
                    InternalCapability::framework_from_expose_decl(expose).map_err(|_| {
                        ModelError::from(RoutingError::expose_from_framework_not_found(
                            pos.moniker(),
                            pos.capability.source_id(),
                        ))
                    })?;
                return Ok(CapabilitySource::Framework {
                    capability,
                    scope_moniker: pos.moniker().clone(),
                });
            }
            CapabilityExposeSource::Runner(ExposeSource::Capability(_))
            | CapabilityExposeSource::Resolver(ExposeSource::Capability(_))
            | CapabilityExposeSource::Directory(ExposeSource::Capability(_)) => {
                // Currently we don't expose any of these capabilities based on a different
                // capability. This is disallowed in validation, so we should never reach here.
                panic!("non-protocol used a capability as a source");
            }
            CapabilityExposeSource::Runner(ExposeSource::Framework)
            | CapabilityExposeSource::Resolver(ExposeSource::Framework) => {
                // Currently we don't expose any runners/resolvers from `framework`.
                // TODO: This error should be caught by validation. We shouldn't have to handle
                // this case here.
                return Err(RoutingError::expose_from_framework_not_found(
                    pos.moniker(),
                    pos.capability.source_id(),
                )
                .into());
            }
        }
    }
}

/// Sets an epitaph on `server_end` for a capability routing failure, and logs the error. Logs a
/// failure to route a capability. Formats `err` as a `String`, but elides the type if the error is
/// a `RoutingError`, the common case.
pub(super) fn report_routing_failure(
    target_moniker: &AbsoluteMoniker,
    cap: &ComponentCapability,
    err: &ModelError,
    server_end: zx::Channel,
    logger: Option<&dyn FmtArgsLogger>,
) {
    let _ = server_end.close_with_epitaph(routing_epitaph(err));
    let err_str = match err {
        ModelError::RoutingError { err } => format!("{}", err),
        _ => format!("{}", err),
    };
    let log_msg = format!(
        "Failed to route {} `{}` with target component `{}`: {}",
        cap.type_name(),
        cap.source_id(),
        target_moniker,
        err_str
    );
    if let Some(l) = logger {
        l.log(Level::Error, format_args!("{}", log_msg));
    } else {
        MODEL_LOGGER.log(Level::Error, format_args!("{}", log_msg))
    }
}

/// Converts `err` to a `zx::Status` to use as an epitaph on a routed channel.
fn routing_epitaph(err: &ModelError) -> zx::Status {
    match err {
        ModelError::RoutingError { err } => err.as_zx_status(),
        ModelError::RightsError { err } => err.as_zx_status(),
        ModelError::PolicyError { err } => err.as_zx_status(),
        ModelError::Unsupported { .. } => zx::Status::NOT_SUPPORTED,
        // Any other type of error is not expected.
        _ => zx::Status::INTERNAL,
    }
}
