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