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