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