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