From 57d8d46ab6f926b6dbbccc7f1bcc248a3f145210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Laignel?= Date: Thu, 29 Sep 2022 14:22:19 +0200 Subject: [PATCH] gst/format: fix some ops and add others Some operations were implemented on types that wouldn't result in the expected physical unit. E.g.: - `ClockTime / ClockTime` results in a unit-less factor. - `u64 / ClockTime` would result in a `1 / ClockTime`. Since we don't use any `Frequency` type, this operation is removed. Users should use the `ClockTime` accessors to compute the expected value. This commit also adds: - multiplications with integers as the left hand side operands. - `Partial{Eq,Ord} for `Signed` with `T` as left hand side operand. - `opt_add` / `opt_sub` for `Signed` with `T` as left or right hand side operands. - missing tests for `Partial{Eq,Ord}` and `OptionOrd`. This implementation can interfere with unrelated code and was removed: - `Signed.` `PartialOrd` makes existing code computing the len of slices needing type annotation because the len is later used in a comparison for which the compiler is unable to determine if the len is `Signed` or `usize`. --- gstreamer/src/format/clock_time.rs | 119 +++++++- gstreamer/src/format/macros.rs | 357 +++++++++++++++++++++-- gstreamer/src/format/signed.rs | 4 - tutorials/src/bin/playback-tutorial-4.rs | 6 +- 4 files changed, 443 insertions(+), 43 deletions(-) diff --git a/gstreamer/src/format/clock_time.rs b/gstreamer/src/format/clock_time.rs index e93bf4496..4e26f9037 100644 --- a/gstreamer/src/format/clock_time.rs +++ b/gstreamer/src/format/clock_time.rs @@ -288,7 +288,7 @@ impl TryFrom for ClockTime { let nanos = d.as_nanos(); - // Note: `std::u64::MAX` is `ClockTime::None`. + // Note: `std::u64::MAX` is `ClockTime::NONE`. if nanos >= std::u64::MAX as u128 { return Err(DurationError); } @@ -527,6 +527,8 @@ mod tests { const CT_20: ClockTime = ClockTime::from_nseconds(20); const CT_30: ClockTime = ClockTime::from_nseconds(30); + const P_CT_0: Signed = Signed::Positive(ClockTime::ZERO); + const P_CT_NONE: Option> = None; const P_CT_1: Signed = Signed::Positive(ClockTime::from_nseconds(1)); const P_CT_2: Signed = Signed::Positive(ClockTime::from_nseconds(2)); const P_CT_3: Signed = Signed::Positive(ClockTime::from_nseconds(3)); @@ -558,6 +560,8 @@ mod tests { assert_eq!(CT_30 - CT_30, ClockTime::ZERO); assert_eq!(CT_10 * 3, CT_30); assert_eq!(3 * CT_10, CT_30); + assert_eq!(CT_20 / 2, CT_10); + assert_eq!(CT_20 / CT_2, 10); assert_eq!(CT_30.nseconds(), 30); assert_eq!(P_CT_1 + P_CT_2, P_CT_3); @@ -567,17 +571,30 @@ mod tests { assert_eq!(N_CT_2 + P_CT_3, P_CT_1); assert_eq!(N_CT_2 + N_CT_1, N_CT_3); + assert_eq!(CT_1 + P_CT_2, P_CT_3); + assert_eq!(P_CT_1 + CT_2, P_CT_3); + assert_eq!(CT_3 + N_CT_1, P_CT_2); + assert_eq!(N_CT_1 + CT_2, P_CT_1); + assert_eq!(P_CT_3 - P_CT_2, P_CT_1); assert_eq!(P_CT_2 - P_CT_3, N_CT_1); assert_eq!(P_CT_2 - N_CT_1, P_CT_3); assert_eq!(N_CT_2 - P_CT_1, N_CT_3); assert_eq!(N_CT_3 - N_CT_1, N_CT_2); + assert_eq!(CT_3 - P_CT_2, P_CT_1); + assert_eq!(P_CT_3 - CT_2, P_CT_1); + assert_eq!(N_CT_2 - CT_1, N_CT_3); + assert_eq!(CT_2 - N_CT_1, P_CT_3); + assert_eq!(P_CT_1 * 2i64, P_CT_2); assert_eq!(P_CT_1 * -2i64, N_CT_2); assert_eq!(N_CT_1 * 2i64, N_CT_2); assert_eq!(N_CT_1 * -2i64, P_CT_2); + assert_eq!(2i64 * P_CT_1, P_CT_2); + assert_eq!(-2i64 * P_CT_1, N_CT_2); + assert_eq!(P_CT_1 * 2u64, P_CT_2); assert_eq!(N_CT_1 * 2u64, N_CT_2); @@ -586,6 +603,8 @@ mod tests { assert_eq!(N_CT_2 / 2i64, N_CT_1); assert_eq!(N_CT_2 / -2i64, P_CT_1); + assert_eq!(P_CT_2 / N_CT_2, Signed::Negative(1)); + assert_eq!(P_CT_2 / 2u64, P_CT_1); assert_eq!(N_CT_2 / 2u64, N_CT_1); @@ -594,6 +613,8 @@ mod tests { assert_eq!(N_CT_3 % 2i64, N_CT_1); assert_eq!(N_CT_3 % -2i64, N_CT_1); + assert_eq!(N_CT_3 % N_CT_2, N_CT_1); + assert_eq!(P_CT_3 % 2u64, P_CT_1); assert_eq!(N_CT_3 % 2u64, N_CT_1); } @@ -611,8 +632,11 @@ mod tests { assert_eq!(CT_1.opt_checked_add(CT_1), Ok(Some(CT_2))); assert_eq!(CT_1.opt_checked_add(Some(CT_1)), Ok(Some(CT_2))); assert_eq!(Some(CT_1).opt_checked_add(Some(CT_1)), Ok(Some(CT_2))); - assert_eq!(CT_1.opt_checked_add(None), Ok(None)); - assert_eq!(Some(CT_1).opt_checked_add(None), Ok(None)); + assert_eq!(CT_1.opt_checked_add(ClockTime::NONE), Ok(None)); + assert_eq!(Some(CT_1).opt_checked_add(ClockTime::NONE), Ok(None)); + + assert_eq!(CT_1.opt_checked_add(P_CT_1), Ok(Some(P_CT_2))); + assert_eq!(N_CT_3.opt_checked_add(CT_1), Ok(Some(N_CT_2))); assert!(ClockTime::MAX.checked_add(CT_1).is_none()); assert_eq!( @@ -623,8 +647,8 @@ mod tests { 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!(P_CT_1.opt_checked_add(ClockTime::NONE), Ok(None)); + assert_eq!(Some(N_CT_1).opt_checked_add(ClockTime::NONE), Ok(None)); assert_eq!( ClockTime::MAX.into_positive().opt_checked_add(Some(P_CT_1)), @@ -643,8 +667,11 @@ mod tests { assert_eq!(CT_2.opt_checked_sub(Some(CT_1)), Ok(Some(CT_1))); assert_eq!(Some(CT_2).opt_checked_sub(CT_1), Ok(Some(CT_1))); assert_eq!(Some(CT_2).opt_checked_sub(Some(CT_1)), Ok(Some(CT_1))); - assert_eq!(CT_2.opt_checked_sub(None), Ok(None)); - assert_eq!(Some(CT_2).opt_checked_sub(None), Ok(None)); + assert_eq!(CT_2.opt_checked_sub(ClockTime::NONE), Ok(None)); + assert_eq!(Some(CT_2).opt_checked_sub(ClockTime::NONE), Ok(None)); + + assert_eq!(P_CT_2.opt_checked_sub(CT_1), Ok(Some(P_CT_1))); + assert_eq!(N_CT_2.opt_checked_sub(CT_1), Ok(Some(N_CT_3))); assert!(CT_1.checked_sub(CT_2).is_none()); assert_eq!( @@ -656,6 +683,8 @@ mod tests { 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!(Some(CT_1).opt_checked_mul(2), Ok(Some(CT_2))); + assert_eq!(1u64.opt_checked_mul(Some(CT_2)), Ok(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)); @@ -664,6 +693,8 @@ mod tests { 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!((-2i64).opt_checked_mul(Some(P_CT_1)), 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)); @@ -673,6 +704,8 @@ 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(CT_3).opt_checked_div(CT_3), Ok(Some(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))); @@ -689,6 +722,7 @@ mod tests { Some(CT_1).opt_overflowing_add(Some(CT_2)), Some((CT_3, false)) ); + assert_eq!(ClockTime::NONE.opt_overflowing_add(CT_2), None); assert_eq!(CT_1.opt_overflowing_add(ClockTime::NONE), None); @@ -737,7 +771,10 @@ mod tests { assert_eq!(CT_1.opt_saturating_add(Some(CT_2)), Some(CT_3)); assert_eq!(Some(CT_1).opt_saturating_add(Some(CT_2)), Some(CT_3)); - assert_eq!(Some(CT_1).opt_saturating_add(None), None); + assert_eq!(Some(CT_1).opt_saturating_add(ClockTime::NONE), None); + + assert_eq!(P_CT_1.opt_saturating_add(Some(CT_2)), Some(P_CT_3)); + assert_eq!(Some(CT_1).opt_saturating_add(P_CT_2), Some(P_CT_3)); assert_eq!(ClockTime::MAX.saturating_add(CT_1), ClockTime::MAX); assert_eq!( @@ -756,7 +793,10 @@ mod tests { assert_eq!(CT_3.opt_saturating_sub(Some(CT_2)), Some(CT_1)); assert_eq!(Some(CT_3).opt_saturating_sub(Some(CT_2)), Some(CT_1)); - assert_eq!(Some(CT_3).opt_saturating_sub(None), None); + assert_eq!(Some(CT_3).opt_saturating_sub(ClockTime::NONE), None); + + assert_eq!(P_CT_2.opt_saturating_sub(Some(CT_3)), Some(N_CT_1)); + assert_eq!(Some(CT_3).opt_saturating_sub(P_CT_2), Some(P_CT_1)); assert!(CT_1.saturating_sub(CT_2).is_zero()); assert_eq!(P_CT_1.saturating_sub(P_CT_2), N_CT_1); @@ -773,12 +813,18 @@ mod tests { assert_eq!(N_CT_1.saturating_mul(2), N_CT_2); assert_eq!(N_CT_1.saturating_mul(-2), P_CT_2); + assert_eq!(Some(N_CT_1).opt_saturating_mul(-2i64), Some(P_CT_2)); + assert_eq!((-2i64).opt_saturating_mul(Some(N_CT_1)), Some(P_CT_2)); + assert_eq!(P_CT_1.saturating_mul_unsigned(2u64), P_CT_2); assert_eq!(N_CT_1.saturating_mul_unsigned(2u64), N_CT_2); assert_eq!(p_ct_max.saturating_mul(2), p_ct_max); assert_eq!(n_ct_max.saturating_mul(2), n_ct_max); + assert_eq!(Some(2i64).opt_saturating_mul(p_ct_max), Some(p_ct_max)); + assert_eq!(2u64.opt_saturating_mul(Some(n_ct_max)), Some(n_ct_max)); + assert_eq!(p_ct_max.saturating_mul_unsigned(2u64), p_ct_max); assert_eq!(n_ct_max.saturating_mul_unsigned(2u64), n_ct_max); } @@ -801,7 +847,7 @@ mod tests { assert_eq!(CT_3.opt_wrapping_sub(CT_2), Some(CT_1)); assert_eq!(Some(CT_3).opt_wrapping_sub(CT_2), Some(CT_1)); assert_eq!(Some(CT_3).opt_wrapping_sub(Some(CT_2)), Some(CT_1)); - assert_eq!(Some(CT_3).opt_wrapping_sub(None), None); + assert_eq!(Some(CT_3).opt_wrapping_sub(ClockTime::NONE), None); assert_eq!(CT_1.wrapping_sub(CT_2), ClockTime::MAX); assert_eq!( @@ -864,6 +910,9 @@ mod tests { assert!(ClockTime::ZERO < CT_3); assert!(Some(ClockTime::ZERO) < Some(CT_3)); + assert_eq!(CT_2, CT_2); + assert_ne!(CT_3, CT_2); + assert!(ClockTime::ZERO.into_positive() < P_CT_1); assert!(ClockTime::ZERO.into_positive() > N_CT_1); assert!(P_CT_1 < P_CT_2); @@ -871,11 +920,35 @@ mod tests { assert!(N_CT_1 < P_CT_2); assert!(N_CT_3 < N_CT_2); + assert!(P_CT_1 < CT_2); + assert!(CT_1 < P_CT_2); + assert!(N_CT_2 < CT_1); + assert!(CT_1 > N_CT_2); + + assert_eq!(CT_2, P_CT_2); + assert_ne!(N_CT_3, CT_3); + assert_eq!(Some(CT_2).opt_lt(Some(CT_3)), Some(true)); assert_eq!(Some(CT_3).opt_lt(CT_2), Some(false)); assert_eq!(Some(CT_2).opt_le(Some(CT_3)), Some(true)); assert_eq!(Some(CT_3).opt_le(CT_3), Some(true)); + assert_eq!(Some(P_CT_2).opt_lt(Some(P_CT_3)), Some(true)); + assert_eq!(Some(P_CT_3).opt_lt(P_CT_2), Some(false)); + assert_eq!(Some(P_CT_2).opt_le(Some(P_CT_3)), Some(true)); + assert_eq!(Some(P_CT_3).opt_le(P_CT_3), Some(true)); + + assert_eq!(Some(P_CT_0).opt_lt(P_CT_NONE), None); + assert_eq!(P_CT_NONE.opt_lt(P_CT_0), None); + + assert_eq!(Some(N_CT_3).opt_lt(Some(N_CT_2)), Some(true)); + assert_eq!(Some(N_CT_2).opt_lt(N_CT_3), Some(false)); + assert_eq!(Some(N_CT_3).opt_le(Some(N_CT_2)), Some(true)); + assert_eq!(Some(N_CT_3).opt_le(N_CT_3), Some(true)); + + assert_eq!(Some(P_CT_2).opt_lt(N_CT_3), Some(false)); + assert_eq!(Some(N_CT_3).opt_lt(Some(P_CT_2)), Some(true)); + assert!(CT_3 > CT_2); assert!(Some(CT_3) > Some(CT_2)); assert!(CT_2 > ClockTime::ZERO); @@ -891,6 +964,20 @@ mod tests { assert_eq!(Some(CT_3).opt_ge(Some(CT_2)), Some(true)); assert_eq!(Some(CT_3).opt_ge(CT_3), Some(true)); + assert_eq!(Some(P_CT_3).opt_gt(Some(P_CT_2)), Some(true)); + assert_eq!(Some(P_CT_3).opt_ge(Some(P_CT_2)), Some(true)); + assert_eq!(Some(P_CT_3).opt_ge(P_CT_3), Some(true)); + + assert_eq!(Some(P_CT_0).opt_gt(P_CT_NONE), None); + assert_eq!(P_CT_NONE.opt_gt(P_CT_0), None); + + assert_eq!(Some(N_CT_3).opt_gt(Some(N_CT_2)), Some(false)); + assert_eq!(Some(N_CT_3).opt_ge(Some(N_CT_2)), Some(false)); + assert_eq!(Some(N_CT_3).opt_ge(N_CT_3), Some(true)); + + assert_eq!(Some(P_CT_2).opt_gt(N_CT_3), Some(true)); + assert_eq!(Some(N_CT_3).opt_gt(Some(P_CT_2)), Some(false)); + assert!(!(ClockTime::NONE < None)); assert!(!(ClockTime::NONE > None)); @@ -914,11 +1001,23 @@ mod tests { assert_eq!(ClockTime::NONE.opt_min(Some(CT_2)), None); assert_eq!(Some(CT_3).opt_min(ClockTime::NONE), None); + assert_eq!(P_CT_3.opt_min(P_CT_2), Some(P_CT_2)); + assert_eq!(P_CT_2.opt_min(P_CT_3), Some(P_CT_2)); + assert_eq!(N_CT_3.opt_min(N_CT_2), Some(N_CT_3)); + assert_eq!(N_CT_2.opt_min(N_CT_3), Some(N_CT_3)); + assert_eq!(P_CT_2.opt_min(N_CT_3), Some(N_CT_3)); + assert_eq!(CT_3.opt_max(CT_2), Some(CT_3)); assert_eq!(CT_3.opt_max(Some(CT_2)), Some(CT_3)); assert_eq!(Some(CT_3).opt_max(Some(CT_2)), Some(CT_3)); assert_eq!(ClockTime::NONE.opt_max(Some(CT_2)), None); assert_eq!(Some(CT_3).opt_max(ClockTime::NONE), None); + + assert_eq!(P_CT_3.opt_max(P_CT_2), Some(P_CT_3)); + assert_eq!(P_CT_2.opt_max(P_CT_3), Some(P_CT_3)); + assert_eq!(N_CT_3.opt_max(N_CT_2), Some(N_CT_2)); + assert_eq!(N_CT_2.opt_max(N_CT_3), Some(N_CT_2)); + assert_eq!(P_CT_2.opt_max(N_CT_3), Some(P_CT_2)); } #[test] diff --git a/gstreamer/src/format/macros.rs b/gstreamer/src/format/macros.rs index 376360908..0ad2d49ce 100644 --- a/gstreamer/src/format/macros.rs +++ b/gstreamer/src/format/macros.rs @@ -106,14 +106,6 @@ macro_rules! impl_trait_op_inner_type( } } - impl std::ops::$op<$name> for $inner_type { - type Output = $name; - - fn $op_name(self, rhs: $name) -> $name { - $name(self.$op_name(rhs.0)) - } - } - impl std::ops::$op_assign<$inner_type> for $name { fn $op_assign_name(&mut self, rhs: $inner_type) { self.0.$op_assign_name(rhs) @@ -192,9 +184,9 @@ macro_rules! impl_non_trait_op_inner_type( ); macro_rules! impl_unsigned_int_into_signed( - ($name:ident) => { - impl crate::UnsignedIntoSigned for $name { - type Signed = crate::Signed<$name>; + ($type:ty) => { + impl crate::UnsignedIntoSigned for $type { + type Signed = crate::Signed<$type>; fn into_positive(self) -> Self::Signed { crate::Signed::Positive(self) @@ -205,8 +197,8 @@ macro_rules! impl_unsigned_int_into_signed( } } - impl crate::UnsignedIntoSigned for Option<$name> { - type Signed = Option>; + impl crate::UnsignedIntoSigned for Option<$type> { + type Signed = Option>; fn into_positive(self) -> Self::Signed { Some(self?.into_positive()) @@ -217,6 +209,22 @@ macro_rules! impl_unsigned_int_into_signed( } } }; + + ($type:ty, $inner_type:ty) => { + impl_unsigned_int_into_signed!($type); + + impl crate::Signed<$type> { + // rustdoc-stripper-ignore-next + /// Returns a `Signed` containing the inner type of `self`. + pub fn into_inner_signed(self) -> crate::Signed<$inner_type> { + use crate::Signed::*; + match self { + Positive(new_type) => Positive(*new_type), + Negative(new_type) => Negative(*new_type), + } + } + } + }; ); macro_rules! impl_common_ops_for_newtype_uint( @@ -235,19 +243,39 @@ macro_rules! impl_common_ops_for_newtype_uint( impl_trait_op_same!($name, Add, add, AddAssign, add_assign); impl_trait_op_same!($name, Sub, sub, SubAssign, sub_assign); - impl_trait_op_same!($name, Mul, mul, MulAssign, mul_assign); - impl_trait_op_same!($name, Div, div, DivAssign, div_assign); - impl_trait_op_same!($name, Rem, rem, RemAssign, rem_assign); + impl std::ops::Div<$name> for $name { + type Output = $inner_type; + + fn div(self, rhs: $name) -> $inner_type { + self.0.div(rhs.0) + } + } + impl std::ops::Rem<$name> for $name { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + Self(self.0.rem(rhs.0)) + } + } impl_non_trait_op_same!($name, $inner_type); impl_trait_op_inner_type!($name, $inner_type, Mul, mul, MulAssign, mul_assign); + impl std::ops::Mul<$name> for $inner_type { + type Output = $name; + + fn mul(self, rhs: $name) -> $name { + $name(self.mul(rhs.0)) + } + } + impl_trait_op_inner_type!($name, $inner_type, Div, div, DivAssign, div_assign); impl_trait_op_inner_type!($name, $inner_type, Rem, rem, RemAssign, rem_assign); impl_non_trait_op_inner_type!($name, $inner_type); - impl_unsigned_int_into_signed!($name); + impl_unsigned_int_into_signed!($name, $inner_type); + impl_signed_ops!($name, $inner_type, $name::ZERO); impl muldiv::MulDiv<$inner_type> for $name { @@ -314,10 +342,23 @@ macro_rules! impl_common_ops_for_newtype_uint( if rhs == 0 { return Err(opt_ops::Error::DivisionByZero); } - self.0 + self .checked_div(rhs) .ok_or(opt_ops::Error::Overflow) - .map(|val| Some(Self(val))) + .map(Some) + } + } + + impl opt_ops::OptionCheckedDiv for $name { + type Output = $inner_type; + fn opt_checked_div(self, rhs: Self) -> Result, opt_ops::Error> { + if rhs.0 == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.0 + .checked_div(rhs.0) + .ok_or(opt_ops::Error::Overflow) + .map(Some) } } @@ -333,6 +374,18 @@ macro_rules! impl_common_ops_for_newtype_uint( } } + impl opt_ops::OptionCheckedMul<$name> for $inner_type { + type Output = $name; + fn opt_checked_mul( + self, + rhs: $name, + ) -> Result, opt_ops::Error> { + rhs.checked_mul(self) + .ok_or(opt_ops::Error::Overflow) + .map(Some) + } + } + impl opt_ops::OptionSaturatingMul<$inner_type> for $name { type Output = Self; fn opt_saturating_mul(self, rhs: $inner_type) -> Option { @@ -340,6 +393,13 @@ macro_rules! impl_common_ops_for_newtype_uint( } } + impl opt_ops::OptionSaturatingMul<$name> for $inner_type { + type Output = $name; + fn opt_saturating_mul(self, rhs: $name) -> Option { + Some(rhs.saturating_mul(self)) + } + } + impl opt_ops::OptionOverflowingMul<$inner_type> for $name { type Output = Self; fn opt_overflowing_mul(self, rhs: $inner_type) -> Option<(Self::Output, bool)> { @@ -348,6 +408,14 @@ macro_rules! impl_common_ops_for_newtype_uint( } } + impl opt_ops::OptionOverflowingMul<$name> for $inner_type { + type Output = $name; + fn opt_overflowing_mul(self, rhs: $name) -> Option<(Self::Output, bool)> { + let res = rhs.overflowing_mul(self); + Some((res.0, res.1)) + } + } + impl opt_ops::OptionWrappingMul<$inner_type> for $name { type Output = Self; fn opt_wrapping_mul(self, rhs: $inner_type) -> Option { @@ -355,16 +423,34 @@ macro_rules! impl_common_ops_for_newtype_uint( } } + impl opt_ops::OptionWrappingMul<$name> for $inner_type { + type Output = $name; + fn opt_wrapping_mul(self, rhs: $name) -> Option { + Some(rhs.wrapping_mul(self)) + } + } + impl opt_ops::OptionCheckedRem<$inner_type> for $name { 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.0 - .checked_rem(rhs) + self.checked_rem(rhs) .ok_or(opt_ops::Error::Overflow) - .map(|val| Some(Self(val))) + .map(Some) + } + } + + impl opt_ops::OptionCheckedRem for $name { + type Output = Self; + fn opt_checked_rem(self, rhs: Self) -> Result, opt_ops::Error> { + if rhs.0 == 0 { + return Err(opt_ops::Error::DivisionByZero); + } + self.checked_rem(rhs.0) + .ok_or(opt_ops::Error::Overflow) + .map(Some) } } @@ -409,10 +495,6 @@ macro_rules! impl_signed_ops( impl_signed_ops!(u64, u64, 0); }; - (usize) => { - impl_signed_ops!(usize, usize, 0); - }; - (u32) => { impl_signed_ops!(u32, u32, 0); }; @@ -577,6 +659,20 @@ macro_rules! impl_signed_ops( } } + impl std::ops::Add> for $type { + type Output = crate::Signed<$type>; + fn add(self, other: crate::Signed<$type>) -> crate::Signed<$type> { + crate::Signed::Positive(self).checked_add(other).expect("Overflowing addition") + } + } + + impl std::ops::Sub> for $type { + type Output = crate::Signed<$type>; + fn sub(self, other: crate::Signed<$type>) -> crate::Signed<$type> { + crate::Signed::Positive(self).checked_sub(other).expect("Overflowing subtraction") + } + } + impl std::cmp::PartialOrd> for crate::Signed<$type> { fn partial_cmp(&self, other: &crate::Signed<$type>) -> Option { Some(self.cmp(other)) @@ -589,12 +685,24 @@ macro_rules! impl_signed_ops( } } + impl std::cmp::PartialEq> for $type { + fn eq(&self, other: &crate::Signed<$type>) -> bool { + crate::Signed::Positive(*self).eq(other) + } + } + impl std::cmp::PartialOrd<$type> for crate::Signed<$type> { fn partial_cmp(&self, other: &$type) -> Option { Some(self.cmp(&crate::Signed::Positive(*other))) } } + impl std::cmp::PartialOrd> for $type { + fn partial_cmp(&self, other: &crate::Signed<$type>) -> Option { + Some(crate::Signed::Positive(*self).cmp(other)) + } + } + impl std::cmp::Ord for crate::Signed<$type> { fn cmp(&self, other: &crate::Signed<$type>) -> std::cmp::Ordering { use crate::Signed::*; @@ -646,32 +754,111 @@ macro_rules! impl_signed_ops( Some(self.saturating_sub(rhs)) } } + + impl opt_ops::OptionCheckedAdd<$type> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_add( + self, + rhs: $type, + ) -> Result, opt_ops::Error> { + self.opt_checked_add(crate::Signed::Positive(rhs)) + } + } + + impl opt_ops::OptionSaturatingAdd<$type> for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_add(self, rhs: $type) -> Option { + self.opt_saturating_add(crate::Signed::Positive(rhs)) + } + } + + impl opt_ops::OptionCheckedSub<$type> for crate::Signed<$type> { + type Output = Self; + fn opt_checked_sub( + self, + rhs: $type, + ) -> Result, opt_ops::Error> { + self.opt_checked_sub(crate::Signed::Positive(rhs)) + } + } + + impl opt_ops::OptionSaturatingSub<$type> for crate::Signed<$type> { + type Output = Self; + fn opt_saturating_sub(self, rhs: $type) -> Option { + self.opt_saturating_sub(crate::Signed::Positive(rhs)) + } + } + + impl opt_ops::OptionCheckedAdd> for $type { + type Output = crate::Signed<$type>; + fn opt_checked_add( + self, + rhs: crate::Signed<$type>, + ) -> Result, opt_ops::Error> { + crate::Signed::Positive(self).opt_checked_add(rhs) + } + } + + impl opt_ops::OptionSaturatingAdd> for $type { + type Output = crate::Signed<$type>; + fn opt_saturating_add( + self, + rhs: crate::Signed<$type> + ) -> Option { + crate::Signed::Positive(self).opt_saturating_add(rhs) + } + } + + impl opt_ops::OptionCheckedSub> for $type { + type Output = crate::Signed<$type>; + fn opt_checked_sub( + self, + rhs: crate::Signed<$type>, + ) -> Result, opt_ops::Error> { + crate::Signed::Positive(self).opt_checked_sub(rhs) + } + } + + impl opt_ops::OptionSaturatingSub> for $type { + type Output = crate::Signed<$type>; + fn opt_saturating_sub( + self, + rhs: crate::Signed<$type> + ) -> Option { + crate::Signed::Positive(self).opt_saturating_sub(rhs) + } + } }; ); macro_rules! impl_signed_div_mul( (u64) => { impl_signed_div_mul!(u64, u64, i64, |val: u64| val); + impl_signed_extra_div_mul!(u64, i64); impl_signed_div_mul_trait!(u64, u64, i64, |val: u64| val); }; (usize) => { impl_signed_div_mul!(usize, usize, isize, |val: usize| val); + impl_signed_extra_div_mul!(usize, isize); // `MulDiv` not available for usize }; (u32) => { impl_signed_div_mul!(u32, u32, i32, |val: u32| val); + impl_signed_extra_div_mul!(u32, i32); impl_signed_div_mul_trait!(u32, u32, i32, |val: u32| val); }; ($new_type:ty, u64) => { impl_signed_div_mul!($new_type, u64, i64, |val: $new_type| *val); + impl_signed_extra_div_mul!($new_type, u64, i64); impl_signed_div_mul_trait!($new_type, u64, i64, |val: $new_type| *val); }; ($new_type:ty, u32) => { impl_signed_div_mul!($new_type, u32, i32, |val: $new_type| *val); + impl_signed_extra_div_mul!($new_type, u32, i32); impl_signed_div_mul_trait!($new_type, u32, i32, |val: $new_type| *val); }; @@ -972,6 +1159,124 @@ macro_rules! impl_signed_div_mul( }; ); +macro_rules! impl_signed_extra_div_mul( + ($type:ty, $signed:ty) => { + impl std::ops::Div for crate::Signed<$type> { + type Output = Self; + + fn div(self, rhs: Self) -> Self { + match rhs { + crate::Signed::Positive(rhs) => self.div(rhs), + crate::Signed::Negative(rhs) => std::ops::Neg::neg(self.div(rhs)), + } + } + } + + impl std::ops::Rem for crate::Signed<$type> { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + self.rem(rhs.abs()) + } + } + + impl opt_ops::OptionCheckedDiv for crate::Signed<$type> { + type Output = Self; + fn opt_checked_div(self, rhs: Self) -> Result, opt_ops::Error> { + match rhs { + crate::Signed::Positive(rhs) => self.opt_checked_div(rhs), + crate::Signed::Negative(rhs) => { + self.opt_checked_div(rhs) + .map(|res| res.map(std::ops::Neg::neg)) + } + } + } + } + + impl opt_ops::OptionCheckedRem for crate::Signed<$type> { + type Output = Self; + fn opt_checked_rem(self, rhs: Self) -> Result, opt_ops::Error> { + self.opt_checked_rem(rhs.abs()) + } + } + }; + ($new_type:ty, $inner_type:ty, $signed_innner_type:ty) => { + impl std::ops::Div for crate::Signed<$new_type> { + type Output = crate::Signed<$inner_type>; + + fn div(self, rhs: Self) -> Self::Output { + self.into_inner_signed().div(rhs.into_inner_signed()) + } + } + + impl std::ops::Rem for crate::Signed<$new_type> { + type Output = crate::Signed<$new_type>; + + fn rem(self, rhs: Self) -> Self::Output { + self.rem(rhs.abs().0) + } + } + + impl std::ops::Mul> for $inner_type { + type Output = crate::Signed<$new_type>; + + fn mul(self, rhs: crate::Signed<$new_type>) -> Self::Output { + rhs.mul(self) + } + } + + impl std::ops::Mul> for $signed_innner_type { + type Output = crate::Signed<$new_type>; + + fn mul(self, rhs: crate::Signed<$new_type>) -> Self::Output { + rhs.mul(self) + } + } + + impl opt_ops::OptionCheckedDiv for crate::Signed<$new_type> { + type Output = crate::Signed<$inner_type>; + fn opt_checked_div(self, rhs: Self) -> Result, opt_ops::Error> { + self.into_inner_signed().opt_checked_div(rhs.into_inner_signed()) + } + } + + impl opt_ops::OptionCheckedRem for crate::Signed<$new_type> { + type Output = crate::Signed<$inner_type>; + fn opt_checked_rem(self, rhs: Self) -> Result, opt_ops::Error> { + self.into_inner_signed().opt_checked_rem(rhs.abs().0) + } + } + + impl opt_ops::OptionCheckedMul> for $signed_innner_type { + type Output = crate::Signed<$new_type>; + fn opt_checked_mul(self, rhs: crate::Signed<$new_type>) -> Result, opt_ops::Error> { + rhs.opt_checked_mul(self) + } + } + + impl opt_ops::OptionSaturatingMul> for $signed_innner_type { + type Output = crate::Signed<$new_type>; + fn opt_saturating_mul(self, rhs: crate::Signed<$new_type>) -> Option { + rhs.opt_saturating_mul(self) + } + } + + impl opt_ops::OptionCheckedMul> for $inner_type { + type Output = crate::Signed<$new_type>; + fn opt_checked_mul(self, rhs: crate::Signed<$new_type>) -> Result, opt_ops::Error> { + rhs.opt_checked_mul(self) + } + } + + impl opt_ops::OptionSaturatingMul> for $inner_type { + type Output = crate::Signed<$new_type>; + fn opt_saturating_mul(self, rhs: crate::Signed<$new_type>) -> Option { + rhs.opt_saturating_mul(self) + } + } + }; +); + macro_rules! impl_signed_div_mul_trait( ($type:ty, $inner_type:ty, $signed_rhs:ty, $into_inner:expr) => { impl crate::Signed<$type> { diff --git a/gstreamer/src/format/signed.rs b/gstreamer/src/format/signed.rs index 026637186..1d15a2407 100644 --- a/gstreamer/src/format/signed.rs +++ b/gstreamer/src/format/signed.rs @@ -232,10 +232,6 @@ impl_unsigned_int_into_signed!(u64); impl_signed_ops!(u64); impl_signed_div_mul!(u64); -impl_unsigned_int_into_signed!(usize); -impl_signed_ops!(usize); -impl_signed_div_mul!(usize); - impl_unsigned_int_into_signed!(u32); impl_signed_ops!(u32); impl_signed_div_mul!(u32); diff --git a/tutorials/src/bin/playback-tutorial-4.rs b/tutorials/src/bin/playback-tutorial-4.rs index a9caa10c9..f11c85a5d 100644 --- a/tutorials/src/bin/playback-tutorial-4.rs +++ b/tutorials/src/bin/playback-tutorial-4.rs @@ -135,11 +135,11 @@ fn tutorial_main() -> Result<(), Error> { } else { Percent::ZERO } / Percent::MAX; - if start.is_zero() && stop.is_zero() { + if start == 0 && stop == 0 { continue; } - let start_ = *((start * GRAPH_LENGTH as u32) / (stop - start)); - let stop_ = *((stop * GRAPH_LENGTH as u32) / (stop - start)); + let start_ = (start * GRAPH_LENGTH as u32) / (stop - start); + let stop_ = (stop * GRAPH_LENGTH as u32) / (stop - start); for j in start_..stop_ { graph[j as usize] = b'-'; }