From e402851ac4a84249bfb506edcc2b688f54099c27 Mon Sep 17 00:00:00 2001 From: Rinde van Lon Date: Mon, 1 Apr 2024 16:23:51 +0100 Subject: [PATCH 1/5] new TimeWindow API --- src/lib.rs | 298 ++++++++++++++++++++++++----------------------------- 1 file changed, 137 insertions(+), 161 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 350d989..41dadfb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -418,9 +418,7 @@ impl TimeWindow { /// /// # Examples /// ``` - /// # use tinytime::{Duration, TimeWindowError}; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; + /// # use tinytime::*; /// assert!(TimeWindow::new_checked(Time::hours(1), Time::hours(2)).is_ok()); /// assert_eq!( /// Err(TimeWindowError::StartAfterEnd), @@ -451,36 +449,32 @@ impl TimeWindow { TimeWindow::new(Time::seconds(a), Time::seconds(b)) } - /// Creates time window from start time and duration. - /// # Examples + /// Creates time window from start time and length. /// + /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; - /// let mut x = TimeWindow::from_duration(Time::seconds(1), Duration::seconds(2)); + /// # use tinytime::*; + /// let mut x = TimeWindow::from_length_start(Time::seconds(1), Duration::seconds(2)); /// assert_eq!(Time::seconds(1), x.start()); /// assert_eq!(Time::seconds(3), x.end()); /// ``` #[must_use] - pub fn from_duration(start: Time, duration: Duration) -> Self { - TimeWindow::new(start, start.add(duration)) + pub fn from_length_start(start: Time, length: Duration) -> Self { + TimeWindow::new(start, start.add(length)) } - /// Creates time window from duration and end time. - /// # Examples + /// Creates time window from length and end time. /// + /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; - /// let mut x = TimeWindow::from_end(Duration::seconds(2), Time::seconds(3)); + /// # use tinytime::*; + /// let mut x = TimeWindow::from_length_end(Duration::seconds(2), Time::seconds(3)); /// assert_eq!(Time::seconds(1), x.start()); /// assert_eq!(Time::seconds(3), x.end()); /// ``` #[must_use] - pub fn from_end(duration: Duration, end: Time) -> Self { - TimeWindow::new(end.sub(duration), end) + pub fn from_length_end(length: Duration, end: Time) -> Self { + TimeWindow::new(end.sub(length), end) } #[must_use] @@ -515,228 +509,210 @@ impl TimeWindow { } #[must_use] - pub fn duration(&self) -> Duration { + pub fn length(&self) -> Duration { self.end - self.start } - #[must_use] - pub fn with_new_start(self, start: Time) -> TimeWindow { - TimeWindow::new(start, self.end) + /// Changes the start of the `TimeWindow` to `new_start`. If `new_start` is + /// greater than or equal to `end` the start will be set equal to `end`. + pub fn set_start(&mut self, new_start: Time) { + self.start = new_start.min(self.end); } - #[must_use] - pub fn with_new_end(self, end: Time) -> TimeWindow { - TimeWindow::new(self.start, end) + /// Changes the end of the `TimeWindow` to `new_end`. If `new_end` is + /// smaller or equal to `start`, the `end` will be set to `start.` + pub fn set_end(&mut self, new_end: Time) { + self.end = new_end.max(self.start); } - /// Extends time window start to the given value. Is a No-Op when given - /// value isn't earlier than current time window start. - /// Returns by which duration the start was moved. - /// # Examples + /// Prepones time window start to the given value. /// + /// Is a no-op when the given value isn't earlier than current time window + /// start. Returns the duration of the preponement. + /// + /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; + /// # use tinytime::*; /// let mut x = TimeWindow::from_seconds(4, 5); - /// assert_eq!(Some(Duration::seconds(1)), x.extend_start(Time::seconds(3))); + /// assert_eq!( + /// Some(Duration::seconds(1)), + /// x.prepone_start_to(Time::seconds(3)) + /// ); /// assert_eq!(Time::seconds(3), x.start()); - /// assert_eq!(None, x.extend_start(Time::seconds(6))); + /// assert_eq!(None, x.prepone_start_to(Time::seconds(6))); /// assert_eq!(Time::seconds(3), x.start()); /// ``` - #[must_use] - pub fn extend_start(&mut self, new_start: Time) -> Option { + pub fn prepone_start_to(&mut self, new_start: Time) -> Option { (new_start < self.start).then(|| { let diff = self.start - new_start; - *self = self.with_new_start(new_start); + self.set_start(new_start); diff }) } - /// Extends time window end to the given value. Is a No-Op when given value - /// isn't greater than current time window end. - /// Returns by which duration the deadline was extended. - /// # Examples + /// Postpones time window end to the given value. + /// + /// Is a no-op when the given value isn't greater than current time window + /// end. Returns the duration of the postponement. /// + /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; + /// # use tinytime::*; /// let mut x = TimeWindow::from_seconds(1, 2); - /// assert_eq!(Some(Duration::seconds(1)), x.extend_end(Time::seconds(3))); + /// assert_eq!( + /// Some(Duration::seconds(1)), + /// x.postpone_end_to(Time::seconds(3)) + /// ); /// assert_eq!(Time::seconds(3), x.end()); - /// assert_eq!(None, x.extend_end(Time::EPOCH)); + /// assert_eq!(None, x.postpone_end_to(Time::EPOCH)); /// assert_eq!(Time::seconds(3), x.end()); /// ``` - #[must_use] - pub fn extend_end(&mut self, new_end: Time) -> Option { + pub fn postpone_end_to(&mut self, new_end: Time) -> Option { (new_end > self.end).then(|| { let diff = new_end - self.end; - *self = self.with_new_end(new_end); + self.set_end(new_end); diff }) } - /// Extends time window start by the given duration. + /// Prepones time window start by the given duration. /// /// # Examples - /// /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; - /// let x = TimeWindow::from_seconds(8, 9); - /// let y = x.extend_start_by(Duration::seconds(3)); - /// assert_eq!(Time::seconds(5), y.start()); + /// # use tinytime::*; + /// let mut tw = TimeWindow::from_seconds(8, 9); + /// tw.prepone_start_by(Duration::seconds(3)); + /// assert_eq!(Time::seconds(5), tw.start()); /// ``` - #[must_use] - pub fn extend_start_by(&self, duration: Duration) -> TimeWindow { - TimeWindow { - start: self.start - duration, - end: self.end, - } + pub fn prepone_start_by(&mut self, duration: Duration) { + self.start -= duration; } - /// Extends time window end by the given duration. + /// Postpones time window end by the given duration. /// /// # Examples - /// /// ``` - /// # use tinytime::Duration; - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; - /// let x = TimeWindow::from_seconds(1, 2); - /// let y = x.extend_end_by(Duration::seconds(3)); - /// assert_eq!(Time::seconds(5), y.end()); + /// # use tinytime::*; + /// let mut tw = TimeWindow::from_seconds(1, 2); + /// tw.postpone_end_by(Duration::seconds(3)); + /// assert_eq!(Time::seconds(5), tw.end()); /// ``` - #[must_use] - pub fn extend_end_by(&self, duration: Duration) -> TimeWindow { - TimeWindow { - start: self.start, - end: self.end + duration, - } + pub fn postpone_end_by(&mut self, duration: Duration) { + self.end += duration; } - /// Postpones the time window start to the given value. Is a No-Op when - /// given value isn't greater than current time window start. Will never - /// postpone the start past the end of the time window. - /// # Examples + /// Postpones the time window start to the given value. + /// + /// Is a no-op when the given value isn't greater than current time window + /// start. Will never postpone the start past the end of the time + /// window. /// + /// # Examples /// ``` - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; + /// # use tinytime::*; /// let mut x = TimeWindow::from_seconds(1, 3); - /// x.shrink_towards_end(Time::EPOCH); + /// x.postpone_start_to(Time::EPOCH); /// assert_eq!(Time::seconds(1), x.start()); - /// x.shrink_towards_end(Time::seconds(2)); + /// x.postpone_start_to(Time::seconds(2)); /// assert_eq!(Time::seconds(2), x.start()); - /// x.shrink_towards_end(Time::seconds(4)); + /// x.postpone_start_to(Time::seconds(4)); /// assert_eq!(Time::seconds(3), x.start()); /// ``` - pub fn shrink_towards_end(&mut self, new_start: Time) { + pub fn postpone_start_to(&mut self, new_start: Time) { if new_start > self.start { if new_start > self.end { - *self = self.with_new_start(self.end); + self.set_start(self.end); } else { - *self = self.with_new_start(new_start); + self.set_start(new_start); } } } - /// Prepones the time window end to the given value. May be a No-Op. - /// Will never prepone the end more than to the start of the time window. - /// # Examples + /// Prepones the time window end to the given value. /// + /// May be a no-op. Will never prepone the end more than to the start of the + /// time window. + /// + /// # Examples /// ``` - /// # use tinytime::Time; - /// # use tinytime::TimeWindow; + /// # use tinytime::*; /// let mut x = TimeWindow::from_seconds(1, 3); - /// x.shrink_towards_start(Time::seconds(4)); + /// x.prepone_end_to(Time::seconds(4)); /// assert_eq!(Time::seconds(3), x.end()); - /// x.shrink_towards_start(Time::seconds(2)); + /// x.prepone_end_to(Time::seconds(2)); /// assert_eq!(Time::seconds(2), x.end()); - /// x.shrink_towards_start(Time::EPOCH); + /// x.prepone_end_to(Time::EPOCH); /// assert_eq!(Time::seconds(1), x.end()); /// ``` - pub fn shrink_towards_start(&mut self, new_end: Time) { + pub fn prepone_end_to(&mut self, new_end: Time) { if new_end < self.end { if new_end < self.start { - *self = self.with_new_end(self.start); + self.set_end(self.start); } else { - *self = self.with_new_end(new_end); + self.set_end(new_end); } } } - /// Postpones the time window start so that the new duration matches the - /// given value. Is a No-Op if the new duration is smaller than the - /// current one. Negative durations set the result time window size to - /// zero. + /// Postpones the time window start so that the new length matches the + /// given value. + /// + /// Is a no-op if the new length is smaller than the current one. Negative + /// length will set the result time window size to zero. /// /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::TimeWindow; - /// let x = TimeWindow::from_seconds(1, 3); - /// assert_eq!( - /// TimeWindow::from_seconds(3, 3), - /// x.shrink_towards_end_to(Duration::seconds(-1)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(3, 3), - /// x.shrink_towards_end_to(Duration::seconds(0)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(2, 3), - /// x.shrink_towards_end_to(Duration::seconds(1)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(1, 3), - /// x.shrink_towards_end_to(Duration::seconds(5)) - /// ); + /// # use tinytime::*; + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.postpone_start_shrink_to(Duration::seconds(-1)); + /// assert_eq!(TimeWindow::from_seconds(3, 3), tw); + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.postpone_start_shrink_to(Duration::seconds(0)); + /// assert_eq!(TimeWindow::from_seconds(3, 3), tw); + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.postpone_start_shrink_to(Duration::seconds(1)); + /// assert_eq!(TimeWindow::from_seconds(2, 3), tw); + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.postpone_start_shrink_to(Duration::seconds(5)); + /// assert_eq!(TimeWindow::from_seconds(1, 3), tw); /// ``` - #[must_use] - pub fn shrink_towards_end_to(self, new_duration: Duration) -> TimeWindow { - let duration = new_duration - .min(self.duration()) // Resize only if new duration is smaller than the current one - .max(Duration::ZERO); // Make sure the new duration is non-negative - - TimeWindow::from_end(duration, self.end) + pub fn postpone_start_shrink_to(&mut self, new_length: Duration) { + let length = new_length + .min(self.length()) // Resize only if new length is smaller than the current one + .max(Duration::ZERO); // Make sure the new length is non-negative + self.start = self.end - length; } - /// Prepones the time window end so that the new duration matches the given - /// value. Is a No-Op if the new duration is smaller than the current - /// one. Negative durations set the result time window size to zero. + /// Prepones the time window end so that the new length matches the given + /// value. + /// + /// Is a no-op if the new length is smaller than the current one. Negative + /// lengths set the time window size to zero. /// /// # Examples /// ``` - /// # use tinytime::Duration; - /// # use tinytime::TimeWindow; - /// let x = TimeWindow::from_seconds(1, 3); - /// assert_eq!( - /// TimeWindow::from_seconds(1, 1), - /// x.shrink_towards_start_to(Duration::seconds(-1)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(1, 1), - /// x.shrink_towards_start_to(Duration::seconds(0)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(1, 2), - /// x.shrink_towards_start_to(Duration::seconds(1)) - /// ); - /// assert_eq!( - /// TimeWindow::from_seconds(1, 3), - /// x.shrink_towards_start_to(Duration::seconds(5)) - /// ); + /// # use tinytime::*; + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.prepone_end_shrink_to(Duration::seconds(-1)); + /// assert_eq!(TimeWindow::from_seconds(1, 1), tw); + /// + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.prepone_end_shrink_to(Duration::seconds(0)); + /// assert_eq!(TimeWindow::from_seconds(1, 1), tw); + /// + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.prepone_end_shrink_to(Duration::seconds(1)); + /// assert_eq!(TimeWindow::from_seconds(1, 2), tw); + /// + /// let mut tw = TimeWindow::from_seconds(1, 3); + /// tw.prepone_end_shrink_to(Duration::seconds(5)); + /// assert_eq!(TimeWindow::from_seconds(1, 3), tw); /// ``` - #[must_use] - pub fn shrink_towards_start_to(self, new_duration: Duration) -> TimeWindow { - let duration = new_duration - .min(self.duration()) // Resize only if new duration is smaller than the current one - .max(Duration::ZERO); // Make sure the new duration is non-negative - - TimeWindow::from_duration(self.start, duration) + pub fn prepone_end_shrink_to(&mut self, new_length: Duration) { + let length = new_length + .min(self.length()) // Resize only if new length is smaller than the current one + .max(Duration::ZERO); // Make sure the new length is non-negative + self.end = self.start + length; } /// Returns true if this time window contains the given time. @@ -836,7 +812,7 @@ impl TimeWindow { } /// Shifts this time window by `duration` into the future. Affects both - /// `start` and `end` equally. + /// `start` and `end` equally, leaving the length untouched. /// /// # Examples /// From 20b4f25d058ac92f4c9f2e0226111a5b56a71ca6 Mon Sep 17 00:00:00 2001 From: Rinde van Lon Date: Tue, 2 Apr 2024 15:59:53 +0100 Subject: [PATCH 2/5] use functional style --- src/lib.rs | 274 +++++++++++++++++++++++++++++------------------------ 1 file changed, 149 insertions(+), 125 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 41dadfb..53a6746 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -513,206 +513,230 @@ impl TimeWindow { self.end - self.start } - /// Changes the start of the `TimeWindow` to `new_start`. If `new_start` is - /// greater than or equal to `end` the start will be set equal to `end`. - pub fn set_start(&mut self, new_start: Time) { - self.start = new_start.min(self.end); + /// Creates a new `TimeWindow` with `start` set to `new_start`. If + /// `new_start` is greater than or equal to `end` the start will be set + /// equal to `end`. + #[must_use] + pub fn with_start(&self, new_start: Time) -> Self { + Self::new(new_start.min(self.end), self.end) } - /// Changes the end of the `TimeWindow` to `new_end`. If `new_end` is + /// Creates a new `TimeWindow` with `end` set to `new_end`. If `new_end` is /// smaller or equal to `start`, the `end` will be set to `start.` - pub fn set_end(&mut self, new_end: Time) { - self.end = new_end.max(self.start); + #[must_use] + pub fn with_end(&self, new_end: Time) -> Self { + Self::new(self.start, new_end.max(self.start)) } - /// Prepones time window start to the given value. - /// - /// Is a no-op when the given value isn't earlier than current time window - /// start. Returns the duration of the preponement. + /// Creates a new `TimeWindow` with the `start` preponed to the given value. + /// If `new_start` isn't earlier than the current time window start, a copy + /// of `self` is returned. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_seconds(4, 5); + /// let x = TimeWindow::from_seconds(4, 5); /// assert_eq!( - /// Some(Duration::seconds(1)), + /// TimeWindow::from_seconds(3, 5), /// x.prepone_start_to(Time::seconds(3)) /// ); - /// assert_eq!(Time::seconds(3), x.start()); - /// assert_eq!(None, x.prepone_start_to(Time::seconds(6))); - /// assert_eq!(Time::seconds(3), x.start()); + /// assert_eq!( + /// TimeWindow::from_seconds(4, 5), + /// x.prepone_start_to(Time::seconds(6)) + /// ); /// ``` - pub fn prepone_start_to(&mut self, new_start: Time) -> Option { - (new_start < self.start).then(|| { - let diff = self.start - new_start; - self.set_start(new_start); - diff - }) + #[must_use] + pub fn prepone_start_to(&self, new_start: Time) -> Self { + (new_start < self.start) + .then(|| self.with_start(new_start)) + .unwrap_or(*self) } - /// Postpones time window end to the given value. - /// - /// Is a no-op when the given value isn't greater than current time window - /// end. Returns the duration of the postponement. + /// Creates a new `TimeWindow` with the `end` postponed to the given value. + /// If `new_end` isn't later than the current time window end, a copy of + /// `self` is returned. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_seconds(1, 2); + /// let x = TimeWindow::from_seconds(1, 2); /// assert_eq!( - /// Some(Duration::seconds(1)), + /// TimeWindow::from_seconds(1, 3), /// x.postpone_end_to(Time::seconds(3)) /// ); - /// assert_eq!(Time::seconds(3), x.end()); - /// assert_eq!(None, x.postpone_end_to(Time::EPOCH)); - /// assert_eq!(Time::seconds(3), x.end()); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 2), + /// x.postpone_end_to(Time::EPOCH) + /// ); /// ``` - pub fn postpone_end_to(&mut self, new_end: Time) -> Option { - (new_end > self.end).then(|| { - let diff = new_end - self.end; - self.set_end(new_end); - diff - }) + #[must_use] + pub fn postpone_end_to(&self, new_end: Time) -> Self { + (new_end > self.end) + .then(|| self.with_end(new_end)) + .unwrap_or(*self) } - /// Prepones time window start by the given duration. + /// Creates a new `TimeWindow` with the `start` preponed by the given + /// duration. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut tw = TimeWindow::from_seconds(8, 9); - /// tw.prepone_start_by(Duration::seconds(3)); - /// assert_eq!(Time::seconds(5), tw.start()); + /// let tw = TimeWindow::from_seconds(8, 9); + /// assert_eq!( + /// TimeWindow::from_seconds(5, 9), + /// tw.prepone_start_by(Duration::seconds(3)) + /// ); /// ``` - pub fn prepone_start_by(&mut self, duration: Duration) { - self.start -= duration; + #[must_use] + pub fn prepone_start_by(&self, duration: Duration) -> Self { + self.with_start(self.start - duration) } - /// Postpones time window end by the given duration. + /// Creates a new `TimeWindow` with the `end` postponed by the given + /// duration. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut tw = TimeWindow::from_seconds(1, 2); - /// tw.postpone_end_by(Duration::seconds(3)); - /// assert_eq!(Time::seconds(5), tw.end()); + /// let tw = TimeWindow::from_seconds(1, 2); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 5), + /// tw.postpone_end_by(Duration::seconds(3)) + /// ); /// ``` - pub fn postpone_end_by(&mut self, duration: Duration) { - self.end += duration; + #[must_use] + pub fn postpone_end_by(&self, duration: Duration) -> Self { + self.with_end(self.end + duration) } - /// Postpones the time window start to the given value. + /// Creates a new `TimeWindow` with the `start` postponed to the given + /// value. /// - /// Is a no-op when the given value isn't greater than current time window - /// start. Will never postpone the start past the end of the time - /// window. + /// Returns a copy of `self` when the given value isn't later than the + /// current time window start. Will never postpone the start past the + /// end of the time window. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_seconds(1, 3); - /// x.postpone_start_to(Time::EPOCH); - /// assert_eq!(Time::seconds(1), x.start()); - /// x.postpone_start_to(Time::seconds(2)); - /// assert_eq!(Time::seconds(2), x.start()); - /// x.postpone_start_to(Time::seconds(4)); - /// assert_eq!(Time::seconds(3), x.start()); + /// let tw = TimeWindow::from_seconds(1, 3); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// tw.postpone_start_to(Time::EPOCH) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(2, 3), + /// tw.postpone_start_to(Time::seconds(2)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(3, 3), + /// tw.postpone_start_to(Time::seconds(3)) + /// ); /// ``` - pub fn postpone_start_to(&mut self, new_start: Time) { - if new_start > self.start { - if new_start > self.end { - self.set_start(self.end); - } else { - self.set_start(new_start); - } - } + #[must_use] + pub fn postpone_start_to(&self, new_start: Time) -> Self { + (new_start > self.start) + .then(|| self.with_start(new_start)) + .unwrap_or(*self) } - /// Prepones the time window end to the given value. + /// Creates a new `TimeWindow` with the `end` preponed to the given value. /// - /// May be a no-op. Will never prepone the end more than to the start of the - /// time window. + /// Returns a copy of `self` when the given value isn't earlier than the + /// current time window end. Will never prepone the end more than to the + /// start of the time window. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_seconds(1, 3); - /// x.prepone_end_to(Time::seconds(4)); - /// assert_eq!(Time::seconds(3), x.end()); - /// x.prepone_end_to(Time::seconds(2)); - /// assert_eq!(Time::seconds(2), x.end()); - /// x.prepone_end_to(Time::EPOCH); - /// assert_eq!(Time::seconds(1), x.end()); + /// let tw = TimeWindow::from_seconds(1, 3); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// tw.prepone_end_to(Time::seconds(4)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 2), + /// tw.prepone_end_to(Time::seconds(2)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 1), + /// tw.prepone_end_to(Time::EPOCH) + /// ); /// ``` - pub fn prepone_end_to(&mut self, new_end: Time) { - if new_end < self.end { - if new_end < self.start { - self.set_end(self.start); - } else { - self.set_end(new_end); - } - } + #[must_use] + pub fn prepone_end_to(&self, new_end: Time) -> Self { + (new_end < self.end) + .then(|| self.with_end(new_end)) + .unwrap_or(*self) } - /// Postpones the time window start so that the new length matches the - /// given value. + /// Creates a new `TimeWindow` with the `start` postponed so that the new + /// time window length matches the given value. /// - /// Is a no-op if the new length is smaller than the current one. Negative - /// length will set the result time window size to zero. + /// Returns a copy of `self` if the new length is smaller than the current + /// one. Negative length will set the resulting time window length to zero. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.postpone_start_shrink_to(Duration::seconds(-1)); - /// assert_eq!(TimeWindow::from_seconds(3, 3), tw); - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.postpone_start_shrink_to(Duration::seconds(0)); - /// assert_eq!(TimeWindow::from_seconds(3, 3), tw); - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.postpone_start_shrink_to(Duration::seconds(1)); - /// assert_eq!(TimeWindow::from_seconds(2, 3), tw); - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.postpone_start_shrink_to(Duration::seconds(5)); - /// assert_eq!(TimeWindow::from_seconds(1, 3), tw); + /// let tw = TimeWindow::from_seconds(1, 3); + /// assert_eq!( + /// TimeWindow::from_seconds(3, 3), + /// tw.postpone_start_shrink_to(Duration::seconds(-1)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(3, 3), + /// tw.postpone_start_shrink_to(Duration::seconds(0)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(2, 3), + /// tw.postpone_start_shrink_to(Duration::seconds(1)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// tw.postpone_start_shrink_to(Duration::seconds(5)) + /// ); /// ``` - pub fn postpone_start_shrink_to(&mut self, new_length: Duration) { + pub fn postpone_start_shrink_to(&self, new_length: Duration) -> Self { let length = new_length .min(self.length()) // Resize only if new length is smaller than the current one .max(Duration::ZERO); // Make sure the new length is non-negative - self.start = self.end - length; + self.with_start(self.end - length) } - /// Prepones the time window end so that the new length matches the given - /// value. + /// Creates a new `TimeWindow` with the `end` preponed so that the new time + /// window length matches the given value. /// - /// Is a no-op if the new length is smaller than the current one. Negative - /// lengths set the time window size to zero. + /// Returns a copy of `self` if the new length is smaller than the current + /// one. Negative length will set the resulting time window length to zero. /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.prepone_end_shrink_to(Duration::seconds(-1)); - /// assert_eq!(TimeWindow::from_seconds(1, 1), tw); - /// - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.prepone_end_shrink_to(Duration::seconds(0)); - /// assert_eq!(TimeWindow::from_seconds(1, 1), tw); - /// - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.prepone_end_shrink_to(Duration::seconds(1)); - /// assert_eq!(TimeWindow::from_seconds(1, 2), tw); - /// - /// let mut tw = TimeWindow::from_seconds(1, 3); - /// tw.prepone_end_shrink_to(Duration::seconds(5)); - /// assert_eq!(TimeWindow::from_seconds(1, 3), tw); + /// let tw = TimeWindow::from_seconds(1, 3); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 1), + /// tw.prepone_end_shrink_to(Duration::seconds(-1)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 1), + /// tw.prepone_end_shrink_to(Duration::seconds(0)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 2), + /// tw.prepone_end_shrink_to(Duration::seconds(1)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// tw.prepone_end_shrink_to(Duration::seconds(5)) + /// ); /// ``` - pub fn prepone_end_shrink_to(&mut self, new_length: Duration) { + pub fn prepone_end_shrink_to(&self, new_length: Duration) -> Self { let length = new_length .min(self.length()) // Resize only if new length is smaller than the current one .max(Duration::ZERO); // Make sure the new length is non-negative - self.end = self.start + length; + self.with_end(self.start + length) } /// Returns true if this time window contains the given time. From d63031d73e909acd072db950137e1327f7dd2a81 Mon Sep 17 00:00:00 2001 From: Rinde van Lon Date: Wed, 3 Apr 2024 15:04:50 +0100 Subject: [PATCH 3/5] improve names, simplify code --- src/lib.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 53a6746..4718ab0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -454,12 +454,12 @@ impl TimeWindow { /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_length_start(Time::seconds(1), Duration::seconds(2)); + /// let mut x = TimeWindow::from_length_starting_at(Time::seconds(1), Duration::seconds(2)); /// assert_eq!(Time::seconds(1), x.start()); /// assert_eq!(Time::seconds(3), x.end()); /// ``` #[must_use] - pub fn from_length_start(start: Time, length: Duration) -> Self { + pub fn from_length_starting_at(start: Time, length: Duration) -> Self { TimeWindow::new(start, start.add(length)) } @@ -468,12 +468,12 @@ impl TimeWindow { /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_length_end(Duration::seconds(2), Time::seconds(3)); + /// let mut x = TimeWindow::from_length_ending_at(Duration::seconds(2), Time::seconds(3)); /// assert_eq!(Time::seconds(1), x.start()); /// assert_eq!(Time::seconds(3), x.end()); /// ``` #[must_use] - pub fn from_length_end(length: Duration, end: Time) -> Self { + pub fn from_length_ending_at(length: Duration, end: Time) -> Self { TimeWindow::new(end.sub(length), end) } @@ -547,9 +547,7 @@ impl TimeWindow { /// ``` #[must_use] pub fn prepone_start_to(&self, new_start: Time) -> Self { - (new_start < self.start) - .then(|| self.with_start(new_start)) - .unwrap_or(*self) + self.with_start(self.start.min(new_start)) } /// Creates a new `TimeWindow` with the `end` postponed to the given value. @@ -571,9 +569,7 @@ impl TimeWindow { /// ``` #[must_use] pub fn postpone_end_to(&self, new_end: Time) -> Self { - (new_end > self.end) - .then(|| self.with_end(new_end)) - .unwrap_or(*self) + self.with_end(self.end.max(new_end)) } /// Creates a new `TimeWindow` with the `start` preponed by the given @@ -636,9 +632,7 @@ impl TimeWindow { /// ``` #[must_use] pub fn postpone_start_to(&self, new_start: Time) -> Self { - (new_start > self.start) - .then(|| self.with_start(new_start)) - .unwrap_or(*self) + self.with_start(self.start.max(new_start)) } /// Creates a new `TimeWindow` with the `end` preponed to the given value. @@ -666,9 +660,7 @@ impl TimeWindow { /// ``` #[must_use] pub fn prepone_end_to(&self, new_end: Time) -> Self { - (new_end < self.end) - .then(|| self.with_end(new_end)) - .unwrap_or(*self) + self.with_end(self.end.min(new_end)) } /// Creates a new `TimeWindow` with the `start` postponed so that the new @@ -698,6 +690,7 @@ impl TimeWindow { /// tw.postpone_start_shrink_to(Duration::seconds(5)) /// ); /// ``` + #[must_use] pub fn postpone_start_shrink_to(&self, new_length: Duration) -> Self { let length = new_length .min(self.length()) // Resize only if new length is smaller than the current one @@ -732,6 +725,7 @@ impl TimeWindow { /// tw.prepone_end_shrink_to(Duration::seconds(5)) /// ); /// ``` + #[must_use] pub fn prepone_end_shrink_to(&self, new_length: Duration) -> Self { let length = new_length .min(self.length()) // Resize only if new length is smaller than the current one From 60533a83137a20d0f464f76cceb58f18fa5096a4 Mon Sep 17 00:00:00 2001 From: Rinde van Lon Date: Wed, 3 Apr 2024 15:07:34 +0100 Subject: [PATCH 4/5] make arg order consistent --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4718ab0..abdf37a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -454,12 +454,12 @@ impl TimeWindow { /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_length_starting_at(Time::seconds(1), Duration::seconds(2)); + /// let mut x = TimeWindow::from_length_starting_at(Duration::seconds(2), Time::seconds(1)); /// assert_eq!(Time::seconds(1), x.start()); /// assert_eq!(Time::seconds(3), x.end()); /// ``` #[must_use] - pub fn from_length_starting_at(start: Time, length: Duration) -> Self { + pub fn from_length_starting_at(length: Duration, start: Time) -> Self { TimeWindow::new(start, start.add(length)) } From 5e55372ecb43a71f18f7411e179b428d9494c8c0 Mon Sep 17 00:00:00 2001 From: Rinde van Lon Date: Thu, 4 Apr 2024 10:28:34 +0100 Subject: [PATCH 5/5] improve negative length and duration handling --- src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index abdf37a..d40873e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -451,30 +451,44 @@ impl TimeWindow { /// Creates time window from start time and length. /// + /// Negative lengths are treated as [`Duration::ZERO`]. + /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_length_starting_at(Duration::seconds(2), Time::seconds(1)); - /// assert_eq!(Time::seconds(1), x.start()); - /// assert_eq!(Time::seconds(3), x.end()); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// TimeWindow::from_length_starting_at(Duration::seconds(2), Time::seconds(1)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 1), + /// TimeWindow::from_length_starting_at(Duration::seconds(-2), Time::seconds(1)) + /// ); /// ``` #[must_use] pub fn from_length_starting_at(length: Duration, start: Time) -> Self { - TimeWindow::new(start, start.add(length)) + TimeWindow::new(start, start.add(length.max(Duration::ZERO))) } /// Creates time window from length and end time. /// + /// Negative lengths are treated as [`Duration::ZERO`]. + /// /// # Examples /// ``` /// # use tinytime::*; - /// let mut x = TimeWindow::from_length_ending_at(Duration::seconds(2), Time::seconds(3)); - /// assert_eq!(Time::seconds(1), x.start()); - /// assert_eq!(Time::seconds(3), x.end()); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 3), + /// TimeWindow::from_length_ending_at(Duration::seconds(2), Time::seconds(3)) + /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(3, 3), + /// TimeWindow::from_length_ending_at(Duration::seconds(-2), Time::seconds(3)) + /// ); /// ``` #[must_use] pub fn from_length_ending_at(length: Duration, end: Time) -> Self { - TimeWindow::new(end.sub(length), end) + TimeWindow::new(end.sub(length.max(Duration::ZERO)), end) } #[must_use] @@ -575,6 +589,8 @@ impl TimeWindow { /// Creates a new `TimeWindow` with the `start` preponed by the given /// duration. /// + /// Negative durations are treated as [`Duration::ZERO`]. + /// /// # Examples /// ``` /// # use tinytime::*; @@ -583,15 +599,21 @@ impl TimeWindow { /// TimeWindow::from_seconds(5, 9), /// tw.prepone_start_by(Duration::seconds(3)) /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(8, 9), + /// tw.prepone_start_by(Duration::seconds(-3)) + /// ); /// ``` #[must_use] pub fn prepone_start_by(&self, duration: Duration) -> Self { - self.with_start(self.start - duration) + self.with_start(self.start - duration.max(Duration::ZERO)) } /// Creates a new `TimeWindow` with the `end` postponed by the given /// duration. /// + /// Negative durations are treated as [`Duration::ZERO`]. + /// /// # Examples /// ``` /// # use tinytime::*; @@ -600,10 +622,14 @@ impl TimeWindow { /// TimeWindow::from_seconds(1, 5), /// tw.postpone_end_by(Duration::seconds(3)) /// ); + /// assert_eq!( + /// TimeWindow::from_seconds(1, 2), + /// tw.postpone_end_by(Duration::seconds(-3)) + /// ); /// ``` #[must_use] pub fn postpone_end_by(&self, duration: Duration) -> Self { - self.with_end(self.end + duration) + self.with_end(self.end + duration.max(Duration::ZERO)) } /// Creates a new `TimeWindow` with the `start` postponed to the given