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