1use crate::{Bridge, DISPATCH_KEY, DispatchSlot, cjson, cmsgpack, host};
6use luna_core::version::LuaVersion;
7use luna_core::vm::exec::Vm;
8use std::rc::Rc;
9
10pub(crate) fn dialect_slot(v: LuaVersion) -> usize {
11 match v {
12 LuaVersion::Lua51 => 0,
13 LuaVersion::Lua52 => 1,
14 LuaVersion::Lua53 => 2,
15 LuaVersion::Lua54 => 3,
16 LuaVersion::MacroLua => 4,
17 LuaVersion::Lua55 => 5,
18 }
19}
20
21impl Bridge {
22 #[cfg(test)]
25 fn vm_count(&self) -> usize {
26 self.vms.iter().filter(|s| s.is_some()).count()
27 }
28
29 pub(crate) fn vm_for(&mut self, version: LuaVersion) -> &mut Vm {
36 let slot = &mut self.vms[dialect_slot(version)];
37 if slot.is_none() {
38 let mut builder =
39 Vm::sandbox(version).open_base().open_math().open_string().open_table();
40 if self.instr_budget > 0 {
41 builder = builder.with_instr_budget(self.instr_budget);
42 }
43 let mut vm = builder.build();
44 host::install_redis_table(&mut vm);
45 cmsgpack::install_cmsgpack(&mut vm);
47 cjson::install_cjson(&mut vm);
48 let _ = vm.set_userdata(
54 DISPATCH_KEY,
55 DispatchSlot {
56 f: Rc::clone(&self.dispatch),
57 read_only: Rc::clone(&self.read_only),
58 },
59 );
60 *slot = Some(vm);
61 }
62 slot.as_mut().expect("just-inserted Vm")
63 }
64}
65
66pub(crate) fn format_lua_error(e: &luna_core::vm::error::LuaError) -> String {
67 format!("{e}")
70}
71
72pub(crate) fn version_tag(v: LuaVersion) -> &'static str {
73 match v {
74 LuaVersion::Lua51 => "5.1",
75 LuaVersion::Lua52 => "5.2",
76 LuaVersion::Lua53 => "5.3",
77 LuaVersion::Lua54 => "5.4",
78 LuaVersion::MacroLua => "macro",
79 LuaVersion::Lua55 => "5.5",
80 }
81}
82
83impl core::fmt::Debug for Bridge {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
93 f.debug_struct("Bridge")
94 .field("vms_spawned", &self.vms.iter().filter(|v| v.is_some()).count())
95 .field("read_only", &self.read_only.get())
96 .field("instr_budget", &self.instr_budget)
97 .field("allow", &self.allow)
98 .field("cached_scripts", &self.script_cache.len())
99 .finish_non_exhaustive()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use crate::{Bridge, FlushMode};
106
107 #[test]
108 fn eval_reuses_vm_across_calls() {
109 let mut b = Bridge::with_no_dispatch();
110 assert_eq!(b.eval(b"return 1", &[], &[]), b":1\r\n");
111 assert_eq!(b.eval(b"return 2", &[], &[]), b":2\r\n");
112 assert_eq!(b.vm_count(), 1);
114 }
115
116 #[test]
117 fn script_flush_drops_vm_pool() {
118 let mut b = Bridge::with_no_dispatch();
119 let _ = b.eval(b"return 1", &[], &[]);
120 assert_eq!(b.vm_count(), 1);
121 b.script_flush(FlushMode::Sync);
122 assert_eq!(b.vm_count(), 0);
123 }
124}