1use crate::ValRaw;
2use crate::component::ResourceAny;
3use crate::component::concurrent::{self, ErrorContext, FutureReader, StreamReader};
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 FutureReader::<()>::linear_lift_from_flat(cx, ty, next(src))?.into_val()
211 }
212 InterfaceType::Stream(_) => {
213 StreamReader::<()>::linear_lift_from_flat(cx, ty, next(src))?.into_val()
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(_) => {
340 FutureReader::<()>::linear_lift_from_memory(cx, ty, bytes)?.into_val()
341 }
342 InterfaceType::Stream(_) => {
343 StreamReader::<()>::linear_lift_from_memory(cx, ty, bytes)?.into_val()
344 }
345 InterfaceType::ErrorContext(_) => {
346 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val()
347 }
348 })
349 }
350
351 pub(crate) fn lower<T>(
353 &self,
354 cx: &mut LowerContext<'_, T>,
355 ty: InterfaceType,
356 dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
357 ) -> Result<()> {
358 match (ty, self) {
359 (InterfaceType::Bool, Val::Bool(value)) => {
360 value.linear_lower_to_flat(cx, ty, next_mut(dst))
361 }
362 (InterfaceType::Bool, _) => unexpected(ty, self),
363 (InterfaceType::S8, Val::S8(value)) => {
364 value.linear_lower_to_flat(cx, ty, next_mut(dst))
365 }
366 (InterfaceType::S8, _) => unexpected(ty, self),
367 (InterfaceType::U8, Val::U8(value)) => {
368 value.linear_lower_to_flat(cx, ty, next_mut(dst))
369 }
370 (InterfaceType::U8, _) => unexpected(ty, self),
371 (InterfaceType::S16, Val::S16(value)) => {
372 value.linear_lower_to_flat(cx, ty, next_mut(dst))
373 }
374 (InterfaceType::S16, _) => unexpected(ty, self),
375 (InterfaceType::U16, Val::U16(value)) => {
376 value.linear_lower_to_flat(cx, ty, next_mut(dst))
377 }
378 (InterfaceType::U16, _) => unexpected(ty, self),
379 (InterfaceType::S32, Val::S32(value)) => {
380 value.linear_lower_to_flat(cx, ty, next_mut(dst))
381 }
382 (InterfaceType::S32, _) => unexpected(ty, self),
383 (InterfaceType::U32, Val::U32(value)) => {
384 value.linear_lower_to_flat(cx, ty, next_mut(dst))
385 }
386 (InterfaceType::U32, _) => unexpected(ty, self),
387 (InterfaceType::S64, Val::S64(value)) => {
388 value.linear_lower_to_flat(cx, ty, next_mut(dst))
389 }
390 (InterfaceType::S64, _) => unexpected(ty, self),
391 (InterfaceType::U64, Val::U64(value)) => {
392 value.linear_lower_to_flat(cx, ty, next_mut(dst))
393 }
394 (InterfaceType::U64, _) => unexpected(ty, self),
395 (InterfaceType::Float32, Val::Float32(value)) => {
396 value.linear_lower_to_flat(cx, ty, next_mut(dst))
397 }
398 (InterfaceType::Float32, _) => unexpected(ty, self),
399 (InterfaceType::Float64, Val::Float64(value)) => {
400 value.linear_lower_to_flat(cx, ty, next_mut(dst))
401 }
402 (InterfaceType::Float64, _) => unexpected(ty, self),
403 (InterfaceType::Char, Val::Char(value)) => {
404 value.linear_lower_to_flat(cx, ty, next_mut(dst))
405 }
406 (InterfaceType::Char, _) => unexpected(ty, self),
407 (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
410 value.linear_lower_to_flat(cx, ty, next_mut(dst))
411 }
412 (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
413 (InterfaceType::String, Val::String(value)) => {
414 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit();
415 value.linear_lower_to_flat(cx, ty, my_dst)?;
416 let my_dst = unsafe { my_dst.assume_init() };
417 next_mut(dst).write(my_dst[0]);
418 next_mut(dst).write(my_dst[1]);
419 Ok(())
420 }
421 (InterfaceType::String, _) => unexpected(ty, self),
422 (InterfaceType::List(ty), Val::List(values)) => {
423 let ty = &cx.types[ty];
424 let (ptr, len) = lower_list(cx, ty.element, values)?;
425 next_mut(dst).write(ValRaw::i64(ptr as i64));
426 next_mut(dst).write(ValRaw::i64(len as i64));
427 Ok(())
428 }
429 (InterfaceType::List(_), _) => unexpected(ty, self),
430 (InterfaceType::Record(ty), Val::Record(values)) => {
431 let ty = &cx.types[ty];
432 if ty.fields.len() != values.len() {
433 bail!("expected {} fields, got {}", ty.fields.len(), values.len());
434 }
435 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
436 if *name != field.name {
437 bail!("expected field `{}`, got `{name}`", field.name);
438 }
439 value.lower(cx, field.ty, dst)?;
440 }
441 Ok(())
442 }
443 (InterfaceType::Record(_), _) => unexpected(ty, self),
444 (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
445 let ty = &cx.types[ty];
446 if ty.types.len() != values.len() {
447 bail!("expected {} types, got {}", ty.types.len(), values.len());
448 }
449 for (value, ty) in values.iter().zip(ty.types.iter()) {
450 value.lower(cx, *ty, dst)?;
451 }
452 Ok(())
453 }
454 (InterfaceType::Tuple(_), _) => unexpected(ty, self),
455 (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
456 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst)
457 }
458 (InterfaceType::Variant(_), _) => unexpected(ty, self),
459 (InterfaceType::Option(ty), Val::Option(v)) => {
460 GenericVariant::option(&cx.types[ty], v).lower(cx, dst)
461 }
462 (InterfaceType::Option(_), _) => unexpected(ty, self),
463 (InterfaceType::Result(ty), Val::Result(v)) => {
464 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst)
465 }
466 (InterfaceType::Result(_), _) => unexpected(ty, self),
467 (InterfaceType::Enum(ty), Val::Enum(discriminant)) => {
468 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?;
469 next_mut(dst).write(ValRaw::u32(discriminant));
470 Ok(())
471 }
472 (InterfaceType::Enum(_), _) => unexpected(ty, self),
473 (InterfaceType::Flags(ty), Val::Flags(value)) => {
474 let ty = &cx.types[ty];
475 let storage = flags_to_storage(ty, value)?;
476 for value in storage {
477 next_mut(dst).write(ValRaw::u32(value));
478 }
479 Ok(())
480 }
481 (InterfaceType::Flags(_), _) => unexpected(ty, self),
482 (InterfaceType::Future(_), Val::Future(FutureAny(rep))) => {
483 concurrent::lower_future_to_index(*rep, cx, ty)?.linear_lower_to_flat(
484 cx,
485 InterfaceType::U32,
486 next_mut(dst),
487 )
488 }
489 (InterfaceType::Future(_), _) => unexpected(ty, self),
490 (InterfaceType::Stream(_), Val::Stream(StreamAny(rep))) => {
491 concurrent::lower_stream_to_index(*rep, cx, ty)?.linear_lower_to_flat(
492 cx,
493 InterfaceType::U32,
494 next_mut(dst),
495 )
496 }
497 (InterfaceType::Stream(_), _) => unexpected(ty, self),
498 (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
499 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat(
500 cx,
501 InterfaceType::U32,
502 next_mut(dst),
503 )
504 }
505 (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
506 }
507 }
508
509 pub(crate) fn store<T>(
511 &self,
512 cx: &mut LowerContext<'_, T>,
513 ty: InterfaceType,
514 offset: usize,
515 ) -> Result<()> {
516 debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0);
517
518 match (ty, self) {
519 (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset),
520 (InterfaceType::Bool, _) => unexpected(ty, self),
521 (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset),
522 (InterfaceType::U8, _) => unexpected(ty, self),
523 (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset),
524 (InterfaceType::S8, _) => unexpected(ty, self),
525 (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset),
526 (InterfaceType::U16, _) => unexpected(ty, self),
527 (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset),
528 (InterfaceType::S16, _) => unexpected(ty, self),
529 (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset),
530 (InterfaceType::U32, _) => unexpected(ty, self),
531 (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset),
532 (InterfaceType::S32, _) => unexpected(ty, self),
533 (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset),
534 (InterfaceType::U64, _) => unexpected(ty, self),
535 (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset),
536 (InterfaceType::S64, _) => unexpected(ty, self),
537 (InterfaceType::Float32, Val::Float32(value)) => {
538 value.linear_lower_to_memory(cx, ty, offset)
539 }
540 (InterfaceType::Float32, _) => unexpected(ty, self),
541 (InterfaceType::Float64, Val::Float64(value)) => {
542 value.linear_lower_to_memory(cx, ty, offset)
543 }
544 (InterfaceType::Float64, _) => unexpected(ty, self),
545 (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset),
546 (InterfaceType::Char, _) => unexpected(ty, self),
547 (InterfaceType::String, Val::String(value)) => {
548 value.linear_lower_to_memory(cx, ty, offset)
549 }
550 (InterfaceType::String, _) => unexpected(ty, self),
551
552 (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
554 value.linear_lower_to_memory(cx, ty, offset)
555 }
556 (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
557 (InterfaceType::List(ty), Val::List(values)) => {
558 let ty = &cx.types[ty];
559 let (ptr, len) = lower_list(cx, ty.element, values)?;
560 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
562 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
563 Ok(())
564 }
565 (InterfaceType::List(_), _) => unexpected(ty, self),
566 (InterfaceType::Record(ty), Val::Record(values)) => {
567 let ty = &cx.types[ty];
568 if ty.fields.len() != values.len() {
569 bail!("expected {} fields, got {}", ty.fields.len(), values.len());
570 }
571 let mut offset = offset;
572 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
573 if *name != field.name {
574 bail!("expected field `{}`, got `{name}`", field.name);
575 }
576 value.store(
577 cx,
578 field.ty,
579 cx.types
580 .canonical_abi(&field.ty)
581 .next_field32_size(&mut offset),
582 )?;
583 }
584 Ok(())
585 }
586 (InterfaceType::Record(_), _) => unexpected(ty, self),
587 (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
588 let ty = &cx.types[ty];
589 if ty.types.len() != values.len() {
590 bail!("expected {} types, got {}", ty.types.len(), values.len());
591 }
592 let mut offset = offset;
593 for (value, ty) in values.iter().zip(ty.types.iter()) {
594 value.store(
595 cx,
596 *ty,
597 cx.types.canonical_abi(ty).next_field32_size(&mut offset),
598 )?;
599 }
600 Ok(())
601 }
602 (InterfaceType::Tuple(_), _) => unexpected(ty, self),
603
604 (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
605 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
606 }
607 (InterfaceType::Variant(_), _) => unexpected(ty, self),
608 (InterfaceType::Enum(ty), Val::Enum(v)) => {
609 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
610 }
611 (InterfaceType::Enum(_), _) => unexpected(ty, self),
612 (InterfaceType::Option(ty), Val::Option(v)) => {
613 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
614 }
615 (InterfaceType::Option(_), _) => unexpected(ty, self),
616 (InterfaceType::Result(ty), Val::Result(v)) => {
617 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
618 }
619 (InterfaceType::Result(_), _) => unexpected(ty, self),
620
621 (InterfaceType::Flags(ty), Val::Flags(flags)) => {
622 let ty = &cx.types[ty];
623 let storage = flags_to_storage(ty, flags)?;
624 match FlagsSize::from_count(ty.names.len()) {
625 FlagsSize::Size0 => {}
626 FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory(
627 cx,
628 InterfaceType::U8,
629 offset,
630 )?,
631 FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory(
632 cx,
633 InterfaceType::U16,
634 offset,
635 )?,
636 FlagsSize::Size4Plus(_) => {
637 let mut offset = offset;
638 for value in storage {
639 value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?;
640 offset += 4;
641 }
642 }
643 }
644 Ok(())
645 }
646 (InterfaceType::Flags(_), _) => unexpected(ty, self),
647 (InterfaceType::Future(_), Val::Future(FutureAny(rep))) => {
648 concurrent::lower_future_to_index::<T>(*rep, cx, ty)?.linear_lower_to_memory(
649 cx,
650 InterfaceType::U32,
651 offset,
652 )
653 }
654 (InterfaceType::Future(_), _) => unexpected(ty, self),
655 (InterfaceType::Stream(_), Val::Stream(StreamAny(rep))) => {
656 concurrent::lower_stream_to_index::<T>(*rep, cx, ty)?.linear_lower_to_memory(
657 cx,
658 InterfaceType::U32,
659 offset,
660 )
661 }
662 (InterfaceType::Stream(_), _) => unexpected(ty, self),
663 (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
664 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory(
665 cx,
666 InterfaceType::U32,
667 offset,
668 )
669 }
670 (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
671 }
672 }
673
674 pub(crate) fn desc(&self) -> &'static str {
675 match self {
676 Val::Bool(_) => "bool",
677 Val::U8(_) => "u8",
678 Val::S8(_) => "s8",
679 Val::U16(_) => "u16",
680 Val::S16(_) => "s16",
681 Val::U32(_) => "u32",
682 Val::S32(_) => "s32",
683 Val::U64(_) => "u64",
684 Val::S64(_) => "s64",
685 Val::Float32(_) => "f32",
686 Val::Float64(_) => "f64",
687 Val::Char(_) => "char",
688 Val::List(_) => "list",
689 Val::String(_) => "string",
690 Val::Record(_) => "record",
691 Val::Enum(_) => "enum",
692 Val::Variant(..) => "variant",
693 Val::Tuple(_) => "tuple",
694 Val::Option(_) => "option",
695 Val::Result(_) => "result",
696 Val::Resource(_) => "resource",
697 Val::Flags(_) => "flags",
698 Val::Future(_) => "future",
699 Val::Stream(_) => "stream",
700 Val::ErrorContext(_) => "error-context",
701 }
702 }
703
704 #[cfg(feature = "wave")]
707 pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
708 Ok(wasm_wave::from_str(ty, s)?)
709 }
710
711 #[cfg(feature = "wave")]
713 pub fn to_wave(&self) -> Result<String> {
714 Ok(wasm_wave::to_string(self)?)
715 }
716}
717
718impl PartialEq for Val {
719 fn eq(&self, other: &Self) -> bool {
720 match (self, other) {
721 (Self::Float32(l), Self::Float32(r)) => {
727 (*l != 0.0 && l == r)
728 || (*l == 0.0 && l.to_bits() == r.to_bits())
729 || (l.is_nan() && r.is_nan())
730 }
731 (Self::Float32(_), _) => false,
732 (Self::Float64(l), Self::Float64(r)) => {
733 (*l != 0.0 && l == r)
734 || (*l == 0.0 && l.to_bits() == r.to_bits())
735 || (l.is_nan() && r.is_nan())
736 }
737 (Self::Float64(_), _) => false,
738
739 (Self::Bool(l), Self::Bool(r)) => l == r,
740 (Self::Bool(_), _) => false,
741 (Self::S8(l), Self::S8(r)) => l == r,
742 (Self::S8(_), _) => false,
743 (Self::U8(l), Self::U8(r)) => l == r,
744 (Self::U8(_), _) => false,
745 (Self::S16(l), Self::S16(r)) => l == r,
746 (Self::S16(_), _) => false,
747 (Self::U16(l), Self::U16(r)) => l == r,
748 (Self::U16(_), _) => false,
749 (Self::S32(l), Self::S32(r)) => l == r,
750 (Self::S32(_), _) => false,
751 (Self::U32(l), Self::U32(r)) => l == r,
752 (Self::U32(_), _) => false,
753 (Self::S64(l), Self::S64(r)) => l == r,
754 (Self::S64(_), _) => false,
755 (Self::U64(l), Self::U64(r)) => l == r,
756 (Self::U64(_), _) => false,
757 (Self::Char(l), Self::Char(r)) => l == r,
758 (Self::Char(_), _) => false,
759 (Self::String(l), Self::String(r)) => l == r,
760 (Self::String(_), _) => false,
761 (Self::List(l), Self::List(r)) => l == r,
762 (Self::List(_), _) => false,
763 (Self::Record(l), Self::Record(r)) => l == r,
764 (Self::Record(_), _) => false,
765 (Self::Tuple(l), Self::Tuple(r)) => l == r,
766 (Self::Tuple(_), _) => false,
767 (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
768 (Self::Variant(..), _) => false,
769 (Self::Enum(l), Self::Enum(r)) => l == r,
770 (Self::Enum(_), _) => false,
771 (Self::Option(l), Self::Option(r)) => l == r,
772 (Self::Option(_), _) => false,
773 (Self::Result(l), Self::Result(r)) => l == r,
774 (Self::Result(_), _) => false,
775 (Self::Flags(l), Self::Flags(r)) => l == r,
776 (Self::Flags(_), _) => false,
777 (Self::Resource(l), Self::Resource(r)) => l == r,
778 (Self::Resource(_), _) => false,
779 (Self::Future(l), Self::Future(r)) => l == r,
780 (Self::Future(_), _) => false,
781 (Self::Stream(l), Self::Stream(r)) => l == r,
782 (Self::Stream(_), _) => false,
783 (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r,
784 (Self::ErrorContext(_), _) => false,
785 }
786 }
787}
788
789impl Eq for Val {}
790
791struct GenericVariant<'a> {
792 discriminant: u32,
793 payload: Option<(&'a Val, InterfaceType)>,
794 abi: &'a CanonicalAbiInfo,
795 info: &'a VariantInfo,
796}
797
798impl GenericVariant<'_> {
799 fn result<'a>(
800 ty: &'a TypeResult,
801 r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
802 ) -> Result<GenericVariant<'a>> {
803 let (discriminant, payload) = match r {
804 Ok(val) => {
805 let payload = match (val, ty.ok) {
806 (Some(val), Some(ty)) => Some((&**val, ty)),
807 (None, None) => None,
808 (Some(_), None) => {
809 bail!("payload provided to `ok` but not expected");
810 }
811 (None, Some(_)) => {
812 bail!("payload expected to `ok` but not provided");
813 }
814 };
815 (0, payload)
816 }
817 Err(val) => {
818 let payload = match (val, ty.err) {
819 (Some(val), Some(ty)) => Some((&**val, ty)),
820 (None, None) => None,
821 (Some(_), None) => {
822 bail!("payload provided to `err` but not expected");
823 }
824 (None, Some(_)) => {
825 bail!("payload expected to `err` but not provided");
826 }
827 };
828 (1, payload)
829 }
830 };
831 Ok(GenericVariant {
832 discriminant,
833 payload,
834 abi: &ty.abi,
835 info: &ty.info,
836 })
837 }
838
839 fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
840 let (discriminant, payload) = match r {
841 None => (0, None),
842 Some(val) => (1, Some((&**val, ty.ty))),
843 };
844 GenericVariant {
845 discriminant,
846 payload,
847 abi: &ty.abi,
848 info: &ty.info,
849 }
850 }
851
852 fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
853 let discriminant = get_enum_discriminant(ty, discriminant)?;
854
855 Ok(GenericVariant {
856 discriminant,
857 payload: None,
858 abi: &ty.abi,
859 info: &ty.info,
860 })
861 }
862
863 fn variant<'a>(
864 ty: &'a TypeVariant,
865 discriminant_name: &str,
866 payload: &'a Option<Box<Val>>,
867 ) -> Result<GenericVariant<'a>> {
868 let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
869
870 let payload = match (payload, payload_ty) {
871 (Some(val), Some(ty)) => Some((&**val, *ty)),
872 (None, None) => None,
873 (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
874 (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
875 };
876
877 Ok(GenericVariant {
878 discriminant,
879 payload,
880 abi: &ty.abi,
881 info: &ty.info,
882 })
883 }
884
885 fn lower<T>(
886 &self,
887 cx: &mut LowerContext<'_, T>,
888 dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
889 ) -> Result<()> {
890 next_mut(dst).write(ValRaw::u32(self.discriminant));
891
892 let value_flat = match self.payload {
896 Some((value, ty)) => {
897 value.lower(cx, ty, dst)?;
898 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
899 }
900 None => 0,
901 };
902 let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
903 for _ in (1 + value_flat)..variant_flat {
904 next_mut(dst).write(ValRaw::u64(0));
905 }
906 Ok(())
907 }
908
909 fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
910 match self.info.size {
911 DiscriminantSize::Size1 => u8::try_from(self.discriminant)
912 .unwrap()
913 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?,
914 DiscriminantSize::Size2 => u16::try_from(self.discriminant)
915 .unwrap()
916 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?,
917 DiscriminantSize::Size4 => {
918 self.discriminant
919 .linear_lower_to_memory(cx, InterfaceType::U32, offset)?
920 }
921 }
922
923 if let Some((value, ty)) = self.payload {
924 let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
925 value.store(cx, ty, offset)?;
926 }
927
928 Ok(())
929 }
930}
931
932fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
933 let elem = cx.types[ty].element;
934 let abi = cx.types.canonical_abi(&elem);
935 let element_size = usize::try_from(abi.size32).unwrap();
936 let element_alignment = abi.align32;
937
938 match len
939 .checked_mul(element_size)
940 .and_then(|len| ptr.checked_add(len))
941 {
942 Some(n) if n <= cx.memory().len() => {}
943 _ => bail!("list pointer/length out of bounds of memory"),
944 }
945 if ptr % usize::try_from(element_alignment)? != 0 {
946 bail!("list pointer is not aligned")
947 }
948
949 Ok(Val::List(
950 (0..len)
951 .map(|index| {
952 Val::load(
953 cx,
954 elem,
955 &cx.memory()[ptr + (index * element_size)..][..element_size],
956 )
957 })
958 .collect::<Result<_>>()?,
959 ))
960}
961
962fn load_variant(
963 cx: &mut LiftContext<'_>,
964 info: &VariantInfo,
965 mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
966 bytes: &[u8],
967) -> Result<(u32, Option<Box<Val>>)> {
968 let discriminant = match info.size {
969 DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory(
970 cx,
971 InterfaceType::U8,
972 &bytes[..1],
973 )?),
974 DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory(
975 cx,
976 InterfaceType::U16,
977 &bytes[..2],
978 )?),
979 DiscriminantSize::Size4 => {
980 u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])?
981 }
982 };
983 let case_ty = types.nth(discriminant as usize).ok_or_else(|| {
984 anyhow!(
985 "discriminant {} out of range [0..{})",
986 discriminant,
987 types.len()
988 )
989 })?;
990 let value = match case_ty {
991 Some(case_ty) => {
992 let payload_offset = usize::try_from(info.payload_offset32).unwrap();
993 let case_abi = cx.types.canonical_abi(&case_ty);
994 let case_size = usize::try_from(case_abi.size32).unwrap();
995 Some(Box::new(Val::load(
996 cx,
997 case_ty,
998 &bytes[payload_offset..][..case_size],
999 )?))
1000 }
1001 None => None,
1002 };
1003 Ok((discriminant, value))
1004}
1005
1006fn lift_variant(
1007 cx: &mut LiftContext<'_>,
1008 flatten_count: usize,
1009 mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1010 src: &mut Iter<'_, ValRaw>,
1011) -> Result<(u32, Option<Box<Val>>)> {
1012 let len = types.len();
1013 let discriminant = next(src).get_u32();
1014 let ty = types
1015 .nth(discriminant as usize)
1016 .ok_or_else(|| anyhow!("discriminant {} out of range [0..{})", discriminant, len))?;
1017 let (value, value_flat) = match ty {
1018 Some(ty) => (
1019 Some(Box::new(Val::lift(cx, ty, src)?)),
1020 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1021 ),
1022 None => (None, 0),
1023 };
1024 for _ in (1 + value_flat)..flatten_count {
1025 next(src);
1026 }
1027 Ok((discriminant, value))
1028}
1029
1030fn lower_list<T>(
1032 cx: &mut LowerContext<'_, T>,
1033 element_type: InterfaceType,
1034 items: &[Val],
1035) -> Result<(usize, usize)> {
1036 let abi = cx.types.canonical_abi(&element_type);
1037 let elt_size = usize::try_from(abi.size32)?;
1038 let elt_align = abi.align32;
1039 let size = items
1040 .len()
1041 .checked_mul(elt_size)
1042 .ok_or_else(|| anyhow::anyhow!("size overflow copying a list"))?;
1043 let ptr = cx.realloc(0, 0, elt_align, size)?;
1044 let mut element_ptr = ptr;
1045 for item in items {
1046 item.store(cx, element_type, element_ptr)?;
1047 element_ptr += elt_size;
1048 }
1049 Ok((ptr, items.len()))
1050}
1051
1052fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1053 while bits > 0 {
1054 if bits & 1 != 0 {
1055 flags.push(ty.names[offset as usize].clone());
1056 }
1057 bits >>= 1;
1058 offset += 1;
1059 }
1060}
1061
1062fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
1063 let mut storage = match FlagsSize::from_count(ty.names.len()) {
1064 FlagsSize::Size0 => Vec::new(),
1065 FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
1066 FlagsSize::Size4Plus(n) => vec![0; n.into()],
1067 };
1068
1069 for flag in flags {
1070 let bit = ty
1071 .names
1072 .get_index_of(flag)
1073 .ok_or_else(|| anyhow::anyhow!("unknown flag: `{flag}`"))?;
1074 storage[bit / 32] |= 1 << (bit % 32);
1075 }
1076 Ok(storage)
1077}
1078
1079fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
1080 ty.names
1081 .get_index_of(n)
1082 .ok_or_else(|| anyhow::anyhow!("enum variant name `{n}` is not valid"))
1083 .map(|i| i.try_into().unwrap())
1084}
1085
1086fn get_variant_discriminant<'a>(
1087 ty: &'a TypeVariant,
1088 name: &str,
1089) -> Result<(u32, &'a Option<InterfaceType>)> {
1090 let (i, _, ty) = ty
1091 .cases
1092 .get_full(name)
1093 .ok_or_else(|| anyhow::anyhow!("unknown variant case: `{name}`"))?;
1094 Ok((i.try_into().unwrap(), ty))
1095}
1096
1097fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1098 src.next().unwrap()
1099}
1100
1101fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1102 dst.next().unwrap()
1103}
1104
1105#[cold]
1106fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
1107 bail!(
1108 "type mismatch: expected {}, found {}",
1109 desc(&ty),
1110 val.desc()
1111 )
1112}
1113
1114#[derive(Debug, Clone, PartialEq, Eq)]
1124pub struct FutureAny(pub(crate) u32);
1125
1126#[derive(Debug, Clone, PartialEq, Eq)]
1136pub struct StreamAny(pub(crate) u32);
1137
1138#[derive(Debug, Clone, PartialEq, Eq)]
1146pub struct ErrorContextAny(pub(crate) u32);