use crate::CmsError;
use std::ops::Add;
pub(crate) trait SafeAdd<T: Copy + Add<T, Output = T>> {
fn safe_add(&self, other: T) -> Result<T, CmsError>;
}
pub(crate) trait SafeMul<T: Copy + Add<T, Output = T>> {
fn safe_mul(&self, other: T) -> Result<T, CmsError>;
}
pub(crate) trait SafePowi<T: Copy + Add<T, Output = T>> {
fn safe_powi(&self, power: u32) -> Result<T, CmsError>;
}
macro_rules! safe_add_impl {
($type_name: ident) => {
impl SafeAdd<$type_name> for $type_name {
#[inline(always)]
fn safe_add(&self, other: $type_name) -> Result<$type_name, CmsError> {
if let Some(result) = self.checked_add(other) {
return Ok(result);
}
Err(CmsError::OverflowingError)
}
}
};
}
safe_add_impl!(u16);
safe_add_impl!(u32);
safe_add_impl!(i32);
safe_add_impl!(usize);
safe_add_impl!(isize);
macro_rules! safe_mul_impl {
($type_name: ident) => {
impl SafeMul<$type_name> for $type_name {
#[inline(always)]
fn safe_mul(&self, other: $type_name) -> Result<$type_name, CmsError> {
if let Some(result) = self.checked_mul(other) {
return Ok(result);
}
Err(CmsError::OverflowingError)
}
}
};
}
safe_mul_impl!(u16);
safe_mul_impl!(u32);
safe_mul_impl!(i32);
safe_mul_impl!(usize);
safe_mul_impl!(isize);
macro_rules! safe_powi_impl {
($type_name: ident) => {
impl SafePowi<$type_name> for $type_name {
#[inline(always)]
fn safe_powi(&self, power: u32) -> Result<$type_name, CmsError> {
if let Some(result) = self.checked_pow(power) {
return Ok(result);
}
Err(CmsError::OverflowingError)
}
}
};
}
safe_powi_impl!(u8);
safe_powi_impl!(u16);
safe_powi_impl!(u32);
safe_powi_impl!(i32);
safe_powi_impl!(usize);
safe_powi_impl!(isize);