pros_simulator/
lib.rs

1use std::{path::Path, sync::mpsc::Receiver};
2
3use anyhow::Result;
4use host::{task::TaskPool, Host};
5use interface::SimulatorInterface;
6use pros_simulator_interface::{SimulatorEvent, SimulatorMessage};
7use wasmtime::*;
8
9use crate::system::system_daemon::system_daemon_initialize;
10
11mod api;
12pub mod host;
13pub mod interface;
14pub mod stream;
15mod system;
16
17/// Simulate the WebAssembly robot program at the given path.
18///
19/// # Arguments
20///
21/// - `robot_code`: The path to the robot program to simulate.
22/// - `interface`: A callback function that will be invoked with any events that occur during
23///   simulation.
24/// - `messages`: Input message stream to send to the robot program. This can be used to simulate
25///  controller input, LCD touch events, and more.
26pub async fn simulate(
27    robot_code: &Path,
28    interface: impl Into<SimulatorInterface>,
29    messages: Receiver<SimulatorMessage>,
30) -> Result<()> {
31    let interface: SimulatorInterface = interface.into();
32    tracing::info!("Initializing WASM runtime");
33    let engine = Engine::new(
34        Config::new()
35            .async_support(true)
36            .wasm_threads(true)
37            .debug_info(true)
38            .wasm_backtrace_details(WasmBacktraceDetails::Enable),
39    )
40    .unwrap();
41
42    tracing::info!("JIT compiling your robot code... 🚀");
43    interface.send(SimulatorEvent::RobotCodeLoading);
44
45    let module = Module::from_file(&engine, robot_code)?;
46
47    let shared_memory = SharedMemory::new(&engine, MemoryType::shared(18, 16384))?;
48    let host = Host::new(
49        engine.clone(),
50        shared_memory.clone(),
51        interface.clone(),
52        module.clone(),
53    )?;
54
55    system_daemon_initialize(&host, messages).await?;
56
57    TaskPool::run_to_completion(&host).await?;
58    interface.send(SimulatorEvent::RobotCodeFinished);
59
60    Ok(())
61}