Skip to main content

sim_lib_web_bridge/
cookbook.rs

1//! Deterministic cookbook builders for web bridge recipes.
2
3use std::sync::Arc;
4
5use sim_kernel::{Cx, DefaultFactory, EagerPolicy, Expr, Symbol};
6use sim_lib_view::{
7    LensRegistry, UNIVERSAL_EDITOR_ID, UNIVERSAL_VIEW_ID, register_universal_default,
8};
9use sim_value::build::entry;
10
11use crate::{FixtureTransport, Session};
12
13/// Build the fixture-backed session descriptor used by the cookbook recipe.
14pub fn session_fixture_demo() -> Expr {
15    let mut cx = Cx::new(Arc::new(EagerPolicy), Arc::new(DefaultFactory));
16    let registry = registry();
17    let mut session = Session::new(FixtureTransport::new().with(resource(), sample_value()));
18    let scene = session
19        .open(
20            &mut cx,
21            &registry,
22            Symbol::new("pane-1"),
23            resource(),
24            Symbol::new(UNIVERSAL_VIEW_ID),
25            Symbol::new(UNIVERSAL_EDITOR_ID),
26        )
27        .expect("fixture session opens");
28    debug_assert!(sim_lib_scene::validate_scene(&scene).is_ok());
29    Expr::Map(vec![
30        entry("transport", Expr::Symbol(Symbol::new("fixture"))),
31        entry("resource", Expr::Symbol(resource())),
32        entry("pane", Expr::Symbol(Symbol::new("pane-1"))),
33        entry("scene", scene),
34    ])
35}
36
37fn registry() -> LensRegistry {
38    let mut registry = LensRegistry::new();
39    register_universal_default(&mut registry, false);
40    registry
41}
42
43fn sample_value() -> Expr {
44    Expr::Map(vec![
45        entry("title", Expr::String("Fixture-backed session".to_owned())),
46        entry("status", Expr::Symbol(Symbol::new("modeled"))),
47    ])
48}
49
50fn resource() -> Symbol {
51    Symbol::qualified("doc", "cookbook")
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn session_fixture_demo_carries_valid_scene() {
60        let demo = session_fixture_demo();
61        let Expr::Map(entries) = demo else {
62            panic!("demo descriptor is a map")
63        };
64        let scene = entries
65            .iter()
66            .find_map(|(key, value)| {
67                matches!(key, Expr::Symbol(symbol) if &*symbol.name == "scene").then_some(value)
68            })
69            .expect("scene field exists");
70        sim_lib_scene::validate_scene(scene).expect("session scene validates");
71    }
72
73    #[test]
74    fn canonical_entry_matches_session_cookbook_field_shape() {
75        let value = Expr::Symbol(Symbol::new("fixture"));
76        assert_eq!(
77            entry("transport", value.clone()),
78            (Expr::Symbol(Symbol::new("transport")), value)
79        );
80    }
81}