|
1 | | -use crate::{Imports, ModuleInstance, Result, Store}; |
2 | | -use tinywasm_types::TinyWasmModule; |
| 1 | +use crate::{CoroState, Imports, ModuleInstance, PotentialCoroCallResult, Result, Store, SuspendFunc}; |
| 2 | +use tinywasm_types::{ResumeArgument, TinyWasmModule}; |
3 | 3 |
|
4 | 4 | /// A WebAssembly Module |
5 | 5 | /// |
@@ -56,4 +56,60 @@ impl Module { |
56 | 56 | let _ = instance.start(store)?; |
57 | 57 | Ok(instance) |
58 | 58 | } |
| 59 | + |
| 60 | + /// same as [Self::instantiate] but accounts for possibility of start function suspending, in which case it returns |
| 61 | + /// [PotentialCoroCallResult::Suspended]. You can call [CoroState::resume] on it at any time to resume instantiation |
| 62 | + pub fn instantiate_coro( |
| 63 | + self, |
| 64 | + store: &mut Store, |
| 65 | + imports: Option<Imports>, |
| 66 | + ) -> Result<PotentialCoroCallResult<ModuleInstance, IncompleteModule>> { |
| 67 | + let instance = ModuleInstance::instantiate(store, self, imports)?; |
| 68 | + let core_res = match instance.start_coro(store)? { |
| 69 | + Some(res) => res, |
| 70 | + None => return Ok(PotentialCoroCallResult::Return(instance)), |
| 71 | + }; |
| 72 | + match core_res { |
| 73 | + crate::PotentialCoroCallResult::Return(_) => return Ok(PotentialCoroCallResult::Return(instance)), |
| 74 | + crate::PotentialCoroCallResult::Suspended(suspend_reason, state) => { |
| 75 | + return Ok(PotentialCoroCallResult::Suspended( |
| 76 | + suspend_reason, |
| 77 | + IncompleteModule(Some(HitTheFloor(instance, state))), |
| 78 | + )) |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +/// a corostate that results in [ModuleInstance] when finished |
| 85 | +#[derive(Debug)] |
| 86 | +pub struct IncompleteModule(Option<HitTheFloor>); |
| 87 | + |
| 88 | +#[derive(Debug)] |
| 89 | +struct HitTheFloor(ModuleInstance, SuspendFunc); |
| 90 | + |
| 91 | +impl<'a> CoroState<ModuleInstance, &'a mut Store> for IncompleteModule { |
| 92 | + fn resume(&mut self, ctx: &mut Store, arg: ResumeArgument) -> Result<crate::CoroStateResumeResult<ModuleInstance>> { |
| 93 | + let mut body: HitTheFloor = match self.0.take() { |
| 94 | + Some(body) => body, |
| 95 | + None => return Err(crate::Error::InvalidResume), |
| 96 | + }; |
| 97 | + let coro_res = match body.1.resume(ctx, arg) { |
| 98 | + Ok(res) => res, |
| 99 | + Err(e) => { |
| 100 | + self.0 = Some(body); |
| 101 | + return Err(e); |
| 102 | + } |
| 103 | + }; |
| 104 | + match coro_res { |
| 105 | + crate::CoroStateResumeResult::Return(_) => { |
| 106 | + let res = body.0; |
| 107 | + Ok(crate::CoroStateResumeResult::Return(res)) |
| 108 | + } |
| 109 | + crate::CoroStateResumeResult::Suspended(suspend_reason) => { |
| 110 | + self.0 = Some(body); // ...once told me |
| 111 | + Ok(crate::CoroStateResumeResult::Suspended(suspend_reason)) |
| 112 | + } |
| 113 | + } |
| 114 | + } |
59 | 115 | } |
0 commit comments