|
1 |
| -use core::{convert::TryInto, fmt}; |
| 1 | +use core::{convert::TryInto, fmt, ops}; |
2 | 2 |
|
3 | 3 | use crate::utils::{Init, ZeroInit};
|
4 | 4 |
|
@@ -168,6 +168,30 @@ impl Duration {
|
168 | 168 | None
|
169 | 169 | }
|
170 | 170 | }
|
| 171 | + |
| 172 | + /// Add the specified value to `self`, returning `None` if the result |
| 173 | + /// overflows. |
| 174 | + #[inline] |
| 175 | + pub const fn checked_add(self, other: Self) -> Option<Self> { |
| 176 | + // FIXME: `Option::map` is not `const fn` yet |
| 177 | + if let Some(x) = self.micros.checked_add(other.micros) { |
| 178 | + Some(Self::from_micros(x)) |
| 179 | + } else { |
| 180 | + None |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + /// Subtract the specified value from `self`, returning `None` if the result |
| 185 | + /// overflows. |
| 186 | + #[inline] |
| 187 | + pub const fn checked_sub(self, other: Self) -> Option<Self> { |
| 188 | + // FIXME: `Option::map` is not `const fn` yet |
| 189 | + if let Some(x) = self.micros.checked_sub(other.micros) { |
| 190 | + Some(Self::from_micros(x)) |
| 191 | + } else { |
| 192 | + None |
| 193 | + } |
| 194 | + } |
171 | 195 | }
|
172 | 196 |
|
173 | 197 | /// Error type returned when a checked duration type conversion fails.
|
@@ -217,6 +241,110 @@ impl fmt::Debug for Duration {
|
217 | 241 | }
|
218 | 242 | }
|
219 | 243 |
|
| 244 | +impl ops::Add for Duration { |
| 245 | + type Output = Self; |
| 246 | + |
| 247 | + /// Perform a checked addition, panicking on overflow. |
| 248 | + #[inline] |
| 249 | + fn add(self, rhs: Self) -> Self::Output { |
| 250 | + self.checked_add(rhs) |
| 251 | + .expect("overflow when adding durations") |
| 252 | + } |
| 253 | +} |
| 254 | + |
| 255 | +impl ops::AddAssign for Duration { |
| 256 | + /// Perform a checked addition, panicking on overflow. |
| 257 | + #[inline] |
| 258 | + fn add_assign(&mut self, rhs: Self) { |
| 259 | + *self = *self + rhs; |
| 260 | + } |
| 261 | +} |
| 262 | + |
| 263 | +impl ops::Sub for Duration { |
| 264 | + type Output = Self; |
| 265 | + |
| 266 | + /// Perform a checked subtraction, panicking on overflow. |
| 267 | + #[inline] |
| 268 | + fn sub(self, rhs: Self) -> Self::Output { |
| 269 | + self.checked_sub(rhs) |
| 270 | + .expect("overflow when subtracting durations") |
| 271 | + } |
| 272 | +} |
| 273 | + |
| 274 | +impl ops::SubAssign for Duration { |
| 275 | + /// Perform a checked subtraction, panicking on overflow. |
| 276 | + #[inline] |
| 277 | + fn sub_assign(&mut self, rhs: Self) { |
| 278 | + *self = *self - rhs; |
| 279 | + } |
| 280 | +} |
| 281 | + |
| 282 | +impl ops::Mul<i32> for Duration { |
| 283 | + type Output = Duration; |
| 284 | + |
| 285 | + /// Perform a checked multiplication, panicking on overflow. |
| 286 | + #[inline] |
| 287 | + fn mul(self, rhs: i32) -> Self::Output { |
| 288 | + self.checked_mul(rhs) |
| 289 | + .expect("overflow when multiplying duration by scalar") |
| 290 | + } |
| 291 | +} |
| 292 | + |
| 293 | +impl ops::Mul<Duration> for i32 { |
| 294 | + type Output = Duration; |
| 295 | + |
| 296 | + /// Perform a checked multiplication, panicking on overflow. |
| 297 | + #[inline] |
| 298 | + fn mul(self, rhs: Duration) -> Self::Output { |
| 299 | + rhs.checked_mul(self) |
| 300 | + .expect("overflow when multiplying duration by scalar") |
| 301 | + } |
| 302 | +} |
| 303 | + |
| 304 | +impl ops::MulAssign<i32> for Duration { |
| 305 | + /// Perform a checked multiplication, panicking on overflow. |
| 306 | + #[inline] |
| 307 | + fn mul_assign(&mut self, rhs: i32) { |
| 308 | + *self = *self * rhs; |
| 309 | + } |
| 310 | +} |
| 311 | + |
| 312 | +impl ops::Div<i32> for Duration { |
| 313 | + type Output = Duration; |
| 314 | + |
| 315 | + /// Perform a checked division, panicking on overflow or when `rhs` is zero. |
| 316 | + #[inline] |
| 317 | + fn div(self, rhs: i32) -> Self::Output { |
| 318 | + self.checked_div(rhs) |
| 319 | + .expect("divide by zero or overflow when dividing duration by scalar") |
| 320 | + } |
| 321 | +} |
| 322 | + |
| 323 | +impl ops::DivAssign<i32> for Duration { |
| 324 | + /// Perform a checked division, panicking on overflow or when `rhs` is zero. |
| 325 | + #[inline] |
| 326 | + fn div_assign(&mut self, rhs: i32) { |
| 327 | + *self = *self / rhs; |
| 328 | + } |
| 329 | +} |
| 330 | + |
| 331 | +impl core::iter::Sum for Duration { |
| 332 | + /// Perform a checked summation, panicking on overflow. |
| 333 | + fn sum<I: Iterator<Item = Duration>>(iter: I) -> Self { |
| 334 | + iter.fold(Duration::ZERO, |x, y| { |
| 335 | + x.checked_add(y) |
| 336 | + .expect("overflow in iter::sum over durations") |
| 337 | + }) |
| 338 | + } |
| 339 | +} |
| 340 | + |
| 341 | +impl<'a> core::iter::Sum<&'a Duration> for Duration { |
| 342 | + /// Perform a checked summation, panicking on overflow. |
| 343 | + fn sum<I: Iterator<Item = &'a Duration>>(iter: I) -> Self { |
| 344 | + iter.cloned().sum() |
| 345 | + } |
| 346 | +} |
| 347 | + |
220 | 348 | // TODO: Add more tests
|
221 | 349 | // TODO: Maybe add macros to construct a `Duration` with compile-time overflow
|
222 | 350 | // check
|
|
0 commit comments