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!(
443             offset % usize::try_from(cx.types.canonical_abi(&ty).align32).err2anyhow()? == 0
444         );
445 
446         match (ty, self) {
447             (InterfaceType::Bool, Val::Bool(value)) => value.store(cx, ty, offset),
448             (InterfaceType::Bool, _) => unexpected(ty, self),
449             (InterfaceType::U8, Val::U8(value)) => value.store(cx, ty, offset),
450             (InterfaceType::U8, _) => unexpected(ty, self),
451             (InterfaceType::S8, Val::S8(value)) => value.store(cx, ty, offset),
452             (InterfaceType::S8, _) => unexpected(ty, self),
453             (InterfaceType::U16, Val::U16(value)) => value.store(cx, ty, offset),
454             (InterfaceType::U16, _) => unexpected(ty, self),
455             (InterfaceType::S16, Val::S16(value)) => value.store(cx, ty, offset),
456             (InterfaceType::S16, _) => unexpected(ty, self),
457             (InterfaceType::U32, Val::U32(value)) => value.store(cx, ty, offset),
458             (InterfaceType::U32, _) => unexpected(ty, self),
459             (InterfaceType::S32, Val::S32(value)) => value.store(cx, ty, offset),
460             (InterfaceType::S32, _) => unexpected(ty, self),
461             (InterfaceType::U64, Val::U64(value)) => value.store(cx, ty, offset),
462             (InterfaceType::U64, _) => unexpected(ty, self),
463             (InterfaceType::S64, Val::S64(value)) => value.store(cx, ty, offset),
464             (InterfaceType::S64, _) => unexpected(ty, self),
465             (InterfaceType::Float32, Val::Float32(value)) => value.store(cx, ty, offset),
466             (InterfaceType::Float32, _) => unexpected(ty, self),
467             (InterfaceType::Float64, Val::Float64(value)) => value.store(cx, ty, offset),
468             (InterfaceType::Float64, _) => unexpected(ty, self),
469             (InterfaceType::Char, Val::Char(value)) => value.store(cx, ty, offset),
470             (InterfaceType::Char, _) => unexpected(ty, self),
471             (InterfaceType::String, Val::String(value)) => value.store(cx, ty, offset),
472             (InterfaceType::String, _) => unexpected(ty, self),
473 
474             // NB: resources do type-checking when they lower.
475             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
476                 value.store(cx, ty, offset)
477             }
478             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
479             (InterfaceType::List(ty), Val::List(values)) => {
480                 let ty = &cx.types[ty];
481                 let (ptr, len) = lower_list(cx, ty.element, values)?;
482                 // FIXME: needs memory64 handling
483                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
484                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
485                 Ok(())
486             }
487             (InterfaceType::List(_), _) => unexpected(ty, self),
488             (InterfaceType::Record(ty), Val::Record(values)) => {
489                 let ty = &cx.types[ty];
490                 if ty.fields.len() != values.len() {
491                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
492                 }
493                 let mut offset = offset;
494                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
495                     if *name != field.name {
496                         bail!("expected field `{}`, got `{name}`", field.name);
497                     }
498                     value.store(
499                         cx,
500                         field.ty,
501                         cx.types
502                             .canonical_abi(&field.ty)
503                             .next_field32_size(&mut offset),
504                     )?;
505                 }
506                 Ok(())
507             }
508             (InterfaceType::Record(_), _) => unexpected(ty, self),
509             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
510                 let ty = &cx.types[ty];
511                 if ty.types.len() != values.len() {
512                     bail!("expected {} types, got {}", ty.types.len(), values.len());
513                 }
514                 let mut offset = offset;
515                 for (value, ty) in values.iter().zip(ty.types.iter()) {
516                     value.store(
517                         cx,
518                         *ty,
519                         cx.types.canonical_abi(ty).next_field32_size(&mut offset),
520                     )?;
521                 }
522                 Ok(())
523             }
524             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
525 
526             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
527                 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
528             }
529             (InterfaceType::Variant(_), _) => unexpected(ty, self),
530             (InterfaceType::Enum(ty), Val::Enum(v)) => {
531                 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
532             }
533             (InterfaceType::Enum(_), _) => unexpected(ty, self),
534             (InterfaceType::Option(ty), Val::Option(v)) => {
535                 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
536             }
537             (InterfaceType::Option(_), _) => unexpected(ty, self),
538             (InterfaceType::Result(ty), Val::Result(v)) => {
539                 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
540             }
541             (InterfaceType::Result(_), _) => unexpected(ty, self),
542 
543             (InterfaceType::Flags(ty), Val::Flags(flags)) => {
544                 let ty = &cx.types[ty];
545                 let storage = flags_to_storage(ty, flags)?;
546                 match FlagsSize::from_count(ty.names.len()) {
547                     FlagsSize::Size0 => {}
548                     FlagsSize::Size1 => {
549                         u8::try_from(storage[0])
550                             .unwrap()
551                             .store(cx, InterfaceType::U8, offset)?
552                     }
553                     FlagsSize::Size2 => {
554                         u16::try_from(storage[0])
555                             .unwrap()
556                             .store(cx, InterfaceType::U16, offset)?
557                     }
558                     FlagsSize::Size4Plus(_) => {
559                         let mut offset = offset;
560                         for value in storage {
561                             value.store(cx, InterfaceType::U32, offset)?;
562                             offset += 4;
563                         }
564                     }
565                 }
566                 Ok(())
567             }
568             (InterfaceType::Flags(_), _) => unexpected(ty, self),
569         }
570     }
571 
572     fn desc(&self) -> &'static str {
573         match self {
574             Val::Bool(_) => "bool",
575             Val::U8(_) => "u8",
576             Val::S8(_) => "s8",
577             Val::U16(_) => "u16",
578             Val::S16(_) => "s16",
579             Val::U32(_) => "u32",
580             Val::S32(_) => "s32",
581             Val::U64(_) => "u64",
582             Val::S64(_) => "s64",
583             Val::Float32(_) => "f32",
584             Val::Float64(_) => "f64",
585             Val::Char(_) => "char",
586             Val::List(_) => "list",
587             Val::String(_) => "string",
588             Val::Record(_) => "record",
589             Val::Enum(_) => "enum",
590             Val::Variant(..) => "variant",
591             Val::Tuple(_) => "tuple",
592             Val::Option(_) => "option",
593             Val::Result(_) => "result",
594             Val::Resource(_) => "resource",
595             Val::Flags(_) => "flags",
596         }
597     }
598 
599     /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization
600     /// requrires a target [`crate::component::Type`].
601     #[cfg(feature = "wave")]
602     pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
603         Ok(wasm_wave::from_str(ty, s)?)
604     }
605 
606     /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding.
607     #[cfg(feature = "wave")]
608     pub fn to_wave(&self) -> Result<String> {
609         Ok(wasm_wave::to_string(self)?)
610     }
611 }
612 
613 impl PartialEq for Val {
614     fn eq(&self, other: &Self) -> bool {
615         match (self, other) {
616             // IEEE 754 equality considers NaN inequal to NaN and negative zero
617             // equal to positive zero, however we do the opposite here, because
618             // this logic is used by testing and fuzzing, which want to know
619             // whether two values are semantically the same, rather than
620             // numerically equal.
621             (Self::Float32(l), Self::Float32(r)) => {
622                 (*l != 0.0 && l == r)
623                     || (*l == 0.0 && l.to_bits() == r.to_bits())
624                     || (l.is_nan() && r.is_nan())
625             }
626             (Self::Float32(_), _) => false,
627             (Self::Float64(l), Self::Float64(r)) => {
628                 (*l != 0.0 && l == r)
629                     || (*l == 0.0 && l.to_bits() == r.to_bits())
630                     || (l.is_nan() && r.is_nan())
631             }
632             (Self::Float64(_), _) => false,
633 
634             (Self::Bool(l), Self::Bool(r)) => l == r,
635             (Self::Bool(_), _) => false,
636             (Self::S8(l), Self::S8(r)) => l == r,
637             (Self::S8(_), _) => false,
638             (Self::U8(l), Self::U8(r)) => l == r,
639             (Self::U8(_), _) => false,
640             (Self::S16(l), Self::S16(r)) => l == r,
641             (Self::S16(_), _) => false,
642             (Self::U16(l), Self::U16(r)) => l == r,
643             (Self::U16(_), _) => false,
644             (Self::S32(l), Self::S32(r)) => l == r,
645             (Self::S32(_), _) => false,
646             (Self::U32(l), Self::U32(r)) => l == r,
647             (Self::U32(_), _) => false,
648             (Self::S64(l), Self::S64(r)) => l == r,
649             (Self::S64(_), _) => false,
650             (Self::U64(l), Self::U64(r)) => l == r,
651             (Self::U64(_), _) => false,
652             (Self::Char(l), Self::Char(r)) => l == r,
653             (Self::Char(_), _) => false,
654             (Self::String(l), Self::String(r)) => l == r,
655             (Self::String(_), _) => false,
656             (Self::List(l), Self::List(r)) => l == r,
657             (Self::List(_), _) => false,
658             (Self::Record(l), Self::Record(r)) => l == r,
659             (Self::Record(_), _) => false,
660             (Self::Tuple(l), Self::Tuple(r)) => l == r,
661             (Self::Tuple(_), _) => false,
662             (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
663             (Self::Variant(..), _) => false,
664             (Self::Enum(l), Self::Enum(r)) => l == r,
665             (Self::Enum(_), _) => false,
666             (Self::Option(l), Self::Option(r)) => l == r,
667             (Self::Option(_), _) => false,
668             (Self::Result(l), Self::Result(r)) => l == r,
669             (Self::Result(_), _) => false,
670             (Self::Flags(l), Self::Flags(r)) => l == r,
671             (Self::Flags(_), _) => false,
672             (Self::Resource(l), Self::Resource(r)) => l == r,
673             (Self::Resource(_), _) => false,
674         }
675     }
676 }
677 
678 impl Eq for Val {}
679 
680 struct GenericVariant<'a> {
681     discriminant: u32,
682     payload: Option<(&'a Val, InterfaceType)>,
683     abi: &'a CanonicalAbiInfo,
684     info: &'a VariantInfo,
685 }
686 
687 impl GenericVariant<'_> {
688     fn result<'a>(
689         ty: &'a TypeResult,
690         r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
691     ) -> Result<GenericVariant<'a>> {
692         let (discriminant, payload) = match r {
693             Ok(val) => {
694                 let payload = match (val, ty.ok) {
695                     (Some(val), Some(ty)) => Some((&**val, ty)),
696                     (None, None) => None,
697                     (Some(_), None) => {
698                         bail!("payload provided to `ok` but not expected");
699                     }
700                     (None, Some(_)) => {
701                         bail!("payload expected to `ok` but not provided");
702                     }
703                 };
704                 (0, payload)
705             }
706             Err(val) => {
707                 let payload = match (val, ty.err) {
708                     (Some(val), Some(ty)) => Some((&**val, ty)),
709                     (None, None) => None,
710                     (Some(_), None) => {
711                         bail!("payload provided to `err` but not expected");
712                     }
713                     (None, Some(_)) => {
714                         bail!("payload expected to `err` but not provided");
715                     }
716                 };
717                 (1, payload)
718             }
719         };
720         Ok(GenericVariant {
721             discriminant,
722             payload,
723             abi: &ty.abi,
724             info: &ty.info,
725         })
726     }
727 
728     fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
729         let (discriminant, payload) = match r {
730             None => (0, None),
731             Some(val) => (1, Some((&**val, ty.ty))),
732         };
733         GenericVariant {
734             discriminant,
735             payload,
736             abi: &ty.abi,
737             info: &ty.info,
738         }
739     }
740 
741     fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
742         let discriminant = get_enum_discriminant(ty, discriminant)?;
743 
744         Ok(GenericVariant {
745             discriminant,
746             payload: None,
747             abi: &ty.abi,
748             info: &ty.info,
749         })
750     }
751 
752     fn variant<'a>(
753         ty: &'a TypeVariant,
754         discriminant_name: &str,
755         payload: &'a Option<Box<Val>>,
756     ) -> Result<GenericVariant<'a>> {
757         let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
758 
759         let payload = match (payload, payload_ty) {
760             (Some(val), Some(ty)) => Some((&**val, *ty)),
761             (None, None) => None,
762             (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
763             (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
764         };
765 
766         Ok(GenericVariant {
767             discriminant,
768             payload,
769             abi: &ty.abi,
770             info: &ty.info,
771         })
772     }
773 
774     fn lower<T>(
775         &self,
776         cx: &mut LowerContext<'_, T>,
777         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
778     ) -> Result<()> {
779         next_mut(dst).write(ValRaw::u32(self.discriminant));
780 
781         // For the remaining lowered representation of this variant that
782         // the payload didn't write we write out zeros here to ensure
783         // the entire variant is written.
784         let value_flat = match self.payload {
785             Some((value, ty)) => {
786                 value.lower(cx, ty, dst)?;
787                 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
788             }
789             None => 0,
790         };
791         let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
792         for _ in (1 + value_flat)..variant_flat {
793             next_mut(dst).write(ValRaw::u64(0));
794         }
795         Ok(())
796     }
797 
798     fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
799         match self.info.size {
800             DiscriminantSize::Size1 => {
801                 u8::try_from(self.discriminant)
802                     .unwrap()
803                     .store(cx, InterfaceType::U8, offset)?
804             }
805             DiscriminantSize::Size2 => {
806                 u16::try_from(self.discriminant)
807                     .unwrap()
808                     .store(cx, InterfaceType::U16, offset)?
809             }
810             DiscriminantSize::Size4 => self.discriminant.store(cx, InterfaceType::U32, offset)?,
811         }
812 
813         if let Some((value, ty)) = self.payload {
814             let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
815             value.store(cx, ty, offset)?;
816         }
817 
818         Ok(())
819     }
820 }
821 
822 fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
823     let elem = cx.types[ty].element;
824     let abi = cx.types.canonical_abi(&elem);
825     let element_size = usize::try_from(abi.size32).unwrap();
826     let element_alignment = abi.align32;
827 
828     match len
829         .checked_mul(element_size)
830         .and_then(|len| ptr.checked_add(len))
831     {
832         Some(n) if n <= cx.memory().len() => {}
833         _ => bail!("list pointer/length out of bounds of memory"),
834     }
835     if ptr % usize::try_from(element_alignment).err2anyhow()? != 0 {
836         bail!("list pointer is not aligned")
837     }
838 
839     Ok(Val::List(
840         (0..len)
841             .map(|index| {
842                 Val::load(
843                     cx,
844                     elem,
845                     &cx.memory()[ptr + (index * element_size)..][..element_size],
846                 )
847             })
848             .collect::<Result<_>>()?,
849     ))
850 }
851 
852 fn load_variant(
853     cx: &mut LiftContext<'_>,
854     info: &VariantInfo,
855     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
856     bytes: &[u8],
857 ) -> Result<(u32, Option<Box<Val>>)> {
858     let discriminant = match info.size {
859         DiscriminantSize::Size1 => u32::from(u8::load(cx, InterfaceType::U8, &bytes[..1])?),
860         DiscriminantSize::Size2 => u32::from(u16::load(cx, InterfaceType::U16, &bytes[..2])?),
861         DiscriminantSize::Size4 => u32::load(cx, InterfaceType::U32, &bytes[..4])?,
862     };
863     let case_ty = types.nth(discriminant as usize).ok_or_else(|| {
864         anyhow!(
865             "discriminant {} out of range [0..{})",
866             discriminant,
867             types.len()
868         )
869     })?;
870     let value = match case_ty {
871         Some(case_ty) => {
872             let payload_offset = usize::try_from(info.payload_offset32).unwrap();
873             let case_abi = cx.types.canonical_abi(&case_ty);
874             let case_size = usize::try_from(case_abi.size32).unwrap();
875             Some(Box::new(Val::load(
876                 cx,
877                 case_ty,
878                 &bytes[payload_offset..][..case_size],
879             )?))
880         }
881         None => None,
882     };
883     Ok((discriminant, value))
884 }
885 
886 fn lift_variant(
887     cx: &mut LiftContext<'_>,
888     flatten_count: usize,
889     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
890     src: &mut Iter<'_, ValRaw>,
891 ) -> Result<(u32, Option<Box<Val>>)> {
892     let len = types.len();
893     let discriminant = next(src).get_u32();
894     let ty = types
895         .nth(discriminant as usize)
896         .ok_or_else(|| anyhow!("discriminant {} out of range [0..{})", discriminant, len))?;
897     let (value, value_flat) = match ty {
898         Some(ty) => (
899             Some(Box::new(Val::lift(cx, ty, src)?)),
900             cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
901         ),
902         None => (None, 0),
903     };
904     for _ in (1 + value_flat)..flatten_count {
905         next(src);
906     }
907     Ok((discriminant, value))
908 }
909 
910 /// Lower a list with the specified element type and values.
911 fn lower_list<T>(
912     cx: &mut LowerContext<'_, T>,
913     element_type: InterfaceType,
914     items: &[Val],
915 ) -> Result<(usize, usize)> {
916     let abi = cx.types.canonical_abi(&element_type);
917     let elt_size = usize::try_from(abi.size32).err2anyhow()?;
918     let elt_align = abi.align32;
919     let size = items
920         .len()
921         .checked_mul(elt_size)
922         .ok_or_else(|| anyhow::anyhow!("size overflow copying a list"))?;
923     let ptr = cx.realloc(0, 0, elt_align, size)?;
924     let mut element_ptr = ptr;
925     for item in items {
926         item.store(cx, element_type, element_ptr)?;
927         element_ptr += elt_size;
928     }
929     Ok((ptr, items.len()))
930 }
931 
932 fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
933     while bits > 0 {
934         if bits & 1 != 0 {
935             flags.push(ty.names[offset as usize].clone());
936         }
937         bits >>= 1;
938         offset += 1;
939     }
940 }
941 
942 fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
943     let mut storage = match FlagsSize::from_count(ty.names.len()) {
944         FlagsSize::Size0 => Vec::new(),
945         FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
946         FlagsSize::Size4Plus(n) => vec![0; n.into()],
947     };
948 
949     for flag in flags {
950         let bit = ty
951             .names
952             .get_index_of(flag)
953             .ok_or_else(|| anyhow::anyhow!("unknown flag: `{flag}`"))?;
954         storage[bit / 32] |= 1 << (bit % 32);
955     }
956     Ok(storage)
957 }
958 
959 fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
960     ty.names
961         .get_index_of(n)
962         .ok_or_else(|| anyhow::anyhow!("enum variant name `{n}` is not valid"))
963         .map(|i| i.try_into().unwrap())
964 }
965 
966 fn get_variant_discriminant<'a>(
967     ty: &'a TypeVariant,
968     name: &str,
969 ) -> Result<(u32, &'a Option<InterfaceType>)> {
970     let (i, _, ty) = ty
971         .cases
972         .get_full(name)
973         .ok_or_else(|| anyhow::anyhow!("unknown variant case: `{name}`"))?;
974     Ok((i.try_into().unwrap(), ty))
975 }
976 
977 fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
978     src.next().unwrap()
979 }
980 
981 fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
982     dst.next().unwrap()
983 }
984 
985 #[cold]
986 fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
987     bail!(
988         "type mismatch: expected {}, found {}",
989         desc(&ty),
990         val.desc()
991     )
992 }
993