1use crate::builtin::BuiltinProgram;
2#[cfg(feature = "native")]
3use crate::native::NativeProgram;
4#[cfg(feature = "wasm")]
5use crate::runtime::StoreData;
6#[cfg(feature = "wasm")]
7use wasmtime::{Instance, Module, Store};
8
9pub enum ProgramBackend {
10 Builtin(BuiltinProgram),
11 #[cfg(feature = "wasm")]
12 Wasm(WasmProgram),
13 #[cfg(feature = "native")]
14 Native(NativeProgram),
15}
16
17#[cfg(feature = "wasm")]
18pub struct WasmProgram {
19 pub module: Module,
20 pub export_name: String,
21 pub cached: Option<(Store<StoreData>, Instance)>,
23}
24
25pub struct LoadedProgram {
27 pub name: String,
28 pub priority: i32,
29 pub consecutive_traps: u32,
30 pub enabled: bool,
31 pub max_consecutive_traps: u32,
32 pub backend: ProgramBackend,
33}
34
35impl LoadedProgram {
36 pub fn new_builtin(name: String, builtin: BuiltinProgram, priority: i32) -> Self {
37 LoadedProgram {
38 name,
39 priority,
40 consecutive_traps: 0,
41 enabled: true,
42 max_consecutive_traps: 10,
43 backend: ProgramBackend::Builtin(builtin),
44 }
45 }
46
47 #[cfg(feature = "wasm")]
48 pub fn new(name: String, module: Module, priority: i32) -> Self {
49 LoadedProgram {
50 name,
51 priority,
52 consecutive_traps: 0,
53 enabled: true,
54 max_consecutive_traps: 10,
55 backend: ProgramBackend::Wasm(WasmProgram {
56 module,
57 export_name: "on_hook".to_string(),
58 cached: None,
59 }),
60 }
61 }
62
63 #[cfg(feature = "native")]
64 pub fn new_native(name: String, native: NativeProgram, priority: i32) -> Self {
65 LoadedProgram {
66 name,
67 priority,
68 consecutive_traps: 0,
69 enabled: true,
70 max_consecutive_traps: 10,
71 backend: ProgramBackend::Native(native),
72 }
73 }
74
75 pub fn record_success(&mut self) {
77 self.consecutive_traps = 0;
78 }
79
80 pub fn drop_cache(&mut self) {
82 match &mut self.backend {
83 ProgramBackend::Builtin(_) => {}
84 #[cfg(feature = "wasm")]
85 ProgramBackend::Wasm(wasm) => {
86 wasm.cached = None;
87 }
88 #[cfg(feature = "native")]
89 ProgramBackend::Native(_) => {}
90 }
91 }
92
93 pub fn backend_name(&self) -> &'static str {
94 match &self.backend {
95 ProgramBackend::Builtin(_) => "builtin",
96 #[cfg(feature = "wasm")]
97 ProgramBackend::Wasm(_) => "wasm",
98 #[cfg(feature = "native")]
99 ProgramBackend::Native(_) => "native",
100 }
101 }
102
103 pub fn record_trap(&mut self) -> bool {
105 self.consecutive_traps += 1;
106 if self.consecutive_traps >= self.max_consecutive_traps {
107 self.enabled = false;
108 true
109 } else {
110 false
111 }
112 }
113}