sim-lib-server 0.1.0-rc.1

SIM workspace package for sim lib server.
Documentation
use std::collections::BTreeMap;

use sim_kernel::{CapabilityName, Expr, Symbol, Value};

use crate::install_server_lib;

use super::{cx, quoted};

pub(crate) fn table_field(entries: &[(Expr, Expr)], key: &str) -> Option<Expr> {
    entries
        .iter()
        .find_map(|(entry_key, entry_value)| match entry_key {
            Expr::Symbol(symbol) if symbol.name.as_ref() == key => Some(entry_value.clone()),
            _ => None,
        })
}

pub(crate) fn normalized_reflect_table(
    cx: &mut sim_kernel::Cx,
    value: Value,
) -> BTreeMap<String, Expr> {
    let Expr::Map(entries) = value.object().as_expr(cx).unwrap() else {
        panic!("server/reflect should produce a table expression");
    };
    let mut map = BTreeMap::new();
    for (key, value) in entries {
        let Expr::Symbol(symbol) = key else {
            continue;
        };
        if matches!(symbol.name.as_ref(), "id" | "uptime") {
            continue;
        }
        map.insert(symbol.as_qualified_str(), value);
    }
    map
}

pub(crate) fn assert_trigger_source_requires_capability(source: Expr, capability: CapabilityName) {
    let mut cx = cx();
    install_server_lib(&mut cx).unwrap();

    let server = cx
        .eval_expr(Expr::Call {
            operator: Box::new(Expr::Symbol(Symbol::qualified("server", "start"))),
            args: vec![],
        })
        .unwrap();
    cx.registry_mut()
        .register_value(Symbol::qualified("test", "cap-server"), server)
        .unwrap();

    let err = cx
        .call_exprs(
            cx.resolve_function(&Symbol::qualified("server", "trigger"))
                .unwrap(),
            vec![
                Expr::Symbol(Symbol::qualified("test", "cap-server")),
                Expr::Symbol(Symbol::new(":source")),
                source,
                Expr::Symbol(Symbol::new(":decode")),
                quoted(Expr::Symbol(Symbol::new("lisp"))),
            ],
        )
        .unwrap_err();
    assert!(matches!(
        err,
        sim_kernel::Error::CapabilityDenied { capability: denied }
            if denied == capability
    ));
}