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