wasm/execution/runtime_structure/
values.rs1use core::{
2 fmt::{Debug, Display},
3 ops::{Add, Div, Mul, Sub},
4};
5
6use crate::{FuncAddr, NumType, RefType, ValType};
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
334impl Ref {
335 pub fn ty(self) -> RefType {
336 match self {
337 Ref::Null(ref_type) => ref_type,
338 Ref::Func(_) => RefType::FuncRef,
339 Ref::Extern(_) => RefType::ExternRef,
340 }
341 }
342}
343
344#[derive(Debug, Clone, Copy, PartialEq, Eq)]
353pub struct ExternAddr(pub usize);
354
355impl Value {
356 pub fn default_from_ty(ty: ValType) -> Self {
357 match ty {
358 ValType::NumType(NumType::I32) => Self::I32(0),
359 ValType::NumType(NumType::I64) => Self::I64(0),
360 ValType::NumType(NumType::F32) => Self::F32(F32(0.0)),
361 ValType::NumType(NumType::F64) => Self::F64(F64(0.0_f64)),
362 ValType::RefType(ref_type) => Self::Ref(Ref::Null(ref_type)),
363 ValType::VecType => Self::V128([0; 16]),
364 }
365 }
366
367 pub fn to_ty(&self) -> ValType {
368 match self {
369 Value::I32(_) => ValType::NumType(NumType::I32),
370 Value::I64(_) => ValType::NumType(NumType::I64),
371 Value::F32(_) => ValType::NumType(NumType::F32),
372 Value::F64(_) => ValType::NumType(NumType::F64),
373 Value::Ref(Ref::Null(ref_type)) => ValType::RefType(*ref_type),
374 Value::Ref(Ref::Func(_)) => ValType::RefType(RefType::FuncRef),
375 Value::Ref(Ref::Extern(_)) => ValType::RefType(RefType::ExternRef),
376 Value::V128(_) => ValType::VecType,
377 }
378 }
379}
380
381#[derive(Debug, PartialEq, Eq)]
383pub struct ValueTypeMismatchError;
384
385impl Display for ValueTypeMismatchError {
386 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387 f.write_str("failed to convert Value to a Rust value because the types did not match")
388 }
389}
390
391impl From<u32> for Value {
392 fn from(x: u32) -> Self {
393 Value::I32(x)
394 }
395}
396impl TryFrom<Value> for u32 {
397 type Error = ValueTypeMismatchError;
398
399 fn try_from(value: Value) -> Result<Self, Self::Error> {
400 match value {
401 Value::I32(x) => Ok(x),
402 _ => Err(ValueTypeMismatchError),
403 }
404 }
405}
406
407impl From<i32> for Value {
408 fn from(x: i32) -> Self {
409 Value::I32(x as u32)
410 }
411}
412impl TryFrom<Value> for i32 {
413 type Error = ValueTypeMismatchError;
414
415 fn try_from(value: Value) -> Result<Self, Self::Error> {
416 match value {
417 Value::I32(x) => Ok(x as i32),
418 _ => Err(ValueTypeMismatchError),
419 }
420 }
421}
422
423impl From<u64> for Value {
424 fn from(x: u64) -> Self {
425 Value::I64(x)
426 }
427}
428impl TryFrom<Value> for u64 {
429 type Error = ValueTypeMismatchError;
430
431 fn try_from(value: Value) -> Result<Self, Self::Error> {
432 match value {
433 Value::I64(x) => Ok(x),
434 _ => Err(ValueTypeMismatchError),
435 }
436 }
437}
438impl From<i64> for Value {
439 fn from(x: i64) -> Self {
440 Value::I64(x as u64)
441 }
442}
443impl TryFrom<Value> for i64 {
444 type Error = ValueTypeMismatchError;
445
446 fn try_from(value: Value) -> Result<Self, Self::Error> {
447 match value {
448 Value::I64(x) => Ok(x as i64),
449 _ => Err(ValueTypeMismatchError),
450 }
451 }
452}
453
454impl From<F32> for Value {
455 fn from(x: F32) -> Self {
456 Value::F32(x)
457 }
458}
459impl TryFrom<Value> for F32 {
460 type Error = ValueTypeMismatchError;
461
462 fn try_from(value: Value) -> Result<Self, Self::Error> {
463 match value {
464 Value::F32(x) => Ok(x),
465 _ => Err(ValueTypeMismatchError),
466 }
467 }
468}
469
470impl From<F64> for Value {
471 fn from(x: F64) -> Self {
472 Value::F64(x)
473 }
474}
475impl TryFrom<Value> for F64 {
476 type Error = ValueTypeMismatchError;
477
478 fn try_from(value: Value) -> Result<Self, Self::Error> {
479 match value {
480 Value::F64(x) => Ok(x),
481 _ => Err(ValueTypeMismatchError),
482 }
483 }
484}
485
486impl From<[u8; 16]> for Value {
487 fn from(value: [u8; 16]) -> Self {
488 Value::V128(value)
489 }
490}
491impl TryFrom<Value> for [u8; 16] {
492 type Error = ValueTypeMismatchError;
493
494 fn try_from(value: Value) -> Result<Self, Self::Error> {
495 match value {
496 Value::V128(x) => Ok(x),
497 _ => Err(ValueTypeMismatchError),
498 }
499 }
500}
501
502impl From<Ref> for Value {
503 fn from(value: Ref) -> Self {
504 Self::Ref(value)
505 }
506}
507
508impl TryFrom<Value> for Ref {
509 type Error = ValueTypeMismatchError;
510
511 fn try_from(value: Value) -> Result<Self, Self::Error> {
512 match value {
513 Value::Ref(rref) => Ok(rref),
514 _ => Err(ValueTypeMismatchError),
515 }
516 }
517}
518
519impl From<f32> for Value {
520 fn from(value: f32) -> Self {
521 F32(value).into()
522 }
523}
524
525impl TryFrom<Value> for f32 {
526 type Error = ValueTypeMismatchError;
527
528 fn try_from(value: Value) -> Result<Self, Self::Error> {
529 F32::try_from(value).map(|f| f.0)
530 }
531}
532
533impl From<f64> for Value {
534 fn from(value: f64) -> Self {
535 F64(value).into()
536 }
537}
538
539impl TryFrom<Value> for f64 {
540 type Error = ValueTypeMismatchError;
541
542 fn try_from(value: Value) -> Result<Self, Self::Error> {
543 F64::try_from(value).map(|f| f.0)
544 }
545}
546
547#[cfg(test)]
548mod test {
549 use alloc::string::ToString;
550
551 use crate::{Addr, ExternAddr, RefType, F32, F64};
552
553 use super::{FuncAddr, Ref};
554
555 #[test]
556 fn rounding_f32() {
557 let round_towards_0_f32 = F32(0.5 - f32::EPSILON).round();
558 let round_towards_1_f32 = F32(0.5 + f32::EPSILON).round();
559
560 assert_eq!(round_towards_0_f32, F32(0.0));
561 assert_eq!(round_towards_1_f32, F32(1.0));
562 }
563
564 #[test]
565 fn rounding_f64() {
566 let round_towards_0_f64 = F64(0.5 - f64::EPSILON).round();
567 let round_towards_1_f64 = F64(0.5 + f64::EPSILON).round();
568
569 assert_eq!(round_towards_0_f64, F64(0.0));
570 assert_eq!(round_towards_1_f64, F64(1.0));
571 }
572
573 #[test]
574 fn display_f32() {
575 for x in [
576 -1.0,
577 0.0,
578 1.0,
579 13.3,
580 f32::INFINITY,
581 f32::MAX,
582 f32::MIN,
583 f32::NAN,
584 f32::NEG_INFINITY,
585 core::f32::consts::PI,
586 ] {
587 let wrapped = F32(x).to_string();
588 let expected = x.to_string();
589 assert_eq!(wrapped, expected);
590 }
591 }
592
593 #[test]
594 fn display_f64() {
595 for x in [
596 -1.0,
597 0.0,
598 1.0,
599 13.3,
600 f64::INFINITY,
601 f64::MAX,
602 f64::MIN,
603 f64::NAN,
604 f64::NEG_INFINITY,
605 core::f64::consts::PI,
606 ] {
607 let wrapped = F64(x).to_string();
608 let expected = x.to_string();
609 assert_eq!(wrapped, expected);
610 }
611 }
612
613 #[test]
614 fn display_ref() {
615 assert_eq!(
616 Ref::Func(FuncAddr::new(11)).to_string(),
617 "FuncRef(FuncAddr(11))"
618 );
619 assert_eq!(
620 Ref::Extern(ExternAddr(13)).to_string(),
621 "ExternRef(ExternAddr(13))"
622 );
623 assert_eq!(Ref::Null(RefType::FuncRef).to_string(), "Null(FuncRef)");
624 assert_eq!(Ref::Null(RefType::ExternRef).to_string(), "Null(ExternRef)");
625 }
626}