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