1use crate::error;
2use crate::ffi;
3use zwasm_sys as sys;
4
5pub struct Config {
14 pub(crate) ptr: *mut sys::zwasm_config_t,
15 allocator: Option<Box<ConfigAllocator>>,
16 _not_send_sync: std::marker::PhantomData<std::rc::Rc<()>>,
17}
18
19impl Config {
20 pub fn new() -> Result<Self, error::ZwasmError> {
24 let ptr = unsafe { sys::zwasm_config_new() };
25
26 if ptr.is_null() {
27 Err(error::last_error()
28 .unwrap_or_else(|| error::ZwasmError("Unknown error".to_string())))
29 } else {
30 Ok(Config {
31 ptr,
32 allocator: None,
33 _not_send_sync: std::marker::PhantomData,
34 })
35 }
36 }
37
38 pub fn set_allocator<F, G>(&mut self, alloc_fn: F, free_fn: G)
47 where
48 F: Fn(usize, usize) -> *mut std::ffi::c_void + Send + Sync + 'static,
49 G: Fn(*mut std::ffi::c_void, usize, usize) + Send + Sync + 'static,
50 {
51 let mut allocator = Box::new(ConfigAllocator {
52 alloc: Box::new(alloc_fn),
53 free: Box::new(free_fn),
54 });
55
56 let env = &mut *allocator as *mut ConfigAllocator as *mut std::ffi::c_void;
57
58 unsafe {
59 sys::zwasm_config_set_allocator(
60 self.ptr,
61 Some(ffi::config_allocator_alloc_trampoline),
62 Some(ffi::config_allocator_free_trampoline),
63 env,
64 );
65 }
66
67 self.allocator = Some(allocator);
68 }
69
70 pub fn set_fuel(&mut self, fuel: u64) {
74 unsafe {
75 sys::zwasm_config_set_fuel(self.ptr, fuel);
76 }
77 }
78
79 pub fn set_timeout(&mut self, timeout_ms: u64) {
83 unsafe {
84 sys::zwasm_config_set_timeout(self.ptr, timeout_ms);
85 }
86 }
87
88 pub fn set_max_memory(&mut self, max_memory: u64) {
92 unsafe {
93 sys::zwasm_config_set_max_memory(self.ptr, max_memory);
94 }
95 }
96
97 pub fn set_force_interpreter(&mut self, force: bool) {
101 unsafe {
102 sys::zwasm_config_set_force_interpreter(self.ptr, force);
103 }
104 }
105
106 pub fn set_cancelable(&mut self, cancelable: bool) {
110 unsafe {
111 sys::zwasm_config_set_cancellable(self.ptr, cancelable);
112 }
113 }
114}
115
116impl Drop for Config {
117 fn drop(&mut self) {
118 unsafe {
119 sys::zwasm_config_delete(self.ptr);
120 }
121 }
122}
123
124pub(crate) struct ConfigAllocator {
125 pub(crate) alloc: Box<dyn Fn(usize, usize) -> *mut std::ffi::c_void + Send + Sync + 'static>,
126 pub(crate) free: Box<dyn Fn(*mut std::ffi::c_void, usize, usize) + Send + Sync + 'static>,
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use crate::module;
133
134 const RETURN42_WASM: &[u8] = &[
140 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f,
141 0x03, 0x02, 0x01, 0x00, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x06, 0x01, 0x04,
142 0x00, 0x41, 0x2a, 0x0b,
143 ];
144
145 #[test]
146 fn test_config_lifecycle() {
147 let config = Config::new().expect("Failed to create config");
148 let module = module::Module::new_configured(RETURN42_WASM, &config)
149 .expect("Failed to create module with config");
150 let results = module.invoke("f", &[]).expect("Failed to invoke function");
151 assert_eq!(results[0], 42, "f() == 42 via configured module");
152 }
153}