use core::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub};
macro_rules! overflowing_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn $method(self, v: Self) -> (Self, bool) {
<$t>::$method(self, v)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait OverflowingAdd: Sized + [c0nst] Add<Self> {
fn overflowing_add(self, v: Self) -> (<Self as Add<Self>>::Output, bool);
}
}
overflowing_impl!(OverflowingAdd, overflowing_add, u8);
overflowing_impl!(OverflowingAdd, overflowing_add, u16);
overflowing_impl!(OverflowingAdd, overflowing_add, u32);
overflowing_impl!(OverflowingAdd, overflowing_add, u64);
overflowing_impl!(OverflowingAdd, overflowing_add, usize);
overflowing_impl!(OverflowingAdd, overflowing_add, u128);
overflowing_impl!(OverflowingAdd, overflowing_add, i8);
overflowing_impl!(OverflowingAdd, overflowing_add, i16);
overflowing_impl!(OverflowingAdd, overflowing_add, i32);
overflowing_impl!(OverflowingAdd, overflowing_add, i64);
overflowing_impl!(OverflowingAdd, overflowing_add, isize);
overflowing_impl!(OverflowingAdd, overflowing_add, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingSub: Sized + [c0nst] Sub<Self> {
fn overflowing_sub(self, v: Self) -> (<Self as Sub<Self>>::Output, bool);
}
}
overflowing_impl!(OverflowingSub, overflowing_sub, u8);
overflowing_impl!(OverflowingSub, overflowing_sub, u16);
overflowing_impl!(OverflowingSub, overflowing_sub, u32);
overflowing_impl!(OverflowingSub, overflowing_sub, u64);
overflowing_impl!(OverflowingSub, overflowing_sub, usize);
overflowing_impl!(OverflowingSub, overflowing_sub, u128);
overflowing_impl!(OverflowingSub, overflowing_sub, i8);
overflowing_impl!(OverflowingSub, overflowing_sub, i16);
overflowing_impl!(OverflowingSub, overflowing_sub, i32);
overflowing_impl!(OverflowingSub, overflowing_sub, i64);
overflowing_impl!(OverflowingSub, overflowing_sub, isize);
overflowing_impl!(OverflowingSub, overflowing_sub, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingMul: Sized + [c0nst] Mul<Self> {
fn overflowing_mul(self, v: Self) -> (<Self as Mul<Self>>::Output, bool);
}
}
overflowing_impl!(OverflowingMul, overflowing_mul, u8);
overflowing_impl!(OverflowingMul, overflowing_mul, u16);
overflowing_impl!(OverflowingMul, overflowing_mul, u32);
overflowing_impl!(OverflowingMul, overflowing_mul, u64);
overflowing_impl!(OverflowingMul, overflowing_mul, usize);
overflowing_impl!(OverflowingMul, overflowing_mul, u128);
overflowing_impl!(OverflowingMul, overflowing_mul, i8);
overflowing_impl!(OverflowingMul, overflowing_mul, i16);
overflowing_impl!(OverflowingMul, overflowing_mul, i32);
overflowing_impl!(OverflowingMul, overflowing_mul, i64);
overflowing_impl!(OverflowingMul, overflowing_mul, isize);
overflowing_impl!(OverflowingMul, overflowing_mul, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingDiv: Sized + [c0nst] Div<Self> {
fn overflowing_div(self, v: Self) -> (<Self as Div<Self>>::Output, bool);
}
}
overflowing_impl!(OverflowingDiv, overflowing_div, u8);
overflowing_impl!(OverflowingDiv, overflowing_div, u16);
overflowing_impl!(OverflowingDiv, overflowing_div, u32);
overflowing_impl!(OverflowingDiv, overflowing_div, u64);
overflowing_impl!(OverflowingDiv, overflowing_div, usize);
overflowing_impl!(OverflowingDiv, overflowing_div, u128);
overflowing_impl!(OverflowingDiv, overflowing_div, i8);
overflowing_impl!(OverflowingDiv, overflowing_div, i16);
overflowing_impl!(OverflowingDiv, overflowing_div, i32);
overflowing_impl!(OverflowingDiv, overflowing_div, i64);
overflowing_impl!(OverflowingDiv, overflowing_div, isize);
overflowing_impl!(OverflowingDiv, overflowing_div, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingRem: Sized + [c0nst] Rem<Self> {
fn overflowing_rem(self, v: Self) -> (<Self as Rem<Self>>::Output, bool);
}
}
overflowing_impl!(OverflowingRem, overflowing_rem, u8);
overflowing_impl!(OverflowingRem, overflowing_rem, u16);
overflowing_impl!(OverflowingRem, overflowing_rem, u32);
overflowing_impl!(OverflowingRem, overflowing_rem, u64);
overflowing_impl!(OverflowingRem, overflowing_rem, usize);
overflowing_impl!(OverflowingRem, overflowing_rem, u128);
overflowing_impl!(OverflowingRem, overflowing_rem, i8);
overflowing_impl!(OverflowingRem, overflowing_rem, i16);
overflowing_impl!(OverflowingRem, overflowing_rem, i32);
overflowing_impl!(OverflowingRem, overflowing_rem, i64);
overflowing_impl!(OverflowingRem, overflowing_rem, isize);
overflowing_impl!(OverflowingRem, overflowing_rem, i128);
macro_rules! overflowing_neg_impl {
($($t:ty)*) => {$(
c0nst::c0nst! {
c0nst impl OverflowingNeg for $t {
type Output = $t;
#[inline]
fn overflowing_neg(self) -> ($t, bool) { <$t>::overflowing_neg(self) }
}
}
)*};
}
macro_rules! overflowing_unary_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn $method(self) -> ($t, bool) {
<$t>::$method(self)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait OverflowingNeg: Sized {
type Output;
fn overflowing_neg(self) -> (Self::Output, bool);
}
}
overflowing_neg_impl!(u8 u16 u32 u64 usize u128 i8 i16 i32 i64 isize i128);
c0nst::c0nst! {
pub c0nst trait OverflowingAbs: Sized + [c0nst] Neg {
fn overflowing_abs(self) -> (<Self as Neg>::Output, bool);
}
}
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, i8);
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, i16);
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, i32);
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, i64);
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, isize);
overflowing_unary_impl!(OverflowingAbs, overflowing_abs, i128);
macro_rules! overflowing_u32_rhs_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn $method(self, rhs: u32) -> ($t, bool) {
<$t>::$method(self, rhs)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait OverflowingShl: Sized + [c0nst] Shl<u32> {
fn overflowing_shl(self, rhs: u32) -> (<Self as Shl<u32>>::Output, bool);
}
}
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, u8);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, u16);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, u32);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, u64);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, usize);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, u128);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, i8);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, i16);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, i32);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, i64);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, isize);
overflowing_u32_rhs_impl!(OverflowingShl, overflowing_shl, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingShr: Sized + [c0nst] Shr<u32> {
fn overflowing_shr(self, rhs: u32) -> (<Self as Shr<u32>>::Output, bool);
}
}
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, u8);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, u16);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, u32);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, u64);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, usize);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, u128);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, i8);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, i16);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, i32);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, i64);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, isize);
overflowing_u32_rhs_impl!(OverflowingShr, overflowing_shr, i128);
c0nst::c0nst! {
pub c0nst trait OverflowingPow: Sized + [c0nst] Mul<Self> {
fn overflowing_pow(self, exp: u32) -> (<Self as Mul<Self>>::Output, bool);
}
}
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, u8);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, u16);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, u32);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, u64);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, usize);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, u128);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, i8);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, i16);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, i32);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, i64);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, isize);
overflowing_u32_rhs_impl!(OverflowingPow, overflowing_pow, i128);
#[test]
fn test_overflowing_extended_traits() {
assert_eq!(
OverflowingDiv::overflowing_div(i8::MIN, -1),
(i8::MIN, true)
);
assert_eq!(OverflowingDiv::overflowing_div(100u8, 7), (14, false));
assert_eq!(OverflowingRem::overflowing_rem(i8::MIN, -1), (0, true));
assert_eq!(OverflowingNeg::overflowing_neg(1u8), (255, true));
assert_eq!(OverflowingNeg::overflowing_neg(0u8), (0, false));
assert_eq!(OverflowingNeg::overflowing_neg(i8::MIN), (i8::MIN, true));
assert_eq!(OverflowingAbs::overflowing_abs(i8::MIN), (i8::MIN, true));
assert_eq!(OverflowingAbs::overflowing_abs(-7i8), (7, false));
assert_eq!(OverflowingShl::overflowing_shl(1u8, 8), (1, true));
assert_eq!(OverflowingShr::overflowing_shr(0x80u8, 9), (0x40, true));
assert_eq!(OverflowingPow::overflowing_pow(3u8, 6), (217, true));
assert_eq!(OverflowingPow::overflowing_pow(3i32, 4), (81, false));
}
#[test]
fn test_overflowing_traits() {
fn overflowing_add<T: OverflowingAdd<Output = T>>(a: T, b: T) -> (T, bool) {
a.overflowing_add(b)
}
fn overflowing_sub<T: OverflowingSub<Output = T>>(a: T, b: T) -> (T, bool) {
a.overflowing_sub(b)
}
fn overflowing_mul<T: OverflowingMul<Output = T>>(a: T, b: T) -> (T, bool) {
a.overflowing_mul(b)
}
assert_eq!(overflowing_add(5i16, 2), (7, false));
assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
assert_eq!(overflowing_sub(5i16, 2), (3, false));
assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
assert_eq!(overflowing_mul(5i16, 2), (10, false));
assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
}