wasm_component_layer/
func.rs

1use std::marker::*;
2use std::mem::*;
3use std::sync::atomic::*;
4use std::sync::*;
5use std::usize;
6
7use bytemuck::*;
8use wasm_runtime_layer::*;
9#[allow(unused_imports)]
10use wasmtime_environ::component::StringEncoding;
11
12#[allow(unused_imports)]
13use crate::abi::{Generator, *};
14use crate::types::{FuncType, ValueType};
15use crate::values::Value;
16use crate::{AsContext, AsContextMut, StoreContextMut, *};
17
18/// Stores the backing implementation for a function.
19#[derive(Clone, Debug)]
20pub(crate) enum FuncImpl {
21    /// A function backed by a guest implementation.
22    GuestFunc(Option<crate::Instance>, Arc<GuestFunc>),
23    /// A host-provided function.
24    HostFunc(Arc<AtomicUsize>),
25}
26
27/// Stores the data necessary to call a guest function.
28#[derive(Debug)]
29pub(crate) struct GuestFunc {
30    /// The core function to call.
31    pub callee: wasm_runtime_layer::Func,
32    /// The component for this function.
33    pub component: Arc<ComponentInner>,
34    /// The string encoding to use.
35    pub encoding: StringEncoding,
36    /// The function definition to use.
37    pub function: Function,
38    /// The memory to use.
39    pub memory: Option<Memory>,
40    /// The reallocation function to use.
41    pub realloc: Option<wasm_runtime_layer::Func>,
42    /// The post-return function to use.
43    pub post_return: Option<wasm_runtime_layer::Func>,
44    /// The state table to use.
45    pub state_table: Arc<StateTable>,
46    /// The types to use.
47    pub types: Arc<[crate::types::ValueType]>,
48    /// The instance ID to use.
49    pub instance_id: u64,
50    /// The ID of the interface associated with this function.
51    pub interface_id: Option<InterfaceIdentifier>,
52}
53
54/// A component model function that may be invoked to interact with an `Instance`.
55#[derive(Clone, Debug)]
56pub struct Func {
57    /// The store ID associated with this function.
58    pub(crate) store_id: u64,
59    /// The type of this function.
60    pub(crate) ty: FuncType,
61    /// The backing implementation for this function.
62    pub(crate) backing: FuncImpl,
63}
64
65impl Func {
66    /// Creates a new function with the provided type and arguments.
67    pub fn new<C: AsContextMut>(
68        mut ctx: C,
69        ty: FuncType,
70        f: impl 'static
71            + Send
72            + Sync
73            + Fn(StoreContextMut<C::UserState, C::Engine>, &[Value], &mut [Value]) -> Result<()>,
74    ) -> Self {
75        let mut ctx_mut = ctx.as_context_mut();
76        let data = ctx_mut.inner.data_mut();
77        let idx = data.host_functions.push(f);
78
79        Self {
80            store_id: data.id,
81            ty,
82            backing: FuncImpl::HostFunc(idx),
83        }
84    }
85
86    /// Calls this function, returning an error if:
87    ///
88    /// - The store did not match the original.
89    /// - The arguments or results did not match the signature.
90    /// - A trap occurred.
91    pub fn call<C: AsContextMut>(
92        &self,
93        mut ctx: C,
94        arguments: &[Value],
95        results: &mut [Value],
96    ) -> Result<()> {
97        if ctx.as_context().inner.data().id != self.store_id {
98            panic!("Attempted to call function with incorrect store.");
99        }
100
101        self.ty.match_params(arguments)?;
102
103        if self.ty.results().len() != results.len() {
104            bail!("Incorrect result length.");
105        }
106
107        match &self.backing {
108            FuncImpl::GuestFunc(i, x) => {
109                let GuestFunc {
110                    callee,
111                    component,
112                    encoding,
113                    function,
114                    memory,
115                    realloc,
116                    state_table,
117                    post_return,
118                    types,
119                    instance_id,
120                    interface_id,
121                } = &**x;
122
123                ensure!(
124                    !state_table.dropped.load(Ordering::Acquire),
125                    "Instance had been dropped."
126                );
127
128                let mut bindgen = FuncBindgen {
129                    ctx,
130                    flat_results: Vec::default(),
131                    arguments,
132                    results,
133                    callee_interface: None,
134                    callee_wasm: Some(callee),
135                    component,
136                    encoding,
137                    memory,
138                    realloc,
139                    resource_tables: &state_table.resource_tables,
140                    post_return,
141                    types,
142                    handles_to_drop: Vec::new(),
143                    required_dropped: Vec::new(),
144                    instance_id: *instance_id,
145                    store_id: self.store_id,
146                };
147
148                Ok(Generator::new(
149                    &component.resolve,
150                    AbiVariant::GuestExport,
151                    LiftLower::LowerArgsLiftResults,
152                    &mut bindgen,
153                )
154                .call(function)
155                .map_err(|error| FuncError {
156                    name: function.name.clone(),
157                    interface: interface_id.clone(),
158                    instance: i.as_ref().expect("No instance available.").clone(),
159                    error,
160                })?)
161            }
162            FuncImpl::HostFunc(idx) => {
163                let callee = ctx.as_context().inner.data().host_functions.get(idx);
164                (callee)(ctx.as_context_mut(), arguments, results)?;
165                self.ty.match_results(results)
166            }
167        }
168    }
169
170    /// Gets the type of this value.
171    pub fn ty(&self) -> FuncType {
172        self.ty.clone()
173    }
174
175    /// Converts this function to a [`TypedFunc`], failing if the signatures do not match.
176    pub fn typed<P: ComponentList, R: ComponentList>(&self) -> Result<TypedFunc<P, R>> {
177        let mut params_results = vec![ValueType::Bool; P::LEN + R::LEN];
178        P::into_tys(&mut params_results[..P::LEN]);
179        R::into_tys(&mut params_results[P::LEN..]);
180        ensure!(
181            &params_results[..P::LEN] == self.ty.params(),
182            "Parameters did not match function signature. Expected {:?} but got {:?}",
183            self.ty.params(),
184            &params_results[..P::LEN]
185        );
186        ensure!(
187            &params_results[P::LEN..] == self.ty.results(),
188            "Results did not match function signature. Expected {:?} but got {:?}",
189            self.ty.results(),
190            &params_results[P::LEN..]
191        );
192        Ok(TypedFunc {
193            inner: self.clone(),
194            data: PhantomData,
195        })
196    }
197
198    /// Ties the given instance to this function.
199    pub(crate) fn instantiate(&self, inst: crate::Instance) -> Self {
200        if let FuncImpl::GuestFunc(None, y) = &self.backing {
201            Self {
202                store_id: self.store_id,
203                backing: FuncImpl::GuestFunc(Some(inst), y.clone()),
204                ty: self.ty.clone(),
205            }
206        } else {
207            panic!("Function was not an uninitialized guest function.");
208        }
209    }
210
211    /// Calls this function from a guest context.
212    pub(crate) fn call_from_guest<C: AsContextMut>(
213        &self,
214        ctx: C,
215        options: &GuestInvokeOptions,
216        arguments: &[wasm_runtime_layer::Value],
217        results: &mut [wasm_runtime_layer::Value],
218    ) -> Result<()> {
219        ensure!(
220            self.store_id == options.store_id,
221            "Function stores did not match."
222        );
223
224        let args = arguments
225            .iter()
226            .map(TryFrom::try_from)
227            .collect::<Result<Vec<_>>>()?;
228        let mut res = vec![Value::Bool(false); results.len()];
229
230        let mut bindgen = FuncBindgen {
231            ctx,
232            flat_results: Vec::default(),
233            arguments: &args,
234            results: &mut res,
235            callee_interface: Some(self),
236            callee_wasm: None,
237            component: &options.component,
238            encoding: &options.encoding,
239            memory: &options.memory,
240            realloc: &options.realloc,
241            resource_tables: &options.state_table.resource_tables,
242            post_return: &options.post_return,
243            types: &options.types,
244            handles_to_drop: Vec::new(),
245            required_dropped: Vec::new(),
246            instance_id: options.instance_id,
247            store_id: self.store_id,
248        };
249
250        Generator::new(
251            &options.component.resolve,
252            AbiVariant::GuestImport,
253            LiftLower::LiftArgsLowerResults,
254            &mut bindgen,
255        )
256        .call(&options.function)?;
257
258        for (idx, val) in res.into_iter().enumerate() {
259            results[idx] = (&val).try_into()?;
260        }
261
262        Ok(())
263    }
264}
265
266/// Describes options to invoke an imported function from a guest.
267pub(crate) struct GuestInvokeOptions {
268    /// The component to use.
269    pub component: Arc<ComponentInner>,
270    /// The string encoding to use.
271    pub encoding: StringEncoding,
272    /// The function definition to use.
273    pub function: Function,
274    /// The memory to use.
275    pub memory: Option<Memory>,
276    /// The reallocation function to use.
277    pub realloc: Option<wasm_runtime_layer::Func>,
278    /// The post-return function to use.
279    pub post_return: Option<wasm_runtime_layer::Func>,
280    /// The resource tables to use.
281    pub state_table: Arc<StateTable>,
282    /// The types to use.
283    pub types: Arc<[crate::types::ValueType]>,
284    /// The instance ID to use.
285    pub instance_id: u64,
286    /// The store ID to use.
287    pub store_id: u64,
288}
289
290/// Manages the invocation of a component model function with the canonical ABI.
291struct FuncBindgen<'a, C: AsContextMut> {
292    /// The interface function to call.
293    pub callee_interface: Option<&'a Func>,
294    /// The core WASM function to call.
295    pub callee_wasm: Option<&'a wasm_runtime_layer::Func>,
296    /// The component to use.
297    pub component: &'a ComponentInner,
298    /// The context.
299    pub ctx: C,
300    /// The encoding to use.
301    pub encoding: &'a StringEncoding,
302    /// The list of flat results.
303    pub flat_results: Vec<wasm_runtime_layer::Value>,
304    /// The memory to use.
305    pub memory: &'a Option<Memory>,
306    /// The reallocation function to use.
307    pub realloc: &'a Option<wasm_runtime_layer::Func>,
308    /// The post-return function to use.
309    pub post_return: &'a Option<wasm_runtime_layer::Func>,
310    /// The arguments to use.
311    pub arguments: &'a [Value],
312    /// The results to use.
313    pub results: &'a mut [Value],
314    /// The resource tables to use.
315    pub resource_tables: &'a Mutex<Vec<HandleTable>>,
316    /// The types to use.
317    pub types: &'a [crate::types::ValueType],
318    /// The handles to drop at the call's end.
319    pub handles_to_drop: Vec<(u32, i32)>,
320    /// The handles to require dropped at the call's end.
321    pub required_dropped: Vec<(bool, u32, i32, Arc<AtomicBool>)>,
322    /// The instance ID to use.
323    pub instance_id: u64,
324    /// The store ID to use.
325    pub store_id: u64,
326}
327
328impl<'a, C: AsContextMut> FuncBindgen<'a, C> {
329    /// Loads a type from the given offset in guest memory.
330    fn load<B: Blittable>(&self, offset: usize) -> Result<B> {
331        Ok(B::from_bytes(<B::Array as ByteArray>::load(
332            &self.ctx,
333            self.memory.as_ref().expect("No memory."),
334            offset,
335        )?))
336    }
337
338    /// Stores a type to the given offset in guest memory.
339    fn store<B: Blittable>(&mut self, offset: usize, value: B) -> Result<()> {
340        value.to_bytes().store(
341            &mut self.ctx,
342            self.memory.as_ref().expect("No memory."),
343            offset,
344        )
345    }
346
347    /// Loads a list of types from the given offset in guest memory.
348    fn load_array<B: Blittable>(&self, offset: usize, len: usize) -> Result<Arc<[B]>> {
349        let mut raw_memory = B::zeroed_array(len);
350        self.memory.as_ref().expect("No memory").read(
351            self.ctx.as_context().inner,
352            offset,
353            B::to_le_slice_mut(
354                Arc::get_mut(&mut raw_memory).expect("Could not get exclusive reference."),
355            ),
356        )?;
357        Ok(raw_memory)
358    }
359
360    /// Stores a list of types to the given offset in guest memory.
361    fn store_array<B: Blittable>(&mut self, offset: usize, value: &[B]) -> Result<()> {
362        self.memory.as_ref().expect("No memory.").write(
363            self.ctx.as_context_mut().inner,
364            offset,
365            B::to_le_slice(value),
366        )
367    }
368}
369
370impl<'a, C: AsContextMut> Bindgen for FuncBindgen<'a, C> {
371    type Operand = Value;
372
373    fn emit(
374        &mut self,
375        _resolve: &Resolve,
376        inst: &Instruction<'_>,
377        operands: &mut Vec<Self::Operand>,
378        results: &mut Vec<Self::Operand>,
379    ) -> Result<()> {
380        match inst {
381            Instruction::GetArg { nth } => results.push(
382                self.arguments
383                    .get(*nth)
384                    .cloned()
385                    .ok_or_else(|| Error::msg("Invalid argument count."))?,
386            ),
387            Instruction::I32Const { val } => results.push(Value::S32(*val)),
388            Instruction::Bitcasts { casts } => {
389                for (cast, op) in casts.iter().zip(operands) {
390                    match cast {
391                        Bitcast::I32ToF32 => require_matches!(
392                            op,
393                            Value::S32(x),
394                            results.push(Value::F32(f32::from_bits(*x as u32)))
395                        ),
396                        Bitcast::F32ToI32 => require_matches!(
397                            op,
398                            Value::F32(x),
399                            results.push(Value::S32(x.to_bits() as i32))
400                        ),
401                        Bitcast::I64ToF64 => require_matches!(
402                            op,
403                            Value::S64(x),
404                            results.push(Value::F64(f64::from_bits(*x as u64)))
405                        ),
406                        Bitcast::F64ToI64 => require_matches!(
407                            op,
408                            Value::F64(x),
409                            results.push(Value::S64(x.to_bits() as i64))
410                        ),
411                        Bitcast::I32ToI64 => {
412                            require_matches!(op, Value::S32(x), results.push(Value::S64(*x as i64)))
413                        }
414                        Bitcast::I64ToI32 => {
415                            require_matches!(op, Value::S64(x), results.push(Value::S32(*x as i32)))
416                        }
417                        Bitcast::I64ToF32 => {
418                            require_matches!(op, Value::S64(x), results.push(Value::F32(*x as f32)))
419                        }
420                        Bitcast::F32ToI64 => {
421                            require_matches!(op, Value::F32(x), results.push(Value::S64(*x as i64)))
422                        }
423                        Bitcast::None => results.push(op.clone()),
424                    }
425                }
426            }
427            Instruction::ConstZero { tys } => {
428                for t in tys.iter() {
429                    match t {
430                        WasmType::I32 => results.push(Value::S32(0)),
431                        WasmType::I64 => results.push(Value::S64(0)),
432                        WasmType::F32 => results.push(Value::F32(0.0)),
433                        WasmType::F64 => results.push(Value::F64(0.0)),
434                    }
435                }
436            }
437            Instruction::I32Load { offset } => require_matches!(
438                operands.pop(),
439                Some(Value::S32(x)),
440                results.push(Value::S32(self.load((x as usize) + (*offset as usize))?))
441            ),
442            Instruction::I32Load8U { offset } => require_matches!(
443                operands.pop(),
444                Some(Value::S32(x)),
445                results.push(Value::S32(
446                    self.load::<u8>((x as usize) + (*offset as usize))? as i32
447                ))
448            ),
449            Instruction::I32Load8S { offset } => require_matches!(
450                operands.pop(),
451                Some(Value::S32(x)),
452                results.push(Value::S32(
453                    self.load::<i8>((x as usize) + (*offset as usize))? as i32
454                ))
455            ),
456            Instruction::I32Load16U { offset } => require_matches!(
457                operands.pop(),
458                Some(Value::S32(x)),
459                results.push(Value::S32(
460                    self.load::<u16>((x as usize) + (*offset as usize))? as i32
461                ))
462            ),
463            Instruction::I32Load16S { offset } => require_matches!(
464                operands.pop(),
465                Some(Value::S32(x)),
466                results.push(Value::S32(
467                    self.load::<i16>((x as usize) + (*offset as usize))? as i32
468                ))
469            ),
470            Instruction::I64Load { offset } => require_matches!(
471                operands.pop(),
472                Some(Value::S32(x)),
473                results.push(Value::S64(self.load((x as usize) + (*offset as usize))?))
474            ),
475            Instruction::F32Load { offset } => require_matches!(
476                operands.pop(),
477                Some(Value::S32(x)),
478                results.push(Value::F32(self.load((x as usize) + (*offset as usize))?))
479            ),
480            Instruction::F64Load { offset } => require_matches!(
481                operands.pop(),
482                Some(Value::S32(x)),
483                results.push(Value::F64(self.load((x as usize) + (*offset as usize))?))
484            ),
485            Instruction::I32Store { offset } => require_matches!(
486                operands.pop(),
487                Some(Value::S32(address)),
488                require_matches!(
489                    operands.pop(),
490                    Some(Value::S32(x)),
491                    self.store((address as usize) + (*offset as usize), x)?
492                )
493            ),
494            Instruction::I32Store8 { offset } => require_matches!(
495                operands.pop(),
496                Some(Value::S32(address)),
497                require_matches!(
498                    operands.pop(),
499                    Some(Value::S32(x)),
500                    self.store((address as usize) + (*offset as usize), x as u8)?
501                )
502            ),
503            Instruction::I32Store16 { offset } => require_matches!(
504                operands.pop(),
505                Some(Value::S32(address)),
506                require_matches!(
507                    operands.pop(),
508                    Some(Value::S32(x)),
509                    self.store((address as usize) + (*offset as usize), x as u16)?
510                )
511            ),
512            Instruction::I64Store { offset } => require_matches!(
513                operands.pop(),
514                Some(Value::S32(address)),
515                require_matches!(
516                    operands.pop(),
517                    Some(Value::S64(x)),
518                    self.store((address as usize) + (*offset as usize), x)?
519                )
520            ),
521            Instruction::F32Store { offset } => require_matches!(
522                operands.pop(),
523                Some(Value::S32(address)),
524                require_matches!(
525                    operands.pop(),
526                    Some(Value::F32(x)),
527                    self.store((address as usize) + (*offset as usize), x)?
528                )
529            ),
530            Instruction::F64Store { offset } => require_matches!(
531                operands.pop(),
532                Some(Value::S32(address)),
533                require_matches!(
534                    operands.pop(),
535                    Some(Value::F64(x)),
536                    self.store((address as usize) + (*offset as usize), x)?
537                )
538            ),
539            Instruction::I32FromChar => require_matches!(
540                operands.pop(),
541                Some(Value::Char(x)),
542                results.push(Value::S32(x as i32))
543            ),
544            Instruction::I64FromU64 => require_matches!(
545                operands.pop(),
546                Some(Value::U64(x)),
547                results.push(Value::S64(x as i64))
548            ),
549            Instruction::I64FromS64 => require_matches!(
550                operands.pop(),
551                Some(Value::S64(x)),
552                results.push(Value::S64(x))
553            ),
554            Instruction::I32FromU32 => require_matches!(
555                operands.pop(),
556                Some(Value::U32(x)),
557                results.push(Value::S32(x as i32))
558            ),
559            Instruction::I32FromS32 => require_matches!(
560                operands.pop(),
561                Some(Value::S32(x)),
562                results.push(Value::S32(x))
563            ),
564            Instruction::I32FromU16 => require_matches!(
565                operands.pop(),
566                Some(Value::U16(x)),
567                results.push(Value::S32(x as i32))
568            ),
569            Instruction::I32FromS16 => require_matches!(
570                operands.pop(),
571                Some(Value::S16(x)),
572                results.push(Value::S32(x as i32))
573            ),
574            Instruction::I32FromU8 => require_matches!(
575                operands.pop(),
576                Some(Value::U8(x)),
577                results.push(Value::S32(x as i32))
578            ),
579            Instruction::I32FromS8 => require_matches!(
580                operands.pop(),
581                Some(Value::S8(x)),
582                results.push(Value::S32(x as i32))
583            ),
584            Instruction::F32FromFloat32 => require_matches!(
585                operands.pop(),
586                Some(Value::F32(x)),
587                results.push(Value::F32(x))
588            ),
589            Instruction::F64FromFloat64 => require_matches!(
590                operands.pop(),
591                Some(Value::F64(x)),
592                results.push(Value::F64(x))
593            ),
594            Instruction::S8FromI32 => require_matches!(
595                operands.pop(),
596                Some(Value::S32(x)),
597                results.push(Value::S8(x as i8))
598            ),
599            Instruction::U8FromI32 => require_matches!(
600                operands.pop(),
601                Some(Value::S32(x)),
602                results.push(Value::U8(x as u8))
603            ),
604            Instruction::S16FromI32 => require_matches!(
605                operands.pop(),
606                Some(Value::S32(x)),
607                results.push(Value::S16(x as i16))
608            ),
609            Instruction::U16FromI32 => require_matches!(
610                operands.pop(),
611                Some(Value::S32(x)),
612                results.push(Value::U16(x as u16))
613            ),
614            Instruction::S32FromI32 => require_matches!(
615                operands.pop(),
616                Some(Value::S32(x)),
617                results.push(Value::S32(x))
618            ),
619            Instruction::U32FromI32 => require_matches!(
620                operands.pop(),
621                Some(Value::S32(x)),
622                results.push(Value::U32(x as u32))
623            ),
624            Instruction::S64FromI64 => require_matches!(
625                operands.pop(),
626                Some(Value::S64(x)),
627                results.push(Value::S64(x))
628            ),
629            Instruction::U64FromI64 => require_matches!(
630                operands.pop(),
631                Some(Value::S64(x)),
632                results.push(Value::U64(x as u64))
633            ),
634            Instruction::CharFromI32 => require_matches!(
635                operands.pop(),
636                Some(Value::S32(x)),
637                results.push(Value::Char(char::from_u32(x as u32).ok_or_else(|| {
638                    Error::msg("Could not convert integer to char.")
639                })?))
640            ),
641            Instruction::Float32FromF32 => require_matches!(
642                operands.pop(),
643                Some(Value::F32(x)),
644                results.push(Value::F32(x))
645            ),
646            Instruction::Float64FromF64 => require_matches!(
647                operands.pop(),
648                Some(Value::F64(x)),
649                results.push(Value::F64(x))
650            ),
651            Instruction::BoolFromI32 => require_matches!(
652                operands.pop(),
653                Some(Value::S32(x)),
654                results.push(Value::Bool(x > 0))
655            ),
656            Instruction::I32FromBool => require_matches!(
657                operands.pop(),
658                Some(Value::Bool(x)),
659                results.push(Value::S32(x as i32))
660            ),
661            Instruction::StringLower { realloc: _ } => {
662                let encoded = require_matches!(
663                    operands.pop(),
664                    Some(Value::String(x)),
665                    match self.encoding {
666                        StringEncoding::Utf8 => Vec::from_iter(x.bytes()),
667                        StringEncoding::Utf16 | StringEncoding::CompactUtf16 =>
668                            x.encode_utf16().flat_map(|a| a.to_le_bytes()).collect(),
669                    }
670                );
671
672                let realloc = self.realloc.as_ref().expect("No realloc.");
673                let args = [
674                    wasm_runtime_layer::Value::I32(0),
675                    wasm_runtime_layer::Value::I32(0),
676                    wasm_runtime_layer::Value::I32(1),
677                    wasm_runtime_layer::Value::I32(encoded.len() as i32),
678                ];
679                let mut res = [wasm_runtime_layer::Value::I32(0)];
680                realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
681                let ptr = require_matches!(&res[0], wasm_runtime_layer::Value::I32(x), *x);
682
683                let memory = self.memory.as_ref().expect("No memory.");
684                memory.write(&mut self.ctx.as_context_mut().inner, ptr as usize, &encoded)?;
685
686                results.push(Value::S32(ptr));
687                results.push(Value::S32(encoded.len() as i32));
688            }
689            Instruction::ListCanonLower {
690                element,
691                realloc: _,
692            } => {
693                let list = require_matches!(operands.pop(), Some(Value::List(x)), x);
694                let align = self.component.size_align.align(element);
695                let size = self.component.size_align.size(element);
696
697                let realloc = self.realloc.as_ref().expect("No realloc.");
698                let args = [
699                    wasm_runtime_layer::Value::I32(0),
700                    wasm_runtime_layer::Value::I32(0),
701                    wasm_runtime_layer::Value::I32(align as i32),
702                    wasm_runtime_layer::Value::I32((list.len() * size) as i32),
703                ];
704                let mut res = [wasm_runtime_layer::Value::I32(0)];
705                realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
706                let ptr = require_matches!(res[0], wasm_runtime_layer::Value::I32(x), x);
707
708                match element {
709                    Type::U8 => self.store_array(ptr as usize, list.typed::<u8>()?)?,
710                    Type::U16 => self.store_array(ptr as usize, list.typed::<u16>()?)?,
711                    Type::U32 => self.store_array(ptr as usize, list.typed::<u32>()?)?,
712                    Type::U64 => self.store_array(ptr as usize, list.typed::<u64>()?)?,
713                    Type::S8 => self.store_array(ptr as usize, list.typed::<i8>()?)?,
714                    Type::S16 => self.store_array(ptr as usize, list.typed::<i16>()?)?,
715                    Type::S32 => self.store_array(ptr as usize, list.typed::<i32>()?)?,
716                    Type::S64 => self.store_array(ptr as usize, list.typed::<i64>()?)?,
717                    Type::Float32 => self.store_array(ptr as usize, list.typed::<f32>()?)?,
718                    Type::Float64 => self.store_array(ptr as usize, list.typed::<f64>()?)?,
719                    _ => unreachable!(),
720                }
721
722                results.push(Value::S32(ptr));
723                results.push(Value::S32(list.len() as i32));
724            }
725            Instruction::ListLower {
726                element,
727                realloc: _,
728                len,
729            } => {
730                let list = require_matches!(operands.pop(), Some(Value::List(x)), x);
731                let align = self.component.size_align.align(element);
732                let size = self.component.size_align.size(element);
733
734                let realloc = self.realloc.as_ref().expect("No realloc.");
735                let args = [
736                    wasm_runtime_layer::Value::I32(0),
737                    wasm_runtime_layer::Value::I32(0),
738                    wasm_runtime_layer::Value::I32(align as i32),
739                    wasm_runtime_layer::Value::I32((list.len() * size) as i32),
740                ];
741                let mut res = [wasm_runtime_layer::Value::I32(0)];
742                realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
743                let ptr = require_matches!(res[0], wasm_runtime_layer::Value::I32(x), x);
744
745                len.set(list.len() as i32);
746
747                results.push(Value::S32(ptr));
748                results.push(Value::S32(list.len() as i32));
749
750                for item in &list {
751                    results.push(item.clone());
752                }
753
754                results.push(Value::S32(ptr));
755            }
756            Instruction::StringLift => {
757                let memory = self.memory.as_ref().expect("No memory.");
758                let len = require_matches!(operands.pop(), Some(Value::S32(len)), len) as usize;
759                let mut result = vec![0; len];
760                require_matches!(
761                    operands.pop(),
762                    Some(Value::S32(ptr)),
763                    memory.read(&self.ctx.as_context().inner, ptr as usize, &mut result)?
764                );
765
766                match self.encoding {
767                    StringEncoding::Utf8 => {
768                        results.push(Value::String(String::from_utf8(result)?.into()))
769                    }
770                    StringEncoding::Utf16 | StringEncoding::CompactUtf16 => {
771                        ensure!(result.len() & 0b1 == 0, "Invalid string length");
772                        results.push(Value::String(
773                            String::from_utf16(
774                                &result
775                                    .chunks_exact(2)
776                                    .map(|e| {
777                                        u16::from_be_bytes(
778                                            e.try_into().expect("All chunks must have size 2."),
779                                        )
780                                    })
781                                    .collect::<Vec<_>>(),
782                            )?
783                            .into(),
784                        ));
785                    }
786                }
787            }
788            Instruction::ListCanonLift { element, ty: _ } => {
789                let len = require_matches!(operands.pop(), Some(Value::S32(x)), x);
790                let ptr = require_matches!(operands.pop(), Some(Value::S32(x)), x);
791
792                results.push(Value::List(match element {
793                    Type::U8 => self.load_array::<u8>(ptr as usize, len as usize)?.into(),
794                    Type::U16 => self.load_array::<u16>(ptr as usize, len as usize)?.into(),
795                    Type::U32 => self.load_array::<u32>(ptr as usize, len as usize)?.into(),
796                    Type::U64 => self.load_array::<u64>(ptr as usize, len as usize)?.into(),
797                    Type::S8 => self.load_array::<i8>(ptr as usize, len as usize)?.into(),
798                    Type::S16 => self.load_array::<i16>(ptr as usize, len as usize)?.into(),
799                    Type::S32 => self.load_array::<i32>(ptr as usize, len as usize)?.into(),
800                    Type::S64 => self.load_array::<i64>(ptr as usize, len as usize)?.into(),
801                    Type::Float32 => self.load_array::<f32>(ptr as usize, len as usize)?.into(),
802                    Type::Float64 => self.load_array::<f64>(ptr as usize, len as usize)?.into(),
803                    _ => unreachable!(),
804                }));
805            }
806            Instruction::ListLift {
807                element: _,
808                ty,
809                len: _,
810            } => {
811                let ty = self.types[ty.index()].clone();
812                results.push(Value::List(List::new(
813                    require_matches!(ty, crate::types::ValueType::List(x), x),
814                    operands.drain(..),
815                )?));
816            }
817            Instruction::ReadI32 { value } => {
818                value.set(require_matches!(operands.pop(), Some(Value::S32(x)), x))
819            }
820            Instruction::RecordLower { record: _, ty } => {
821                let official_ty =
822                    require_matches!(&self.types[ty.index()], ValueType::Record(x), x);
823                let record = require_matches!(operands.pop(), Some(Value::Record(x)), x);
824                ensure!(&record.ty() == official_ty, "Record types did not match.");
825
826                for _i in 0..record.fields().len() {
827                    results.push(Value::Bool(false));
828                }
829
830                for (index, value) in official_ty
831                    .fields
832                    .iter()
833                    .map(|x| x.0)
834                    .zip(record.fields().map(|x| x.1))
835                {
836                    results[index] = value;
837                }
838            }
839            Instruction::RecordLift { record: _, ty } => {
840                let official_ty =
841                    require_matches!(&self.types[ty.index()], ValueType::Record(x), x);
842                ensure!(
843                    operands.len() == official_ty.fields().len(),
844                    "Record types did not match."
845                );
846
847                results.push(Value::Record(crate::values::Record::from_sorted(
848                    official_ty.clone(),
849                    official_ty.fields.iter().map(|(i, name, _)| {
850                        (name.clone(), replace(&mut operands[*i], Value::Bool(false)))
851                    }),
852                )));
853                operands.clear();
854            }
855            Instruction::HandleLower { handle, ty } => match &self.types[ty.index()] {
856                ValueType::Own(_ty) => {
857                    let def = match handle {
858                        Handle::Own(x) => x,
859                        Handle::Borrow(x) => x,
860                    };
861                    let val = require_matches!(operands.pop(), Some(Value::Own(x)), x);
862                    let rep = val.lower(&mut self.ctx)?;
863
864                    let mut tables = self
865                        .resource_tables
866                        .try_lock()
867                        .expect("Could not acquire table access.");
868                    results.push(Value::S32(
869                        tables[self.component.resource_map[def.index()].as_u32() as usize].add(
870                            HandleElement {
871                                rep,
872                                own: true,
873                                lend_count: 0,
874                            },
875                        ),
876                    ));
877                }
878                ValueType::Borrow(_ty) => {
879                    let def = match handle {
880                        Handle::Own(x) => x,
881                        Handle::Borrow(x) => x,
882                    };
883                    let val = require_matches!(operands.pop(), Some(Value::Borrow(x)), x);
884                    let rep = val.lower(&mut self.ctx)?;
885
886                    if val.ty().is_owned_by_instance(self.instance_id) {
887                        results.push(Value::S32(rep));
888                    } else {
889                        let mut tables = self
890                            .resource_tables
891                            .try_lock()
892                            .expect("Could not acquire table access.");
893                        let res = self.component.resource_map[def.index()].as_u32();
894                        let idx = tables[res as usize].add(HandleElement {
895                            rep,
896                            own: false,
897                            lend_count: 0,
898                        });
899                        results.push(Value::S32(idx));
900                        self.handles_to_drop.push((res, idx));
901                    }
902                }
903                _ => unreachable!(),
904            },
905            Instruction::HandleLift { handle, ty } => match &self.types[ty.index()] {
906                ValueType::Own(ty) => {
907                    let def = match handle {
908                        Handle::Own(x) => x,
909                        Handle::Borrow(x) => x,
910                    };
911                    let val = require_matches!(operands.pop(), Some(Value::S32(x)), x);
912
913                    let mut tables = self
914                        .resource_tables
915                        .try_lock()
916                        .expect("Could not acquire table access.");
917                    let table =
918                        &mut tables[self.component.resource_map[def.index()].as_u32() as usize];
919                    let elem = table.remove(val)?;
920                    ensure!(
921                        elem.lend_count == 0,
922                        "Attempted to transfer ownership while handle was lent."
923                    );
924                    ensure!(
925                        elem.own,
926                        "Attempted to transfer ownership of non-owned handle."
927                    );
928
929                    results.push(Value::Own(ResourceOwn::new_guest(
930                        elem.rep,
931                        ty.clone(),
932                        self.store_id,
933                        table.destructor().cloned(),
934                    )));
935                }
936                ValueType::Borrow(ty) => {
937                    let def = match handle {
938                        Handle::Own(x) => x,
939                        Handle::Borrow(x) => x,
940                    };
941                    let val = require_matches!(operands.pop(), Some(Value::S32(x)), x);
942
943                    let mut tables = self
944                        .resource_tables
945                        .try_lock()
946                        .expect("Could not acquire table access.");
947                    let res = self.component.resource_map[def.index()].as_u32();
948                    let table = &mut tables[res as usize];
949                    let mut elem = *table.get(val)?;
950
951                    if elem.own {
952                        elem.lend_count += 1;
953                        table.set(val, elem);
954                    }
955
956                    let borrow = ResourceBorrow::new(elem.rep, self.store_id, ty.clone());
957                    self.required_dropped
958                        .push((elem.own, res, val, borrow.dead_ref()));
959                    results.push(Value::Borrow(borrow));
960                }
961                _ => unreachable!(),
962            },
963            Instruction::TupleLower { tuple: _, ty: _ } => {
964                let tuple = require_matches!(operands.pop(), Some(Value::Tuple(x)), x);
965                results.extend(tuple.iter().cloned());
966            }
967            Instruction::TupleLift { tuple: _, ty } => {
968                results.push(Value::Tuple(crate::values::Tuple::new_unchecked(
969                    require_matches!(&self.types[ty.index()], ValueType::Tuple(x), x.clone()),
970                    operands.drain(..),
971                )));
972            }
973            Instruction::FlagsLower { flags: _, ty: _ } => {
974                let flags = require_matches!(operands.pop(), Some(Value::Flags(x)), x);
975                if flags.ty().names().len() > 0 {
976                    results.extend(flags.as_u32_list().iter().map(|x| Value::S32(*x as i32)));
977                }
978            }
979            Instruction::FlagsLift { flags: _, ty } => {
980                let flags = require_matches!(&self.types[ty.index()], ValueType::Flags(x), x);
981
982                let list = match operands.len() {
983                    0 => FlagsList::Single(0),
984                    1 => FlagsList::Single(require_matches!(
985                        operands.pop(),
986                        Some(Value::S32(x)),
987                        x as u32
988                    )),
989                    _ => FlagsList::Multiple(Arc::new(
990                        operands
991                            .drain(..)
992                            .map(|x| Ok(require_matches!(x, Value::S32(y), y) as u32))
993                            .collect::<Result<_>>()?,
994                    )),
995                };
996
997                results.push(Value::Flags(crate::values::Flags::new_unchecked(
998                    flags.clone(),
999                    list,
1000                )));
1001            }
1002            Instruction::ExtractVariantDiscriminant { discriminant_value } => {
1003                let (discriminant, val) = match operands
1004                    .pop()
1005                    .expect("No operand on stack for which to extract discriminant.")
1006                {
1007                    Value::Variant(x) => (x.discriminant(), x.value()),
1008                    Value::Enum(x) => (x.discriminant(), None),
1009                    Value::Option(x) => {
1010                        (x.is_some().then_some(1).unwrap_or_default(), (*x).clone())
1011                    }
1012                    Value::Result(x) => (
1013                        x.is_err().then_some(1).unwrap_or_default(),
1014                        match &*x {
1015                            std::result::Result::Ok(y) => y,
1016                            std::result::Result::Err(y) => y,
1017                        }
1018                        .clone(),
1019                    ),
1020                    _ => bail!("Invalid type for which to extract variant."),
1021                };
1022
1023                if let Some(value) = val {
1024                    results.push(value);
1025                    discriminant_value.set((discriminant as i32, true));
1026                } else {
1027                    discriminant_value.set((discriminant as i32, false));
1028                }
1029            }
1030            Instruction::ExtractReadVariantDiscriminant { value, .. } => {
1031                value.set(require_matches!(operands.pop(), Some(Value::S32(x)), x))
1032            }
1033            Instruction::VariantLift {
1034                ty, discriminant, ..
1035            } => {
1036                let variant_ty =
1037                    require_matches!(&self.types[ty.index()], ValueType::Variant(x), x);
1038                results.push(Value::Variant(crate::values::Variant::new(
1039                    variant_ty.clone(),
1040                    *discriminant as usize,
1041                    operands.pop(),
1042                )?));
1043            }
1044            Instruction::EnumLower { enum_: _, ty: _ } => {
1045                let en = require_matches!(operands.pop(), Some(Value::Enum(x)), x);
1046                results.push(Value::S32(en.discriminant() as i32));
1047            }
1048            Instruction::EnumLift {
1049                enum_: _,
1050                ty,
1051                discriminant,
1052            } => {
1053                let enum_ty = require_matches!(&self.types[ty.index()], ValueType::Enum(x), x);
1054                results.push(Value::Enum(crate::values::Enum::new(
1055                    enum_ty.clone(),
1056                    *discriminant as usize,
1057                )?));
1058            }
1059            Instruction::OptionLift {
1060                ty, discriminant, ..
1061            } => {
1062                let option_ty = require_matches!(&self.types[ty.index()], ValueType::Option(x), x);
1063                results.push(Value::Option(OptionValue::new(
1064                    option_ty.clone(),
1065                    if *discriminant == 0 {
1066                        None
1067                    } else {
1068                        Some(require_matches!(operands.pop(), Some(x), x))
1069                    },
1070                )?));
1071            }
1072            Instruction::ResultLift {
1073                discriminant, ty, ..
1074            } => {
1075                let result_ty = require_matches!(&self.types[ty.index()], ValueType::Result(x), x);
1076                results.push(Value::Result(ResultValue::new(
1077                    result_ty.clone(),
1078                    if *discriminant == 0 {
1079                        std::result::Result::Ok(operands.pop())
1080                    } else {
1081                        std::result::Result::Err(operands.pop())
1082                    },
1083                )?));
1084            }
1085            Instruction::CallWasm { name: _, sig } => {
1086                let args = operands
1087                    .iter()
1088                    .map(TryFrom::try_from)
1089                    .collect::<Result<Vec<_>>>()?;
1090                self.flat_results = vec![wasm_runtime_layer::Value::I32(0); sig.results.len()];
1091                self.callee_wasm.expect("No available WASM callee.").call(
1092                    &mut self.ctx.as_context_mut().inner,
1093                    &args,
1094                    &mut self.flat_results,
1095                )?;
1096                results.extend(
1097                    self.flat_results
1098                        .iter()
1099                        .map(TryFrom::try_from)
1100                        .collect::<Result<Vec<_>>>()?,
1101                );
1102            }
1103            Instruction::CallInterface { func } => {
1104                for _i in 0..func.results.len() {
1105                    results.push(Value::Bool(false));
1106                }
1107
1108                self.callee_interface
1109                    .expect("No available interface callee.")
1110                    .call(self.ctx.as_context_mut(), operands, &mut results[..])?;
1111            }
1112            Instruction::Return { amt: _, func: _ } => {
1113                if let Some(post) = &self.post_return {
1114                    post.call(
1115                        &mut self.ctx.as_context_mut().inner,
1116                        &self.flat_results,
1117                        &mut [],
1118                    )?;
1119                }
1120
1121                let mut tables = self
1122                    .resource_tables
1123                    .try_lock()
1124                    .expect("Could not lock resource table.");
1125                for (res, idx) in &self.handles_to_drop {
1126                    tables[*res as usize]
1127                        .remove(*idx)
1128                        .expect("Could not find handle to drop.");
1129                }
1130
1131                for (own, res, idx, ptr) in &self.required_dropped {
1132                    ensure!(
1133                        Arc::strong_count(ptr) == 1,
1134                        "Borrow was not dropped at the end of method."
1135                    );
1136
1137                    if *own {
1138                        let table = &mut tables[*res as usize];
1139                        let mut elem = *table.get(*idx)?;
1140
1141                        elem.lend_count -= 1;
1142                        table.set(*idx, elem);
1143                    }
1144                }
1145
1146                for (i, val) in operands.drain(..).enumerate() {
1147                    *self
1148                        .results
1149                        .get_mut(i)
1150                        .ok_or_else(|| Error::msg("Unexpected number of output arguments."))? = val;
1151                }
1152            }
1153            Instruction::Malloc {
1154                realloc: _,
1155                size,
1156                align,
1157            } => {
1158                let realloc = self.realloc.as_ref().expect("No realloc.");
1159                let args = [
1160                    wasm_runtime_layer::Value::I32(0),
1161                    wasm_runtime_layer::Value::I32(0),
1162                    wasm_runtime_layer::Value::I32(*align as i32),
1163                    wasm_runtime_layer::Value::I32(*size as i32),
1164                ];
1165                let mut res = [wasm_runtime_layer::Value::I32(0)];
1166                realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
1167                require_matches!(
1168                    &res[0],
1169                    wasm_runtime_layer::Value::I32(x),
1170                    results.push(Value::S32(*x))
1171                );
1172            }
1173        }
1174
1175        Ok(())
1176    }
1177
1178    fn sizes(&self) -> &SizeAlign {
1179        &self.component.size_align
1180    }
1181
1182    fn is_list_canonical(&self, element: &Type) -> bool {
1183        /// Whether this is a little-endian machine.
1184        const LITTLE_ENDIAN: bool = cfg!(target_endian = "little");
1185
1186        match element {
1187            Type::Bool => false,
1188            Type::U8 => true,
1189            Type::U16 => LITTLE_ENDIAN,
1190            Type::U32 => LITTLE_ENDIAN,
1191            Type::U64 => LITTLE_ENDIAN,
1192            Type::S8 => true,
1193            Type::S16 => LITTLE_ENDIAN,
1194            Type::S32 => LITTLE_ENDIAN,
1195            Type::S64 => LITTLE_ENDIAN,
1196            Type::Float32 => LITTLE_ENDIAN,
1197            Type::Float64 => LITTLE_ENDIAN,
1198            Type::Char => false,
1199            Type::String => false,
1200            Type::Id(_) => false,
1201        }
1202    }
1203}
1204
1205/// A strongly-typed component model function that can be called to interact with [`Instance`]s.
1206#[derive(Clone, Debug)]
1207pub struct TypedFunc<P: ComponentList, R: ComponentList> {
1208    /// The inner function to call.
1209    inner: Func,
1210    /// A marker to prevent compiler errors.
1211    data: PhantomData<fn(P) -> R>,
1212}
1213
1214impl<P: ComponentList, R: ComponentList> TypedFunc<P, R> {
1215    /// Creates a new function, wrapping the given closure.
1216    pub fn new<C: AsContextMut>(
1217        ctx: C,
1218        f: impl 'static + Send + Sync + Fn(StoreContextMut<C::UserState, C::Engine>, P) -> Result<R>,
1219    ) -> Self {
1220        let mut params_results = vec![ValueType::Bool; P::LEN + R::LEN];
1221        P::into_tys(&mut params_results[..P::LEN]);
1222        R::into_tys(&mut params_results[P::LEN..]);
1223
1224        Self {
1225            inner: Func::new(
1226                ctx,
1227                FuncType::new(
1228                    params_results[..P::LEN].iter().cloned(),
1229                    params_results[P::LEN..].iter().cloned(),
1230                ),
1231                move |ctx, args, res| {
1232                    let p = P::from_values(args)?;
1233                    let r = f(ctx, p)?;
1234                    r.into_values(res)
1235                },
1236            ),
1237            data: PhantomData,
1238        }
1239    }
1240
1241    /// Calls this function, returning an error if:
1242    ///
1243    /// - The store did not match the original.
1244    /// - A trap occurred.
1245    pub fn call(&self, ctx: impl AsContextMut, params: P) -> Result<R> {
1246        let mut params_results = vec![Value::Bool(false); P::LEN + R::LEN];
1247        params.into_values(&mut params_results[0..P::LEN])?;
1248        let (params, results) = params_results.split_at_mut(P::LEN);
1249        self.inner.call(ctx, params, results)?;
1250        R::from_values(results)
1251    }
1252
1253    /// Gets the underlying, untyped function.
1254    pub fn func(&self) -> Func {
1255        self.inner.clone()
1256    }
1257
1258    /// Gets the component model type of this function.
1259    pub fn ty(&self) -> FuncType {
1260        self.inner.ty.clone()
1261    }
1262}
1263
1264/// Details the function name and instance in which an error occurred.
1265pub struct FuncError {
1266    /// The name of the function.
1267    name: String,
1268    /// The ID of the interface associated with the function.
1269    interface: Option<InterfaceIdentifier>,
1270    /// The instance.
1271    instance: crate::Instance,
1272    /// The error.
1273    error: Error,
1274}
1275
1276impl FuncError {
1277    /// Gets the name of the function for which the error was thrown.
1278    pub fn name(&self) -> &str {
1279        &self.name
1280    }
1281
1282    /// Gets the instance for which this error occurred.
1283    pub fn instance(&self) -> &crate::Instance {
1284        &self.instance
1285    }
1286}
1287
1288impl std::fmt::Debug for FuncError {
1289    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1290        if let Some(inter) = &self.interface {
1291            f.write_fmt(format_args!("in {}.{}: {:?}", inter, self.name, self.error))
1292        } else {
1293            f.write_fmt(format_args!("in {}: {:?}", self.name, self.error))
1294        }
1295    }
1296}
1297
1298impl std::fmt::Display for FuncError {
1299    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1300        if let Some(inter) = &self.interface {
1301            f.write_fmt(format_args!("in {}.{}: {}", inter, self.name, self.error))
1302        } else {
1303            f.write_fmt(format_args!("in {}: {}", self.name, self.error))
1304        }
1305    }
1306}
1307
1308impl std::error::Error for FuncError {
1309    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1310        Some(self.error.as_ref())
1311    }
1312}
1313
1314/// Marks a type that may be blitted directly to and from guest memory.
1315trait Blittable: Sized {
1316    /// The type of byte array that matches the layout of this type.
1317    type Array: ByteArray;
1318
1319    /// Creates this type from a byte array.
1320    fn from_bytes(array: Self::Array) -> Self;
1321    /// Converts this type to a byte array.
1322    fn to_bytes(self) -> Self::Array;
1323
1324    /// Creates a new, zeroed byte array for an array of `Self` of the given size.
1325    fn zeroed_array(len: usize) -> Arc<[Self]>;
1326
1327    /// Converts a slice of `Self` to a slice of bytes.
1328    fn to_le_slice(data: &[Self]) -> &[u8];
1329    /// Converts a mutable slice of `Self` to a mutable slice of bytes.
1330    fn to_le_slice_mut(data: &mut [Self]) -> &mut [u8];
1331}
1332
1333/// Implements the `Blittable` interface for primitive types.
1334macro_rules! impl_blittable {
1335    ($($type_impl: ident)*) => {
1336        $(
1337            impl Blittable for $type_impl {
1338                type Array = [u8; std::mem::size_of::<$type_impl>()];
1339
1340                fn from_bytes(array: Self::Array) -> Self {
1341                    Self::from_le_bytes(array)
1342                }
1343
1344                fn to_bytes(self) -> Self::Array {
1345                    Self::to_le_bytes(self)
1346                }
1347
1348                fn zeroed_array(len: usize) -> Arc<[Self]> {
1349                    Arc::from(zeroed_slice_box::<Self>(len))
1350                }
1351
1352                fn to_le_slice(data: &[Self]) -> &[u8] {
1353                    assert!(cfg!(target_endian = "little"), "Attempted to bitcast to little-endian bytes on a big endian platform.");
1354                    cast_slice(data)
1355                }
1356
1357                fn to_le_slice_mut(data: &mut [Self]) -> &mut [u8] {
1358                    assert!(cfg!(target_endian = "little"), "Attempted to bitcast to little-endian bytes on a big endian platform.");
1359                    cast_slice_mut(data)
1360                }
1361            }
1362        )*
1363    };
1364}
1365
1366impl_blittable!(u8 u16 u32 u64 i8 i16 i32 i64 f32 f64);
1367
1368/// Denotes a byte array of any size.
1369trait ByteArray: Sized {
1370    /// Loads this byte array from a WASM memory.
1371    fn load(ctx: impl AsContext, memory: &Memory, offset: usize) -> Result<Self>;
1372
1373    /// Stores the contents of this byte array into a WASM memory.
1374    fn store(self, ctx: impl AsContextMut, memory: &Memory, offset: usize) -> Result<()>;
1375}
1376
1377impl<const N: usize> ByteArray for [u8; N] {
1378    fn load(ctx: impl AsContext, memory: &Memory, offset: usize) -> Result<Self> {
1379        let mut res = [0; N];
1380        memory.read(ctx.as_context().inner, offset, &mut res)?;
1381        Ok(res)
1382    }
1383
1384    fn store(self, mut ctx: impl AsContextMut, memory: &Memory, offset: usize) -> Result<()> {
1385        memory.write(ctx.as_context_mut().inner, offset, &self)?;
1386        Ok(())
1387    }
1388}
1389
1390/// The type of a dynamic host function.
1391type FunctionBacking<T, E> =
1392    dyn 'static + Send + Sync + Fn(StoreContextMut<T, E>, &[Value], &mut [Value]) -> Result<()>;
1393
1394/// The type of the key used in the vector of host functions.
1395type FunctionBackingKeyPair<T, E> = (Arc<AtomicUsize>, Arc<FunctionBacking<T, E>>);
1396
1397/// A vector for functions that automatically drops items when the references are dropped.
1398pub(crate) struct FuncVec<T, E: backend::WasmEngine> {
1399    /// The functions stored in the vector.
1400    functions: Vec<FunctionBackingKeyPair<T, E>>,
1401}
1402
1403impl<T, E: backend::WasmEngine> FuncVec<T, E> {
1404    /// Pushes a new function into the vector.
1405    pub fn push(
1406        &mut self,
1407        f: impl 'static + Send + Sync + Fn(StoreContextMut<T, E>, &[Value], &mut [Value]) -> Result<()>,
1408    ) -> Arc<AtomicUsize> {
1409        if self.functions.capacity() == self.functions.len() {
1410            self.clear_dead_functions();
1411        }
1412        let idx = Arc::new(AtomicUsize::new(self.functions.len()));
1413        self.functions.push((idx.clone(), Arc::new(f)));
1414        idx
1415    }
1416
1417    /// Gets a function from the vector.
1418    pub fn get(&self, value: &AtomicUsize) -> Arc<FunctionBacking<T, E>> {
1419        self.functions[value.load(Ordering::Acquire)].1.clone()
1420    }
1421
1422    /// Clears all dead functions from the vector, and doubles its capacity.
1423    fn clear_dead_functions(&mut self) {
1424        let new_len = 2 * self.functions.len();
1425        let old = replace(&mut self.functions, Vec::with_capacity(new_len));
1426        for (idx, val) in old {
1427            if Arc::strong_count(&idx) > 1 {
1428                idx.store(self.functions.len(), Ordering::Release);
1429                self.functions.push((idx, val));
1430            }
1431        }
1432    }
1433}
1434
1435impl<T, E: backend::WasmEngine> Default for FuncVec<T, E> {
1436    fn default() -> Self {
1437        Self {
1438            functions: Vec::new(),
1439        }
1440    }
1441}