Skip to main content

wasmtime/runtime/component/
values.rs

1use crate::ValRaw;
2use crate::component::ResourceAny;
3use crate::component::concurrent::{self, ErrorContext, FutureAny, StreamAny};
4use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc};
5use crate::prelude::*;
6use core::mem::MaybeUninit;
7use core::slice::{Iter, IterMut};
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9use 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")]
67pub 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
98impl Val {
99    /// Deserialize a value of this type from core Wasm stack values.
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.
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.
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.
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
678    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")]
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")]
718    pub fn to_wave(&self) -> Result<String> {
719        Ok(wasm_wave::to_string(self)?)
720    }
721}
722
723impl PartialEq for Val {
724    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
796impl Eq for Val {}
797
798struct GenericVariant<'a> {
799    discriminant: u32,
800    payload: Option<(&'a Val, InterfaceType)>,
801    abi: &'a CanonicalAbiInfo,
802    info: &'a VariantInfo,
803}
804
805impl GenericVariant<'_> {
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
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
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
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
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
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
939fn 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
949fn 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
955fn 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
985fn 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
1027fn 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
1068fn 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.
1093fn 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.
1115fn 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
1144fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1145    while bits > 0 {
1146        if bits & 1 != 0 {
1147            flags.push(ty.names[offset as usize].clone());
1148        }
1149        bits >>= 1;
1150        offset += 1;
1151    }
1152}
1153
1154fn 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
1171fn 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
1178fn 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
1189fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1190    src.next().unwrap()
1191}
1192
1193fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1194    dst.next().unwrap()
1195}
1196
1197#[cold]
1198fn 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)]
1214pub struct ErrorContextAny(pub(crate) u32);
1215
1216impl From<bool> for Val {
1217    fn from(b: bool) -> Self {
1218        Val::Bool(b)
1219    }
1220}
1221
1222impl From<u8> for Val {
1223    fn from(u: u8) -> Self {
1224        Val::U8(u)
1225    }
1226}
1227
1228impl From<i8> for Val {
1229    fn from(i: i8) -> Self {
1230        Val::S8(i)
1231    }
1232}
1233
1234impl From<u16> for Val {
1235    fn from(u: u16) -> Self {
1236        Val::U16(u)
1237    }
1238}
1239
1240impl From<i16> for Val {
1241    fn from(i: i16) -> Self {
1242        Val::S16(i)
1243    }
1244}
1245
1246impl From<u32> for Val {
1247    fn from(u: u32) -> Self {
1248        Val::U32(u)
1249    }
1250}
1251
1252impl From<i32> for Val {
1253    fn from(i: i32) -> Self {
1254        Val::S32(i)
1255    }
1256}
1257
1258impl From<u64> for Val {
1259    fn from(u: u64) -> Self {
1260        Val::U64(u)
1261    }
1262}
1263
1264impl From<i64> for Val {
1265    fn from(i: i64) -> Self {
1266        Val::S64(i)
1267    }
1268}
1269
1270impl From<char> for Val {
1271    fn from(i: char) -> Self {
1272        Val::Char(i)
1273    }
1274}
1275
1276impl From<String> for Val {
1277    fn from(i: String) -> Self {
1278        Val::String(i)
1279    }
1280}
1281
1282impl From<ResourceAny> for Val {
1283    fn from(i: ResourceAny) -> Self {
1284        Val::Resource(i)
1285    }
1286}
1287
1288impl From<FutureAny> for Val {
1289    fn from(i: FutureAny) -> Self {
1290        Val::Future(i)
1291    }
1292}
1293
1294impl From<StreamAny> for Val {
1295    fn from(i: StreamAny) -> Self {
1296        Val::Stream(i)
1297    }
1298}