1use casper_types::{U128, U256, U512};
3
4use crate::ExecutionError;
5
6pub trait OverflowingAdd: Sized {
8 fn overflowing_add(self, rhs: Self) -> Result<Self, ExecutionError>;
10}
11
12pub trait OverflowingSub: Sized {
14 fn overflowing_sub(self, rhs: Self) -> Result<Self, ExecutionError>;
16}
17
18#[cfg_attr(debug_assertions, derive(Debug, PartialEq, Eq))]
20pub enum ArithmeticsError {
21 AdditionOverflow,
23 SubtractingOverflow
25}
26
27#[macro_export]
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}