1use core::fmt::{Debug, Display};
2use core::ops::{Add, Div, Mul, Sub};
3use core::{f32, f64};
4
5use crate::core::reader::types::{NumType, ValType};
6use crate::RefType;
7
8#[derive(Clone, Debug, Copy, PartialOrd)]
9#[repr(transparent)]
10pub struct F32(pub f32);
11
12impl Display for F32 {
13 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14 write!(f, "{}", self.0)
15 }
16}
17
18impl PartialEq for F32 {
19 fn eq(&self, other: &Self) -> bool {
20 self.0.eq(&other.0)
21 }
22}
23
24impl Add for F32 {
25 type Output = Self;
26 fn add(self, rhs: Self) -> Self::Output {
27 Self(self.0 + rhs.0)
28 }
29}
30
31impl Sub for F32 {
32 type Output = Self;
33 fn sub(self, rhs: Self) -> Self::Output {
34 Self(self.0 - rhs.0)
35 }
36}
37
38impl Mul for F32 {
39 type Output = Self;
40 fn mul(self, rhs: Self) -> Self::Output {
41 Self(self.0 * rhs.0)
42 }
43}
44
45impl Div for F32 {
46 type Output = Self;
47 fn div(self, rhs: Self) -> Self::Output {
48 Self(self.0 / rhs.0)
49 }
50}
51
52impl F32 {
53 pub fn abs(&self) -> Self {
54 Self(libm::fabsf(self.0))
55 }
56 pub fn neg(&self) -> Self {
57 Self(-self.0)
58 }
59 pub fn ceil(&self) -> Self {
60 if self.0.is_nan() {
61 return Self(f32::NAN);
62 }
63 Self(libm::ceilf(self.0))
64 }
65 pub fn floor(&self) -> Self {
66 if self.0.is_nan() {
67 return Self(f32::NAN);
68 }
69 Self(libm::floorf(self.0))
70 }
71 pub fn trunc(&self) -> Self {
72 if self.0.is_nan() {
73 return Self(f32::NAN);
74 }
75 Self(libm::truncf(self.0))
76 }
77 pub fn nearest(&self) -> Self {
78 if self.0.is_nan() {
79 return Self(f32::NAN);
80 }
81 Self(libm::rintf(self.0))
82 }
83 pub fn round(&self) -> Self {
84 Self(libm::roundf(self.0))
85 }
86 pub fn sqrt(&self) -> Self {
87 Self(libm::sqrtf(self.0))
88 }
89
90 pub fn min(&self, rhs: Self) -> Self {
91 Self(if self.0.is_nan() || rhs.0.is_nan() {
92 f32::NAN
93 } else if self.0 == 0.0 && rhs.0 == 0.0 {
94 if self.to_bits() >> 31 == 1 {
95 self.0
96 } else {
97 rhs.0
98 }
99 } else {
100 self.0.min(rhs.0)
101 })
102 }
103 pub fn max(&self, rhs: Self) -> Self {
104 Self(if self.0.is_nan() || rhs.0.is_nan() {
105 f32::NAN
106 } else if self.0 == 0.0 && rhs.0 == 0.0 {
107 if self.to_bits() >> 31 == 1 {
108 rhs.0
109 } else {
110 self.0
111 }
112 } else {
113 self.0.max(rhs.0)
114 })
115 }
116 pub fn copysign(&self, rhs: Self) -> Self {
117 Self(libm::copysignf(self.0, rhs.0))
118 }
119 pub fn from_bits(other: u32) -> Self {
120 Self(f32::from_bits(other))
121 }
122 pub fn is_nan(&self) -> bool {
123 self.0.is_nan()
124 }
125 pub fn is_infinity(&self) -> bool {
126 self.0.is_infinite()
127 }
128 pub fn is_negative_infinity(&self) -> bool {
129 self.0.is_infinite() && self.0 < 0.0
130 }
131
132 pub fn as_i32(&self) -> i32 {
133 self.0 as i32
134 }
135 pub fn as_u32(&self) -> u32 {
136 self.0 as u32
137 }
138 pub fn as_i64(&self) -> i64 {
139 self.0 as i64
140 }
141 pub fn as_u64(&self) -> u64 {
142 self.0 as u64
143 }
144 pub fn as_f64(&self) -> F64 {
145 F64(self.0 as f64)
146 }
147 pub fn reinterpret_as_i32(&self) -> i32 {
148 self.0.to_bits() as i32
149 }
150 pub fn to_bits(&self) -> u32 {
151 self.0.to_bits()
152 }
153}
154
155#[derive(Clone, Debug, Copy, PartialOrd)]
156#[repr(transparent)]
157pub struct F64(pub f64);
158
159impl Display for F64 {
160 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
161 write!(f, "{}", self.0)
162 }
163}
164
165impl PartialEq for F64 {
166 fn eq(&self, other: &Self) -> bool {
167 self.0.eq(&other.0)
168 }
169}
170
171impl Add for F64 {
172 type Output = Self;
173 fn add(self, rhs: Self) -> Self::Output {
174 Self(self.0 + rhs.0)
175 }
176}
177
178impl Sub for F64 {
179 type Output = Self;
180 fn sub(self, rhs: Self) -> Self::Output {
181 Self(self.0 - rhs.0)
182 }
183}
184
185impl Mul for F64 {
186 type Output = Self;
187 fn mul(self, rhs: Self) -> Self::Output {
188 Self(self.0 * rhs.0)
189 }
190}
191
192impl Div for F64 {
193 type Output = Self;
194 fn div(self, rhs: Self) -> Self::Output {
195 Self(self.0 / rhs.0)
196 }
197}
198
199impl F64 {
200 pub fn abs(&self) -> Self {
201 Self(libm::fabs(self.0))
202 }
203 pub fn neg(&self) -> Self {
204 Self(-self.0)
205 }
206 pub fn ceil(&self) -> Self {
207 if self.0.is_nan() {
208 return Self(f64::NAN);
209 }
210 Self(libm::ceil(self.0))
211 }
212 pub fn floor(&self) -> Self {
213 if self.0.is_nan() {
214 return Self(f64::NAN);
215 }
216 Self(libm::floor(self.0))
217 }
218 pub fn trunc(&self) -> Self {
219 if self.0.is_nan() {
220 return Self(f64::NAN);
221 }
222 Self(libm::trunc(self.0))
223 }
224 pub fn nearest(&self) -> Self {
225 if self.0.is_nan() {
226 return Self(f64::NAN);
227 }
228 Self(libm::rint(self.0))
229 }
230 pub fn round(&self) -> Self {
231 Self(libm::round(self.0))
232 }
233 pub fn sqrt(&self) -> Self {
234 Self(libm::sqrt(self.0))
235 }
236
237 pub fn min(&self, rhs: Self) -> Self {
238 Self(if self.0.is_nan() || rhs.0.is_nan() {
239 f64::NAN
240 } else if self.0 == 0.0 && rhs.0 == 0.0 {
241 if self.to_bits() >> 63 == 1 {
242 self.0
243 } else {
244 rhs.0
245 }
246 } else {
247 self.0.min(rhs.0)
248 })
249 }
250 pub fn max(&self, rhs: Self) -> Self {
251 Self(if self.0.is_nan() || rhs.0.is_nan() {
252 f64::NAN
253 } else if self.0 == 0.0 && rhs.0 == 0.0 {
254 if self.to_bits() >> 63 == 1 {
255 rhs.0
256 } else {
257 self.0
258 }
259 } else {
260 self.0.max(rhs.0)
261 })
262 }
263 pub fn copysign(&self, rhs: Self) -> Self {
264 Self(libm::copysign(self.0, rhs.0))
265 }
266
267 pub fn from_bits(other: u64) -> Self {
268 Self(f64::from_bits(other))
269 }
270 pub fn is_nan(&self) -> bool {
271 self.0.is_nan()
272 }
273 pub fn is_infinity(&self) -> bool {
274 self.0.is_infinite()
275 }
276 pub fn is_negative_infinity(&self) -> bool {
277 self.0.is_infinite() && self.0 < 0.0
278 }
279
280 pub fn as_i32(&self) -> i32 {
281 self.0 as i32
282 }
283 pub fn as_u32(&self) -> u32 {
284 self.0 as u32
285 }
286 pub fn as_i64(&self) -> i64 {
287 self.0 as i64
288 }
289 pub fn as_u64(&self) -> u64 {
290 self.0 as u64
291 }
292 pub fn as_f32(&self) -> F32 {
293 F32(self.0 as f32)
294 }
295 pub fn reinterpret_as_i64(&self) -> i64 {
296 self.0.to_bits() as i64
297 }
298 pub fn to_bits(&self) -> u64 {
299 self.0.to_bits()
300 }
301}
302
303#[derive(Clone, Copy, Debug, PartialEq)]
308pub enum Value {
309 I32(u32),
310 I64(u64),
311 F32(F32),
312 F64(F64),
313 V128([u8; 16]),
314 Ref(Ref),
315}
316
317#[derive(Clone, Copy, Debug, PartialEq, Eq)]
318pub enum Ref {
319 Null(RefType),
320 Func(FuncAddr),
321 Extern(ExternAddr),
322}
323
324impl Display for Ref {
325 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
326 match self {
327 Ref::Func(func_addr) => write!(f, "FuncRef({func_addr:?})"),
328 Ref::Extern(extern_addr) => write!(f, "ExternRef({extern_addr:?})"),
329 Ref::Null(ty) => write!(f, "Null({ty:?})"),
330 }
331 }
332}
333
334#[derive(Debug, Clone, Copy, PartialEq, Eq)]
344pub struct FuncAddr(pub usize);
345
346#[derive(Debug, Clone, Copy, PartialEq, Eq)]
355pub struct ExternAddr(pub usize);
356
357#[derive(Clone, Copy, Debug, PartialEq)]
358pub enum RefValueTy {
359 Func,
360 Extern,
361}
362
363impl Value {
364 pub fn default_from_ty(ty: ValType) -> Self {
365 match ty {
366 ValType::NumType(NumType::I32) => Self::I32(0),
367 ValType::NumType(NumType::I64) => Self::I64(0),
368 ValType::NumType(NumType::F32) => Self::F32(F32(0.0)),
369 ValType::NumType(NumType::F64) => Self::F64(F64(0.0_f64)),
370 ValType::RefType(ref_type) => Self::Ref(Ref::Null(ref_type)),
371 ValType::VecType => Self::V128([0; 16]),
372 }
373 }
374
375 pub fn to_ty(&self) -> ValType {
376 match self {
377 Value::I32(_) => ValType::NumType(NumType::I32),
378 Value::I64(_) => ValType::NumType(NumType::I64),
379 Value::F32(_) => ValType::NumType(NumType::F32),
380 Value::F64(_) => ValType::NumType(NumType::F64),
381 Value::Ref(Ref::Null(ref_type)) => ValType::RefType(*ref_type),
382 Value::Ref(Ref::Func(_)) => ValType::RefType(RefType::FuncRef),
383 Value::Ref(Ref::Extern(_)) => ValType::RefType(RefType::ExternRef),
384 Value::V128(_) => ValType::VecType,
385 }
386 }
387}
388
389impl From<u32> for Value {
390 fn from(x: u32) -> Self {
391 Value::I32(x)
392 }
393}
394impl TryFrom<Value> for u32 {
395 type Error = ();
396
397 fn try_from(value: Value) -> Result<Self, Self::Error> {
398 match value {
399 Value::I32(x) => Ok(x),
400 _ => Err(()),
401 }
402 }
403}
404
405impl From<i32> for Value {
406 fn from(x: i32) -> Self {
407 Value::I32(x as u32)
408 }
409}
410impl TryFrom<Value> for i32 {
411 type Error = ();
412
413 fn try_from(value: Value) -> Result<Self, Self::Error> {
414 match value {
415 Value::I32(x) => Ok(x as i32),
416 _ => Err(()),
417 }
418 }
419}
420
421impl From<u64> for Value {
422 fn from(x: u64) -> Self {
423 Value::I64(x)
424 }
425}
426impl TryFrom<Value> for u64 {
427 type Error = ();
428
429 fn try_from(value: Value) -> Result<Self, Self::Error> {
430 match value {
431 Value::I64(x) => Ok(x),
432 _ => Err(()),
433 }
434 }
435}
436impl From<i64> for Value {
437 fn from(x: i64) -> Self {
438 Value::I64(x as u64)
439 }
440}
441impl TryFrom<Value> for i64 {
442 type Error = ();
443
444 fn try_from(value: Value) -> Result<Self, Self::Error> {
445 match value {
446 Value::I64(x) => Ok(x as i64),
447 _ => Err(()),
448 }
449 }
450}
451
452impl From<F32> for Value {
453 fn from(x: F32) -> Self {
454 Value::F32(x)
455 }
456}
457impl TryFrom<Value> for F32 {
458 type Error = ();
459
460 fn try_from(value: Value) -> Result<Self, Self::Error> {
461 match value {
462 Value::F32(x) => Ok(x),
463 _ => Err(()),
464 }
465 }
466}
467
468impl From<F64> for Value {
469 fn from(x: F64) -> Self {
470 Value::F64(x)
471 }
472}
473impl TryFrom<Value> for F64 {
474 type Error = ();
475
476 fn try_from(value: Value) -> Result<Self, Self::Error> {
477 match value {
478 Value::F64(x) => Ok(x),
479 _ => Err(()),
480 }
481 }
482}
483
484impl From<[u8; 16]> for Value {
485 fn from(value: [u8; 16]) -> Self {
486 Value::V128(value)
487 }
488}
489impl TryFrom<Value> for [u8; 16] {
490 type Error = ();
491
492 fn try_from(value: Value) -> Result<Self, Self::Error> {
493 match value {
494 Value::V128(x) => Ok(x),
495 _ => Err(()),
496 }
497 }
498}
499
500impl From<Ref> for Value {
501 fn from(value: Ref) -> Self {
502 Self::Ref(value)
503 }
504}
505
506impl TryFrom<Value> for Ref {
507 type Error = ();
508
509 fn try_from(value: Value) -> Result<Self, ()> {
510 match value {
511 Value::Ref(rref) => Ok(rref),
512 _ => Err(()),
513 }
514 }
515}
516
517#[cfg(test)]
518mod test {
519 use alloc::string::ToString;
520
521 use crate::{
522 value::{ExternAddr, F32, F64},
523 RefType,
524 };
525
526 use super::{FuncAddr, Ref};
527
528 #[test]
529 fn rounding_f32() {
530 let round_towards_0_f32 = F32(0.5 - f32::EPSILON).round();
531 let round_towards_1_f32 = F32(0.5 + f32::EPSILON).round();
532
533 assert_eq!(round_towards_0_f32, F32(0.0));
534 assert_eq!(round_towards_1_f32, F32(1.0));
535 }
536
537 #[test]
538 fn rounding_f64() {
539 let round_towards_0_f64 = F64(0.5 - f64::EPSILON).round();
540 let round_towards_1_f64 = F64(0.5 + f64::EPSILON).round();
541
542 assert_eq!(round_towards_0_f64, F64(0.0));
543 assert_eq!(round_towards_1_f64, F64(1.0));
544 }
545
546 #[test]
547 fn display_f32() {
548 for x in [
549 -1.0,
550 0.0,
551 1.0,
552 13.3,
553 f32::INFINITY,
554 f32::MAX,
555 f32::MIN,
556 f32::NAN,
557 f32::NEG_INFINITY,
558 core::f32::consts::PI,
559 ] {
560 let wrapped = F32(x).to_string();
561 let expected = x.to_string();
562 assert_eq!(wrapped, expected);
563 }
564 }
565
566 #[test]
567 fn display_f64() {
568 for x in [
569 -1.0,
570 0.0,
571 1.0,
572 13.3,
573 f64::INFINITY,
574 f64::MAX,
575 f64::MIN,
576 f64::NAN,
577 f64::NEG_INFINITY,
578 core::f64::consts::PI,
579 ] {
580 let wrapped = F64(x).to_string();
581 let expected = x.to_string();
582 assert_eq!(wrapped, expected);
583 }
584 }
585
586 #[test]
587 fn display_ref() {
588 assert_eq!(Ref::Func(FuncAddr(11)).to_string(), "FuncRef(FuncAddr(11))");
589 assert_eq!(
590 Ref::Extern(ExternAddr(13)).to_string(),
591 "ExternRef(ExternAddr(13))"
592 );
593 assert_eq!(Ref::Null(RefType::FuncRef).to_string(), "Null(FuncRef)");
594 assert_eq!(Ref::Null(RefType::ExternRef).to_string(), "Null(ExternRef)");
595 }
596}