1use crate::{
2 ArithmeticOps,
3 ExtendInto,
4 Float,
5 Integer,
6 SignExtendFrom,
7 TrapCode,
8 TruncateSaturateInto,
9 TryTruncateInto,
10 Value,
11 ValueType,
12 WrapInto,
13 F32,
14 F64,
15};
16use core::{
17 fmt::{self, Display},
18 ops::{Neg, Shl, Shr},
19};
20
21#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
25#[repr(transparent)]
26pub struct UntypedValue {
27 bits: u64,
30}
31
32impl UntypedValue {
33 pub fn to_bits(self) -> u64 {
35 self.bits
36 }
37
38 pub fn with_type(self, value_type: ValueType) -> Value {
40 match value_type {
41 ValueType::I32 => Value::I32(<_>::from(self)),
42 ValueType::I64 => Value::I64(<_>::from(self)),
43 ValueType::F32 => Value::F32(<_>::from(self)),
44 ValueType::F64 => Value::F64(<_>::from(self)),
45 }
46 }
47}
48
49macro_rules! impl_from_untyped_for_int {
50 ( $( $int:ty ),* $(,)? ) => {
51 $(
52 impl From<UntypedValue> for $int {
53 fn from(untyped: UntypedValue) -> Self {
54 untyped.to_bits() as _
55 }
56 }
57 )*
58 };
59}
60impl_from_untyped_for_int!(i8, i16, i32, i64, u8, u16, u32, u64);
61
62macro_rules! impl_from_untyped_for_float {
63 ( $( $float:ty ),* $(,)? ) => {
64 $(
65 impl From<UntypedValue> for $float {
66 fn from(untyped: UntypedValue) -> Self {
67 Self::from_bits(untyped.to_bits() as _)
68 }
69 }
70 )*
71 };
72}
73impl_from_untyped_for_float!(f32, f64, F32, F64);
74
75impl From<UntypedValue> for bool {
76 fn from(untyped: UntypedValue) -> Self {
77 untyped.to_bits() != 0
78 }
79}
80
81impl From<Value> for UntypedValue {
82 fn from(value: Value) -> Self {
83 match value {
84 Value::I32(value) => value.into(),
85 Value::I64(value) => value.into(),
86 Value::F32(value) => value.into(),
87 Value::F64(value) => value.into(),
88 }
89 }
90}
91
92macro_rules! impl_from_unsigned_prim {
93 ( $( $prim:ty ),* $(,)? ) => {
94 $(
95 impl From<$prim> for UntypedValue {
96 fn from(value: $prim) -> Self {
97 Self { bits: value as _ }
98 }
99 }
100 )*
101 };
102}
103#[rustfmt::skip]
104impl_from_unsigned_prim!(
105 bool, u8, u16, u32, u64,
106);
107
108macro_rules! impl_from_signed_prim {
109 ( $( $prim:ty as $base:ty ),* $(,)? ) => {
110 $(
111 impl From<$prim> for UntypedValue {
112 fn from(value: $prim) -> Self {
113 Self { bits: value as $base as _ }
114 }
115 }
116 )*
117 };
118}
119#[rustfmt::skip]
120impl_from_signed_prim!(
121 i8 as u8,
122 i16 as u16,
123 i32 as u32,
124 i64 as u64,
125);
126
127macro_rules! impl_from_float {
128 ( $( $float:ty ),* $(,)? ) => {
129 $(
130 impl From<$float> for UntypedValue {
131 fn from(value: $float) -> Self {
132 Self {
133 bits: value.to_bits() as _,
134 }
135 }
136 }
137 )*
138 };
139}
140impl_from_float!(f32, f64, F32, F64);
141
142macro_rules! op {
143 ( $operator:tt ) => {{
144 |lhs, rhs| lhs $operator rhs
145 }};
146}
147
148impl UntypedValue {
149 fn execute_unary<T, R>(self, op: fn(T) -> R) -> Self
151 where
152 T: From<Self>,
153 R: Into<Self>,
154 {
155 op(T::from(self)).into()
156 }
157
158 fn try_execute_unary<T, R>(self, op: fn(T) -> Result<R, TrapCode>) -> Result<Self, TrapCode>
160 where
161 T: From<Self>,
162 R: Into<Self>,
163 {
164 op(T::from(self)).map(Into::into)
165 }
166
167 fn execute_binary<T, R>(self, rhs: Self, op: fn(T, T) -> R) -> Self
169 where
170 T: From<Self>,
171 R: Into<Self>,
172 {
173 op(T::from(self), T::from(rhs)).into()
174 }
175
176 fn try_execute_binary<T, R>(
178 self,
179 rhs: Self,
180 op: fn(T, T) -> Result<R, TrapCode>,
181 ) -> Result<Self, TrapCode>
182 where
183 T: From<Self>,
184 R: Into<Self>,
185 {
186 op(T::from(self), T::from(rhs)).map(Into::into)
187 }
188
189 pub fn i32_add(self, rhs: Self) -> Self {
191 self.execute_binary(rhs, <i32 as ArithmeticOps<i32>>::add)
192 }
193
194 pub fn i64_add(self, rhs: Self) -> Self {
196 self.execute_binary(rhs, <i64 as ArithmeticOps<i64>>::add)
197 }
198
199 pub fn i32_sub(self, rhs: Self) -> Self {
201 self.execute_binary(rhs, <i32 as ArithmeticOps<i32>>::sub)
202 }
203
204 pub fn i64_sub(self, rhs: Self) -> Self {
206 self.execute_binary(rhs, <i64 as ArithmeticOps<i64>>::sub)
207 }
208
209 pub fn i32_mul(self, rhs: Self) -> Self {
211 self.execute_binary(rhs, <i32 as ArithmeticOps<i32>>::mul)
212 }
213
214 pub fn i64_mul(self, rhs: Self) -> Self {
216 self.execute_binary(rhs, <i64 as ArithmeticOps<i64>>::mul)
217 }
218
219 pub fn i32_div_s(self, rhs: Self) -> Result<Self, TrapCode> {
221 self.try_execute_binary(rhs, <i32 as ArithmeticOps<i32>>::div)
222 }
223
224 pub fn i64_div_s(self, rhs: Self) -> Result<Self, TrapCode> {
226 self.try_execute_binary(rhs, <i64 as ArithmeticOps<i64>>::div)
227 }
228
229 pub fn i32_div_u(self, rhs: Self) -> Result<Self, TrapCode> {
231 self.try_execute_binary(rhs, <u32 as ArithmeticOps<u32>>::div)
232 }
233
234 pub fn i64_div_u(self, rhs: Self) -> Result<Self, TrapCode> {
236 self.try_execute_binary(rhs, <u64 as ArithmeticOps<u64>>::div)
237 }
238
239 pub fn i32_rem_s(self, rhs: Self) -> Result<Self, TrapCode> {
241 self.try_execute_binary(rhs, <i32 as Integer<i32>>::rem)
242 }
243
244 pub fn i64_rem_s(self, rhs: Self) -> Result<Self, TrapCode> {
246 self.try_execute_binary(rhs, <i64 as Integer<i64>>::rem)
247 }
248
249 pub fn i32_rem_u(self, rhs: Self) -> Result<Self, TrapCode> {
251 self.try_execute_binary(rhs, <u32 as Integer<u32>>::rem)
252 }
253
254 pub fn i64_rem_u(self, rhs: Self) -> Result<Self, TrapCode> {
256 self.try_execute_binary(rhs, <u64 as Integer<u64>>::rem)
257 }
258
259 pub fn i32_and(self, rhs: Self) -> Self {
261 self.execute_binary::<i32, _>(rhs, op!(&))
262 }
263
264 pub fn i64_and(self, rhs: Self) -> Self {
266 self.execute_binary::<i64, _>(rhs, op!(&))
267 }
268
269 pub fn i32_or(self, rhs: Self) -> Self {
271 self.execute_binary::<i32, _>(rhs, op!(|))
272 }
273
274 pub fn i64_or(self, rhs: Self) -> Self {
276 self.execute_binary::<i64, _>(rhs, op!(|))
277 }
278
279 pub fn i32_xor(self, rhs: Self) -> Self {
281 self.execute_binary::<i32, _>(rhs, op!(^))
282 }
283
284 pub fn i64_xor(self, rhs: Self) -> Self {
286 self.execute_binary::<i64, _>(rhs, op!(^))
287 }
288
289 pub fn i32_shl(self, rhs: Self) -> Self {
291 self.execute_binary::<i32, _>(rhs, |lhs, rhs| lhs.shl(rhs & 0x1F))
292 }
293
294 pub fn i64_shl(self, rhs: Self) -> Self {
296 self.execute_binary::<i64, _>(rhs, |lhs, rhs| lhs.shl(rhs & 0x3F))
297 }
298
299 pub fn i32_shr_s(self, rhs: Self) -> Self {
301 self.execute_binary::<i32, _>(rhs, |lhs, rhs| lhs.shr(rhs & 0x1F))
302 }
303
304 pub fn i64_shr_s(self, rhs: Self) -> Self {
306 self.execute_binary::<i64, _>(rhs, |lhs, rhs| lhs.shr(rhs & 0x3F))
307 }
308
309 pub fn i32_shr_u(self, rhs: Self) -> Self {
311 self.execute_binary::<u32, _>(rhs, |lhs, rhs| lhs.shr(rhs & 0x1F))
312 }
313
314 pub fn i64_shr_u(self, rhs: Self) -> Self {
316 self.execute_binary::<u64, _>(rhs, |lhs, rhs| lhs.shr(rhs & 0x3F))
317 }
318
319 pub fn i32_clz(self) -> Self {
321 self.execute_unary(<i32 as Integer<i32>>::leading_zeros)
322 }
323
324 pub fn i64_clz(self) -> Self {
326 self.execute_unary(<i64 as Integer<i64>>::leading_zeros)
327 }
328
329 pub fn i32_ctz(self) -> Self {
331 self.execute_unary(<i32 as Integer<i32>>::trailing_zeros)
332 }
333
334 pub fn i64_ctz(self) -> Self {
336 self.execute_unary(<i64 as Integer<i64>>::trailing_zeros)
337 }
338
339 pub fn i32_popcnt(self) -> Self {
341 self.execute_unary(<i32 as Integer<i32>>::count_ones)
342 }
343
344 pub fn i64_popcnt(self) -> Self {
346 self.execute_unary(<i64 as Integer<i64>>::count_ones)
347 }
348
349 pub fn i32_rotl(self, rhs: Self) -> Self {
351 self.execute_binary(rhs, <i32 as Integer<i32>>::rotl)
352 }
353
354 pub fn i64_rotl(self, rhs: Self) -> Self {
356 self.execute_binary(rhs, <i64 as Integer<i64>>::rotl)
357 }
358
359 pub fn i32_rotr(self, rhs: Self) -> Self {
361 self.execute_binary(rhs, <i32 as Integer<i32>>::rotr)
362 }
363
364 pub fn i64_rotr(self, rhs: Self) -> Self {
366 self.execute_binary(rhs, <i64 as Integer<i64>>::rotr)
367 }
368
369 pub fn i32_eqz(self) -> Self {
371 self.execute_unary::<i32, bool>(|value| value == 0)
372 }
373
374 pub fn i64_eqz(self) -> Self {
376 self.execute_unary::<i64, bool>(|value| value == 0)
377 }
378
379 pub fn i32_eq(self, rhs: Self) -> Self {
381 self.execute_binary::<i32, bool>(rhs, op!(==))
382 }
383
384 pub fn i64_eq(self, rhs: Self) -> Self {
386 self.execute_binary::<i64, bool>(rhs, op!(==))
387 }
388
389 pub fn f32_eq(self, rhs: Self) -> Self {
391 self.execute_binary::<F32, bool>(rhs, op!(==))
392 }
393
394 pub fn f64_eq(self, rhs: Self) -> Self {
396 self.execute_binary::<F64, bool>(rhs, op!(==))
397 }
398
399 pub fn i32_ne(self, rhs: Self) -> Self {
401 self.execute_binary::<i32, bool>(rhs, op!(!=))
402 }
403
404 pub fn i64_ne(self, rhs: Self) -> Self {
406 self.execute_binary::<i64, bool>(rhs, op!(!=))
407 }
408
409 pub fn f32_ne(self, rhs: Self) -> Self {
411 self.execute_binary::<F32, bool>(rhs, op!(!=))
412 }
413
414 pub fn f64_ne(self, rhs: Self) -> Self {
416 self.execute_binary::<F64, bool>(rhs, op!(!=))
417 }
418
419 pub fn i32_lt_s(self, rhs: Self) -> Self {
421 self.execute_binary::<i32, bool>(rhs, op!(<))
422 }
423
424 pub fn i64_lt_s(self, rhs: Self) -> Self {
426 self.execute_binary::<i64, bool>(rhs, op!(<))
427 }
428
429 pub fn i32_lt_u(self, rhs: Self) -> Self {
431 self.execute_binary::<u32, bool>(rhs, op!(<))
432 }
433
434 pub fn i64_lt_u(self, rhs: Self) -> Self {
436 self.execute_binary::<u64, bool>(rhs, op!(<))
437 }
438
439 pub fn f32_lt(self, rhs: Self) -> Self {
441 self.execute_binary::<F32, bool>(rhs, op!(<))
442 }
443
444 pub fn f64_lt(self, rhs: Self) -> Self {
446 self.execute_binary::<F64, bool>(rhs, op!(<))
447 }
448
449 pub fn i32_le_s(self, rhs: Self) -> Self {
451 self.execute_binary::<i32, bool>(rhs, op!(<=))
452 }
453
454 pub fn i64_le_s(self, rhs: Self) -> Self {
456 self.execute_binary::<i64, bool>(rhs, op!(<=))
457 }
458
459 pub fn i32_le_u(self, rhs: Self) -> Self {
461 self.execute_binary::<u32, bool>(rhs, op!(<=))
462 }
463
464 pub fn i64_le_u(self, rhs: Self) -> Self {
466 self.execute_binary::<u64, bool>(rhs, op!(<=))
467 }
468
469 pub fn f32_le(self, rhs: Self) -> Self {
471 self.execute_binary::<F32, bool>(rhs, op!(<=))
472 }
473
474 pub fn f64_le(self, rhs: Self) -> Self {
476 self.execute_binary::<F64, bool>(rhs, op!(<=))
477 }
478
479 pub fn i32_gt_s(self, rhs: Self) -> Self {
481 self.execute_binary::<i32, bool>(rhs, op!(>))
482 }
483
484 pub fn i64_gt_s(self, rhs: Self) -> Self {
486 self.execute_binary::<i64, bool>(rhs, op!(>))
487 }
488
489 pub fn i32_gt_u(self, rhs: Self) -> Self {
491 self.execute_binary::<u32, bool>(rhs, op!(>))
492 }
493
494 pub fn i64_gt_u(self, rhs: Self) -> Self {
496 self.execute_binary::<u64, bool>(rhs, op!(>))
497 }
498
499 pub fn f32_gt(self, rhs: Self) -> Self {
501 self.execute_binary::<F32, bool>(rhs, op!(>))
502 }
503
504 pub fn f64_gt(self, rhs: Self) -> Self {
506 self.execute_binary::<F64, bool>(rhs, op!(>))
507 }
508
509 pub fn i32_ge_s(self, rhs: Self) -> Self {
511 self.execute_binary::<i32, bool>(rhs, op!(>=))
512 }
513
514 pub fn i64_ge_s(self, rhs: Self) -> Self {
516 self.execute_binary::<i64, bool>(rhs, op!(>=))
517 }
518
519 pub fn i32_ge_u(self, rhs: Self) -> Self {
521 self.execute_binary::<u32, bool>(rhs, op!(>=))
522 }
523
524 pub fn i64_ge_u(self, rhs: Self) -> Self {
526 self.execute_binary::<u64, bool>(rhs, op!(>=))
527 }
528
529 pub fn f32_ge(self, rhs: Self) -> Self {
531 self.execute_binary::<F32, bool>(rhs, op!(>=))
532 }
533
534 pub fn f64_ge(self, rhs: Self) -> Self {
536 self.execute_binary::<F64, bool>(rhs, op!(>=))
537 }
538
539 pub fn f32_abs(self) -> Self {
541 self.execute_unary(<F32 as Float<F32>>::abs)
542 }
543
544 pub fn f32_neg(self) -> Self {
546 self.execute_unary(<F32 as Neg>::neg)
547 }
548
549 pub fn f32_ceil(self) -> Self {
551 self.execute_unary(<F32 as Float<F32>>::ceil)
552 }
553
554 pub fn f32_floor(self) -> Self {
556 self.execute_unary(<F32 as Float<F32>>::floor)
557 }
558
559 pub fn f32_trunc(self) -> Self {
561 self.execute_unary(<F32 as Float<F32>>::trunc)
562 }
563
564 pub fn f32_nearest(self) -> Self {
566 self.execute_unary(<F32 as Float<F32>>::nearest)
567 }
568
569 pub fn f32_sqrt(self) -> Self {
571 self.execute_unary(<F32 as Float<F32>>::sqrt)
572 }
573
574 pub fn f32_min(self, other: Self) -> Self {
576 self.execute_binary(other, <F32 as Float<F32>>::min)
577 }
578
579 pub fn f32_max(self, other: Self) -> Self {
581 self.execute_binary(other, <F32 as Float<F32>>::max)
582 }
583
584 pub fn f32_copysign(self, other: Self) -> Self {
586 self.execute_binary(other, <F32 as Float<F32>>::copysign)
587 }
588
589 pub fn f64_abs(self) -> Self {
591 self.execute_unary(<F64 as Float<F64>>::abs)
592 }
593
594 pub fn f64_neg(self) -> Self {
596 self.execute_unary(<F64 as Neg>::neg)
597 }
598
599 pub fn f64_ceil(self) -> Self {
601 self.execute_unary(<F64 as Float<F64>>::ceil)
602 }
603
604 pub fn f64_floor(self) -> Self {
606 self.execute_unary(<F64 as Float<F64>>::floor)
607 }
608
609 pub fn f64_trunc(self) -> Self {
611 self.execute_unary(<F64 as Float<F64>>::trunc)
612 }
613
614 pub fn f64_nearest(self) -> Self {
616 self.execute_unary(<F64 as Float<F64>>::nearest)
617 }
618
619 pub fn f64_sqrt(self) -> Self {
621 self.execute_unary(<F64 as Float<F64>>::sqrt)
622 }
623
624 pub fn f32_add(self, rhs: Self) -> Self {
626 self.execute_binary(rhs, <F32 as ArithmeticOps<F32>>::add)
627 }
628
629 pub fn f64_add(self, rhs: Self) -> Self {
631 self.execute_binary(rhs, <F64 as ArithmeticOps<F64>>::add)
632 }
633
634 pub fn f32_sub(self, rhs: Self) -> Self {
636 self.execute_binary(rhs, <F32 as ArithmeticOps<F32>>::sub)
637 }
638
639 pub fn f64_sub(self, rhs: Self) -> Self {
641 self.execute_binary(rhs, <F64 as ArithmeticOps<F64>>::sub)
642 }
643
644 pub fn f32_mul(self, rhs: Self) -> Self {
646 self.execute_binary(rhs, <F32 as ArithmeticOps<F32>>::mul)
647 }
648
649 pub fn f64_mul(self, rhs: Self) -> Self {
651 self.execute_binary(rhs, <F64 as ArithmeticOps<F64>>::mul)
652 }
653
654 pub fn f32_div(self, rhs: Self) -> Result<Self, TrapCode> {
656 self.try_execute_binary(rhs, <F32 as ArithmeticOps<F32>>::div)
657 }
658
659 pub fn f64_div(self, rhs: Self) -> Result<Self, TrapCode> {
661 self.try_execute_binary(rhs, <F64 as ArithmeticOps<F64>>::div)
662 }
663
664 pub fn f64_min(self, other: Self) -> Self {
666 self.execute_binary(other, <F64 as Float<F64>>::min)
667 }
668
669 pub fn f64_max(self, other: Self) -> Self {
671 self.execute_binary(other, <F64 as Float<F64>>::max)
672 }
673
674 pub fn f64_copysign(self, other: Self) -> Self {
676 self.execute_binary(other, <F64 as Float<F64>>::copysign)
677 }
678
679 pub fn i32_wrap_i64(self) -> Self {
681 self.execute_unary(<i64 as WrapInto<i32>>::wrap_into)
682 }
683
684 pub fn i32_trunc_f32_s(self) -> Result<Self, TrapCode> {
686 self.try_execute_unary(<F32 as TryTruncateInto<i32, TrapCode>>::try_truncate_into)
687 }
688
689 pub fn i32_trunc_f32_u(self) -> Result<Self, TrapCode> {
691 self.try_execute_unary(<F32 as TryTruncateInto<u32, TrapCode>>::try_truncate_into)
692 }
693
694 pub fn i32_trunc_f64_s(self) -> Result<Self, TrapCode> {
696 self.try_execute_unary(<F64 as TryTruncateInto<i32, TrapCode>>::try_truncate_into)
697 }
698
699 pub fn i32_trunc_f64_u(self) -> Result<Self, TrapCode> {
701 self.try_execute_unary(<F64 as TryTruncateInto<u32, TrapCode>>::try_truncate_into)
702 }
703
704 pub fn i64_extend_i32_s(self) -> Self {
706 self.execute_unary(<i32 as ExtendInto<i64>>::extend_into)
707 }
708
709 pub fn i64_extend_i32_u(self) -> Self {
711 self.execute_unary(<u32 as ExtendInto<i64>>::extend_into)
712 }
713
714 pub fn i64_trunc_f32_s(self) -> Result<Self, TrapCode> {
716 self.try_execute_unary(<F32 as TryTruncateInto<i64, TrapCode>>::try_truncate_into)
717 }
718
719 pub fn i64_trunc_f32_u(self) -> Result<Self, TrapCode> {
721 self.try_execute_unary(<F32 as TryTruncateInto<u64, TrapCode>>::try_truncate_into)
722 }
723
724 pub fn i64_trunc_f64_s(self) -> Result<Self, TrapCode> {
726 self.try_execute_unary(<F64 as TryTruncateInto<i64, TrapCode>>::try_truncate_into)
727 }
728
729 pub fn i64_trunc_f64_u(self) -> Result<Self, TrapCode> {
731 self.try_execute_unary(<F64 as TryTruncateInto<u64, TrapCode>>::try_truncate_into)
732 }
733
734 pub fn f32_convert_i32_s(self) -> Self {
736 self.execute_unary(<i32 as ExtendInto<F32>>::extend_into)
737 }
738
739 pub fn f32_convert_i32_u(self) -> Self {
741 self.execute_unary(<u32 as ExtendInto<F32>>::extend_into)
742 }
743
744 pub fn f32_convert_i64_s(self) -> Self {
746 self.execute_unary(<i64 as WrapInto<F32>>::wrap_into)
747 }
748
749 pub fn f32_convert_i64_u(self) -> Self {
751 self.execute_unary(<u64 as WrapInto<F32>>::wrap_into)
752 }
753
754 pub fn f32_demote_f64(self) -> Self {
756 self.execute_unary(<F64 as WrapInto<F32>>::wrap_into)
757 }
758
759 pub fn f64_convert_i32_s(self) -> Self {
761 self.execute_unary(<i32 as ExtendInto<F64>>::extend_into)
762 }
763
764 pub fn f64_convert_i32_u(self) -> Self {
766 self.execute_unary(<u32 as ExtendInto<F64>>::extend_into)
767 }
768
769 pub fn f64_convert_i64_s(self) -> Self {
771 self.execute_unary(<i64 as ExtendInto<F64>>::extend_into)
772 }
773
774 pub fn f64_convert_i64_u(self) -> Self {
776 self.execute_unary(<u64 as ExtendInto<F64>>::extend_into)
777 }
778
779 pub fn f64_promote_f32(self) -> Self {
781 self.execute_unary(<F32 as ExtendInto<F64>>::extend_into)
782 }
783
784 pub fn i32_extend8_s(self) -> Self {
786 self.execute_unary(<i32 as SignExtendFrom<i8>>::sign_extend_from)
787 }
788
789 pub fn i32_extend16_s(self) -> Self {
791 self.execute_unary(<i32 as SignExtendFrom<i16>>::sign_extend_from)
792 }
793
794 pub fn i64_extend8_s(self) -> Self {
796 self.execute_unary(<i64 as SignExtendFrom<i8>>::sign_extend_from)
797 }
798
799 pub fn i64_extend16_s(self) -> Self {
801 self.execute_unary(<i64 as SignExtendFrom<i16>>::sign_extend_from)
802 }
803
804 pub fn i64_extend32_s(self) -> Self {
806 self.execute_unary(<i64 as SignExtendFrom<i32>>::sign_extend_from)
807 }
808
809 pub fn i32_trunc_sat_f32_s(self) -> Self {
811 self.execute_unary(<F32 as TruncateSaturateInto<i32>>::truncate_saturate_into)
812 }
813
814 pub fn i32_trunc_sat_f32_u(self) -> Self {
816 self.execute_unary(<F32 as TruncateSaturateInto<u32>>::truncate_saturate_into)
817 }
818
819 pub fn i32_trunc_sat_f64_s(self) -> Self {
821 self.execute_unary(<F64 as TruncateSaturateInto<i32>>::truncate_saturate_into)
822 }
823
824 pub fn i32_trunc_sat_f64_u(self) -> Self {
826 self.execute_unary(<F64 as TruncateSaturateInto<u32>>::truncate_saturate_into)
827 }
828
829 pub fn i64_trunc_sat_f32_s(self) -> Self {
831 self.execute_unary(<F32 as TruncateSaturateInto<i64>>::truncate_saturate_into)
832 }
833
834 pub fn i64_trunc_sat_f32_u(self) -> Self {
836 self.execute_unary(<F32 as TruncateSaturateInto<u64>>::truncate_saturate_into)
837 }
838
839 pub fn i64_trunc_sat_f64_s(self) -> Self {
841 self.execute_unary(<F64 as TruncateSaturateInto<i64>>::truncate_saturate_into)
842 }
843
844 pub fn i64_trunc_sat_f64_u(self) -> Self {
846 self.execute_unary(<F64 as TruncateSaturateInto<u64>>::truncate_saturate_into)
847 }
848}
849
850macro_rules! for_each_tuple {
852 ($mac:ident) => {
853 $mac!( 0 );
854 $mac!( 1 T1);
855 $mac!( 2 T1 T2);
856 $mac!( 3 T1 T2 T3);
857 $mac!( 4 T1 T2 T3 T4);
858 $mac!( 5 T1 T2 T3 T4 T5);
859 $mac!( 6 T1 T2 T3 T4 T5 T6);
860 $mac!( 7 T1 T2 T3 T4 T5 T6 T7);
861 $mac!( 8 T1 T2 T3 T4 T5 T6 T7 T8);
862 $mac!( 9 T1 T2 T3 T4 T5 T6 T7 T8 T9);
863 $mac!(10 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10);
864 $mac!(11 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11);
865 $mac!(12 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12);
866 $mac!(13 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13);
867 $mac!(14 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14);
868 $mac!(15 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
869 $mac!(16 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16);
870 }
871}
872
873#[derive(Debug, Copy, Clone)]
875pub enum UntypedError {
876 InvalidLen {
878 expected: usize,
880 found: usize,
882 },
883}
884
885impl UntypedError {
886 #[cold]
888 pub fn invalid_len(expected: usize, found: usize) -> Self {
889 Self::InvalidLen { expected, found }
890 }
891}
892
893impl Display for UntypedError {
894 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
895 match self {
896 UntypedError::InvalidLen { expected, found } => {
897 write!(
898 f,
899 "encountered invalid length for untyped slice. \
900 expected: {expected}, found: {found}"
901 )
902 }
903 }
904 }
905}
906
907impl UntypedValue {
908 pub fn decode_slice<T>(slice: &[Self]) -> Result<T, UntypedError>
919 where
920 T: DecodeUntypedSlice,
921 {
922 <T as DecodeUntypedSlice>::decode_untyped_slice(slice)
923 }
924
925 pub fn encode_slice<T>(slice: &mut [Self], input: T) -> Result<(), UntypedError>
936 where
937 T: EncodeUntypedSlice,
938 {
939 <T as EncodeUntypedSlice>::encode_untyped_slice(input, slice)
940 }
941}
942
943pub trait DecodeUntypedSlice: Sized {
945 fn decode_untyped_slice(params: &[UntypedValue]) -> Result<Self, UntypedError>;
956}
957
958impl<T1> DecodeUntypedSlice for T1
959where
960 T1: From<UntypedValue>,
961{
962 fn decode_untyped_slice(results: &[UntypedValue]) -> Result<Self, UntypedError> {
963 if results.len() != 1 {
964 return Err(UntypedError::invalid_len(1, results.len()));
965 }
966 Ok(<T1 as From<UntypedValue>>::from(results[0]))
967 }
968}
969
970macro_rules! impl_decode_untyped_slice {
971 ( $n:literal $( $tuple:ident )* ) => {
972 impl<$($tuple),*> DecodeUntypedSlice for ($($tuple,)*)
973 where
974 $(
975 $tuple: From<UntypedValue>
976 ),*
977 {
978 #[allow(non_snake_case)]
979 fn decode_untyped_slice(results: &[UntypedValue]) -> Result<Self, UntypedError> {
980 match results {
981 &[$($tuple),*] => Ok((
982 $(
983 <$tuple as From<UntypedValue>>::from($tuple),
984 )*
985 )),
986 _unexpected => {
987 Err(UntypedError::invalid_len($n, results.len()))
988 }
989 }
990 }
991 }
992 };
993}
994for_each_tuple!(impl_decode_untyped_slice);
995
996pub trait EncodeUntypedSlice {
998 fn encode_untyped_slice(self, results: &mut [UntypedValue]) -> Result<(), UntypedError>;
1009}
1010
1011impl<T1> EncodeUntypedSlice for T1
1012where
1013 T1: Into<UntypedValue>,
1014{
1015 fn encode_untyped_slice(self, results: &mut [UntypedValue]) -> Result<(), UntypedError> {
1016 if results.len() != 1 {
1017 return Err(UntypedError::invalid_len(1, results.len()));
1018 }
1019 results[0] = self.into();
1020 Ok(())
1021 }
1022}
1023
1024macro_rules! impl_encode_untyped_slice {
1025 ( $n:literal $( $tuple:ident )* ) => {
1026 impl<$($tuple),*> EncodeUntypedSlice for ($($tuple,)*)
1027 where
1028 $(
1029 $tuple: Into<UntypedValue>
1030 ),*
1031 {
1032 #[allow(non_snake_case)]
1033 fn encode_untyped_slice(self, results: &mut [UntypedValue]) -> Result<(), UntypedError> {
1034 if results.len() != $n {
1035 return Err(UntypedError::invalid_len($n, results.len()))
1036 }
1037 let ($($tuple,)*) = self;
1038 let converted: [UntypedValue; $n] = [
1039 $(
1040 <$tuple as Into<UntypedValue>>::into($tuple)
1041 ),*
1042 ];
1043 results.copy_from_slice(&converted);
1044 Ok(())
1045 }
1046 }
1047 };
1048}
1049for_each_tuple!(impl_encode_untyped_slice);