1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::{ffi::module_run_v0 as ffi, Error, ErrorCode};
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
#[doc(hidden)]
pub use ffi::API as FFI_API;
pub use crate::ffi::entrypoints::module_run::ModuleRunFn;
pub struct Function {
handle: ffi::FunctionHandle,
}
impl Function {
pub fn new(fn_module: &str, fn_name: &str) -> Result<Self, Error> {
ffi::create_function(ffi::FunctionSource::NamedModule, fn_module, fn_name)
.map_err(Error::from)
.map(|handle| Self { handle })
}
pub fn with_local_fn(fn_name: &str) -> Result<Self, Error> {
ffi::create_function(ffi::FunctionSource::OwnModule, "", fn_name)
.map_err(Error::from)
.map(|handle| Self { handle })
}
pub(crate) fn handle(&self) -> ffi::FunctionHandle {
self.handle
}
}
impl Drop for Function {
fn drop(&mut self) {
ffi::remove_function(self.handle).unwrap();
}
}
pub fn blocking_launch(function: &Function, input: &[u8]) -> Result<Vec<u8>, Error> {
let handle = ffi::blocking_launch(function.handle(), input).map_err(Error::from)?;
let ready = ffi::is_ready(handle).map_err(Error::from)?;
assert!(ready.is_ready);
let mut out_buffer = vec![0; ready.size as usize];
ffi::retrieve(handle, &mut out_buffer)?;
Ok(out_buffer)
}
pub fn launch(function: &Function, input: &[u8]) -> impl Future<Output = Result<Vec<u8>, Error>> {
struct LaunchFuture(Result<ffi::RequestHandle, ErrorCode>);
impl Future for LaunchFuture {
type Output = Result<Vec<u8>, Error>;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.0 {
Ok(handle) => match ffi::is_ready(handle) {
Ok(ffi::IsReady {
is_ready: false, ..
}) => Poll::Pending,
Ok(ffi::IsReady {
is_ready: true,
size,
..
}) => {
let mut buffer = vec![0; size as usize];
match ffi::retrieve(handle, &mut buffer) {
Err(err) => Poll::Ready(Err(err.into())),
Ok(()) => Poll::Ready(Ok(buffer)),
}
}
Err(error_code) => Poll::Ready(Err(Error::from(error_code))),
},
Err(error_code) => Poll::Ready(Err(Error::from(error_code))),
}
}
}
LaunchFuture(ffi::launch(function.handle(), input))
}