Skip to main content

sim_lib_numbers_codec/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3#![allow(deprecated)]
4
5//! The number-literal codec surface: helpers that build the `numeric-plugin-v1`
6//! descriptor symbols and table values advertising a numeric codec or method
7//! provider to the runtime.
8
9use sim_kernel::{Factory, Result, Symbol, Value};
10
11/// Build the descriptor symbol `group/name` advertising a numeric codec or
12/// method provider under the `numeric-plugin-v1` API.
13///
14/// # Examples
15///
16/// ```
17/// use sim_kernel::Symbol;
18/// use sim_lib_numbers_codec::numeric_plugin_descriptor_symbol;
19///
20/// assert_eq!(
21///     numeric_plugin_descriptor_symbol("numbers/quad", "simpson"),
22///     Symbol::qualified("numbers/quad", "simpson"),
23/// );
24/// ```
25pub fn numeric_plugin_descriptor_symbol(group: &str, name: &str) -> Symbol {
26    Symbol::qualified(group, name)
27}
28
29/// Build the `numeric-plugin-v1` descriptor table for `method`, recording its
30/// plugin `kind`, whether it is `adaptive`, and the `provider` domain that
31/// supplies it.
32pub fn numeric_plugin_descriptor_value(
33    factory: &dyn Factory,
34    method: Symbol,
35    kind: &str,
36    adaptive: bool,
37    provider: Symbol,
38) -> Result<Value> {
39    factory.table(vec![
40        (
41            Symbol::new("kind"),
42            factory.string("numeric-plugin".to_owned())?,
43        ),
44        (Symbol::new("method"), factory.symbol(method)?),
45        (Symbol::new("plugin-kind"), factory.string(kind.to_owned())?),
46        (Symbol::new("adaptive"), factory.bool(adaptive)?),
47        (Symbol::new("provider"), factory.symbol(provider)?),
48        (
49            Symbol::new("api"),
50            factory.string("numeric-plugin-v1".to_owned())?,
51        ),
52    ])
53}
54
55/// Cookbook recipes for this lib, embedded at build time.
56pub static RECIPES: sim_cookbook::EmbeddedDir =
57    include!(concat!(env!("OUT_DIR"), "/cookbook_recipes.rs"));
58
59#[cfg(test)]
60mod tests {
61    use std::sync::Arc;
62
63    use sim_kernel::{DefaultFactory, Expr, NoopEvalPolicy};
64    use sim_lib_numbers_core::domains;
65
66    use super::{numeric_plugin_descriptor_symbol, numeric_plugin_descriptor_value};
67
68    #[test]
69    fn descriptor_symbol_uses_namespaced_group() {
70        assert_eq!(
71            numeric_plugin_descriptor_symbol("numbers/quad", "simpson"),
72            sim_kernel::Symbol::qualified("numbers/quad", "simpson")
73        );
74    }
75
76    #[test]
77    fn descriptor_value_has_stable_table_surface() {
78        let factory = DefaultFactory;
79        let mut cx = sim_kernel::Cx::new(Arc::new(NoopEvalPolicy), Arc::new(DefaultFactory));
80        let value = numeric_plugin_descriptor_value(
81            &factory,
82            sim_kernel::Symbol::new("rkf45"),
83            "ode",
84            true,
85            domains::rk(),
86        )
87        .unwrap();
88        let Expr::Map(entries) = value.object().as_expr(&mut cx).unwrap() else {
89            panic!("descriptor should encode as a map");
90        };
91        assert!(entries.iter().any(|(key, value)| {
92            *key == Expr::Symbol(sim_kernel::Symbol::new("method"))
93                && *value == Expr::Symbol(sim_kernel::Symbol::new("rkf45"))
94        }));
95    }
96}