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