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