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