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