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