1 use crate::ValRaw; 2 use crate::component::ResourceAny; 3 use crate::component::concurrent::{self, ErrorContext, FutureAny, StreamAny}; 4 use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc}; 5 use crate::prelude::*; 6 use core::mem::MaybeUninit; 7 use core::slice::{Iter, IterMut}; 8 use wasmtime_component_util::{DiscriminantSize, FlagsSize}; 9 use wasmtime_environ::component::{ 10 CanonicalAbiInfo, InterfaceType, TypeEnum, TypeFlags, TypeListIndex, TypeMap, TypeMapIndex, 11 TypeOption, TypeResult, TypeVariant, VariantInfo, 12 }; 13 14 /// Represents possible runtime values which a component function can either 15 /// consume or produce 16 /// 17 /// This is a dynamic representation of possible values in the component model. 18 /// Note that this is not an efficient representation but is instead intended to 19 /// be a flexible and somewhat convenient representation. The most efficient 20 /// representation of component model types is to use the `bindgen!` macro to 21 /// generate native Rust types with specialized liftings and lowerings. 22 /// 23 /// This type is used in conjunction with [`Func::call`] for example if the 24 /// signature of a component is not statically known ahead of time. 25 /// 26 /// # Equality and `Val` 27 /// 28 /// This type implements both the Rust `PartialEq` and `Eq` traits. This type 29 /// additionally contains values which are not necessarily easily equated, 30 /// however, such as floats (`Float32` and `Float64`) and resources. Equality 31 /// does require that two values have the same type, and then these cases are 32 /// handled as: 33 /// 34 /// * Floats are tested if they are "semantically the same" meaning all NaN 35 /// values are equal to all other NaN values. Additionally zero values must be 36 /// exactly the same, so positive zero is not equal to negative zero. The 37 /// primary use case at this time is fuzzing-related equality which this is 38 /// sufficient for. 39 /// 40 /// * Resources are tested if their types and indices into the host table are 41 /// equal. This does not compare the underlying representation so borrows of 42 /// the same guest resource are not considered equal. This additionally 43 /// doesn't go further and test for equality in the guest itself (for example 44 /// two different heap allocations of `Box<u32>` can be equal in normal Rust 45 /// if they contain the same value, but will never be considered equal when 46 /// compared as `Val::Resource`s). 47 /// 48 /// In general if a strict guarantee about equality is required here it's 49 /// recommended to "build your own" as this equality intended for fuzzing 50 /// Wasmtime may not be suitable for you. 51 /// 52 /// # Component model types and `Val` 53 /// 54 /// The `Val` type here does not contain enough information to say what the 55 /// component model type of a `Val` is. This is instead more of an AST of sorts. 56 /// For example the `Val::Enum` only carries information about a single 57 /// discriminant, not the entire enumeration or what it's a discriminant of. 58 /// 59 /// This means that when a `Val` is passed to Wasmtime, for example as a 60 /// function parameter when calling a function or as a return value from an 61 /// host-defined imported function, then it must pass a type-check. Instances of 62 /// `Val` are type-checked against what's required by the component itself. 63 /// 64 /// [`Func::call`]: crate::component::Func::call 65 #[derive(Debug, Clone)] 66 #[expect(missing_docs, reason = "self-describing variants")] 67 pub 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 /// A map type represented as a list of key-value pairs. 83 /// Duplicate keys are allowed and follow "last value wins" semantics. 84 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 } 97 98 impl Val { 99 /// Deserialize a value of this type from core Wasm stack values. 100 pub(crate) fn lift( 101 cx: &mut LiftContext<'_>, 102 ty: InterfaceType, 103 src: &mut Iter<'_, ValRaw>, 104 ) -> Result<Val> { 105 Ok(match ty { 106 InterfaceType::Bool => Val::Bool(bool::linear_lift_from_flat(cx, ty, next(src))?), 107 InterfaceType::S8 => Val::S8(i8::linear_lift_from_flat(cx, ty, next(src))?), 108 InterfaceType::U8 => Val::U8(u8::linear_lift_from_flat(cx, ty, next(src))?), 109 InterfaceType::S16 => Val::S16(i16::linear_lift_from_flat(cx, ty, next(src))?), 110 InterfaceType::U16 => Val::U16(u16::linear_lift_from_flat(cx, ty, next(src))?), 111 InterfaceType::S32 => Val::S32(i32::linear_lift_from_flat(cx, ty, next(src))?), 112 InterfaceType::U32 => Val::U32(u32::linear_lift_from_flat(cx, ty, next(src))?), 113 InterfaceType::S64 => Val::S64(i64::linear_lift_from_flat(cx, ty, next(src))?), 114 InterfaceType::U64 => Val::U64(u64::linear_lift_from_flat(cx, ty, next(src))?), 115 InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_flat(cx, ty, next(src))?), 116 InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_flat(cx, ty, next(src))?), 117 InterfaceType::Char => Val::Char(char::linear_lift_from_flat(cx, ty, next(src))?), 118 InterfaceType::Own(_) | InterfaceType::Borrow(_) => { 119 Val::Resource(ResourceAny::linear_lift_from_flat(cx, ty, next(src))?) 120 } 121 InterfaceType::String => Val::String(<_>::linear_lift_from_flat( 122 cx, 123 ty, 124 &[*next(src), *next(src)], 125 )?), 126 InterfaceType::List(i) => { 127 // FIXME(#4311): needs memory64 treatment 128 let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize; 129 let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize; 130 load_list(cx, i, ptr, len)? 131 } 132 InterfaceType::Map(i) => { 133 // FIXME(#4311): needs memory64 treatment 134 // Maps are represented as list<tuple<k, v>> in canonical ABI 135 let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize; 136 let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize; 137 load_map(cx, i, ptr, len)? 138 } 139 InterfaceType::Record(i) => Val::Record( 140 cx.types[i] 141 .fields 142 .iter() 143 .map(|field| { 144 let val = Self::lift(cx, field.ty, src)?; 145 Ok((field.name.to_string(), val)) 146 }) 147 .collect::<Result<_>>()?, 148 ), 149 InterfaceType::Tuple(i) => Val::Tuple( 150 cx.types[i] 151 .types 152 .iter() 153 .map(|ty| Self::lift(cx, *ty, src)) 154 .collect::<Result<_>>()?, 155 ), 156 InterfaceType::Variant(i) => { 157 let vty = &cx.types[i]; 158 let (discriminant, value) = lift_variant( 159 cx, 160 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(), 161 vty.cases.values().copied(), 162 src, 163 )?; 164 165 let (k, _) = vty.cases.get_index(discriminant as usize).unwrap(); 166 Val::Variant(k.clone(), value) 167 } 168 InterfaceType::Enum(i) => { 169 let ety = &cx.types[i]; 170 let (discriminant, _) = lift_variant( 171 cx, 172 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(), 173 ety.names.iter().map(|_| None), 174 src, 175 )?; 176 177 Val::Enum(ety.names[discriminant as usize].clone()) 178 } 179 InterfaceType::Option(i) => { 180 let (_discriminant, value) = lift_variant( 181 cx, 182 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(), 183 [None, Some(cx.types[i].ty)].into_iter(), 184 src, 185 )?; 186 187 Val::Option(value) 188 } 189 InterfaceType::Result(i) => { 190 let result_ty = &cx.types[i]; 191 let (discriminant, value) = lift_variant( 192 cx, 193 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(), 194 [result_ty.ok, result_ty.err].into_iter(), 195 src, 196 )?; 197 198 Val::Result(if discriminant == 0 { 199 Ok(value) 200 } else { 201 Err(value) 202 }) 203 } 204 InterfaceType::Flags(i) => { 205 let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(); 206 let ty = &cx.types[i]; 207 let mut flags = Vec::new(); 208 for i in 0..u32::try_from(u32_count).unwrap() { 209 push_flags( 210 ty, 211 &mut flags, 212 i * 32, 213 u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))?, 214 ); 215 } 216 217 Val::Flags(flags) 218 } 219 InterfaceType::Future(_) => { 220 Val::Future(FutureAny::linear_lift_from_flat(cx, ty, next(src))?) 221 } 222 InterfaceType::Stream(_) => { 223 Val::Stream(StreamAny::linear_lift_from_flat(cx, ty, next(src))?) 224 } 225 InterfaceType::ErrorContext(_) => { 226 ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val() 227 } 228 InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279) 229 }) 230 } 231 232 /// Deserialize a value of this type from the heap. 233 pub(crate) fn load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val> { 234 Ok(match ty { 235 InterfaceType::Bool => Val::Bool(bool::linear_lift_from_memory(cx, ty, bytes)?), 236 InterfaceType::S8 => Val::S8(i8::linear_lift_from_memory(cx, ty, bytes)?), 237 InterfaceType::U8 => Val::U8(u8::linear_lift_from_memory(cx, ty, bytes)?), 238 InterfaceType::S16 => Val::S16(i16::linear_lift_from_memory(cx, ty, bytes)?), 239 InterfaceType::U16 => Val::U16(u16::linear_lift_from_memory(cx, ty, bytes)?), 240 InterfaceType::S32 => Val::S32(i32::linear_lift_from_memory(cx, ty, bytes)?), 241 InterfaceType::U32 => Val::U32(u32::linear_lift_from_memory(cx, ty, bytes)?), 242 InterfaceType::S64 => Val::S64(i64::linear_lift_from_memory(cx, ty, bytes)?), 243 InterfaceType::U64 => Val::U64(u64::linear_lift_from_memory(cx, ty, bytes)?), 244 InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_memory(cx, ty, bytes)?), 245 InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_memory(cx, ty, bytes)?), 246 InterfaceType::Char => Val::Char(char::linear_lift_from_memory(cx, ty, bytes)?), 247 InterfaceType::String => Val::String(<_>::linear_lift_from_memory(cx, ty, bytes)?), 248 InterfaceType::Own(_) | InterfaceType::Borrow(_) => { 249 Val::Resource(ResourceAny::linear_lift_from_memory(cx, ty, bytes)?) 250 } 251 InterfaceType::List(i) => { 252 // FIXME(#4311): needs memory64 treatment 253 let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize; 254 let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize; 255 load_list(cx, i, ptr, len)? 256 } 257 InterfaceType::Map(i) => { 258 // FIXME(#4311): needs memory64 treatment 259 let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize; 260 let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize; 261 load_map(cx, i, ptr, len)? 262 } 263 264 InterfaceType::Record(i) => { 265 let mut offset = 0; 266 let fields = cx.types[i].fields.iter(); 267 Val::Record( 268 fields 269 .map(|field| -> Result<(String, Val)> { 270 let abi = cx.types.canonical_abi(&field.ty); 271 let offset = abi.next_field32(&mut offset); 272 let offset = usize::try_from(offset).unwrap(); 273 let size = usize::try_from(abi.size32).unwrap(); 274 Ok(( 275 field.name.to_string(), 276 Val::load(cx, field.ty, &bytes[offset..][..size])?, 277 )) 278 }) 279 .collect::<Result<_>>()?, 280 ) 281 } 282 InterfaceType::Tuple(i) => { 283 let types = cx.types[i].types.iter().copied(); 284 let mut offset = 0; 285 Val::Tuple( 286 types 287 .map(|ty| { 288 let abi = cx.types.canonical_abi(&ty); 289 let offset = abi.next_field32(&mut offset); 290 let offset = usize::try_from(offset).unwrap(); 291 let size = usize::try_from(abi.size32).unwrap(); 292 Val::load(cx, ty, &bytes[offset..][..size]) 293 }) 294 .collect::<Result<_>>()?, 295 ) 296 } 297 InterfaceType::Variant(i) => { 298 let ty = &cx.types[i]; 299 let (discriminant, value) = 300 load_variant(cx, &ty.info, ty.cases.values().copied(), bytes)?; 301 302 let (k, _) = ty.cases.get_index(discriminant as usize).unwrap(); 303 Val::Variant(k.clone(), value) 304 } 305 InterfaceType::Enum(i) => { 306 let ty = &cx.types[i]; 307 let (discriminant, _) = 308 load_variant(cx, &ty.info, ty.names.iter().map(|_| None), bytes)?; 309 310 Val::Enum(ty.names[discriminant as usize].clone()) 311 } 312 InterfaceType::Option(i) => { 313 let ty = &cx.types[i]; 314 let (_discriminant, value) = 315 load_variant(cx, &ty.info, [None, Some(ty.ty)].into_iter(), bytes)?; 316 317 Val::Option(value) 318 } 319 InterfaceType::Result(i) => { 320 let ty = &cx.types[i]; 321 let (discriminant, value) = 322 load_variant(cx, &ty.info, [ty.ok, ty.err].into_iter(), bytes)?; 323 324 Val::Result(if discriminant == 0 { 325 Ok(value) 326 } else { 327 Err(value) 328 }) 329 } 330 InterfaceType::Flags(i) => { 331 let ty = &cx.types[i]; 332 let mut flags = Vec::new(); 333 match FlagsSize::from_count(ty.names.len()) { 334 FlagsSize::Size0 => {} 335 FlagsSize::Size1 => { 336 let bits = u8::linear_lift_from_memory(cx, InterfaceType::U8, bytes)?; 337 push_flags(ty, &mut flags, 0, u32::from(bits)); 338 } 339 FlagsSize::Size2 => { 340 let bits = u16::linear_lift_from_memory(cx, InterfaceType::U16, bytes)?; 341 push_flags(ty, &mut flags, 0, u32::from(bits)); 342 } 343 FlagsSize::Size4Plus(n) => { 344 for i in 0..n { 345 let bits = u32::linear_lift_from_memory( 346 cx, 347 InterfaceType::U32, 348 &bytes[usize::from(i) * 4..][..4], 349 )?; 350 push_flags(ty, &mut flags, u32::from(i) * 32, bits); 351 } 352 } 353 } 354 Val::Flags(flags) 355 } 356 InterfaceType::Future(_) => FutureAny::linear_lift_from_memory(cx, ty, bytes)?.into(), 357 InterfaceType::Stream(_) => StreamAny::linear_lift_from_memory(cx, ty, bytes)?.into(), 358 InterfaceType::ErrorContext(_) => { 359 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val() 360 } 361 InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279) 362 }) 363 } 364 365 /// Serialize this value as core Wasm stack values. 366 pub(crate) fn lower<T>( 367 &self, 368 cx: &mut LowerContext<'_, T>, 369 ty: InterfaceType, 370 dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, 371 ) -> Result<()> { 372 match (ty, self) { 373 (InterfaceType::Bool, Val::Bool(value)) => { 374 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 375 } 376 (InterfaceType::Bool, _) => unexpected(ty, self), 377 (InterfaceType::S8, Val::S8(value)) => { 378 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 379 } 380 (InterfaceType::S8, _) => unexpected(ty, self), 381 (InterfaceType::U8, Val::U8(value)) => { 382 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 383 } 384 (InterfaceType::U8, _) => unexpected(ty, self), 385 (InterfaceType::S16, Val::S16(value)) => { 386 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 387 } 388 (InterfaceType::S16, _) => unexpected(ty, self), 389 (InterfaceType::U16, Val::U16(value)) => { 390 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 391 } 392 (InterfaceType::U16, _) => unexpected(ty, self), 393 (InterfaceType::S32, Val::S32(value)) => { 394 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 395 } 396 (InterfaceType::S32, _) => unexpected(ty, self), 397 (InterfaceType::U32, Val::U32(value)) => { 398 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 399 } 400 (InterfaceType::U32, _) => unexpected(ty, self), 401 (InterfaceType::S64, Val::S64(value)) => { 402 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 403 } 404 (InterfaceType::S64, _) => unexpected(ty, self), 405 (InterfaceType::U64, Val::U64(value)) => { 406 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 407 } 408 (InterfaceType::U64, _) => unexpected(ty, self), 409 (InterfaceType::Float32, Val::Float32(value)) => { 410 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 411 } 412 (InterfaceType::Float32, _) => unexpected(ty, self), 413 (InterfaceType::Float64, Val::Float64(value)) => { 414 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 415 } 416 (InterfaceType::Float64, _) => unexpected(ty, self), 417 (InterfaceType::Char, Val::Char(value)) => { 418 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 419 } 420 (InterfaceType::Char, _) => unexpected(ty, self), 421 // NB: `lower` on `ResourceAny` does its own type-checking, so skip 422 // looking at it here. 423 (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => { 424 value.linear_lower_to_flat(cx, ty, next_mut(dst)) 425 } 426 (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self), 427 (InterfaceType::String, Val::String(value)) => { 428 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit(); 429 value.linear_lower_to_flat(cx, ty, my_dst)?; 430 let my_dst = unsafe { my_dst.assume_init() }; 431 next_mut(dst).write(my_dst[0]); 432 next_mut(dst).write(my_dst[1]); 433 Ok(()) 434 } 435 (InterfaceType::String, _) => unexpected(ty, self), 436 (InterfaceType::List(ty), Val::List(values)) => { 437 let ty = &cx.types[ty]; 438 let (ptr, len) = lower_list(cx, ty.element, values)?; 439 next_mut(dst).write(ValRaw::i64(ptr as i64)); 440 next_mut(dst).write(ValRaw::i64(len as i64)); 441 Ok(()) 442 } 443 (InterfaceType::List(_), _) => unexpected(ty, self), 444 (InterfaceType::Map(ty), Val::Map(pairs)) => { 445 let map_ty = &cx.types[ty]; 446 let (ptr, len) = lower_map(cx, map_ty, pairs)?; 447 next_mut(dst).write(ValRaw::i64(ptr as i64)); 448 next_mut(dst).write(ValRaw::i64(len as i64)); 449 Ok(()) 450 } 451 (InterfaceType::Map(_), _) => unexpected(ty, self), 452 (InterfaceType::Record(ty), Val::Record(values)) => { 453 let ty = &cx.types[ty]; 454 if ty.fields.len() != values.len() { 455 bail!("expected {} fields, got {}", ty.fields.len(), values.len()); 456 } 457 for ((name, value), field) in values.iter().zip(ty.fields.iter()) { 458 if *name != field.name { 459 bail!("expected field `{}`, got `{name}`", field.name); 460 } 461 value.lower(cx, field.ty, dst)?; 462 } 463 Ok(()) 464 } 465 (InterfaceType::Record(_), _) => unexpected(ty, self), 466 (InterfaceType::Tuple(ty), Val::Tuple(values)) => { 467 let ty = &cx.types[ty]; 468 if ty.types.len() != values.len() { 469 bail!("expected {} types, got {}", ty.types.len(), values.len()); 470 } 471 for (value, ty) in values.iter().zip(ty.types.iter()) { 472 value.lower(cx, *ty, dst)?; 473 } 474 Ok(()) 475 } 476 (InterfaceType::Tuple(_), _) => unexpected(ty, self), 477 (InterfaceType::Variant(ty), Val::Variant(n, v)) => { 478 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst) 479 } 480 (InterfaceType::Variant(_), _) => unexpected(ty, self), 481 (InterfaceType::Option(ty), Val::Option(v)) => { 482 GenericVariant::option(&cx.types[ty], v).lower(cx, dst) 483 } 484 (InterfaceType::Option(_), _) => unexpected(ty, self), 485 (InterfaceType::Result(ty), Val::Result(v)) => { 486 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst) 487 } 488 (InterfaceType::Result(_), _) => unexpected(ty, self), 489 (InterfaceType::Enum(ty), Val::Enum(discriminant)) => { 490 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?; 491 next_mut(dst).write(ValRaw::u32(discriminant)); 492 Ok(()) 493 } 494 (InterfaceType::Enum(_), _) => unexpected(ty, self), 495 (InterfaceType::Flags(ty), Val::Flags(value)) => { 496 let ty = &cx.types[ty]; 497 let storage = flags_to_storage(ty, value)?; 498 for value in storage { 499 next_mut(dst).write(ValRaw::u32(value)); 500 } 501 Ok(()) 502 } 503 (InterfaceType::Flags(_), _) => unexpected(ty, self), 504 (InterfaceType::Future(_), Val::Future(f)) => { 505 f.linear_lower_to_flat(cx, ty, next_mut(dst)) 506 } 507 (InterfaceType::Future(_), _) => unexpected(ty, self), 508 (InterfaceType::Stream(_), Val::Stream(s)) => { 509 s.linear_lower_to_flat(cx, ty, next_mut(dst)) 510 } 511 (InterfaceType::Stream(_), _) => unexpected(ty, self), 512 (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => { 513 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat( 514 cx, 515 InterfaceType::U32, 516 next_mut(dst), 517 ) 518 } 519 (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), 520 (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279) 521 } 522 } 523 524 /// Serialize this value to the heap at the specified memory location. 525 pub(crate) fn store<T>( 526 &self, 527 cx: &mut LowerContext<'_, T>, 528 ty: InterfaceType, 529 offset: usize, 530 ) -> Result<()> { 531 debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0); 532 533 match (ty, self) { 534 (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset), 535 (InterfaceType::Bool, _) => unexpected(ty, self), 536 (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset), 537 (InterfaceType::U8, _) => unexpected(ty, self), 538 (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset), 539 (InterfaceType::S8, _) => unexpected(ty, self), 540 (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset), 541 (InterfaceType::U16, _) => unexpected(ty, self), 542 (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset), 543 (InterfaceType::S16, _) => unexpected(ty, self), 544 (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset), 545 (InterfaceType::U32, _) => unexpected(ty, self), 546 (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset), 547 (InterfaceType::S32, _) => unexpected(ty, self), 548 (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset), 549 (InterfaceType::U64, _) => unexpected(ty, self), 550 (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset), 551 (InterfaceType::S64, _) => unexpected(ty, self), 552 (InterfaceType::Float32, Val::Float32(value)) => { 553 value.linear_lower_to_memory(cx, ty, offset) 554 } 555 (InterfaceType::Float32, _) => unexpected(ty, self), 556 (InterfaceType::Float64, Val::Float64(value)) => { 557 value.linear_lower_to_memory(cx, ty, offset) 558 } 559 (InterfaceType::Float64, _) => unexpected(ty, self), 560 (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset), 561 (InterfaceType::Char, _) => unexpected(ty, self), 562 (InterfaceType::String, Val::String(value)) => { 563 value.linear_lower_to_memory(cx, ty, offset) 564 } 565 (InterfaceType::String, _) => unexpected(ty, self), 566 567 // NB: resources do type-checking when they lower. 568 (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => { 569 value.linear_lower_to_memory(cx, ty, offset) 570 } 571 (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self), 572 (InterfaceType::List(ty), Val::List(values)) => { 573 let ty = &cx.types[ty]; 574 let (ptr, len) = lower_list(cx, ty.element, values)?; 575 // FIXME(#4311): needs memory64 handling 576 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes(); 577 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes(); 578 Ok(()) 579 } 580 (InterfaceType::List(_), _) => unexpected(ty, self), 581 (InterfaceType::Map(ty_idx), Val::Map(values)) => { 582 let map_ty = &cx.types[ty_idx]; 583 let (ptr, len) = lower_map(cx, map_ty, values)?; 584 // FIXME(#4311): needs memory64 handling 585 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes(); 586 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes(); 587 Ok(()) 588 } 589 (InterfaceType::Map(_), _) => unexpected(ty, self), 590 (InterfaceType::Record(ty), Val::Record(values)) => { 591 let ty = &cx.types[ty]; 592 if ty.fields.len() != values.len() { 593 bail!("expected {} fields, got {}", ty.fields.len(), values.len()); 594 } 595 let mut offset = offset; 596 for ((name, value), field) in values.iter().zip(ty.fields.iter()) { 597 if *name != field.name { 598 bail!("expected field `{}`, got `{name}`", field.name); 599 } 600 value.store( 601 cx, 602 field.ty, 603 cx.types 604 .canonical_abi(&field.ty) 605 .next_field32_size(&mut offset), 606 )?; 607 } 608 Ok(()) 609 } 610 (InterfaceType::Record(_), _) => unexpected(ty, self), 611 (InterfaceType::Tuple(ty), Val::Tuple(values)) => { 612 let ty = &cx.types[ty]; 613 if ty.types.len() != values.len() { 614 bail!("expected {} types, got {}", ty.types.len(), values.len()); 615 } 616 let mut offset = offset; 617 for (value, ty) in values.iter().zip(ty.types.iter()) { 618 value.store( 619 cx, 620 *ty, 621 cx.types.canonical_abi(ty).next_field32_size(&mut offset), 622 )?; 623 } 624 Ok(()) 625 } 626 (InterfaceType::Tuple(_), _) => unexpected(ty, self), 627 628 (InterfaceType::Variant(ty), Val::Variant(n, v)) => { 629 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset) 630 } 631 (InterfaceType::Variant(_), _) => unexpected(ty, self), 632 (InterfaceType::Enum(ty), Val::Enum(v)) => { 633 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset) 634 } 635 (InterfaceType::Enum(_), _) => unexpected(ty, self), 636 (InterfaceType::Option(ty), Val::Option(v)) => { 637 GenericVariant::option(&cx.types[ty], v).store(cx, offset) 638 } 639 (InterfaceType::Option(_), _) => unexpected(ty, self), 640 (InterfaceType::Result(ty), Val::Result(v)) => { 641 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset) 642 } 643 (InterfaceType::Result(_), _) => unexpected(ty, self), 644 645 (InterfaceType::Flags(ty), Val::Flags(flags)) => { 646 let ty = &cx.types[ty]; 647 let storage = flags_to_storage(ty, flags)?; 648 match FlagsSize::from_count(ty.names.len()) { 649 FlagsSize::Size0 => {} 650 FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory( 651 cx, 652 InterfaceType::U8, 653 offset, 654 )?, 655 FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory( 656 cx, 657 InterfaceType::U16, 658 offset, 659 )?, 660 FlagsSize::Size4Plus(_) => { 661 let mut offset = offset; 662 for value in storage { 663 value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?; 664 offset += 4; 665 } 666 } 667 } 668 Ok(()) 669 } 670 (InterfaceType::Flags(_), _) => unexpected(ty, self), 671 (InterfaceType::Future(_), Val::Future(f)) => f.linear_lower_to_memory(cx, ty, offset), 672 (InterfaceType::Future(_), _) => unexpected(ty, self), 673 (InterfaceType::Stream(_), Val::Stream(s)) => s.linear_lower_to_memory(cx, ty, offset), 674 (InterfaceType::Stream(_), _) => unexpected(ty, self), 675 (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => { 676 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory( 677 cx, 678 InterfaceType::U32, 679 offset, 680 ) 681 } 682 (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), 683 (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279) 684 } 685 } 686 687 pub(crate) fn desc(&self) -> &'static str { 688 match self { 689 Val::Bool(_) => "bool", 690 Val::U8(_) => "u8", 691 Val::S8(_) => "s8", 692 Val::U16(_) => "u16", 693 Val::S16(_) => "s16", 694 Val::U32(_) => "u32", 695 Val::S32(_) => "s32", 696 Val::U64(_) => "u64", 697 Val::S64(_) => "s64", 698 Val::Float32(_) => "f32", 699 Val::Float64(_) => "f64", 700 Val::Char(_) => "char", 701 Val::List(_) => "list", 702 Val::Map(_) => "map", 703 Val::String(_) => "string", 704 Val::Record(_) => "record", 705 Val::Enum(_) => "enum", 706 Val::Variant(..) => "variant", 707 Val::Tuple(_) => "tuple", 708 Val::Option(_) => "option", 709 Val::Result(_) => "result", 710 Val::Resource(_) => "resource", 711 Val::Flags(_) => "flags", 712 Val::Future(_) => "future", 713 Val::Stream(_) => "stream", 714 Val::ErrorContext(_) => "error-context", 715 } 716 } 717 718 /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization 719 /// requires a target [`crate::component::Type`]. 720 #[cfg(feature = "wave")] 721 pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> { 722 Ok(wasm_wave::from_str(ty, s)?) 723 } 724 725 /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding. 726 #[cfg(feature = "wave")] 727 pub fn to_wave(&self) -> Result<String> { 728 Ok(wasm_wave::to_string(self)?) 729 } 730 } 731 732 impl PartialEq for Val { 733 fn eq(&self, other: &Self) -> bool { 734 match (self, other) { 735 // IEEE 754 equality considers NaN inequal to NaN and negative zero 736 // equal to positive zero, however we do the opposite here, because 737 // this logic is used by testing and fuzzing, which want to know 738 // whether two values are semantically the same, rather than 739 // numerically equal. 740 (Self::Float32(l), Self::Float32(r)) => { 741 (*l != 0.0 && l == r) 742 || (*l == 0.0 && l.to_bits() == r.to_bits()) 743 || (l.is_nan() && r.is_nan()) 744 } 745 (Self::Float32(_), _) => false, 746 (Self::Float64(l), Self::Float64(r)) => { 747 (*l != 0.0 && l == r) 748 || (*l == 0.0 && l.to_bits() == r.to_bits()) 749 || (l.is_nan() && r.is_nan()) 750 } 751 (Self::Float64(_), _) => false, 752 753 (Self::Bool(l), Self::Bool(r)) => l == r, 754 (Self::Bool(_), _) => false, 755 (Self::S8(l), Self::S8(r)) => l == r, 756 (Self::S8(_), _) => false, 757 (Self::U8(l), Self::U8(r)) => l == r, 758 (Self::U8(_), _) => false, 759 (Self::S16(l), Self::S16(r)) => l == r, 760 (Self::S16(_), _) => false, 761 (Self::U16(l), Self::U16(r)) => l == r, 762 (Self::U16(_), _) => false, 763 (Self::S32(l), Self::S32(r)) => l == r, 764 (Self::S32(_), _) => false, 765 (Self::U32(l), Self::U32(r)) => l == r, 766 (Self::U32(_), _) => false, 767 (Self::S64(l), Self::S64(r)) => l == r, 768 (Self::S64(_), _) => false, 769 (Self::U64(l), Self::U64(r)) => l == r, 770 (Self::U64(_), _) => false, 771 (Self::Char(l), Self::Char(r)) => l == r, 772 (Self::Char(_), _) => false, 773 (Self::String(l), Self::String(r)) => l == r, 774 (Self::String(_), _) => false, 775 (Self::List(l), Self::List(r)) => l == r, 776 (Self::List(_), _) => false, 777 (Self::Map(l), Self::Map(r)) => l == r, 778 (Self::Map(_), _) => false, 779 (Self::Record(l), Self::Record(r)) => l == r, 780 (Self::Record(_), _) => false, 781 (Self::Tuple(l), Self::Tuple(r)) => l == r, 782 (Self::Tuple(_), _) => false, 783 (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv, 784 (Self::Variant(..), _) => false, 785 (Self::Enum(l), Self::Enum(r)) => l == r, 786 (Self::Enum(_), _) => false, 787 (Self::Option(l), Self::Option(r)) => l == r, 788 (Self::Option(_), _) => false, 789 (Self::Result(l), Self::Result(r)) => l == r, 790 (Self::Result(_), _) => false, 791 (Self::Flags(l), Self::Flags(r)) => l == r, 792 (Self::Flags(_), _) => false, 793 (Self::Resource(l), Self::Resource(r)) => l == r, 794 (Self::Resource(_), _) => false, 795 (Self::Future(l), Self::Future(r)) => l == r, 796 (Self::Future(_), _) => false, 797 (Self::Stream(l), Self::Stream(r)) => l == r, 798 (Self::Stream(_), _) => false, 799 (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r, 800 (Self::ErrorContext(_), _) => false, 801 } 802 } 803 } 804 805 impl Eq for Val {} 806 807 struct GenericVariant<'a> { 808 discriminant: u32, 809 payload: Option<(&'a Val, InterfaceType)>, 810 abi: &'a CanonicalAbiInfo, 811 info: &'a VariantInfo, 812 } 813 814 impl GenericVariant<'_> { 815 fn result<'a>( 816 ty: &'a TypeResult, 817 r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>, 818 ) -> Result<GenericVariant<'a>> { 819 let (discriminant, payload) = match r { 820 Ok(val) => { 821 let payload = match (val, ty.ok) { 822 (Some(val), Some(ty)) => Some((&**val, ty)), 823 (None, None) => None, 824 (Some(_), None) => { 825 bail!("payload provided to `ok` but not expected"); 826 } 827 (None, Some(_)) => { 828 bail!("payload expected to `ok` but not provided"); 829 } 830 }; 831 (0, payload) 832 } 833 Err(val) => { 834 let payload = match (val, ty.err) { 835 (Some(val), Some(ty)) => Some((&**val, ty)), 836 (None, None) => None, 837 (Some(_), None) => { 838 bail!("payload provided to `err` but not expected"); 839 } 840 (None, Some(_)) => { 841 bail!("payload expected to `err` but not provided"); 842 } 843 }; 844 (1, payload) 845 } 846 }; 847 Ok(GenericVariant { 848 discriminant, 849 payload, 850 abi: &ty.abi, 851 info: &ty.info, 852 }) 853 } 854 855 fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> { 856 let (discriminant, payload) = match r { 857 None => (0, None), 858 Some(val) => (1, Some((&**val, ty.ty))), 859 }; 860 GenericVariant { 861 discriminant, 862 payload, 863 abi: &ty.abi, 864 info: &ty.info, 865 } 866 } 867 868 fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> { 869 let discriminant = get_enum_discriminant(ty, discriminant)?; 870 871 Ok(GenericVariant { 872 discriminant, 873 payload: None, 874 abi: &ty.abi, 875 info: &ty.info, 876 }) 877 } 878 879 fn variant<'a>( 880 ty: &'a TypeVariant, 881 discriminant_name: &str, 882 payload: &'a Option<Box<Val>>, 883 ) -> Result<GenericVariant<'a>> { 884 let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?; 885 886 let payload = match (payload, payload_ty) { 887 (Some(val), Some(ty)) => Some((&**val, *ty)), 888 (None, None) => None, 889 (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"), 890 (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"), 891 }; 892 893 Ok(GenericVariant { 894 discriminant, 895 payload, 896 abi: &ty.abi, 897 info: &ty.info, 898 }) 899 } 900 901 fn lower<T>( 902 &self, 903 cx: &mut LowerContext<'_, T>, 904 dst: &mut IterMut<'_, MaybeUninit<ValRaw>>, 905 ) -> Result<()> { 906 next_mut(dst).write(ValRaw::u32(self.discriminant)); 907 908 // For the remaining lowered representation of this variant that 909 // the payload didn't write we write out zeros here to ensure 910 // the entire variant is written. 911 let value_flat = match self.payload { 912 Some((value, ty)) => { 913 value.lower(cx, ty, dst)?; 914 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap() 915 } 916 None => 0, 917 }; 918 let variant_flat = self.abi.flat_count(usize::MAX).unwrap(); 919 for _ in (1 + value_flat)..variant_flat { 920 next_mut(dst).write(ValRaw::u64(0)); 921 } 922 Ok(()) 923 } 924 925 fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> { 926 match self.info.size { 927 DiscriminantSize::Size1 => u8::try_from(self.discriminant) 928 .unwrap() 929 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?, 930 DiscriminantSize::Size2 => u16::try_from(self.discriminant) 931 .unwrap() 932 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?, 933 DiscriminantSize::Size4 => { 934 self.discriminant 935 .linear_lower_to_memory(cx, InterfaceType::U32, offset)? 936 } 937 } 938 939 if let Some((value, ty)) = self.payload { 940 let offset = offset + usize::try_from(self.info.payload_offset32).unwrap(); 941 value.store(cx, ty, offset)?; 942 } 943 944 Ok(()) 945 } 946 } 947 948 fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> { 949 let elem = cx.types[ty].element; 950 let abi = cx.types.canonical_abi(&elem); 951 let element_size = usize::try_from(abi.size32).unwrap(); 952 let element_alignment = abi.align32; 953 954 match len 955 .checked_mul(element_size) 956 .and_then(|len| ptr.checked_add(len)) 957 { 958 Some(n) if n <= cx.memory().len() => cx.consume_fuel_array(len, size_of::<Val>())?, 959 _ => bail!("list pointer/length out of bounds of memory"), 960 } 961 if ptr % usize::try_from(element_alignment)? != 0 { 962 bail!("list pointer is not aligned") 963 } 964 965 Ok(Val::List( 966 (0..len) 967 .map(|index| { 968 Val::load( 969 cx, 970 elem, 971 &cx.memory()[ptr + (index * element_size)..][..element_size], 972 ) 973 }) 974 .collect::<Result<_>>()?, 975 )) 976 } 977 978 fn load_map(cx: &mut LiftContext<'_>, ty: TypeMapIndex, ptr: usize, len: usize) -> Result<Val> { 979 // Maps are stored as list<tuple<k, v>> in canonical ABI 980 let map_ty = &cx.types[ty]; 981 let key_ty = map_ty.key; 982 let value_ty = map_ty.value; 983 984 let key_abi = cx.types.canonical_abi(&key_ty); 985 let value_abi = cx.types.canonical_abi(&value_ty); 986 let key_size = usize::try_from(key_abi.size32).unwrap(); 987 let value_size = usize::try_from(value_abi.size32).unwrap(); 988 let value_offset = usize::try_from(map_ty.value_offset32).unwrap(); 989 let tuple_alignment = map_ty.entry_abi.align32; 990 let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap(); 991 992 // Bounds check 993 match len 994 .checked_mul(tuple_size) 995 .and_then(|len| ptr.checked_add(len)) 996 { 997 Some(n) if n <= cx.memory().len() => {} 998 _ => bail!("map pointer/length out of bounds of memory"), 999 } 1000 if ptr % usize::try_from(tuple_alignment)? != 0 { 1001 bail!("map pointer is not aligned") 1002 } 1003 1004 // Load each tuple (key, value) into a Vec 1005 let mut map = Vec::with_capacity(len); 1006 for index in 0..len { 1007 let tuple_ptr = ptr + (index * tuple_size); 1008 let key = Val::load(cx, key_ty, &cx.memory()[tuple_ptr..][..key_size])?; 1009 let value = Val::load( 1010 cx, 1011 value_ty, 1012 &cx.memory()[tuple_ptr + value_offset..][..value_size], 1013 )?; 1014 map.push((key, value)); 1015 } 1016 1017 Ok(Val::Map(map)) 1018 } 1019 1020 fn load_variant( 1021 cx: &mut LiftContext<'_>, 1022 info: &VariantInfo, 1023 mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, 1024 bytes: &[u8], 1025 ) -> Result<(u32, Option<Box<Val>>)> { 1026 let discriminant = match info.size { 1027 DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory( 1028 cx, 1029 InterfaceType::U8, 1030 &bytes[..1], 1031 )?), 1032 DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory( 1033 cx, 1034 InterfaceType::U16, 1035 &bytes[..2], 1036 )?), 1037 DiscriminantSize::Size4 => { 1038 u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])? 1039 } 1040 }; 1041 let case_ty = types.nth(discriminant as usize).ok_or_else(|| { 1042 format_err!( 1043 "discriminant {} out of range [0..{})", 1044 discriminant, 1045 types.len() 1046 ) 1047 })?; 1048 let value = match case_ty { 1049 Some(case_ty) => { 1050 let payload_offset = usize::try_from(info.payload_offset32).unwrap(); 1051 let case_abi = cx.types.canonical_abi(&case_ty); 1052 let case_size = usize::try_from(case_abi.size32).unwrap(); 1053 Some(Box::new(Val::load( 1054 cx, 1055 case_ty, 1056 &bytes[payload_offset..][..case_size], 1057 )?)) 1058 } 1059 None => None, 1060 }; 1061 Ok((discriminant, value)) 1062 } 1063 1064 fn lift_variant( 1065 cx: &mut LiftContext<'_>, 1066 flatten_count: usize, 1067 mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>, 1068 src: &mut Iter<'_, ValRaw>, 1069 ) -> Result<(u32, Option<Box<Val>>)> { 1070 let len = types.len(); 1071 let discriminant = next(src).get_u32(); 1072 let ty = types 1073 .nth(discriminant as usize) 1074 .ok_or_else(|| format_err!("discriminant {discriminant} out of range [0..{len})"))?; 1075 let (value, value_flat) = match ty { 1076 Some(ty) => ( 1077 Some(Box::new(Val::lift(cx, ty, src)?)), 1078 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(), 1079 ), 1080 None => (None, 0), 1081 }; 1082 for _ in (1 + value_flat)..flatten_count { 1083 next(src); 1084 } 1085 Ok((discriminant, value)) 1086 } 1087 1088 /// Lower a list with the specified element type and values. 1089 fn lower_list<T>( 1090 cx: &mut LowerContext<'_, T>, 1091 element_type: InterfaceType, 1092 items: &[Val], 1093 ) -> Result<(usize, usize)> { 1094 let abi = cx.types.canonical_abi(&element_type); 1095 let elt_size = usize::try_from(abi.size32)?; 1096 let elt_align = abi.align32; 1097 let size = items 1098 .len() 1099 .checked_mul(elt_size) 1100 .ok_or_else(|| crate::format_err!("size overflow copying a list"))?; 1101 let ptr = cx.realloc(0, 0, elt_align, size)?; 1102 let mut element_ptr = ptr; 1103 for item in items { 1104 item.store(cx, element_type, element_ptr)?; 1105 element_ptr += elt_size; 1106 } 1107 Ok((ptr, items.len())) 1108 } 1109 1110 /// Lower a map as list<tuple<k, v>> with the specified key and value types. 1111 fn lower_map<T>( 1112 cx: &mut LowerContext<'_, T>, 1113 map_ty: &TypeMap, 1114 pairs: &[(Val, Val)], 1115 ) -> Result<(usize, usize)> { 1116 let key_type = map_ty.key; 1117 let value_type = map_ty.value; 1118 let value_offset = usize::try_from(map_ty.value_offset32).unwrap(); 1119 let tuple_align = map_ty.entry_abi.align32; 1120 let tuple_size = usize::try_from(map_ty.entry_abi.size32).unwrap(); 1121 1122 let size = pairs 1123 .len() 1124 .checked_mul(tuple_size) 1125 .ok_or_else(|| crate::format_err!("size overflow copying a map"))?; 1126 let ptr = cx.realloc(0, 0, tuple_align, size)?; 1127 1128 let mut tuple_ptr = ptr; 1129 for (key, value) in pairs { 1130 // Store key at tuple_ptr 1131 key.store(cx, key_type, tuple_ptr)?; 1132 // Store value at tuple_ptr + value_offset (properly aligned) 1133 value.store(cx, value_type, tuple_ptr + value_offset)?; 1134 tuple_ptr += tuple_size; 1135 } 1136 1137 Ok((ptr, pairs.len())) 1138 } 1139 1140 fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) { 1141 while bits > 0 { 1142 if bits & 1 != 0 { 1143 flags.push(ty.names[offset as usize].clone()); 1144 } 1145 bits >>= 1; 1146 offset += 1; 1147 } 1148 } 1149 1150 fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> { 1151 let mut storage = match FlagsSize::from_count(ty.names.len()) { 1152 FlagsSize::Size0 => Vec::new(), 1153 FlagsSize::Size1 | FlagsSize::Size2 => vec![0], 1154 FlagsSize::Size4Plus(n) => vec![0; n.into()], 1155 }; 1156 1157 for flag in flags { 1158 let bit = ty 1159 .names 1160 .get_index_of(flag) 1161 .ok_or_else(|| crate::format_err!("unknown flag: `{flag}`"))?; 1162 storage[bit / 32] |= 1 << (bit % 32); 1163 } 1164 Ok(storage) 1165 } 1166 1167 fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> { 1168 ty.names 1169 .get_index_of(n) 1170 .ok_or_else(|| crate::format_err!("enum variant name `{n}` is not valid")) 1171 .map(|i| i.try_into().unwrap()) 1172 } 1173 1174 fn get_variant_discriminant<'a>( 1175 ty: &'a TypeVariant, 1176 name: &str, 1177 ) -> Result<(u32, &'a Option<InterfaceType>)> { 1178 let (i, _, ty) = ty 1179 .cases 1180 .get_full(name) 1181 .ok_or_else(|| crate::format_err!("unknown variant case: `{name}`"))?; 1182 Ok((i.try_into().unwrap(), ty)) 1183 } 1184 1185 fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw { 1186 src.next().unwrap() 1187 } 1188 1189 fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> { 1190 dst.next().unwrap() 1191 } 1192 1193 #[cold] 1194 fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> { 1195 bail!( 1196 "type mismatch: expected {}, found {}", 1197 desc(&ty), 1198 val.desc() 1199 ) 1200 } 1201 1202 /// Represents a component model `error-context`. 1203 /// 1204 /// Note that this type is not usable at this time as its implementation has not 1205 /// been filled out. There are no operations on this and there's additionally no 1206 /// ability to "drop" or deallocate this index. 1207 // 1208 // FIXME(#11161) this needs to be filled out implementation-wise 1209 #[derive(Debug, Clone, PartialEq, Eq)] 1210 pub struct ErrorContextAny(pub(crate) u32); 1211 1212 impl From<bool> for Val { 1213 fn from(b: bool) -> Self { 1214 Val::Bool(b) 1215 } 1216 } 1217 1218 impl From<u8> for Val { 1219 fn from(u: u8) -> Self { 1220 Val::U8(u) 1221 } 1222 } 1223 1224 impl From<i8> for Val { 1225 fn from(i: i8) -> Self { 1226 Val::S8(i) 1227 } 1228 } 1229 1230 impl From<u16> for Val { 1231 fn from(u: u16) -> Self { 1232 Val::U16(u) 1233 } 1234 } 1235 1236 impl From<i16> for Val { 1237 fn from(i: i16) -> Self { 1238 Val::S16(i) 1239 } 1240 } 1241 1242 impl From<u32> for Val { 1243 fn from(u: u32) -> Self { 1244 Val::U32(u) 1245 } 1246 } 1247 1248 impl From<i32> for Val { 1249 fn from(i: i32) -> Self { 1250 Val::S32(i) 1251 } 1252 } 1253 1254 impl From<u64> for Val { 1255 fn from(u: u64) -> Self { 1256 Val::U64(u) 1257 } 1258 } 1259 1260 impl From<i64> for Val { 1261 fn from(i: i64) -> Self { 1262 Val::S64(i) 1263 } 1264 } 1265 1266 impl From<char> for Val { 1267 fn from(i: char) -> Self { 1268 Val::Char(i) 1269 } 1270 } 1271 1272 impl From<String> for Val { 1273 fn from(i: String) -> Self { 1274 Val::String(i) 1275 } 1276 } 1277 1278 impl From<ResourceAny> for Val { 1279 fn from(i: ResourceAny) -> Self { 1280 Val::Resource(i) 1281 } 1282 } 1283 1284 impl From<FutureAny> for Val { 1285 fn from(i: FutureAny) -> Self { 1286 Val::Future(i) 1287 } 1288 } 1289 1290 impl From<StreamAny> for Val { 1291 fn from(i: StreamAny) -> Self { 1292 Val::Stream(i) 1293 } 1294 } 1295