odra_core/
arithmetic.rs

1//! Safe, overflowing addition and subtraction utilities.
2use crate::prelude::*;
3use casper_types::{U128, U256, U512};
4
5/// Overflowing addition, returning the result of addition or [ArithmeticsError::AdditionOverflow].
6pub trait OverflowingAdd: Sized {
7    /// Overflowing addition. Compute `self + rhs`, returns the result or error if overflowed.
8    fn overflowing_add(self, rhs: Self) -> Result<Self, ExecutionError>;
9}
10
11/// Overflowing subtraction, returning the result of addition or [ArithmeticsError::SubtractingOverflow].
12pub trait OverflowingSub: Sized {
13    /// Overflowing subtraction. Compute `self - rhs`, returns the result or error if overflowed.
14    fn overflowing_sub(self, rhs: Self) -> Result<Self, ExecutionError>;
15}
16
17/// Computation result error.
18#[cfg_attr(debug_assertions, derive(Debug, PartialEq, Eq))]
19pub enum ArithmeticsError {
20    /// Addition result exceeds the max value.
21    AdditionOverflow,
22    /// Subtraction result is lower than the min value.
23    SubtractingOverflow,
24    /// Conversion error
25    ConversionError
26}
27
28/// Implements [OverflowingAdd] and [OverflowingSub] for all the given types.
29macro_rules! impl_overflowing_add_sub {
30    ( $( $ty:ty ),+ ) => {
31        $(
32            impl OverflowingAdd for $ty {
33                fn overflowing_add(self, rhs: Self) -> Result<Self, ExecutionError> {
34                    let (res, is_overflowed)  = self.overflowing_add(rhs);
35                    match is_overflowed {
36                        true => Err(ArithmeticsError::AdditionOverflow.into()),
37                        false => Ok(res)
38                    }
39                }
40            }
41
42            impl OverflowingSub for $ty {
43                fn overflowing_sub(self, rhs: Self) -> Result<Self, ExecutionError> {
44                    let (res, is_overflowed)  = self.overflowing_sub(rhs);
45                    match is_overflowed {
46                        true => Err(ArithmeticsError::SubtractingOverflow.into()),
47                        false => Ok(res)
48                    }
49                }
50            }
51        )+
52    };
53}
54
55impl_overflowing_add_sub!(u8, u16, u32, u64, i8, i16, i32, i64, U128, U256, U512);
56
57#[cfg(test)]
58mod test {
59    use crate::arithmetic::{ArithmeticsError, OverflowingSub};
60
61    use super::OverflowingAdd;
62
63    #[test]
64    fn test_add() {
65        assert_eq!(<u8 as OverflowingAdd>::overflowing_add(2u8, 1u8), Ok(3u8));
66        assert_eq!(
67            <u8 as OverflowingAdd>::overflowing_add(u8::MAX, 1u8),
68            Err(ArithmeticsError::AdditionOverflow.into())
69        );
70    }
71
72    #[test]
73    fn test_sub() {
74        assert_eq!(<u8 as OverflowingSub>::overflowing_sub(2u8, 1u8), Ok(1u8));
75        assert_eq!(
76            <u8 as OverflowingSub>::overflowing_sub(u8::MIN, 1u8),
77            Err(ArithmeticsError::SubtractingOverflow.into())
78        );
79    }
80}