Skip to main content

sim_lib_plugin_vst3/
cookbook.rs

1//! Deterministic cookbook builders for VST3 plugin recipes.
2
3use sim_kernel::{Expr, NumberLiteral, Symbol};
4
5use crate::vst3_gain_vst3_descriptor;
6
7/// Build the modeled VST3 gain descriptor used by the cookbook recipe.
8pub fn vst3_gain_demo() -> Expr {
9    let descriptor = vst3_gain_vst3_descriptor().expect("valid VST3 gain descriptor");
10    let plugin = descriptor
11        .to_plugin_descriptor()
12        .expect("VST3 gain lowers to plugin-core descriptor");
13    Expr::Map(vec![
14        (field("kind"), sym("plugin-vst3", "descriptor")),
15        (field("class-id"), Expr::String(descriptor.class_id)),
16        (field("name"), Expr::String(descriptor.name)),
17        (field("buses"), number(descriptor.buses.len())),
18        (field("parameters"), number(descriptor.parameters.len())),
19        (
20            field("format"),
21            sym("plugin-format", plugin.id.format.as_str()),
22        ),
23    ])
24}
25
26fn field(name: &str) -> Expr {
27    Expr::Symbol(Symbol::qualified("plugin-vst3", name))
28}
29
30fn sym(namespace: &str, name: &str) -> Expr {
31    Expr::Symbol(Symbol::qualified(namespace, name))
32}
33
34fn number(value: impl ToString) -> Expr {
35    Expr::Number(NumberLiteral {
36        domain: Symbol::qualified("numbers", "i64"),
37        canonical: value.to_string(),
38    })
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn vst3_gain_demo_lowers_to_core_plugin_descriptor() {
47        let Expr::Map(entries) = vst3_gain_demo() else {
48            panic!("VST3 demo is a map")
49        };
50        assert!(entries.iter().any(|(_, value)| {
51            matches!(value, Expr::Symbol(symbol) if symbol.as_qualified_str() == "plugin-format/vst3")
52        }));
53    }
54}