diff --git a/gstreamer-app/src/app_sink.rs b/gstreamer-app/src/app_sink.rs index 3f7134e5e..bb10989ff 100644 --- a/gstreamer-app/src/app_sink.rs +++ b/gstreamer-app/src/app_sink.rs @@ -422,7 +422,7 @@ impl Stream for AppSinkStream { }; app_sink - .try_pull_sample(gst::ClockTime::from_mseconds(0)) + .try_pull_sample(gst::ClockTime::zero()) .map(|sample| Poll::Ready(Some(sample))) .unwrap_or_else(|| { if app_sink.is_eos() { diff --git a/gstreamer/src/clock_time.rs b/gstreamer/src/clock_time.rs index 1aa55d56f..e9fe463a8 100644 --- a/gstreamer/src/clock_time.rs +++ b/gstreamer/src/clock_time.rs @@ -64,11 +64,44 @@ impl ClockTime { nseconds * ::NSECOND } + pub fn zero() -> ClockTime { + ClockTime(Some(0)) + } + + // FIXME `matches!` was introduced in rustc 1.42.0, current MSRV is 1.41.0 + #[allow(clippy::match_like_matches_macro)] + pub fn is_zero(&self) -> bool { + match self.0 { + Some(0) => true, + _ => false, + } + } + pub fn none() -> ClockTime { ClockTime(None) } } +impl ClockTime { + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub fn saturating_add(self, rhs: ClockTime) -> Option { + match (self.0, rhs.0) { + (Some(this), Some(rhs)) => Some(ClockTime(Some(this.saturating_add(rhs)))), + _ => None, + } + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub fn saturating_sub(self, rhs: ClockTime) -> Option { + match (self.0, rhs.0) { + (Some(this), Some(rhs)) => Some(ClockTime(Some(this.saturating_sub(rhs)))), + _ => None, + } + } +} + impl fmt::Display for ClockTime { #[allow(clippy::many_single_char_names)] fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -187,3 +220,46 @@ impl convert::TryFrom for Duration { .ok_or_else(|| glib_bool_error!("Can't convert ClockTime::NONE to Duration")) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[allow(clippy::eq_op)] + fn ops() { + let ct_10 = ClockTime::from_mseconds(10); + let ct_20 = ClockTime::from_mseconds(20); + let ct_30 = ClockTime::from_mseconds(30); + + let ct_none = ClockTime::none(); + + assert_eq!(ct_10 + ct_20, ct_30); + assert_eq!(ct_10 + ct_none, ct_none); + assert_eq!(ct_none + ct_10, ct_none); + assert_eq!(ct_none + ct_none, ct_none); + + assert_eq!(ct_30 - ct_20, ct_10); + assert_eq!(ct_30 - ct_30, ClockTime::zero()); + assert_eq!(ct_30 - ct_none, ct_none); + assert_eq!(ct_none - ct_30, ct_none); + assert_eq!(ct_none - ct_none, ct_none); + } + + #[test] + fn saturating_ops() { + let ct_1 = ClockTime::from_nseconds(1); + let ct_2 = ClockTime::from_nseconds(2); + + let ct_max = ClockTime::from_nseconds(std::u64::MAX); + let ct_none = ClockTime::none(); + + assert_eq!(ct_max.saturating_add(ct_1), Some(ct_max)); + assert!(ct_max.saturating_add(ct_none).is_none()); + assert!(ct_none.saturating_add(ct_max).is_none()); + + assert!(ct_1.saturating_sub(ct_2).unwrap().is_zero()); + assert!(ct_1.saturating_sub(ct_none).is_none()); + assert!(ct_none.saturating_sub(ct_1).is_none()); + } +}