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