diff --git a/gstreamer/src/clock_time.rs b/gstreamer/src/clock_time.rs index f4d48587d..ee74ac8bf 100644 --- a/gstreamer/src/clock_time.rs +++ b/gstreamer/src/clock_time.rs @@ -541,6 +541,17 @@ mod tests { Err(opt_ops::Error::Overflow) ); + assert_eq!(P_CT_1.opt_checked_add(P_CT_1), Ok(Some(P_CT_2))); + assert_eq!(P_CT_1.opt_checked_add(Some(N_CT_2)), Ok(Some(N_CT_1))); + assert_eq!(Some(P_CT_1).opt_checked_add(Some(P_CT_1)), Ok(Some(P_CT_2))); + assert_eq!(P_CT_1.opt_checked_add(None), Ok(None)); + assert_eq!(Some(N_CT_1).opt_checked_add(None), Ok(None)); + + assert_eq!( + ClockTime::MAX.into_positive().opt_checked_add(Some(P_CT_1)), + Err(opt_ops::Error::Overflow) + ); + assert_eq!(CT_2.checked_sub(CT_1), Some(CT_1)); assert_eq!(P_CT_3.checked_sub(P_CT_2), Some(P_CT_1)); assert_eq!(P_CT_2.checked_sub(P_CT_3), Some(N_CT_1)); @@ -562,12 +573,18 @@ mod tests { Err(opt_ops::Error::Overflow) ); + assert_eq!(P_CT_2.opt_checked_sub(Some(N_CT_1)), Ok(Some(P_CT_3))); + assert_eq!(Some(N_CT_2).opt_checked_sub(P_CT_1), Ok(Some(N_CT_3))); + assert_eq!(CT_1.checked_mul(2), Some(CT_2)); assert_eq!(P_CT_1.checked_mul(2), Some(P_CT_2)); assert_eq!(P_CT_1.checked_mul(-2), Some(N_CT_2)); assert_eq!(N_CT_1.checked_mul(2), Some(N_CT_2)); assert_eq!(N_CT_1.checked_mul(-2), Some(P_CT_2)); + assert_eq!(Some(P_CT_1).opt_checked_mul(-2i64), Ok(Some(N_CT_2))); + assert_eq!(N_CT_1.opt_checked_mul(2u64), Ok(Some(N_CT_2))); + assert_eq!(P_CT_1.checked_mul_unsigned(2u64), Some(P_CT_2)); assert_eq!(N_CT_1.checked_mul_unsigned(2u64), Some(N_CT_2)); @@ -577,6 +594,9 @@ mod tests { assert_eq!(N_CT_3.checked_div(3), Some(N_CT_1)); assert_eq!(N_CT_3.checked_div(-3), Some(P_CT_1)); + assert_eq!(Some(P_CT_3).opt_checked_div(-3i64), Ok(Some(N_CT_1))); + assert_eq!(N_CT_3.opt_checked_div(3u64), Ok(Some(N_CT_1))); + assert_eq!(P_CT_3.checked_div_unsigned(3u64), Some(P_CT_1)); assert_eq!(N_CT_3.checked_div_unsigned(3u64), Some(N_CT_1)); } diff --git a/gstreamer/src/macros.rs b/gstreamer/src/macros.rs index 63cdf8939..cd9ca06c2 100644 --- a/gstreamer/src/macros.rs +++ b/gstreamer/src/macros.rs @@ -630,6 +630,46 @@ macro_rules! impl_signed_ops( } } } + + impl OptionOperations for crate::Signed<$type> {} + + impl OptionCheckedAdd for crate::Signed<$type> { + type Output = Self; + fn opt_checked_add( + self, + rhs: Self, + ) -> Result, opt_ops::Error> { + self.checked_add(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionSaturatingAdd for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_add(self, rhs: Self) -> Option { + Some(self.saturating_add(rhs)) + } + } + + impl OptionCheckedSub for crate::Signed<$type> { + type Output = Self; + fn opt_checked_sub( + self, + rhs: Self, + ) -> Result, opt_ops::Error> { + self.checked_sub(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionSaturatingSub for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_sub(self, rhs: Self) -> Option { + Some(self.saturating_sub(rhs)) + } + } }; ); @@ -873,6 +913,86 @@ macro_rules! impl_signed_div_mul( *self = std::ops::Mul::mul(*self, rhs); } } + + impl OptionCheckedDiv<$signed_rhs> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_div(self, rhs: $signed_rhs) -> Result, opt_ops::Error> { + if rhs == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.checked_div(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionCheckedMul<$signed_rhs> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_mul(self, rhs: $signed_rhs) -> Result, opt_ops::Error> { + self.checked_mul(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionSaturatingMul<$signed_rhs> for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_mul(self, rhs: $signed_rhs) -> Option { + Some(self.saturating_mul(rhs)) + } + } + + impl OptionCheckedRem<$signed_rhs> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_rem(self, rhs: $signed_rhs) -> Result, opt_ops::Error> { + if rhs == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.checked_rem(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionCheckedDiv<$inner_type> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_div(self, rhs: $inner_type) -> Result, opt_ops::Error> { + if rhs == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.checked_div_unsigned(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionCheckedMul<$inner_type> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_mul(self, rhs: $inner_type) -> Result, opt_ops::Error> { + self.checked_mul_unsigned(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + + impl OptionSaturatingMul<$inner_type> for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_mul(self, rhs: $inner_type) -> Option { + Some(self.saturating_mul_unsigned(rhs)) + } + } + + impl OptionCheckedRem<$inner_type> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_rem(self, rhs: $inner_type) -> Result, opt_ops::Error> { + if rhs == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.checked_rem_unsigned(rhs) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } }; );