memlink_runtime/
instance.rs1use std::path::{Path, PathBuf};
4use std::sync::Arc;
5
6use crate::arena::Arena;
7use crate::error::{Error, Result};
8use crate::ffi::symbols::{LibHandle, ModuleSymbols};
9use crate::mhash::fnv1a_hash;
10use crate::panic::{safe_call_unchecked, setup_panic_hook};
11
12#[derive(Debug, Clone, Default)]
13pub struct ModuleProfile {
14 pub name: Option<String>,
15}
16
17struct ModuleInstanceInner {
18 #[allow(dead_code)]
19 handle: LibHandle,
20 _symbols: ModuleSymbols<'static>,
21}
22
23pub struct ModuleInstance {
24 inner: Arc<ModuleInstanceInner>,
25 path: PathBuf,
26 arena: Arena,
27 profile: ModuleProfile,
28}
29
30unsafe impl Send for ModuleInstance {}
31unsafe impl Sync for ModuleInstance {}
32
33impl ModuleInstance {
34 pub(crate) fn new(handle: LibHandle, symbols: ModuleSymbols, path: PathBuf) -> Self {
35 setup_panic_hook();
36
37 let symbols = unsafe {
38 std::mem::transmute::<ModuleSymbols<'_>, ModuleSymbols<'static>>(symbols)
39 };
40
41 ModuleInstance {
42 inner: Arc::new(ModuleInstanceInner {
43 handle,
44 _symbols: symbols,
45 }),
46 path,
47 arena: Arena::with_default_capacity(),
48 profile: ModuleProfile::default(),
49 }
50 }
51
52 pub fn path(&self) -> &Path {
53 &self.path
54 }
55
56 pub fn profile(&self) -> &ModuleProfile {
57 &self.profile
58 }
59
60 pub fn arena(&self) -> &Arena {
61 &self.arena
62 }
63
64 fn symbols(&self) -> &ModuleSymbols<'static> {
65 &self.inner._symbols
66 }
67
68 pub fn init(&self, config: &[u8]) -> Result<()> {
69 safe_call_unchecked(|| {
70 let result = unsafe { (self.symbols().memlink_init)(config.as_ptr(), config.len()) };
71
72 if result == 0 {
73 Ok(())
74 } else {
75 Err(Error::ModuleCallFailed(result))
76 }
77 })?
78 }
79
80 pub fn call(&self, method: &str, args: &[u8]) -> Result<Vec<u8>> {
81 let method_id = fnv1a_hash(method);
82 let mut output = vec![0u8; 4096];
83
84 safe_call_unchecked(|| {
85 let result = unsafe {
86 (self.symbols().memlink_call)(method_id, args.as_ptr(), args.len(), output.as_mut_ptr())
87 };
88
89 if result == 0 {
90 Ok(output)
91 } else {
92 Err(Error::ModuleCallFailed(result))
93 }
94 })?
95 }
96
97 pub fn shutdown(&self) -> Result<()> {
98 safe_call_unchecked(|| {
99 let result = unsafe { (self.symbols().memlink_shutdown)() };
100
101 if result == 0 {
102 Ok(())
103 } else {
104 Err(Error::ModuleCallFailed(result))
105 }
106 })?
107 }
108}
109
110impl Clone for ModuleInstance {
111 fn clone(&self) -> Self {
112 ModuleInstance {
113 inner: Arc::clone(&self.inner),
114 path: self.path.clone(),
115 arena: self.arena.clone(),
116 profile: self.profile.clone(),
117 }
118 }
119}
120
121impl std::fmt::Debug for ModuleInstance {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 f.debug_struct("ModuleInstance")
124 .field("path", &self.path)
125 .field("profile", &self.profile)
126 .finish()
127 }
128}
129
130impl Drop for ModuleInstance {
131 fn drop(&mut self) {
132 let _ = self.shutdown();
133 }
134}