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