1 use crate::ValRaw;
2 use crate::component::ResourceAny;
3 use crate::component::concurrent::{self, ErrorContext, FutureAny, StreamAny};
4 use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc};
5 use crate::prelude::*;
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, TypeMap, TypeMapIndex,
11     TypeOption, TypeResult, 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 #[expect(missing_docs, reason = "self-describing variants")]
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     /// A map type represented as a list of key-value pairs.
83     /// Duplicate keys are allowed and follow "last value wins" semantics.
84     Map(Vec<(Val, Val)>),
85     Record(Vec<(String, Val)>),
86     Tuple(Vec<Val>),
87     Variant(String, Option<Box<Val>>),
88     Enum(String),
89     Option(Option<Box<Val>>),
90     Result(Result<Option<Box<Val>>, Option<Box<Val>>>),
91     Flags(Vec<String>),
92     Resource(ResourceAny),
93     Future(FutureAny),
94     Stream(StreamAny),
95     ErrorContext(ErrorContextAny),
96 }
97 
98 impl Val {
99     /// Deserialize a value of this type from core Wasm stack values.
lift( cx: &mut LiftContext<'_>, ty: InterfaceType, src: &mut Iter<'_, ValRaw>, ) -> Result<Val>100     pub(crate) fn lift(
101         cx: &mut LiftContext<'_>,
102         ty: InterfaceType,
103         src: &mut Iter<'_, ValRaw>,
104     ) -> Result<Val> {
105         Ok(match ty {
106             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_flat(cx, ty, next(src))?),
107             InterfaceType::S8 => Val::S8(i8::linear_lift_from_flat(cx, ty, next(src))?),
108             InterfaceType::U8 => Val::U8(u8::linear_lift_from_flat(cx, ty, next(src))?),
109             InterfaceType::S16 => Val::S16(i16::linear_lift_from_flat(cx, ty, next(src))?),
110             InterfaceType::U16 => Val::U16(u16::linear_lift_from_flat(cx, ty, next(src))?),
111             InterfaceType::S32 => Val::S32(i32::linear_lift_from_flat(cx, ty, next(src))?),
112             InterfaceType::U32 => Val::U32(u32::linear_lift_from_flat(cx, ty, next(src))?),
113             InterfaceType::S64 => Val::S64(i64::linear_lift_from_flat(cx, ty, next(src))?),
114             InterfaceType::U64 => Val::U64(u64::linear_lift_from_flat(cx, ty, next(src))?),
115             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_flat(cx, ty, next(src))?),
116             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_flat(cx, ty, next(src))?),
117             InterfaceType::Char => Val::Char(char::linear_lift_from_flat(cx, ty, next(src))?),
118             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
119                 Val::Resource(ResourceAny::linear_lift_from_flat(cx, ty, next(src))?)
120             }
121             InterfaceType::String => Val::String(<_>::linear_lift_from_flat(
122                 cx,
123                 ty,
124                 &[*next(src), *next(src)],
125             )?),
126             InterfaceType::List(i) => {
127                 let (ptr, len) = lift_flat_pointer_pair(cx, src)?;
128                 load_list(cx, i, ptr, len)?
129             }
130             InterfaceType::Map(i) => {
131                 let (ptr, len) = lift_flat_pointer_pair(cx, src)?;
132                 load_map(cx, i, ptr, len)?
133             }
134             InterfaceType::Record(i) => Val::Record(
135                 cx.types[i]
136                     .fields
137                     .iter()
138                     .map(|field| {
139                         let val = Self::lift(cx, field.ty, src)?;
140                         Ok((field.name.to_string(), val))
141                     })
142                     .collect::<Result<_>>()?,
143             ),
144             InterfaceType::Tuple(i) => Val::Tuple(
145                 cx.types[i]
146                     .types
147                     .iter()
148                     .map(|ty| Self::lift(cx, *ty, src))
149                     .collect::<Result<_>>()?,
150             ),
151             InterfaceType::Variant(i) => {
152                 let vty = &cx.types[i];
153                 let (discriminant, value) = lift_variant(
154                     cx,
155                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
156                     vty.cases.values().copied(),
157                     src,
158                 )?;
159 
160                 let (k, _) = vty.cases.get_index(discriminant as usize).unwrap();
161                 Val::Variant(k.clone(), value)
162             }
163             InterfaceType::Enum(i) => {
164                 let ety = &cx.types[i];
165                 let (discriminant, _) = lift_variant(
166                     cx,
167                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
168                     ety.names.iter().map(|_| None),
169                     src,
170                 )?;
171 
172                 Val::Enum(ety.names[discriminant as usize].clone())
173             }
174             InterfaceType::Option(i) => {
175                 let (_discriminant, value) = lift_variant(
176                     cx,
177                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
178                     [None, Some(cx.types[i].ty)].into_iter(),
179                     src,
180                 )?;
181 
182                 Val::Option(value)
183             }
184             InterfaceType::Result(i) => {
185                 let result_ty = &cx.types[i];
186                 let (discriminant, value) = lift_variant(
187                     cx,
188                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
189                     [result_ty.ok, result_ty.err].into_iter(),
190                     src,
191                 )?;
192 
193                 Val::Result(if discriminant == 0 {
194                     Ok(value)
195                 } else {
196                     Err(value)
197                 })
198             }
199             InterfaceType::Flags(i) => {
200                 let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap();
201                 let ty = &cx.types[i];
202                 let mut flags = Vec::new();
203                 for i in 0..u32::try_from(u32_count).unwrap() {
204                     push_flags(
205                         ty,
206                         &mut flags,
207                         i * 32,
208                         u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))?,
209                     );
210                 }
211 
212                 Val::Flags(flags)
213             }
214             InterfaceType::Future(_) => {
215                 Val::Future(FutureAny::linear_lift_from_flat(cx, ty, next(src))?)
216             }
217             InterfaceType::Stream(_) => {
218                 Val::Stream(StreamAny::linear_lift_from_flat(cx, ty, next(src))?)
219             }
220             InterfaceType::ErrorContext(_) => {
221                 ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val()
222             }
223             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
224         })
225     }
226 
227     /// Deserialize a value of this type from the heap.
load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val>228     pub(crate) fn load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val> {
229         Ok(match ty {
230             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_memory(cx, ty, bytes)?),
231             InterfaceType::S8 => Val::S8(i8::linear_lift_from_memory(cx, ty, bytes)?),
232             InterfaceType::U8 => Val::U8(u8::linear_lift_from_memory(cx, ty, bytes)?),
233             InterfaceType::S16 => Val::S16(i16::linear_lift_from_memory(cx, ty, bytes)?),
234             InterfaceType::U16 => Val::U16(u16::linear_lift_from_memory(cx, ty, bytes)?),
235             InterfaceType::S32 => Val::S32(i32::linear_lift_from_memory(cx, ty, bytes)?),
236             InterfaceType::U32 => Val::U32(u32::linear_lift_from_memory(cx, ty, bytes)?),
237             InterfaceType::S64 => Val::S64(i64::linear_lift_from_memory(cx, ty, bytes)?),
238             InterfaceType::U64 => Val::U64(u64::linear_lift_from_memory(cx, ty, bytes)?),
239             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_memory(cx, ty, bytes)?),
240             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_memory(cx, ty, bytes)?),
241             InterfaceType::Char => Val::Char(char::linear_lift_from_memory(cx, ty, bytes)?),
242             InterfaceType::String => Val::String(<_>::linear_lift_from_memory(cx, ty, bytes)?),
243             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
244                 Val::Resource(ResourceAny::linear_lift_from_memory(cx, ty, bytes)?)
245             }
246             InterfaceType::List(i) => {
247                 let (ptr, len) = load_flat_pointer_pair(bytes);
248                 load_list(cx, i, ptr, len)?
249             }
250             InterfaceType::Map(i) => {
251                 let (ptr, len) = load_flat_pointer_pair(bytes);
252                 load_map(cx, i, ptr, len)?
253             }
254 
255             InterfaceType::Record(i) => {
256                 let mut offset = 0;
257                 let fields = cx.types[i].fields.iter();
258                 Val::Record(
259                     fields
260                         .map(|field| -> Result<(String, Val)> {
261                             let abi = cx.types.canonical_abi(&field.ty);
262                             let offset = abi.next_field32(&mut offset);
263                             let offset = usize::try_from(offset).unwrap();
264                             let size = usize::try_from(abi.size32).unwrap();
265                             Ok((
266                                 field.name.to_string(),
267                                 Val::load(cx, field.ty, &bytes[offset..][..size])?,
268                             ))
269                         })
270                         .collect::<Result<_>>()?,
271                 )
272             }
273             InterfaceType::Tuple(i) => {
274                 let types = cx.types[i].types.iter().copied();
275                 let mut offset = 0;
276                 Val::Tuple(
277                     types
278                         .map(|ty| {
279                             let abi = cx.types.canonical_abi(&ty);
280                             let offset = abi.next_field32(&mut offset);
281                             let offset = usize::try_from(offset).unwrap();
282                             let size = usize::try_from(abi.size32).unwrap();
283                             Val::load(cx, ty, &bytes[offset..][..size])
284                         })
285                         .collect::<Result<_>>()?,
286                 )
287             }
288             InterfaceType::Variant(i) => {
289                 let ty = &cx.types[i];
290                 let (discriminant, value) =
291                     load_variant(cx, &ty.info, ty.cases.values().copied(), bytes)?;
292 
293                 let (k, _) = ty.cases.get_index(discriminant as usize).unwrap();
294                 Val::Variant(k.clone(), value)
295             }
296             InterfaceType::Enum(i) => {
297                 let ty = &cx.types[i];
298                 let (discriminant, _) =
299                     load_variant(cx, &ty.info, ty.names.iter().map(|_| None), bytes)?;
300 
301                 Val::Enum(ty.names[discriminant as usize].clone())
302             }
303             InterfaceType::Option(i) => {
304                 let ty = &cx.types[i];
305                 let (_discriminant, value) =
306                     load_variant(cx, &ty.info, [None, Some(ty.ty)].into_iter(), bytes)?;
307 
308                 Val::Option(value)
309             }
310             InterfaceType::Result(i) => {
311                 let ty = &cx.types[i];
312                 let (discriminant, value) =
313                     load_variant(cx, &ty.info, [ty.ok, ty.err].into_iter(), bytes)?;
314 
315                 Val::Result(if discriminant == 0 {
316                     Ok(value)
317                 } else {
318                     Err(value)
319                 })
320             }
321             InterfaceType::Flags(i) => {
322                 let ty = &cx.types[i];
323                 let mut flags = Vec::new();
324                 match FlagsSize::from_count(ty.names.len()) {
325                     FlagsSize::Size0 => {}
326                     FlagsSize::Size1 => {
327                         let bits = u8::linear_lift_from_memory(cx, InterfaceType::U8, bytes)?;
328                         push_flags(ty, &mut flags, 0, u32::from(bits));
329                     }
330                     FlagsSize::Size2 => {
331                         let bits = u16::linear_lift_from_memory(cx, InterfaceType::U16, bytes)?;
332                         push_flags(ty, &mut flags, 0, u32::from(bits));
333                     }
334                     FlagsSize::Size4Plus(n) => {
335                         for i in 0..n {
336                             let bits = u32::linear_lift_from_memory(
337                                 cx,
338                                 InterfaceType::U32,
339                                 &bytes[usize::from(i) * 4..][..4],
340                             )?;
341                             push_flags(ty, &mut flags, u32::from(i) * 32, bits);
342                         }
343                     }
344                 }
345                 Val::Flags(flags)
346             }
347             InterfaceType::Future(_) => FutureAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
348             InterfaceType::Stream(_) => StreamAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
349             InterfaceType::ErrorContext(_) => {
350                 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val()
351             }
352             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
353         })
354     }
355 
356     /// Serialize this value as core Wasm stack values.
lower<T>( &self, cx: &mut LowerContext<'_, T>, ty: InterfaceType, dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, ) -> Result<()>357     pub(crate) fn lower<T>(
358         &self,
359         cx: &mut LowerContext<'_, T>,
360         ty: InterfaceType,
361         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
362     ) -> Result<()> {
363         match (ty, self) {
364             (InterfaceType::Bool, Val::Bool(value)) => {
365                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
366             }
367             (InterfaceType::Bool, _) => unexpected(ty, self),
368             (InterfaceType::S8, Val::S8(value)) => {
369                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
370             }
371             (InterfaceType::S8, _) => unexpected(ty, self),
372             (InterfaceType::U8, Val::U8(value)) => {
373                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
374             }
375             (InterfaceType::U8, _) => unexpected(ty, self),
376             (InterfaceType::S16, Val::S16(value)) => {
377                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
378             }
379             (InterfaceType::S16, _) => unexpected(ty, self),
380             (InterfaceType::U16, Val::U16(value)) => {
381                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
382             }
383             (InterfaceType::U16, _) => unexpected(ty, self),
384             (InterfaceType::S32, Val::S32(value)) => {
385                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
386             }
387             (InterfaceType::S32, _) => unexpected(ty, self),
388             (InterfaceType::U32, Val::U32(value)) => {
389                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
390             }
391             (InterfaceType::U32, _) => unexpected(ty, self),
392             (InterfaceType::S64, Val::S64(value)) => {
393                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
394             }
395             (InterfaceType::S64, _) => unexpected(ty, self),
396             (InterfaceType::U64, Val::U64(value)) => {
397                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
398             }
399             (InterfaceType::U64, _) => unexpected(ty, self),
400             (InterfaceType::Float32, Val::Float32(value)) => {
401                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
402             }
403             (InterfaceType::Float32, _) => unexpected(ty, self),
404             (InterfaceType::Float64, Val::Float64(value)) => {
405                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
406             }
407             (InterfaceType::Float64, _) => unexpected(ty, self),
408             (InterfaceType::Char, Val::Char(value)) => {
409                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
410             }
411             (InterfaceType::Char, _) => unexpected(ty, self),
412             // NB: `lower` on `ResourceAny` does its own type-checking, so skip
413             // looking at it here.
414             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
415                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
416             }
417             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
418             (InterfaceType::String, Val::String(value)) => {
419                 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit();
420                 value.linear_lower_to_flat(cx, ty, my_dst)?;
421                 let my_dst = unsafe { my_dst.assume_init() };
422                 next_mut(dst).write(my_dst[0]);
423                 next_mut(dst).write(my_dst[1]);
424                 Ok(())
425             }
426             (InterfaceType::String, _) => unexpected(ty, self),
427             (InterfaceType::List(ty), Val::List(values)) => {
428                 let ty = &cx.types[ty];
429                 let (ptr, len) = lower_list(cx, ty.element, values)?;
430                 next_mut(dst).write(ValRaw::i64(ptr as i64));
431                 next_mut(dst).write(ValRaw::i64(len as i64));
432                 Ok(())
433             }
434             (InterfaceType::List(_), _) => unexpected(ty, self),
435             (InterfaceType::Map(ty), Val::Map(pairs)) => {
436                 let map_ty = &cx.types[ty];
437                 let (ptr, len) = lower_map(cx, map_ty, pairs)?;
438                 next_mut(dst).write(ValRaw::i64(ptr as i64));
439                 next_mut(dst).write(ValRaw::i64(len as i64));
440                 Ok(())
441             }
442             (InterfaceType::Map(_), _) => unexpected(ty, self),
443             (InterfaceType::Record(ty), Val::Record(values)) => {
444                 let ty = &cx.types[ty];
445                 if ty.fields.len() != values.len() {
446                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
447                 }
448                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
449                     if *name != field.name {
450                         bail!("expected field `{}`, got `{name}`", field.name);
451                     }
452                     value.lower(cx, field.ty, dst)?;
453                 }
454                 Ok(())
455             }
456             (InterfaceType::Record(_), _) => unexpected(ty, self),
457             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
458                 let ty = &cx.types[ty];
459                 if ty.types.len() != values.len() {
460                     bail!("expected {} types, got {}", ty.types.len(), values.len());
461                 }
462                 for (value, ty) in values.iter().zip(ty.types.iter()) {
463                     value.lower(cx, *ty, dst)?;
464                 }
465                 Ok(())
466             }
467             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
468             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
469                 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst)
470             }
471             (InterfaceType::Variant(_), _) => unexpected(ty, self),
472             (InterfaceType::Option(ty), Val::Option(v)) => {
473                 GenericVariant::option(&cx.types[ty], v).lower(cx, dst)
474             }
475             (InterfaceType::Option(_), _) => unexpected(ty, self),
476             (InterfaceType::Result(ty), Val::Result(v)) => {
477                 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst)
478             }
479             (InterfaceType::Result(_), _) => unexpected(ty, self),
480             (InterfaceType::Enum(ty), Val::Enum(discriminant)) => {
481                 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?;
482                 next_mut(dst).write(ValRaw::u32(discriminant));
483                 Ok(())
484             }
485             (InterfaceType::Enum(_), _) => unexpected(ty, self),
486             (InterfaceType::Flags(ty), Val::Flags(value)) => {
487                 let ty = &cx.types[ty];
488                 let storage = flags_to_storage(ty, value)?;
489                 for value in storage {
490                     next_mut(dst).write(ValRaw::u32(value));
491                 }
492                 Ok(())
493             }
494             (InterfaceType::Flags(_), _) => unexpected(ty, self),
495             (InterfaceType::Future(_), Val::Future(f)) => {
496                 f.linear_lower_to_flat(cx, ty, next_mut(dst))
497             }
498             (InterfaceType::Future(_), _) => unexpected(ty, self),
499             (InterfaceType::Stream(_), Val::Stream(s)) => {
500                 s.linear_lower_to_flat(cx, ty, next_mut(dst))
501             }
502             (InterfaceType::Stream(_), _) => unexpected(ty, self),
503             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
504                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat(
505                     cx,
506                     InterfaceType::U32,
507                     next_mut(dst),
508                 )
509             }
510             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
511             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
512         }
513     }
514 
515     /// Serialize this value to the heap at the specified memory location.
store<T>( &self, cx: &mut LowerContext<'_, T>, ty: InterfaceType, offset: usize, ) -> Result<()>516     pub(crate) fn store<T>(
517         &self,
518         cx: &mut LowerContext<'_, T>,
519         ty: InterfaceType,
520         offset: usize,
521     ) -> Result<()> {
522         debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0);
523 
524         match (ty, self) {
525             (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset),
526             (InterfaceType::Bool, _) => unexpected(ty, self),
527             (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset),
528             (InterfaceType::U8, _) => unexpected(ty, self),
529             (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset),
530             (InterfaceType::S8, _) => unexpected(ty, self),
531             (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset),
532             (InterfaceType::U16, _) => unexpected(ty, self),
533             (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset),
534             (InterfaceType::S16, _) => unexpected(ty, self),
535             (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset),
536             (InterfaceType::U32, _) => unexpected(ty, self),
537             (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset),
538             (InterfaceType::S32, _) => unexpected(ty, self),
539             (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset),
540             (InterfaceType::U64, _) => unexpected(ty, self),
541             (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset),
542             (InterfaceType::S64, _) => unexpected(ty, self),
543             (InterfaceType::Float32, Val::Float32(value)) => {
544                 value.linear_lower_to_memory(cx, ty, offset)
545             }
546             (InterfaceType::Float32, _) => unexpected(ty, self),
547             (InterfaceType::Float64, Val::Float64(value)) => {
548                 value.linear_lower_to_memory(cx, ty, offset)
549             }
550             (InterfaceType::Float64, _) => unexpected(ty, self),
551             (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset),
552             (InterfaceType::Char, _) => unexpected(ty, self),
553             (InterfaceType::String, Val::String(value)) => {
554                 value.linear_lower_to_memory(cx, ty, offset)
555             }
556             (InterfaceType::String, _) => unexpected(ty, self),
557 
558             // NB: resources do type-checking when they lower.
559             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
560                 value.linear_lower_to_memory(cx, ty, offset)
561             }
562             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
563             (InterfaceType::List(ty), Val::List(values)) => {
564                 let ty = &cx.types[ty];
565                 let (ptr, len) = lower_list(cx, ty.element, values)?;
566                 // FIXME(#4311): needs memory64 handling
567                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
568                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
569                 Ok(())
570             }
571             (InterfaceType::List(_), _) => unexpected(ty, self),
572             (InterfaceType::Map(ty_idx), Val::Map(values)) => {
573                 let map_ty = &cx.types[ty_idx];
574                 let (ptr, len) = lower_map(cx, map_ty, values)?;
575                 // FIXME(#4311): needs memory64 handling
576                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
577                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
578                 Ok(())
579             }
580             (InterfaceType::Map(_), _) => unexpected(ty, self),
581             (InterfaceType::Record(ty), Val::Record(values)) => {
582                 let ty = &cx.types[ty];
583                 if ty.fields.len() != values.len() {
584                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
585                 }
586                 let mut offset = offset;
587                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
588                     if *name != field.name {
589                         bail!("expected field `{}`, got `{name}`", field.name);
590                     }
591                     value.store(
592                         cx,
593                         field.ty,
594                         cx.types
595                             .canonical_abi(&field.ty)
596                             .next_field32_size(&mut offset),
597                     )?;
598                 }
599                 Ok(())
600             }
601             (InterfaceType::Record(_), _) => unexpected(ty, self),
602             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
603                 let ty = &cx.types[ty];
604                 if ty.types.len() != values.len() {
605                     bail!("expected {} types, got {}", ty.types.len(), values.len());
606                 }
607                 let mut offset = offset;
608                 for (value, ty) in values.iter().zip(ty.types.iter()) {
609                     value.store(
610                         cx,
611                         *ty,
612                         cx.types.canonical_abi(ty).next_field32_size(&mut offset),
613                     )?;
614                 }
615                 Ok(())
616             }
617             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
618 
619             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
620                 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
621             }
622             (InterfaceType::Variant(_), _) => unexpected(ty, self),
623             (InterfaceType::Enum(ty), Val::Enum(v)) => {
624                 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
625             }
626             (InterfaceType::Enum(_), _) => unexpected(ty, self),
627             (InterfaceType::Option(ty), Val::Option(v)) => {
628                 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
629             }
630             (InterfaceType::Option(_), _) => unexpected(ty, self),
631             (InterfaceType::Result(ty), Val::Result(v)) => {
632                 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
633             }
634             (InterfaceType::Result(_), _) => unexpected(ty, self),
635 
636             (InterfaceType::Flags(ty), Val::Flags(flags)) => {
637                 let ty = &cx.types[ty];
638                 let storage = flags_to_storage(ty, flags)?;
639                 match FlagsSize::from_count(ty.names.len()) {
640                     FlagsSize::Size0 => {}
641                     FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory(
642                         cx,
643                         InterfaceType::U8,
644                         offset,
645                     )?,
646                     FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory(
647                         cx,
648                         InterfaceType::U16,
649                         offset,
650                     )?,
651                     FlagsSize::Size4Plus(_) => {
652                         let mut offset = offset;
653                         for value in storage {
654                             value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?;
655                             offset += 4;
656                         }
657                     }
658                 }
659                 Ok(())
660             }
661             (InterfaceType::Flags(_), _) => unexpected(ty, self),
662             (InterfaceType::Future(_), Val::Future(f)) => f.linear_lower_to_memory(cx, ty, offset),
663             (InterfaceType::Future(_), _) => unexpected(ty, self),
664             (InterfaceType::Stream(_), Val::Stream(s)) => s.linear_lower_to_memory(cx, ty, offset),
665             (InterfaceType::Stream(_), _) => unexpected(ty, self),
666             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
667                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory(
668                     cx,
669                     InterfaceType::U32,
670                     offset,
671                 )
672             }
673             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
674             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
675         }
676     }
677 
desc(&self) -> &'static str678     pub(crate) fn desc(&self) -> &'static str {
679         match self {
680             Val::Bool(_) => "bool",
681             Val::U8(_) => "u8",
682             Val::S8(_) => "s8",
683             Val::U16(_) => "u16",
684             Val::S16(_) => "s16",
685             Val::U32(_) => "u32",
686             Val::S32(_) => "s32",
687             Val::U64(_) => "u64",
688             Val::S64(_) => "s64",
689             Val::Float32(_) => "f32",
690             Val::Float64(_) => "f64",
691             Val::Char(_) => "char",
692             Val::List(_) => "list",
693             Val::Map(_) => "map",
694             Val::String(_) => "string",
695             Val::Record(_) => "record",
696             Val::Enum(_) => "enum",
697             Val::Variant(..) => "variant",
698             Val::Tuple(_) => "tuple",
699             Val::Option(_) => "option",
700             Val::Result(_) => "result",
701             Val::Resource(_) => "resource",
702             Val::Flags(_) => "flags",
703             Val::Future(_) => "future",
704             Val::Stream(_) => "stream",
705             Val::ErrorContext(_) => "error-context",
706         }
707     }
708 
709     /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization
710     /// requires a target [`crate::component::Type`].
711     #[cfg(feature = "wave")]
from_wave(ty: &crate::component::Type, s: &str) -> Result<Self>712     pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
713         Ok(wasm_wave::from_str(ty, s)?)
714     }
715 
716     /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding.
717     #[cfg(feature = "wave")]
to_wave(&self) -> Result<String>718     pub fn to_wave(&self) -> Result<String> {
719         Ok(wasm_wave::to_string(self)?)
720     }
721 }
722 
723 impl PartialEq for Val {
eq(&self, other: &Self) -> bool724     fn eq(&self, other: &Self) -> bool {
725         match (self, other) {
726             // IEEE 754 equality considers NaN inequal to NaN and negative zero
727             // equal to positive zero, however we do the opposite here, because
728             // this logic is used by testing and fuzzing, which want to know
729             // whether two values are semantically the same, rather than
730             // numerically equal.
731             (Self::Float32(l), Self::Float32(r)) => {
732                 (*l != 0.0 && l == r)
733                     || (*l == 0.0 && l.to_bits() == r.to_bits())
734                     || (l.is_nan() && r.is_nan())
735             }
736             (Self::Float32(_), _) => false,
737             (Self::Float64(l), Self::Float64(r)) => {
738                 (*l != 0.0 && l == r)
739                     || (*l == 0.0 && l.to_bits() == r.to_bits())
740                     || (l.is_nan() && r.is_nan())
741             }
742             (Self::Float64(_), _) => false,
743 
744             (Self::Bool(l), Self::Bool(r)) => l == r,
745             (Self::Bool(_), _) => false,
746             (Self::S8(l), Self::S8(r)) => l == r,
747             (Self::S8(_), _) => false,
748             (Self::U8(l), Self::U8(r)) => l == r,
749             (Self::U8(_), _) => false,
750             (Self::S16(l), Self::S16(r)) => l == r,
751             (Self::S16(_), _) => false,
752             (Self::U16(l), Self::U16(r)) => l == r,
753             (Self::U16(_), _) => false,
754             (Self::S32(l), Self::S32(r)) => l == r,
755             (Self::S32(_), _) => false,
756             (Self::U32(l), Self::U32(r)) => l == r,
757             (Self::U32(_), _) => false,
758             (Self::S64(l), Self::S64(r)) => l == r,
759             (Self::S64(_), _) => false,
760             (Self::U64(l), Self::U64(r)) => l == r,
761             (Self::U64(_), _) => false,
762             (Self::Char(l), Self::Char(r)) => l == r,
763             (Self::Char(_), _) => false,
764             (Self::String(l), Self::String(r)) => l == r,
765             (Self::String(_), _) => false,
766             (Self::List(l), Self::List(r)) => l == r,
767             (Self::List(_), _) => false,
768             (Self::Map(l), Self::Map(r)) => l == r,
769             (Self::Map(_), _) => false,
770             (Self::Record(l), Self::Record(r)) => l == r,
771             (Self::Record(_), _) => false,
772             (Self::Tuple(l), Self::Tuple(r)) => l == r,
773             (Self::Tuple(_), _) => false,
774             (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
775             (Self::Variant(..), _) => false,
776             (Self::Enum(l), Self::Enum(r)) => l == r,
777             (Self::Enum(_), _) => false,
778             (Self::Option(l), Self::Option(r)) => l == r,
779             (Self::Option(_), _) => false,
780             (Self::Result(l), Self::Result(r)) => l == r,
781             (Self::Result(_), _) => false,
782             (Self::Flags(l), Self::Flags(r)) => l == r,
783             (Self::Flags(_), _) => false,
784             (Self::Resource(l), Self::Resource(r)) => l == r,
785             (Self::Resource(_), _) => false,
786             (Self::Future(l), Self::Future(r)) => l == r,
787             (Self::Future(_), _) => false,
788             (Self::Stream(l), Self::Stream(r)) => l == r,
789             (Self::Stream(_), _) => false,
790             (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r,
791             (Self::ErrorContext(_), _) => false,
792         }
793     }
794 }
795 
796 impl Eq for Val {}
797 
798 struct GenericVariant<'a> {
799     discriminant: u32,
800     payload: Option<(&'a Val, InterfaceType)>,
801     abi: &'a CanonicalAbiInfo,
802     info: &'a VariantInfo,
803 }
804 
805 impl GenericVariant<'_> {
result<'a>( ty: &'a TypeResult, r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>, ) -> Result<GenericVariant<'a>>806     fn result<'a>(
807         ty: &'a TypeResult,
808         r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
809     ) -> Result<GenericVariant<'a>> {
810         let (discriminant, payload) = match r {
811             Ok(val) => {
812                 let payload = match (val, ty.ok) {
813                     (Some(val), Some(ty)) => Some((&**val, ty)),
814                     (None, None) => None,
815                     (Some(_), None) => {
816                         bail!("payload provided to `ok` but not expected");
817                     }
818                     (None, Some(_)) => {
819                         bail!("payload expected to `ok` but not provided");
820                     }
821                 };
822                 (0, payload)
823             }
824             Err(val) => {
825                 let payload = match (val, ty.err) {
826                     (Some(val), Some(ty)) => Some((&**val, ty)),
827                     (None, None) => None,
828                     (Some(_), None) => {
829                         bail!("payload provided to `err` but not expected");
830                     }
831                     (None, Some(_)) => {
832                         bail!("payload expected to `err` but not provided");
833                     }
834                 };
835                 (1, payload)
836             }
837         };
838         Ok(GenericVariant {
839             discriminant,
840             payload,
841             abi: &ty.abi,
842             info: &ty.info,
843         })
844     }
845 
option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a>846     fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
847         let (discriminant, payload) = match r {
848             None => (0, None),
849             Some(val) => (1, Some((&**val, ty.ty))),
850         };
851         GenericVariant {
852             discriminant,
853             payload,
854             abi: &ty.abi,
855             info: &ty.info,
856         }
857     }
858 
enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>>859     fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
860         let discriminant = get_enum_discriminant(ty, discriminant)?;
861 
862         Ok(GenericVariant {
863             discriminant,
864             payload: None,
865             abi: &ty.abi,
866             info: &ty.info,
867         })
868     }
869 
variant<'a>( ty: &'a TypeVariant, discriminant_name: &str, payload: &'a Option<Box<Val>>, ) -> Result<GenericVariant<'a>>870     fn variant<'a>(
871         ty: &'a TypeVariant,
872         discriminant_name: &str,
873         payload: &'a Option<Box<Val>>,
874     ) -> Result<GenericVariant<'a>> {
875         let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
876 
877         let payload = match (payload, payload_ty) {
878             (Some(val), Some(ty)) => Some((&**val, *ty)),
879             (None, None) => None,
880             (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
881             (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
882         };
883 
884         Ok(GenericVariant {
885             discriminant,
886             payload,
887             abi: &ty.abi,
888             info: &ty.info,
889         })
890     }
891 
lower<T>( &self, cx: &mut LowerContext<'_, T>, dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, ) -> Result<()>892     fn lower<T>(
893         &self,
894         cx: &mut LowerContext<'_, T>,
895         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
896     ) -> Result<()> {
897         next_mut(dst).write(ValRaw::u32(self.discriminant));
898 
899         // For the remaining lowered representation of this variant that
900         // the payload didn't write we write out zeros here to ensure
901         // the entire variant is written.
902         let value_flat = match self.payload {
903             Some((value, ty)) => {
904                 value.lower(cx, ty, dst)?;
905                 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
906             }
907             None => 0,
908         };
909         let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
910         for _ in (1 + value_flat)..variant_flat {
911             next_mut(dst).write(ValRaw::u64(0));
912         }
913         Ok(())
914     }
915 
store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()>916     fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
917         match self.info.size {
918             DiscriminantSize::Size1 => u8::try_from(self.discriminant)
919                 .unwrap()
920                 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?,
921             DiscriminantSize::Size2 => u16::try_from(self.discriminant)
922                 .unwrap()
923                 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?,
924             DiscriminantSize::Size4 => {
925                 self.discriminant
926                     .linear_lower_to_memory(cx, InterfaceType::U32, offset)?
927             }
928         }
929 
930         if let Some((value, ty)) = self.payload {
931             let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
932             value.store(cx, ty, offset)?;
933         }
934 
935         Ok(())
936     }
937 }
938 
lift_flat_pointer_pair( cx: &mut LiftContext<'_>, src: &mut Iter<'_, ValRaw>, ) -> Result<(usize, usize)>939 fn lift_flat_pointer_pair(
940     cx: &mut LiftContext<'_>,
941     src: &mut Iter<'_, ValRaw>,
942 ) -> Result<(usize, usize)> {
943     // FIXME(#4311): needs memory64 treatment
944     let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
945     let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
946     Ok((ptr, len))
947 }
948 
load_flat_pointer_pair(bytes: &[u8]) -> (usize, usize)949 fn load_flat_pointer_pair(bytes: &[u8]) -> (usize, usize) {
950     let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize;
951     let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize;
952     (ptr, len)
953 }
954 
load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val>955 fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
956     let elem = cx.types[ty].element;
957     let abi = cx.types.canonical_abi(&elem);
958     let element_size = usize::try_from(abi.size32).unwrap();
959     let element_alignment = abi.align32;
960 
961     match len
962         .checked_mul(element_size)
963         .and_then(|len| ptr.checked_add(len))
964     {
965         Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<Val>())?,
966         _ => bail!("list pointer/length out of bounds of memory"),
967     }
968     if ptr % usize::try_from(element_alignment)? != 0 {
969         bail!("list pointer is not aligned")
970     }
971 
972     Ok(Val::List(
973         (0..len)
974             .map(|index| {
975                 Val::load(
976                     cx,
977                     elem,
978                     &cx.memory()[ptr + (index * element_size)..][..element_size],
979                 )
980             })
981             .collect::<Result<_>>()?,
982     ))
983 }
984 
load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val>985 fn load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val> {
986     // Maps are stored as list<tuple<k, v>> in canonical ABI
987     let map_ty = &cx.types[ty];
988     let key_ty = map_ty.key;
989     let value_ty = map_ty.value;
990 
991     let key_abi = cx.types.canonical_abi(&key_ty);
992     let value_abi = cx.types.canonical_abi(&value_ty);
993     let key_size = usize::try_from(key_abi.size32).unwrap();
994     let value_size = usize::try_from(value_abi.size32).unwrap();
995     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
996     let tuple_alignment = map_ty.entry_abi.align32;
997     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
998 
999     // Bounds check
1000     match len
1001         .checked_mul(tuple_size)
1002         .and_then(|len| ptr.checked_add(len))
1003     {
1004         Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<(Val, Val)>())?,
1005         _ => bail!("map pointer/length out of bounds of memory"),
1006     }
1007     if ptr % usize::try_from(tuple_alignment)? != 0 {
1008         bail!("map pointer is not aligned")
1009     }
1010 
1011     // Load each tuple (key, value) into a Vec
1012     let mut map = Vec::with_capacity(len);
1013     for index in 0..len {
1014         let tuple_ptr = ptr + (index * tuple_size);
1015         let key = Val::load(cx, key_ty, &cx.memory()[tuple_ptr..][..key_size])?;
1016         let value = Val::load(
1017             cx,
1018             value_ty,
1019             &cx.memory()[tuple_ptr + value_offset..][..value_size],
1020         )?;
1021         map.push((key, value));
1022     }
1023 
1024     Ok(Val::Map(map))
1025 }
1026 
load_variant( cx: &mut LiftContext<'_>, info: &VariantInfo, mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, bytes: &[u8], ) -> Result<(u32, Option<Box<Val>>)>1027 fn load_variant(
1028     cx: &mut LiftContext<'_>,
1029     info: &VariantInfo,
1030     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1031     bytes: &[u8],
1032 ) -> Result<(u32, Option<Box<Val>>)> {
1033     let discriminant = match info.size {
1034         DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory(
1035             cx,
1036             InterfaceType::U8,
1037             &bytes[..1],
1038         )?),
1039         DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory(
1040             cx,
1041             InterfaceType::U16,
1042             &bytes[..2],
1043         )?),
1044         DiscriminantSize::Size4 => {
1045             u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])?
1046         }
1047     };
1048     let len = types.len();
1049     let case_ty = types
1050         .nth(discriminant as usize)
1051         .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?;
1052     let value = match case_ty {
1053         Some(case_ty) => {
1054             let payload_offset = usize::try_from(info.payload_offset32).unwrap();
1055             let case_abi = cx.types.canonical_abi(&case_ty);
1056             let case_size = usize::try_from(case_abi.size32).unwrap();
1057             Some(Box::new(Val::load(
1058                 cx,
1059                 case_ty,
1060                 &bytes[payload_offset..][..case_size],
1061             )?))
1062         }
1063         None => None,
1064     };
1065     Ok((discriminant, value))
1066 }
1067 
lift_variant( cx: &mut LiftContext<'_>, flatten_count: usize, mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, src: &mut Iter<'_, ValRaw>, ) -> Result<(u32, Option<Box<Val>>)>1068 fn lift_variant(
1069     cx: &mut LiftContext<'_>,
1070     flatten_count: usize,
1071     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1072     src: &mut Iter<'_, ValRaw>,
1073 ) -> Result<(u32, Option<Box<Val>>)> {
1074     let len = types.len();
1075     let discriminant = next(src).get_u32();
1076     let ty = types
1077         .nth(discriminant as usize)
1078         .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?;
1079     let (value, value_flat) = match ty {
1080         Some(ty) => (
1081             Some(Box::new(Val::lift(cx, ty, src)?)),
1082             cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1083         ),
1084         None => (None, 0),
1085     };
1086     for _ in (1 + value_flat)..flatten_count {
1087         next(src);
1088     }
1089     Ok((discriminant, value))
1090 }
1091 
1092 /// Lower a list with the specified element type and values.
lower_list<T>( cx: &mut LowerContext<'_, T>, element_type: InterfaceType, items: &[Val], ) -> Result<(usize, usize)>1093 fn lower_list<T>(
1094     cx: &mut LowerContext<'_, T>,
1095     element_type: InterfaceType,
1096     items: &[Val],
1097 ) -> Result<(usize, usize)> {
1098     let abi = cx.types.canonical_abi(&element_type);
1099     let elt_size = usize::try_from(abi.size32)?;
1100     let elt_align = abi.align32;
1101     let size = items
1102         .len()
1103         .checked_mul(elt_size)
1104         .ok_or_else(|| crate::format_err!("size overflow copying a list"))?;
1105     let ptr = cx.realloc(0, 0, elt_align, size)?;
1106     let mut element_ptr = ptr;
1107     for item in items {
1108         item.store(cx, element_type, element_ptr)?;
1109         element_ptr += elt_size;
1110     }
1111     Ok((ptr, items.len()))
1112 }
1113 
1114 /// Lower a map as list<tuple<k, v>> with the specified key and value types.
lower_map<T>( cx: &mut LowerContext<'_, T>, map_ty: &TypeMap, pairs: &[(Val, Val)], ) -> Result<(usize, usize)>1115 fn lower_map<T>(
1116     cx: &mut LowerContext<'_, T>,
1117     map_ty: &TypeMap,
1118     pairs: &[(Val, Val)],
1119 ) -> Result<(usize, usize)> {
1120     let key_type = map_ty.key;
1121     let value_type = map_ty.value;
1122     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
1123     let tuple_align = map_ty.entry_abi.align32;
1124     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
1125 
1126     let size = pairs
1127         .len()
1128         .checked_mul(tuple_size)
1129         .ok_or_else(|| crate::format_err!("size overflow copying a map"))?;
1130     let ptr = cx.realloc(0, 0, tuple_align, size)?;
1131 
1132     let mut tuple_ptr = ptr;
1133     for (key, value) in pairs {
1134         // Store key at tuple_ptr
1135         key.store(cx, key_type, tuple_ptr)?;
1136         // Store value at tuple_ptr + value_offset (properly aligned)
1137         value.store(cx, value_type, tuple_ptr + value_offset)?;
1138         tuple_ptr += tuple_size;
1139     }
1140 
1141     Ok((ptr, pairs.len()))
1142 }
1143 
push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32)1144 fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1145     while bits > 0 && usize::try_from(offset).unwrap() < ty.names.len() {
1146         if bits & 1 != 0 {
1147             flags.push(ty.names[offset as usize].clone());
1148         }
1149         bits >>= 1;
1150         offset += 1;
1151     }
1152 }
1153 
flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>>1154 fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
1155     let mut storage = match FlagsSize::from_count(ty.names.len()) {
1156         FlagsSize::Size0 => Vec::new(),
1157         FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
1158         FlagsSize::Size4Plus(n) => vec![0; n.into()],
1159     };
1160 
1161     for flag in flags {
1162         let bit = ty
1163             .names
1164             .get_index_of(flag)
1165             .ok_or_else(|| crate::format_err!("unknown flag: `{flag}`"))?;
1166         storage[bit / 32] |= 1 << (bit % 32);
1167     }
1168     Ok(storage)
1169 }
1170 
get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32>1171 fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
1172     ty.names
1173         .get_index_of(n)
1174         .ok_or_else(|| crate::format_err!("enum variant name `{n}` is not valid"))
1175         .map(|i| i.try_into().unwrap())
1176 }
1177 
get_variant_discriminant<'a>( ty: &'a TypeVariant, name: &str, ) -> Result<(u32, &'a Option<InterfaceType>)>1178 fn get_variant_discriminant<'a>(
1179     ty: &'a TypeVariant,
1180     name: &str,
1181 ) -> Result<(u32, &'a Option<InterfaceType>)> {
1182     let (i, _, ty) = ty
1183         .cases
1184         .get_full(name)
1185         .ok_or_else(|| crate::format_err!("unknown variant case: `{name}`"))?;
1186     Ok((i.try_into().unwrap(), ty))
1187 }
1188 
next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw1189 fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1190     src.next().unwrap()
1191 }
1192 
next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw>1193 fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1194     dst.next().unwrap()
1195 }
1196 
1197 #[cold]
unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T>1198 fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
1199     bail!(
1200         "type mismatch: expected {}, found {}",
1201         desc(&ty),
1202         val.desc()
1203     )
1204 }
1205 
1206 /// Represents a component model `error-context`.
1207 ///
1208 /// Note that this type is not usable at this time as its implementation has not
1209 /// been filled out. There are no operations on this and there's additionally no
1210 /// ability to "drop" or deallocate this index.
1211 //
1212 // FIXME(#11161) this needs to be filled out implementation-wise
1213 #[derive(Debug, Clone, PartialEq, Eq)]
1214 pub struct ErrorContextAny(pub(crate) u32);
1215 
1216 impl From<bool> for Val {
from(b: bool) -> Self1217     fn from(b: bool) -> Self {
1218         Val::Bool(b)
1219     }
1220 }
1221 
1222 impl From<u8> for Val {
from(u: u8) -> Self1223     fn from(u: u8) -> Self {
1224         Val::U8(u)
1225     }
1226 }
1227 
1228 impl From<i8> for Val {
from(i: i8) -> Self1229     fn from(i: i8) -> Self {
1230         Val::S8(i)
1231     }
1232 }
1233 
1234 impl From<u16> for Val {
from(u: u16) -> Self1235     fn from(u: u16) -> Self {
1236         Val::U16(u)
1237     }
1238 }
1239 
1240 impl From<i16> for Val {
from(i: i16) -> Self1241     fn from(i: i16) -> Self {
1242         Val::S16(i)
1243     }
1244 }
1245 
1246 impl From<u32> for Val {
from(u: u32) -> Self1247     fn from(u: u32) -> Self {
1248         Val::U32(u)
1249     }
1250 }
1251 
1252 impl From<i32> for Val {
from(i: i32) -> Self1253     fn from(i: i32) -> Self {
1254         Val::S32(i)
1255     }
1256 }
1257 
1258 impl From<u64> for Val {
from(u: u64) -> Self1259     fn from(u: u64) -> Self {
1260         Val::U64(u)
1261     }
1262 }
1263 
1264 impl From<i64> for Val {
from(i: i64) -> Self1265     fn from(i: i64) -> Self {
1266         Val::S64(i)
1267     }
1268 }
1269 
1270 impl From<char> for Val {
from(i: char) -> Self1271     fn from(i: char) -> Self {
1272         Val::Char(i)
1273     }
1274 }
1275 
1276 impl From<String> for Val {
from(i: String) -> Self1277     fn from(i: String) -> Self {
1278         Val::String(i)
1279     }
1280 }
1281 
1282 impl From<ResourceAny> for Val {
from(i: ResourceAny) -> Self1283     fn from(i: ResourceAny) -> Self {
1284         Val::Resource(i)
1285     }
1286 }
1287 
1288 impl From<FutureAny> for Val {
from(i: FutureAny) -> Self1289     fn from(i: FutureAny) -> Self {
1290         Val::Future(i)
1291     }
1292 }
1293 
1294 impl From<StreamAny> for Val {
from(i: StreamAny) -> Self1295     fn from(i: StreamAny) -> Self {
1296         Val::Stream(i)
1297     }
1298 }
1299