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