Skip to main content

waclay/
func.rs

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