1use std::sync::Arc;
2
3use crate::{Bridge, CompiledModule, ExecutionResult, Observation, Result, SandboxConfig};
4
5pub struct PersistentSandbox {
11 module: Arc<CompiledModule>,
12 bridge: Arc<dyn Bridge>,
13 config: SandboxConfig,
14 loaded_scripts: Vec<String>,
15}
16
17impl PersistentSandbox {
18 pub fn new(
20 module: &CompiledModule,
21 bridge: Arc<dyn Bridge>,
22 config: &SandboxConfig,
23 ) -> Result<Self> {
24 let serialized = module.serialize()?;
25 let module = CompiledModule::load_cached(&serialized)?;
26 Ok(Self {
27 module: Arc::new(module),
28 bridge,
29 config: config.clone(),
30 loaded_scripts: Vec::new(),
31 })
32 }
33
34 pub fn load(&mut self, scripts: &[String]) -> Result<()> {
36 self.loaded_scripts = scripts.to_vec();
37 let _ = self.execute(&[])?;
38 Ok(())
39 }
40
41 #[must_use]
43 pub fn eval_only(&mut self, script: &str) -> Vec<Observation> {
44 self.execute(&[script.to_string()])
45 .map(|result| result.observations)
46 .unwrap_or_default()
47 }
48
49 pub fn store_fuel(&self) -> Result<u64> {
51 Ok(self.config.max_fuel)
52 }
53
54 pub fn set_store_fuel(&mut self, fuel: u64) {
56 self.config.max_fuel = fuel;
57 }
58
59 fn execute(&self, extra_scripts: &[String]) -> Result<ExecutionResult> {
60 let mut scripts = self.loaded_scripts.clone();
61 scripts.extend(extra_scripts.iter().cloned());
62 self.module
63 .execute(&scripts, Arc::clone(&self.bridge), &self.config)
64 }
65}