Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 89d9dcc

Browse files
committed
minor: clippy, names, qol function
1 parent 9b7496b commit 89d9dcc

File tree

9 files changed

+78
-71
lines changed

9 files changed

+78
-71
lines changed

crates/tinywasm/src/coro.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ use crate::Result;
44
// use alloc::boxed::Box;
55
pub(crate) use tinywasm_types::{ResumeArgument, YieldedValue};
66

7+
///"coroutine statse", "coroutine instance", "resumable". Stores info to continue a function that was paused
8+
pub trait CoroState<Ret, ResumeContext>: Debug {
9+
/// resumes the execution of the coroutine
10+
fn resume(&mut self, ctx: ResumeContext, arg: ResumeArgument) -> Result<CoroStateResumeResult<Ret>>;
11+
}
712

813
/// explains why did execution suspend, and carries payload if needed
914
#[derive(Debug)]
@@ -24,7 +29,6 @@ pub enum SuspendReason {
2429
/// async should_suspend flag was set
2530
/// host shouldn't provide resume argument when calling resume
2631
SuspendedFlag,
27-
2832
// possible others: delimited continuations proposal, debugger breakpoint, out of fuel
2933
}
3034

@@ -55,13 +59,19 @@ pub enum CoroStateResumeResult<R> {
5559
}
5660

