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