sim-lib-agent 0.1.8

Agent runtime surfaces for SIM.
Documentation
use sim_kernel::{CapabilityName, Cx, Error, Result};

pub(crate) fn fs_read_capability() -> CapabilityName {
    CapabilityName::new("fs/read")
}

pub(crate) fn fs_write_capability() -> CapabilityName {
    CapabilityName::new("fs/write")
}

pub(crate) fn find_capability() -> CapabilityName {
    CapabilityName::new("find")
}

pub(crate) fn edit_capability() -> CapabilityName {
    CapabilityName::new("edit")
}

pub(crate) fn exec_capability() -> CapabilityName {
    CapabilityName::new("exec")
}

pub(crate) fn net_http_capability() -> CapabilityName {
    CapabilityName::new("net/http")
}

pub(crate) fn require_fs_read_capability(cx: &Cx) -> Result<()> {
    require_with_aliases(cx, fs_read_capability(), fs_read_aliases())
}

pub(crate) fn require_fs_write_capability(cx: &Cx) -> Result<()> {
    require_with_aliases(cx, fs_write_capability(), fs_write_aliases())
}

pub(crate) fn require_net_http_capability(cx: &Cx) -> Result<()> {
    require_with_aliases(cx, net_http_capability(), net_http_aliases())
}

pub(crate) fn require_component_capability(cx: &Cx, capability: &CapabilityName) -> Result<()> {
    if capability == &fs_read_capability() {
        require_fs_read_capability(cx)
    } else if capability == &fs_write_capability() {
        require_fs_write_capability(cx)
    } else if capability == &net_http_capability() {
        require_net_http_capability(cx)
    } else {
        cx.require(capability)
    }
}

fn fs_read_aliases() -> &'static [&'static str] {
    &["table.fs.read", "stream.file.read", "file-read"]
}

fn fs_write_aliases() -> &'static [&'static str] {
    &[
        "table.fs.write",
        "table.fs.mkdir",
        "table.fs.rmdir",
        "stream.file.write",
        "file-write",
    ]
}

fn net_http_aliases() -> &'static [&'static str] {
    &["net.http", "net-connect", "network"]
}

fn require_with_aliases(
    cx: &Cx,
    canonical: CapabilityName,
    aliases: &'static [&'static str],
) -> Result<()> {
    if cx.capabilities().contains(&canonical)
        || aliases
            .iter()
            .any(|alias| cx.capabilities().contains(&CapabilityName::new(*alias)))
    {
        Ok(())
    } else {
        Err(Error::CapabilityDenied {
            capability: canonical,
        })
    }
}