Skip to main content

wasmtime/runtime/component/func/
typed.rs

1use crate::component::Instance;
2use crate::component::func::{Func, LiftContext, LowerContext};
3use crate::component::matching::InstanceType;
4use crate::component::storage::{storage_as_slice, storage_as_slice_mut};
5use crate::hash_map::HashMap;
6use crate::prelude::*;
7use crate::{AsContextMut, StoreContext, StoreContextMut, ValRaw};
8use alloc::borrow::Cow;
9use core::fmt;
10use core::hash::Hash;
11use core::iter;
12use core::marker;
13use core::mem::{self, MaybeUninit};
14use core::str;
15use wasmtime_environ::component::{
16    CanonicalAbiInfo, ComponentTypes, InterfaceType, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
17    OptionsIndex, StringEncoding, TypeMap, VariantInfo,
18};
19
20/// A statically-typed version of [`Func`] which takes `Params` as input and
21/// returns `Return`.
22///
23/// This is an efficient way to invoke a WebAssembly component where if the
24/// inputs and output are statically known this can eschew the vast majority of
25/// machinery and checks when calling WebAssembly. This is the most optimized
26/// way to call a WebAssembly component.
27///
28/// Note that like [`Func`] this is a pointer within a [`Store`](crate::Store)
29/// and usage will panic if used with the wrong store.
30///
31/// This type is primarily created with the [`Func::typed`] API.
32///
33/// See [`ComponentType`] for more information about supported types.
34pub struct TypedFunc<Params, Return> {
35    func: Func,
36
37    // The definition of this field is somewhat subtle and may be surprising.
38    // Naively one might expect something like
39    //
40    //      _marker: marker::PhantomData<fn(Params) -> Return>,
41    //
42    // Since this is a function pointer after all. The problem with this
43    // definition though is that it imposes the wrong variance on `Params` from
44    // what we want. Abstractly a `fn(Params)` is able to store `Params` within
45    // it meaning you can only give it `Params` that live longer than the
46    // function pointer.
47    //
48    // With a component model function, however, we're always copying data from
49    // the host into the guest, so we are never storing pointers to `Params`
50    // into the guest outside the duration of a `call`, meaning we can actually
51    // accept values in `TypedFunc::call` which live for a shorter duration
52    // than the `Params` argument on the struct.
53    //
54    // This all means that we don't use a phantom function pointer, but instead
55    // feign phantom storage here to get the variance desired.
56    _marker: marker::PhantomData<(Params, Return)>,
57}
58
59impl<Params, Return> Copy for TypedFunc<Params, Return> {}
60
61impl<Params, Return> Clone for TypedFunc<Params, Return> {
62    fn clone(&self) -> TypedFunc<Params, Return> {
63        *self
64    }
65}
66
67impl<Params, Return> TypedFunc<Params, Return>
68where
69    Params: ComponentNamedList + Lower,
70    Return: ComponentNamedList + Lift,
71{
72    /// Creates a new [`TypedFunc`] from the provided component [`Func`],
73    /// unsafely asserting that the underlying function takes `Params` as
74    /// input and returns `Return`.
75    ///
76    /// # Unsafety
77    ///
78    /// This is an unsafe function because it does not verify that the [`Func`]
79    /// provided actually implements this signature. It's up to the caller to
80    /// have performed some other sort of check to ensure that the signature is
81    /// correct.
82    pub unsafe fn new_unchecked(func: Func) -> TypedFunc<Params, Return> {
83        TypedFunc {
84            _marker: marker::PhantomData,
85            func,
86        }
87    }
88
89    /// Returns the underlying un-typed [`Func`] that this [`TypedFunc`]
90    /// references.
91    pub fn func(&self) -> &Func {
92        &self.func
93    }
94
95    /// Calls the underlying WebAssembly component function using the provided
96    /// `params` as input.
97    ///
98    /// This method is used to enter into a component. Execution happens within
99    /// the `store` provided. The `params` are copied into WebAssembly memory
100    /// as appropriate and a core wasm function is invoked.
101    ///
102    /// # Post-return
103    ///
104    /// In the component model each function can have a "post return" specified
105    /// which allows cleaning up the arguments returned to the host. For example
106    /// if WebAssembly returns a string to the host then it might be a uniquely
107    /// allocated string which, after the host finishes processing it, needs to
108    /// be deallocated in the wasm instance's own linear memory to prevent
109    /// memory leaks in wasm itself. The `post-return` canonical abi option is
110    /// used to configured this.
111    ///
112    /// If a post-return function is present, it will be called automatically by
113    /// this function.
114    ///
115    /// # Errors
116    ///
117    /// This function can return an error for a number of reasons:
118    ///
119    /// * If the wasm itself traps during execution.
120    /// * If the wasm traps while copying arguments into memory.
121    /// * If the wasm provides bad allocation pointers when copying arguments
122    ///   into memory.
123    /// * If the wasm returns a value which violates the canonical ABI.
124    /// * If this function's instances cannot be entered, for example if the
125    ///   instance is currently calling a host function.
126    /// * If `store` requires using [`Self::call_async`] instead, see
127    ///   [crate documentation](crate#async) for more info.
128    ///
129    /// In general there are many ways that things could go wrong when copying
130    /// types in and out of a wasm module with the canonical ABI, and certain
131    /// error conditions are specific to certain types. For example a
132    /// WebAssembly module can't return an invalid `char`. When allocating space
133    /// for this host to copy a string into the returned pointer must be
134    /// in-bounds in memory.
135    ///
136    /// If an error happens then the error should contain detailed enough
137    /// information to understand which part of the canonical ABI went wrong
138    /// and what to inspect.
139    ///
140    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
141    /// memory allocation fails. See the `OutOfMemory` type's documentation for
142    /// details on Wasmtime's out-of-memory handling.
143    ///
144    /// # Panics
145    ///
146    /// Panics if `store` does not own this function.
147    pub fn call(&self, mut store: impl AsContextMut, params: Params) -> Result<Return> {
148        let mut store = store.as_context_mut();
149        store.0.validate_sync_call()?;
150        self.call_impl(store.as_context_mut(), params)
151    }
152
153    /// Exactly like [`Self::call`], except for invoking WebAssembly
154    /// [asynchronously](crate#async).
155    ///
156    /// # Errors
157    ///
158    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
159    /// memory allocation fails. See the `OutOfMemory` type's documentation for
160    /// details on Wasmtime's out-of-memory handling.
161    ///
162    /// # Panics
163    ///
164    /// Panics if `store` does not own this function.
165    #[cfg(feature = "async")]
166    pub async fn call_async(
167        &self,
168        mut store: impl AsContextMut<Data: Send>,
169        params: Params,
170    ) -> Result<Return>
171    where
172        Return: 'static,
173    {
174        let mut store = store.as_context_mut();
175
176        #[cfg(feature = "component-model-async")]
177        if store.0.concurrency_support() {
178            return self.call_async_concurrent(store, params).await;
179        }
180
181        store
182            .on_fiber(|store| self.call_impl(store, params))
183            .await?
184    }
185
186    pub(crate) fn lower_args<T>(
187        cx: &mut LowerContext<T>,
188        ty: InterfaceType,
189        dst: &mut [MaybeUninit<ValRaw>],
190        params: &Params,
191    ) -> Result<()> {
192        use crate::component::storage::slice_to_storage_mut;
193
194        if Params::flatten_count() <= MAX_FLAT_PARAMS {
195            // SAFETY: the safety of `slice_to_storage_mut` relies on
196            // `Params::Lower` being represented by a sequence of
197            // `ValRaw`, and that's a guarantee upheld by the `Lower`
198            // trait itself.
199            let dst: &mut MaybeUninit<Params::Lower> = unsafe { slice_to_storage_mut(dst) };
200            Self::lower_stack_args(cx, &params, ty, dst)
201        } else {
202            Self::lower_heap_args(cx, &params, ty, &mut dst[0])
203        }
204    }
205
206    fn call_impl(&self, mut store: impl AsContextMut, params: Params) -> Result<Return> {
207        let mut store = store.as_context_mut();
208
209        if self.func.abi_async(store.0) {
210            bail!("must enable the `component-model-async` feature to call async-lifted exports")
211        }
212
213        // Note that this is in theory simpler than it might read at this time.
214        // Here we're doing a runtime dispatch on the `flatten_count` for the
215        // params/results to see whether they're inbounds. This creates 4 cases
216        // to handle. In reality this is a highly optimizable branch where LLVM
217        // will easily figure out that only one branch here is taken.
218        //
219        // Otherwise this current construction is done to ensure that the stack
220        // space reserved for the params/results is always of the appropriate
221        // size (as the params/results needed differ depending on the "flatten"
222        // count)
223        //
224        // SAFETY: the safety of these invocations of `call_raw` depends on the
225        // correctness of the ascription of the `LowerParams` and `LowerReturn`
226        // types on the `call_raw` function. That's upheld here through the
227        // safety requirements of `Lift` and `Lower` on `Params` and `Return` in
228        // combination with checking the various possible branches here and
229        // dispatching to appropriately typed functions.
230        let (result, post_return_arg) = unsafe {
231            // This type is used as `LowerParams` for `call_raw` which is either
232            // `Params::Lower` or `ValRaw` representing it's either on the stack
233            // or it's on the heap. This allocates 1 extra `ValRaw` on the stack
234            // if `Params` is empty and `Return` is also empty, but that's a
235            // reasonable enough price to pay for now given the current code
236            // organization.
237            #[derive(Copy, Clone)]
238            union Union<T: Copy, U: Copy> {
239                _a: T,
240                _b: U,
241            }
242
243            if Return::flatten_count() <= MAX_FLAT_RESULTS {
244                self.func.call_raw(
245                    store.as_context_mut(),
246                    |cx, ty, dst: &mut MaybeUninit<Union<Params::Lower, ValRaw>>| {
247                        let dst = storage_as_slice_mut(dst);
248                        Self::lower_args(cx, ty, dst, &params)
249                    },
250                    Self::lift_stack_result,
251                )
252            } else {
253                self.func.call_raw(
254                    store.as_context_mut(),
255                    |cx, ty, dst: &mut MaybeUninit<Union<Params::Lower, ValRaw>>| {
256                        let dst = storage_as_slice_mut(dst);
257                        Self::lower_args(cx, ty, dst, &params)
258                    },
259                    Self::lift_heap_result,
260                )
261            }
262        }?;
263
264        self.func.post_return_impl(store, post_return_arg)?;
265
266        Ok(result)
267    }
268
269    /// Lower parameters directly onto the stack specified by the `dst`
270    /// location.
271    ///
272    /// This is only valid to call when the "flatten count" is small enough, or
273    /// when the canonical ABI says arguments go through the stack rather than
274    /// the heap.
275    fn lower_stack_args<T>(
276        cx: &mut LowerContext<'_, T>,
277        params: &Params,
278        ty: InterfaceType,
279        dst: &mut MaybeUninit<Params::Lower>,
280    ) -> Result<()> {
281        assert!(Params::flatten_count() <= MAX_FLAT_PARAMS);
282        params.linear_lower_to_flat(cx, ty, dst)?;
283        Ok(())
284    }
285
286    /// Lower parameters onto a heap-allocated location.
287    ///
288    /// This is used when the stack space to be used for the arguments is above
289    /// the `MAX_FLAT_PARAMS` threshold. Here the wasm's `realloc` function is
290    /// invoked to allocate space and then parameters are stored at that heap
291    /// pointer location.
292    fn lower_heap_args<T>(
293        cx: &mut LowerContext<'_, T>,
294        params: &Params,
295        ty: InterfaceType,
296        dst: &mut MaybeUninit<ValRaw>,
297    ) -> Result<()> {
298        // Memory must exist via validation if the arguments are stored on the
299        // heap, so we can create a `MemoryMut` at this point. Afterwards
300        // `realloc` is used to allocate space for all the arguments and then
301        // they're all stored in linear memory.
302        //
303        // Note that `realloc` will bake in a check that the returned pointer is
304        // in-bounds.
305        let ptr = cx.realloc(0, 0, Params::ALIGN32, Params::SIZE32)?;
306        params.linear_lower_to_memory(cx, ty, ptr)?;
307
308        // Note that the pointer here is stored as a 64-bit integer. This allows
309        // this to work with either 32 or 64-bit memories. For a 32-bit memory
310        // it'll just ignore the upper 32 zero bits, and for 64-bit memories
311        // this'll have the full 64-bits. Note that for 32-bit memories the call
312        // to `realloc` above guarantees that the `ptr` is in-bounds meaning
313        // that we will know that the zero-extended upper bits of `ptr` are
314        // guaranteed to be zero.
315        //
316        // This comment about 64-bit integers is also referred to below with
317        // "WRITEPTR64".
318        dst.write(ValRaw::i64(ptr as i64));
319
320        Ok(())
321    }
322
323    /// Lift the result of a function directly from the stack result.
324    ///
325    /// This is only used when the result fits in the maximum number of stack
326    /// slots.
327    pub(crate) fn lift_stack_result(
328        cx: &mut LiftContext<'_>,
329        ty: InterfaceType,
330        dst: &Return::Lower,
331    ) -> Result<Return> {
332        Return::linear_lift_from_flat(cx, ty, dst)
333    }
334
335    /// Lift the result of a function where the result is stored indirectly on
336    /// the heap.
337    pub(crate) fn lift_heap_result(
338        cx: &mut LiftContext<'_>,
339        ty: InterfaceType,
340        dst: &ValRaw,
341    ) -> Result<Return> {
342        assert!(Return::flatten_count() > MAX_FLAT_RESULTS);
343        // FIXME(#4311): needs to read an i64 for memory64
344        let ptr = usize::try_from(dst.get_u32())?;
345        if ptr % usize::try_from(Return::ALIGN32)? != 0 {
346            bail!("return pointer not aligned");
347        }
348
349        let bytes = cx
350            .memory()
351            .get(ptr..)
352            .and_then(|b| b.get(..Return::SIZE32))
353            .ok_or_else(|| crate::format_err!("pointer out of bounds of memory"))?;
354        Return::linear_lift_from_memory(cx, ty, bytes)
355    }
356
357    #[doc(hidden)]
358    #[deprecated(note = "no longer needs to be called; this function has no effect")]
359    pub fn post_return(&self, _store: impl AsContextMut) -> Result<()> {
360        Ok(())
361    }
362
363    #[doc(hidden)]
364    #[deprecated(note = "no longer needs to be called; this function has no effect")]
365    #[cfg(feature = "async")]
366    pub async fn post_return_async<T: Send>(
367        &self,
368        _store: impl AsContextMut<Data = T>,
369    ) -> Result<()> {
370        Ok(())
371    }
372}
373
374/// A trait representing a static list of named types that can be passed to or
375/// returned from a [`TypedFunc`].
376///
377/// This trait is implemented for a number of tuple types and is not expected
378/// to be implemented externally. The contents of this trait are hidden as it's
379/// intended to be an implementation detail of Wasmtime. The contents of this
380/// trait are not covered by Wasmtime's stability guarantees.
381///
382/// For more information about this trait see [`Func::typed`] and
383/// [`TypedFunc`].
384//
385// Note that this is an `unsafe` trait, and the unsafety means that
386// implementations of this trait must be correct or otherwise [`TypedFunc`]
387// would not be memory safe. The main reason this is `unsafe` is the
388// `typecheck` function which must operate correctly relative to the `AsTuple`
389// interpretation of the implementor.
390pub unsafe trait ComponentNamedList: ComponentType {}
391
392/// A trait representing types which can be passed to and read from components
393/// with the canonical ABI.
394///
395/// This trait is implemented for Rust types which can be communicated to
396/// components. The [`Func::typed`] and [`TypedFunc`] Rust items are the main
397/// consumers of this trait.
398///
399/// Supported Rust types include:
400///
401/// | Component Model Type              | Rust Type                            |
402/// |-----------------------------------|--------------------------------------|
403/// | `{s,u}{8,16,32,64}`               | `{i,u}{8,16,32,64}`                  |
404/// | `f{32,64}`                        | `f{32,64}`                           |
405/// | `bool`                            | `bool`                               |
406/// | `char`                            | `char`                               |
407/// | `tuple<A, B>`                     | `(A, B)`                             |
408/// | `option<T>`                       | `Option<T>`                          |
409/// | `result`                          | `Result<(), ()>`                     |
410/// | `result<T>`                       | `Result<T, ()>`                      |
411/// | `result<_, E>`                    | `Result<(), E>`                      |
412/// | `result<T, E>`                    | `Result<T, E>`                       |
413/// | `string`                          | `String`, `&str`, or [`WasmStr`]     |
414/// | `list<T>`                         | `Vec<T>`, `&[T]`, or [`WasmList`]    |
415/// | `map<K, V>`                       | `HashMap<K, V>`                      |
416/// | `own<T>`, `borrow<T>`             | [`Resource<T>`] or [`ResourceAny`]   |
417/// | `record`                          | [`#[derive(ComponentType)]`][d-cm]   |
418/// | `variant`                         | [`#[derive(ComponentType)]`][d-cm]   |
419/// | `enum`                            | [`#[derive(ComponentType)]`][d-cm]   |
420/// | `flags`                           | [`flags!`][f-m]                      |
421///
422/// [`Resource<T>`]: crate::component::Resource
423/// [`ResourceAny`]: crate::component::ResourceAny
424/// [d-cm]: macro@crate::component::ComponentType
425/// [f-m]: crate::component::flags
426///
427/// Rust standard library pointers such as `&T`, `Box<T>`, and `Arc<T>`
428/// additionally represent whatever type `T` represents in the component model.
429/// Note that types such as `record`, `variant`, `enum`, and `flags` are
430/// generated by the embedder at compile time. These macros derive
431/// implementation of this trait for custom types to map to custom types in the
432/// component model. Note that for `record`, `variant`, `enum`, and `flags`
433/// those types are often generated by the
434/// [`bindgen!`](crate::component::bindgen) macro from WIT definitions.
435///
436/// Types that implement [`ComponentType`] are used for `Params` and `Return`
437/// in [`TypedFunc`] and [`Func::typed`].
438///
439/// The contents of this trait are hidden as it's intended to be an
440/// implementation detail of Wasmtime. The contents of this trait are not
441/// covered by Wasmtime's stability guarantees.
442///
443/// # Safety
444///
445/// Note that this is an `unsafe` trait as `TypedFunc`'s safety heavily relies on
446/// the correctness of the implementations of this trait. Some ways in which this
447/// trait must be correct to be safe are:
448///
449/// * The `Lower` associated type must be a `ValRaw` sequence. It doesn't have to
450///   literally be `[ValRaw; N]` but when laid out in memory it must be adjacent
451///   `ValRaw` values and have a multiple of the size of `ValRaw` and the same
452///   alignment.
453///
454/// * The `lower` function must initialize the bits within `Lower` that are going
455///   to be read by the trampoline that's used to enter core wasm. A trampoline
456///   is passed `*mut Lower` and will read the canonical abi arguments in
457///   sequence, so all of the bits must be correctly initialized.
458///
459/// * The `size` and `align` functions must be correct for this value stored in
460///   the canonical ABI. The `Cursor<T>` iteration of these bytes rely on this
461///   for correctness as they otherwise eschew bounds-checking.
462///
463/// There are likely some other correctness issues which aren't documented as
464/// well, this isn't currently an exhaustive list. It suffices to say, though,
465/// that correctness bugs in this trait implementation are highly likely to
466/// lead to security bugs, which again leads to the `unsafe` in the trait.
467///
468/// Note that this trait specifically is not sealed because `bindgen!`-generated
469/// types must be able to implement this trait using a `#[derive]` macro. For
470/// users it's recommended to not implement this trait manually given the
471/// non-exhaustive list of safety requirements that must be upheld. This trait
472/// is implemented at your own risk if you do so.
473///
474/// # Send and Sync
475///
476/// While on the topic of safety it's worth discussing the `Send` and `Sync`
477/// bounds here as well. These bounds might naively seem like they shouldn't be
478/// required for all component types as they're host-level types not guest-level
479/// types persisted anywhere. Various subtleties lead to these bounds, however:
480///
481/// * Fibers require that all stack-local variables are `Send` and `Sync` for
482///   fibers themselves to be send/sync. Unfortunately we have no help from the
483///   compiler on this one so it's up to Wasmtime's discipline to maintain this.
484///   One instance of this is that return values are placed on the stack as
485///   they're lowered into guest memory. This lowering operation can involve
486///   malloc and context switches, so return values must be Send/Sync.
487///
488/// * In the implementation of component model async it's not uncommon for types
489///   to be "buffered" in the store temporarily. For example parameters might
490///   reside in a store temporarily while wasm has backpressure turned on.
491///
492/// Overall it's generally easiest to require `Send` and `Sync` for all
493/// component types. There additionally aren't known use case for non-`Send` or
494/// non-`Sync` types at this time.
495pub unsafe trait ComponentType: Send + Sync {
496    /// Representation of the "lowered" form of this component value.
497    ///
498    /// Lowerings lower into core wasm values which are represented by `ValRaw`.
499    /// This `Lower` type must be a list of `ValRaw` as either a literal array
500    /// or a struct where every field is a `ValRaw`. This must be `Copy` (as
501    /// `ValRaw` is `Copy`) and support all byte patterns. This being correct is
502    /// one reason why the trait is unsafe.
503    #[doc(hidden)]
504    type Lower: Copy;
505
506    /// The information about this type's canonical ABI (size/align/etc).
507    #[doc(hidden)]
508    const ABI: CanonicalAbiInfo;
509
510    #[doc(hidden)]
511    const SIZE32: usize = Self::ABI.size32 as usize;
512    #[doc(hidden)]
513    const ALIGN32: u32 = Self::ABI.align32;
514
515    #[doc(hidden)]
516    const IS_RUST_UNIT_TYPE: bool = false;
517
518    /// Whether this type might require a call to the guest's realloc function
519    /// to allocate linear memory when lowering (e.g. a non-empty `string`).
520    ///
521    /// If this is `false`, Wasmtime may optimize lowering by using
522    /// `LowerContext::new_without_realloc` and lowering values outside of any
523    /// fiber.  That will panic if the lowering process ends up needing realloc
524    /// after all, so `true` is a conservative default.
525    #[doc(hidden)]
526    const MAY_REQUIRE_REALLOC: bool = true;
527
528    /// Returns the number of core wasm abi values will be used to represent
529    /// this type in its lowered form.
530    ///
531    /// This divides the size of `Self::Lower` by the size of `ValRaw`.
532    #[doc(hidden)]
533    fn flatten_count() -> usize {
534        assert!(mem::size_of::<Self::Lower>() % mem::size_of::<ValRaw>() == 0);
535        assert!(mem::align_of::<Self::Lower>() == mem::align_of::<ValRaw>());
536        mem::size_of::<Self::Lower>() / mem::size_of::<ValRaw>()
537    }
538
539    /// Performs a type-check to see whether this component value type matches
540    /// the interface type `ty` provided.
541    #[doc(hidden)]
542    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()>;
543}
544
545#[doc(hidden)]
546pub unsafe trait ComponentVariant: ComponentType {
547    const CASES: &'static [Option<CanonicalAbiInfo>];
548    const INFO: VariantInfo = VariantInfo::new_static(Self::CASES);
549    const PAYLOAD_OFFSET32: usize = Self::INFO.payload_offset32 as usize;
550}
551
552/// Host types which can be passed to WebAssembly components.
553///
554/// This trait is implemented for all types that can be passed to components
555/// either as parameters of component exports or returns of component imports.
556/// This trait represents the ability to convert from the native host
557/// representation to the canonical ABI.
558///
559/// Built-in types to Rust such as `Option<T>` implement this trait as
560/// appropriate. For a mapping of component model to Rust types see
561/// [`ComponentType`].
562///
563/// For user-defined types, for example `record` types mapped to Rust `struct`s,
564/// this crate additionally has
565/// [`#[derive(Lower)]`](macro@crate::component::Lower).
566///
567/// Note that like [`ComponentType`] the definition of this trait is intended to
568/// be an internal implementation detail of Wasmtime at this time. It's
569/// recommended to use the `#[derive(Lower)]` implementation instead.
570pub unsafe trait Lower: ComponentType {
571    /// Performs the "lower" function in the linear memory version of the
572    /// canonical ABI.
573    ///
574    /// This method will lower the current value into a component. The `lower`
575    /// function performs a "flat" lowering into the `dst` specified which is
576    /// allowed to be uninitialized entering this method but is guaranteed to be
577    /// fully initialized if the method returns `Ok(())`.
578    ///
579    /// The `cx` context provided is the context within which this lowering is
580    /// happening. This contains information such as canonical options specified
581    /// (e.g. string encodings, memories, etc), the store itself, along with
582    /// type information.
583    ///
584    /// The `ty` parameter is the destination type that is being lowered into.
585    /// For example this is the component's "view" of the type that is being
586    /// lowered. This is guaranteed to have passed a `typecheck` earlier.
587    ///
588    /// This will only be called if `typecheck` passes for `Op::Lower`.
589    #[doc(hidden)]
590    fn linear_lower_to_flat<T>(
591        &self,
592        cx: &mut LowerContext<'_, T>,
593        ty: InterfaceType,
594        dst: &mut MaybeUninit<Self::Lower>,
595    ) -> Result<()>;
596
597    /// Performs the "store" operation in the linear memory version of the
598    /// canonical ABI.
599    ///
600    /// This function will store `self` into the linear memory described by
601    /// `cx` at the `offset` provided.
602    ///
603    /// It is expected that `offset` is a valid offset in memory for
604    /// `Self::SIZE32` bytes. At this time that's not an unsafe contract as it's
605    /// always re-checked on all stores, but this is something that will need to
606    /// be improved in the future to remove extra bounds checks. For now this
607    /// function will panic if there's a bug and `offset` isn't valid within
608    /// memory.
609    ///
610    /// The `ty` type information passed here is the same as the type
611    /// information passed to `lower` above, and is the component's own view of
612    /// what the resulting type should be.
613    ///
614    /// This will only be called if `typecheck` passes for `Op::Lower`.
615    #[doc(hidden)]
616    fn linear_lower_to_memory<T>(
617        &self,
618        cx: &mut LowerContext<'_, T>,
619        ty: InterfaceType,
620        offset: usize,
621    ) -> Result<()>;
622
623    /// Provided method to lower a list of `Self` into memory.
624    ///
625    /// Requires that `offset` has already been checked for alignment and
626    /// validity in terms of being in-bounds, otherwise this may panic.
627    ///
628    /// This is primarily here to get overridden for implementations of integers
629    /// which can avoid some extra fluff and use a pattern that's more easily
630    /// optimizable by LLVM.
631    #[doc(hidden)]
632    fn linear_store_list_to_memory<T>(
633        cx: &mut LowerContext<'_, T>,
634        ty: InterfaceType,
635        mut offset: usize,
636        items: &[Self],
637    ) -> Result<()>
638    where
639        Self: Sized,
640    {
641        for item in items {
642            item.linear_lower_to_memory(cx, ty, offset)?;
643            offset += Self::SIZE32;
644        }
645        Ok(())
646    }
647}
648
649/// Host types which can be created from the canonical ABI.
650///
651/// This is the mirror of the [`Lower`] trait where it represents the capability
652/// of acquiring items from WebAssembly and passing them to the host.
653///
654/// Built-in types to Rust such as `Option<T>` implement this trait as
655/// appropriate. For a mapping of component model to Rust types see
656/// [`ComponentType`].
657///
658/// For user-defined types, for example `record` types mapped to Rust `struct`s,
659/// this crate additionally has
660/// [`#[derive(Lift)]`](macro@crate::component::Lift).
661///
662/// Note that like [`ComponentType`] the definition of this trait is intended to
663/// be an internal implementation detail of Wasmtime at this time. It's
664/// recommended to use the `#[derive(Lift)]` implementation instead.
665pub unsafe trait Lift: Sized + ComponentType {
666    /// Performs the "lift" operation in the linear memory version of the
667    /// canonical ABI.
668    ///
669    /// This function performs a "flat" lift operation from the `src` specified
670    /// which is a sequence of core wasm values. The lifting operation will
671    /// validate core wasm values and produce a `Self` on success.
672    ///
673    /// The `cx` provided contains contextual information such as the store
674    /// that's being loaded from, canonical options, and type information.
675    ///
676    /// The `ty` parameter is the origin component's specification for what the
677    /// type that is being lifted is. For example this is the record type or the
678    /// resource type that is being lifted.
679    ///
680    /// Note that this has a default implementation but if `typecheck` passes
681    /// for `Op::Lift` this needs to be overridden.
682    #[doc(hidden)]
683    fn linear_lift_from_flat(
684        cx: &mut LiftContext<'_>,
685        ty: InterfaceType,
686        src: &Self::Lower,
687    ) -> Result<Self>;
688
689    /// Performs the "load" operation in the linear memory version of the
690    /// canonical ABI.
691    ///
692    /// This will read the `bytes` provided, which are a sub-slice into the
693    /// linear memory described by `cx`. The `bytes` array provided is
694    /// guaranteed to be `Self::SIZE32` bytes large. All of memory is then also
695    /// available through `cx` for bounds-checks and such as necessary for
696    /// strings/lists.
697    ///
698    /// The `ty` argument is the type that's being loaded, as described by the
699    /// original component.
700    ///
701    /// Note that this has a default implementation but if `typecheck` passes
702    /// for `Op::Lift` this needs to be overridden.
703    #[doc(hidden)]
704    fn linear_lift_from_memory(
705        cx: &mut LiftContext<'_>,
706        ty: InterfaceType,
707        bytes: &[u8],
708    ) -> Result<Self>;
709
710    /// Converts `list` into a `Vec<T>`, used in `Lift for Vec<T>`.
711    #[doc(hidden)]
712    fn linear_lift_list_from_memory(
713        cx: &mut LiftContext<'_>,
714        list: &WasmList<Self>,
715    ) -> Result<Vec<Self>>
716    where
717        Self: Sized,
718    {
719        let mut dst = Vec::with_capacity(list.len);
720        Self::linear_lift_into_from_memory(cx, list, &mut dst)?;
721        Ok(dst)
722    }
723
724    /// Load no more than `max_count` items from `list` into `dst`.
725    ///
726    /// This is primarily here to get overridden for implementations of integers
727    /// which can avoid some extra fluff and use a pattern that's more easily
728    /// optimizable by LLVM.
729    #[doc(hidden)]
730    fn linear_lift_into_from_memory(
731        cx: &mut LiftContext<'_>,
732        list: &WasmList<Self>,
733        dst: &mut impl Extend<Self>,
734    ) -> Result<()>
735    where
736        Self: Sized,
737    {
738        for i in 0..list.len {
739            dst.extend(Some(list.get_from_store(cx, i).unwrap()?));
740        }
741        Ok(())
742    }
743}
744
745// Macro to help generate "forwarding implementations" of `ComponentType` to
746// another type, used for wrappers in Rust like `&T`, `Box<T>`, etc. Note that
747// these wrappers only implement lowering because lifting native Rust types
748// cannot be done.
749macro_rules! forward_type_impls {
750    ($(
751        $(#[$attr:meta])*
752        ($($generics:tt)*) $a:ty => $b:ty,
753    )*) => ($(
754        $(#[$attr])*
755        unsafe impl <$($generics)*> ComponentType for $a {
756            type Lower = <$b as ComponentType>::Lower;
757
758            const ABI: CanonicalAbiInfo = <$b as ComponentType>::ABI;
759            const MAY_REQUIRE_REALLOC: bool = <$b as ComponentType>::MAY_REQUIRE_REALLOC;
760
761            #[inline]
762            fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
763                <$b as ComponentType>::typecheck(ty, types)
764            }
765        }
766    )*)
767}
768
769forward_type_impls! {
770    (T: ComponentType + ?Sized) &'_ T => T,
771    (T: ComponentType + ?Sized) Box<T> => T,
772    (T: ComponentType + ?Sized) alloc::sync::Arc<T> => T,
773    () String => str,
774    (T: ComponentType) Vec<T> => [T],
775    #[cfg(feature = "component-model-bytes")]
776    () bytes::Bytes => [u8],
777    #[cfg(feature = "component-model-bytes")]
778    () bytes::BytesMut => [u8],
779}
780
781macro_rules! forward_lowers {
782    ($(
783        $(#[$attr:meta])*
784        ($($generics:tt)*) $a:ty => $b:ty,
785    )*) => ($(
786        $(#[$attr])*
787        unsafe impl <$($generics)*> Lower for $a {
788            fn linear_lower_to_flat<U>(
789                &self,
790                cx: &mut LowerContext<'_, U>,
791                ty: InterfaceType,
792                dst: &mut MaybeUninit<Self::Lower>,
793            ) -> Result<()> {
794                <$b as Lower>::linear_lower_to_flat(self, cx, ty, dst)
795            }
796
797            fn linear_lower_to_memory<U>(
798                &self,
799                cx: &mut LowerContext<'_, U>,
800                ty: InterfaceType,
801                offset: usize,
802            ) -> Result<()> {
803                <$b as Lower>::linear_lower_to_memory(self, cx, ty, offset)
804            }
805        }
806    )*)
807}
808
809forward_lowers! {
810    (T: Lower + ?Sized) &'_ T => T,
811    (T: Lower + ?Sized) Box<T> => T,
812    (T: Lower + ?Sized) alloc::sync::Arc<T> => T,
813    () String => str,
814    (T: Lower) Vec<T> => [T],
815    #[cfg(feature = "component-model-bytes")]
816    () bytes::Bytes => [u8],
817    #[cfg(feature = "component-model-bytes")]
818    () bytes::BytesMut => [u8],
819}
820
821macro_rules! forward_string_lifts {
822    ($($a:ty,)*) => ($(
823        unsafe impl Lift for $a {
824            #[inline]
825            fn linear_lift_from_flat(cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result<Self> {
826                let s = <WasmStr as Lift>::linear_lift_from_flat(cx, ty, src)?;
827                let encoding = cx.options().string_encoding;
828                Ok(s.to_str_from_memory(encoding, cx.memory())?.into())
829            }
830
831            #[inline]
832            fn linear_lift_from_memory(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Self> {
833                let s = <WasmStr as Lift>::linear_lift_from_memory(cx, ty, bytes)?;
834                let encoding = cx.options().string_encoding;
835                Ok(s.to_str_from_memory(encoding, cx.memory())?.into())
836            }
837        }
838    )*)
839}
840
841forward_string_lifts! {
842    Box<str>,
843    alloc::sync::Arc<str>,
844    String,
845}
846
847macro_rules! forward_list_lifts {
848    ($(
849        $(#[$attr:meta])*
850        ($($generics:tt)*) $a:ty => WasmList<$b:ty> $(( $via:ident $c:ty ))?,
851    )*) => ($(
852        $(#[$attr])*
853        unsafe impl <$($generics)*> Lift for $a {
854            fn linear_lift_from_flat(cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result<Self> {
855                let list = <WasmList::<$b> as Lift>::linear_lift_from_flat(cx, ty, src)?;
856                let vec = <$b>::linear_lift_list_from_memory(cx, &list)?;
857                $(let vec = <$c>::from(vec);)?
858                Ok(Self::from(vec))
859            }
860
861            fn linear_lift_from_memory(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Self> {
862                let list = <WasmList::<$b> as Lift>::linear_lift_from_memory(cx, ty, bytes)?;
863                let vec = <$b>::linear_lift_list_from_memory(cx, &list)?;
864                $(let vec = <$c>::from(vec);)?
865                Ok(Self::from(vec))
866            }
867        }
868    )*)
869}
870
871forward_list_lifts! {
872    (T: Lift) Box<[T]> => WasmList<T>,
873    (T: Lift) alloc::sync::Arc<[T]> => WasmList<T>,
874    (T: Lift) Vec<T> => WasmList<T>,
875    #[cfg(feature = "component-model-bytes")]
876    () bytes::Bytes => WasmList<u8>,
877    // Note that `From<Vec<u8>> for BytesMut` is missing from the `bytes` crate
878    // and this is the subject of tokio-rs/bytes#615
879    #[cfg(feature = "component-model-bytes")]
880    () bytes::BytesMut => WasmList<u8> (via bytes::Bytes),
881}
882
883// Macro to help generate `ComponentType` implementations for primitive types
884// such as integers, char, bool, etc.
885macro_rules! integers {
886    ($($primitive:ident = $ty:ident in $field:ident/$get:ident with abi:$abi:ident,)*) => ($(
887        unsafe impl ComponentType for $primitive {
888            type Lower = ValRaw;
889
890            const ABI: CanonicalAbiInfo = CanonicalAbiInfo::$abi;
891
892            const MAY_REQUIRE_REALLOC: bool = false;
893
894            fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
895                match ty {
896                    InterfaceType::$ty => Ok(()),
897                    other => bail!("expected `{}` found `{}`", desc(&InterfaceType::$ty), desc(other))
898                }
899            }
900        }
901
902        unsafe impl Lower for $primitive {
903            #[inline]
904            #[allow(trivial_numeric_casts, reason = "macro-generated code")]
905            fn linear_lower_to_flat<T>(
906                &self,
907                _cx: &mut LowerContext<'_, T>,
908                ty: InterfaceType,
909                dst: &mut MaybeUninit<Self::Lower>,
910            ) -> Result<()> {
911                debug_assert!(matches!(ty, InterfaceType::$ty));
912                dst.write(ValRaw::$field(*self as $field));
913                Ok(())
914            }
915
916            #[inline]
917            fn linear_lower_to_memory<T>(
918                &self,
919                cx: &mut LowerContext<'_, T>,
920                ty: InterfaceType,
921                offset: usize,
922            ) -> Result<()> {
923                debug_assert!(matches!(ty, InterfaceType::$ty));
924                debug_assert!(offset % Self::SIZE32 == 0);
925                *cx.get(offset) = self.to_le_bytes();
926                Ok(())
927            }
928
929            fn linear_store_list_to_memory<T>(
930                cx: &mut LowerContext<'_, T>,
931                ty: InterfaceType,
932                offset: usize,
933                items: &[Self],
934            ) -> Result<()> {
935                debug_assert!(matches!(ty, InterfaceType::$ty));
936
937                // Double-check that the CM alignment is at least the host's
938                // alignment for this type which should be true for all
939                // platforms.
940                assert!((Self::ALIGN32 as usize) >= mem::align_of::<Self>());
941
942                // Slice `cx`'s memory to the window that we'll be modifying.
943                // This should all have already been verified in terms of
944                // alignment and sizing meaning that these assertions here are
945                // not truly necessary but are instead double-checks.
946                //
947                // Note that we're casting a `[u8]` slice to `[Self]` with
948                // `align_to_mut` which is not safe in general but is safe in
949                // our specific case as all `u8` patterns are valid `Self`
950                // patterns since `Self` is an integral type.
951                let dst = &mut cx.as_slice_mut()[offset..][..items.len() * Self::SIZE32];
952                let (before, middle, end) = unsafe { dst.align_to_mut::<Self>() };
953                assert!(before.is_empty() && end.is_empty());
954                assert_eq!(middle.len(), items.len());
955
956                // And with all that out of the way perform the copying loop.
957                // This is not a `copy_from_slice` because endianness needs to
958                // be handled here, but LLVM should pretty easily transform this
959                // into a memcpy on little-endian platforms.
960                for (dst, src) in middle.iter_mut().zip(items) {
961                    *dst = src.to_le();
962                }
963                Ok(())
964            }
965        }
966
967        unsafe impl Lift for $primitive {
968            #[inline]
969            #[allow(
970                trivial_numeric_casts,
971                clippy::cast_possible_truncation,
972                reason = "macro-generated code"
973            )]
974            fn linear_lift_from_flat(_cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result<Self> {
975                debug_assert!(matches!(ty, InterfaceType::$ty));
976                Ok(src.$get() as $primitive)
977            }
978
979            #[inline]
980            fn linear_lift_from_memory(_cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Self> {
981                debug_assert!(matches!(ty, InterfaceType::$ty));
982                debug_assert!((bytes.as_ptr() as usize) % Self::SIZE32 == 0);
983                Ok($primitive::from_le_bytes(*bytes.as_array().unwrap()))
984            }
985
986            fn linear_lift_into_from_memory(
987                cx: &mut LiftContext<'_>,
988                list: &WasmList<Self>,
989                dst: &mut impl Extend<Self>,
990            ) -> Result<()>
991            where
992                Self: Sized,
993            {
994                dst.extend(list._as_le_slice(cx.memory())
995                           .iter()
996                           .map(|i| Self::from_le(*i)));
997                Ok(())
998            }
999        }
1000    )*)
1001}
1002
1003integers! {
1004    i8 = S8 in i32/get_i32 with abi:SCALAR1,
1005    u8 = U8 in u32/get_u32 with abi:SCALAR1,
1006    i16 = S16 in i32/get_i32 with abi:SCALAR2,
1007    u16 = U16 in u32/get_u32 with abi:SCALAR2,
1008    i32 = S32 in i32/get_i32 with abi:SCALAR4,
1009    u32 = U32 in u32/get_u32 with abi:SCALAR4,
1010    i64 = S64 in i64/get_i64 with abi:SCALAR8,
1011    u64 = U64 in u64/get_u64 with abi:SCALAR8,
1012}
1013
1014macro_rules! floats {
1015    ($($float:ident/$get_float:ident = $ty:ident with abi:$abi:ident)*) => ($(const _: () = {
1016        unsafe impl ComponentType for $float {
1017            type Lower = ValRaw;
1018
1019            const ABI: CanonicalAbiInfo = CanonicalAbiInfo::$abi;
1020            const MAY_REQUIRE_REALLOC: bool = false;
1021
1022            fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
1023                match ty {
1024                    InterfaceType::$ty => Ok(()),
1025                    other => bail!("expected `{}` found `{}`", desc(&InterfaceType::$ty), desc(other))
1026                }
1027            }
1028        }
1029
1030        unsafe impl Lower for $float {
1031            #[inline]
1032            fn linear_lower_to_flat<T>(
1033                &self,
1034                _cx: &mut LowerContext<'_, T>,
1035                ty: InterfaceType,
1036                dst: &mut MaybeUninit<Self::Lower>,
1037            ) -> Result<()> {
1038                debug_assert!(matches!(ty, InterfaceType::$ty));
1039                dst.write(ValRaw::$float(self.to_bits()));
1040                Ok(())
1041            }
1042
1043            #[inline]
1044            fn linear_lower_to_memory<T>(
1045                &self,
1046                cx: &mut LowerContext<'_, T>,
1047                ty: InterfaceType,
1048                offset: usize,
1049            ) -> Result<()> {
1050                debug_assert!(matches!(ty, InterfaceType::$ty));
1051                debug_assert!(offset % Self::SIZE32 == 0);
1052                let ptr = cx.get(offset);
1053                *ptr = self.to_bits().to_le_bytes();
1054                Ok(())
1055            }
1056
1057            fn linear_store_list_to_memory<T>(
1058                cx: &mut LowerContext<'_, T>,
1059                ty: InterfaceType,
1060                offset: usize,
1061                items: &[Self],
1062            ) -> Result<()> {
1063                debug_assert!(matches!(ty, InterfaceType::$ty));
1064
1065                // Double-check that the CM alignment is at least the host's
1066                // alignment for this type which should be true for all
1067                // platforms.
1068                assert!((Self::ALIGN32 as usize) >= mem::align_of::<Self>());
1069
1070                // Slice `cx`'s memory to the window that we'll be modifying.
1071                // This should all have already been verified in terms of
1072                // alignment and sizing meaning that these assertions here are
1073                // not truly necessary but are instead double-checks.
1074                let dst = &mut cx.as_slice_mut()[offset..][..items.len() * Self::SIZE32];
1075                assert!(dst.as_ptr().cast::<Self>().is_aligned());
1076
1077                // And with all that out of the way perform the copying loop.
1078                // This is not a `copy_from_slice` because endianness needs to
1079                // be handled here, but LLVM should pretty easily transform this
1080                // into a memcpy on little-endian platforms.
1081                // TODO use `as_chunks` when https://github.com/rust-lang/rust/issues/74985
1082                // is stabilized
1083                let (dst, rest) = dst.as_chunks_mut::<{Self::SIZE32}>();
1084                debug_assert!(rest.is_empty());
1085                for (dst, src) in iter::zip(dst, items) {
1086                    *dst = src.to_le_bytes();
1087                }
1088                Ok(())
1089            }
1090        }
1091
1092        unsafe impl Lift for $float {
1093            #[inline]
1094            fn linear_lift_from_flat(_cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result<Self> {
1095                debug_assert!(matches!(ty, InterfaceType::$ty));
1096                Ok($float::from_bits(src.$get_float()))
1097            }
1098
1099            #[inline]
1100            fn linear_lift_from_memory(_cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Self> {
1101                debug_assert!(matches!(ty, InterfaceType::$ty));
1102                debug_assert!((bytes.as_ptr() as usize) % Self::SIZE32 == 0);
1103                Ok($float::from_le_bytes(*bytes.as_array().unwrap()))
1104            }
1105
1106            fn linear_lift_list_from_memory(cx: &mut LiftContext<'_>, list: &WasmList<Self>) -> Result<Vec<Self>> where Self: Sized {
1107                // See comments in `WasmList::get` for the panicking indexing
1108                let byte_size = list.len * mem::size_of::<Self>();
1109                let bytes = &cx.memory()[list.ptr..][..byte_size];
1110
1111                // The canonical ABI requires that everything is aligned to its
1112                // own size, so this should be an aligned array.
1113                assert!(bytes.as_ptr().cast::<Self>().is_aligned());
1114
1115                // Copy the resulting slice to a new Vec, handling endianness
1116                // in the process
1117                // TODO use `as_chunks` when https://github.com/rust-lang/rust/issues/74985
1118                // is stabilized
1119                Ok(
1120                    bytes
1121                        .chunks_exact(Self::SIZE32)
1122                        .map(|i| $float::from_le_bytes(*i.as_array().unwrap()))
1123                        .collect()
1124                )
1125            }
1126        }
1127    };)*)
1128}
1129
1130floats! {
1131    f32/get_f32 = Float32 with abi:SCALAR4
1132    f64/get_f64 = Float64 with abi:SCALAR8
1133}
1134
1135unsafe impl ComponentType for bool {
1136    type Lower = ValRaw;
1137
1138    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::SCALAR1;
1139    const MAY_REQUIRE_REALLOC: bool = false;
1140
1141    fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
1142        match ty {
1143            InterfaceType::Bool => Ok(()),
1144            other => bail!("expected `bool` found `{}`", desc(other)),
1145        }
1146    }
1147}
1148
1149unsafe impl Lower for bool {
1150    fn linear_lower_to_flat<T>(
1151        &self,
1152        _cx: &mut LowerContext<'_, T>,
1153        ty: InterfaceType,
1154        dst: &mut MaybeUninit<Self::Lower>,
1155    ) -> Result<()> {
1156        debug_assert!(matches!(ty, InterfaceType::Bool));
1157        dst.write(ValRaw::i32(*self as i32));
1158        Ok(())
1159    }
1160
1161    fn linear_lower_to_memory<T>(
1162        &self,
1163        cx: &mut LowerContext<'_, T>,
1164        ty: InterfaceType,
1165        offset: usize,
1166    ) -> Result<()> {
1167        debug_assert!(matches!(ty, InterfaceType::Bool));
1168        debug_assert!(offset % Self::SIZE32 == 0);
1169        cx.get::<1>(offset)[0] = *self as u8;
1170        Ok(())
1171    }
1172}
1173
1174unsafe impl Lift for bool {
1175    #[inline]
1176    fn linear_lift_from_flat(
1177        _cx: &mut LiftContext<'_>,
1178        ty: InterfaceType,
1179        src: &Self::Lower,
1180    ) -> Result<Self> {
1181        debug_assert!(matches!(ty, InterfaceType::Bool));
1182        match src.get_i32() {
1183            0 => Ok(false),
1184            _ => Ok(true),
1185        }
1186    }
1187
1188    #[inline]
1189    fn linear_lift_from_memory(
1190        _cx: &mut LiftContext<'_>,
1191        ty: InterfaceType,
1192        bytes: &[u8],
1193    ) -> Result<Self> {
1194        debug_assert!(matches!(ty, InterfaceType::Bool));
1195        match bytes[0] {
1196            0 => Ok(false),
1197            _ => Ok(true),
1198        }
1199    }
1200}
1201
1202unsafe impl ComponentType for char {
1203    type Lower = ValRaw;
1204
1205    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::SCALAR4;
1206    const MAY_REQUIRE_REALLOC: bool = false;
1207
1208    fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
1209        match ty {
1210            InterfaceType::Char => Ok(()),
1211            other => bail!("expected `char` found `{}`", desc(other)),
1212        }
1213    }
1214}
1215
1216unsafe impl Lower for char {
1217    #[inline]
1218    fn linear_lower_to_flat<T>(
1219        &self,
1220        _cx: &mut LowerContext<'_, T>,
1221        ty: InterfaceType,
1222        dst: &mut MaybeUninit<Self::Lower>,
1223    ) -> Result<()> {
1224        debug_assert!(matches!(ty, InterfaceType::Char));
1225        dst.write(ValRaw::u32(u32::from(*self)));
1226        Ok(())
1227    }
1228
1229    #[inline]
1230    fn linear_lower_to_memory<T>(
1231        &self,
1232        cx: &mut LowerContext<'_, T>,
1233        ty: InterfaceType,
1234        offset: usize,
1235    ) -> Result<()> {
1236        debug_assert!(matches!(ty, InterfaceType::Char));
1237        debug_assert!(offset % Self::SIZE32 == 0);
1238        *cx.get::<4>(offset) = u32::from(*self).to_le_bytes();
1239        Ok(())
1240    }
1241}
1242
1243unsafe impl Lift for char {
1244    #[inline]
1245    fn linear_lift_from_flat(
1246        _cx: &mut LiftContext<'_>,
1247        ty: InterfaceType,
1248        src: &Self::Lower,
1249    ) -> Result<Self> {
1250        debug_assert!(matches!(ty, InterfaceType::Char));
1251        Ok(char::try_from(src.get_u32())?)
1252    }
1253
1254    #[inline]
1255    fn linear_lift_from_memory(
1256        _cx: &mut LiftContext<'_>,
1257        ty: InterfaceType,
1258        bytes: &[u8],
1259    ) -> Result<Self> {
1260        debug_assert!(matches!(ty, InterfaceType::Char));
1261        debug_assert!((bytes.as_ptr() as usize) % Self::SIZE32 == 0);
1262        let bits = u32::from_le_bytes(*bytes.as_array().unwrap());
1263        Ok(char::try_from(bits)?)
1264    }
1265}
1266
1267fn lift_pointer_pair_from_flat(
1268    cx: &mut LiftContext<'_>,
1269    src: &[ValRaw; 2],
1270) -> Result<(usize, usize)> {
1271    // FIXME(#4311): needs memory64 treatment
1272    let _ = cx; // this will be needed for memory64 in the future
1273    let ptr = src[0].get_u32();
1274    let len = src[1].get_u32();
1275    Ok((usize::try_from(ptr)?, usize::try_from(len)?))
1276}
1277
1278fn lift_pointer_pair_from_memory(cx: &mut LiftContext<'_>, bytes: &[u8]) -> Result<(usize, usize)> {
1279    // FIXME(#4311): needs memory64 treatment
1280    let _ = cx; // this will be needed for memory64 in the future
1281    let ptr = u32::from_le_bytes(*bytes[..4].as_array().unwrap());
1282    let len = u32::from_le_bytes(*bytes[4..].as_array().unwrap());
1283    Ok((usize::try_from(ptr)?, usize::try_from(len)?))
1284}
1285
1286fn lower_pointer_pair_to_flat<T>(
1287    cx: &mut LowerContext<T>,
1288    dst: &mut MaybeUninit<[ValRaw; 2]>,
1289    ptr: usize,
1290    len: usize,
1291) {
1292    // See "WRITEPTR64" above for why this is always storing a 64-bit
1293    // integer.
1294    let _ = cx; // this will eventually be needed for memory64 information.
1295    map_maybe_uninit!(dst[0]).write(ValRaw::i64(ptr as i64));
1296    map_maybe_uninit!(dst[1]).write(ValRaw::i64(len as i64));
1297}
1298
1299fn lower_pointer_pair_to_memory<T>(
1300    cx: &mut LowerContext<T>,
1301    offset: usize,
1302    ptr: usize,
1303    len: usize,
1304) {
1305    // FIXME(#4311): needs memory64 handling
1306    *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
1307    *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
1308}
1309
1310// FIXME(#4311): these probably need different constants for memory64
1311const UTF16_TAG: usize = 1 << 31;
1312const MAX_STRING_BYTE_LENGTH: usize = (1 << 31) - 1;
1313
1314// Note that this is similar to `ComponentType for WasmStr` except it can only
1315// be used for lowering, not lifting.
1316unsafe impl ComponentType for str {
1317    type Lower = [ValRaw; 2];
1318
1319    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
1320
1321    fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
1322        match ty {
1323            InterfaceType::String => Ok(()),
1324            other => bail!("expected `string` found `{}`", desc(other)),
1325        }
1326    }
1327}
1328
1329unsafe impl Lower for str {
1330    fn linear_lower_to_flat<T>(
1331        &self,
1332        cx: &mut LowerContext<'_, T>,
1333        ty: InterfaceType,
1334        dst: &mut MaybeUninit<[ValRaw; 2]>,
1335    ) -> Result<()> {
1336        debug_assert!(matches!(ty, InterfaceType::String));
1337        let (ptr, len) = lower_string(cx, self)?;
1338        lower_pointer_pair_to_flat(cx, dst, ptr, len);
1339        Ok(())
1340    }
1341
1342    fn linear_lower_to_memory<T>(
1343        &self,
1344        cx: &mut LowerContext<'_, T>,
1345        ty: InterfaceType,
1346        offset: usize,
1347    ) -> Result<()> {
1348        debug_assert!(matches!(ty, InterfaceType::String));
1349        debug_assert!(offset % (Self::ALIGN32 as usize) == 0);
1350        let (ptr, len) = lower_string(cx, self)?;
1351        lower_pointer_pair_to_memory(cx, offset, ptr, len);
1352        Ok(())
1353    }
1354}
1355
1356fn lower_string<T>(cx: &mut LowerContext<'_, T>, string: &str) -> Result<(usize, usize)> {
1357    // Note that in general the wasm module can't assume anything about what the
1358    // host strings are encoded as. Additionally hosts are allowed to have
1359    // differently-encoded strings at runtime. Finally when copying a string
1360    // into wasm it's somewhat strict in the sense that the various patterns of
1361    // allocation and such are already dictated for us.
1362    //
1363    // In general what this means is that when copying a string from the host
1364    // into the destination we need to follow one of the cases of copying into
1365    // WebAssembly. It doesn't particularly matter which case as long as it ends
1366    // up in the right encoding. For example a destination encoding of
1367    // latin1+utf16 has a number of ways to get copied into and we do something
1368    // here that isn't the default "utf8 to latin1+utf16" since we have access
1369    // to simd-accelerated helpers in the `encoding_rs` crate. This is ok though
1370    // because we can fake that the host string was already stored in latin1
1371    // format and follow that copy pattern instead.
1372    match cx.options().string_encoding {
1373        // This corresponds to `store_string_copy` in the canonical ABI where
1374        // the host's representation is utf-8 and the wasm module wants utf-8 so
1375        // a copy is all that's needed (and the `realloc` can be precise for the
1376        // initial memory allocation).
1377        StringEncoding::Utf8 => {
1378            if string.len() > MAX_STRING_BYTE_LENGTH {
1379                bail!(
1380                    "string length of {} too large to copy into wasm",
1381                    string.len()
1382                );
1383            }
1384            let ptr = cx.realloc(0, 0, 1, string.len())?;
1385            cx.as_slice_mut()[ptr..][..string.len()].copy_from_slice(string.as_bytes());
1386            Ok((ptr, string.len()))
1387        }
1388
1389        // This corresponds to `store_utf8_to_utf16` in the canonical ABI. Here
1390        // an over-large allocation is performed and then shrunk afterwards if
1391        // necessary.
1392        StringEncoding::Utf16 => {
1393            let size = string.len() * 2;
1394            if size > MAX_STRING_BYTE_LENGTH {
1395                bail!(
1396                    "string length of {} too large to copy into wasm",
1397                    string.len()
1398                );
1399            }
1400            let mut ptr = cx.realloc(0, 0, 2, size)?;
1401            let mut copied = 0;
1402            let bytes = &mut cx.as_slice_mut()[ptr..][..size];
1403            for (u, bytes) in string.encode_utf16().zip(bytes.chunks_mut(2)) {
1404                let u_bytes = u.to_le_bytes();
1405                bytes[0] = u_bytes[0];
1406                bytes[1] = u_bytes[1];
1407                copied += 1;
1408            }
1409            if (copied * 2) < size {
1410                ptr = cx.realloc(ptr, size, 2, copied * 2)?;
1411            }
1412            Ok((ptr, copied))
1413        }
1414
1415        StringEncoding::CompactUtf16 => {
1416            // This corresponds to `store_string_to_latin1_or_utf16`
1417            let bytes = string.as_bytes();
1418            let mut iter = string.char_indices();
1419            let mut ptr = cx.realloc(0, 0, 2, bytes.len())?;
1420            let mut dst = &mut cx.as_slice_mut()[ptr..][..bytes.len()];
1421            let mut result = 0;
1422            while let Some((i, ch)) = iter.next() {
1423                // Test if this `char` fits into the latin1 encoding.
1424                if let Ok(byte) = u8::try_from(u32::from(ch)) {
1425                    dst[result] = byte;
1426                    result += 1;
1427                    continue;
1428                }
1429
1430                // .. if utf16 is forced to be used then the allocation is
1431                // bumped up to the maximum size.
1432                let worst_case = bytes
1433                    .len()
1434                    .checked_mul(2)
1435                    .ok_or_else(|| format_err!("byte length overflow"))?;
1436                if worst_case > MAX_STRING_BYTE_LENGTH {
1437                    bail!("byte length too large");
1438                }
1439                ptr = cx.realloc(ptr, bytes.len(), 2, worst_case)?;
1440                dst = &mut cx.as_slice_mut()[ptr..][..worst_case];
1441
1442                // Previously encoded latin1 bytes are inflated to their 16-bit
1443                // size for utf16
1444                for i in (0..result).rev() {
1445                    dst[2 * i] = dst[i];
1446                    dst[2 * i + 1] = 0;
1447                }
1448
1449                // and then the remainder of the string is encoded.
1450                for (u, bytes) in string[i..]
1451                    .encode_utf16()
1452                    .zip(dst[2 * result..].chunks_mut(2))
1453                {
1454                    let u_bytes = u.to_le_bytes();
1455                    bytes[0] = u_bytes[0];
1456                    bytes[1] = u_bytes[1];
1457                    result += 1;
1458                }
1459                if worst_case > 2 * result {
1460                    ptr = cx.realloc(ptr, worst_case, 2, 2 * result)?;
1461                }
1462                return Ok((ptr, result | UTF16_TAG));
1463            }
1464            if result < bytes.len() {
1465                ptr = cx.realloc(ptr, bytes.len(), 2, result)?;
1466            }
1467            Ok((ptr, result))
1468        }
1469    }
1470}
1471
1472/// Representation of a string located in linear memory in a WebAssembly
1473/// instance.
1474///
1475/// This type can be used in place of `String` and `str` for string-taking APIs
1476/// in some situations. The purpose of this type is to represent a range of
1477/// validated bytes within a component but does not actually copy the bytes. The
1478/// primary method, [`WasmStr::to_str`], attempts to return a reference to the
1479/// string directly located in the component's memory, avoiding a copy into the
1480/// host if possible.
1481///
1482/// The downside of this type, however, is that accessing a string requires a
1483/// [`Store`](crate::Store) pointer (via [`StoreContext`]). Bindings generated
1484/// by [`bindgen!`](crate::component::bindgen), for example, do not have access
1485/// to [`StoreContext`] and thus can't use this type.
1486///
1487/// This is intended for more advanced use cases such as defining functions
1488/// directly in a [`Linker`](crate::component::Linker). It's expected that in
1489/// the future [`bindgen!`](crate::component::bindgen) will also have a way to
1490/// use this type.
1491///
1492/// This type is used with [`TypedFunc`], for example, when WebAssembly returns
1493/// a string. This type cannot be used to give a string to WebAssembly, instead
1494/// `&str` should be used for that (since it's coming from the host).
1495///
1496/// Note that this type represents an in-bounds string in linear memory, but it
1497/// does not represent a valid string (e.g. valid utf-8). Validation happens
1498/// when [`WasmStr::to_str`] is called.
1499///
1500/// Also note that this type does not implement [`Lower`], it only implements
1501/// [`Lift`].
1502pub struct WasmStr {
1503    ptr: usize,
1504    len: usize,
1505    options: OptionsIndex,
1506    instance: Instance,
1507}
1508
1509impl WasmStr {
1510    pub(crate) fn new(ptr: usize, len: usize, cx: &mut LiftContext<'_>) -> Result<WasmStr> {
1511        let (byte_len, align) = match cx.options().string_encoding {
1512            StringEncoding::Utf8 => (Some(len), 1_usize),
1513            StringEncoding::Utf16 => (len.checked_mul(2), 2),
1514            StringEncoding::CompactUtf16 => {
1515                if len & UTF16_TAG == 0 {
1516                    (Some(len), 2)
1517                } else {
1518                    ((len ^ UTF16_TAG).checked_mul(2), 2)
1519                }
1520            }
1521        };
1522        debug_assert!(align.is_power_of_two());
1523        if ptr & (align - 1) != 0 {
1524            bail!("string pointer not aligned to {align}");
1525        }
1526        match byte_len.and_then(|len| ptr.checked_add(len)) {
1527            Some(n) if n <= cx.memory().len() => cx.consume_fuel(n - ptr)?,
1528            _ => bail!("string pointer/length out of bounds of memory"),
1529        }
1530        Ok(WasmStr {
1531            ptr,
1532            len,
1533            options: cx.options_index(),
1534            instance: cx.instance_handle(),
1535        })
1536    }
1537
1538    /// Returns the underlying string that this cursor points to.
1539    ///
1540    /// Note that this will internally decode the string from the wasm's
1541    /// encoding to utf-8 and additionally perform validation.
1542    ///
1543    /// The `store` provided must be the store where this string lives to
1544    /// access the correct memory.
1545    ///
1546    /// # Errors
1547    ///
1548    /// Returns an error if the string wasn't encoded correctly (e.g. invalid
1549    /// utf-8).
1550    ///
1551    /// # Panics
1552    ///
1553    /// Panics if this string is not owned by `store`.
1554    //
1555    // TODO: should add accessors for specifically utf-8 and utf-16 that perhaps
1556    // in an opt-in basis don't do validation. Additionally there should be some
1557    // method that returns `[u16]` after validating to avoid the utf16-to-utf8
1558    // transcode.
1559    pub fn to_str<'a, T: 'static>(
1560        &self,
1561        store: impl Into<StoreContext<'a, T>>,
1562    ) -> Result<Cow<'a, str>> {
1563        let store = store.into().0;
1564        let memory = self.instance.options_memory(store, self.options);
1565        let encoding = self.instance.options(store, self.options).string_encoding;
1566        self.to_str_from_memory(encoding, memory)
1567    }
1568
1569    pub(crate) fn to_str_from_memory<'a>(
1570        &self,
1571        encoding: StringEncoding,
1572        memory: &'a [u8],
1573    ) -> Result<Cow<'a, str>> {
1574        match encoding {
1575            StringEncoding::Utf8 => self.decode_utf8(memory),
1576            StringEncoding::Utf16 => self.decode_utf16(memory, self.len),
1577            StringEncoding::CompactUtf16 => {
1578                if self.len & UTF16_TAG == 0 {
1579                    self.decode_latin1(memory)
1580                } else {
1581                    self.decode_utf16(memory, self.len ^ UTF16_TAG)
1582                }
1583            }
1584        }
1585    }
1586
1587    fn decode_utf8<'a>(&self, memory: &'a [u8]) -> Result<Cow<'a, str>> {
1588        // Note that bounds-checking already happen in construction of `WasmStr`
1589        // so this is never expected to panic. This could theoretically be
1590        // unchecked indexing if we're feeling wild enough.
1591        Ok(str::from_utf8(&memory[self.ptr..][..self.len])?.into())
1592    }
1593
1594    fn decode_utf16<'a>(&self, memory: &'a [u8], len: usize) -> Result<Cow<'a, str>> {
1595        // See notes in `decode_utf8` for why this is panicking indexing.
1596        let (chunks, rest) = &memory[self.ptr..][..len * 2].as_chunks::<2>();
1597        debug_assert!(rest.is_empty());
1598        Ok(
1599            core::char::decode_utf16(chunks.iter().map(|chunk| u16::from_le_bytes(*chunk)))
1600                .collect::<Result<String, _>>()?
1601                .into(),
1602        )
1603    }
1604
1605    fn decode_latin1<'a>(&self, memory: &'a [u8]) -> Result<Cow<'a, str>> {
1606        // See notes in `decode_utf8` for why this is panicking indexing.
1607        Ok(encoding_rs::mem::decode_latin1(
1608            &memory[self.ptr..][..self.len],
1609        ))
1610    }
1611}
1612
1613// Note that this is similar to `ComponentType for str` except it can only be
1614// used for lifting, not lowering.
1615unsafe impl ComponentType for WasmStr {
1616    type Lower = <str as ComponentType>::Lower;
1617
1618    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
1619
1620    fn typecheck(ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
1621        match ty {
1622            InterfaceType::String => Ok(()),
1623            other => bail!("expected `string` found `{}`", desc(other)),
1624        }
1625    }
1626}
1627
1628unsafe impl Lift for WasmStr {
1629    #[inline]
1630    fn linear_lift_from_flat(
1631        cx: &mut LiftContext<'_>,
1632        ty: InterfaceType,
1633        src: &Self::Lower,
1634    ) -> Result<Self> {
1635        debug_assert!(matches!(ty, InterfaceType::String));
1636        let (ptr, len) = lift_pointer_pair_from_flat(cx, src)?;
1637        WasmStr::new(ptr, len, cx)
1638    }
1639
1640    #[inline]
1641    fn linear_lift_from_memory(
1642        cx: &mut LiftContext<'_>,
1643        ty: InterfaceType,
1644        bytes: &[u8],
1645    ) -> Result<Self> {
1646        debug_assert!(matches!(ty, InterfaceType::String));
1647        debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
1648        let (ptr, len) = lift_pointer_pair_from_memory(cx, bytes)?;
1649        WasmStr::new(ptr, len, cx)
1650    }
1651}
1652
1653unsafe impl<T> ComponentType for [T]
1654where
1655    T: ComponentType,
1656{
1657    type Lower = [ValRaw; 2];
1658
1659    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
1660
1661    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
1662        match ty {
1663            InterfaceType::List(t) => T::typecheck(&types.types[*t].element, types),
1664            other => bail!("expected `list` found `{}`", desc(other)),
1665        }
1666    }
1667}
1668
1669unsafe impl<T> Lower for [T]
1670where
1671    T: Lower,
1672{
1673    fn linear_lower_to_flat<U>(
1674        &self,
1675        cx: &mut LowerContext<'_, U>,
1676        ty: InterfaceType,
1677        dst: &mut MaybeUninit<[ValRaw; 2]>,
1678    ) -> Result<()> {
1679        let elem = match ty {
1680            InterfaceType::List(i) => cx.types[i].element,
1681            _ => bad_type_info(),
1682        };
1683        let (ptr, len) = lower_list(cx, elem, self)?;
1684        lower_pointer_pair_to_flat(cx, dst, ptr, len);
1685        Ok(())
1686    }
1687
1688    fn linear_lower_to_memory<U>(
1689        &self,
1690        cx: &mut LowerContext<'_, U>,
1691        ty: InterfaceType,
1692        offset: usize,
1693    ) -> Result<()> {
1694        let elem = match ty {
1695            InterfaceType::List(i) => cx.types[i].element,
1696            _ => bad_type_info(),
1697        };
1698        debug_assert!(offset % (Self::ALIGN32 as usize) == 0);
1699        let (ptr, len) = lower_list(cx, elem, self)?;
1700        lower_pointer_pair_to_memory(cx, offset, ptr, len);
1701        Ok(())
1702    }
1703}
1704
1705// FIXME: this is not a memcpy for `T` where `T` is something like `u8`.
1706//
1707// Some attempts to fix this have proved not fruitful. In isolation an attempt
1708// was made where:
1709//
1710// * `MemoryMut` stored a `*mut [u8]` as its "last view" of memory to avoid
1711//   reloading the base pointer constantly. This view is reset on `realloc`.
1712// * The bounds-checks in `MemoryMut::get` were removed (replaced with unsafe
1713//   indexing)
1714//
1715// Even then though this didn't correctly vectorized for `Vec<u8>`. It's not
1716// entirely clear why but it appeared that it's related to reloading the base
1717// pointer to memory (I guess from `MemoryMut` itself?). Overall I'm not really
1718// clear on what's happening there, but this is surely going to be a performance
1719// bottleneck in the future.
1720fn lower_list<T, U>(
1721    cx: &mut LowerContext<'_, U>,
1722    ty: InterfaceType,
1723    list: &[T],
1724) -> Result<(usize, usize)>
1725where
1726    T: Lower,
1727{
1728    let elem_size = T::SIZE32;
1729    let size = list
1730        .len()
1731        .checked_mul(elem_size)
1732        .ok_or_else(|| format_err!("size overflow copying a list"))?;
1733    let ptr = cx.realloc(0, 0, T::ALIGN32, size)?;
1734    T::linear_store_list_to_memory(cx, ty, ptr, list)?;
1735    Ok((ptr, list.len()))
1736}
1737
1738/// Representation of a list of values that are owned by a WebAssembly instance.
1739///
1740/// For some more commentary about the rationale for this type see the
1741/// documentation of [`WasmStr`]. In summary this type can avoid a copy when
1742/// passing data to the host in some situations but is additionally more
1743/// cumbersome to use by requiring a [`Store`](crate::Store) to be provided.
1744///
1745/// This type is used whenever a `(list T)` is returned from a [`TypedFunc`],
1746/// for example. This type represents a list of values that are stored in linear
1747/// memory which are waiting to be read.
1748///
1749/// Note that this type represents only a valid range of bytes for the list
1750/// itself, it does not represent validity of the elements themselves and that's
1751/// performed when they're iterated.
1752///
1753/// Note that this type does not implement the [`Lower`] trait, only [`Lift`].
1754pub struct WasmList<T> {
1755    ptr: usize,
1756    len: usize,
1757    options: OptionsIndex,
1758    elem: InterfaceType,
1759    instance: Instance,
1760    _marker: marker::PhantomData<T>,
1761}
1762
1763impl<T: Lift> WasmList<T> {
1764    pub(crate) fn new(
1765        ptr: usize,
1766        len: usize,
1767        cx: &mut LiftContext<'_>,
1768        elem: InterfaceType,
1769    ) -> Result<WasmList<T>> {
1770        match len
1771            .checked_mul(T::SIZE32)
1772            .and_then(|len| ptr.checked_add(len))
1773        {
1774            Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<T>())?,
1775            _ => bail!("list pointer/length out of bounds of memory"),
1776        }
1777        if ptr % usize::try_from(T::ALIGN32)? != 0 {
1778            bail!("list pointer is not aligned")
1779        }
1780        Ok(WasmList {
1781            ptr,
1782            len,
1783            options: cx.options_index(),
1784            elem,
1785            instance: cx.instance_handle(),
1786            _marker: marker::PhantomData,
1787        })
1788    }
1789
1790    /// Returns the item length of this vector
1791    #[inline]
1792    pub fn len(&self) -> usize {
1793        self.len
1794    }
1795
1796    /// Gets the `n`th element of this list.
1797    ///
1798    /// Returns `None` if `index` is out of bounds. Returns `Some(Err(..))` if
1799    /// the value couldn't be decoded (it was invalid). Returns `Some(Ok(..))`
1800    /// if the value is valid.
1801    ///
1802    /// # Panics
1803    ///
1804    /// This function will panic if the string did not originally come from the
1805    /// `store` specified.
1806    //
1807    // TODO: given that interface values are intended to be consumed in one go
1808    // should we even expose a random access iteration API? In theory all
1809    // consumers should be validating through the iterator.
1810    pub fn get(&self, mut store: impl AsContextMut, index: usize) -> Option<Result<T>> {
1811        let store = store.as_context_mut().0;
1812        let mut cx = LiftContext::new(store, self.options, self.instance);
1813        self.get_from_store(&mut cx, index)
1814    }
1815
1816    fn get_from_store(&self, cx: &mut LiftContext<'_>, index: usize) -> Option<Result<T>> {
1817        if index >= self.len {
1818            return None;
1819        }
1820        // Note that this is using panicking indexing and this is expected to
1821        // never fail. The bounds-checking here happened during the construction
1822        // of the `WasmList` itself which means these should always be in-bounds
1823        // (and wasm memory can only grow). This could theoretically be
1824        // unchecked indexing if we're confident enough and it's actually a perf
1825        // issue one day.
1826        let bytes = &cx.memory()[self.ptr + index * T::SIZE32..][..T::SIZE32];
1827        Some(T::linear_lift_from_memory(cx, self.elem, bytes))
1828    }
1829
1830    /// Returns an iterator over the elements of this list.
1831    ///
1832    /// Each item of the list may fail to decode and is represented through the
1833    /// `Result` value of the iterator.
1834    pub fn iter<'a, U: 'static>(
1835        &'a self,
1836        store: impl Into<StoreContextMut<'a, U>>,
1837    ) -> impl ExactSizeIterator<Item = Result<T>> + 'a {
1838        let store = store.into().0;
1839        let mut cx = LiftContext::new(store, self.options, self.instance);
1840        (0..self.len).map(move |i| self.get_from_store(&mut cx, i).unwrap())
1841    }
1842}
1843
1844macro_rules! raw_wasm_list_accessors {
1845    ($($i:ident)*) => ($(
1846        impl WasmList<$i> {
1847            /// Get access to the raw underlying memory for this list.
1848            ///
1849            /// This method will return a direct slice into the original wasm
1850            /// module's linear memory where the data for this slice is stored.
1851            /// This allows the embedder to have efficient access to the
1852            /// underlying memory if needed and avoid copies and such if
1853            /// desired.
1854            ///
1855            /// Note that multi-byte integers are stored in little-endian format
1856            /// so portable processing of this slice must be aware of the host's
1857            /// byte-endianness. The `from_le` constructors in the Rust standard
1858            /// library should be suitable for converting from little-endian.
1859            ///
1860            /// # Panics
1861            ///
1862            /// Panics if the `store` provided is not the one from which this
1863            /// slice originated.
1864            pub fn as_le_slice<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a [$i] {
1865                let memory = self.instance.options_memory(store.into().0, self.options);
1866                self._as_le_slice(memory)
1867            }
1868
1869            fn _as_le_slice<'a>(&self, all_of_memory: &'a [u8]) -> &'a [$i] {
1870                // See comments in `WasmList::get` for the panicking indexing
1871                let byte_size = self.len * mem::size_of::<$i>();
1872                let bytes = &all_of_memory[self.ptr..][..byte_size];
1873
1874                // The canonical ABI requires that everything is aligned to its
1875                // own size, so this should be an aligned array. Furthermore the
1876                // alignment of primitive integers for hosts should be smaller
1877                // than or equal to the size of the primitive itself, meaning
1878                // that a wasm canonical-abi-aligned list is also aligned for
1879                // the host. That should mean that the head/tail slices here are
1880                // empty.
1881                //
1882                // Also note that the `unsafe` here is needed since the type
1883                // we're aligning to isn't guaranteed to be valid, but in our
1884                // case it's just integers and bytes so this should be safe.
1885                unsafe {
1886                    let (head, body, tail) = bytes.align_to::<$i>();
1887                    assert!(head.is_empty() && tail.is_empty());
1888                    body
1889                }
1890            }
1891        }
1892    )*)
1893}
1894
1895raw_wasm_list_accessors! {
1896    i8 i16 i32 i64
1897    u8 u16 u32 u64
1898}
1899
1900// Note that this is similar to `ComponentType for str` except it can only be
1901// used for lifting, not lowering.
1902unsafe impl<T: ComponentType> ComponentType for WasmList<T> {
1903    type Lower = <[T] as ComponentType>::Lower;
1904
1905    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
1906
1907    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
1908        <[T] as ComponentType>::typecheck(ty, types)
1909    }
1910}
1911
1912unsafe impl<T: Lift> Lift for WasmList<T> {
1913    fn linear_lift_from_flat(
1914        cx: &mut LiftContext<'_>,
1915        ty: InterfaceType,
1916        src: &Self::Lower,
1917    ) -> Result<Self> {
1918        let elem = match ty {
1919            InterfaceType::List(i) => cx.types[i].element,
1920            _ => bad_type_info(),
1921        };
1922        let (ptr, len) = lift_pointer_pair_from_flat(cx, src)?;
1923        WasmList::new(ptr, len, cx, elem)
1924    }
1925
1926    fn linear_lift_from_memory(
1927        cx: &mut LiftContext<'_>,
1928        ty: InterfaceType,
1929        bytes: &[u8],
1930    ) -> Result<Self> {
1931        let elem = match ty {
1932            InterfaceType::List(i) => cx.types[i].element,
1933            _ => bad_type_info(),
1934        };
1935        debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
1936        let (ptr, len) = lift_pointer_pair_from_memory(cx, bytes)?;
1937        WasmList::new(ptr, len, cx, elem)
1938    }
1939}
1940
1941// =============================================================================
1942// HashMap<K, V> support for component model `map<K, V>`
1943//
1944// Maps are represented as `list<tuple<K, V>>` in the canonical ABI, so the
1945// lowered form is a (pointer, length) pair just like lists.
1946
1947fn map_abi<'a>(ty: InterfaceType, types: &'a ComponentTypes) -> &'a TypeMap {
1948    match ty {
1949        InterfaceType::Map(i) => &types[i],
1950        _ => bad_type_info(),
1951    }
1952}
1953
1954unsafe impl<K, V> ComponentType for HashMap<K, V>
1955where
1956    K: ComponentType,
1957    V: ComponentType,
1958{
1959    type Lower = [ValRaw; 2];
1960
1961    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
1962
1963    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
1964        TryHashMap::<K, V>::typecheck(ty, types)
1965    }
1966}
1967
1968unsafe impl<K, V> Lower for HashMap<K, V>
1969where
1970    K: Lower,
1971    V: Lower,
1972{
1973    fn linear_lower_to_flat<U>(
1974        &self,
1975        cx: &mut LowerContext<'_, U>,
1976        ty: InterfaceType,
1977        dst: &mut MaybeUninit<[ValRaw; 2]>,
1978    ) -> Result<()> {
1979        let map = map_abi(ty, &cx.types);
1980        let (ptr, len) = lower_map_iter(cx, map, self.len(), self.iter())?;
1981        lower_pointer_pair_to_flat(cx, dst, ptr, len);
1982        Ok(())
1983    }
1984
1985    fn linear_lower_to_memory<U>(
1986        &self,
1987        cx: &mut LowerContext<'_, U>,
1988        ty: InterfaceType,
1989        offset: usize,
1990    ) -> Result<()> {
1991        let map = map_abi(ty, &cx.types);
1992        debug_assert!(offset % (CanonicalAbiInfo::POINTER_PAIR.align32 as usize) == 0);
1993        let (ptr, len) = lower_map_iter(cx, map, self.len(), self.iter())?;
1994        lower_pointer_pair_to_memory(cx, offset, ptr, len);
1995        Ok(())
1996    }
1997}
1998
1999unsafe impl<K, V> Lift for HashMap<K, V>
2000where
2001    K: Lift + Eq + Hash,
2002    V: Lift,
2003{
2004    fn linear_lift_from_flat(
2005        cx: &mut LiftContext<'_>,
2006        ty: InterfaceType,
2007        src: &Self::Lower,
2008    ) -> Result<Self> {
2009        Ok(TryHashMap::<K, V>::linear_lift_from_flat(cx, ty, src)?.into())
2010    }
2011
2012    fn linear_lift_from_memory(
2013        cx: &mut LiftContext<'_>,
2014        ty: InterfaceType,
2015        bytes: &[u8],
2016    ) -> Result<Self> {
2017        Ok(TryHashMap::<K, V>::linear_lift_from_memory(cx, ty, bytes)?.into())
2018    }
2019}
2020
2021fn lower_map_iter<'a, K, V, U>(
2022    cx: &mut LowerContext<'_, U>,
2023    map: &TypeMap,
2024    len: usize,
2025    iter: impl Iterator<Item = (&'a K, &'a V)>,
2026) -> Result<(usize, usize)>
2027where
2028    K: Lower + 'a,
2029    V: Lower + 'a,
2030{
2031    let size = len
2032        .checked_mul(usize::try_from(map.entry_abi.size32)?)
2033        .ok_or_else(|| format_err!("size overflow copying a map"))?;
2034    let ptr = cx.realloc(0, 0, map.entry_abi.align32, size)?;
2035
2036    let mut entry_offset = ptr;
2037    for (key, value) in iter {
2038        // Keys are the first field in each entry tuple.
2039        <K as Lower>::linear_lower_to_memory(key, cx, map.key, entry_offset)?;
2040        // Values start at the precomputed value offset within the tuple.
2041        <V as Lower>::linear_lower_to_memory(
2042            value,
2043            cx,
2044            map.value,
2045            entry_offset + usize::try_from(map.value_offset32)?,
2046        )?;
2047        entry_offset += usize::try_from(map.entry_abi.size32)?;
2048    }
2049
2050    Ok((ptr, len))
2051}
2052
2053unsafe impl<K, V> ComponentType for TryHashMap<K, V>
2054where
2055    K: ComponentType,
2056    V: ComponentType,
2057{
2058    type Lower = [ValRaw; 2];
2059
2060    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::POINTER_PAIR;
2061
2062    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
2063        match ty {
2064            InterfaceType::Map(t) => {
2065                let map_ty = &types.types[*t];
2066                K::typecheck(&map_ty.key, types)?;
2067                V::typecheck(&map_ty.value, types)?;
2068                Ok(())
2069            }
2070            other => bail!("expected `map` found `{}`", desc(other)),
2071        }
2072    }
2073}
2074
2075unsafe impl<K, V> Lower for TryHashMap<K, V>
2076where
2077    K: Lower,
2078    V: Lower,
2079{
2080    fn linear_lower_to_flat<U>(
2081        &self,
2082        cx: &mut LowerContext<'_, U>,
2083        ty: InterfaceType,
2084        dst: &mut MaybeUninit<[ValRaw; 2]>,
2085    ) -> Result<()> {
2086        let map = map_abi(ty, &cx.types);
2087        let (ptr, len) = lower_map_iter(cx, map, self.len(), self.iter())?;
2088        lower_pointer_pair_to_flat(cx, dst, ptr, len);
2089        Ok(())
2090    }
2091
2092    fn linear_lower_to_memory<U>(
2093        &self,
2094        cx: &mut LowerContext<'_, U>,
2095        ty: InterfaceType,
2096        offset: usize,
2097    ) -> Result<()> {
2098        let map = map_abi(ty, &cx.types);
2099        debug_assert!(offset % (CanonicalAbiInfo::POINTER_PAIR.align32 as usize) == 0);
2100        let (ptr, len) = lower_map_iter(cx, map, self.len(), self.iter())?;
2101        lower_pointer_pair_to_memory(cx, offset, ptr, len);
2102        Ok(())
2103    }
2104}
2105
2106unsafe impl<K, V> Lift for TryHashMap<K, V>
2107where
2108    K: Lift + Eq + Hash,
2109    V: Lift,
2110{
2111    fn linear_lift_from_flat(
2112        cx: &mut LiftContext<'_>,
2113        ty: InterfaceType,
2114        src: &Self::Lower,
2115    ) -> Result<Self> {
2116        let map = map_abi(ty, &cx.types);
2117        let (ptr, len) = lift_pointer_pair_from_flat(cx, src)?;
2118        lift_try_map(cx, map, ptr, len)
2119    }
2120
2121    fn linear_lift_from_memory(
2122        cx: &mut LiftContext<'_>,
2123        ty: InterfaceType,
2124        bytes: &[u8],
2125    ) -> Result<Self> {
2126        let map = map_abi(ty, &cx.types);
2127        debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
2128        let (ptr, len) = lift_pointer_pair_from_memory(cx, bytes)?;
2129        lift_try_map(cx, map, ptr, len)
2130    }
2131}
2132
2133fn lift_try_map<K, V>(
2134    cx: &mut LiftContext<'_>,
2135    map: &TypeMap,
2136    ptr: usize,
2137    len: usize,
2138) -> Result<TryHashMap<K, V>>
2139where
2140    K: Lift + Eq + Hash,
2141    V: Lift,
2142{
2143    let mut result = TryHashMap::with_capacity(len)?;
2144
2145    match len
2146        .checked_mul(usize::try_from(map.entry_abi.size32)?)
2147        .and_then(|total| ptr.checked_add(total))
2148    {
2149        Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<(K, V)>())?,
2150        _ => bail!("map pointer/length out of bounds of memory"),
2151    }
2152    if ptr % (map.entry_abi.align32 as usize) != 0 {
2153        bail!("map pointer is not aligned");
2154    }
2155
2156    for i in 0..len {
2157        let entry_base = ptr + (i * usize::try_from(map.entry_abi.size32)?);
2158
2159        let key_bytes = &cx.memory()[entry_base..][..K::SIZE32];
2160        let key = K::linear_lift_from_memory(cx, map.key, key_bytes)?;
2161
2162        let value_bytes =
2163            &cx.memory()[entry_base + usize::try_from(map.value_offset32)?..][..V::SIZE32];
2164        let value = V::linear_lift_from_memory(cx, map.value, value_bytes)?;
2165
2166        result.insert(key, value)?;
2167    }
2168
2169    Ok(result)
2170}
2171
2172/// Verify that the given wasm type is a tuple with the expected fields in the right order.
2173fn typecheck_tuple(
2174    ty: &InterfaceType,
2175    types: &InstanceType<'_>,
2176    expected: &[fn(&InterfaceType, &InstanceType<'_>) -> Result<()>],
2177) -> Result<()> {
2178    match ty {
2179        InterfaceType::Tuple(t) => {
2180            let tuple = &types.types[*t];
2181            if tuple.types.len() != expected.len() {
2182                bail!(
2183                    "expected {}-tuple, found {}-tuple",
2184                    expected.len(),
2185                    tuple.types.len()
2186                );
2187            }
2188            for (ty, check) in tuple.types.iter().zip(expected) {
2189                check(ty, types)?;
2190            }
2191            Ok(())
2192        }
2193        other => bail!("expected `tuple` found `{}`", desc(other)),
2194    }
2195}
2196
2197/// Verify that the given wasm type is a record with the expected fields in the right order and with the right
2198/// names.
2199pub fn typecheck_record(
2200    ty: &InterfaceType,
2201    types: &InstanceType<'_>,
2202    expected: &[(&str, fn(&InterfaceType, &InstanceType<'_>) -> Result<()>)],
2203) -> Result<()> {
2204    match ty {
2205        InterfaceType::Record(index) => {
2206            let fields = &types.types[*index].fields;
2207
2208            if fields.len() != expected.len() {
2209                bail!(
2210                    "expected record of {} fields, found {} fields",
2211                    expected.len(),
2212                    fields.len()
2213                );
2214            }
2215
2216            for (field, &(name, check)) in fields.iter().zip(expected) {
2217                check(&field.ty, types)
2218                    .with_context(|| format!("type mismatch for field {name}"))?;
2219
2220                if field.name != name {
2221                    bail!("expected record field named {}, found {}", name, field.name);
2222                }
2223            }
2224
2225            Ok(())
2226        }
2227        other => bail!("expected `record` found `{}`", desc(other)),
2228    }
2229}
2230
2231/// Verify that the given wasm type is a variant with the expected cases in the right order and with the right
2232/// names.
2233pub fn typecheck_variant(
2234    ty: &InterfaceType,
2235    types: &InstanceType<'_>,
2236    expected: &[(
2237        &str,
2238        Option<fn(&InterfaceType, &InstanceType<'_>) -> Result<()>>,
2239    )],
2240) -> Result<()> {
2241    match ty {
2242        InterfaceType::Variant(index) => {
2243            let cases = &types.types[*index].cases;
2244
2245            if cases.len() != expected.len() {
2246                bail!(
2247                    "expected variant of {} cases, found {} cases",
2248                    expected.len(),
2249                    cases.len()
2250                );
2251            }
2252
2253            for ((case_name, case_ty), &(name, check)) in cases.iter().zip(expected) {
2254                if *case_name != name {
2255                    bail!("expected variant case named {name}, found {case_name}");
2256                }
2257
2258                match (check, case_ty) {
2259                    (Some(check), Some(ty)) => check(ty, types)
2260                        .with_context(|| format!("type mismatch for case {name}"))?,
2261                    (None, None) => {}
2262                    (Some(_), None) => {
2263                        bail!("case `{name}` has no type but one was expected")
2264                    }
2265                    (None, Some(_)) => {
2266                        bail!("case `{name}` has a type but none was expected")
2267                    }
2268                }
2269            }
2270
2271            Ok(())
2272        }
2273        other => bail!("expected `variant` found `{}`", desc(other)),
2274    }
2275}
2276
2277/// Verify that the given wasm type is a enum with the expected cases in the right order and with the right
2278/// names.
2279pub fn typecheck_enum(
2280    ty: &InterfaceType,
2281    types: &InstanceType<'_>,
2282    expected: &[&str],
2283) -> Result<()> {
2284    match ty {
2285        InterfaceType::Enum(index) => {
2286            let names = &types.types[*index].names;
2287
2288            if names.len() != expected.len() {
2289                bail!(
2290                    "expected enum of {} names, found {} names",
2291                    expected.len(),
2292                    names.len()
2293                );
2294            }
2295
2296            for (name, expected) in names.iter().zip(expected) {
2297                if name != expected {
2298                    bail!("expected enum case named {expected}, found {name}");
2299                }
2300            }
2301
2302            Ok(())
2303        }
2304        other => bail!("expected `enum` found `{}`", desc(other)),
2305    }
2306}
2307
2308/// Verify that the given wasm type is a flags type with the expected flags in the right order and with the right
2309/// names.
2310pub fn typecheck_flags(
2311    ty: &InterfaceType,
2312    types: &InstanceType<'_>,
2313    expected: &[&str],
2314) -> Result<()> {
2315    match ty {
2316        InterfaceType::Flags(index) => {
2317            let names = &types.types[*index].names;
2318
2319            if names.len() != expected.len() {
2320                bail!(
2321                    "expected flags type with {} names, found {} names",
2322                    expected.len(),
2323                    names.len()
2324                );
2325            }
2326
2327            for (name, expected) in names.iter().zip(expected) {
2328                if name != expected {
2329                    bail!("expected flag named {expected}, found {name}");
2330                }
2331            }
2332
2333            Ok(())
2334        }
2335        other => bail!("expected `flags` found `{}`", desc(other)),
2336    }
2337}
2338
2339/// Format the specified bitflags using the specified names for debugging
2340pub fn format_flags(bits: &[u32], names: &[&str], f: &mut fmt::Formatter) -> fmt::Result {
2341    f.write_str("(")?;
2342    let mut wrote = false;
2343    for (index, name) in names.iter().enumerate() {
2344        if ((bits[index / 32] >> (index % 32)) & 1) != 0 {
2345            if wrote {
2346                f.write_str("|")?;
2347            } else {
2348                wrote = true;
2349            }
2350
2351            f.write_str(name)?;
2352        }
2353    }
2354    f.write_str(")")
2355}
2356
2357unsafe impl<T> ComponentType for Option<T>
2358where
2359    T: ComponentType,
2360{
2361    type Lower = TupleLower<<u32 as ComponentType>::Lower, T::Lower>;
2362
2363    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::variant_static(&[None, Some(T::ABI)]);
2364    const MAY_REQUIRE_REALLOC: bool = T::MAY_REQUIRE_REALLOC;
2365
2366    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
2367        match ty {
2368            InterfaceType::Option(t) => T::typecheck(&types.types[*t].ty, types),
2369            other => bail!("expected `option` found `{}`", desc(other)),
2370        }
2371    }
2372}
2373
2374unsafe impl<T> ComponentVariant for Option<T>
2375where
2376    T: ComponentType,
2377{
2378    const CASES: &'static [Option<CanonicalAbiInfo>] = &[None, Some(T::ABI)];
2379}
2380
2381unsafe impl<T> Lower for Option<T>
2382where
2383    T: Lower,
2384{
2385    fn linear_lower_to_flat<U>(
2386        &self,
2387        cx: &mut LowerContext<'_, U>,
2388        ty: InterfaceType,
2389        dst: &mut MaybeUninit<Self::Lower>,
2390    ) -> Result<()> {
2391        let payload = match ty {
2392            InterfaceType::Option(ty) => cx.types[ty].ty,
2393            _ => bad_type_info(),
2394        };
2395        match self {
2396            None => {
2397                map_maybe_uninit!(dst.A1).write(ValRaw::i32(0));
2398                // Note that this is unsafe as we're writing an arbitrary
2399                // bit-pattern to an arbitrary type, but part of the unsafe
2400                // contract of the `ComponentType` trait is that we can assign
2401                // any bit-pattern. By writing all zeros here we're ensuring
2402                // that the core wasm arguments this translates to will all be
2403                // zeros (as the canonical ABI requires).
2404                unsafe {
2405                    map_maybe_uninit!(dst.A2).as_mut_ptr().write_bytes(0u8, 1);
2406                }
2407            }
2408            Some(val) => {
2409                map_maybe_uninit!(dst.A1).write(ValRaw::i32(1));
2410                val.linear_lower_to_flat(cx, payload, map_maybe_uninit!(dst.A2))?;
2411            }
2412        }
2413        Ok(())
2414    }
2415
2416    fn linear_lower_to_memory<U>(
2417        &self,
2418        cx: &mut LowerContext<'_, U>,
2419        ty: InterfaceType,
2420        offset: usize,
2421    ) -> Result<()> {
2422        debug_assert!(offset % (Self::ALIGN32 as usize) == 0);
2423        let payload = match ty {
2424            InterfaceType::Option(ty) => cx.types[ty].ty,
2425            _ => bad_type_info(),
2426        };
2427        match self {
2428            None => {
2429                cx.get::<1>(offset)[0] = 0;
2430            }
2431            Some(val) => {
2432                cx.get::<1>(offset)[0] = 1;
2433                val.linear_lower_to_memory(
2434                    cx,
2435                    payload,
2436                    offset + (Self::INFO.payload_offset32 as usize),
2437                )?;
2438            }
2439        }
2440        Ok(())
2441    }
2442}
2443
2444unsafe impl<T> Lift for Option<T>
2445where
2446    T: Lift,
2447{
2448    fn linear_lift_from_flat(
2449        cx: &mut LiftContext<'_>,
2450        ty: InterfaceType,
2451        src: &Self::Lower,
2452    ) -> Result<Self> {
2453        let payload = match ty {
2454            InterfaceType::Option(ty) => cx.types[ty].ty,
2455            _ => bad_type_info(),
2456        };
2457        Ok(match src.A1.get_i32() {
2458            0 => None,
2459            1 => Some(T::linear_lift_from_flat(cx, payload, &src.A2)?),
2460            _ => bail!("invalid option discriminant"),
2461        })
2462    }
2463
2464    fn linear_lift_from_memory(
2465        cx: &mut LiftContext<'_>,
2466        ty: InterfaceType,
2467        bytes: &[u8],
2468    ) -> Result<Self> {
2469        debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
2470        let payload_ty = match ty {
2471            InterfaceType::Option(ty) => cx.types[ty].ty,
2472            _ => bad_type_info(),
2473        };
2474        let discrim = bytes[0];
2475        let payload = &bytes[Self::INFO.payload_offset32 as usize..];
2476        match discrim {
2477            0 => Ok(None),
2478            1 => Ok(Some(T::linear_lift_from_memory(cx, payload_ty, payload)?)),
2479            _ => bail!("invalid option discriminant"),
2480        }
2481    }
2482}
2483
2484#[derive(Clone, Copy)]
2485#[repr(C)]
2486pub struct ResultLower<T: Copy, E: Copy> {
2487    tag: ValRaw,
2488    payload: ResultLowerPayload<T, E>,
2489}
2490
2491#[derive(Clone, Copy)]
2492#[repr(C)]
2493union ResultLowerPayload<T: Copy, E: Copy> {
2494    ok: T,
2495    err: E,
2496}
2497
2498unsafe impl<T, E> ComponentType for Result<T, E>
2499where
2500    T: ComponentType,
2501    E: ComponentType,
2502{
2503    type Lower = ResultLower<T::Lower, E::Lower>;
2504
2505    const ABI: CanonicalAbiInfo = CanonicalAbiInfo::variant_static(&[Some(T::ABI), Some(E::ABI)]);
2506    const MAY_REQUIRE_REALLOC: bool = T::MAY_REQUIRE_REALLOC || E::MAY_REQUIRE_REALLOC;
2507
2508    fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
2509        match ty {
2510            InterfaceType::Result(r) => {
2511                let result = &types.types[*r];
2512                match &result.ok {
2513                    Some(ty) => T::typecheck(ty, types)?,
2514                    None if T::IS_RUST_UNIT_TYPE => {}
2515                    None => bail!("expected no `ok` type"),
2516                }
2517                match &result.err {
2518                    Some(ty) => E::typecheck(ty, types)?,
2519                    None if E::IS_RUST_UNIT_TYPE => {}
2520                    None => bail!("expected no `err` type"),
2521                }
2522                Ok(())
2523            }
2524            other => bail!("expected `result` found `{}`", desc(other)),
2525        }
2526    }
2527}
2528
2529/// Lowers the payload of a variant into the storage for the entire payload,
2530/// handling writing zeros at the end of the representation if this payload is
2531/// smaller than the entire flat representation.
2532///
2533/// * `payload` - the flat storage space for the entire payload of the variant
2534/// * `typed_payload` - projection from the payload storage space to the
2535///   individual storage space for this variant.
2536/// * `lower` - lowering operation used to initialize the `typed_payload` return
2537///   value.
2538///
2539/// For more information on this se the comments in the `Lower for Result`
2540/// implementation below.
2541pub unsafe fn lower_payload<P, T>(
2542    payload: &mut MaybeUninit<P>,
2543    typed_payload: impl FnOnce(&mut MaybeUninit<P>) -> &mut MaybeUninit<T>,
2544    lower: impl FnOnce(&mut MaybeUninit<T>) -> Result<()>,
2545) -> Result<()> {
2546    let typed = typed_payload(payload);
2547    lower(typed)?;
2548
2549    let typed_len = unsafe { storage_as_slice(typed).len() };
2550    let payload = unsafe { storage_as_slice_mut(payload) };
2551    for slot in payload[typed_len..].iter_mut() {
2552        slot.write(ValRaw::u64(0));
2553    }
2554    Ok(())
2555}
2556
2557unsafe impl<T, E> ComponentVariant for Result<T, E>
2558where
2559    T: ComponentType,
2560    E: ComponentType,
2561{
2562    const CASES: &'static [Option<CanonicalAbiInfo>] = &[Some(T::ABI), Some(E::ABI)];
2563}
2564
2565unsafe impl<T, E> Lower for Result<T, E>
2566where
2567    T: Lower,
2568    E: Lower,
2569{
2570    fn linear_lower_to_flat<U>(
2571        &self,
2572        cx: &mut LowerContext<'_, U>,
2573        ty: InterfaceType,
2574        dst: &mut MaybeUninit<Self::Lower>,
2575    ) -> Result<()> {
2576        let (ok, err) = match ty {
2577            InterfaceType::Result(ty) => {
2578                let ty = &cx.types[ty];
2579                (ty.ok, ty.err)
2580            }
2581            _ => bad_type_info(),
2582        };
2583
2584        // This implementation of `Lower::lower`, if you're reading these from
2585        // the top of this file, is the first location that the "join" logic of
2586        // the component model's canonical ABI encountered. The rough problem is
2587        // that let's say we have a component model type of the form:
2588        //
2589        //      (result u64 (error (tuple f32 u16)))
2590        //
2591        // The flat representation of this is actually pretty tricky. Currently
2592        // it is:
2593        //
2594        //      i32 i64 i32
2595        //
2596        // The first `i32` is the discriminant for the `result`, and the payload
2597        // is represented by `i64 i32`. The "ok" variant will only use the `i64`
2598        // and the "err" variant will use both `i64` and `i32`.
2599        //
2600        // In the "ok" variant the first issue is encountered. The size of one
2601        // variant may not match the size of the other variants. All variants
2602        // start at the "front" but when lowering a type we need to be sure to
2603        // initialize the later variants (lest we leak random host memory into
2604        // the guest module). Due to how the `Lower` type is represented as a
2605        // `union` of all the variants what ends up happening here is that
2606        // internally within the `lower_payload` after the typed payload is
2607        // lowered the remaining bits of the payload that weren't initialized
2608        // are all set to zero. This will guarantee that we'll write to all the
2609        // slots for each variant.
2610        //
2611        // The "err" variant encounters the second issue, however, which is that
2612        // the flat representation for each type may differ between payloads. In
2613        // the "ok" arm an `i64` is written, but the `lower` implementation for
2614        // the "err" arm will write an `f32` and then an `i32`. For this
2615        // implementation of `lower` to be valid the `f32` needs to get inflated
2616        // to an `i64` with zero-padding in the upper bits. What may be
2617        // surprising, however, is that none of this is handled in this file.
2618        // This implementation looks like it's blindly deferring to `E::lower`
2619        // and hoping it does the right thing.
2620        //
2621        // In reality, however, the correctness of variant lowering relies on
2622        // two subtle details of the `ValRaw` implementation in Wasmtime:
2623        //
2624        // 1. First the `ValRaw` value always contains little-endian values.
2625        //    This means that if a `u32` is written, a `u64` is read, and then
2626        //    the `u64` has its upper bits truncated the original value will
2627        //    always be retained. This is primarily here for big-endian
2628        //    platforms where if it weren't little endian then the opposite
2629        //    would occur and the wrong value would be read.
2630        //
2631        // 2. Second, and perhaps even more subtly, the `ValRaw` constructors
2632        //    for 32-bit types actually always initialize 64-bits of the
2633        //    `ValRaw`. In the component model flat ABI only 32 and 64-bit types
2634        //    are used so 64-bits is big enough to contain everything. This
2635        //    means that when a `ValRaw` is written into the destination it will
2636        //    always, whether it's needed or not, be "ready" to get extended up
2637        //    to 64-bits.
2638        //
2639        // Put together these two subtle guarantees means that all `Lower`
2640        // implementations can be written "naturally" as one might naively
2641        // expect. Variants will, on each arm, zero out remaining fields and all
2642        // writes to the flat representation will automatically be 64-bit writes
2643        // meaning that if the value is read as a 64-bit value, which isn't
2644        // known at the time of the write, it'll still be correct.
2645        match self {
2646            Ok(e) => {
2647                map_maybe_uninit!(dst.tag).write(ValRaw::i32(0));
2648                unsafe {
2649                    lower_payload(
2650                        map_maybe_uninit!(dst.payload),
2651                        |payload| map_maybe_uninit!(payload.ok),
2652                        |dst| match ok {
2653                            Some(ok) => e.linear_lower_to_flat(cx, ok, dst),
2654                            None => Ok(()),
2655                        },
2656                    )
2657                }
2658            }
2659            Err(e) => {
2660                map_maybe_uninit!(dst.tag).write(ValRaw::i32(1));
2661                unsafe {
2662                    lower_payload(
2663                        map_maybe_uninit!(dst.payload),
2664                        |payload| map_maybe_uninit!(payload.err),
2665                        |dst| match err {
2666                            Some(err) => e.linear_lower_to_flat(cx, err, dst),
2667                            None => Ok(()),
2668                        },
2669                    )
2670                }
2671            }
2672        }
2673    }
2674
2675    fn linear_lower_to_memory<U>(
2676        &self,
2677        cx: &mut LowerContext<'_, U>,
2678        ty: InterfaceType,
2679        offset: usize,
2680    ) -> Result<()> {
2681        let (ok, err) = match ty {
2682            InterfaceType::Result(ty) => {
2683                let ty = &cx.types[ty];
2684                (ty.ok, ty.err)
2685            }
2686            _ => bad_type_info(),
2687        };
2688        debug_assert!(offset % (Self::ALIGN32 as usize) == 0);
2689        let payload_offset = Self::INFO.payload_offset32 as usize;
2690        match self {
2691            Ok(e) => {
2692                cx.get::<1>(offset)[0] = 0;
2693                if let Some(ok) = ok {
2694                    e.linear_lower_to_memory(cx, ok, offset + payload_offset)?;
2695                }
2696            }
2697            Err(e) => {
2698                cx.get::<1>(offset)[0] = 1;
2699                if let Some(err) = err {
2700                    e.linear_lower_to_memory(cx, err, offset + payload_offset)?;
2701                }
2702            }
2703        }
2704        Ok(())
2705    }
2706}
2707
2708unsafe impl<T, E> Lift for Result<T, E>
2709where
2710    T: Lift,
2711    E: Lift,
2712{
2713    #[inline]
2714    fn linear_lift_from_flat(
2715        cx: &mut LiftContext<'_>,
2716        ty: InterfaceType,
2717        src: &Self::Lower,
2718    ) -> Result<Self> {
2719        let (ok, err) = match ty {
2720            InterfaceType::Result(ty) => {
2721                let ty = &cx.types[ty];
2722                (ty.ok, ty.err)
2723            }
2724            _ => bad_type_info(),
2725        };
2726        // Note that this implementation specifically isn't trying to actually
2727        // reinterpret or alter the bits of `lower` depending on which variant
2728        // we're lifting. This ends up all working out because the value is
2729        // stored in little-endian format.
2730        //
2731        // When stored in little-endian format the `{T,E}::Lower`, when each
2732        // individual `ValRaw` is read, means that if an i64 value, extended
2733        // from an i32 value, was stored then when the i32 value is read it'll
2734        // automatically ignore the upper bits.
2735        //
2736        // This "trick" allows us to seamlessly pass through the `Self::Lower`
2737        // representation into the lifting/lowering without trying to handle
2738        // "join"ed types as per the canonical ABI. It just so happens that i64
2739        // bits will naturally be reinterpreted as f64. Additionally if the
2740        // joined type is i64 but only the lower bits are read that's ok and we
2741        // don't need to validate the upper bits.
2742        //
2743        // This is largely enabled by WebAssembly/component-model#35 where no
2744        // validation needs to be performed for ignored bits and bytes here.
2745        Ok(match src.tag.get_i32() {
2746            0 => Ok(unsafe { lift_option(cx, ok, &src.payload.ok)? }),
2747            1 => Err(unsafe { lift_option(cx, err, &src.payload.err)? }),
2748            _ => bail!("invalid expected discriminant"),
2749        })
2750    }
2751
2752    #[inline]
2753    fn linear_lift_from_memory(
2754        cx: &mut LiftContext<'_>,
2755        ty: InterfaceType,
2756        bytes: &[u8],
2757    ) -> Result<Self> {
2758        debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
2759        let discrim = bytes[0];
2760        let payload = &bytes[Self::INFO.payload_offset32 as usize..];
2761        let (ok, err) = match ty {
2762            InterfaceType::Result(ty) => {
2763                let ty = &cx.types[ty];
2764                (ty.ok, ty.err)
2765            }
2766            _ => bad_type_info(),
2767        };
2768        match discrim {
2769            0 => Ok(Ok(load_option(cx, ok, &payload[..T::SIZE32])?)),
2770            1 => Ok(Err(load_option(cx, err, &payload[..E::SIZE32])?)),
2771            _ => bail!("invalid expected discriminant"),
2772        }
2773    }
2774}
2775
2776fn lift_option<T>(cx: &mut LiftContext<'_>, ty: Option<InterfaceType>, src: &T::Lower) -> Result<T>
2777where
2778    T: Lift,
2779{
2780    match ty {
2781        Some(ty) => T::linear_lift_from_flat(cx, ty, src),
2782        None => Ok(empty_lift()),
2783    }
2784}
2785
2786fn load_option<T>(cx: &mut LiftContext<'_>, ty: Option<InterfaceType>, bytes: &[u8]) -> Result<T>
2787where
2788    T: Lift,
2789{
2790    match ty {
2791        Some(ty) => T::linear_lift_from_memory(cx, ty, bytes),
2792        None => Ok(empty_lift()),
2793    }
2794}
2795
2796fn empty_lift<T>() -> T
2797where
2798    T: Lift,
2799{
2800    assert!(T::IS_RUST_UNIT_TYPE);
2801    assert_eq!(mem::size_of::<T>(), 0);
2802    unsafe { MaybeUninit::uninit().assume_init() }
2803}
2804
2805/// Helper structure to define `Lower` for tuples below.
2806///
2807/// Uses default type parameters to have fields be zero-sized and not present
2808/// in memory for smaller tuple values.
2809#[expect(non_snake_case, reason = "more amenable to macro-generated code")]
2810#[doc(hidden)]
2811#[derive(Clone, Copy)]
2812#[repr(C)]
2813pub struct TupleLower<
2814    T1 = (),
2815    T2 = (),
2816    T3 = (),
2817    T4 = (),
2818    T5 = (),
2819    T6 = (),
2820    T7 = (),
2821    T8 = (),
2822    T9 = (),
2823    T10 = (),
2824    T11 = (),
2825    T12 = (),
2826    T13 = (),
2827    T14 = (),
2828    T15 = (),
2829    T16 = (),
2830    T17 = (),
2831> {
2832    // NB: these names match the names in `for_each_function_signature!`
2833    A1: T1,
2834    A2: T2,
2835    A3: T3,
2836    A4: T4,
2837    A5: T5,
2838    A6: T6,
2839    A7: T7,
2840    A8: T8,
2841    A9: T9,
2842    A10: T10,
2843    A11: T11,
2844    A12: T12,
2845    A13: T13,
2846    A14: T14,
2847    A15: T15,
2848    A16: T16,
2849    A17: T17,
2850    _align_tuple_lower0_correctly: [ValRaw; 0],
2851}
2852
2853macro_rules! impl_component_ty_for_tuples {
2854    ($n:tt $($t:ident)*) => {
2855        #[allow(non_snake_case, reason = "macro-generated code")]
2856        unsafe impl<$($t,)*> ComponentType for ($($t,)*)
2857            where $($t: ComponentType),*
2858        {
2859            type Lower = TupleLower<$($t::Lower),*>;
2860
2861            const ABI: CanonicalAbiInfo = CanonicalAbiInfo::record_static(&[
2862                $($t::ABI),*
2863            ]);
2864            const MAY_REQUIRE_REALLOC: bool = false $(|| $t::MAY_REQUIRE_REALLOC)*;
2865
2866            const IS_RUST_UNIT_TYPE: bool = {
2867                let mut _is_unit = true;
2868                $(
2869                    let _anything_to_bind_the_macro_variable = $t::IS_RUST_UNIT_TYPE;
2870                    _is_unit = false;
2871                )*
2872                _is_unit
2873            };
2874
2875            fn typecheck(
2876                ty: &InterfaceType,
2877                types: &InstanceType<'_>,
2878            ) -> Result<()> {
2879                typecheck_tuple(ty, types, &[$($t::typecheck),*])
2880            }
2881        }
2882
2883        #[allow(non_snake_case, reason = "macro-generated code")]
2884        unsafe impl<$($t,)*> Lower for ($($t,)*)
2885            where $($t: Lower),*
2886        {
2887            fn linear_lower_to_flat<U>(
2888                &self,
2889                cx: &mut LowerContext<'_, U>,
2890                ty: InterfaceType,
2891                _dst: &mut MaybeUninit<Self::Lower>,
2892            ) -> Result<()> {
2893                let types = match ty {
2894                    InterfaceType::Tuple(t) => &cx.types[t].types,
2895                    _ => bad_type_info(),
2896                };
2897                let ($($t,)*) = self;
2898                let mut _types = types.iter();
2899                $(
2900                    let ty = *_types.next().unwrap_or_else(bad_type_info);
2901                    $t.linear_lower_to_flat(cx, ty, map_maybe_uninit!(_dst.$t))?;
2902                )*
2903                Ok(())
2904            }
2905
2906            fn linear_lower_to_memory<U>(
2907                &self,
2908                cx: &mut LowerContext<'_, U>,
2909                ty: InterfaceType,
2910                mut _offset: usize,
2911            ) -> Result<()> {
2912                debug_assert!(_offset % (Self::ALIGN32 as usize) == 0);
2913                let types = match ty {
2914                    InterfaceType::Tuple(t) => &cx.types[t].types,
2915                    _ => bad_type_info(),
2916                };
2917                let ($($t,)*) = self;
2918                let mut _types = types.iter();
2919                $(
2920                    let ty = *_types.next().unwrap_or_else(bad_type_info);
2921                    $t.linear_lower_to_memory(cx, ty, $t::ABI.next_field32_size(&mut _offset))?;
2922                )*
2923                Ok(())
2924            }
2925        }
2926
2927        #[allow(non_snake_case, reason = "macro-generated code")]
2928        unsafe impl<$($t,)*> Lift for ($($t,)*)
2929            where $($t: Lift),*
2930        {
2931            #[inline]
2932            fn linear_lift_from_flat(cx: &mut LiftContext<'_>, ty: InterfaceType, _src: &Self::Lower) -> Result<Self> {
2933                let types = match ty {
2934                    InterfaceType::Tuple(t) => &cx.types[t].types,
2935                    _ => bad_type_info(),
2936                };
2937                let mut _types = types.iter();
2938                Ok(($(
2939                    $t::linear_lift_from_flat(
2940                        cx,
2941                        *_types.next().unwrap_or_else(bad_type_info),
2942                        &_src.$t,
2943                    )?,
2944                )*))
2945            }
2946
2947            #[inline]
2948            fn linear_lift_from_memory(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Self> {
2949                debug_assert!((bytes.as_ptr() as usize) % (Self::ALIGN32 as usize) == 0);
2950                let types = match ty {
2951                    InterfaceType::Tuple(t) => &cx.types[t].types,
2952                    _ => bad_type_info(),
2953                };
2954                let mut _types = types.iter();
2955                let mut _offset = 0;
2956                $(
2957                    let ty = *_types.next().unwrap_or_else(bad_type_info);
2958                    let $t = $t::linear_lift_from_memory(cx, ty, &bytes[$t::ABI.next_field32_size(&mut _offset)..][..$t::SIZE32])?;
2959                )*
2960                Ok(($($t,)*))
2961            }
2962        }
2963
2964        #[allow(non_snake_case, reason = "macro-generated code")]
2965        unsafe impl<$($t,)*> ComponentNamedList for ($($t,)*)
2966            where $($t: ComponentType),*
2967        {}
2968    };
2969}
2970
2971for_each_function_signature!(impl_component_ty_for_tuples);
2972
2973pub fn desc(ty: &InterfaceType) -> &'static str {
2974    match ty {
2975        InterfaceType::U8 => "u8",
2976        InterfaceType::S8 => "s8",
2977        InterfaceType::U16 => "u16",
2978        InterfaceType::S16 => "s16",
2979        InterfaceType::U32 => "u32",
2980        InterfaceType::S32 => "s32",
2981        InterfaceType::U64 => "u64",
2982        InterfaceType::S64 => "s64",
2983        InterfaceType::Float32 => "f32",
2984        InterfaceType::Float64 => "f64",
2985        InterfaceType::Bool => "bool",
2986        InterfaceType::Char => "char",
2987        InterfaceType::String => "string",
2988        InterfaceType::List(_) => "list",
2989        InterfaceType::Tuple(_) => "tuple",
2990        InterfaceType::Option(_) => "option",
2991        InterfaceType::Result(_) => "result",
2992
2993        InterfaceType::Record(_) => "record",
2994        InterfaceType::Variant(_) => "variant",
2995        InterfaceType::Flags(_) => "flags",
2996        InterfaceType::Enum(_) => "enum",
2997        InterfaceType::Own(_) => "owned resource",
2998        InterfaceType::Borrow(_) => "borrowed resource",
2999        InterfaceType::Future(_) => "future",
3000        InterfaceType::Stream(_) => "stream",
3001        InterfaceType::ErrorContext(_) => "error-context",
3002        InterfaceType::Map(_) => "map",
3003        InterfaceType::FixedLengthList(_) => "list<_, N>",
3004    }
3005}
3006
3007#[cold]
3008#[doc(hidden)]
3009pub fn bad_type_info<T>() -> T {
3010    // NB: should consider something like `unreachable_unchecked` here if this
3011    // becomes a performance bottleneck at some point, but that also comes with
3012    // a tradeoff of propagating a lot of unsafety, so it may not be worth it.
3013    panic!("bad type information detected");
3014}