1use crate::prelude::*;
3use casper_types::{U128, U256, U512};
4
5pub trait OverflowingAdd: Sized {
7 fn overflowing_add(self, rhs: Self) -> Result<Self, ExecutionError>;
9}
10
11pub trait OverflowingSub: Sized {
13 fn overflowing_sub(self, rhs: Self) -> Result<Self, ExecutionError>;
15}
16
17#[cfg_attr(debug_assertions, derive(Debug, PartialEq, Eq))]
19pub enum ArithmeticsError {
20 AdditionOverflow,
22 SubtractingOverflow
24}
25
26macro_rules! impl_overflowing_add_sub {
28 ( $( $ty:ty ),+ ) => {
29 $(
30 impl OverflowingAdd for $ty {
31 fn overflowing_add(self, rhs: Self) -> Result<Self, ExecutionError> {
32 let (res, is_overflowed) = self.overflowing_add(rhs);
33 match is_overflowed {
34 true => Err(ArithmeticsError::AdditionOverflow.into()),
35 false => Ok(res)
36 }
37 }
38 }
39
40 impl OverflowingSub for $ty {
41 fn overflowing_sub(self, rhs: Self) -> Result<Self, ExecutionError> {
42 let (res, is_overflowed) = self.overflowing_sub(rhs);
43 match is_overflowed {
44 true => Err(ArithmeticsError::SubtractingOverflow.into()),
45 false => Ok(res)
46 }
47 }
48 }
49 )+
50 };
51}
52
53impl_overflowing_add_sub!(u8, u16, u32, u64, i8, i16, i32, i64, U128, U256, U512);
54
55#[cfg(test)]
56mod test {
57 use crate::arithmetic::{ArithmeticsError, OverflowingSub};
58
59 use super::OverflowingAdd;
60
61 #[test]
62 fn test_add() {
63 assert_eq!(<u8 as OverflowingAdd>::overflowing_add(2u8, 1u8), Ok(3u8));
64 assert_eq!(
65 <u8 as OverflowingAdd>::overflowing_add(u8::MAX, 1u8),
66 Err(ArithmeticsError::AdditionOverflow.into())
67 );
68 }
69
70 #[test]
71 fn test_sub() {
72 assert_eq!(<u8 as OverflowingSub>::overflowing_sub(2u8, 1u8), Ok(1u8));
73 assert_eq!(
74 <u8 as OverflowingSub>::overflowing_sub(u8::MIN, 1u8),
75 Err(ArithmeticsError::SubtractingOverflow.into())
76 );
77 }
78}