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