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