1 use crate::ValRaw;
2 use crate::component::ResourceAny;
3 use crate::component::concurrent::{self, ErrorContext, FutureAny, StreamAny};
4 use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc};
5 use crate::prelude::*;
6 use core::mem::MaybeUninit;
7 use core::slice::{Iter, IterMut};
8 use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9 use wasmtime_environ::component::{
10     CanonicalAbiInfo, InterfaceType, TypeEnum, TypeFlags, TypeListIndex, TypeMap, TypeMapIndex,
11     TypeOption, TypeResult, TypeVariant, VariantInfo,
12 };
13 
14 /// Represents possible runtime values which a component function can either
15 /// consume or produce
16 ///
17 /// This is a dynamic representation of possible values in the component model.
18 /// Note that this is not an efficient representation but is instead intended to
19 /// be a flexible and somewhat convenient representation. The most efficient
20 /// representation of component model types is to use the `bindgen!` macro to
21 /// generate native Rust types with specialized liftings and lowerings.
22 ///
23 /// This type is used in conjunction with [`Func::call`] for example if the
24 /// signature of a component is not statically known ahead of time.
25 ///
26 /// # Equality and `Val`
27 ///
28 /// This type implements both the Rust `PartialEq` and `Eq` traits. This type
29 /// additionally contains values which are not necessarily easily equated,
30 /// however, such as floats (`Float32` and `Float64`) and resources. Equality
31 /// does require that two values have the same type, and then these cases are
32 /// handled as:
33 ///
34 /// * Floats are tested if they are "semantically the same" meaning all NaN
35 ///   values are equal to all other NaN values. Additionally zero values must be
36 ///   exactly the same, so positive zero is not equal to negative zero. The
37 ///   primary use case at this time is fuzzing-related equality which this is
38 ///   sufficient for.
39 ///
40 /// * Resources are tested if their types and indices into the host table are
41 ///   equal. This does not compare the underlying representation so borrows of
42 ///   the same guest resource are not considered equal. This additionally
43 ///   doesn't go further and test for equality in the guest itself (for example
44 ///   two different heap allocations of `Box<u32>` can be equal in normal Rust
45 ///   if they contain the same value, but will never be considered equal when
46 ///   compared as `Val::Resource`s).
47 ///
48 /// In general if a strict guarantee about equality is required here it's
49 /// recommended to "build your own" as this equality intended for fuzzing
50 /// Wasmtime may not be suitable for you.
51 ///
52 /// # Component model types and `Val`
53 ///
54 /// The `Val` type here does not contain enough information to say what the
55 /// component model type of a `Val` is. This is instead more of an AST of sorts.
56 /// For example the `Val::Enum` only carries information about a single
57 /// discriminant, not the entire enumeration or what it's a discriminant of.
58 ///
59 /// This means that when a `Val` is passed to Wasmtime, for example as a
60 /// function parameter when calling a function or as a return value from an
61 /// host-defined imported function, then it must pass a type-check. Instances of
62 /// `Val` are type-checked against what's required by the component itself.
63 ///
64 /// [`Func::call`]: crate::component::Func::call
65 #[derive(Debug, Clone)]
66 #[expect(missing_docs, reason = "self-describing variants")]
67 pub enum Val {
68     Bool(bool),
69     S8(i8),
70     U8(u8),
71     S16(i16),
72     U16(u16),
73     S32(i32),
74     U32(u32),
75     S64(i64),
76     U64(u64),
77     Float32(f32),
78     Float64(f64),
79     Char(char),
80     String(String),
81     List(Vec<Val>),
82     /// A map type represented as a list of key-value pairs.
83     /// Duplicate keys are allowed and follow "last value wins" semantics.
84     Map(Vec<(Val, Val)>),
85     Record(Vec<(String, Val)>),
86     Tuple(Vec<Val>),
87     Variant(String, Option<Box<Val>>),
88     Enum(String),
89     Option(Option<Box<Val>>),
90     Result(Result<Option<Box<Val>>, Option<Box<Val>>>),
91     Flags(Vec<String>),
92     Resource(ResourceAny),
93     Future(FutureAny),
94     Stream(StreamAny),
95     ErrorContext(ErrorContextAny),
96 }
97 
98 impl Val {
99     /// Deserialize a value of this type from core Wasm stack values.
100     pub(crate) fn lift(
101         cx: &mut LiftContext<'_>,
102         ty: InterfaceType,
103         src: &mut Iter<'_, ValRaw>,
104     ) -> Result<Val> {
105         Ok(match ty {
106             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_flat(cx, ty, next(src))?),
107             InterfaceType::S8 => Val::S8(i8::linear_lift_from_flat(cx, ty, next(src))?),
108             InterfaceType::U8 => Val::U8(u8::linear_lift_from_flat(cx, ty, next(src))?),
109             InterfaceType::S16 => Val::S16(i16::linear_lift_from_flat(cx, ty, next(src))?),
110             InterfaceType::U16 => Val::U16(u16::linear_lift_from_flat(cx, ty, next(src))?),
111             InterfaceType::S32 => Val::S32(i32::linear_lift_from_flat(cx, ty, next(src))?),
112             InterfaceType::U32 => Val::U32(u32::linear_lift_from_flat(cx, ty, next(src))?),
113             InterfaceType::S64 => Val::S64(i64::linear_lift_from_flat(cx, ty, next(src))?),
114             InterfaceType::U64 => Val::U64(u64::linear_lift_from_flat(cx, ty, next(src))?),
115             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_flat(cx, ty, next(src))?),
116             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_flat(cx, ty, next(src))?),
117             InterfaceType::Char => Val::Char(char::linear_lift_from_flat(cx, ty, next(src))?),
118             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
119                 Val::Resource(ResourceAny::linear_lift_from_flat(cx, ty, next(src))?)
120             }
121             InterfaceType::String => Val::String(<_>::linear_lift_from_flat(
122                 cx,
123                 ty,
124                 &[*next(src), *next(src)],
125             )?),
126             InterfaceType::List(i) => {
127                 // FIXME(#4311): needs memory64 treatment
128                 let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
129                 let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
130                 load_list(cx, i, ptr, len)?
131             }
132             InterfaceType::Map(i) => {
133                 // FIXME(#4311): needs memory64 treatment
134                 // Maps are represented as list<tuple<k, v>> in canonical ABI
135                 let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
136                 let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
137                 load_map(cx, i, ptr, len)?
138             }
139             InterfaceType::Record(i) => Val::Record(
140                 cx.types[i]
141                     .fields
142                     .iter()
143                     .map(|field| {
144                         let val = Self::lift(cx, field.ty, src)?;
145                         Ok((field.name.to_string(), val))
146                     })
147                     .collect::<Result<_>>()?,
148             ),
149             InterfaceType::Tuple(i) => Val::Tuple(
150                 cx.types[i]
151                     .types
152                     .iter()
153                     .map(|ty| Self::lift(cx, *ty, src))
154                     .collect::<Result<_>>()?,
155             ),
156             InterfaceType::Variant(i) => {
157                 let vty = &cx.types[i];
158                 let (discriminant, value) = lift_variant(
159                     cx,
160                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
161                     vty.cases.values().copied(),
162                     src,
163                 )?;
164 
165                 let (k, _) = vty.cases.get_index(discriminant as usize).unwrap();
166                 Val::Variant(k.clone(), value)
167             }
168             InterfaceType::Enum(i) => {
169                 let ety = &cx.types[i];
170                 let (discriminant, _) = lift_variant(
171                     cx,
172                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
173                     ety.names.iter().map(|_| None),
174                     src,
175                 )?;
176 
177                 Val::Enum(ety.names[discriminant as usize].clone())
178             }
179             InterfaceType::Option(i) => {
180                 let (_discriminant, value) = lift_variant(
181                     cx,
182                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
183                     [None, Some(cx.types[i].ty)].into_iter(),
184                     src,
185                 )?;
186 
187                 Val::Option(value)
188             }
189             InterfaceType::Result(i) => {
190                 let result_ty = &cx.types[i];
191                 let (discriminant, value) = lift_variant(
192                     cx,
193                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
194                     [result_ty.ok, result_ty.err].into_iter(),
195                     src,
196                 )?;
197 
198                 Val::Result(if discriminant == 0 {
199                     Ok(value)
200                 } else {
201                     Err(value)
202                 })
203             }
204             InterfaceType::Flags(i) => {
205                 let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap();
206                 let ty = &cx.types[i];
207                 let mut flags = Vec::new();
208                 for i in 0..u32::try_from(u32_count).unwrap() {
209                     push_flags(
210                         ty,
211                         &mut flags,
212                         i * 32,
213                         u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))?,
214                     );
215                 }
216 
217                 Val::Flags(flags)
218             }
219             InterfaceType::Future(_) => {
220                 Val::Future(FutureAny::linear_lift_from_flat(cx, ty, next(src))?)
221             }
222             InterfaceType::Stream(_) => {
223                 Val::Stream(StreamAny::linear_lift_from_flat(cx, ty, next(src))?)
224             }
225             InterfaceType::ErrorContext(_) => {
226                 ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val()
227             }
228             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
229         })
230     }
231 
232     /// Deserialize a value of this type from the heap.
233     pub(crate) fn load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val> {
234         Ok(match ty {
235             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_memory(cx, ty, bytes)?),
236             InterfaceType::S8 => Val::S8(i8::linear_lift_from_memory(cx, ty, bytes)?),
237             InterfaceType::U8 => Val::U8(u8::linear_lift_from_memory(cx, ty, bytes)?),
238             InterfaceType::S16 => Val::S16(i16::linear_lift_from_memory(cx, ty, bytes)?),
239             InterfaceType::U16 => Val::U16(u16::linear_lift_from_memory(cx, ty, bytes)?),
240             InterfaceType::S32 => Val::S32(i32::linear_lift_from_memory(cx, ty, bytes)?),
241             InterfaceType::U32 => Val::U32(u32::linear_lift_from_memory(cx, ty, bytes)?),
242             InterfaceType::S64 => Val::S64(i64::linear_lift_from_memory(cx, ty, bytes)?),
243             InterfaceType::U64 => Val::U64(u64::linear_lift_from_memory(cx, ty, bytes)?),
244             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_memory(cx, ty, bytes)?),
245             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_memory(cx, ty, bytes)?),
246             InterfaceType::Char => Val::Char(char::linear_lift_from_memory(cx, ty, bytes)?),
247             InterfaceType::String => Val::String(<_>::linear_lift_from_memory(cx, ty, bytes)?),
248             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
249                 Val::Resource(ResourceAny::linear_lift_from_memory(cx, ty, bytes)?)
250             }
251             InterfaceType::List(i) => {
252                 // FIXME(#4311): needs memory64 treatment
253                 let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize;
254                 let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize;
255                 load_list(cx, i, ptr, len)?
256             }
257             InterfaceType::Map(i) => {
258                 // FIXME(#4311): needs memory64 treatment
259                 let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize;
260                 let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize;
261                 load_map(cx, i, ptr, len)?
262             }
263 
264             InterfaceType::Record(i) => {
265                 let mut offset = 0;
266                 let fields = cx.types[i].fields.iter();
267                 Val::Record(
268                     fields
269                         .map(|field| -> Result<(String, Val)> {
270                             let abi = cx.types.canonical_abi(&field.ty);
271                             let offset = abi.next_field32(&mut offset);
272                             let offset = usize::try_from(offset).unwrap();
273                             let size = usize::try_from(abi.size32).unwrap();
274                             Ok((
275                                 field.name.to_string(),
276                                 Val::load(cx, field.ty, &bytes[offset..][..size])?,
277                             ))
278                         })
279                         .collect::<Result<_>>()?,
280                 )
281             }
282             InterfaceType::Tuple(i) => {
283                 let types = cx.types[i].types.iter().copied();
284                 let mut offset = 0;
285                 Val::Tuple(
286                     types
287                         .map(|ty| {
288                             let abi = cx.types.canonical_abi(&ty);
289                             let offset = abi.next_field32(&mut offset);
290                             let offset = usize::try_from(offset).unwrap();
291                             let size = usize::try_from(abi.size32).unwrap();
292                             Val::load(cx, ty, &bytes[offset..][..size])
293                         })
294                         .collect::<Result<_>>()?,
295                 )
296             }
297             InterfaceType::Variant(i) => {
298                 let ty = &cx.types[i];
299                 let (discriminant, value) =
300                     load_variant(cx, &ty.info, ty.cases.values().copied(), bytes)?;
301 
302                 let (k, _) = ty.cases.get_index(discriminant as usize).unwrap();
303                 Val::Variant(k.clone(), value)
304             }
305             InterfaceType::Enum(i) => {
306                 let ty = &cx.types[i];
307                 let (discriminant, _) =
308                     load_variant(cx, &ty.info, ty.names.iter().map(|_| None), bytes)?;
309 
310                 Val::Enum(ty.names[discriminant as usize].clone())
311             }
312             InterfaceType::Option(i) => {
313                 let ty = &cx.types[i];
314                 let (_discriminant, value) =
315                     load_variant(cx, &ty.info, [None, Some(ty.ty)].into_iter(), bytes)?;
316 
317                 Val::Option(value)
318             }
319             InterfaceType::Result(i) => {
320                 let ty = &cx.types[i];
321                 let (discriminant, value) =
322                     load_variant(cx, &ty.info, [ty.ok, ty.err].into_iter(), bytes)?;
323 
324                 Val::Result(if discriminant == 0 {
325                     Ok(value)
326                 } else {
327                     Err(value)
328                 })
329             }
330             InterfaceType::Flags(i) => {
331                 let ty = &cx.types[i];
332                 let mut flags = Vec::new();
333                 match FlagsSize::from_count(ty.names.len()) {
334                     FlagsSize::Size0 => {}
335                     FlagsSize::Size1 => {
336                         let bits = u8::linear_lift_from_memory(cx, InterfaceType::U8, bytes)?;
337                         push_flags(ty, &mut flags, 0, u32::from(bits));
338                     }
339                     FlagsSize::Size2 => {
340                         let bits = u16::linear_lift_from_memory(cx, InterfaceType::U16, bytes)?;
341                         push_flags(ty, &mut flags, 0, u32::from(bits));
342                     }
343                     FlagsSize::Size4Plus(n) => {
344                         for i in 0..n {
345                             let bits = u32::linear_lift_from_memory(
346                                 cx,
347                                 InterfaceType::U32,
348                                 &bytes[usize::from(i) * 4..][..4],
349                             )?;
350                             push_flags(ty, &mut flags, u32::from(i) * 32, bits);
351                         }
352                     }
353                 }
354                 Val::Flags(flags)
355             }
356             InterfaceType::Future(_) => FutureAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
357             InterfaceType::Stream(_) => StreamAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
358             InterfaceType::ErrorContext(_) => {
359                 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val()
360             }
361             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
362         })
363     }
364 
365     /// Serialize this value as core Wasm stack values.
366     pub(crate) fn lower<T>(
367         &self,
368         cx: &mut LowerContext<'_, T>,
369         ty: InterfaceType,
370         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
371     ) -> Result<()> {
372         match (ty, self) {
373             (InterfaceType::Bool, Val::Bool(value)) => {
374                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
375             }
376             (InterfaceType::Bool, _) => unexpected(ty, self),
377             (InterfaceType::S8, Val::S8(value)) => {
378                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
379             }
380             (InterfaceType::S8, _) => unexpected(ty, self),
381             (InterfaceType::U8, Val::U8(value)) => {
382                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
383             }
384             (InterfaceType::U8, _) => unexpected(ty, self),
385             (InterfaceType::S16, Val::S16(value)) => {
386                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
387             }
388             (InterfaceType::S16, _) => unexpected(ty, self),
389             (InterfaceType::U16, Val::U16(value)) => {
390                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
391             }
392             (InterfaceType::U16, _) => unexpected(ty, self),
393             (InterfaceType::S32, Val::S32(value)) => {
394                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
395             }
396             (InterfaceType::S32, _) => unexpected(ty, self),
397             (InterfaceType::U32, Val::U32(value)) => {
398                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
399             }
400             (InterfaceType::U32, _) => unexpected(ty, self),
401             (InterfaceType::S64, Val::S64(value)) => {
402                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
403             }
404             (InterfaceType::S64, _) => unexpected(ty, self),
405             (InterfaceType::U64, Val::U64(value)) => {
406                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
407             }
408             (InterfaceType::U64, _) => unexpected(ty, self),
409             (InterfaceType::Float32, Val::Float32(value)) => {
410                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
411             }
412             (InterfaceType::Float32, _) => unexpected(ty, self),
413             (InterfaceType::Float64, Val::Float64(value)) => {
414                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
415             }
416             (InterfaceType::Float64, _) => unexpected(ty, self),
417             (InterfaceType::Char, Val::Char(value)) => {
418                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
419             }
420             (InterfaceType::Char, _) => unexpected(ty, self),
421             // NB: `lower` on `ResourceAny` does its own type-checking, so skip
422             // looking at it here.
423             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
424                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
425             }
426             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
427             (InterfaceType::String, Val::String(value)) => {
428                 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit();
429                 value.linear_lower_to_flat(cx, ty, my_dst)?;
430                 let my_dst = unsafe { my_dst.assume_init() };
431                 next_mut(dst).write(my_dst[0]);
432                 next_mut(dst).write(my_dst[1]);
433                 Ok(())
434             }
435             (InterfaceType::String, _) => unexpected(ty, self),
436             (InterfaceType::List(ty), Val::List(values)) => {
437                 let ty = &cx.types[ty];
438                 let (ptr, len) = lower_list(cx, ty.element, values)?;
439                 next_mut(dst).write(ValRaw::i64(ptr as i64));
440                 next_mut(dst).write(ValRaw::i64(len as i64));
441                 Ok(())
442             }
443             (InterfaceType::List(_), _) => unexpected(ty, self),
444             (InterfaceType::Map(ty), Val::Map(pairs)) => {
445                 let map_ty = &cx.types[ty];
446                 let (ptr, len) = lower_map(cx, map_ty, pairs)?;
447                 next_mut(dst).write(ValRaw::i64(ptr as i64));
448                 next_mut(dst).write(ValRaw::i64(len as i64));
449                 Ok(())
450             }
451             (InterfaceType::Map(_), _) => unexpected(ty, self),
452             (InterfaceType::Record(ty), Val::Record(values)) => {
453                 let ty = &cx.types[ty];
454                 if ty.fields.len() != values.len() {
455                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
456                 }
457                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
458                     if *name != field.name {
459                         bail!("expected field `{}`, got `{name}`", field.name);
460                     }
461                     value.lower(cx, field.ty, dst)?;
462                 }
463                 Ok(())
464             }
465             (InterfaceType::Record(_), _) => unexpected(ty, self),
466             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
467                 let ty = &cx.types[ty];
468                 if ty.types.len() != values.len() {
469                     bail!("expected {} types, got {}", ty.types.len(), values.len());
470                 }
471                 for (value, ty) in values.iter().zip(ty.types.iter()) {
472                     value.lower(cx, *ty, dst)?;
473                 }
474                 Ok(())
475             }
476             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
477             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
478                 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst)
479             }
480             (InterfaceType::Variant(_), _) => unexpected(ty, self),
481             (InterfaceType::Option(ty), Val::Option(v)) => {
482                 GenericVariant::option(&cx.types[ty], v).lower(cx, dst)
483             }
484             (InterfaceType::Option(_), _) => unexpected(ty, self),
485             (InterfaceType::Result(ty), Val::Result(v)) => {
486                 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst)
487             }
488             (InterfaceType::Result(_), _) => unexpected(ty, self),
489             (InterfaceType::Enum(ty), Val::Enum(discriminant)) => {
490                 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?;
491                 next_mut(dst).write(ValRaw::u32(discriminant));
492                 Ok(())
493             }
494             (InterfaceType::Enum(_), _) => unexpected(ty, self),
495             (InterfaceType::Flags(ty), Val::Flags(value)) => {
496                 let ty = &cx.types[ty];
497                 let storage = flags_to_storage(ty, value)?;
498                 for value in storage {
499                     next_mut(dst).write(ValRaw::u32(value));
500                 }
501                 Ok(())
502             }
503             (InterfaceType::Flags(_), _) => unexpected(ty, self),
504             (InterfaceType::Future(_), Val::Future(f)) => {
505                 f.linear_lower_to_flat(cx, ty, next_mut(dst))
506             }
507             (InterfaceType::Future(_), _) => unexpected(ty, self),
508             (InterfaceType::Stream(_), Val::Stream(s)) => {
509                 s.linear_lower_to_flat(cx, ty, next_mut(dst))
510             }
511             (InterfaceType::Stream(_), _) => unexpected(ty, self),
512             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
513                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat(
514                     cx,
515                     InterfaceType::U32,
516                     next_mut(dst),
517                 )
518             }
519             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
520             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
521         }
522     }
523 
524     /// Serialize this value to the heap at the specified memory location.
525     pub(crate) fn store<T>(
526         &self,
527         cx: &mut LowerContext<'_, T>,
528         ty: InterfaceType,
529         offset: usize,
530     ) -> Result<()> {
531         debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0);
532 
533         match (ty, self) {
534             (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset),
535             (InterfaceType::Bool, _) => unexpected(ty, self),
536             (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset),
537             (InterfaceType::U8, _) => unexpected(ty, self),
538             (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset),
539             (InterfaceType::S8, _) => unexpected(ty, self),
540             (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset),
541             (InterfaceType::U16, _) => unexpected(ty, self),
542             (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset),
543             (InterfaceType::S16, _) => unexpected(ty, self),
544             (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset),
545             (InterfaceType::U32, _) => unexpected(ty, self),
546             (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset),
547             (InterfaceType::S32, _) => unexpected(ty, self),
548             (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset),
549             (InterfaceType::U64, _) => unexpected(ty, self),
550             (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset),
551             (InterfaceType::S64, _) => unexpected(ty, self),
552             (InterfaceType::Float32, Val::Float32(value)) => {
553                 value.linear_lower_to_memory(cx, ty, offset)
554             }
555             (InterfaceType::Float32, _) => unexpected(ty, self),
556             (InterfaceType::Float64, Val::Float64(value)) => {
557                 value.linear_lower_to_memory(cx, ty, offset)
558             }
559             (InterfaceType::Float64, _) => unexpected(ty, self),
560             (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset),
561             (InterfaceType::Char, _) => unexpected(ty, self),
562             (InterfaceType::String, Val::String(value)) => {
563                 value.linear_lower_to_memory(cx, ty, offset)
564             }
565             (InterfaceType::String, _) => unexpected(ty, self),
566 
567             // NB: resources do type-checking when they lower.
568             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
569                 value.linear_lower_to_memory(cx, ty, offset)
570             }
571             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
572             (InterfaceType::List(ty), Val::List(values)) => {
573                 let ty = &cx.types[ty];
574                 let (ptr, len) = lower_list(cx, ty.element, values)?;
575                 // FIXME(#4311): needs memory64 handling
576                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
577                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
578                 Ok(())
579             }
580             (InterfaceType::List(_), _) => unexpected(ty, self),
581             (InterfaceType::Map(ty_idx), Val::Map(values)) => {
582                 let map_ty = &cx.types[ty_idx];
583                 let (ptr, len) = lower_map(cx, map_ty, values)?;
584                 // FIXME(#4311): needs memory64 handling
585                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
586                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
587                 Ok(())
588             }
589             (InterfaceType::Map(_), _) => unexpected(ty, self),
590             (InterfaceType::Record(ty), Val::Record(values)) => {
591                 let ty = &cx.types[ty];
592                 if ty.fields.len() != values.len() {
593                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
594                 }
595                 let mut offset = offset;
596                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
597                     if *name != field.name {
598                         bail!("expected field `{}`, got `{name}`", field.name);
599                     }
600                     value.store(
601                         cx,
602                         field.ty,
603                         cx.types
604                             .canonical_abi(&field.ty)
605                             .next_field32_size(&mut offset),
606                     )?;
607                 }
608                 Ok(())
609             }
610             (InterfaceType::Record(_), _) => unexpected(ty, self),
611             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
612                 let ty = &cx.types[ty];
613                 if ty.types.len() != values.len() {
614                     bail!("expected {} types, got {}", ty.types.len(), values.len());
615                 }
616                 let mut offset = offset;
617                 for (value, ty) in values.iter().zip(ty.types.iter()) {
618                     value.store(
619                         cx,
620                         *ty,
621                         cx.types.canonical_abi(ty).next_field32_size(&mut offset),
622                     )?;
623                 }
624                 Ok(())
625             }
626             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
627 
628             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
629                 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
630             }
631             (InterfaceType::Variant(_), _) => unexpected(ty, self),
632             (InterfaceType::Enum(ty), Val::Enum(v)) => {
633                 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
634             }
635             (InterfaceType::Enum(_), _) => unexpected(ty, self),
636             (InterfaceType::Option(ty), Val::Option(v)) => {
637                 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
638             }
639             (InterfaceType::Option(_), _) => unexpected(ty, self),
640             (InterfaceType::Result(ty), Val::Result(v)) => {
641                 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
642             }
643             (InterfaceType::Result(_), _) => unexpected(ty, self),
644 
645             (InterfaceType::Flags(ty), Val::Flags(flags)) => {
646                 let ty = &cx.types[ty];
647                 let storage = flags_to_storage(ty, flags)?;
648                 match FlagsSize::from_count(ty.names.len()) {
649                     FlagsSize::Size0 => {}
650                     FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory(
651                         cx,
652                         InterfaceType::U8,
653                         offset,
654                     )?,
655                     FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory(
656                         cx,
657                         InterfaceType::U16,
658                         offset,
659                     )?,
660                     FlagsSize::Size4Plus(_) => {
661                         let mut offset = offset;
662                         for value in storage {
663                             value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?;
664                             offset += 4;
665                         }
666                     }
667                 }
668                 Ok(())
669             }
670             (InterfaceType::Flags(_), _) => unexpected(ty, self),
671             (InterfaceType::Future(_), Val::Future(f)) => f.linear_lower_to_memory(cx, ty, offset),
672             (InterfaceType::Future(_), _) => unexpected(ty, self),
673             (InterfaceType::Stream(_), Val::Stream(s)) => s.linear_lower_to_memory(cx, ty, offset),
674             (InterfaceType::Stream(_), _) => unexpected(ty, self),
675             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
676                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory(
677                     cx,
678                     InterfaceType::U32,
679                     offset,
680                 )
681             }
682             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
683             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
684         }
685     }
686 
687     pub(crate) fn desc(&self) -> &'static str {
688         match self {
689             Val::Bool(_) => "bool",
690             Val::U8(_) => "u8",
691             Val::S8(_) => "s8",
692             Val::U16(_) => "u16",
693             Val::S16(_) => "s16",
694             Val::U32(_) => "u32",
695             Val::S32(_) => "s32",
696             Val::U64(_) => "u64",
697             Val::S64(_) => "s64",
698             Val::Float32(_) => "f32",
699             Val::Float64(_) => "f64",
700             Val::Char(_) => "char",
701             Val::List(_) => "list",
702             Val::Map(_) => "map",
703             Val::String(_) => "string",
704             Val::Record(_) => "record",
705             Val::Enum(_) => "enum",
706             Val::Variant(..) => "variant",
707             Val::Tuple(_) => "tuple",
708             Val::Option(_) => "option",
709             Val::Result(_) => "result",
710             Val::Resource(_) => "resource",
711             Val::Flags(_) => "flags",
712             Val::Future(_) => "future",
713             Val::Stream(_) => "stream",
714             Val::ErrorContext(_) => "error-context",
715         }
716     }
717 
718     /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization
719     /// requires a target [`crate::component::Type`].
720     #[cfg(feature = "wave")]
721     pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
722         Ok(wasm_wave::from_str(ty, s)?)
723     }
724 
725     /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding.
726     #[cfg(feature = "wave")]
727     pub fn to_wave(&self) -> Result<String> {
728         Ok(wasm_wave::to_string(self)?)
729     }
730 }
731 
732 impl PartialEq for Val {
733     fn eq(&self, other: &Self) -> bool {
734         match (self, other) {
735             // IEEE 754 equality considers NaN inequal to NaN and negative zero
736             // equal to positive zero, however we do the opposite here, because
737             // this logic is used by testing and fuzzing, which want to know
738             // whether two values are semantically the same, rather than
739             // numerically equal.
740             (Self::Float32(l), Self::Float32(r)) => {
741                 (*l != 0.0 && l == r)
742                     || (*l == 0.0 && l.to_bits() == r.to_bits())
743                     || (l.is_nan() && r.is_nan())
744             }
745             (Self::Float32(_), _) => false,
746             (Self::Float64(l), Self::Float64(r)) => {
747                 (*l != 0.0 && l == r)
748                     || (*l == 0.0 && l.to_bits() == r.to_bits())
749                     || (l.is_nan() && r.is_nan())
750             }
751             (Self::Float64(_), _) => false,
752 
753             (Self::Bool(l), Self::Bool(r)) => l == r,
754             (Self::Bool(_), _) => false,
755             (Self::S8(l), Self::S8(r)) => l == r,
756             (Self::S8(_), _) => false,
757             (Self::U8(l), Self::U8(r)) => l == r,
758             (Self::U8(_), _) => false,
759             (Self::S16(l), Self::S16(r)) => l == r,
760             (Self::S16(_), _) => false,
761             (Self::U16(l), Self::U16(r)) => l == r,
762             (Self::U16(_), _) => false,
763             (Self::S32(l), Self::S32(r)) => l == r,
764             (Self::S32(_), _) => false,
765             (Self::U32(l), Self::U32(r)) => l == r,
766             (Self::U32(_), _) => false,
767             (Self::S64(l), Self::S64(r)) => l == r,
768             (Self::S64(_), _) => false,
769             (Self::U64(l), Self::U64(r)) => l == r,
770             (Self::U64(_), _) => false,
771             (Self::Char(l), Self::Char(r)) => l == r,
772             (Self::Char(_), _) => false,
773             (Self::String(l), Self::String(r)) => l == r,
774             (Self::String(_), _) => false,
775             (Self::List(l), Self::List(r)) => l == r,
776             (Self::List(_), _) => false,
777             (Self::Map(l), Self::Map(r)) => l == r,
778             (Self::Map(_), _) => false,
779             (Self::Record(l), Self::Record(r)) => l == r,
780             (Self::Record(_), _) => false,
781             (Self::Tuple(l), Self::Tuple(r)) => l == r,
782             (Self::Tuple(_), _) => false,
783             (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
784             (Self::Variant(..), _) => false,
785             (Self::Enum(l), Self::Enum(r)) => l == r,
786             (Self::Enum(_), _) => false,
787             (Self::Option(l), Self::Option(r)) => l == r,
788             (Self::Option(_), _) => false,
789             (Self::Result(l), Self::Result(r)) => l == r,
790             (Self::Result(_), _) => false,
791             (Self::Flags(l), Self::Flags(r)) => l == r,
792             (Self::Flags(_), _) => false,
793             (Self::Resource(l), Self::Resource(r)) => l == r,
794             (Self::Resource(_), _) => false,
795             (Self::Future(l), Self::Future(r)) => l == r,
796             (Self::Future(_), _) => false,
797             (Self::Stream(l), Self::Stream(r)) => l == r,
798             (Self::Stream(_), _) => false,
799             (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r,
800             (Self::ErrorContext(_), _) => false,
801         }
802     }
803 }
804 
805 impl Eq for Val {}
806 
807 struct GenericVariant<'a> {
808     discriminant: u32,
809     payload: Option<(&'a Val, InterfaceType)>,
810     abi: &'a CanonicalAbiInfo,
811     info: &'a VariantInfo,
812 }
813 
814 impl GenericVariant<'_> {
815     fn result<'a>(
816         ty: &'a TypeResult,
817         r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
818     ) -> Result<GenericVariant<'a>> {
819         let (discriminant, payload) = match r {
820             Ok(val) => {
821                 let payload = match (val, ty.ok) {
822                     (Some(val), Some(ty)) => Some((&**val, ty)),
823                     (None, None) => None,
824                     (Some(_), None) => {
825                         bail!("payload provided to `ok` but not expected");
826                     }
827                     (None, Some(_)) => {
828                         bail!("payload expected to `ok` but not provided");
829                     }
830                 };
831                 (0, payload)
832             }
833             Err(val) => {
834                 let payload = match (val, ty.err) {
835                     (Some(val), Some(ty)) => Some((&**val, ty)),
836                     (None, None) => None,
837                     (Some(_), None) => {
838                         bail!("payload provided to `err` but not expected");
839                     }
840                     (None, Some(_)) => {
841                         bail!("payload expected to `err` but not provided");
842                     }
843                 };
844                 (1, payload)
845             }
846         };
847         Ok(GenericVariant {
848             discriminant,
849             payload,
850             abi: &ty.abi,
851             info: &ty.info,
852         })
853     }
854 
855     fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
856         let (discriminant, payload) = match r {
857             None => (0, None),
858             Some(val) => (1, Some((&**val, ty.ty))),
859         };
860         GenericVariant {
861             discriminant,
862             payload,
863             abi: &ty.abi,
864             info: &ty.info,
865         }
866     }
867 
868     fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
869         let discriminant = get_enum_discriminant(ty, discriminant)?;
870 
871         Ok(GenericVariant {
872             discriminant,
873             payload: None,
874             abi: &ty.abi,
875             info: &ty.info,
876         })
877     }
878 
879     fn variant<'a>(
880         ty: &'a TypeVariant,
881         discriminant_name: &str,
882         payload: &'a Option<Box<Val>>,
883     ) -> Result<GenericVariant<'a>> {
884         let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
885 
886         let payload = match (payload, payload_ty) {
887             (Some(val), Some(ty)) => Some((&**val, *ty)),
888             (None, None) => None,
889             (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
890             (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
891         };
892 
893         Ok(GenericVariant {
894             discriminant,
895             payload,
896             abi: &ty.abi,
897             info: &ty.info,
898         })
899     }
900 
901     fn lower<T>(
902         &self,
903         cx: &mut LowerContext<'_, T>,
904         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
905     ) -> Result<()> {
906         next_mut(dst).write(ValRaw::u32(self.discriminant));
907 
908         // For the remaining lowered representation of this variant that
909         // the payload didn't write we write out zeros here to ensure
910         // the entire variant is written.
911         let value_flat = match self.payload {
912             Some((value, ty)) => {
913                 value.lower(cx, ty, dst)?;
914                 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
915             }
916             None => 0,
917         };
918         let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
919         for _ in (1 + value_flat)..variant_flat {
920             next_mut(dst).write(ValRaw::u64(0));
921         }
922         Ok(())
923     }
924 
925     fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
926         match self.info.size {
927             DiscriminantSize::Size1 => u8::try_from(self.discriminant)
928                 .unwrap()
929                 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?,
930             DiscriminantSize::Size2 => u16::try_from(self.discriminant)
931                 .unwrap()
932                 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?,
933             DiscriminantSize::Size4 => {
934                 self.discriminant
935                     .linear_lower_to_memory(cx, InterfaceType::U32, offset)?
936             }
937         }
938 
939         if let Some((value, ty)) = self.payload {
940             let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
941             value.store(cx, ty, offset)?;
942         }
943 
944         Ok(())
945     }
946 }
947 
948 fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
949     let elem = cx.types[ty].element;
950     let abi = cx.types.canonical_abi(&elem);
951     let element_size = usize::try_from(abi.size32).unwrap();
952     let element_alignment = abi.align32;
953 
954     match len
955         .checked_mul(element_size)
956         .and_then(|len| ptr.checked_add(len))
957     {
958         Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<Val>())?,
959         _ => bail!("list pointer/length out of bounds of memory"),
960     }
961     if ptr % usize::try_from(element_alignment)? != 0 {
962         bail!("list pointer is not aligned")
963     }
964 
965     Ok(Val::List(
966         (0..len)
967             .map(|index| {
968                 Val::load(
969                     cx,
970                     elem,
971                     &cx.memory()[ptr + (index * element_size)..][..element_size],
972                 )
973             })
974             .collect::<Result<_>>()?,
975     ))
976 }
977 
978 fn load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val> {
979     // Maps are stored as list<tuple<k, v>> in canonical ABI
980     let map_ty = &cx.types[ty];
981     let key_ty = map_ty.key;
982     let value_ty = map_ty.value;
983 
984     let key_abi = cx.types.canonical_abi(&key_ty);
985     let value_abi = cx.types.canonical_abi(&value_ty);
986     let key_size = usize::try_from(key_abi.size32).unwrap();
987     let value_size = usize::try_from(value_abi.size32).unwrap();
988     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
989     let tuple_alignment = map_ty.entry_abi.align32;
990     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
991 
992     // Bounds check
993     match len
994         .checked_mul(tuple_size)
995         .and_then(|len| ptr.checked_add(len))
996     {
997         Some(n) if n <= cx.memory().len() => {}
998         _ => bail!("map pointer/length out of bounds of memory"),
999     }
1000     if ptr % usize::try_from(tuple_alignment)? != 0 {
1001         bail!("map pointer is not aligned")
1002     }
1003 
1004     // Load each tuple (key, value) into a Vec
1005     let mut map = Vec::with_capacity(len);
1006     for index in 0..len {
1007         let tuple_ptr = ptr + (index * tuple_size);
1008         let key = Val::load(cx, key_ty, &cx.memory()[tuple_ptr..][..key_size])?;
1009         let value = Val::load(
1010             cx,
1011             value_ty,
1012             &cx.memory()[tuple_ptr + value_offset..][..value_size],
1013         )?;
1014         map.push((key, value));
1015     }
1016 
1017     Ok(Val::Map(map))
1018 }
1019 
1020 fn load_variant(
1021     cx: &mut LiftContext<'_>,
1022     info: &VariantInfo,
1023     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1024     bytes: &[u8],
1025 ) -> Result<(u32, Option<Box<Val>>)> {
1026     let discriminant = match info.size {
1027         DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory(
1028             cx,
1029             InterfaceType::U8,
1030             &bytes[..1],
1031         )?),
1032         DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory(
1033             cx,
1034             InterfaceType::U16,
1035             &bytes[..2],
1036         )?),
1037         DiscriminantSize::Size4 => {
1038             u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])?
1039         }
1040     };
1041     let case_ty = types.nth(discriminant as usize).ok_or_else(|| {
1042         format_err!(
1043             "discriminant {} out of range [0..{})",
1044             discriminant,
1045             types.len()
1046         )
1047     })?;
1048     let value = match case_ty {
1049         Some(case_ty) => {
1050             let payload_offset = usize::try_from(info.payload_offset32).unwrap();
1051             let case_abi = cx.types.canonical_abi(&case_ty);
1052             let case_size = usize::try_from(case_abi.size32).unwrap();
1053             Some(Box::new(Val::load(
1054                 cx,
1055                 case_ty,
1056                 &bytes[payload_offset..][..case_size],
1057             )?))
1058         }
1059         None => None,
1060     };
1061     Ok((discriminant, value))
1062 }
1063 
1064 fn lift_variant(
1065     cx: &mut LiftContext<'_>,
1066     flatten_count: usize,
1067     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1068     src: &mut Iter<'_, ValRaw>,
1069 ) -> Result<(u32, Option<Box<Val>>)> {
1070     let len = types.len();
1071     let discriminant = next(src).get_u32();
1072     let ty = types
1073         .nth(discriminant as usize)
1074         .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?;
1075     let (value, value_flat) = match ty {
1076         Some(ty) => (
1077             Some(Box::new(Val::lift(cx, ty, src)?)),
1078             cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1079         ),
1080         None => (None, 0),
1081     };
1082     for _ in (1 + value_flat)..flatten_count {
1083         next(src);
1084     }
1085     Ok((discriminant, value))
1086 }
1087 
1088 /// Lower a list with the specified element type and values.
1089 fn lower_list<T>(
1090     cx: &mut LowerContext<'_, T>,
1091     element_type: InterfaceType,
1092     items: &[Val],
1093 ) -> Result<(usize, usize)> {
1094     let abi = cx.types.canonical_abi(&element_type);
1095     let elt_size = usize::try_from(abi.size32)?;
1096     let elt_align = abi.align32;
1097     let size = items
1098         .len()
1099         .checked_mul(elt_size)
1100         .ok_or_else(|| crate::format_err!("size overflow copying a list"))?;
1101     let ptr = cx.realloc(0, 0, elt_align, size)?;
1102     let mut element_ptr = ptr;
1103     for item in items {
1104         item.store(cx, element_type, element_ptr)?;
1105         element_ptr += elt_size;
1106     }
1107     Ok((ptr, items.len()))
1108 }
1109 
1110 /// Lower a map as list<tuple<k, v>> with the specified key and value types.
1111 fn lower_map<T>(
1112     cx: &mut LowerContext<'_, T>,
1113     map_ty: &TypeMap,
1114     pairs: &[(Val, Val)],
1115 ) -> Result<(usize, usize)> {
1116     let key_type = map_ty.key;
1117     let value_type = map_ty.value;
1118     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
1119     let tuple_align = map_ty.entry_abi.align32;
1120     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
1121 
1122     let size = pairs
1123         .len()
1124         .checked_mul(tuple_size)
1125         .ok_or_else(|| crate::format_err!("size overflow copying a map"))?;
1126     let ptr = cx.realloc(0, 0, tuple_align, size)?;
1127 
1128     let mut tuple_ptr = ptr;
1129     for (key, value) in pairs {
1130         // Store key at tuple_ptr
1131         key.store(cx, key_type, tuple_ptr)?;
1132         // Store value at tuple_ptr + value_offset (properly aligned)
1133         value.store(cx, value_type, tuple_ptr + value_offset)?;
1134         tuple_ptr += tuple_size;
1135     }
1136 
1137     Ok((ptr, pairs.len()))
1138 }
1139 
1140 fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1141     while bits > 0 {
1142         if bits & 1 != 0 {
1143             flags.push(ty.names[offset as usize].clone());
1144         }
1145         bits >>= 1;
1146         offset += 1;
1147     }
1148 }
1149 
1150 fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
1151     let mut storage = match FlagsSize::from_count(ty.names.len()) {
1152         FlagsSize::Size0 => Vec::new(),
1153         FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
1154         FlagsSize::Size4Plus(n) => vec![0; n.into()],
1155     };
1156 
1157     for flag in flags {
1158         let bit = ty
1159             .names
1160             .get_index_of(flag)
1161             .ok_or_else(|| crate::format_err!("unknown flag: `{flag}`"))?;
1162         storage[bit / 32] |= 1 << (bit % 32);
1163     }
1164     Ok(storage)
1165 }
1166 
1167 fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
1168     ty.names
1169         .get_index_of(n)
1170         .ok_or_else(|| crate::format_err!("enum variant name `{n}` is not valid"))
1171         .map(|i| i.try_into().unwrap())
1172 }
1173 
1174 fn get_variant_discriminant<'a>(
1175     ty: &'a TypeVariant,
1176     name: &str,
1177 ) -> Result<(u32, &'a Option<InterfaceType>)> {
1178     let (i, _, ty) = ty
1179         .cases
1180         .get_full(name)
1181         .ok_or_else(|| crate::format_err!("unknown variant case: `{name}`"))?;
1182     Ok((i.try_into().unwrap(), ty))
1183 }
1184 
1185 fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1186     src.next().unwrap()
1187 }
1188 
1189 fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1190     dst.next().unwrap()
1191 }
1192 
1193 #[cold]
1194 fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
1195     bail!(
1196         "type mismatch: expected {}, found {}",
1197         desc(&ty),
1198         val.desc()
1199     )
1200 }
1201 
1202 /// Represents a component model `error-context`.
1203 ///
1204 /// Note that this type is not usable at this time as its implementation has not
1205 /// been filled out. There are no operations on this and there's additionally no
1206 /// ability to "drop" or deallocate this index.
1207 //
1208 // FIXME(#11161) this needs to be filled out implementation-wise
1209 #[derive(Debug, Clone, PartialEq, Eq)]
1210 pub struct ErrorContextAny(pub(crate) u32);
1211 
1212 impl From<bool> for Val {
1213     fn from(b: bool) -> Self {
1214         Val::Bool(b)
1215     }
1216 }
1217 
1218 impl From<u8> for Val {
1219     fn from(u: u8) -> Self {
1220         Val::U8(u)
1221     }
1222 }
1223 
1224 impl From<i8> for Val {
1225     fn from(i: i8) -> Self {
1226         Val::S8(i)
1227     }
1228 }
1229 
1230 impl From<u16> for Val {
1231     fn from(u: u16) -> Self {
1232         Val::U16(u)
1233     }
1234 }
1235 
1236 impl From<i16> for Val {
1237     fn from(i: i16) -> Self {
1238         Val::S16(i)
1239     }
1240 }
1241 
1242 impl From<u32> for Val {
1243     fn from(u: u32) -> Self {
1244         Val::U32(u)
1245     }
1246 }
1247 
1248 impl From<i32> for Val {
1249     fn from(i: i32) -> Self {
1250         Val::S32(i)
1251     }
1252 }
1253 
1254 impl From<u64> for Val {
1255     fn from(u: u64) -> Self {
1256         Val::U64(u)
1257     }
1258 }
1259 
1260 impl From<i64> for Val {
1261     fn from(i: i64) -> Self {
1262         Val::S64(i)
1263     }
1264 }
1265 
1266 impl From<char> for Val {
1267     fn from(i: char) -> Self {
1268         Val::Char(i)
1269     }
1270 }
1271 
1272 impl From<String> for Val {
1273     fn from(i: String) -> Self {
1274         Val::String(i)
1275     }
1276 }
1277 
1278 impl From<ResourceAny> for Val {
1279     fn from(i: ResourceAny) -> Self {
1280         Val::Resource(i)
1281     }
1282 }
1283 
1284 impl From<FutureAny> for Val {
1285     fn from(i: FutureAny) -> Self {
1286         Val::Future(i)
1287     }
1288 }
1289 
1290 impl From<StreamAny> for Val {
1291     fn from(i: StreamAny) -> Self {
1292         Val::Stream(i)
1293     }
1294 }
1295