wapc/wapchost/
host_async.rs1use std::sync::{atomic::Ordering, Arc};
2
3use tokio::sync::Mutex;
4
5use crate::{
6 wapchost::{
7 errors, modulestate_async::ModuleStateAsync, traits::WebAssemblyEngineProviderAsync, Invocation, Result,
8 GLOBAL_MODULE_COUNT,
9 },
10 HostCallbackAsync,
11};
12
13#[must_use]
20pub struct WapcHostAsync {
21 engine: Mutex<Box<dyn WebAssemblyEngineProviderAsync + Send>>,
22 state: Arc<ModuleStateAsync>,
23}
24
25impl std::fmt::Debug for WapcHostAsync {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_struct("WapcHostAsync").field("state", &self.state).finish()
28 }
29}
30
31impl WapcHostAsync {
32 pub async fn new(
35 engine: Box<dyn WebAssemblyEngineProviderAsync + Send>,
36 host_callback: Option<Box<HostCallbackAsync>>,
37 ) -> Result<Self> {
38 let id = GLOBAL_MODULE_COUNT.fetch_add(1, Ordering::SeqCst);
39
40 let state = Arc::new(ModuleStateAsync::new(host_callback, id));
41
42 let mh = WapcHostAsync {
43 engine: Mutex::new(engine),
44 state: state.clone(),
45 };
46
47 mh.initialize(state).await?;
48
49 Ok(mh)
50 }
51
52 async fn initialize(&self, state: Arc<ModuleStateAsync>) -> Result<()> {
53 match self.engine.lock().await.init(state).await {
54 Ok(_) => Ok(()),
55 Err(e) => Err(errors::Error::InitFailed(e.to_string())),
56 }
57 }
58
59 pub fn id(&self) -> u64 {
63 self.state.id
64 }
65
66 pub async fn call(&self, op: &str, payload: &[u8]) -> Result<Vec<u8>> {
74 let inv = Invocation::new(op, payload.to_vec());
75 let op_len = inv.operation.len();
76 let msg_len = inv.msg.len();
77
78 {
79 *self.state.guest_response.write().await = None;
80 *self.state.guest_request.write().await = Some(inv);
81 *self.state.guest_error.write().await = None;
82 *self.state.host_response.write().await = None;
83 *self.state.host_error.write().await = None;
84 }
85
86 let callresult = match self.engine.lock().await.call(op_len as i32, msg_len as i32).await {
87 Ok(c) => c,
88 Err(e) => {
89 return Err(errors::Error::GuestCallFailure(e.to_string()));
90 }
91 };
92
93 if callresult == 0 {
94 let lock = self.state.guest_error.read().await;
96 lock.as_ref().map_or_else(
97 || {
98 Err(errors::Error::GuestCallFailure(
99 "No error message set for call failure".to_owned(),
100 ))
101 },
102 |s| Err(errors::Error::GuestCallFailure(s.clone())),
103 )
104 } else {
105 match self.state.guest_response.read().await.as_ref() {
107 Some(r) => Ok(r.clone()),
108 None => {
109 let lock = self.state.guest_error.read().await;
110 lock.as_ref().map_or_else(
111 || {
112 Err(errors::Error::GuestCallFailure(
113 "No error message OR response set for call success".to_owned(),
114 ))
115 },
116 |s| Err(errors::Error::GuestCallFailure(s.clone())),
117 )
118 }
119 }
120 }
121 }
122
123 pub async fn replace_module(&self, module: &[u8]) -> Result<()> {
134 match self.engine.lock().await.replace(module).await {
135 Ok(_) => Ok(()),
136 Err(e) => Err(errors::Error::ReplacementFailed(e.to_string())),
137 }
138 }
139}