1d4242001SAdam Bratschi-Kaye use crate::ValRaw;
290ac295eSAlex Crichton use crate::component::ResourceAny;
3f586be11SAlex Crichton use crate::component::concurrent::{self, ErrorContext, FutureAny, StreamAny};
490ac295eSAlex Crichton use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc};
590ac295eSAlex Crichton use crate::prelude::*;
681a89169SAlex Crichton use core::mem::MaybeUninit;
781a89169SAlex Crichton use core::slice::{Iter, IterMut};
8d4242001SAdam Bratschi-Kaye use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9d4242001SAdam Bratschi-Kaye use wasmtime_environ::component::{
101b59b579SYordis Prieto     CanonicalAbiInfo, InterfaceType, TypeEnum, TypeFlags, TypeListIndex, TypeMap, TypeMapIndex,
111b59b579SYordis Prieto     TypeOption, TypeResult, TypeVariant, VariantInfo,
12d4242001SAdam Bratschi-Kaye };
13d4242001SAdam Bratschi-Kaye 
14d4242001SAdam Bratschi-Kaye /// Represents possible runtime values which a component function can either
15d4242001SAdam Bratschi-Kaye /// consume or produce
16d4242001SAdam Bratschi-Kaye ///
17d4242001SAdam Bratschi-Kaye /// This is a dynamic representation of possible values in the component model.
18d4242001SAdam Bratschi-Kaye /// Note that this is not an efficient representation but is instead intended to
19d4242001SAdam Bratschi-Kaye /// be a flexible and somewhat convenient representation. The most efficient
20d4242001SAdam Bratschi-Kaye /// representation of component model types is to use the `bindgen!` macro to
21d4242001SAdam Bratschi-Kaye /// generate native Rust types with specialized liftings and lowerings.
22d4242001SAdam Bratschi-Kaye ///
23d4242001SAdam Bratschi-Kaye /// This type is used in conjunction with [`Func::call`] for example if the
24d4242001SAdam Bratschi-Kaye /// signature of a component is not statically known ahead of time.
25d4242001SAdam Bratschi-Kaye ///
269de6828eSAlex Crichton /// # Equality and `Val`
27d4242001SAdam Bratschi-Kaye ///
28d4242001SAdam Bratschi-Kaye /// This type implements both the Rust `PartialEq` and `Eq` traits. This type
29d4242001SAdam Bratschi-Kaye /// additionally contains values which are not necessarily easily equated,
30d4242001SAdam Bratschi-Kaye /// however, such as floats (`Float32` and `Float64`) and resources. Equality
31d4242001SAdam Bratschi-Kaye /// does require that two values have the same type, and then these cases are
32d4242001SAdam Bratschi-Kaye /// handled as:
33d4242001SAdam Bratschi-Kaye ///
34d4242001SAdam Bratschi-Kaye /// * Floats are tested if they are "semantically the same" meaning all NaN
35d4242001SAdam Bratschi-Kaye ///   values are equal to all other NaN values. Additionally zero values must be
36d4242001SAdam Bratschi-Kaye ///   exactly the same, so positive zero is not equal to negative zero. The
37d4242001SAdam Bratschi-Kaye ///   primary use case at this time is fuzzing-related equality which this is
38d4242001SAdam Bratschi-Kaye ///   sufficient for.
39d4242001SAdam Bratschi-Kaye ///
40d4242001SAdam Bratschi-Kaye /// * Resources are tested if their types and indices into the host table are
41d4242001SAdam Bratschi-Kaye ///   equal. This does not compare the underlying representation so borrows of
42d4242001SAdam Bratschi-Kaye ///   the same guest resource are not considered equal. This additionally
43d4242001SAdam Bratschi-Kaye ///   doesn't go further and test for equality in the guest itself (for example
44d4242001SAdam Bratschi-Kaye ///   two different heap allocations of `Box<u32>` can be equal in normal Rust
45d4242001SAdam Bratschi-Kaye ///   if they contain the same value, but will never be considered equal when
46d4242001SAdam Bratschi-Kaye ///   compared as `Val::Resource`s).
47d4242001SAdam Bratschi-Kaye ///
48d4242001SAdam Bratschi-Kaye /// In general if a strict guarantee about equality is required here it's
49d4242001SAdam Bratschi-Kaye /// recommended to "build your own" as this equality intended for fuzzing
50d4242001SAdam Bratschi-Kaye /// Wasmtime may not be suitable for you.
51d4242001SAdam Bratschi-Kaye ///
529de6828eSAlex Crichton /// # Component model types and `Val`
539de6828eSAlex Crichton ///
549de6828eSAlex Crichton /// The `Val` type here does not contain enough information to say what the
559de6828eSAlex Crichton /// component model type of a `Val` is. This is instead more of an AST of sorts.
569de6828eSAlex Crichton /// For example the `Val::Enum` only carries information about a single
579de6828eSAlex Crichton /// discriminant, not the entire enumeration or what it's a discriminant of.
589de6828eSAlex Crichton ///
599de6828eSAlex Crichton /// This means that when a `Val` is passed to Wasmtime, for example as a
609de6828eSAlex Crichton /// function parameter when calling a function or as a return value from an
619de6828eSAlex Crichton /// host-defined imported function, then it must pass a type-check. Instances of
629de6828eSAlex Crichton /// `Val` are type-checked against what's required by the component itself.
639de6828eSAlex Crichton ///
64d4242001SAdam Bratschi-Kaye /// [`Func::call`]: crate::component::Func::call
65d4242001SAdam Bratschi-Kaye #[derive(Debug, Clone)]
66838ed2d0SAlex Crichton #[expect(missing_docs, reason = "self-describing variants")]
67d4242001SAdam Bratschi-Kaye pub enum Val {
68d4242001SAdam Bratschi-Kaye     Bool(bool),
69d4242001SAdam Bratschi-Kaye     S8(i8),
70d4242001SAdam Bratschi-Kaye     U8(u8),
71d4242001SAdam Bratschi-Kaye     S16(i16),
72d4242001SAdam Bratschi-Kaye     U16(u16),
73d4242001SAdam Bratschi-Kaye     S32(i32),
74d4242001SAdam Bratschi-Kaye     U32(u32),
75d4242001SAdam Bratschi-Kaye     S64(i64),
76d4242001SAdam Bratschi-Kaye     U64(u64),
77d4242001SAdam Bratschi-Kaye     Float32(f32),
78d4242001SAdam Bratschi-Kaye     Float64(f64),
79d4242001SAdam Bratschi-Kaye     Char(char),
809de6828eSAlex Crichton     String(String),
819de6828eSAlex Crichton     List(Vec<Val>),
821b59b579SYordis Prieto     /// A map type represented as a list of key-value pairs.
831b59b579SYordis Prieto     /// Duplicate keys are allowed and follow "last value wins" semantics.
841b59b579SYordis Prieto     Map(Vec<(Val, Val)>),
859de6828eSAlex Crichton     Record(Vec<(String, Val)>),
869de6828eSAlex Crichton     Tuple(Vec<Val>),
879de6828eSAlex Crichton     Variant(String, Option<Box<Val>>),
889de6828eSAlex Crichton     Enum(String),
899de6828eSAlex Crichton     Option(Option<Box<Val>>),
909de6828eSAlex Crichton     Result(Result<Option<Box<Val>>, Option<Box<Val>>>),
919de6828eSAlex Crichton     Flags(Vec<String>),
92d4242001SAdam Bratschi-Kaye     Resource(ResourceAny),
93b221fca7SJoel Dice     Future(FutureAny),
94b221fca7SJoel Dice     Stream(StreamAny),
95b221fca7SJoel Dice     ErrorContext(ErrorContextAny),
96d4242001SAdam Bratschi-Kaye }
97d4242001SAdam Bratschi-Kaye 
98d4242001SAdam Bratschi-Kaye impl Val {
99d4242001SAdam Bratschi-Kaye     /// Deserialize a value of this type from core Wasm stack values.
lift( cx: &mut LiftContext<'_>, ty: InterfaceType, src: &mut Iter<'_, ValRaw>, ) -> Result<Val>100d4242001SAdam Bratschi-Kaye     pub(crate) fn lift(
101d4242001SAdam Bratschi-Kaye         cx: &mut LiftContext<'_>,
102d4242001SAdam Bratschi-Kaye         ty: InterfaceType,
10381a89169SAlex Crichton         src: &mut Iter<'_, ValRaw>,
104d4242001SAdam Bratschi-Kaye     ) -> Result<Val> {
105d4242001SAdam Bratschi-Kaye         Ok(match ty {
1067dba8efdSNick Fitzgerald             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_flat(cx, ty, next(src))?),
1077dba8efdSNick Fitzgerald             InterfaceType::S8 => Val::S8(i8::linear_lift_from_flat(cx, ty, next(src))?),
1087dba8efdSNick Fitzgerald             InterfaceType::U8 => Val::U8(u8::linear_lift_from_flat(cx, ty, next(src))?),
1097dba8efdSNick Fitzgerald             InterfaceType::S16 => Val::S16(i16::linear_lift_from_flat(cx, ty, next(src))?),
1107dba8efdSNick Fitzgerald             InterfaceType::U16 => Val::U16(u16::linear_lift_from_flat(cx, ty, next(src))?),
1117dba8efdSNick Fitzgerald             InterfaceType::S32 => Val::S32(i32::linear_lift_from_flat(cx, ty, next(src))?),
1127dba8efdSNick Fitzgerald             InterfaceType::U32 => Val::U32(u32::linear_lift_from_flat(cx, ty, next(src))?),
1137dba8efdSNick Fitzgerald             InterfaceType::S64 => Val::S64(i64::linear_lift_from_flat(cx, ty, next(src))?),
1147dba8efdSNick Fitzgerald             InterfaceType::U64 => Val::U64(u64::linear_lift_from_flat(cx, ty, next(src))?),
1157dba8efdSNick Fitzgerald             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_flat(cx, ty, next(src))?),
1167dba8efdSNick Fitzgerald             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_flat(cx, ty, next(src))?),
1177dba8efdSNick Fitzgerald             InterfaceType::Char => Val::Char(char::linear_lift_from_flat(cx, ty, next(src))?),
118d4242001SAdam Bratschi-Kaye             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
1197dba8efdSNick Fitzgerald                 Val::Resource(ResourceAny::linear_lift_from_flat(cx, ty, next(src))?)
120d4242001SAdam Bratschi-Kaye             }
1217dba8efdSNick Fitzgerald             InterfaceType::String => Val::String(<_>::linear_lift_from_flat(
1227dba8efdSNick Fitzgerald                 cx,
1237dba8efdSNick Fitzgerald                 ty,
1247dba8efdSNick Fitzgerald                 &[*next(src), *next(src)],
1257dba8efdSNick Fitzgerald             )?),
126d4242001SAdam Bratschi-Kaye             InterfaceType::List(i) => {
127a0d5346dSAlex Crichton                 let (ptr, len) = lift_flat_pointer_pair(cx, src)?;
128d4242001SAdam Bratschi-Kaye                 load_list(cx, i, ptr, len)?
129d4242001SAdam Bratschi-Kaye             }
1301b59b579SYordis Prieto             InterfaceType::Map(i) => {
131a0d5346dSAlex Crichton                 let (ptr, len) = lift_flat_pointer_pair(cx, src)?;
1321b59b579SYordis Prieto                 load_map(cx, i, ptr, len)?
1331b59b579SYordis Prieto             }
1349de6828eSAlex Crichton             InterfaceType::Record(i) => Val::Record(
1359de6828eSAlex Crichton                 cx.types[i]
136d4242001SAdam Bratschi-Kaye                     .fields
137d4242001SAdam Bratschi-Kaye                     .iter()
1389de6828eSAlex Crichton                     .map(|field| {
1399de6828eSAlex Crichton                         let val = Self::lift(cx, field.ty, src)?;
1409de6828eSAlex Crichton                         Ok((field.name.to_string(), val))
1419de6828eSAlex Crichton                     })
142d4242001SAdam Bratschi-Kaye                     .collect::<Result<_>>()?,
1439de6828eSAlex Crichton             ),
1449de6828eSAlex Crichton             InterfaceType::Tuple(i) => Val::Tuple(
1459de6828eSAlex Crichton                 cx.types[i]
146d4242001SAdam Bratschi-Kaye                     .types
147d4242001SAdam Bratschi-Kaye                     .iter()
148d4242001SAdam Bratschi-Kaye                     .map(|ty| Self::lift(cx, *ty, src))
149d4242001SAdam Bratschi-Kaye                     .collect::<Result<_>>()?,
1509de6828eSAlex Crichton             ),
151d4242001SAdam Bratschi-Kaye             InterfaceType::Variant(i) => {
1529de6828eSAlex Crichton                 let vty = &cx.types[i];
153d4242001SAdam Bratschi-Kaye                 let (discriminant, value) = lift_variant(
154d4242001SAdam Bratschi-Kaye                     cx,
155d4242001SAdam Bratschi-Kaye                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1569de6828eSAlex Crichton                     vty.cases.values().copied(),
157d4242001SAdam Bratschi-Kaye                     src,
158d4242001SAdam Bratschi-Kaye                 )?;
159d4242001SAdam Bratschi-Kaye 
1609de6828eSAlex Crichton                 let (k, _) = vty.cases.get_index(discriminant as usize).unwrap();
1619de6828eSAlex Crichton                 Val::Variant(k.clone(), value)
162d4242001SAdam Bratschi-Kaye             }
163d4242001SAdam Bratschi-Kaye             InterfaceType::Enum(i) => {
1649de6828eSAlex Crichton                 let ety = &cx.types[i];
165d4242001SAdam Bratschi-Kaye                 let (discriminant, _) = lift_variant(
166d4242001SAdam Bratschi-Kaye                     cx,
167d4242001SAdam Bratschi-Kaye                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1689de6828eSAlex Crichton                     ety.names.iter().map(|_| None),
169d4242001SAdam Bratschi-Kaye                     src,
170d4242001SAdam Bratschi-Kaye                 )?;
171d4242001SAdam Bratschi-Kaye 
1729de6828eSAlex Crichton                 Val::Enum(ety.names[discriminant as usize].clone())
173d4242001SAdam Bratschi-Kaye             }
174d4242001SAdam Bratschi-Kaye             InterfaceType::Option(i) => {
1759de6828eSAlex Crichton                 let (_discriminant, value) = lift_variant(
176d4242001SAdam Bratschi-Kaye                     cx,
177d4242001SAdam Bratschi-Kaye                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
178d4242001SAdam Bratschi-Kaye                     [None, Some(cx.types[i].ty)].into_iter(),
179d4242001SAdam Bratschi-Kaye                     src,
180d4242001SAdam Bratschi-Kaye                 )?;
181d4242001SAdam Bratschi-Kaye 
1829de6828eSAlex Crichton                 Val::Option(value)
183d4242001SAdam Bratschi-Kaye             }
184d4242001SAdam Bratschi-Kaye             InterfaceType::Result(i) => {
185d4242001SAdam Bratschi-Kaye                 let result_ty = &cx.types[i];
186d4242001SAdam Bratschi-Kaye                 let (discriminant, value) = lift_variant(
187d4242001SAdam Bratschi-Kaye                     cx,
188d4242001SAdam Bratschi-Kaye                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
189d4242001SAdam Bratschi-Kaye                     [result_ty.ok, result_ty.err].into_iter(),
190d4242001SAdam Bratschi-Kaye                     src,
191d4242001SAdam Bratschi-Kaye                 )?;
192d4242001SAdam Bratschi-Kaye 
1939de6828eSAlex Crichton                 Val::Result(if discriminant == 0 {
1949de6828eSAlex Crichton                     Ok(value)
1959de6828eSAlex Crichton                 } else {
1969de6828eSAlex Crichton                     Err(value)
197d4242001SAdam Bratschi-Kaye                 })
198d4242001SAdam Bratschi-Kaye             }
199d4242001SAdam Bratschi-Kaye             InterfaceType::Flags(i) => {
200d4242001SAdam Bratschi-Kaye                 let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap();
2019de6828eSAlex Crichton                 let ty = &cx.types[i];
2029de6828eSAlex Crichton                 let mut flags = Vec::new();
2030bce0968SAlex Crichton                 for i in 0..u32::try_from(u32_count).unwrap() {
2049de6828eSAlex Crichton                     push_flags(
2059de6828eSAlex Crichton                         ty,
2069de6828eSAlex Crichton                         &mut flags,
2070bce0968SAlex Crichton                         i * 32,
2087dba8efdSNick Fitzgerald                         u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))?,
2099de6828eSAlex Crichton                     );
2109de6828eSAlex Crichton                 }
211d4242001SAdam Bratschi-Kaye 
212703871a2SAlex Crichton                 Val::Flags(flags)
213d4242001SAdam Bratschi-Kaye             }
214b221fca7SJoel Dice             InterfaceType::Future(_) => {
215f586be11SAlex Crichton                 Val::Future(FutureAny::linear_lift_from_flat(cx, ty, next(src))?)
216b221fca7SJoel Dice             }
217b221fca7SJoel Dice             InterfaceType::Stream(_) => {
218f586be11SAlex Crichton                 Val::Stream(StreamAny::linear_lift_from_flat(cx, ty, next(src))?)
219b221fca7SJoel Dice             }
220b221fca7SJoel Dice             InterfaceType::ErrorContext(_) => {
221b221fca7SJoel Dice                 ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val()
222b221fca7SJoel Dice             }
223caf0f752SChristof Petig             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
224d4242001SAdam Bratschi-Kaye         })
225d4242001SAdam Bratschi-Kaye     }
226d4242001SAdam Bratschi-Kaye 
227d4242001SAdam Bratschi-Kaye     /// Deserialize a value of this type from the heap.
load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val>228d4242001SAdam Bratschi-Kaye     pub(crate) fn load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val> {
229d4242001SAdam Bratschi-Kaye         Ok(match ty {
2307dba8efdSNick Fitzgerald             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_memory(cx, ty, bytes)?),
2317dba8efdSNick Fitzgerald             InterfaceType::S8 => Val::S8(i8::linear_lift_from_memory(cx, ty, bytes)?),
2327dba8efdSNick Fitzgerald             InterfaceType::U8 => Val::U8(u8::linear_lift_from_memory(cx, ty, bytes)?),
2337dba8efdSNick Fitzgerald             InterfaceType::S16 => Val::S16(i16::linear_lift_from_memory(cx, ty, bytes)?),
2347dba8efdSNick Fitzgerald             InterfaceType::U16 => Val::U16(u16::linear_lift_from_memory(cx, ty, bytes)?),
2357dba8efdSNick Fitzgerald             InterfaceType::S32 => Val::S32(i32::linear_lift_from_memory(cx, ty, bytes)?),
2367dba8efdSNick Fitzgerald             InterfaceType::U32 => Val::U32(u32::linear_lift_from_memory(cx, ty, bytes)?),
2377dba8efdSNick Fitzgerald             InterfaceType::S64 => Val::S64(i64::linear_lift_from_memory(cx, ty, bytes)?),
2387dba8efdSNick Fitzgerald             InterfaceType::U64 => Val::U64(u64::linear_lift_from_memory(cx, ty, bytes)?),
2397dba8efdSNick Fitzgerald             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_memory(cx, ty, bytes)?),
2407dba8efdSNick Fitzgerald             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_memory(cx, ty, bytes)?),
2417dba8efdSNick Fitzgerald             InterfaceType::Char => Val::Char(char::linear_lift_from_memory(cx, ty, bytes)?),
2427dba8efdSNick Fitzgerald             InterfaceType::String => Val::String(<_>::linear_lift_from_memory(cx, ty, bytes)?),
243d4242001SAdam Bratschi-Kaye             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
2447dba8efdSNick Fitzgerald                 Val::Resource(ResourceAny::linear_lift_from_memory(cx, ty, bytes)?)
245d4242001SAdam Bratschi-Kaye             }
246d4242001SAdam Bratschi-Kaye             InterfaceType::List(i) => {
247a0d5346dSAlex Crichton                 let (ptr, len) = load_flat_pointer_pair(bytes);
248d4242001SAdam Bratschi-Kaye                 load_list(cx, i, ptr, len)?
249d4242001SAdam Bratschi-Kaye             }
2501b59b579SYordis Prieto             InterfaceType::Map(i) => {
251a0d5346dSAlex Crichton                 let (ptr, len) = load_flat_pointer_pair(bytes);
2521b59b579SYordis Prieto                 load_map(cx, i, ptr, len)?
2531b59b579SYordis Prieto             }
254d4242001SAdam Bratschi-Kaye 
2559de6828eSAlex Crichton             InterfaceType::Record(i) => {
2569de6828eSAlex Crichton                 let mut offset = 0;
2579de6828eSAlex Crichton                 let fields = cx.types[i].fields.iter();
2589de6828eSAlex Crichton                 Val::Record(
2599de6828eSAlex Crichton                     fields
2609de6828eSAlex Crichton                         .map(|field| -> Result<(String, Val)> {
2619de6828eSAlex Crichton                             let abi = cx.types.canonical_abi(&field.ty);
2629de6828eSAlex Crichton                             let offset = abi.next_field32(&mut offset);
2639de6828eSAlex Crichton                             let offset = usize::try_from(offset).unwrap();
2649de6828eSAlex Crichton                             let size = usize::try_from(abi.size32).unwrap();
2659de6828eSAlex Crichton                             Ok((
2669de6828eSAlex Crichton                                 field.name.to_string(),
2679de6828eSAlex Crichton                                 Val::load(cx, field.ty, &bytes[offset..][..size])?,
2689de6828eSAlex Crichton                             ))
2699de6828eSAlex Crichton                         })
2709de6828eSAlex Crichton                         .collect::<Result<_>>()?,
2719de6828eSAlex Crichton                 )
2729de6828eSAlex Crichton             }
2739de6828eSAlex Crichton             InterfaceType::Tuple(i) => {
2749de6828eSAlex Crichton                 let types = cx.types[i].types.iter().copied();
2759de6828eSAlex Crichton                 let mut offset = 0;
2769de6828eSAlex Crichton                 Val::Tuple(
2779de6828eSAlex Crichton                     types
2789de6828eSAlex Crichton                         .map(|ty| {
2799de6828eSAlex Crichton                             let abi = cx.types.canonical_abi(&ty);
2809de6828eSAlex Crichton                             let offset = abi.next_field32(&mut offset);
2819de6828eSAlex Crichton                             let offset = usize::try_from(offset).unwrap();
2829de6828eSAlex Crichton                             let size = usize::try_from(abi.size32).unwrap();
2839de6828eSAlex Crichton                             Val::load(cx, ty, &bytes[offset..][..size])
2849de6828eSAlex Crichton                         })
2859de6828eSAlex Crichton                         .collect::<Result<_>>()?,
2869de6828eSAlex Crichton                 )
2879de6828eSAlex Crichton             }
288d4242001SAdam Bratschi-Kaye             InterfaceType::Variant(i) => {
289d4242001SAdam Bratschi-Kaye                 let ty = &cx.types[i];
290d4242001SAdam Bratschi-Kaye                 let (discriminant, value) =
2919de6828eSAlex Crichton                     load_variant(cx, &ty.info, ty.cases.values().copied(), bytes)?;
292d4242001SAdam Bratschi-Kaye 
2939de6828eSAlex Crichton                 let (k, _) = ty.cases.get_index(discriminant as usize).unwrap();
2949de6828eSAlex Crichton                 Val::Variant(k.clone(), value)
295d4242001SAdam Bratschi-Kaye             }
296d4242001SAdam Bratschi-Kaye             InterfaceType::Enum(i) => {
297d4242001SAdam Bratschi-Kaye                 let ty = &cx.types[i];
298d4242001SAdam Bratschi-Kaye                 let (discriminant, _) =
299d4242001SAdam Bratschi-Kaye                     load_variant(cx, &ty.info, ty.names.iter().map(|_| None), bytes)?;
300d4242001SAdam Bratschi-Kaye 
3019de6828eSAlex Crichton                 Val::Enum(ty.names[discriminant as usize].clone())
302d4242001SAdam Bratschi-Kaye             }
303d4242001SAdam Bratschi-Kaye             InterfaceType::Option(i) => {
304d4242001SAdam Bratschi-Kaye                 let ty = &cx.types[i];
3059de6828eSAlex Crichton                 let (_discriminant, value) =
306d4242001SAdam Bratschi-Kaye                     load_variant(cx, &ty.info, [None, Some(ty.ty)].into_iter(), bytes)?;
307d4242001SAdam Bratschi-Kaye 
3089de6828eSAlex Crichton                 Val::Option(value)
309d4242001SAdam Bratschi-Kaye             }
310d4242001SAdam Bratschi-Kaye             InterfaceType::Result(i) => {
311d4242001SAdam Bratschi-Kaye                 let ty = &cx.types[i];
312d4242001SAdam Bratschi-Kaye                 let (discriminant, value) =
313d4242001SAdam Bratschi-Kaye                     load_variant(cx, &ty.info, [ty.ok, ty.err].into_iter(), bytes)?;
314d4242001SAdam Bratschi-Kaye 
3159de6828eSAlex Crichton                 Val::Result(if discriminant == 0 {
3169de6828eSAlex Crichton                     Ok(value)
3179de6828eSAlex Crichton                 } else {
3189de6828eSAlex Crichton                     Err(value)
319d4242001SAdam Bratschi-Kaye                 })
320d4242001SAdam Bratschi-Kaye             }
3219de6828eSAlex Crichton             InterfaceType::Flags(i) => {
3229de6828eSAlex Crichton                 let ty = &cx.types[i];
3239de6828eSAlex Crichton                 let mut flags = Vec::new();
3249de6828eSAlex Crichton                 match FlagsSize::from_count(ty.names.len()) {
3259de6828eSAlex Crichton                     FlagsSize::Size0 => {}
326d4242001SAdam Bratschi-Kaye                     FlagsSize::Size1 => {
3277dba8efdSNick Fitzgerald                         let bits = u8::linear_lift_from_memory(cx, InterfaceType::U8, bytes)?;
3289de6828eSAlex Crichton                         push_flags(ty, &mut flags, 0, u32::from(bits));
329d4242001SAdam Bratschi-Kaye                     }
330d4242001SAdam Bratschi-Kaye                     FlagsSize::Size2 => {
3317dba8efdSNick Fitzgerald                         let bits = u16::linear_lift_from_memory(cx, InterfaceType::U16, bytes)?;
3329de6828eSAlex Crichton                         push_flags(ty, &mut flags, 0, u32::from(bits));
333d4242001SAdam Bratschi-Kaye                     }
3349de6828eSAlex Crichton                     FlagsSize::Size4Plus(n) => {
3359de6828eSAlex Crichton                         for i in 0..n {
3367dba8efdSNick Fitzgerald                             let bits = u32::linear_lift_from_memory(
337d4242001SAdam Bratschi-Kaye                                 cx,
338d4242001SAdam Bratschi-Kaye                                 InterfaceType::U32,
3399de6828eSAlex Crichton                                 &bytes[usize::from(i) * 4..][..4],
3409de6828eSAlex Crichton                             )?;
3419de6828eSAlex Crichton                             push_flags(ty, &mut flags, u32::from(i) * 32, bits);
3429de6828eSAlex Crichton                         }
3439de6828eSAlex Crichton                     }
3449de6828eSAlex Crichton                 }
345703871a2SAlex Crichton                 Val::Flags(flags)
3469de6828eSAlex Crichton             }
347f586be11SAlex Crichton             InterfaceType::Future(_) => FutureAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
348f586be11SAlex Crichton             InterfaceType::Stream(_) => StreamAny::linear_lift_from_memory(cx, ty, bytes)?.into(),
349b221fca7SJoel Dice             InterfaceType::ErrorContext(_) => {
350b221fca7SJoel Dice                 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val()
351b221fca7SJoel Dice             }
352caf0f752SChristof Petig             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
353d4242001SAdam Bratschi-Kaye         })
354d4242001SAdam Bratschi-Kaye     }
355d4242001SAdam Bratschi-Kaye 
356d4242001SAdam Bratschi-Kaye     /// Serialize this value as core Wasm stack values.
lower<T>( &self, cx: &mut LowerContext<'_, T>, ty: InterfaceType, dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, ) -> Result<()>357d4242001SAdam Bratschi-Kaye     pub(crate) fn lower<T>(
358d4242001SAdam Bratschi-Kaye         &self,
359d4242001SAdam Bratschi-Kaye         cx: &mut LowerContext<'_, T>,
360d4242001SAdam Bratschi-Kaye         ty: InterfaceType,
36181a89169SAlex Crichton         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
362d4242001SAdam Bratschi-Kaye     ) -> Result<()> {
3639de6828eSAlex Crichton         match (ty, self) {
3647dba8efdSNick Fitzgerald             (InterfaceType::Bool, Val::Bool(value)) => {
3657dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3667dba8efdSNick Fitzgerald             }
3679de6828eSAlex Crichton             (InterfaceType::Bool, _) => unexpected(ty, self),
3687dba8efdSNick Fitzgerald             (InterfaceType::S8, Val::S8(value)) => {
3697dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3707dba8efdSNick Fitzgerald             }
3719de6828eSAlex Crichton             (InterfaceType::S8, _) => unexpected(ty, self),
3727dba8efdSNick Fitzgerald             (InterfaceType::U8, Val::U8(value)) => {
3737dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3747dba8efdSNick Fitzgerald             }
3759de6828eSAlex Crichton             (InterfaceType::U8, _) => unexpected(ty, self),
3767dba8efdSNick Fitzgerald             (InterfaceType::S16, Val::S16(value)) => {
3777dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3787dba8efdSNick Fitzgerald             }
3799de6828eSAlex Crichton             (InterfaceType::S16, _) => unexpected(ty, self),
3807dba8efdSNick Fitzgerald             (InterfaceType::U16, Val::U16(value)) => {
3817dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3827dba8efdSNick Fitzgerald             }
3839de6828eSAlex Crichton             (InterfaceType::U16, _) => unexpected(ty, self),
3847dba8efdSNick Fitzgerald             (InterfaceType::S32, Val::S32(value)) => {
3857dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3867dba8efdSNick Fitzgerald             }
3879de6828eSAlex Crichton             (InterfaceType::S32, _) => unexpected(ty, self),
3887dba8efdSNick Fitzgerald             (InterfaceType::U32, Val::U32(value)) => {
3897dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3907dba8efdSNick Fitzgerald             }
3919de6828eSAlex Crichton             (InterfaceType::U32, _) => unexpected(ty, self),
3927dba8efdSNick Fitzgerald             (InterfaceType::S64, Val::S64(value)) => {
3937dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3947dba8efdSNick Fitzgerald             }
3959de6828eSAlex Crichton             (InterfaceType::S64, _) => unexpected(ty, self),
3967dba8efdSNick Fitzgerald             (InterfaceType::U64, Val::U64(value)) => {
3977dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
3987dba8efdSNick Fitzgerald             }
3999de6828eSAlex Crichton             (InterfaceType::U64, _) => unexpected(ty, self),
4007dba8efdSNick Fitzgerald             (InterfaceType::Float32, Val::Float32(value)) => {
4017dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
4027dba8efdSNick Fitzgerald             }
4039de6828eSAlex Crichton             (InterfaceType::Float32, _) => unexpected(ty, self),
4047dba8efdSNick Fitzgerald             (InterfaceType::Float64, Val::Float64(value)) => {
4057dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
4067dba8efdSNick Fitzgerald             }
4079de6828eSAlex Crichton             (InterfaceType::Float64, _) => unexpected(ty, self),
4087dba8efdSNick Fitzgerald             (InterfaceType::Char, Val::Char(value)) => {
4097dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
4107dba8efdSNick Fitzgerald             }
4119de6828eSAlex Crichton             (InterfaceType::Char, _) => unexpected(ty, self),
4129de6828eSAlex Crichton             // NB: `lower` on `ResourceAny` does its own type-checking, so skip
4139de6828eSAlex Crichton             // looking at it here.
4149de6828eSAlex Crichton             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
4157dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
4169de6828eSAlex Crichton             }
4179de6828eSAlex Crichton             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
4189de6828eSAlex Crichton             (InterfaceType::String, Val::String(value)) => {
419d4242001SAdam Bratschi-Kaye                 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit();
4207dba8efdSNick Fitzgerald                 value.linear_lower_to_flat(cx, ty, my_dst)?;
421d4242001SAdam Bratschi-Kaye                 let my_dst = unsafe { my_dst.assume_init() };
422d4242001SAdam Bratschi-Kaye                 next_mut(dst).write(my_dst[0]);
423d4242001SAdam Bratschi-Kaye                 next_mut(dst).write(my_dst[1]);
4249de6828eSAlex Crichton                 Ok(())
425d4242001SAdam Bratschi-Kaye             }
4269de6828eSAlex Crichton             (InterfaceType::String, _) => unexpected(ty, self),
4279de6828eSAlex Crichton             (InterfaceType::List(ty), Val::List(values)) => {
4289de6828eSAlex Crichton                 let ty = &cx.types[ty];
429d4242001SAdam Bratschi-Kaye                 let (ptr, len) = lower_list(cx, ty.element, values)?;
430d4242001SAdam Bratschi-Kaye                 next_mut(dst).write(ValRaw::i64(ptr as i64));
431d4242001SAdam Bratschi-Kaye                 next_mut(dst).write(ValRaw::i64(len as i64));
4329de6828eSAlex Crichton                 Ok(())
433d4242001SAdam Bratschi-Kaye             }
4349de6828eSAlex Crichton             (InterfaceType::List(_), _) => unexpected(ty, self),
4351b59b579SYordis Prieto             (InterfaceType::Map(ty), Val::Map(pairs)) => {
4361b59b579SYordis Prieto                 let map_ty = &cx.types[ty];
4371b59b579SYordis Prieto                 let (ptr, len) = lower_map(cx, map_ty, pairs)?;
4381b59b579SYordis Prieto                 next_mut(dst).write(ValRaw::i64(ptr as i64));
4391b59b579SYordis Prieto                 next_mut(dst).write(ValRaw::i64(len as i64));
4401b59b579SYordis Prieto                 Ok(())
4411b59b579SYordis Prieto             }
4421b59b579SYordis Prieto             (InterfaceType::Map(_), _) => unexpected(ty, self),
4439de6828eSAlex Crichton             (InterfaceType::Record(ty), Val::Record(values)) => {
4449de6828eSAlex Crichton                 let ty = &cx.types[ty];
4459de6828eSAlex Crichton                 if ty.fields.len() != values.len() {
4469de6828eSAlex Crichton                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
4479de6828eSAlex Crichton                 }
4489de6828eSAlex Crichton                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
4499de6828eSAlex Crichton                     if *name != field.name {
4509de6828eSAlex Crichton                         bail!("expected field `{}`, got `{name}`", field.name);
4519de6828eSAlex Crichton                     }
452d4242001SAdam Bratschi-Kaye                     value.lower(cx, field.ty, dst)?;
453d4242001SAdam Bratschi-Kaye                 }
4549de6828eSAlex Crichton                 Ok(())
455d4242001SAdam Bratschi-Kaye             }
4569de6828eSAlex Crichton             (InterfaceType::Record(_), _) => unexpected(ty, self),
4579de6828eSAlex Crichton             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
4589de6828eSAlex Crichton                 let ty = &cx.types[ty];
4599de6828eSAlex Crichton                 if ty.types.len() != values.len() {
4609de6828eSAlex Crichton                     bail!("expected {} types, got {}", ty.types.len(), values.len());
4619de6828eSAlex Crichton                 }
462d4242001SAdam Bratschi-Kaye                 for (value, ty) in values.iter().zip(ty.types.iter()) {
463d4242001SAdam Bratschi-Kaye                     value.lower(cx, *ty, dst)?;
464d4242001SAdam Bratschi-Kaye                 }
465d4242001SAdam Bratschi-Kaye                 Ok(())
466d4242001SAdam Bratschi-Kaye             }
4679de6828eSAlex Crichton             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
4689de6828eSAlex Crichton             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
4699de6828eSAlex Crichton                 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst)
4709de6828eSAlex Crichton             }
4719de6828eSAlex Crichton             (InterfaceType::Variant(_), _) => unexpected(ty, self),
4729de6828eSAlex Crichton             (InterfaceType::Option(ty), Val::Option(v)) => {
4739de6828eSAlex Crichton                 GenericVariant::option(&cx.types[ty], v).lower(cx, dst)
4749de6828eSAlex Crichton             }
4759de6828eSAlex Crichton             (InterfaceType::Option(_), _) => unexpected(ty, self),
4769de6828eSAlex Crichton             (InterfaceType::Result(ty), Val::Result(v)) => {
4779de6828eSAlex Crichton                 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst)
4789de6828eSAlex Crichton             }
4799de6828eSAlex Crichton             (InterfaceType::Result(_), _) => unexpected(ty, self),
4809de6828eSAlex Crichton             (InterfaceType::Enum(ty), Val::Enum(discriminant)) => {
4819de6828eSAlex Crichton                 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?;
4829de6828eSAlex Crichton                 next_mut(dst).write(ValRaw::u32(discriminant));
4839de6828eSAlex Crichton                 Ok(())
4849de6828eSAlex Crichton             }
4859de6828eSAlex Crichton             (InterfaceType::Enum(_), _) => unexpected(ty, self),
4869de6828eSAlex Crichton             (InterfaceType::Flags(ty), Val::Flags(value)) => {
4879de6828eSAlex Crichton                 let ty = &cx.types[ty];
4889de6828eSAlex Crichton                 let storage = flags_to_storage(ty, value)?;
4899de6828eSAlex Crichton                 for value in storage {
4909de6828eSAlex Crichton                     next_mut(dst).write(ValRaw::u32(value));
4919de6828eSAlex Crichton                 }
4929de6828eSAlex Crichton                 Ok(())
4939de6828eSAlex Crichton             }
4949de6828eSAlex Crichton             (InterfaceType::Flags(_), _) => unexpected(ty, self),
495f586be11SAlex Crichton             (InterfaceType::Future(_), Val::Future(f)) => {
496f586be11SAlex Crichton                 f.linear_lower_to_flat(cx, ty, next_mut(dst))
497b221fca7SJoel Dice             }
498b221fca7SJoel Dice             (InterfaceType::Future(_), _) => unexpected(ty, self),
499f586be11SAlex Crichton             (InterfaceType::Stream(_), Val::Stream(s)) => {
500f586be11SAlex Crichton                 s.linear_lower_to_flat(cx, ty, next_mut(dst))
501b221fca7SJoel Dice             }
502b221fca7SJoel Dice             (InterfaceType::Stream(_), _) => unexpected(ty, self),
503b221fca7SJoel Dice             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
504b221fca7SJoel Dice                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat(
505b221fca7SJoel Dice                     cx,
506b221fca7SJoel Dice                     InterfaceType::U32,
507b221fca7SJoel Dice                     next_mut(dst),
508b221fca7SJoel Dice                 )
509b221fca7SJoel Dice             }
510b221fca7SJoel Dice             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
511caf0f752SChristof Petig             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
5129de6828eSAlex Crichton         }
5139de6828eSAlex Crichton     }
514d4242001SAdam Bratschi-Kaye 
515d4242001SAdam Bratschi-Kaye     /// Serialize this value to the heap at the specified memory location.
store<T>( &self, cx: &mut LowerContext<'_, T>, ty: InterfaceType, offset: usize, ) -> Result<()>516d4242001SAdam Bratschi-Kaye     pub(crate) fn store<T>(
517d4242001SAdam Bratschi-Kaye         &self,
518d4242001SAdam Bratschi-Kaye         cx: &mut LowerContext<'_, T>,
519d4242001SAdam Bratschi-Kaye         ty: InterfaceType,
520d4242001SAdam Bratschi-Kaye         offset: usize,
521d4242001SAdam Bratschi-Kaye     ) -> Result<()> {
5229034e101SAlex Crichton         debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0);
523d4242001SAdam Bratschi-Kaye 
5249de6828eSAlex Crichton         match (ty, self) {
5257dba8efdSNick Fitzgerald             (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset),
5269de6828eSAlex Crichton             (InterfaceType::Bool, _) => unexpected(ty, self),
5277dba8efdSNick Fitzgerald             (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset),
5289de6828eSAlex Crichton             (InterfaceType::U8, _) => unexpected(ty, self),
5297dba8efdSNick Fitzgerald             (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset),
5309de6828eSAlex Crichton             (InterfaceType::S8, _) => unexpected(ty, self),
5317dba8efdSNick Fitzgerald             (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset),
5329de6828eSAlex Crichton             (InterfaceType::U16, _) => unexpected(ty, self),
5337dba8efdSNick Fitzgerald             (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset),
5349de6828eSAlex Crichton             (InterfaceType::S16, _) => unexpected(ty, self),
5357dba8efdSNick Fitzgerald             (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset),
5369de6828eSAlex Crichton             (InterfaceType::U32, _) => unexpected(ty, self),
5377dba8efdSNick Fitzgerald             (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset),
5389de6828eSAlex Crichton             (InterfaceType::S32, _) => unexpected(ty, self),
5397dba8efdSNick Fitzgerald             (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset),
5409de6828eSAlex Crichton             (InterfaceType::U64, _) => unexpected(ty, self),
5417dba8efdSNick Fitzgerald             (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset),
5429de6828eSAlex Crichton             (InterfaceType::S64, _) => unexpected(ty, self),
5437dba8efdSNick Fitzgerald             (InterfaceType::Float32, Val::Float32(value)) => {
5447dba8efdSNick Fitzgerald                 value.linear_lower_to_memory(cx, ty, offset)
5457dba8efdSNick Fitzgerald             }
5469de6828eSAlex Crichton             (InterfaceType::Float32, _) => unexpected(ty, self),
5477dba8efdSNick Fitzgerald             (InterfaceType::Float64, Val::Float64(value)) => {
5487dba8efdSNick Fitzgerald                 value.linear_lower_to_memory(cx, ty, offset)
5497dba8efdSNick Fitzgerald             }
5509de6828eSAlex Crichton             (InterfaceType::Float64, _) => unexpected(ty, self),
5517dba8efdSNick Fitzgerald             (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset),
5529de6828eSAlex Crichton             (InterfaceType::Char, _) => unexpected(ty, self),
5537dba8efdSNick Fitzgerald             (InterfaceType::String, Val::String(value)) => {
5547dba8efdSNick Fitzgerald                 value.linear_lower_to_memory(cx, ty, offset)
5557dba8efdSNick Fitzgerald             }
5569de6828eSAlex Crichton             (InterfaceType::String, _) => unexpected(ty, self),
5579de6828eSAlex Crichton 
5589de6828eSAlex Crichton             // NB: resources do type-checking when they lower.
5599de6828eSAlex Crichton             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
5607dba8efdSNick Fitzgerald                 value.linear_lower_to_memory(cx, ty, offset)
5619de6828eSAlex Crichton             }
5629de6828eSAlex Crichton             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
5639de6828eSAlex Crichton             (InterfaceType::List(ty), Val::List(values)) => {
5649de6828eSAlex Crichton                 let ty = &cx.types[ty];
565d4242001SAdam Bratschi-Kaye                 let (ptr, len) = lower_list(cx, ty.element, values)?;
566ef1ec37eSAlex Crichton                 // FIXME(#4311): needs memory64 handling
5670bce0968SAlex Crichton                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
5680bce0968SAlex Crichton                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
5699de6828eSAlex Crichton                 Ok(())
570d4242001SAdam Bratschi-Kaye             }
5719de6828eSAlex Crichton             (InterfaceType::List(_), _) => unexpected(ty, self),
5721b59b579SYordis Prieto             (InterfaceType::Map(ty_idx), Val::Map(values)) => {
5731b59b579SYordis Prieto                 let map_ty = &cx.types[ty_idx];
5741b59b579SYordis Prieto                 let (ptr, len) = lower_map(cx, map_ty, values)?;
5751b59b579SYordis Prieto                 // FIXME(#4311): needs memory64 handling
5761b59b579SYordis Prieto                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
5771b59b579SYordis Prieto                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
5781b59b579SYordis Prieto                 Ok(())
5791b59b579SYordis Prieto             }
5801b59b579SYordis Prieto             (InterfaceType::Map(_), _) => unexpected(ty, self),
5819de6828eSAlex Crichton             (InterfaceType::Record(ty), Val::Record(values)) => {
5829de6828eSAlex Crichton                 let ty = &cx.types[ty];
5839de6828eSAlex Crichton                 if ty.fields.len() != values.len() {
5849de6828eSAlex Crichton                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
5859de6828eSAlex Crichton                 }
586d4242001SAdam Bratschi-Kaye                 let mut offset = offset;
5879de6828eSAlex Crichton                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
5889de6828eSAlex Crichton                     if *name != field.name {
5899de6828eSAlex Crichton                         bail!("expected field `{}`, got `{name}`", field.name);
5909de6828eSAlex Crichton                     }
591d4242001SAdam Bratschi-Kaye                     value.store(
592d4242001SAdam Bratschi-Kaye                         cx,
593d4242001SAdam Bratschi-Kaye                         field.ty,
594d4242001SAdam Bratschi-Kaye                         cx.types
595d4242001SAdam Bratschi-Kaye                             .canonical_abi(&field.ty)
596d4242001SAdam Bratschi-Kaye                             .next_field32_size(&mut offset),
597d4242001SAdam Bratschi-Kaye                     )?;
598d4242001SAdam Bratschi-Kaye                 }
5999de6828eSAlex Crichton                 Ok(())
600d4242001SAdam Bratschi-Kaye             }
6019de6828eSAlex Crichton             (InterfaceType::Record(_), _) => unexpected(ty, self),
6029de6828eSAlex Crichton             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
6039de6828eSAlex Crichton                 let ty = &cx.types[ty];
6049de6828eSAlex Crichton                 if ty.types.len() != values.len() {
6059de6828eSAlex Crichton                     bail!("expected {} types, got {}", ty.types.len(), values.len());
6069de6828eSAlex Crichton                 }
607d4242001SAdam Bratschi-Kaye                 let mut offset = offset;
608d4242001SAdam Bratschi-Kaye                 for (value, ty) in values.iter().zip(ty.types.iter()) {
609d4242001SAdam Bratschi-Kaye                     value.store(
610d4242001SAdam Bratschi-Kaye                         cx,
611d4242001SAdam Bratschi-Kaye                         *ty,
612d4242001SAdam Bratschi-Kaye                         cx.types.canonical_abi(ty).next_field32_size(&mut offset),
613d4242001SAdam Bratschi-Kaye                     )?;
614d4242001SAdam Bratschi-Kaye                 }
6159de6828eSAlex Crichton                 Ok(())
616d4242001SAdam Bratschi-Kaye             }
6179de6828eSAlex Crichton             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
618d4242001SAdam Bratschi-Kaye 
6199de6828eSAlex Crichton             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
6209de6828eSAlex Crichton                 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
6219de6828eSAlex Crichton             }
6229de6828eSAlex Crichton             (InterfaceType::Variant(_), _) => unexpected(ty, self),
6239de6828eSAlex Crichton             (InterfaceType::Enum(ty), Val::Enum(v)) => {
6249de6828eSAlex Crichton                 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
6259de6828eSAlex Crichton             }
6269de6828eSAlex Crichton             (InterfaceType::Enum(_), _) => unexpected(ty, self),
6279de6828eSAlex Crichton             (InterfaceType::Option(ty), Val::Option(v)) => {
6289de6828eSAlex Crichton                 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
6299de6828eSAlex Crichton             }
6309de6828eSAlex Crichton             (InterfaceType::Option(_), _) => unexpected(ty, self),
6319de6828eSAlex Crichton             (InterfaceType::Result(ty), Val::Result(v)) => {
6329de6828eSAlex Crichton                 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
6339de6828eSAlex Crichton             }
6349de6828eSAlex Crichton             (InterfaceType::Result(_), _) => unexpected(ty, self),
635d4242001SAdam Bratschi-Kaye 
6369de6828eSAlex Crichton             (InterfaceType::Flags(ty), Val::Flags(flags)) => {
6379de6828eSAlex Crichton                 let ty = &cx.types[ty];
6389de6828eSAlex Crichton                 let storage = flags_to_storage(ty, flags)?;
6399de6828eSAlex Crichton                 match FlagsSize::from_count(ty.names.len()) {
640d4242001SAdam Bratschi-Kaye                     FlagsSize::Size0 => {}
6417dba8efdSNick Fitzgerald                     FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory(
6427dba8efdSNick Fitzgerald                         cx,
6437dba8efdSNick Fitzgerald                         InterfaceType::U8,
6447dba8efdSNick Fitzgerald                         offset,
6457dba8efdSNick Fitzgerald                     )?,
6467dba8efdSNick Fitzgerald                     FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory(
6477dba8efdSNick Fitzgerald                         cx,
6487dba8efdSNick Fitzgerald                         InterfaceType::U16,
6497dba8efdSNick Fitzgerald                         offset,
6507dba8efdSNick Fitzgerald                     )?,
651d4242001SAdam Bratschi-Kaye                     FlagsSize::Size4Plus(_) => {
652d4242001SAdam Bratschi-Kaye                         let mut offset = offset;
6539de6828eSAlex Crichton                         for value in storage {
6547dba8efdSNick Fitzgerald                             value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?;
655d4242001SAdam Bratschi-Kaye                             offset += 4;
656d4242001SAdam Bratschi-Kaye                         }
657d4242001SAdam Bratschi-Kaye                     }
658d4242001SAdam Bratschi-Kaye                 }
6599de6828eSAlex Crichton                 Ok(())
6609de6828eSAlex Crichton             }
6619de6828eSAlex Crichton             (InterfaceType::Flags(_), _) => unexpected(ty, self),
662f586be11SAlex Crichton             (InterfaceType::Future(_), Val::Future(f)) => f.linear_lower_to_memory(cx, ty, offset),
663b221fca7SJoel Dice             (InterfaceType::Future(_), _) => unexpected(ty, self),
664f586be11SAlex Crichton             (InterfaceType::Stream(_), Val::Stream(s)) => s.linear_lower_to_memory(cx, ty, offset),
665b221fca7SJoel Dice             (InterfaceType::Stream(_), _) => unexpected(ty, self),
666b221fca7SJoel Dice             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
667b221fca7SJoel Dice                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory(
668b221fca7SJoel Dice                     cx,
669b221fca7SJoel Dice                     InterfaceType::U32,
670b221fca7SJoel Dice                     offset,
671b221fca7SJoel Dice                 )
672b221fca7SJoel Dice             }
673b221fca7SJoel Dice             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
674caf0f752SChristof Petig             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
675d4242001SAdam Bratschi-Kaye         }
676d4242001SAdam Bratschi-Kaye     }
677d4242001SAdam Bratschi-Kaye 
desc(&self) -> &'static str678b221fca7SJoel Dice     pub(crate) fn desc(&self) -> &'static str {
6799de6828eSAlex Crichton         match self {
6809de6828eSAlex Crichton             Val::Bool(_) => "bool",
6819de6828eSAlex Crichton             Val::U8(_) => "u8",
6829de6828eSAlex Crichton             Val::S8(_) => "s8",
6839de6828eSAlex Crichton             Val::U16(_) => "u16",
6849de6828eSAlex Crichton             Val::S16(_) => "s16",
6859de6828eSAlex Crichton             Val::U32(_) => "u32",
6869de6828eSAlex Crichton             Val::S32(_) => "s32",
6879de6828eSAlex Crichton             Val::U64(_) => "u64",
6889de6828eSAlex Crichton             Val::S64(_) => "s64",
6899de6828eSAlex Crichton             Val::Float32(_) => "f32",
6909de6828eSAlex Crichton             Val::Float64(_) => "f64",
6919de6828eSAlex Crichton             Val::Char(_) => "char",
6929de6828eSAlex Crichton             Val::List(_) => "list",
6931b59b579SYordis Prieto             Val::Map(_) => "map",
6949de6828eSAlex Crichton             Val::String(_) => "string",
6959de6828eSAlex Crichton             Val::Record(_) => "record",
6969de6828eSAlex Crichton             Val::Enum(_) => "enum",
6979de6828eSAlex Crichton             Val::Variant(..) => "variant",
6989de6828eSAlex Crichton             Val::Tuple(_) => "tuple",
6999de6828eSAlex Crichton             Val::Option(_) => "option",
7009de6828eSAlex Crichton             Val::Result(_) => "result",
7019de6828eSAlex Crichton             Val::Resource(_) => "resource",
7029de6828eSAlex Crichton             Val::Flags(_) => "flags",
703b221fca7SJoel Dice             Val::Future(_) => "future",
704b221fca7SJoel Dice             Val::Stream(_) => "stream",
705b221fca7SJoel Dice             Val::ErrorContext(_) => "error-context",
7069de6828eSAlex Crichton         }
707d4242001SAdam Bratschi-Kaye     }
7084c6739f1SPat Hickey 
7094c6739f1SPat Hickey     /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization
7101e5d77d6Sshenpengfeng     /// requires a target [`crate::component::Type`].
7114c6739f1SPat Hickey     #[cfg(feature = "wave")]
from_wave(ty: &crate::component::Type, s: &str) -> Result<Self>7124c6739f1SPat Hickey     pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
7134c6739f1SPat Hickey         Ok(wasm_wave::from_str(ty, s)?)
7144c6739f1SPat Hickey     }
7154c6739f1SPat Hickey 
7164c6739f1SPat Hickey     /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding.
7174c6739f1SPat Hickey     #[cfg(feature = "wave")]
to_wave(&self) -> Result<String>7184c6739f1SPat Hickey     pub fn to_wave(&self) -> Result<String> {
7194c6739f1SPat Hickey         Ok(wasm_wave::to_string(self)?)
7204c6739f1SPat Hickey     }
721d4242001SAdam Bratschi-Kaye }
722d4242001SAdam Bratschi-Kaye 
723d4242001SAdam Bratschi-Kaye impl PartialEq for Val {
eq(&self, other: &Self) -> bool724d4242001SAdam Bratschi-Kaye     fn eq(&self, other: &Self) -> bool {
725d4242001SAdam Bratschi-Kaye         match (self, other) {
726d4242001SAdam Bratschi-Kaye             // IEEE 754 equality considers NaN inequal to NaN and negative zero
727d4242001SAdam Bratschi-Kaye             // equal to positive zero, however we do the opposite here, because
728d4242001SAdam Bratschi-Kaye             // this logic is used by testing and fuzzing, which want to know
729d4242001SAdam Bratschi-Kaye             // whether two values are semantically the same, rather than
730d4242001SAdam Bratschi-Kaye             // numerically equal.
731d4242001SAdam Bratschi-Kaye             (Self::Float32(l), Self::Float32(r)) => {
732d4242001SAdam Bratschi-Kaye                 (*l != 0.0 && l == r)
733d4242001SAdam Bratschi-Kaye                     || (*l == 0.0 && l.to_bits() == r.to_bits())
734d4242001SAdam Bratschi-Kaye                     || (l.is_nan() && r.is_nan())
735d4242001SAdam Bratschi-Kaye             }
736d4242001SAdam Bratschi-Kaye             (Self::Float32(_), _) => false,
737d4242001SAdam Bratschi-Kaye             (Self::Float64(l), Self::Float64(r)) => {
738d4242001SAdam Bratschi-Kaye                 (*l != 0.0 && l == r)
739d4242001SAdam Bratschi-Kaye                     || (*l == 0.0 && l.to_bits() == r.to_bits())
740d4242001SAdam Bratschi-Kaye                     || (l.is_nan() && r.is_nan())
741d4242001SAdam Bratschi-Kaye             }
742d4242001SAdam Bratschi-Kaye             (Self::Float64(_), _) => false,
743d4242001SAdam Bratschi-Kaye 
744d4242001SAdam Bratschi-Kaye             (Self::Bool(l), Self::Bool(r)) => l == r,
745d4242001SAdam Bratschi-Kaye             (Self::Bool(_), _) => false,
746d4242001SAdam Bratschi-Kaye             (Self::S8(l), Self::S8(r)) => l == r,
747d4242001SAdam Bratschi-Kaye             (Self::S8(_), _) => false,
748d4242001SAdam Bratschi-Kaye             (Self::U8(l), Self::U8(r)) => l == r,
749d4242001SAdam Bratschi-Kaye             (Self::U8(_), _) => false,
750d4242001SAdam Bratschi-Kaye             (Self::S16(l), Self::S16(r)) => l == r,
751d4242001SAdam Bratschi-Kaye             (Self::S16(_), _) => false,
752d4242001SAdam Bratschi-Kaye             (Self::U16(l), Self::U16(r)) => l == r,
753d4242001SAdam Bratschi-Kaye             (Self::U16(_), _) => false,
754d4242001SAdam Bratschi-Kaye             (Self::S32(l), Self::S32(r)) => l == r,
755d4242001SAdam Bratschi-Kaye             (Self::S32(_), _) => false,
756d4242001SAdam Bratschi-Kaye             (Self::U32(l), Self::U32(r)) => l == r,
757d4242001SAdam Bratschi-Kaye             (Self::U32(_), _) => false,
758d4242001SAdam Bratschi-Kaye             (Self::S64(l), Self::S64(r)) => l == r,
759d4242001SAdam Bratschi-Kaye             (Self::S64(_), _) => false,
760d4242001SAdam Bratschi-Kaye             (Self::U64(l), Self::U64(r)) => l == r,
761d4242001SAdam Bratschi-Kaye             (Self::U64(_), _) => false,
762d4242001SAdam Bratschi-Kaye             (Self::Char(l), Self::Char(r)) => l == r,
763d4242001SAdam Bratschi-Kaye             (Self::Char(_), _) => false,
764d4242001SAdam Bratschi-Kaye             (Self::String(l), Self::String(r)) => l == r,
765d4242001SAdam Bratschi-Kaye             (Self::String(_), _) => false,
766d4242001SAdam Bratschi-Kaye             (Self::List(l), Self::List(r)) => l == r,
767d4242001SAdam Bratschi-Kaye             (Self::List(_), _) => false,
7681b59b579SYordis Prieto             (Self::Map(l), Self::Map(r)) => l == r,
7691b59b579SYordis Prieto             (Self::Map(_), _) => false,
770d4242001SAdam Bratschi-Kaye             (Self::Record(l), Self::Record(r)) => l == r,
771d4242001SAdam Bratschi-Kaye             (Self::Record(_), _) => false,
772d4242001SAdam Bratschi-Kaye             (Self::Tuple(l), Self::Tuple(r)) => l == r,
773d4242001SAdam Bratschi-Kaye             (Self::Tuple(_), _) => false,
7749de6828eSAlex Crichton             (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
7759de6828eSAlex Crichton             (Self::Variant(..), _) => false,
776d4242001SAdam Bratschi-Kaye             (Self::Enum(l), Self::Enum(r)) => l == r,
777d4242001SAdam Bratschi-Kaye             (Self::Enum(_), _) => false,
778d4242001SAdam Bratschi-Kaye             (Self::Option(l), Self::Option(r)) => l == r,
779d4242001SAdam Bratschi-Kaye             (Self::Option(_), _) => false,
780d4242001SAdam Bratschi-Kaye             (Self::Result(l), Self::Result(r)) => l == r,
781d4242001SAdam Bratschi-Kaye             (Self::Result(_), _) => false,
782d4242001SAdam Bratschi-Kaye             (Self::Flags(l), Self::Flags(r)) => l == r,
783d4242001SAdam Bratschi-Kaye             (Self::Flags(_), _) => false,
784d4242001SAdam Bratschi-Kaye             (Self::Resource(l), Self::Resource(r)) => l == r,
785d4242001SAdam Bratschi-Kaye             (Self::Resource(_), _) => false,
786b221fca7SJoel Dice             (Self::Future(l), Self::Future(r)) => l == r,
787b221fca7SJoel Dice             (Self::Future(_), _) => false,
788b221fca7SJoel Dice             (Self::Stream(l), Self::Stream(r)) => l == r,
789b221fca7SJoel Dice             (Self::Stream(_), _) => false,
790b221fca7SJoel Dice             (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r,
791b221fca7SJoel Dice             (Self::ErrorContext(_), _) => false,
792d4242001SAdam Bratschi-Kaye         }
793d4242001SAdam Bratschi-Kaye     }
794d4242001SAdam Bratschi-Kaye }
795d4242001SAdam Bratschi-Kaye 
796d4242001SAdam Bratschi-Kaye impl Eq for Val {}
797d4242001SAdam Bratschi-Kaye 
798d4242001SAdam Bratschi-Kaye struct GenericVariant<'a> {
799d4242001SAdam Bratschi-Kaye     discriminant: u32,
800d4242001SAdam Bratschi-Kaye     payload: Option<(&'a Val, InterfaceType)>,
801d4242001SAdam Bratschi-Kaye     abi: &'a CanonicalAbiInfo,
802d4242001SAdam Bratschi-Kaye     info: &'a VariantInfo,
803d4242001SAdam Bratschi-Kaye }
804d4242001SAdam Bratschi-Kaye 
805d4242001SAdam Bratschi-Kaye impl GenericVariant<'_> {
result<'a>( ty: &'a TypeResult, r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>, ) -> Result<GenericVariant<'a>>8069de6828eSAlex Crichton     fn result<'a>(
8079de6828eSAlex Crichton         ty: &'a TypeResult,
8089de6828eSAlex Crichton         r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
8099de6828eSAlex Crichton     ) -> Result<GenericVariant<'a>> {
8109de6828eSAlex Crichton         let (discriminant, payload) = match r {
8119de6828eSAlex Crichton             Ok(val) => {
8129de6828eSAlex Crichton                 let payload = match (val, ty.ok) {
8139de6828eSAlex Crichton                     (Some(val), Some(ty)) => Some((&**val, ty)),
8149de6828eSAlex Crichton                     (None, None) => None,
8159de6828eSAlex Crichton                     (Some(_), None) => {
8169de6828eSAlex Crichton                         bail!("payload provided to `ok` but not expected");
8179de6828eSAlex Crichton                     }
8189de6828eSAlex Crichton                     (None, Some(_)) => {
8199de6828eSAlex Crichton                         bail!("payload expected to `ok` but not provided");
8209de6828eSAlex Crichton                     }
8219de6828eSAlex Crichton                 };
8229de6828eSAlex Crichton                 (0, payload)
8239de6828eSAlex Crichton             }
8249de6828eSAlex Crichton             Err(val) => {
8259de6828eSAlex Crichton                 let payload = match (val, ty.err) {
8269de6828eSAlex Crichton                     (Some(val), Some(ty)) => Some((&**val, ty)),
8279de6828eSAlex Crichton                     (None, None) => None,
8289de6828eSAlex Crichton                     (Some(_), None) => {
8299de6828eSAlex Crichton                         bail!("payload provided to `err` but not expected");
8309de6828eSAlex Crichton                     }
8319de6828eSAlex Crichton                     (None, Some(_)) => {
8329de6828eSAlex Crichton                         bail!("payload expected to `err` but not provided");
8339de6828eSAlex Crichton                     }
8349de6828eSAlex Crichton                 };
8359de6828eSAlex Crichton                 (1, payload)
8369de6828eSAlex Crichton             }
8379de6828eSAlex Crichton         };
8389de6828eSAlex Crichton         Ok(GenericVariant {
8399de6828eSAlex Crichton             discriminant,
8409de6828eSAlex Crichton             payload,
8419de6828eSAlex Crichton             abi: &ty.abi,
8429de6828eSAlex Crichton             info: &ty.info,
8439de6828eSAlex Crichton         })
8449de6828eSAlex Crichton     }
8459de6828eSAlex Crichton 
option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a>8469de6828eSAlex Crichton     fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
8479de6828eSAlex Crichton         let (discriminant, payload) = match r {
8489de6828eSAlex Crichton             None => (0, None),
8499de6828eSAlex Crichton             Some(val) => (1, Some((&**val, ty.ty))),
8509de6828eSAlex Crichton         };
8519de6828eSAlex Crichton         GenericVariant {
8529de6828eSAlex Crichton             discriminant,
8539de6828eSAlex Crichton             payload,
8549de6828eSAlex Crichton             abi: &ty.abi,
8559de6828eSAlex Crichton             info: &ty.info,
8569de6828eSAlex Crichton         }
8579de6828eSAlex Crichton     }
8589de6828eSAlex Crichton 
enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>>8599de6828eSAlex Crichton     fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
8609de6828eSAlex Crichton         let discriminant = get_enum_discriminant(ty, discriminant)?;
8619de6828eSAlex Crichton 
8629de6828eSAlex Crichton         Ok(GenericVariant {
8639de6828eSAlex Crichton             discriminant,
8649de6828eSAlex Crichton             payload: None,
8659de6828eSAlex Crichton             abi: &ty.abi,
8669de6828eSAlex Crichton             info: &ty.info,
8679de6828eSAlex Crichton         })
8689de6828eSAlex Crichton     }
8699de6828eSAlex Crichton 
variant<'a>( ty: &'a TypeVariant, discriminant_name: &str, payload: &'a Option<Box<Val>>, ) -> Result<GenericVariant<'a>>8709de6828eSAlex Crichton     fn variant<'a>(
8719de6828eSAlex Crichton         ty: &'a TypeVariant,
8729de6828eSAlex Crichton         discriminant_name: &str,
8739de6828eSAlex Crichton         payload: &'a Option<Box<Val>>,
8749de6828eSAlex Crichton     ) -> Result<GenericVariant<'a>> {
8759de6828eSAlex Crichton         let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
8769de6828eSAlex Crichton 
8779de6828eSAlex Crichton         let payload = match (payload, payload_ty) {
8789de6828eSAlex Crichton             (Some(val), Some(ty)) => Some((&**val, *ty)),
8799de6828eSAlex Crichton             (None, None) => None,
8809de6828eSAlex Crichton             (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
8819de6828eSAlex Crichton             (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
8829de6828eSAlex Crichton         };
8839de6828eSAlex Crichton 
8849de6828eSAlex Crichton         Ok(GenericVariant {
8859de6828eSAlex Crichton             discriminant,
8869de6828eSAlex Crichton             payload,
8879de6828eSAlex Crichton             abi: &ty.abi,
8889de6828eSAlex Crichton             info: &ty.info,
8899de6828eSAlex Crichton         })
8909de6828eSAlex Crichton     }
8919de6828eSAlex Crichton 
lower<T>( &self, cx: &mut LowerContext<'_, T>, dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, ) -> Result<()>892d4242001SAdam Bratschi-Kaye     fn lower<T>(
893d4242001SAdam Bratschi-Kaye         &self,
894d4242001SAdam Bratschi-Kaye         cx: &mut LowerContext<'_, T>,
89581a89169SAlex Crichton         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
896d4242001SAdam Bratschi-Kaye     ) -> Result<()> {
897d4242001SAdam Bratschi-Kaye         next_mut(dst).write(ValRaw::u32(self.discriminant));
898d4242001SAdam Bratschi-Kaye 
899d4242001SAdam Bratschi-Kaye         // For the remaining lowered representation of this variant that
900d4242001SAdam Bratschi-Kaye         // the payload didn't write we write out zeros here to ensure
901d4242001SAdam Bratschi-Kaye         // the entire variant is written.
902d4242001SAdam Bratschi-Kaye         let value_flat = match self.payload {
903d4242001SAdam Bratschi-Kaye             Some((value, ty)) => {
904d4242001SAdam Bratschi-Kaye                 value.lower(cx, ty, dst)?;
905d4242001SAdam Bratschi-Kaye                 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
906d4242001SAdam Bratschi-Kaye             }
907d4242001SAdam Bratschi-Kaye             None => 0,
908d4242001SAdam Bratschi-Kaye         };
909d4242001SAdam Bratschi-Kaye         let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
910d4242001SAdam Bratschi-Kaye         for _ in (1 + value_flat)..variant_flat {
911d4242001SAdam Bratschi-Kaye             next_mut(dst).write(ValRaw::u64(0));
912d4242001SAdam Bratschi-Kaye         }
913d4242001SAdam Bratschi-Kaye         Ok(())
914d4242001SAdam Bratschi-Kaye     }
915d4242001SAdam Bratschi-Kaye 
store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()>916d4242001SAdam Bratschi-Kaye     fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
917d4242001SAdam Bratschi-Kaye         match self.info.size {
9187dba8efdSNick Fitzgerald             DiscriminantSize::Size1 => u8::try_from(self.discriminant)
919d4242001SAdam Bratschi-Kaye                 .unwrap()
9207dba8efdSNick Fitzgerald                 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?,
9217dba8efdSNick Fitzgerald             DiscriminantSize::Size2 => u16::try_from(self.discriminant)
922d4242001SAdam Bratschi-Kaye                 .unwrap()
9237dba8efdSNick Fitzgerald                 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?,
9247dba8efdSNick Fitzgerald             DiscriminantSize::Size4 => {
9257dba8efdSNick Fitzgerald                 self.discriminant
9267dba8efdSNick Fitzgerald                     .linear_lower_to_memory(cx, InterfaceType::U32, offset)?
927d4242001SAdam Bratschi-Kaye             }
928d4242001SAdam Bratschi-Kaye         }
929d4242001SAdam Bratschi-Kaye 
930d4242001SAdam Bratschi-Kaye         if let Some((value, ty)) = self.payload {
931d4242001SAdam Bratschi-Kaye             let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
932d4242001SAdam Bratschi-Kaye             value.store(cx, ty, offset)?;
933d4242001SAdam Bratschi-Kaye         }
934d4242001SAdam Bratschi-Kaye 
935d4242001SAdam Bratschi-Kaye         Ok(())
936d4242001SAdam Bratschi-Kaye     }
937d4242001SAdam Bratschi-Kaye }
938d4242001SAdam Bratschi-Kaye 
lift_flat_pointer_pair( cx: &mut LiftContext<'_>, src: &mut Iter<'_, ValRaw>, ) -> Result<(usize, usize)>939a0d5346dSAlex Crichton fn lift_flat_pointer_pair(
940a0d5346dSAlex Crichton     cx: &mut LiftContext<'_>,
941a0d5346dSAlex Crichton     src: &mut Iter<'_, ValRaw>,
942a0d5346dSAlex Crichton ) -> Result<(usize, usize)> {
943a0d5346dSAlex Crichton     // FIXME(#4311): needs memory64 treatment
944a0d5346dSAlex Crichton     let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
945a0d5346dSAlex Crichton     let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
946a0d5346dSAlex Crichton     Ok((ptr, len))
947a0d5346dSAlex Crichton }
948a0d5346dSAlex Crichton 
load_flat_pointer_pair(bytes: &[u8]) -> (usize, usize)949a0d5346dSAlex Crichton fn load_flat_pointer_pair(bytes: &[u8]) -> (usize, usize) {
950a0d5346dSAlex Crichton     let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize;
951a0d5346dSAlex Crichton     let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize;
952a0d5346dSAlex Crichton     (ptr, len)
953a0d5346dSAlex Crichton }
954a0d5346dSAlex Crichton 
load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val>955d4242001SAdam Bratschi-Kaye fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
956d4242001SAdam Bratschi-Kaye     let elem = cx.types[ty].element;
957d4242001SAdam Bratschi-Kaye     let abi = cx.types.canonical_abi(&elem);
958d4242001SAdam Bratschi-Kaye     let element_size = usize::try_from(abi.size32).unwrap();
959d4242001SAdam Bratschi-Kaye     let element_alignment = abi.align32;
960d4242001SAdam Bratschi-Kaye 
961d4242001SAdam Bratschi-Kaye     match len
962d4242001SAdam Bratschi-Kaye         .checked_mul(element_size)
963d4242001SAdam Bratschi-Kaye         .and_then(|len| ptr.checked_add(len))
964d4242001SAdam Bratschi-Kaye     {
965c5675cc5SAlex Crichton         Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<Val>())?,
966d4242001SAdam Bratschi-Kaye         _ => bail!("list pointer/length out of bounds of memory"),
967d4242001SAdam Bratschi-Kaye     }
9689034e101SAlex Crichton     if ptr % usize::try_from(element_alignment)? != 0 {
969d4242001SAdam Bratschi-Kaye         bail!("list pointer is not aligned")
970d4242001SAdam Bratschi-Kaye     }
971d4242001SAdam Bratschi-Kaye 
9729de6828eSAlex Crichton     Ok(Val::List(
9739de6828eSAlex Crichton         (0..len)
974d4242001SAdam Bratschi-Kaye             .map(|index| {
975d4242001SAdam Bratschi-Kaye                 Val::load(
976d4242001SAdam Bratschi-Kaye                     cx,
977d4242001SAdam Bratschi-Kaye                     elem,
978d4242001SAdam Bratschi-Kaye                     &cx.memory()[ptr + (index * element_size)..][..element_size],
979d4242001SAdam Bratschi-Kaye                 )
980d4242001SAdam Bratschi-Kaye             })
981d4242001SAdam Bratschi-Kaye             .collect::<Result<_>>()?,
9829de6828eSAlex Crichton     ))
983d4242001SAdam Bratschi-Kaye }
984d4242001SAdam Bratschi-Kaye 
load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val>9851b59b579SYordis Prieto fn load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val> {
9861b59b579SYordis Prieto     // Maps are stored as list<tuple<k, v>> in canonical ABI
9871b59b579SYordis Prieto     let map_ty = &cx.types[ty];
9881b59b579SYordis Prieto     let key_ty = map_ty.key;
9891b59b579SYordis Prieto     let value_ty = map_ty.value;
9901b59b579SYordis Prieto 
9911b59b579SYordis Prieto     let key_abi = cx.types.canonical_abi(&key_ty);
9921b59b579SYordis Prieto     let value_abi = cx.types.canonical_abi(&value_ty);
9931b59b579SYordis Prieto     let key_size = usize::try_from(key_abi.size32).unwrap();
9941b59b579SYordis Prieto     let value_size = usize::try_from(value_abi.size32).unwrap();
9951b59b579SYordis Prieto     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
9961b59b579SYordis Prieto     let tuple_alignment = map_ty.entry_abi.align32;
9971b59b579SYordis Prieto     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
9981b59b579SYordis Prieto 
9991b59b579SYordis Prieto     // Bounds check
10001b59b579SYordis Prieto     match len
10011b59b579SYordis Prieto         .checked_mul(tuple_size)
10021b59b579SYordis Prieto         .and_then(|len| ptr.checked_add(len))
10031b59b579SYordis Prieto     {
10045d52f56cSAlex Crichton         Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<(Val, Val)>())?,
10051b59b579SYordis Prieto         _ => bail!("map pointer/length out of bounds of memory"),
10061b59b579SYordis Prieto     }
10071b59b579SYordis Prieto     if ptr % usize::try_from(tuple_alignment)? != 0 {
10081b59b579SYordis Prieto         bail!("map pointer is not aligned")
10091b59b579SYordis Prieto     }
10101b59b579SYordis Prieto 
10111b59b579SYordis Prieto     // Load each tuple (key, value) into a Vec
10121b59b579SYordis Prieto     let mut map = Vec::with_capacity(len);
10131b59b579SYordis Prieto     for index in 0..len {
10141b59b579SYordis Prieto         let tuple_ptr = ptr + (index * tuple_size);
10151b59b579SYordis Prieto         let key = Val::load(cx, key_ty, &cx.memory()[tuple_ptr..][..key_size])?;
10161b59b579SYordis Prieto         let value = Val::load(
10171b59b579SYordis Prieto             cx,
10181b59b579SYordis Prieto             value_ty,
10191b59b579SYordis Prieto             &cx.memory()[tuple_ptr + value_offset..][..value_size],
10201b59b579SYordis Prieto         )?;
10211b59b579SYordis Prieto         map.push((key, value));
10221b59b579SYordis Prieto     }
10231b59b579SYordis Prieto 
10241b59b579SYordis Prieto     Ok(Val::Map(map))
10251b59b579SYordis Prieto }
10261b59b579SYordis Prieto 
load_variant( cx: &mut LiftContext<'_>, info: &VariantInfo, mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, bytes: &[u8], ) -> Result<(u32, Option<Box<Val>>)>1027d4242001SAdam Bratschi-Kaye fn load_variant(
1028d4242001SAdam Bratschi-Kaye     cx: &mut LiftContext<'_>,
1029d4242001SAdam Bratschi-Kaye     info: &VariantInfo,
1030d4242001SAdam Bratschi-Kaye     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1031d4242001SAdam Bratschi-Kaye     bytes: &[u8],
1032d4242001SAdam Bratschi-Kaye ) -> Result<(u32, Option<Box<Val>>)> {
1033d4242001SAdam Bratschi-Kaye     let discriminant = match info.size {
10347dba8efdSNick Fitzgerald         DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory(
10357dba8efdSNick Fitzgerald             cx,
10367dba8efdSNick Fitzgerald             InterfaceType::U8,
10377dba8efdSNick Fitzgerald             &bytes[..1],
10387dba8efdSNick Fitzgerald         )?),
10397dba8efdSNick Fitzgerald         DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory(
10407dba8efdSNick Fitzgerald             cx,
10417dba8efdSNick Fitzgerald             InterfaceType::U16,
10427dba8efdSNick Fitzgerald             &bytes[..2],
10437dba8efdSNick Fitzgerald         )?),
10447dba8efdSNick Fitzgerald         DiscriminantSize::Size4 => {
10457dba8efdSNick Fitzgerald             u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])?
10467dba8efdSNick Fitzgerald         }
1047d4242001SAdam Bratschi-Kaye     };
1048b8a3e205SAlex Crichton     let len = types.len();
1049b8a3e205SAlex Crichton     let case_ty = types
1050b8a3e205SAlex Crichton         .nth(discriminant as usize)
1051b8a3e205SAlex Crichton         .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?;
1052d4242001SAdam Bratschi-Kaye     let value = match case_ty {
1053d4242001SAdam Bratschi-Kaye         Some(case_ty) => {
1054d4242001SAdam Bratschi-Kaye             let payload_offset = usize::try_from(info.payload_offset32).unwrap();
1055d4242001SAdam Bratschi-Kaye             let case_abi = cx.types.canonical_abi(&case_ty);
1056d4242001SAdam Bratschi-Kaye             let case_size = usize::try_from(case_abi.size32).unwrap();
1057d4242001SAdam Bratschi-Kaye             Some(Box::new(Val::load(
1058d4242001SAdam Bratschi-Kaye                 cx,
1059d4242001SAdam Bratschi-Kaye                 case_ty,
1060d4242001SAdam Bratschi-Kaye                 &bytes[payload_offset..][..case_size],
1061d4242001SAdam Bratschi-Kaye             )?))
1062d4242001SAdam Bratschi-Kaye         }
1063d4242001SAdam Bratschi-Kaye         None => None,
1064d4242001SAdam Bratschi-Kaye     };
1065d4242001SAdam Bratschi-Kaye     Ok((discriminant, value))
1066d4242001SAdam Bratschi-Kaye }
1067d4242001SAdam Bratschi-Kaye 
lift_variant( cx: &mut LiftContext<'_>, flatten_count: usize, mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, src: &mut Iter<'_, ValRaw>, ) -> Result<(u32, Option<Box<Val>>)>1068d4242001SAdam Bratschi-Kaye fn lift_variant(
1069d4242001SAdam Bratschi-Kaye     cx: &mut LiftContext<'_>,
1070d4242001SAdam Bratschi-Kaye     flatten_count: usize,
1071d4242001SAdam Bratschi-Kaye     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
107281a89169SAlex Crichton     src: &mut Iter<'_, ValRaw>,
1073d4242001SAdam Bratschi-Kaye ) -> Result<(u32, Option<Box<Val>>)> {
1074d4242001SAdam Bratschi-Kaye     let len = types.len();
1075d4242001SAdam Bratschi-Kaye     let discriminant = next(src).get_u32();
1076d4242001SAdam Bratschi-Kaye     let ty = types
1077d4242001SAdam Bratschi-Kaye         .nth(discriminant as usize)
1078ff33e949SNick Fitzgerald         .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?;
1079d4242001SAdam Bratschi-Kaye     let (value, value_flat) = match ty {
1080d4242001SAdam Bratschi-Kaye         Some(ty) => (
1081d4242001SAdam Bratschi-Kaye             Some(Box::new(Val::lift(cx, ty, src)?)),
1082d4242001SAdam Bratschi-Kaye             cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1083d4242001SAdam Bratschi-Kaye         ),
1084d4242001SAdam Bratschi-Kaye         None => (None, 0),
1085d4242001SAdam Bratschi-Kaye     };
1086d4242001SAdam Bratschi-Kaye     for _ in (1 + value_flat)..flatten_count {
1087d4242001SAdam Bratschi-Kaye         next(src);
1088d4242001SAdam Bratschi-Kaye     }
1089d4242001SAdam Bratschi-Kaye     Ok((discriminant, value))
1090d4242001SAdam Bratschi-Kaye }
1091d4242001SAdam Bratschi-Kaye 
1092d4242001SAdam Bratschi-Kaye /// Lower a list with the specified element type and values.
lower_list<T>( cx: &mut LowerContext<'_, T>, element_type: InterfaceType, items: &[Val], ) -> Result<(usize, usize)>1093d4242001SAdam Bratschi-Kaye fn lower_list<T>(
1094d4242001SAdam Bratschi-Kaye     cx: &mut LowerContext<'_, T>,
1095d4242001SAdam Bratschi-Kaye     element_type: InterfaceType,
1096d4242001SAdam Bratschi-Kaye     items: &[Val],
1097d4242001SAdam Bratschi-Kaye ) -> Result<(usize, usize)> {
1098d4242001SAdam Bratschi-Kaye     let abi = cx.types.canonical_abi(&element_type);
10999034e101SAlex Crichton     let elt_size = usize::try_from(abi.size32)?;
1100d4242001SAdam Bratschi-Kaye     let elt_align = abi.align32;
1101d4242001SAdam Bratschi-Kaye     let size = items
1102d4242001SAdam Bratschi-Kaye         .len()
1103d4242001SAdam Bratschi-Kaye         .checked_mul(elt_size)
110496e19700SNick Fitzgerald         .ok_or_else(|| crate::format_err!("size overflow copying a list"))?;
1105d4242001SAdam Bratschi-Kaye     let ptr = cx.realloc(0, 0, elt_align, size)?;
1106d4242001SAdam Bratschi-Kaye     let mut element_ptr = ptr;
1107d4242001SAdam Bratschi-Kaye     for item in items {
1108d4242001SAdam Bratschi-Kaye         item.store(cx, element_type, element_ptr)?;
1109d4242001SAdam Bratschi-Kaye         element_ptr += elt_size;
1110d4242001SAdam Bratschi-Kaye     }
1111d4242001SAdam Bratschi-Kaye     Ok((ptr, items.len()))
1112d4242001SAdam Bratschi-Kaye }
1113d4242001SAdam Bratschi-Kaye 
11141b59b579SYordis Prieto /// Lower a map as list<tuple<k, v>> with the specified key and value types.
lower_map<T>( cx: &mut LowerContext<'_, T>, map_ty: &TypeMap, pairs: &[(Val, Val)], ) -> Result<(usize, usize)>11151b59b579SYordis Prieto fn lower_map<T>(
11161b59b579SYordis Prieto     cx: &mut LowerContext<'_, T>,
11171b59b579SYordis Prieto     map_ty: &TypeMap,
11181b59b579SYordis Prieto     pairs: &[(Val, Val)],
11191b59b579SYordis Prieto ) -> Result<(usize, usize)> {
11201b59b579SYordis Prieto     let key_type = map_ty.key;
11211b59b579SYordis Prieto     let value_type = map_ty.value;
11221b59b579SYordis Prieto     let value_offset = usize::try_from(map_ty.value_offset32).unwrap();
11231b59b579SYordis Prieto     let tuple_align = map_ty.entry_abi.align32;
11241b59b579SYordis Prieto     let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap();
11251b59b579SYordis Prieto 
11261b59b579SYordis Prieto     let size = pairs
11271b59b579SYordis Prieto         .len()
11281b59b579SYordis Prieto         .checked_mul(tuple_size)
11291b59b579SYordis Prieto         .ok_or_else(|| crate::format_err!("size overflow copying a map"))?;
11301b59b579SYordis Prieto     let ptr = cx.realloc(0, 0, tuple_align, size)?;
11311b59b579SYordis Prieto 
11321b59b579SYordis Prieto     let mut tuple_ptr = ptr;
11331b59b579SYordis Prieto     for (key, value) in pairs {
11341b59b579SYordis Prieto         // Store key at tuple_ptr
11351b59b579SYordis Prieto         key.store(cx, key_type, tuple_ptr)?;
11361b59b579SYordis Prieto         // Store value at tuple_ptr + value_offset (properly aligned)
11371b59b579SYordis Prieto         value.store(cx, value_type, tuple_ptr + value_offset)?;
11381b59b579SYordis Prieto         tuple_ptr += tuple_size;
11391b59b579SYordis Prieto     }
11401b59b579SYordis Prieto 
11411b59b579SYordis Prieto     Ok((ptr, pairs.len()))
11421b59b579SYordis Prieto }
11431b59b579SYordis Prieto 
push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32)11449de6828eSAlex Crichton fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1145*39e910beSAlex Crichton     while bits > 0 && usize::try_from(offset).unwrap() < ty.names.len() {
11469de6828eSAlex Crichton         if bits & 1 != 0 {
11479de6828eSAlex Crichton             flags.push(ty.names[offset as usize].clone());
11489de6828eSAlex Crichton         }
11499de6828eSAlex Crichton         bits >>= 1;
11509de6828eSAlex Crichton         offset += 1;
11519de6828eSAlex Crichton     }
11529de6828eSAlex Crichton }
11539de6828eSAlex Crichton 
flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>>11549de6828eSAlex Crichton fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
11559de6828eSAlex Crichton     let mut storage = match FlagsSize::from_count(ty.names.len()) {
11569de6828eSAlex Crichton         FlagsSize::Size0 => Vec::new(),
11579de6828eSAlex Crichton         FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
11589de6828eSAlex Crichton         FlagsSize::Size4Plus(n) => vec![0; n.into()],
11599de6828eSAlex Crichton     };
11609de6828eSAlex Crichton 
11619de6828eSAlex Crichton     for flag in flags {
11629de6828eSAlex Crichton         let bit = ty
11639de6828eSAlex Crichton             .names
11649de6828eSAlex Crichton             .get_index_of(flag)
116596e19700SNick Fitzgerald             .ok_or_else(|| crate::format_err!("unknown flag: `{flag}`"))?;
11669de6828eSAlex Crichton         storage[bit / 32] |= 1 << (bit % 32);
11679de6828eSAlex Crichton     }
11689de6828eSAlex Crichton     Ok(storage)
11699de6828eSAlex Crichton }
11709de6828eSAlex Crichton 
get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32>11719de6828eSAlex Crichton fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
11729de6828eSAlex Crichton     ty.names
11739de6828eSAlex Crichton         .get_index_of(n)
117496e19700SNick Fitzgerald         .ok_or_else(|| crate::format_err!("enum variant name `{n}` is not valid"))
11750bce0968SAlex Crichton         .map(|i| i.try_into().unwrap())
11769de6828eSAlex Crichton }
11779de6828eSAlex Crichton 
get_variant_discriminant<'a>( ty: &'a TypeVariant, name: &str, ) -> Result<(u32, &'a Option<InterfaceType>)>11789de6828eSAlex Crichton fn get_variant_discriminant<'a>(
11799de6828eSAlex Crichton     ty: &'a TypeVariant,
11809de6828eSAlex Crichton     name: &str,
11819de6828eSAlex Crichton ) -> Result<(u32, &'a Option<InterfaceType>)> {
11829de6828eSAlex Crichton     let (i, _, ty) = ty
11839de6828eSAlex Crichton         .cases
11849de6828eSAlex Crichton         .get_full(name)
118596e19700SNick Fitzgerald         .ok_or_else(|| crate::format_err!("unknown variant case: `{name}`"))?;
11860bce0968SAlex Crichton     Ok((i.try_into().unwrap(), ty))
11879de6828eSAlex Crichton }
11889de6828eSAlex Crichton 
next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw118981a89169SAlex Crichton fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1190d4242001SAdam Bratschi-Kaye     src.next().unwrap()
1191d4242001SAdam Bratschi-Kaye }
1192d4242001SAdam Bratschi-Kaye 
next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw>119381a89169SAlex Crichton fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1194d4242001SAdam Bratschi-Kaye     dst.next().unwrap()
1195d4242001SAdam Bratschi-Kaye }
11969de6828eSAlex Crichton 
11979de6828eSAlex Crichton #[cold]
unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T>11989de6828eSAlex Crichton fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
11999de6828eSAlex Crichton     bail!(
12009de6828eSAlex Crichton         "type mismatch: expected {}, found {}",
12019de6828eSAlex Crichton         desc(&ty),
12029de6828eSAlex Crichton         val.desc()
12039de6828eSAlex Crichton     )
12049de6828eSAlex Crichton }
1205b221fca7SJoel Dice 
1206b221fca7SJoel Dice /// Represents a component model `error-context`.
1207b221fca7SJoel Dice ///
1208b221fca7SJoel Dice /// Note that this type is not usable at this time as its implementation has not
1209b221fca7SJoel Dice /// been filled out. There are no operations on this and there's additionally no
1210b221fca7SJoel Dice /// ability to "drop" or deallocate this index.
1211b221fca7SJoel Dice //
1212b221fca7SJoel Dice // FIXME(#11161) this needs to be filled out implementation-wise
1213b221fca7SJoel Dice #[derive(Debug, Clone, PartialEq, Eq)]
1214b221fca7SJoel Dice pub struct ErrorContextAny(pub(crate) u32);
1215f586be11SAlex Crichton 
1216f586be11SAlex Crichton impl From<bool> for Val {
from(b: bool) -> Self1217f586be11SAlex Crichton     fn from(b: bool) -> Self {
1218f586be11SAlex Crichton         Val::Bool(b)
1219f586be11SAlex Crichton     }
1220f586be11SAlex Crichton }
1221f586be11SAlex Crichton 
1222f586be11SAlex Crichton impl From<u8> for Val {
from(u: u8) -> Self1223f586be11SAlex Crichton     fn from(u: u8) -> Self {
1224f586be11SAlex Crichton         Val::U8(u)
1225f586be11SAlex Crichton     }
1226f586be11SAlex Crichton }
1227f586be11SAlex Crichton 
1228f586be11SAlex Crichton impl From<i8> for Val {
from(i: i8) -> Self1229f586be11SAlex Crichton     fn from(i: i8) -> Self {
1230f586be11SAlex Crichton         Val::S8(i)
1231f586be11SAlex Crichton     }
1232f586be11SAlex Crichton }
1233f586be11SAlex Crichton 
1234f586be11SAlex Crichton impl From<u16> for Val {
from(u: u16) -> Self1235f586be11SAlex Crichton     fn from(u: u16) -> Self {
1236f586be11SAlex Crichton         Val::U16(u)
1237f586be11SAlex Crichton     }
1238f586be11SAlex Crichton }
1239f586be11SAlex Crichton 
1240f586be11SAlex Crichton impl From<i16> for Val {
from(i: i16) -> Self1241f586be11SAlex Crichton     fn from(i: i16) -> Self {
1242f586be11SAlex Crichton         Val::S16(i)
1243f586be11SAlex Crichton     }
1244f586be11SAlex Crichton }
1245f586be11SAlex Crichton 
1246f586be11SAlex Crichton impl From<u32> for Val {
from(u: u32) -> Self1247f586be11SAlex Crichton     fn from(u: u32) -> Self {
1248f586be11SAlex Crichton         Val::U32(u)
1249f586be11SAlex Crichton     }
1250f586be11SAlex Crichton }
1251f586be11SAlex Crichton 
1252f586be11SAlex Crichton impl From<i32> for Val {
from(i: i32) -> Self1253f586be11SAlex Crichton     fn from(i: i32) -> Self {
1254f586be11SAlex Crichton         Val::S32(i)
1255f586be11SAlex Crichton     }
1256f586be11SAlex Crichton }
1257f586be11SAlex Crichton 
1258f586be11SAlex Crichton impl From<u64> for Val {
from(u: u64) -> Self1259f586be11SAlex Crichton     fn from(u: u64) -> Self {
1260f586be11SAlex Crichton         Val::U64(u)
1261f586be11SAlex Crichton     }
1262f586be11SAlex Crichton }
1263f586be11SAlex Crichton 
1264f586be11SAlex Crichton impl From<i64> for Val {
from(i: i64) -> Self1265f586be11SAlex Crichton     fn from(i: i64) -> Self {
1266f586be11SAlex Crichton         Val::S64(i)
1267f586be11SAlex Crichton     }
1268f586be11SAlex Crichton }
1269f586be11SAlex Crichton 
1270f586be11SAlex Crichton impl From<char> for Val {
from(i: char) -> Self1271f586be11SAlex Crichton     fn from(i: char) -> Self {
1272f586be11SAlex Crichton         Val::Char(i)
1273f586be11SAlex Crichton     }
1274f586be11SAlex Crichton }
1275f586be11SAlex Crichton 
1276f586be11SAlex Crichton impl From<String> for Val {
from(i: String) -> Self1277f586be11SAlex Crichton     fn from(i: String) -> Self {
1278f586be11SAlex Crichton         Val::String(i)
1279f586be11SAlex Crichton     }
1280f586be11SAlex Crichton }
1281f586be11SAlex Crichton 
1282f586be11SAlex Crichton impl From<ResourceAny> for Val {
from(i: ResourceAny) -> Self1283f586be11SAlex Crichton     fn from(i: ResourceAny) -> Self {
1284f586be11SAlex Crichton         Val::Resource(i)
1285f586be11SAlex Crichton     }
1286f586be11SAlex Crichton }
1287f586be11SAlex Crichton 
1288f586be11SAlex Crichton impl From<FutureAny> for Val {
from(i: FutureAny) -> Self1289f586be11SAlex Crichton     fn from(i: FutureAny) -> Self {
1290f586be11SAlex Crichton         Val::Future(i)
1291f586be11SAlex Crichton     }
1292f586be11SAlex Crichton }
1293f586be11SAlex Crichton 
1294f586be11SAlex Crichton impl From<StreamAny> for Val {
from(i: StreamAny) -> Self1295f586be11SAlex Crichton     fn from(i: StreamAny) -> Self {
1296f586be11SAlex Crichton         Val::Stream(i)
1297f586be11SAlex Crichton     }
1298f586be11SAlex Crichton }
1299