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