casper_wasmi_core/
value.rs

1use crate::{
2    nan_preserving_float::{F32, F64},
3    TrapCode,
4};
5use core::{f32, fmt, fmt::Display};
6
7/// Type of a value.
8///
9/// See [`Value`] for details.
10///
11/// [`Value`]: enum.Value.html
12#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
13pub enum ValueType {
14    /// 32-bit signed or unsigned integer.
15    I32,
16    /// 64-bit signed or unsigned integer.
17    I64,
18    /// 32-bit IEEE 754-2008 floating point number.
19    F32,
20    /// 64-bit IEEE 754-2008 floating point number.
21    F64,
22}
23
24impl Display for ValueType {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        match self {
27            Self::I32 => write!(f, "i32"),
28            Self::I64 => write!(f, "i64"),
29            Self::F32 => write!(f, "f32"),
30            Self::F64 => write!(f, "f64"),
31        }
32    }
33}
34
35/// Runtime representation of a value.
36///
37/// Wasm code manipulate values of the four basic value types:
38/// integers and floating-point (IEEE 754-2008) data of 32 or 64 bit width each, respectively.
39///
40/// There is no distinction between signed and unsigned integer types. Instead, integers are
41/// interpreted by respective operations as either unsigned or signed in two’s complement representation.
42#[derive(Copy, Clone, Debug, PartialEq)]
43pub enum Value {
44    /// Value of 32-bit signed or unsigned integer.
45    I32(i32),
46    /// Value of 64-bit signed or unsigned integer.
47    I64(i64),
48    /// Value of 32-bit IEEE 754-2008 floating point number.
49    F32(F32),
50    /// Value of 64-bit IEEE 754-2008 floating point number.
51    F64(F64),
52}
53
54impl Display for Value {
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        match self {
57            Self::I32(value) => write!(f, "{value}"),
58            Self::I64(value) => write!(f, "{value}"),
59            Self::F32(value) => write!(f, "{}", f32::from(*value)),
60            Self::F64(value) => write!(f, "{}", f64::from(*value)),
61        }
62    }
63}
64
65/// Trait for creating value from a [`Value`].
66///
67/// Typically each implementation can create a value from the specific type.
68/// For example, values of type `bool` or `u32` are both represented by [`I32`] and `f64` values are represented by
69/// [`F64`].
70///
71/// [`I32`]: enum.Value.html#variant.I32
72/// [`F64`]: enum.Value.html#variant.F64
73/// [`Value`]: enum.Value.html
74pub trait FromValue
75where
76    Self: Sized,
77{
78    /// Create a value of type `Self` from a given [`Value`].
79    ///
80    /// Returns `None` if the [`Value`] is of type different than
81    /// expected by the conversion in question.
82    ///
83    /// [`Value`]: enum.Value.html
84    fn from_value(val: Value) -> Option<Self>;
85}
86
87/// Convert one type to another by wrapping.
88pub trait WrapInto<T> {
89    /// Convert one type to another by wrapping.
90    fn wrap_into(self) -> T;
91}
92
93/// Convert one type to another by rounding to the nearest integer towards zero.
94///
95/// # Errors
96///
97/// Traps when the input float cannot be represented by the target integer or
98/// when the input float is NaN.
99pub trait TryTruncateInto<T, E> {
100    /// Convert one type to another by rounding to the nearest integer towards zero.
101    fn try_truncate_into(self) -> Result<T, E>;
102}
103
104/// Convert one type to another by rounding to the nearest integer towards zero.
105///
106/// # Note
107///
108/// This has saturating semantics for when the integer cannot represent the float.
109///
110/// Returns
111///
112/// - `0` when the input is NaN.
113/// - `int::MIN` when the input is -INF.
114/// - `int::MAX` when the input is +INF.
115pub trait TruncateSaturateInto<T> {
116    /// Convert one type to another by rounding to the nearest integer towards zero.
117    fn truncate_saturate_into(self) -> T;
118}
119
120/// Convert one type to another by extending with leading zeroes.
121pub trait ExtendInto<T> {
122    /// Convert one type to another by extending with leading zeroes.
123    fn extend_into(self) -> T;
124}
125
126/// Sign-extends `Self` integer type from `T` integer type.
127pub trait SignExtendFrom<T> {
128    /// Convert one type to another by extending with leading zeroes.
129    fn sign_extend_from(self) -> Self;
130}
131
132/// Reinterprets the bits of a value of one type as another type.
133pub trait TransmuteInto<T> {
134    /// Reinterprets the bits of a value of one type as another type.
135    fn transmute_into(self) -> T;
136}
137
138/// Types that can be converted from and to little endian bytes.
139pub trait LittleEndianConvert {
140    /// The little endian bytes representation.
141    type Bytes: Default + AsRef<[u8]> + AsMut<[u8]>;
142
143    /// Converts `self` into little endian bytes.
144    fn into_le_bytes(self) -> Self::Bytes;
145
146    /// Converts little endian bytes into `Self`.
147    fn from_le_bytes(bytes: Self::Bytes) -> Self;
148}
149
150macro_rules! impl_little_endian_convert_primitive {
151    ( $($primitive:ty),* $(,)? ) => {
152        $(
153            impl LittleEndianConvert for $primitive {
154                type Bytes = [::core::primitive::u8; ::core::mem::size_of::<$primitive>()];
155
156                #[inline]
157                fn into_le_bytes(self) -> Self::Bytes {
158                    <$primitive>::to_le_bytes(self)
159                }
160
161                #[inline]
162                fn from_le_bytes(bytes: Self::Bytes) -> Self {
163                    <$primitive>::from_le_bytes(bytes)
164                }
165            }
166        )*
167    };
168}
169impl_little_endian_convert_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
170
171macro_rules! impl_little_endian_convert_float {
172    ( $( struct $float_ty:ident($uint_ty:ty); )* $(,)? ) => {
173        $(
174            impl LittleEndianConvert for $float_ty {
175                type Bytes = <$uint_ty as LittleEndianConvert>::Bytes;
176
177                #[inline]
178                fn into_le_bytes(self) -> Self::Bytes {
179                    <$uint_ty>::into_le_bytes(self.to_bits())
180                }
181
182                #[inline]
183                fn from_le_bytes(bytes: Self::Bytes) -> Self {
184                    Self::from_bits(<$uint_ty>::from_le_bytes(bytes))
185                }
186            }
187        )*
188    };
189}
190impl_little_endian_convert_float!(
191    struct F32(u32);
192    struct F64(u64);
193);
194
195/// Arithmetic operations.
196pub trait ArithmeticOps<T>: Copy {
197    /// Add two values.
198    fn add(self, other: T) -> T;
199    /// Subtract two values.
200    fn sub(self, other: T) -> T;
201    /// Multiply two values.
202    fn mul(self, other: T) -> T;
203    /// Divide two values.
204    fn div(self, other: T) -> Result<T, TrapCode>;
205}
206
207/// Integer value.
208pub trait Integer<T>: ArithmeticOps<T> {
209    /// Counts leading zeros in the bitwise representation of the value.
210    fn leading_zeros(self) -> T;
211    /// Counts trailing zeros in the bitwise representation of the value.
212    fn trailing_zeros(self) -> T;
213    /// Counts 1-bits in the bitwise representation of the value.
214    fn count_ones(self) -> T;
215    /// Get left bit rotation result.
216    fn rotl(self, other: T) -> T;
217    /// Get right bit rotation result.
218    fn rotr(self, other: T) -> T;
219    /// Get division remainder.
220    fn rem(self, other: T) -> Result<T, TrapCode>;
221}
222
223/// Float-point value.
224pub trait Float<T>: ArithmeticOps<T> {
225    /// Get absolute value.
226    fn abs(self) -> T;
227    /// Returns the largest integer less than or equal to a number.
228    fn floor(self) -> T;
229    /// Returns the smallest integer greater than or equal to a number.
230    fn ceil(self) -> T;
231    /// Returns the integer part of a number.
232    fn trunc(self) -> T;
233    /// Returns the nearest integer to a number. Round half-way cases away from 0.0.
234    fn round(self) -> T;
235    /// Returns the nearest integer to a number. Ties are round to even number.
236    fn nearest(self) -> T;
237    /// Takes the square root of a number.
238    fn sqrt(self) -> T;
239    /// Returns `true` if the sign of the number is positive.
240    fn is_sign_positive(self) -> bool;
241    /// Returns `true` if the sign of the number is negative.
242    fn is_sign_negative(self) -> bool;
243    /// Returns the minimum of the two numbers.
244    fn min(self, other: T) -> T;
245    /// Returns the maximum of the two numbers.
246    fn max(self, other: T) -> T;
247    /// Sets sign of this value to the sign of other value.
248    fn copysign(self, other: T) -> T;
249}
250
251impl Value {
252    /// Creates new default value of given type.
253    #[inline]
254    pub fn default(value_type: ValueType) -> Self {
255        match value_type {
256            ValueType::I32 => Value::I32(0),
257            ValueType::I64 => Value::I64(0),
258            ValueType::F32 => Value::F32(0f32.into()),
259            ValueType::F64 => Value::F64(0f64.into()),
260        }
261    }
262
263    /// Creates new value by interpreting passed u32 as f32.
264    #[deprecated(note = "use `F32::from_bits(val).into()` instead")]
265    pub fn decode_f32(val: u32) -> Self {
266        Value::F32(F32::from_bits(val))
267    }
268
269    /// Creates new value by interpreting passed u64 as f64.
270    #[deprecated(note = "use `F64::from_bits(val).into()` instead")]
271    pub fn decode_f64(val: u64) -> Self {
272        Value::F64(F64::from_bits(val))
273    }
274
275    /// Get variable type for this value.
276    #[inline]
277    pub fn value_type(&self) -> ValueType {
278        match *self {
279            Value::I32(_) => ValueType::I32,
280            Value::I64(_) => ValueType::I64,
281            Value::F32(_) => ValueType::F32,
282            Value::F64(_) => ValueType::F64,
283        }
284    }
285
286    /// Returns `T` if this particular [`Value`] contains
287    /// appropriate type.
288    ///
289    /// See [`FromValue`] for details.
290    ///
291    /// [`FromValue`]: trait.FromValue.html
292    /// [`Value`]: enum.Value.html
293    #[inline]
294    pub fn try_into<T: FromValue>(self) -> Option<T> {
295        FromValue::from_value(self)
296    }
297}
298
299impl From<i8> for Value {
300    #[inline]
301    fn from(val: i8) -> Self {
302        Value::I32(val as i32)
303    }
304}
305
306impl From<i16> for Value {
307    #[inline]
308    fn from(val: i16) -> Self {
309        Value::I32(val as i32)
310    }
311}
312
313impl From<i32> for Value {
314    #[inline]
315    fn from(val: i32) -> Self {
316        Value::I32(val)
317    }
318}
319
320impl From<i64> for Value {
321    #[inline]
322    fn from(val: i64) -> Self {
323        Value::I64(val)
324    }
325}
326
327impl From<u8> for Value {
328    #[inline]
329    fn from(val: u8) -> Self {
330        Value::I32(val as i32)
331    }
332}
333
334impl From<u16> for Value {
335    #[inline]
336    fn from(val: u16) -> Self {
337        Value::I32(val as i32)
338    }
339}
340
341impl From<u32> for Value {
342    #[inline]
343    fn from(val: u32) -> Self {
344        Value::I32(val.transmute_into())
345    }
346}
347
348impl From<u64> for Value {
349    #[inline]
350    fn from(val: u64) -> Self {
351        Value::I64(val.transmute_into())
352    }
353}
354
355impl From<F32> for Value {
356    #[inline]
357    fn from(val: F32) -> Self {
358        Value::F32(val)
359    }
360}
361
362impl From<F64> for Value {
363    #[inline]
364    fn from(val: F64) -> Self {
365        Value::F64(val)
366    }
367}
368
369macro_rules! impl_from_value {
370    ($expected_rt_ty: ident, $into: ty) => {
371        impl FromValue for $into {
372            #[inline]
373            fn from_value(val: Value) -> Option<Self> {
374                match val {
375                    Value::$expected_rt_ty(val) => Some(val.transmute_into()),
376                    _ => None,
377                }
378            }
379        }
380    };
381}
382
383/// This conversion assumes that boolean values are represented by
384/// [`I32`] type.
385///
386/// [`I32`]: enum.Value.html#variant.I32
387impl FromValue for bool {
388    #[inline]
389    fn from_value(val: Value) -> Option<Self> {
390        match val {
391            Value::I32(val) => Some(val != 0),
392            _ => None,
393        }
394    }
395}
396
397///  This conversion assumes that `i8` is represented as an [`I32`].
398///
399/// [`I32`]: enum.Value.html#variant.I32
400impl FromValue for i8 {
401    #[inline]
402    fn from_value(val: Value) -> Option<Self> {
403        let min = i8::MIN as i32;
404        let max = i8::MAX as i32;
405        match val {
406            Value::I32(val) if min <= val && val <= max => Some(val as i8),
407            _ => None,
408        }
409    }
410}
411
412///  This conversion assumes that `i16` is represented as an [`I32`].
413///
414/// [`I32`]: enum.Value.html#variant.I32
415impl FromValue for i16 {
416    #[inline]
417    fn from_value(val: Value) -> Option<Self> {
418        let min = i16::MIN as i32;
419        let max = i16::MAX as i32;
420        match val {
421            Value::I32(val) if min <= val && val <= max => Some(val as i16),
422            _ => None,
423        }
424    }
425}
426
427///  This conversion assumes that `u8` is represented as an [`I32`].
428///
429/// [`I32`]: enum.Value.html#variant.I32
430impl FromValue for u8 {
431    #[inline]
432    fn from_value(val: Value) -> Option<Self> {
433        let min = u8::MIN as i32;
434        let max = u8::MAX as i32;
435        match val {
436            Value::I32(val) if min <= val && val <= max => Some(val as u8),
437            _ => None,
438        }
439    }
440}
441
442///  This conversion assumes that `u16` is represented as an [`I32`].
443///
444/// [`I32`]: enum.Value.html#variant.I32
445impl FromValue for u16 {
446    #[inline]
447    fn from_value(val: Value) -> Option<Self> {
448        let min = u16::MIN as i32;
449        let max = u16::MAX as i32;
450        match val {
451            Value::I32(val) if min <= val && val <= max => Some(val as u16),
452            _ => None,
453        }
454    }
455}
456
457impl_from_value!(I32, i32);
458impl_from_value!(I64, i64);
459impl_from_value!(F32, F32);
460impl_from_value!(F64, F64);
461impl_from_value!(I32, u32);
462impl_from_value!(I64, u64);
463
464macro_rules! impl_wrap_into {
465    ($from:ident, $into:ident) => {
466        impl WrapInto<$into> for $from {
467            #[inline]
468            fn wrap_into(self) -> $into {
469                self as $into
470            }
471        }
472    };
473    ($from:ident, $intermediate:ident, $into:ident) => {
474        impl WrapInto<$into> for $from {
475            #[inline]
476            fn wrap_into(self) -> $into {
477                $into::from(self as $intermediate)
478            }
479        }
480    };
481}
482
483impl_wrap_into!(i32, i8);
484impl_wrap_into!(i32, i16);
485impl_wrap_into!(i64, i8);
486impl_wrap_into!(i64, i16);
487impl_wrap_into!(i64, i32);
488impl_wrap_into!(i64, f32, F32);
489impl_wrap_into!(u64, f32, F32);
490// Casting from an f64 to an f32 will produce the closest possible value (rounding strategy unspecified)
491// NOTE: currently this will cause Undefined Behavior if the value is finite but larger or smaller than the
492// largest or smallest finite value representable by f32. This is a bug and will be fixed.
493impl_wrap_into!(f64, f32);
494
495impl WrapInto<F32> for F64 {
496    #[inline]
497    fn wrap_into(self) -> F32 {
498        (f64::from(self) as f32).into()
499    }
500}
501
502macro_rules! impl_try_truncate_into {
503    (@primitive $from: ident, $into: ident, $to_primitive:path) => {
504        impl TryTruncateInto<$into, TrapCode> for $from {
505            #[inline]
506            fn try_truncate_into(self) -> Result<$into, TrapCode> {
507                // Casting from a float to an integer will round the float towards zero
508                if self.is_nan() {
509                    return Err(TrapCode::InvalidConversionToInt);
510                }
511                num_rational::BigRational::from_float(self)
512                    .map(|val| val.to_integer())
513                    .and_then(|val| $to_primitive(&val))
514                    .ok_or(TrapCode::IntegerOverflow)
515            }
516        }
517
518        impl TruncateSaturateInto<$into> for $from {
519            #[inline]
520            fn truncate_saturate_into(self) -> $into {
521                if self.is_nan() {
522                    return <$into as Default>::default();
523                }
524                if self.is_infinite() && self.is_sign_positive() {
525                    return <$into>::MAX;
526                }
527                if self.is_infinite() && self.is_sign_negative() {
528                    return <$into>::MIN;
529                }
530                self as _
531            }
532        }
533    };
534    (@wrapped $from:ident, $intermediate:ident, $into:ident) => {
535        impl TryTruncateInto<$into, TrapCode> for $from {
536            #[inline]
537            fn try_truncate_into(self) -> Result<$into, TrapCode> {
538                $intermediate::from(self).try_truncate_into()
539            }
540        }
541
542        impl TruncateSaturateInto<$into> for $from {
543            #[inline]
544            fn truncate_saturate_into(self) -> $into {
545                $intermediate::from(self).truncate_saturate_into()
546            }
547        }
548    };
549}
550
551impl_try_truncate_into!(@primitive f32, i32, num_traits::cast::ToPrimitive::to_i32);
552impl_try_truncate_into!(@primitive f32, i64, num_traits::cast::ToPrimitive::to_i64);
553impl_try_truncate_into!(@primitive f64, i32, num_traits::cast::ToPrimitive::to_i32);
554impl_try_truncate_into!(@primitive f64, i64, num_traits::cast::ToPrimitive::to_i64);
555impl_try_truncate_into!(@primitive f32, u32, num_traits::cast::ToPrimitive::to_u32);
556impl_try_truncate_into!(@primitive f32, u64, num_traits::cast::ToPrimitive::to_u64);
557impl_try_truncate_into!(@primitive f64, u32, num_traits::cast::ToPrimitive::to_u32);
558impl_try_truncate_into!(@primitive f64, u64, num_traits::cast::ToPrimitive::to_u64);
559impl_try_truncate_into!(@wrapped F32, f32, i32);
560impl_try_truncate_into!(@wrapped F32, f32, i64);
561impl_try_truncate_into!(@wrapped F64, f64, i32);
562impl_try_truncate_into!(@wrapped F64, f64, i64);
563impl_try_truncate_into!(@wrapped F32, f32, u32);
564impl_try_truncate_into!(@wrapped F32, f32, u64);
565impl_try_truncate_into!(@wrapped F64, f64, u32);
566impl_try_truncate_into!(@wrapped F64, f64, u64);
567
568macro_rules! impl_extend_into {
569    ($from:ident, $into:ident) => {
570        impl ExtendInto<$into> for $from {
571            #[inline]
572            fn extend_into(self) -> $into {
573                self as $into
574            }
575        }
576    };
577    ($from:ident, $intermediate:ident, $into:ident) => {
578        impl ExtendInto<$into> for $from {
579            #[inline]
580            fn extend_into(self) -> $into {
581                $into::from(self as $intermediate)
582            }
583        }
584    };
585}
586
587impl_extend_into!(i8, i32);
588impl_extend_into!(u8, i32);
589impl_extend_into!(i16, i32);
590impl_extend_into!(u16, i32);
591impl_extend_into!(i8, i64);
592impl_extend_into!(u8, i64);
593impl_extend_into!(i16, i64);
594impl_extend_into!(u16, i64);
595impl_extend_into!(i32, i64);
596impl_extend_into!(u32, i64);
597impl_extend_into!(u32, u64);
598impl_extend_into!(i32, f32);
599impl_extend_into!(i32, f64);
600impl_extend_into!(u32, f32);
601impl_extend_into!(u32, f64);
602impl_extend_into!(i64, f64);
603impl_extend_into!(u64, f64);
604impl_extend_into!(f32, f64);
605
606impl_extend_into!(i32, f32, F32);
607impl_extend_into!(i32, f64, F64);
608impl_extend_into!(u32, f32, F32);
609impl_extend_into!(u32, f64, F64);
610impl_extend_into!(i64, f64, F64);
611impl_extend_into!(u64, f64, F64);
612impl_extend_into!(f32, f64, F64);
613
614impl ExtendInto<F64> for F32 {
615    #[inline]
616    fn extend_into(self) -> F64 {
617        (f32::from(self) as f64).into()
618    }
619}
620
621macro_rules! impl_sign_extend_from {
622    ( $( impl SignExtendFrom<$from_type:ty> for $for_type:ty; )* ) => {
623        $(
624            impl SignExtendFrom<$from_type> for $for_type {
625                #[inline]
626                fn sign_extend_from(self) -> Self {
627                    (self as $from_type) as Self
628                }
629            }
630        )*
631    };
632}
633impl_sign_extend_from! {
634    impl SignExtendFrom<i8> for i32;
635    impl SignExtendFrom<i16> for i32;
636    impl SignExtendFrom<i8> for i64;
637    impl SignExtendFrom<i16> for i64;
638    impl SignExtendFrom<i32> for i64;
639}
640
641macro_rules! impl_transmute_into_self {
642    ($type: ident) => {
643        impl TransmuteInto<$type> for $type {
644            #[inline]
645            fn transmute_into(self) -> $type {
646                self
647            }
648        }
649    };
650}
651
652impl_transmute_into_self!(i32);
653impl_transmute_into_self!(i64);
654impl_transmute_into_self!(f32);
655impl_transmute_into_self!(f64);
656impl_transmute_into_self!(F32);
657impl_transmute_into_self!(F64);
658
659macro_rules! impl_transmute_into_as {
660    ($from: ident, $into: ident) => {
661        impl TransmuteInto<$into> for $from {
662            #[inline]
663            fn transmute_into(self) -> $into {
664                self as $into
665            }
666        }
667    };
668}
669
670impl_transmute_into_as!(i8, u8);
671impl_transmute_into_as!(i32, u32);
672impl_transmute_into_as!(i64, u64);
673
674macro_rules! impl_transmute_into_npf {
675    ($npf:ident, $float:ident, $signed:ident, $unsigned:ident) => {
676        impl TransmuteInto<$float> for $npf {
677            #[inline]
678            fn transmute_into(self) -> $float {
679                self.into()
680            }
681        }
682
683        impl TransmuteInto<$npf> for $float {
684            #[inline]
685            fn transmute_into(self) -> $npf {
686                self.into()
687            }
688        }
689
690        impl TransmuteInto<$signed> for $npf {
691            #[inline]
692            fn transmute_into(self) -> $signed {
693                self.to_bits() as _
694            }
695        }
696
697        impl TransmuteInto<$unsigned> for $npf {
698            #[inline]
699            fn transmute_into(self) -> $unsigned {
700                self.to_bits()
701            }
702        }
703
704        impl TransmuteInto<$npf> for $signed {
705            #[inline]
706            fn transmute_into(self) -> $npf {
707                $npf::from_bits(self as _)
708            }
709        }
710
711        impl TransmuteInto<$npf> for $unsigned {
712            #[inline]
713            fn transmute_into(self) -> $npf {
714                $npf::from_bits(self)
715            }
716        }
717    };
718}
719
720impl_transmute_into_npf!(F32, f32, i32, u32);
721impl_transmute_into_npf!(F64, f64, i64, u64);
722
723impl TransmuteInto<i32> for f32 {
724    #[inline]
725    fn transmute_into(self) -> i32 {
726        self.to_bits() as i32
727    }
728}
729
730impl TransmuteInto<i64> for f64 {
731    #[inline]
732    fn transmute_into(self) -> i64 {
733        self.to_bits() as i64
734    }
735}
736
737impl TransmuteInto<f32> for i32 {
738    #[inline]
739    fn transmute_into(self) -> f32 {
740        f32::from_bits(self as u32)
741    }
742}
743
744impl TransmuteInto<f64> for i64 {
745    #[inline]
746    fn transmute_into(self) -> f64 {
747        f64::from_bits(self as u64)
748    }
749}
750
751impl TransmuteInto<i32> for u32 {
752    #[inline]
753    fn transmute_into(self) -> i32 {
754        self as _
755    }
756}
757
758impl TransmuteInto<i64> for u64 {
759    #[inline]
760    fn transmute_into(self) -> i64 {
761        self as _
762    }
763}
764
765macro_rules! impl_integer_arithmetic_ops {
766    ($type: ident) => {
767        impl ArithmeticOps<$type> for $type {
768            #[inline]
769            fn add(self, other: $type) -> $type {
770                self.wrapping_add(other)
771            }
772            #[inline]
773            fn sub(self, other: $type) -> $type {
774                self.wrapping_sub(other)
775            }
776            #[inline]
777            fn mul(self, other: $type) -> $type {
778                self.wrapping_mul(other)
779            }
780            #[inline]
781            fn div(self, other: $type) -> Result<$type, TrapCode> {
782                if other == 0 {
783                    Err(TrapCode::DivisionByZero)
784                } else {
785                    let (result, overflow) = self.overflowing_div(other);
786                    if overflow {
787                        Err(TrapCode::IntegerOverflow)
788                    } else {
789                        Ok(result)
790                    }
791                }
792            }
793        }
794    };
795}
796
797impl_integer_arithmetic_ops!(i32);
798impl_integer_arithmetic_ops!(u32);
799impl_integer_arithmetic_ops!(i64);
800impl_integer_arithmetic_ops!(u64);
801
802macro_rules! impl_float_arithmetic_ops {
803    ($type: ident) => {
804        impl ArithmeticOps<$type> for $type {
805            #[inline]
806            fn add(self, other: $type) -> $type {
807                self + other
808            }
809            #[inline]
810            fn sub(self, other: $type) -> $type {
811                self - other
812            }
813            #[inline]
814            fn mul(self, other: $type) -> $type {
815                self * other
816            }
817            #[inline]
818            fn div(self, other: $type) -> Result<$type, TrapCode> {
819                Ok(self / other)
820            }
821        }
822    };
823}
824
825impl_float_arithmetic_ops!(f32);
826impl_float_arithmetic_ops!(f64);
827impl_float_arithmetic_ops!(F32);
828impl_float_arithmetic_ops!(F64);
829
830macro_rules! impl_integer {
831    ($type: ident) => {
832        impl Integer<$type> for $type {
833            #[inline]
834            fn leading_zeros(self) -> $type {
835                self.leading_zeros() as $type
836            }
837            #[inline]
838            fn trailing_zeros(self) -> $type {
839                self.trailing_zeros() as $type
840            }
841            #[inline]
842            fn count_ones(self) -> $type {
843                self.count_ones() as $type
844            }
845            #[inline]
846            fn rotl(self, other: $type) -> $type {
847                self.rotate_left(other as u32)
848            }
849            #[inline]
850            fn rotr(self, other: $type) -> $type {
851                self.rotate_right(other as u32)
852            }
853            #[inline]
854            fn rem(self, other: $type) -> Result<$type, TrapCode> {
855                if other == 0 {
856                    Err(TrapCode::DivisionByZero)
857                } else {
858                    Ok(self.wrapping_rem(other))
859                }
860            }
861        }
862    };
863}
864
865impl_integer!(i32);
866impl_integer!(u32);
867impl_integer!(i64);
868impl_integer!(u64);
869
870#[cfg(feature = "std")]
871mod fmath {
872    pub use f32;
873    pub use f64;
874}
875
876#[cfg(not(feature = "std"))]
877mod fmath {
878    pub use super::libm_adapters::{f32, f64};
879}
880
881// We cannot call the math functions directly, because they are not all available in `core`.
882// In no-std cases we instead rely on `libm`.
883// These wrappers handle that delegation.
884macro_rules! impl_float {
885    ($type:ident, $fXX:ident, $iXX:ident) => {
886        // In this particular instance we want to directly compare floating point numbers.
887        impl Float<$type> for $type {
888            #[inline]
889            fn abs(self) -> $type {
890                fmath::$fXX::abs($fXX::from(self)).into()
891            }
892            #[inline]
893            fn floor(self) -> $type {
894                fmath::$fXX::floor($fXX::from(self)).into()
895            }
896            #[inline]
897            fn ceil(self) -> $type {
898                fmath::$fXX::ceil($fXX::from(self)).into()
899            }
900            #[inline]
901            fn trunc(self) -> $type {
902                fmath::$fXX::trunc($fXX::from(self)).into()
903            }
904            #[inline]
905            fn round(self) -> $type {
906                fmath::$fXX::round($fXX::from(self)).into()
907            }
908            #[inline]
909            fn nearest(self) -> $type {
910                let round = self.round();
911                if fmath::$fXX::fract($fXX::from(self)).abs() != 0.5 {
912                    return round;
913                }
914
915                use core::ops::Rem;
916                if round.rem(2.0) == 1.0 {
917                    self.floor()
918                } else if round.rem(2.0) == -1.0 {
919                    self.ceil()
920                } else {
921                    round
922                }
923            }
924            #[inline]
925            fn sqrt(self) -> $type {
926                fmath::$fXX::sqrt($fXX::from(self)).into()
927            }
928            #[inline]
929            fn is_sign_positive(self) -> bool {
930                $fXX::is_sign_positive($fXX::from(self)).into()
931            }
932            #[inline]
933            fn is_sign_negative(self) -> bool {
934                $fXX::is_sign_negative($fXX::from(self)).into()
935            }
936            #[inline]
937            fn min(self, other: $type) -> $type {
938                // The implementation strictly adheres to the mandated behavior for the Wasm specification.
939                // Note: In other contexts this API is also known as: `nan_min`.
940                match (self.is_nan(), other.is_nan()) {
941                    (true, false) => self,
942                    (false, true) => other,
943                    _ => {
944                        // Case: Both values are NaN; OR both values are non-NaN.
945                        if other.is_sign_negative() {
946                            return other.min(self);
947                        }
948                        self.min(other)
949                    }
950                }
951            }
952            #[inline]
953            fn max(self, other: $type) -> $type {
954                // The implementation strictly adheres to the mandated behavior for the Wasm specification.
955                // Note: In other contexts this API is also known as: `nan_max`.
956                match (self.is_nan(), other.is_nan()) {
957                    (true, false) => self,
958                    (false, true) => other,
959                    _ => {
960                        // Case: Both values are NaN; OR both values are non-NaN.
961                        if other.is_sign_positive() {
962                            return other.max(self);
963                        }
964                        self.max(other)
965                    }
966                }
967            }
968            #[inline]
969            fn copysign(self, other: $type) -> $type {
970                use core::mem::size_of;
971                let sign_mask: $iXX = 1 << ((size_of::<$iXX>() << 3) - 1);
972                let self_int: $iXX = self.transmute_into();
973                let other_int: $iXX = other.transmute_into();
974                let is_self_sign_set = (self_int & sign_mask) != 0;
975                let is_other_sign_set = (other_int & sign_mask) != 0;
976                if is_self_sign_set == is_other_sign_set {
977                    self
978                } else if is_other_sign_set {
979                    (self_int | sign_mask).transmute_into()
980                } else {
981                    (self_int & !sign_mask).transmute_into()
982                }
983            }
984        }
985    };
986}
987
988#[test]
989fn wasm_float_min_regression_works() {
990    assert_eq!(
991        Float::min(F32::from(-0.0), F32::from(0.0)).to_bits(),
992        0x8000_0000,
993    );
994    assert_eq!(
995        Float::min(F32::from(0.0), F32::from(-0.0)).to_bits(),
996        0x8000_0000,
997    );
998}
999
1000#[test]
1001fn wasm_float_max_regression_works() {
1002    assert_eq!(
1003        Float::max(F32::from(-0.0), F32::from(0.0)).to_bits(),
1004        0x0000_0000,
1005    );
1006    assert_eq!(
1007        Float::max(F32::from(0.0), F32::from(-0.0)).to_bits(),
1008        0x0000_0000,
1009    );
1010}
1011
1012impl_float!(f32, f32, i32);
1013impl_float!(f64, f64, i64);
1014impl_float!(F32, f32, i32);
1015impl_float!(F64, f64, i64);
1016
1017#[test]
1018fn copysign_regression_works() {
1019    // This test has been directly extracted from a WebAssembly Specification assertion.
1020    use Float as _;
1021    assert!(F32::from_bits(0xFFC00000).is_nan());
1022    assert_eq!(
1023        F32::from_bits(0xFFC00000)
1024            .copysign(F32::from_bits(0x0000_0000))
1025            .to_bits(),
1026        F32::from_bits(0x7FC00000).to_bits()
1027    )
1028}
1029
1030#[cfg(not(feature = "std"))]
1031mod libm_adapters {
1032    pub mod f32 {
1033        #[inline]
1034        pub fn abs(v: f32) -> f32 {
1035            libm::fabsf(v)
1036        }
1037
1038        #[inline]
1039        pub fn floor(v: f32) -> f32 {
1040            libm::floorf(v)
1041        }
1042
1043        #[inline]
1044        pub fn ceil(v: f32) -> f32 {
1045            libm::ceilf(v)
1046        }
1047
1048        #[inline]
1049        pub fn trunc(v: f32) -> f32 {
1050            libm::truncf(v)
1051        }
1052
1053        #[inline]
1054        pub fn round(v: f32) -> f32 {
1055            libm::roundf(v)
1056        }
1057
1058        #[inline]
1059        pub fn fract(v: f32) -> f32 {
1060            v - trunc(v)
1061        }
1062
1063        #[inline]
1064        pub fn sqrt(v: f32) -> f32 {
1065            libm::sqrtf(v)
1066        }
1067    }
1068
1069    pub mod f64 {
1070        #[inline]
1071        pub fn abs(v: f64) -> f64 {
1072            libm::fabs(v)
1073        }
1074
1075        #[inline]
1076        pub fn floor(v: f64) -> f64 {
1077            libm::floor(v)
1078        }
1079
1080        #[inline]
1081        pub fn ceil(v: f64) -> f64 {
1082            libm::ceil(v)
1083        }
1084
1085        #[inline]
1086        pub fn trunc(v: f64) -> f64 {
1087            libm::trunc(v)
1088        }
1089
1090        #[inline]
1091        pub fn round(v: f64) -> f64 {
1092            libm::round(v)
1093        }
1094
1095        #[inline]
1096        pub fn fract(v: f64) -> f64 {
1097            v - trunc(v)
1098        }
1099
1100        #[inline]
1101        pub fn sqrt(v: f64) -> f64 {
1102            libm::sqrt(v)
1103        }
1104    }
1105}