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