marine_core/
marine_core.rs1use super::generic::*;
18use crate::config::MarineCoreConfig;
19use crate::module::MModule;
20use crate::module::MRecordTypes;
21use crate::{IRecordType, IValue, MemoryStats, MError, MFunctionSignature, ModuleMemoryStat, MResult};
22
23use marine_wasm_backend_traits::AsContextMut;
24use marine_wasm_backend_traits::Store;
25use marine_wasm_backend_traits::WasiState;
26use marine_wasm_backend_traits::WasmBackend;
27
28use serde::Serialize;
29
30use std::collections::hash_map::Entry;
31use std::collections::HashMap;
32use std::sync::Arc;
33use std::cell::RefCell;
34
35#[derive(PartialEq, Eq, Debug, Clone, Serialize)]
37pub struct MModuleInterface<'a> {
38 pub record_types: &'a MRecordTypes,
39 pub function_signatures: Vec<MFunctionSignature>,
40}
41
42pub struct MarineCore<WB: WasmBackend> {
54 modules: HashMap<String, MModule<WB>>,
56 #[allow(unused)]
58 wasm_backend: WB,
59 store: RefCell<<WB as WasmBackend>::Store>,
61}
62
63impl<WB: WasmBackend> MarineCore<WB> {
64 pub fn new(config: MarineCoreConfig<WB>) -> MResult<Self> {
65 let mut store = <WB as WasmBackend>::Store::new(&config.wasm_backend);
66 store.set_total_memory_limit(config.total_memory_limit);
67 Ok(Self {
68 modules: HashMap::new(),
69 wasm_backend: config.wasm_backend,
70 store: RefCell::new(store),
71 })
72 }
73
74 pub async fn call_async(
76 &mut self,
77 module_name: impl AsRef<str>,
78 func_name: impl AsRef<str>,
79 arguments: &[IValue],
80 ) -> MResult<Vec<IValue>> {
81 let module_name = module_name.as_ref();
82 let store = &mut self.store;
83 let module = self
84 .modules
85 .get_mut(module_name)
86 .ok_or_else(|| MError::NoSuchModule(module_name.to_string()))?;
87
88 module
89 .call_async(
90 &mut store.get_mut().as_context_mut(),
91 module_name,
92 func_name.as_ref(),
93 arguments,
94 )
95 .await
96 }
97
98 pub async fn load_module(
100 &mut self,
101 name: impl Into<String>,
102 wasm_bytes: &[u8],
103 config: MModuleConfig<WB>,
104 ) -> MResult<()> {
105 self.load_module_(name.into(), wasm_bytes, config).await
106 }
107
108 async fn load_module_(
109 &mut self,
110 name: String,
111 wasm_bytes: &[u8],
112 config: MModuleConfig<WB>,
113 ) -> MResult<()> {
114 let module = MModule::new(
115 &name,
116 self.store.get_mut(),
117 wasm_bytes,
118 config,
119 &self.modules,
120 )
121 .await?;
122
123 match self.modules.entry(name) {
124 Entry::Vacant(entry) => {
125 entry.insert(module);
126 Ok(())
127 }
128 Entry::Occupied(entry) => Err(MError::NonUniqueModuleName(entry.key().clone())),
129 }
130 }
131
132 pub fn unload_module(&mut self, name: impl AsRef<str>) -> MResult<()> {
134 self.modules
136 .remove(name.as_ref())
137 .map(|_| ())
138 .ok_or_else(|| MError::NoSuchModule(name.as_ref().to_string()))
139 }
140
141 pub fn module_wasi_state<'s>(
142 &'s mut self,
143 module_name: impl AsRef<str>,
144 ) -> Option<Box<dyn WasiState + 's>> {
145 self.modules
146 .get_mut(module_name.as_ref())
147 .map(|module| module.get_wasi_state())
148 }
149
150 pub fn interface(&self) -> impl Iterator<Item = (&str, MModuleInterface<'_>)> {
152 self.modules
153 .iter()
154 .map(|(module_name, module)| (module_name.as_str(), Self::get_module_interface(module)))
155 }
156
157 pub fn module_interface(&self, module_name: impl AsRef<str>) -> Option<MModuleInterface<'_>> {
159 self.modules
160 .get(module_name.as_ref())
161 .map(Self::get_module_interface)
162 }
163
164 pub fn module_record_types(&self, module_name: impl AsRef<str>) -> Option<&MRecordTypes> {
166 self.modules
167 .get(module_name.as_ref())
168 .map(|module| module.export_record_types())
169 }
170
171 pub fn module_record_type_by_id(
173 &self,
174 module_name: impl AsRef<str>,
175 record_id: u64,
176 ) -> Option<&Arc<IRecordType>> {
177 self.modules
178 .get(module_name.as_ref())
179 .and_then(|module| module.export_record_type_by_id(record_id))
180 }
181
182 pub fn module_memory_stats(&self) -> MemoryStats<'_> {
184 let records = self
185 .modules
186 .iter()
187 .map(|(module_name, module)| {
188 ModuleMemoryStat::new(
189 module_name,
190 module.memory_size(&mut self.store.borrow_mut().as_context_mut()),
191 )
192 })
193 .collect::<Vec<_>>();
194 let allocation_stats = self.store.borrow_mut().report_memory_allocation_stats();
195 MemoryStats::new(records, allocation_stats)
196 }
197
198 pub fn clear_allocation_stats(&mut self) {
199 self.store.borrow_mut().clear_allocation_stats()
200 }
201
202 fn get_module_interface(module: &MModule<WB>) -> MModuleInterface<'_> {
203 let record_types = module.export_record_types();
204
205 let function_signatures = module.get_exports_signatures().collect::<Vec<_>>();
206
207 MModuleInterface {
208 record_types,
209 function_signatures,
210 }
211 }
212}