1use alloc::vec;
2use alloc::vec::Vec;
3use core::fmt::{Debug, Display};
4use core::ops::{Add, Div, Mul, Sub};
5use core::{f32, f64};
6
7use crate::core::reader::types::{NumType, ValType};
8use crate::execution::assert_validated::UnwrapValidatedExt;
9use crate::{unreachable_validated, Error, RefType, Result};
10
11#[derive(Clone, Debug, Copy, PartialOrd)]
12pub struct F32(pub f32);
13
14impl Display for F32 {
15 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16 write!(f, "{}", self.0)
17 }
18}
19
20impl PartialEq for F32 {
21 fn eq(&self, other: &Self) -> bool {
22 self.0.eq(&other.0)
23 }
24}
25
26impl Add for F32 {
27 type Output = Self;
28 fn add(self, rhs: Self) -> Self::Output {
29 Self(self.0 + rhs.0)
30 }
31}
32
33impl Sub for F32 {
34 type Output = Self;
35 fn sub(self, rhs: Self) -> Self::Output {
36 Self(self.0 - rhs.0)
37 }
38}
39
40impl Mul for F32 {
41 type Output = Self;
42 fn mul(self, rhs: Self) -> Self::Output {
43 Self(self.0 * rhs.0)
44 }
45}
46
47impl Div for F32 {
48 type Output = Self;
49 fn div(self, rhs: Self) -> Self::Output {
50 Self(self.0 / rhs.0)
51 }
52}
53
54impl F32 {
55 pub fn abs(&self) -> Self {
56 Self(libm::fabsf(self.0))
57 }
58 pub fn neg(&self) -> Self {
59 Self(-self.0)
60 }
61 pub fn ceil(&self) -> Self {
62 if self.0.is_nan() {
63 return Self(f32::NAN);
64 }
65 Self(libm::ceilf(self.0))
66 }
67 pub fn floor(&self) -> Self {
68 if self.0.is_nan() {
69 return Self(f32::NAN);
70 }
71 Self(libm::floorf(self.0))
72 }
73 pub fn trunc(&self) -> Self {
74 if self.0.is_nan() {
75 return Self(f32::NAN);
76 }
77 Self(libm::truncf(self.0))
78 }
79 pub fn nearest(&self) -> Self {
80 if self.0.is_nan() {
81 return Self(f32::NAN);
82 }
83 Self(libm::rintf(self.0))
84 }
85 pub fn round(&self) -> Self {
86 Self(libm::roundf(self.0))
87 }
88 pub fn sqrt(&self) -> Self {
89 Self(libm::sqrtf(self.0))
90 }
91
92 pub fn min(&self, rhs: Self) -> Self {
93 Self(if self.0.is_nan() || rhs.0.is_nan() {
94 f32::NAN
95 } else if self.0 == 0.0 && rhs.0 == 0.0 {
96 if self.to_bits() >> 31 == 1 {
97 self.0
98 } else {
99 rhs.0
100 }
101 } else {
102 self.0.min(rhs.0)
103 })
104 }
105 pub fn max(&self, rhs: Self) -> Self {
106 Self(if self.0.is_nan() || rhs.0.is_nan() {
107 f32::NAN
108 } else if self.0 == 0.0 && rhs.0 == 0.0 {
109 if self.to_bits() >> 31 == 1 {
110 rhs.0
111 } else {
112 self.0
113 }
114 } else {
115 self.0.max(rhs.0)
116 })
117 }
118 pub fn copysign(&self, rhs: Self) -> Self {
119 Self(libm::copysignf(self.0, rhs.0))
120 }
121 pub fn from_bits(other: u32) -> Self {
122 Self(f32::from_bits(other))
123 }
124 pub fn is_nan(&self) -> bool {
125 self.0.is_nan()
126 }
127 pub fn is_infinity(&self) -> bool {
128 self.0.is_infinite()
129 }
130 pub fn is_negative_infinity(&self) -> bool {
131 self.0.is_infinite() && self.0 < 0.0
132 }
133
134 pub fn as_i32(&self) -> i32 {
135 self.0 as i32
136 }
137 pub fn as_u32(&self) -> u32 {
138 self.0 as u32
139 }
140 pub fn as_i64(&self) -> i64 {
141 self.0 as i64
142 }
143 pub fn as_u64(&self) -> u64 {
144 self.0 as u64
145 }
146 pub fn as_f32(&self) -> F64 {
147 F64(self.0 as f64)
148 }
149 pub fn reinterpret_as_i32(&self) -> i32 {
150 self.0.to_bits() as i32
151 }
152 pub fn to_bits(&self) -> u32 {
153 self.0.to_bits()
154 }
155}
156
157#[derive(Clone, Debug, Copy, PartialOrd)]
158pub struct F64(pub f64);
159
160impl Display for F64 {
161 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162 write!(f, "{}", self.0)
163 }
164}
165
166impl PartialEq for F64 {
167 fn eq(&self, other: &Self) -> bool {
168 self.0.eq(&other.0)
169 }
170}
171
172impl Add for F64 {
173 type Output = Self;
174 fn add(self, rhs: Self) -> Self::Output {
175 Self(self.0 + rhs.0)
176 }
177}
178
179impl Sub for F64 {
180 type Output = Self;
181 fn sub(self, rhs: Self) -> Self::Output {
182 Self(self.0 - rhs.0)
183 }
184}
185
186impl Mul for F64 {
187 type Output = Self;
188 fn mul(self, rhs: Self) -> Self::Output {
189 Self(self.0 * rhs.0)
190 }
191}
192
193impl Div for F64 {
194 type Output = Self;
195 fn div(self, rhs: Self) -> Self::Output {
196 Self(self.0 / rhs.0)
197 }
198}
199
200impl F64 {
201 pub fn abs(&self) -> Self {
202 Self(libm::fabs(self.0))
203 }
204 pub fn neg(&self) -> Self {
205 Self(-self.0)
206 }
207 pub fn ceil(&self) -> Self {
208 if self.0.is_nan() {
209 return Self(f64::NAN);
210 }
211 Self(libm::ceil(self.0))
212 }
213 pub fn floor(&self) -> Self {
214 if self.0.is_nan() {
215 return Self(f64::NAN);
216 }
217 Self(libm::floor(self.0))
218 }
219 pub fn trunc(&self) -> Self {
220 if self.0.is_nan() {
221 return Self(f64::NAN);
222 }
223 Self(libm::trunc(self.0))
224 }
225 pub fn nearest(&self) -> Self {
226 if self.0.is_nan() {
227 return Self(f64::NAN);
228 }
229 Self(libm::rint(self.0))
230 }
231 pub fn round(&self) -> Self {
232 Self(libm::round(self.0))
233 }
234 pub fn sqrt(&self) -> Self {
235 Self(libm::sqrt(self.0))
236 }
237
238 pub fn min(&self, rhs: Self) -> Self {
239 Self(if self.0.is_nan() || rhs.0.is_nan() {
240 f64::NAN
241 } else if self.0 == 0.0 && rhs.0 == 0.0 {
242 if self.to_bits() >> 63 == 1 {
243 self.0
244 } else {
245 rhs.0
246 }
247 } else {
248 self.0.min(rhs.0)
249 })
250 }
251 pub fn max(&self, rhs: Self) -> Self {
252 Self(if self.0.is_nan() || rhs.0.is_nan() {
253 f64::NAN
254 } else if self.0 == 0.0 && rhs.0 == 0.0 {
255 if self.to_bits() >> 63 == 1 {
256 rhs.0
257 } else {
258 self.0
259 }
260 } else {
261 self.0.max(rhs.0)
262 })
263 }
264 pub fn copysign(&self, rhs: Self) -> Self {
265 Self(libm::copysign(self.0, rhs.0))
266 }
267
268 pub fn from_bits(other: u64) -> Self {
269 Self(f64::from_bits(other))
270 }
271 pub fn is_nan(&self) -> bool {
272 self.0.is_nan()
273 }
274 pub fn is_infinity(&self) -> bool {
275 self.0.is_infinite()
276 }
277 pub fn is_negative_infinity(&self) -> bool {
278 self.0.is_infinite() && self.0 < 0.0
279 }
280
281 pub fn as_i32(&self) -> i32 {
282 self.0 as i32
283 }
284 pub fn as_u32(&self) -> u32 {
285 self.0 as u32
286 }
287 pub fn as_i64(&self) -> i64 {
288 self.0 as i64
289 }
290 pub fn as_u64(&self) -> u64 {
291 self.0 as u64
292 }
293 pub fn as_f32(&self) -> F32 {
294 F32(self.0 as f32)
295 }
296 pub fn reinterpret_as_i64(&self) -> i64 {
297 self.0.to_bits() as i64
298 }
299 pub fn to_bits(&self) -> u64 {
300 self.0.to_bits()
301 }
302}
303
304#[derive(Clone, Copy, Debug, PartialEq)]
309pub enum Value {
310 I32(u32),
311 I64(u64),
312 F32(F32),
313 F64(F64),
314 Ref(Ref),
317}
318
319#[derive(Clone, Copy, Debug, PartialEq)]
320pub enum Ref {
321 Func(FuncAddr),
322 Extern(ExternAddr),
323}
324
325impl Ref {
326 pub fn default_from_ref_type(rref: RefType) -> Self {
327 match rref {
328 RefType::ExternRef => Self::Extern(ExternAddr::default()),
329 RefType::FuncRef => Self::Func(FuncAddr::default()),
330 }
331 }
332
333 pub fn is_null(&self) -> bool {
334 match self {
335 Self::Extern(extern_addr) => extern_addr.addr.is_none(),
336 Self::Func(func_addr) => func_addr.addr.is_none(),
337 }
338 }
339
340 pub fn is_specific_func(&self, func_id: u32) -> bool {
341 match self {
342 Self::Func(func_addr) => func_addr.addr == Some(func_id as usize),
343 _ => unreachable!(),
344 }
345 }
346}
347
348impl Display for Ref {
349 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
350 match self {
351 Ref::Func(func_addr) => write!(f, "FuncRef({:?})", func_addr),
352 Ref::Extern(extern_addr) => write!(f, "ExternRef({:?})", extern_addr),
353 }
354 }
355}
356
357#[derive(Clone, Copy, PartialEq)]
367pub struct FuncAddr {
368 pub addr: Option<usize>,
369}
370
371impl Debug for FuncAddr {
372 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
373 match self.addr.is_none() {
374 false => write!(f, "FuncAddr {{\n\taddr: {}\n}}", self.addr.unwrap()),
375 true => write!(f, "FuncAddr {{ NULL }}"),
376 }
377 }
378}
379
380impl FuncAddr {
381 pub fn new(addr: Option<usize>) -> Self {
382 match addr {
383 None => Self::null(),
384 Some(u) => Self { addr: Some(u) },
385 }
386 }
387 pub fn null() -> Self {
388 Self { addr: None }
389 }
390 pub fn is_null(&self) -> bool {
391 self.addr.is_none()
392 }
393}
394
395impl Default for FuncAddr {
396 fn default() -> Self {
397 Self::null()
398 }
399}
400
401#[derive(Clone, Copy, Debug, PartialEq)]
410pub struct ExternAddr {
411 pub addr: Option<usize>,
412}
413
414impl ExternAddr {
415 pub fn new(addr: Option<usize>) -> Self {
416 match addr {
417 None => Self::null(),
418 Some(u) => Self { addr: Some(u) },
419 }
420 }
421 pub fn null() -> Self {
422 Self { addr: None }
423 }
424}
425
426impl Default for ExternAddr {
427 fn default() -> Self {
428 Self::null()
429 }
430}
431
432#[derive(Clone, Copy, Debug, PartialEq)]
433pub enum RefValueTy {
434 Func,
435 Extern,
436}
437
438impl Value {
439 pub fn default_from_ty(ty: ValType) -> Self {
440 match ty {
441 ValType::NumType(NumType::I32) => Self::I32(0),
442 ValType::NumType(NumType::I64) => Self::I64(0),
443 ValType::NumType(NumType::F32) => Self::F32(F32(0.0)),
444 ValType::NumType(NumType::F64) => Self::F64(F64(0.0_f64)),
445 ValType::RefType(RefType::ExternRef) => Self::Ref(Ref::Extern(ExternAddr::null())),
446 ValType::RefType(RefType::FuncRef) => Self::Ref(Ref::Func(FuncAddr::null())),
447 other => {
448 todo!("cannot determine type for {other:?} because this value is not supported yet")
449 }
450 }
451 }
452
453 pub fn to_ty(&self) -> ValType {
454 match self {
455 Value::I32(_) => ValType::NumType(NumType::I32),
456 Value::I64(_) => ValType::NumType(NumType::I64),
457 Value::F32(_) => ValType::NumType(NumType::F32),
458 Value::F64(_) => ValType::NumType(NumType::F64),
459 Value::Ref(rref) => match rref {
460 Ref::Extern(_) => ValType::RefType(RefType::ExternRef),
461 Ref::Func(_) => ValType::RefType(RefType::FuncRef),
462 },
463 }
464 }
465}
466
467pub trait InteropValue: Copy + Debug + PartialEq {
472 const TY: ValType;
475 #[allow(warnings)]
476 fn into_value(self) -> Value;
477 #[allow(warnings)]
478 fn from_value(value: Value) -> Self;
479}
480
481pub trait InteropValueList {
483 const TYS: &'static [ValType];
484 #[allow(warnings)]
485 fn into_values(self) -> Vec<Value>;
486 #[allow(warnings)]
487 fn from_values(values: impl Iterator<Item = Value>) -> Self;
488}
489
490impl InteropValue for u32 {
491 const TY: ValType = ValType::NumType(NumType::I32);
492 #[allow(warnings)]
493 fn into_value(self) -> Value {
494 Value::I32(self)
495 }
496
497 #[allow(warnings)]
498 fn from_value(value: Value) -> Self {
499 match value {
500 Value::I32(i) => i,
501 _ => unreachable_validated!(),
502 }
503 }
504}
505
506impl InteropValue for i32 {
507 const TY: ValType = ValType::NumType(NumType::I32);
508
509 #[allow(warnings)]
510 fn into_value(self) -> Value {
511 Value::I32(u32::from_le_bytes(self.to_le_bytes()))
512 }
513
514 #[allow(warnings)]
515 fn from_value(value: Value) -> Self {
516 match value {
517 Value::I32(i) => i32::from_le_bytes(i.to_le_bytes()),
518 _ => unreachable_validated!(),
519 }
520 }
521}
522
523impl InteropValue for u64 {
524 const TY: ValType = ValType::NumType(NumType::I64);
525
526 #[allow(warnings)]
527 fn into_value(self) -> Value {
528 Value::I64(self)
529 }
530
531 #[allow(warnings)]
532 fn from_value(value: Value) -> Self {
533 match value {
534 Value::I64(i) => i,
535 _ => unreachable_validated!(),
536 }
537 }
538}
539
540impl InteropValue for i64 {
541 const TY: ValType = ValType::NumType(NumType::I64);
542
543 #[allow(warnings)]
544 fn into_value(self) -> Value {
545 Value::I64(u64::from_le_bytes(self.to_le_bytes()))
546 }
547
548 #[allow(warnings)]
549 fn from_value(value: Value) -> Self {
550 match value {
551 Value::I64(i) => i64::from_le_bytes(i.to_le_bytes()),
552 _ => unreachable_validated!(),
553 }
554 }
555}
556
557impl InteropValue for F32 {
558 const TY: ValType = ValType::NumType(NumType::F32);
559
560 #[allow(warnings)]
561 fn into_value(self) -> Value {
562 Value::F32(F32(f32::from_le_bytes(self.0.to_le_bytes())))
563 }
564
565 #[allow(warnings)]
566 fn from_value(value: Value) -> Self {
567 match value {
568 Value::F32(f) => F32(f32::from_le_bytes(f.0.to_le_bytes())),
569 _ => unreachable_validated!(),
570 }
571 }
572}
573
574impl InteropValue for f32 {
575 const TY: ValType = ValType::NumType(NumType::F32);
576
577 #[allow(warnings)]
578 fn into_value(self) -> Value {
579 Value::F32(F32(f32::from_le_bytes(self.to_le_bytes())))
580 }
581
582 #[allow(warnings)]
583 fn from_value(value: Value) -> Self {
584 match value {
585 Value::F32(f) => f32::from_le_bytes(f.0.to_le_bytes()),
586 _ => unreachable_validated!(),
587 }
588 }
589}
590
591impl InteropValue for F64 {
592 const TY: ValType = ValType::NumType(NumType::F64);
593
594 #[allow(warnings)]
595 fn into_value(self) -> Value {
596 Value::F64(F64(f64::from_le_bytes(self.0.to_le_bytes())))
597 }
598
599 #[allow(warnings)]
600 fn from_value(value: Value) -> Self {
601 match value {
602 Value::F64(f) => F64(f64::from_le_bytes(f.0.to_le_bytes())),
603 _ => unreachable_validated!(),
604 }
605 }
606}
607
608impl InteropValue for f64 {
609 const TY: ValType = ValType::NumType(NumType::F64);
610
611 #[allow(warnings)]
612 fn into_value(self) -> Value {
613 Value::F64(F64(f64::from_le_bytes(self.to_le_bytes())))
614 }
615
616 #[allow(warnings)]
617 fn from_value(value: Value) -> Self {
618 match value {
619 Value::F64(f) => f64::from_le_bytes(f.0.to_le_bytes()),
620 _ => unreachable_validated!(),
621 }
622 }
623}
624
625#[derive(PartialEq, Debug, Copy, Clone)]
626pub struct FuncRefForInteropValue {
627 rref: Ref,
628}
629
630impl FuncRefForInteropValue {
631 pub fn new(rref: Ref) -> Result<Self> {
632 match rref {
633 Ref::Extern(_) => Err(Error::WrongRefTypeForInteropValue(
634 RefType::ExternRef,
635 RefType::FuncRef,
636 )),
637 Ref::Func(_) => Ok(Self { rref }),
638 }
639 }
640
641 pub fn get_ref(&self) -> Ref {
642 self.rref
643 }
644}
645
646impl InteropValue for FuncRefForInteropValue {
647 const TY: ValType = ValType::RefType(RefType::FuncRef);
648
649 #[allow(warnings)]
650 fn into_value(self) -> Value {
651 Value::Ref(self.rref)
652 }
653
654 #[allow(warnings)]
655 fn from_value(value: Value) -> Self {
656 match value {
657 Value::Ref(rref) => unsafe { FuncRefForInteropValue::new(rref).unwrap_unchecked() },
658 _ => unreachable_validated!(),
659 }
660 }
661}
662
663impl InteropValueList for () {
664 const TYS: &'static [ValType] = &[];
665
666 #[allow(warnings)]
667 fn into_values(self) -> Vec<Value> {
668 Vec::new()
669 }
670
671 #[allow(warnings)]
672 fn from_values(_values: impl Iterator<Item = Value>) -> Self {}
673}
674
675impl<A: InteropValue> InteropValueList for A {
676 const TYS: &'static [ValType] = &[A::TY];
677
678 #[allow(warnings)]
679 fn into_values(self) -> Vec<Value> {
680 vec![self.into_value()]
681 }
682
683 #[allow(warnings)]
684 fn from_values(mut values: impl Iterator<Item = Value>) -> Self {
685 A::from_value(values.next().unwrap_validated())
686 }
687}
688
689impl<A: InteropValue> InteropValueList for (A,) {
690 const TYS: &'static [ValType] = &[A::TY];
691 #[allow(warnings)]
692 fn into_values(self) -> Vec<Value> {
693 vec![self.0.into_value()]
694 }
695
696 #[allow(warnings)]
697 fn from_values(mut values: impl Iterator<Item = Value>) -> Self {
698 (A::from_value(values.next().unwrap_validated()),)
699 }
700}
701
702impl<A: InteropValue, B: InteropValue> InteropValueList for (A, B) {
703 const TYS: &'static [ValType] = &[A::TY, B::TY];
704 #[allow(warnings)]
705 fn into_values(self) -> Vec<Value> {
706 vec![self.0.into_value(), self.1.into_value()]
707 }
708
709 #[allow(warnings)]
710 fn from_values(mut values: impl Iterator<Item = Value>) -> Self {
711 (
712 A::from_value(values.next().unwrap_validated()),
713 B::from_value(values.next().unwrap_validated()),
714 )
715 }
716}
717
718impl<A: InteropValue, B: InteropValue, C: InteropValue> InteropValueList for (A, B, C) {
719 const TYS: &'static [ValType] = &[A::TY, B::TY, C::TY];
720 #[allow(warnings)]
721 fn into_values(self) -> Vec<Value> {
722 vec![
723 self.0.into_value(),
724 self.1.into_value(),
725 self.2.into_value(),
726 ]
727 }
728
729 #[allow(warnings)]
730 fn from_values(mut values: impl Iterator<Item = Value>) -> Self {
731 (
732 A::from_value(values.next().unwrap_validated()),
733 B::from_value(values.next().unwrap_validated()),
734 C::from_value(values.next().unwrap_validated()),
735 )
736 }
737}
738
739impl From<f32> for Value {
741 fn from(x: f32) -> Self {
742 F32(x).into_value()
743 }
744}
745
746impl From<Value> for f32 {
747 fn from(value: Value) -> Self {
748 F32::from(value).0
749 }
750}
751
752impl From<f64> for Value {
754 fn from(x: f64) -> Self {
755 F64(x).into_value()
756 }
757}
758
759impl From<Value> for f64 {
760 fn from(value: Value) -> Self {
761 F64::from(value).0
762 }
763}
764
765macro_rules! impl_value_conversion {
767 ($ty:ty) => {
768 impl From<$ty> for Value {
769 fn from(x: $ty) -> Self {
770 x.into_value()
771 }
772 }
773 impl From<Value> for $ty {
774 fn from(value: Value) -> Self {
775 <$ty>::from_value(value)
776 }
777 }
778 };
779}
780
781impl_value_conversion!(u32);
782impl_value_conversion!(i32);
783impl_value_conversion!(u64);
784impl_value_conversion!(i64);
785impl_value_conversion!(F32);
786impl_value_conversion!(F64);
787
788impl From<Ref> for Value {
789 fn from(value: Ref) -> Self {
790 Self::Ref(value)
791 }
792}
793
794impl From<Value> for Ref {
795 fn from(value: Value) -> Self {
796 match value {
797 Value::Ref(rref) => rref,
798 _ => unreachable!(),
799 }
800 }
801}