numbat_wasm/io/
dyn_arg.rs

1use crate::*;
2use numbat_codec::*;
3
4/// Any type that is used as an endpoint argument must implement this trait.
5pub trait DynArg<I, D>: Sized
6where
7	I: TopDecodeInput,
8	D: DynArgInput<I>,
9{
10	fn dyn_load(loader: &mut D, arg_id: ArgId) -> Self;
11}
12
13/// Used for loading arguments annotated with `#[multi(...)]`.
14pub trait DynArgMulti<I, D>: DynArg<I, D>
15where
16	I: TopDecodeInput,
17	D: DynArgInput<I>,
18{
19	fn dyn_load_multi(loader: &mut D, arg_id: ArgId, num: usize) -> Self;
20}
21
22/// All top-deserializable types can be endpoint arguments.
23impl<I, D, T> DynArg<I, D> for T
24where
25	I: TopDecodeInput,
26	D: DynArgInput<I>,
27	T: TopDecode,
28{
29	fn dyn_load(loader: &mut D, arg_id: ArgId) -> Self {
30		if let TypeInfo::Unit = T::TYPE_INFO {
31			// unit type returns without loading anything
32			let cast_unit: T = unsafe { core::mem::transmute_copy(&()) };
33			return cast_unit;
34		}
35
36		let arg_input = loader.next_arg_input();
37		T::top_decode_or_exit(arg_input, &(&*loader, arg_id), dyn_load_exit)
38	}
39}
40
41#[inline(always)]
42fn dyn_load_exit<I, D>(ctx: &(&D, ArgId), de_err: DecodeError) -> !
43where
44	I: TopDecodeInput,
45	D: DynArgInput<I>,
46{
47	let (loader, arg_id) = ctx;
48	loader.signal_arg_de_error(*arg_id, de_err)
49}