5761
impl<R, State> PotentialCoroCallResult<R, State> {
62+
63+
/// in case you expect function only to return
64+
/// you can make Suspend into [crate::Error::UnexpectedSuspend] error
65+
pub fn suspend_to_err(self) -> Result<R> {
66+
match self {
67+
PotentialCoroCallResult::Return(r) => Ok(r),
68+
PotentialCoroCallResult::Suspended(r, _) => Err(crate::Error::UnexpectedSuspend(r)),
69+
}
70+
}
71+
5872
/// true if coro is finished
5973
pub fn finished(&self) -> bool {
60-
if let Self::Return(_) = self {
61-
true
62-
} else {
63-
false
64-
}
74+
matches!(self, Self::Return(_))
6575
}
6676
/// separates state from PotentialCoroCallResult, leaving CoroStateResumeResult (one without state)
6777
pub fn split_state(self) -> (CoroStateResumeResult<R>, Option<State>) {
@@ -90,7 +100,7 @@ impl<R, State> PotentialCoroCallResult<R, State> {
90100
self,
91101
user_val: Usr,
92102
mapper: impl FnOnce(R, Usr) -> OutR,
93-
otherwise: impl FnOnce(Usr) -> (),
103+
otherwise: impl FnOnce(Usr),
94104
) -> PotentialCoroCallResult<OutR, State> {
95105
match self {
96106
Self::Return(res) => PotentialCoroCallResult::Return(mapper(res, user_val)),
@@ -109,11 +119,7 @@ impl<R, State> PotentialCoroCallResult<R, State> {
109119
impl<R> CoroStateResumeResult<R> {
110120
/// true if coro is finished
111121
pub fn finished(&self) -> bool {
112-
if let Self::Return(_) = self {
113-
true
114-
} else {
115-
false
116-
}
122+
matches!(self, Self::Return(_))
117123
}
118124
/// separates result from CoroStateResumeResult, leaving unit type in it's place
119125
pub fn split_result(self) -> (CoroStateResumeResult<()>, Option<R>) {
@@ -129,7 +135,7 @@ impl<R> CoroStateResumeResult<R> {
129135
self,
130136
user_val: Usr,
131137
mapper: impl FnOnce(R, Usr) -> OutR,
132-
otherwise: impl FnOnce(Usr) -> (),
138+
otherwise: impl FnOnce(Usr),
133139
) -> CoroStateResumeResult<OutR> {
134140
PotentialCoroCallResult::<R, ()>::from(self).map_result_or_else(user_val, mapper, otherwise).into()
135141
}
@@ -154,9 +160,3 @@ impl<SrcR> From<CoroStateResumeResult<SrcR>> for PotentialCoroCallResult<SrcR, (
154160
}
155161
}
156162
}
157-
158-
///"coroutine statse", "coroutine instance", "resumable". Stores info to continue a function that was paused
159-
pub trait CoroState<Ret, ResumeContext>: Debug {
160-
/// resumes the execution of the coroutine
161-
fn resume(&mut self, ctx: ResumeContext, arg: ResumeArgument) -> Result<CoroStateResumeResult<Ret>>;
162-
}

crates/tinywasm/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub enum Error {
3030
/// The actual value
3131
actual: Vec<tinywasm_types::WasmValue>,
3232
},
33-
33+
3434
/// An invalid label type was encountered
3535
InvalidLabelType,
3636

crates/tinywasm/src/func.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,47 +32,44 @@ impl SuspendedWasmFunc {
3232
}
3333

3434
#[derive(Debug)]
35-
pub(self) enum SuspendFuncInner {
35+
#[allow(clippy::large_enum_variant)] // Wasm is bigger, but also much more common variant
36+
enum SuspendedFuncInner {
3637
Wasm(SuspendedWasmFunc),
3738
Host(SuspendedHostCoroState),
3839
}
3940

4041
/// handle to function that was suspended and can be resumed
4142
#[derive(Debug)]
42-
pub struct SuspendFunc {
43-
func: SuspendFuncInner,
43+
pub struct SuspendedFunc {
44+
func: SuspendedFuncInner,
4445
module_addr: ModuleInstanceAddr,
4546
store_id: usize,
4647
}
4748

48-
impl<'a> crate::coro::CoroState<Vec<WasmValue>, &mut Store> for SuspendFunc {
49+
impl crate::coro::CoroState<Vec<WasmValue>, &mut Store> for SuspendedFunc {
4950
fn resume(&mut self, store: &mut Store, arg: ResumeArgument) -> Result<FuncHandleResumeOutcome> {
5051
if store.id() != self.store_id {
5152
return Err(Error::InvalidStore);
5253
}
5354

5455
let ctx = FuncContext { store, module_addr: self.module_addr };
5556
match &mut self.func {
56-
SuspendFuncInner::Wasm(wasm) => wasm.resume(ctx, arg),
57-
SuspendFuncInner::Host(host) => Ok(host.coro_state.resume(ctx, arg)?),
57+
SuspendedFuncInner::Wasm(wasm) => wasm.resume(ctx, arg),
58+
SuspendedFuncInner::Host(host) => Ok(host.coro_state.resume(ctx, arg)?),
5859
}
5960
}
6061
}
6162

62-
type FuncHandleCallOutcome = crate::coro::PotentialCoroCallResult<Vec<WasmValue>, SuspendFunc>;
63+
type FuncHandleCallOutcome = crate::coro::PotentialCoroCallResult<Vec<WasmValue>, SuspendedFunc>;
6364

6465
impl FuncHandle {
6566
/// Call a function (Invocation)
6667
///
6768
/// See <https://webassembly.github.io/spec/core/exec/modules.html#invocation>
6869
///
69-
7070
#[inline]
7171
pub fn call(&self, store: &mut Store, params: &[WasmValue]) -> Result<Vec<WasmValue>> {
72-
match self.call_coro(store, params)? {
73-
crate::coro::PotentialCoroCallResult::Return(res) => Ok(res),
74-
crate::coro::PotentialCoroCallResult::Suspended(suspend, _state) => Err(Error::UnexpectedSuspend(suspend)),
75-
}
72+
self.call_coro(store, params)?.suspend_to_err()
7673
}
7774

7875
/// Call a function (Invocation) and anticipate possible yield instead as well as return
@@ -110,8 +107,8 @@ impl FuncHandle {
110107
Function::Host(host_func) => {
111108
let host_func = host_func.clone();
112109
let ctx = FuncContext { store, module_addr: self.module_addr };
113-
return Ok(host_func.call(ctx, params)?.map_state(|state| SuspendFunc {
114-
func: SuspendFuncInner::Host(SuspendedHostCoroState {
110+
return Ok(host_func.call(ctx, params)?.map_state(|state| SuspendedFunc {
111+
func: SuspendedFuncInner::Host(SuspendedHostCoroState {
115112
coro_state: state,
116113
coro_orig_function: self.addr,
117114
}),
@@ -133,21 +130,20 @@ impl FuncHandle {
133130
let runtime = store.runtime();
134131
let exec_outcome = runtime.exec(store, stack)?;
135132
Ok(exec_outcome
136-
.map_result(|mut stack| {
133+
.map_result(|mut stack|->Vec<WasmValue> {
137134
// Once the function returns:
138135
// let result_m = func_ty.results.len();
139136

140137
// 1. Assert: m values are on the top of the stack (Ensured by validation)
141138
// assert!(stack.values.len() >= result_m);
142139

143140
// 2. Pop m values from the stack
144-
let res = stack.values.pop_results(&func_ty.results);
141+
stack.values.pop_results(&func_ty.results)
145142
// The values are returned as the results of the invocation.
146-
return res;
147143
})
148-
.map_state(|coro_state| -> SuspendFunc {
149-
SuspendFunc {
150-
func: SuspendFuncInner::Wasm(SuspendedWasmFunc {
144+
.map_state(|coro_state| -> SuspendedFunc {
145+
SuspendedFunc {
146+
func: SuspendedFuncInner::Wasm(SuspendedWasmFunc {
151147
runtime: coro_state,
152148
result_types: func_ty.results.clone(),
153149
}),

crates/tinywasm/src/instance.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use alloc::{boxed::Box, format, rc::Rc, string::ToString};
22
use tinywasm_types::*;
33

44
use crate::func::{FromWasmValueTuple, IntoWasmValueTuple};
5-
use crate::{Error, FuncHandle, FuncHandleTyped, Imports, MemoryRef, MemoryRefMut, Module, PotentialCoroCallResult, Result, Store, SuspendFunc};
5+
use crate::{
6+
Error, FuncHandle, FuncHandleTyped, Imports, MemoryRef, MemoryRefMut, Module, PotentialCoroCallResult, Result,
7+
Store, SuspendedFunc,
8+
};
69

710
/// An instanciated WebAssembly module
811
///
@@ -265,16 +268,16 @@ impl ModuleInstance {
265268
}
266269

267270
/// Invoke the start function of the module
268-
///
271+
///
269272
/// Returns None if the module has no start function
270273
/// If start function suspends, returns SuspededFunc.
271274
/// Only when it finishes can this module instance be considered instantiated
272-
pub fn start_coro(&self, store: &mut Store) -> Result<Option<PotentialCoroCallResult<(), SuspendFunc>>> {
275+
pub fn start_coro(&self, store: &mut Store) -> Result<Option<PotentialCoroCallResult<(), SuspendedFunc>>> {
273276
let Some(func) = self.start_func(store)? else {
274277
return Ok(None);
275278
};
276279

277280
let res = func.call_coro(store, &[])?;
278-
Ok(Some(res.map_result(|_|{()})))
281+
Ok(Some(res.map_result(|_| {})))
279282
}
280283
}

crates/tinywasm/src/interpreter/executor.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
7070
#[inline(always)]
7171
pub(crate) fn resume(&mut self, res_arg: ResumeArgument) -> Result<ExecOutcome> {
7272
if let Some(coro_state) = self.suspended_host_coro.as_mut() {
73-
let ctx = FuncContext { store: &mut self.store, module_addr: self.module.id() };
73+
let ctx = FuncContext { store: self.store, module_addr: self.module.id() };
7474
let host_res = coro_state.coro_state.resume(ctx, res_arg)?;
7575
let res = match host_res {
7676
CoroStateResumeResult::Return(res) => res,
@@ -120,7 +120,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
120120
}
121121

122122
if let Some(mut cb) = self.store.suspend_cond.suspend_cb.take() {
123-
let should_suspend = matches!(cb(&self.store), ControlFlow::Break(()));
123+
let should_suspend = matches!(cb(self.store), ControlFlow::Break(()));
124124
self.store.suspend_cond.suspend_cb = Some(cb); // put it back
125125
if should_suspend {
126126
return ReasonToBreak::Suspended(SuspendReason::SuspendedCallback).into();
@@ -416,20 +416,19 @@ impl<'store, 'stack> Executor<'store, 'stack> {
416416
}
417417
fn exec_call_host(&mut self, host_func: Rc<HostFunction>, func_ref: u32) -> ControlFlow<ReasonToBreak> {
418418
let params = self.stack.values.pop_params(&host_func.ty.params);
419-
let res =
420-
host_func.call(FuncContext { store: self.store, module_addr: self.module.id() }, &params).to_cf()?;
419+
let res = host_func.call(FuncContext { store: self.store, module_addr: self.module.id() }, &params).to_cf()?;
421420
match res {
422421
PotentialCoroCallResult::Return(res) => {
423422
self.stack.values.extend_from_wasmvalues(&res);
424423
self.cf.incr_instr_ptr();
425424
self.check_should_suspend()?; // who knows how long we've spent in host function
426-
return ControlFlow::Continue(());
425+
ControlFlow::Continue(())
427426
}
428427
PotentialCoroCallResult::Suspended(suspend_reason, state) => {
429428
self.suspended_host_coro =
430429
Some(SuspendedHostCoroState { coro_state: state, coro_orig_function: func_ref });
431430
self.cf.incr_instr_ptr();
432-
return ReasonToBreak::Suspended(suspend_reason).into();
431+
ReasonToBreak::Suspended(suspend_reason).into()
433432
}
434433
}
435434
}
@@ -527,10 +526,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
527526
if block_ty.is_none() {
528527
return self.exec_return();
529528
}
530-
529+
531530
self.cf.incr_instr_ptr();
532531

533-
if matches!(block_ty, Some(BlockType::Loop)){
532+
if matches!(block_ty, Some(BlockType::Loop)) {
534533
self.check_should_suspend()?;
535534
}
536535
ControlFlow::Continue(())
@@ -581,7 +580,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
581580

582581
self.cf.incr_instr_ptr();
583582

584-
if matches!(block_ty, Some(BlockType::Loop)){
583+
if matches!(block_ty, Some(BlockType::Loop)) {
585584
self.check_should_suspend()?;
586585
}
587586
ControlFlow::Continue(())

crates/tinywasm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub(crate) mod log {
9393
mod error;
9494
pub use coro::{CoroState, CoroStateResumeResult, PotentialCoroCallResult, SuspendReason};
9595
pub use error::*;
96-
pub use func::{FuncHandle, FuncHandleTyped, SuspendFunc};
96+
pub use func::{FuncHandle, FuncHandleTyped, SuspendedFunc};
9797
pub use imports::*;
9898
pub use instance::ModuleInstance;
9999
pub use module::{IncompleteModule, Module};

crates/tinywasm/src/module.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{CoroState, Imports, ModuleInstance, PotentialCoroCallResult, Result, Store, SuspendFunc};
1+
use crate::{CoroState, Imports, ModuleInstance, PotentialCoroCallResult, Result, Store, SuspendedFunc};
22
use tinywasm_types::{ResumeArgument, TinyWasmModule};
33

44
/// A WebAssembly Module
@@ -69,15 +69,12 @@ impl Module {
6969
Some(res) => res,
7070
None => return Ok(PotentialCoroCallResult::Return(instance)),
7171
};
72-
match core_res {
73-
crate::PotentialCoroCallResult::Return(_) => return Ok(PotentialCoroCallResult::Return(instance)),
72+
Ok(match core_res {
73+
crate::PotentialCoroCallResult::Return(_) => PotentialCoroCallResult::Return(instance),
7474
crate::PotentialCoroCallResult::Suspended(suspend_reason, state) => {
75-
return Ok(PotentialCoroCallResult::Suspended(
76-
suspend_reason,
77-
IncompleteModule(Some(HitTheFloor(instance, state))),
78-
))
75+
PotentialCoroCallResult::Suspended(suspend_reason, IncompleteModule(Some(HitTheFloor(instance, state))))
7976
}
80-
}
77+
})
8178
}
8279
}
8380

@@ -86,9 +83,9 @@ impl Module {
8683
pub struct IncompleteModule(Option<HitTheFloor>);
8784

8885
#[derive(Debug)]
89-
struct HitTheFloor(ModuleInstance, SuspendFunc);
86+
struct HitTheFloor(ModuleInstance, SuspendedFunc);
9087

91-
impl<'a> CoroState<ModuleInstance, &'a mut Store> for IncompleteModule {
88+
impl CoroState<ModuleInstance, &mut Store> for IncompleteModule {
9289
fn resume(&mut self, ctx: &mut Store, arg: ResumeArgument) -> Result<crate::CoroStateResumeResult<ModuleInstance>> {
9390
let mut body: HitTheFloor = match self.0.take() {
9491
Some(body) => body,

crates/tinywasm/src/store/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,13 @@ fn get_pair_mut<T>(slice: &mut [T], i: usize, j: usize) -> Option<(&mut T, &mut
486486
Some(pair)
487487
}
488488

489+
/// user callback for use in [SuspendConditions::suspend_cb]
490+
pub type ShouldSuspendCb = Box<dyn FnMut(&Store) -> ControlFlow<(), ()>>;
491+
489492
// idk where really to put it, but it should be accessible to host environment (obviously)
490-
// and, less obviously, to host functions called from it, for calling wasm callbacks and propagating this config to them
491-
// or just complying with suspend conditions
492-
/// used to limit when how much cpu time wasm code should take
493+
// and (less obviously) to host functions called from it - for calling wasm callbacks and propagating this config to them
494+
// (or just complying with suspend conditions themselves)
495+
/// used to limit execution time wasm code takes
493496
#[derive(Default)]
494497
pub struct SuspendConditions {
495498
/// atomic flag. when set to true it means execution should suspend
@@ -499,13 +502,14 @@ pub struct SuspendConditions {
499502
/// instant at which execution should suspend
500503
/// can be used to control how much time will be spent in wasm without requiring other threads
501504
/// such as for time-slice multitasking
505+
/// uses rust standard library for checking time - so not available in no-std
502506
#[cfg(feature = "std")]
503507
pub timeout_instant: Option<crate::std::time::Instant>,
504508

505509
/// callback that returns [`ControlFlow::Break`]` when execution should suspend
506510
/// can be used when above methods are insufficient or
507-
/// instead of [`timeout_instant`] in no-std builds if you have a clock function
508-
pub suspend_cb: Option<Box<dyn FnMut(&Store) -> ControlFlow<(), ()>>>,
511+
/// instead of [`timeout_instant`] in no-std builds, if you have your own clock function
512+
pub suspend_cb: Option<ShouldSuspendCb>,
509513
}
510514

511515
impl Debug for SuspendConditions {
@@ -521,6 +525,14 @@ impl Debug for SuspendConditions {
521525
}
522526
}
523527

528+
impl SuspendConditions {
529+
/// sets timeout_instant to `how_long` from now
530+
#[cfg(feature = "std")]
531+
pub fn set_timeout_in(&mut self, how_long: crate::std::time::Duration) {
532+
self.timeout_instant = Some(crate::std::time::Instant::now() + how_long);
533+
}
534+
}
535+
524536
impl Store {
525537
/// sets suspend conditions for store
526538
pub fn set_suspend_conditions(&mut self, val: SuspendConditions) {
@@ -532,7 +544,7 @@ impl Store {
532544
}
533545
/// transforms suspend conditions for store using user-provided function
534546
pub fn update_suspend_conditions(&mut self, replacer: impl FnOnce(SuspendConditions) -> SuspendConditions) {
535-
let temp = core::mem::replace(&mut self.suspend_cond, SuspendConditions::default());
547+
let temp = core::mem::take(&mut self.suspend_cond);
536548
self.suspend_cond = replacer(temp);
537549
}
538550
}

tests/wasm_resume.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ fn overflow_detect_snippet(var: &str) -> String {
330330
struct TestedModule {
331331
store: Store,
332332
instance: ModuleInstance,
333-
resumable: Option<tinywasm::SuspendFunc>,
333+
resumable: Option<tinywasm::SuspendedFunc>,
334334
}
335335

336336
impl TestedModule {

0 commit comments

Comments
 (0)