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