1use core::fmt::{Debug, Display};
2use core::ops::{Add, Div, Mul, Sub};
3use core::{f32, f64};
4
5use crate::addrs::FuncAddr;
6use crate::core::reader::types::{NumType, ValType};
7use crate::RefType;
8
9#[derive(Clone, Debug, Copy, PartialOrd)]
10#[repr(transparent)]
11pub struct F32(pub f32);
12
13impl Display for F32 {
14 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15 write!(f, "{}", self.0)
16 }
17}
18
19impl PartialEq for F32 {
20 fn eq(&self, other: &Self) -> bool {
21 self.0.eq(&other.0)
22 }
23}
24
25impl Add for F32 {
26 type Output = Self;
27 fn add(self, rhs: Self) -> Self::Output {
28 Self(self.0 + rhs.0)
29 }
30}
31
32impl Sub for F32 {
33 type Output = Self;
34 fn sub(self, rhs: Self) -> Self::Output {
35 Self(self.0 - rhs.0)
36 }
37}
38
39impl Mul for F32 {
40 type Output = Self;
41 fn mul(self, rhs: Self) -> Self::Output {
42 Self(self.0 * rhs.0)
43 }
44}
45
46impl Div for F32 {
47 type Output = Self;
48 fn div(self, rhs: Self) -> Self::Output {
49 Self(self.0 / rhs.0)
50 }
51}
52
53impl F32 {
54 pub fn abs(&self) -> Self {
55 Self(libm::fabsf(self.0))
56 }
57 pub fn neg(&self) -> Self {
58 Self(-self.0)
59 }
60 pub fn ceil(&self) -> Self {
61 if self.0.is_nan() {
62 return Self(f32::NAN);
63 }
64 Self(libm::ceilf(self.0))
65 }
66 pub fn floor(&self) -> Self {
67 if self.0.is_nan() {
68 return Self(f32::NAN);
69 }
70 Self(libm::floorf(self.0))
71 }
72 pub fn trunc(&self) -> Self {
73 if self.0.is_nan() {
74 return Self(f32::NAN);
75 }
76 Self(libm::truncf(self.0))
77 }
78 pub fn nearest(&self) -> Self {
79 if self.0.is_nan() {
80 return Self(f32::NAN);
81 }
82 Self(libm::rintf(self.0))
83 }
84 pub fn round(&self) -> Self {
85 Self(libm::roundf(self.0))
86 }
87 pub fn sqrt(&self) -> Self {
88 Self(libm::sqrtf(self.0))
89 }
90
91 pub fn min(&self, rhs: Self) -> Self {
92 Self(if self.0.is_nan() || rhs.0.is_nan() {
93 f32::NAN
94 } else if self.0 == 0.0 && rhs.0 == 0.0 {
95 if self.to_bits() >> 31 == 1 {
96 self.0
97 } else {
98 rhs.0
99 }
100 } else {
101 self.0.min(rhs.0)
102 })
103 }
104 pub fn max(&self, rhs: Self) -> Self {
105 Self(if self.0.is_nan() || rhs.0.is_nan() {
106 f32::NAN
107 } else if self.0 == 0.0 && rhs.0 == 0.0 {
108 if self.to_bits() >> 31 == 1 {
109 rhs.0
110 } else {
111 self.0
112 }
113 } else {
114 self.0.max(rhs.0)
115 })
116 }
117 pub fn copysign(&self, rhs: Self) -> Self {
118 Self(libm::copysignf(self.0, rhs.0))
119 }
120 pub fn from_bits(other: u32) -> Self {
121 Self(f32::from_bits(other))
122 }
123 pub fn is_nan(&self) -> bool {
124 self.0.is_nan()
125 }
126 pub fn is_infinity(&self) -> bool {
127 self.0.is_infinite()
128 }
129 pub fn is_negative_infinity(&self) -> bool {
130 self.0.is_infinite() && self.0 < 0.0
131 }
132
133 pub fn as_i32(&self) -> i32 {
134 self.0 as i32
135 }
136 pub fn as_u32(&self) -> u32 {
137 self.0 as u32
138 }
139 pub fn as_i64(&self) -> i64 {
140 self.0 as i64
141 }
142 pub fn as_u64(&self) -> u64 {
143 self.0 as u64
144 }
145 pub fn as_f64(&self) -> F64 {
146 F64(self.0 as f64)
147 }
148 pub fn reinterpret_as_i32(&self) -> i32 {
149 self.0.to_bits() as i32
150 }
151 pub fn to_bits(&self) -> u32 {
152 self.0.to_bits()
153 }
154}
155
156#[derive(Clone, Debug, Copy, PartialOrd)]
157#[repr(transparent)]
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 V128([u8; 16]),
315 Ref(Ref),
316}
317
318#[derive(Clone, Copy, Debug, PartialEq, Eq)]
319pub enum Ref {
320 Null(RefType),
321 Func(FuncAddr),
322 Extern(ExternAddr),
323}
324
325impl Display for Ref {
326 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
327 match self {
328 Ref::Func(func_addr) => write!(f, "FuncRef({func_addr:?})"),
329 Ref::Extern(extern_addr) => write!(f, "ExternRef({extern_addr:?})"),
330 Ref::Null(ty) => write!(f, "Null({ty:?})"),
331 }
332 }
333}
334
335impl Ref {
336 pub fn ty(self) -> RefType {
337 match self {
338 Ref::Null(ref_type) => ref_type,
339 Ref::Func(_) => RefType::FuncRef,
340 Ref::Extern(_) => RefType::ExternRef,
341 }
342 }
343}
344
345#[derive(Debug, Clone, Copy, PartialEq, Eq)]
354pub struct ExternAddr(pub usize);
355
356impl Value {
357 pub fn default_from_ty(ty: ValType) -> Self {
358 match ty {
359 ValType::NumType(NumType::I32) => Self::I32(0),
360 ValType::NumType(NumType::I64) => Self::I64(0),
361 ValType::NumType(NumType::F32) => Self::F32(F32(0.0)),
362 ValType::NumType(NumType::F64) => Self::F64(F64(0.0_f64)),
363 ValType::RefType(ref_type) => Self::Ref(Ref::Null(ref_type)),
364 ValType::VecType => Self::V128([0; 16]),
365 }
366 }
367
368 pub fn to_ty(&self) -> ValType {
369 match self {
370 Value::I32(_) => ValType::NumType(NumType::I32),
371 Value::I64(_) => ValType::NumType(NumType::I64),
372 Value::F32(_) => ValType::NumType(NumType::F32),
373 Value::F64(_) => ValType::NumType(NumType::F64),
374 Value::Ref(Ref::Null(ref_type)) => ValType::RefType(*ref_type),
375 Value::Ref(Ref::Func(_)) => ValType::RefType(RefType::FuncRef),
376 Value::Ref(Ref::Extern(_)) => ValType::RefType(RefType::ExternRef),
377 Value::V128(_) => ValType::VecType,
378 }
379 }
380}
381
382#[derive(Debug, PartialEq, Eq)]
384pub struct ValueTypeMismatchError;
385
386impl Display for ValueTypeMismatchError {
387 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
388 f.write_str("failed to convert Value to a Rust value because the types did not match")
389 }
390}
391
392impl From<u32> for Value {
393 fn from(x: u32) -> Self {
394 Value::I32(x)
395 }
396}
397impl TryFrom<Value> for u32 {
398 type Error = ValueTypeMismatchError;
399
400 fn try_from(value: Value) -> Result<Self, Self::Error> {
401 match value {
402 Value::I32(x) => Ok(x),
403 _ => Err(ValueTypeMismatchError),
404 }
405 }
406}
407
408impl From<i32> for Value {
409 fn from(x: i32) -> Self {
410 Value::I32(x as u32)
411 }
412}
413impl TryFrom<Value> for i32 {
414 type Error = ValueTypeMismatchError;
415
416 fn try_from(value: Value) -> Result<Self, Self::Error> {
417 match value {
418 Value::I32(x) => Ok(x as i32),
419 _ => Err(ValueTypeMismatchError),
420 }
421 }
422}
423
424impl From<u64> for Value {
425 fn from(x: u64) -> Self {
426 Value::I64(x)
427 }
428}
429impl TryFrom<Value> for u64 {
430 type Error = ValueTypeMismatchError;
431
432 fn try_from(value: Value) -> Result<Self, Self::Error> {
433 match value {
434 Value::I64(x) => Ok(x),
435 _ => Err(ValueTypeMismatchError),
436 }
437 }
438}
439impl From<i64> for Value {
440 fn from(x: i64) -> Self {
441 Value::I64(x as u64)
442 }
443}
444impl TryFrom<Value> for i64 {
445 type Error = ValueTypeMismatchError;
446
447 fn try_from(value: Value) -> Result<Self, Self::Error> {
448 match value {
449 Value::I64(x) => Ok(x as i64),
450 _ => Err(ValueTypeMismatchError),
451 }
452 }
453}
454
455impl From<F32> for Value {
456 fn from(x: F32) -> Self {
457 Value::F32(x)
458 }
459}
460impl TryFrom<Value> for F32 {
461 type Error = ValueTypeMismatchError;
462
463 fn try_from(value: Value) -> Result<Self, Self::Error> {
464 match value {
465 Value::F32(x) => Ok(x),
466 _ => Err(ValueTypeMismatchError),
467 }
468 }
469}
470
471impl From<F64> for Value {
472 fn from(x: F64) -> Self {
473 Value::F64(x)
474 }
475}
476impl TryFrom<Value> for F64 {
477 type Error = ValueTypeMismatchError;
478
479 fn try_from(value: Value) -> Result<Self, Self::Error> {
480 match value {
481 Value::F64(x) => Ok(x),
482 _ => Err(ValueTypeMismatchError),
483 }
484 }
485}
486
487impl From<[u8; 16]> for Value {
488 fn from(value: [u8; 16]) -> Self {
489 Value::V128(value)
490 }
491}
492impl TryFrom<Value> for [u8; 16] {
493 type Error = ValueTypeMismatchError;
494
495 fn try_from(value: Value) -> Result<Self, Self::Error> {
496 match value {
497 Value::V128(x) => Ok(x),
498 _ => Err(ValueTypeMismatchError),
499 }
500 }
501}
502
503impl From<Ref> for Value {
504 fn from(value: Ref) -> Self {
505 Self::Ref(value)
506 }
507}
508
509impl TryFrom<Value> for Ref {
510 type Error = ValueTypeMismatchError;
511
512 fn try_from(value: Value) -> Result<Self, Self::Error> {
513 match value {
514 Value::Ref(rref) => Ok(rref),
515 _ => Err(ValueTypeMismatchError),
516 }
517 }
518}
519
520#[cfg(test)]
521mod test {
522 use alloc::string::ToString;
523
524 use crate::{
525 addrs::Addr,
526 value::{ExternAddr, F32, F64},
527 RefType,
528 };
529
530 use super::{FuncAddr, Ref};
531
532 #[test]
533 fn rounding_f32() {
534 let round_towards_0_f32 = F32(0.5 - f32::EPSILON).round();
535 let round_towards_1_f32 = F32(0.5 + f32::EPSILON).round();
536
537 assert_eq!(round_towards_0_f32, F32(0.0));
538 assert_eq!(round_towards_1_f32, F32(1.0));
539 }
540
541 #[test]
542 fn rounding_f64() {
543 let round_towards_0_f64 = F64(0.5 - f64::EPSILON).round();
544 let round_towards_1_f64 = F64(0.5 + f64::EPSILON).round();
545
546 assert_eq!(round_towards_0_f64, F64(0.0));
547 assert_eq!(round_towards_1_f64, F64(1.0));
548 }
549
550 #[test]
551 fn display_f32() {
552 for x in [
553 -1.0,
554 0.0,
555 1.0,
556 13.3,
557 f32::INFINITY,
558 f32::MAX,
559 f32::MIN,
560 f32::NAN,
561 f32::NEG_INFINITY,
562 core::f32::consts::PI,
563 ] {
564 let wrapped = F32(x).to_string();
565 let expected = x.to_string();
566 assert_eq!(wrapped, expected);
567 }
568 }
569
570 #[test]
571 fn display_f64() {
572 for x in [
573 -1.0,
574 0.0,
575 1.0,
576 13.3,
577 f64::INFINITY,
578 f64::MAX,
579 f64::MIN,
580 f64::NAN,
581 f64::NEG_INFINITY,
582 core::f64::consts::PI,
583 ] {
584 let wrapped = F64(x).to_string();
585 let expected = x.to_string();
586 assert_eq!(wrapped, expected);
587 }
588 }
589
590 #[test]
591 fn display_ref() {
592 assert_eq!(
593 Ref::Func(FuncAddr::new_unchecked(11)).to_string(),
594 "FuncRef(FuncAddr(11))"
595 );
596 assert_eq!(
597 Ref::Extern(ExternAddr(13)).to_string(),
598 "ExternRef(ExternAddr(13))"
599 );
600 assert_eq!(Ref::Null(RefType::FuncRef).to_string(), "Null(FuncRef)");
601 assert_eq!(Ref::Null(RefType::ExternRef).to_string(), "Null(ExternRef)");
602 }
603}