1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{ |
4 | fmt, |
5 | io::{self, prelude::*}, |
6 | time::Duration, |
7 | }; |
8 | |
9 | use glib::{translate::*, StaticType}; |
10 | |
11 | use super::{ |
12 | Format, FormattedValue, FormattedValueError, FormattedValueFullRange, FormattedValueIntrinsic, |
13 | FormattedValueNoneBuilder, GenericFormattedValue, Signed, SpecificFormattedValue, |
14 | SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic, |
15 | }; |
16 | |
17 | const TRY_FROM_FLOAT_SECS_ERROR_MSG: &str = |
18 | "can not convert float seconds to ClockTime: value is either negative, too big or NaN" ; |
19 | |
20 | #[derive (Debug, Clone, PartialEq, Eq)] |
21 | pub struct TryFromFloatSecsError; |
22 | |
23 | impl fmt::Display for TryFromFloatSecsError { |
24 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
25 | f.write_str(TRY_FROM_FLOAT_SECS_ERROR_MSG) |
26 | } |
27 | } |
28 | |
29 | impl std::error::Error for TryFromFloatSecsError {} |
30 | |
31 | #[derive (PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] |
32 | pub struct ClockTime(u64); |
33 | |
34 | impl ClockTime { |
35 | #[doc (alias = "GST_SECOND" )] |
36 | pub const SECOND: ClockTime = ClockTime(1_000_000_000); |
37 | #[doc (alias = "GST_MSECOND" )] |
38 | pub const MSECOND: ClockTime = ClockTime(1_000_000); |
39 | #[doc (alias = "GST_USECOND" )] |
40 | pub const USECOND: ClockTime = ClockTime(1_000); |
41 | #[doc (alias = "GST_NSECOND" )] |
42 | pub const NSECOND: ClockTime = ClockTime(1); |
43 | // checker-ignore-item |
44 | pub const MAX: ClockTime = ClockTime(ffi::GST_CLOCK_TIME_NONE - 1); |
45 | |
46 | #[inline ] |
47 | pub const fn hours(self) -> u64 { |
48 | self.0 / Self::SECOND.0 / 60 / 60 |
49 | } |
50 | |
51 | #[inline ] |
52 | pub const fn minutes(self) -> u64 { |
53 | self.0 / Self::SECOND.0 / 60 |
54 | } |
55 | |
56 | #[inline ] |
57 | pub const fn seconds(self) -> u64 { |
58 | self.0 / Self::SECOND.0 |
59 | } |
60 | |
61 | #[inline ] |
62 | pub fn seconds_f32(self) -> f32 { |
63 | self.0 as f32 / Self::SECOND.0 as f32 |
64 | } |
65 | |
66 | #[inline ] |
67 | pub fn seconds_f64(self) -> f64 { |
68 | self.0 as f64 / Self::SECOND.0 as f64 |
69 | } |
70 | |
71 | #[inline ] |
72 | pub const fn mseconds(self) -> u64 { |
73 | self.0 / Self::MSECOND.0 |
74 | } |
75 | |
76 | #[inline ] |
77 | pub const fn useconds(self) -> u64 { |
78 | self.0 / Self::USECOND.0 |
79 | } |
80 | |
81 | #[inline ] |
82 | pub const fn nseconds(self) -> u64 { |
83 | self.0 |
84 | } |
85 | |
86 | // rustdoc-stripper-ignore-next |
87 | /// Builds a new `ClockTime` which value is the given number of seconds. |
88 | /// |
89 | /// # Panics |
90 | /// |
91 | /// Panics if the resulting duration in nanoseconds exceeds the `u64` range. |
92 | #[track_caller ] |
93 | #[inline ] |
94 | pub const fn from_seconds(seconds: u64) -> Self { |
95 | skip_assert_initialized!(); |
96 | // `Option::expect` is not `const` as of rustc 1.63.0. |
97 | ClockTime(match seconds.checked_mul(Self::SECOND.0) { |
98 | Some(res) => res, |
99 | None => panic!("Out of `ClockTime` range" ), |
100 | }) |
101 | } |
102 | |
103 | // rustdoc-stripper-ignore-next |
104 | /// Builds a new `ClockTime` which value is the given number of seconds. |
105 | /// |
106 | /// Returns an error if seconds is negative, infinite or NaN, or |
107 | /// the resulting duration in nanoseconds exceeds the `u64` range. |
108 | #[inline ] |
109 | pub fn try_from_seconds_f32(seconds: f32) -> Result<Self, TryFromFloatSecsError> { |
110 | skip_assert_initialized!(); |
111 | |
112 | let dur = Duration::try_from_secs_f32(seconds).map_err(|_| TryFromFloatSecsError)?; |
113 | ClockTime::try_from(dur).map_err(|_| TryFromFloatSecsError) |
114 | } |
115 | |
116 | // rustdoc-stripper-ignore-next |
117 | /// Builds a new `ClockTime` which value is the given number of seconds. |
118 | /// |
119 | /// # Panics |
120 | /// |
121 | /// Panics if seconds is negative, infinite or NaN, or the resulting duration |
122 | /// in nanoseconds exceeds the `u64` range. |
123 | #[track_caller ] |
124 | #[inline ] |
125 | pub fn from_seconds_f32(seconds: f32) -> Self { |
126 | skip_assert_initialized!(); |
127 | |
128 | Self::try_from_seconds_f32(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG) |
129 | } |
130 | |
131 | // rustdoc-stripper-ignore-next |
132 | /// Builds a new `ClockTime` which value is the given number of seconds. |
133 | /// |
134 | /// Returns an error if seconds is negative, infinite or NaN, or |
135 | /// the resulting duration in nanoseconds exceeds the `u64` range. |
136 | #[inline ] |
137 | pub fn try_from_seconds_f64(seconds: f64) -> Result<Self, TryFromFloatSecsError> { |
138 | skip_assert_initialized!(); |
139 | |
140 | let dur = Duration::try_from_secs_f64(seconds).map_err(|_| TryFromFloatSecsError)?; |
141 | ClockTime::try_from(dur).map_err(|_| TryFromFloatSecsError) |
142 | } |
143 | |
144 | // rustdoc-stripper-ignore-next |
145 | /// Builds a new `ClockTime` which value is the given number of seconds. |
146 | /// |
147 | /// # Panics |
148 | /// |
149 | /// Panics if seconds is negative, infinite or NaN, or the resulting duration |
150 | /// in nanoseconds exceeds the `u64` range. |
151 | #[track_caller ] |
152 | #[inline ] |
153 | pub fn from_seconds_f64(seconds: f64) -> Self { |
154 | skip_assert_initialized!(); |
155 | |
156 | Self::try_from_seconds_f64(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG) |
157 | } |
158 | |
159 | // rustdoc-stripper-ignore-next |
160 | /// Builds a new `ClockTime` which value is the given number of milliseconds. |
161 | /// |
162 | /// # Panics |
163 | /// |
164 | /// Panics if the resulting duration in nanoseconds exceeds the `u64` range. |
165 | #[track_caller ] |
166 | #[inline ] |
167 | pub const fn from_mseconds(mseconds: u64) -> Self { |
168 | skip_assert_initialized!(); |
169 | // `Option::expect` is not `const` as of rustc 1.63.0. |
170 | ClockTime(match mseconds.checked_mul(Self::MSECOND.0) { |
171 | Some(res) => res, |
172 | None => panic!("Out of `ClockTime` range" ), |
173 | }) |
174 | } |
175 | |
176 | // rustdoc-stripper-ignore-next |
177 | /// Builds a new `ClockTime` which value is the given number of microseconds. |
178 | /// |
179 | /// # Panics |
180 | /// |
181 | /// Panics if the resulting duration in nanoseconds exceeds the `u64` range. |
182 | #[track_caller ] |
183 | #[inline ] |
184 | pub const fn from_useconds(useconds: u64) -> Self { |
185 | skip_assert_initialized!(); |
186 | // `Option::expect` is not `const` as of rustc 1.63.0. |
187 | ClockTime(match useconds.checked_mul(Self::USECOND.0) { |
188 | Some(res) => res, |
189 | None => panic!("Out of `ClockTime` range" ), |
190 | }) |
191 | } |
192 | |
193 | // rustdoc-stripper-ignore-next |
194 | /// Builds a new `ClockTime` which value is the given number of nanoseconds. |
195 | /// |
196 | /// # Panics |
197 | /// |
198 | /// Panics if the requested duration equals `GST_CLOCK_TIME_NONE` |
199 | /// (`u64::MAX`). |
200 | #[track_caller ] |
201 | #[inline ] |
202 | pub const fn from_nseconds(nseconds: u64) -> Self { |
203 | skip_assert_initialized!(); |
204 | assert!( |
205 | nseconds != ffi::GST_CLOCK_TIME_NONE, |
206 | "Attempt to build a `ClockTime` with value `GST_CLOCK_TIME_NONE`" , |
207 | ); |
208 | ClockTime(nseconds * Self::NSECOND.0) |
209 | } |
210 | } |
211 | |
212 | impl Signed<ClockTime> { |
213 | // rustdoc-stripper-ignore-next |
214 | /// Returns the `self` in nanoseconds. |
215 | #[inline ] |
216 | pub fn nseconds(self) -> Signed<u64> { |
217 | match self { |
218 | Signed::Positive(val) => Signed::Positive(val.nseconds()), |
219 | Signed::Negative(val) => Signed::Negative(val.nseconds()), |
220 | } |
221 | } |
222 | |
223 | // rustdoc-stripper-ignore-next |
224 | /// Creates new value from nanoseconds. |
225 | #[inline ] |
226 | pub fn from_nseconds(val: Signed<u64>) -> Self { |
227 | skip_assert_initialized!(); |
228 | match val { |
229 | Signed::Positive(val) => Signed::Positive(ClockTime::from_nseconds(val)), |
230 | Signed::Negative(val) => Signed::Negative(ClockTime::from_nseconds(val)), |
231 | } |
232 | } |
233 | |
234 | // rustdoc-stripper-ignore-next |
235 | /// Returns the `self` in microseconds. |
236 | #[inline ] |
237 | pub fn useconds(self) -> Signed<u64> { |
238 | match self { |
239 | Signed::Positive(val) => Signed::Positive(val.useconds()), |
240 | Signed::Negative(val) => Signed::Negative(val.useconds()), |
241 | } |
242 | } |
243 | |
244 | // rustdoc-stripper-ignore-next |
245 | /// Creates new value from microseconds. |
246 | #[inline ] |
247 | pub fn from_useconds(val: Signed<u64>) -> Self { |
248 | skip_assert_initialized!(); |
249 | match val { |
250 | Signed::Positive(val) => Signed::Positive(ClockTime::from_useconds(val)), |
251 | Signed::Negative(val) => Signed::Negative(ClockTime::from_useconds(val)), |
252 | } |
253 | } |
254 | |
255 | // rustdoc-stripper-ignore-next |
256 | /// Returns the `self` in milliseconds. |
257 | #[inline ] |
258 | pub fn mseconds(self) -> Signed<u64> { |
259 | match self { |
260 | Signed::Positive(val) => Signed::Positive(val.mseconds()), |
261 | Signed::Negative(val) => Signed::Negative(val.mseconds()), |
262 | } |
263 | } |
264 | |
265 | // rustdoc-stripper-ignore-next |
266 | /// Creates new value from milliseconds. |
267 | #[inline ] |
268 | pub fn from_mseconds(val: Signed<u64>) -> Self { |
269 | skip_assert_initialized!(); |
270 | match val { |
271 | Signed::Positive(val) => Signed::Positive(ClockTime::from_mseconds(val)), |
272 | Signed::Negative(val) => Signed::Negative(ClockTime::from_mseconds(val)), |
273 | } |
274 | } |
275 | |
276 | // rustdoc-stripper-ignore-next |
277 | /// Returns the `self` in seconds. |
278 | #[inline ] |
279 | pub fn seconds(self) -> Signed<u64> { |
280 | match self { |
281 | Signed::Positive(val) => Signed::Positive(val.seconds()), |
282 | Signed::Negative(val) => Signed::Negative(val.seconds()), |
283 | } |
284 | } |
285 | |
286 | // rustdoc-stripper-ignore-next |
287 | /// Returns the `self` in f32 seconds. |
288 | #[inline ] |
289 | pub fn seconds_f32(self) -> f32 { |
290 | match self { |
291 | Signed::Positive(val) => val.seconds_f32(), |
292 | Signed::Negative(val) => -val.seconds_f32(), |
293 | } |
294 | } |
295 | |
296 | // rustdoc-stripper-ignore-next |
297 | /// Returns the `self` in f64 seconds. |
298 | #[inline ] |
299 | pub fn seconds_f64(self) -> f64 { |
300 | match self { |
301 | Signed::Positive(val) => val.seconds_f64(), |
302 | Signed::Negative(val) => -val.seconds_f64(), |
303 | } |
304 | } |
305 | |
306 | // rustdoc-stripper-ignore-next |
307 | /// Creates new value from seconds. |
308 | #[inline ] |
309 | pub fn from_seconds(val: Signed<u64>) -> Self { |
310 | skip_assert_initialized!(); |
311 | match val { |
312 | Signed::Positive(val) => Signed::Positive(ClockTime::from_seconds(val)), |
313 | Signed::Negative(val) => Signed::Negative(ClockTime::from_seconds(val)), |
314 | } |
315 | } |
316 | |
317 | // rustdoc-stripper-ignore-next |
318 | /// Builds a new `Signed<ClockTime>` which value is the given number of seconds. |
319 | /// |
320 | /// Returns an error if seconds is infinite or NaN, or |
321 | /// the resulting duration in nanoseconds exceeds the `u64` range. |
322 | #[inline ] |
323 | pub fn try_from_seconds_f32(seconds: f32) -> Result<Self, TryFromFloatSecsError> { |
324 | skip_assert_initialized!(); |
325 | |
326 | ClockTime::try_from_seconds_f32(seconds.abs()).map(|ct| { |
327 | if seconds.is_sign_positive() { |
328 | Signed::Positive(ct) |
329 | } else { |
330 | Signed::Negative(ct) |
331 | } |
332 | }) |
333 | } |
334 | |
335 | // rustdoc-stripper-ignore-next |
336 | /// Builds a new `Signed<ClockTime>` which value is the given number of seconds. |
337 | /// |
338 | /// # Panics |
339 | /// |
340 | /// Panics if seconds is infinite or NaN, or the resulting duration |
341 | /// in nanoseconds exceeds the `u64` range. |
342 | #[track_caller ] |
343 | #[inline ] |
344 | pub fn from_seconds_f32(seconds: f32) -> Self { |
345 | skip_assert_initialized!(); |
346 | |
347 | Self::try_from_seconds_f32(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG) |
348 | } |
349 | |
350 | // rustdoc-stripper-ignore-next |
351 | /// Builds a new `Signed<ClockTime>` which value is the given number of seconds. |
352 | /// |
353 | /// Returns an error if seconds is infinite or NaN, or |
354 | /// the resulting duration in nanoseconds exceeds the `u64` range. |
355 | #[inline ] |
356 | pub fn try_from_seconds_f64(seconds: f64) -> Result<Self, TryFromFloatSecsError> { |
357 | skip_assert_initialized!(); |
358 | |
359 | ClockTime::try_from_seconds_f64(seconds.abs()).map(|ct| { |
360 | if seconds.is_sign_positive() { |
361 | Signed::Positive(ct) |
362 | } else { |
363 | Signed::Negative(ct) |
364 | } |
365 | }) |
366 | } |
367 | |
368 | // rustdoc-stripper-ignore-next |
369 | /// Builds a new `Signed<ClockTime>` which value is the given number of seconds. |
370 | /// |
371 | /// # Panics |
372 | /// |
373 | /// Panics if seconds is infinite or NaN, or the resulting duration |
374 | /// in nanoseconds exceeds the `u64` range. |
375 | #[track_caller ] |
376 | #[inline ] |
377 | pub fn from_seconds_f64(seconds: f64) -> Self { |
378 | skip_assert_initialized!(); |
379 | |
380 | Self::try_from_seconds_f64(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG) |
381 | } |
382 | } |
383 | |
384 | impl_format_value_traits!(ClockTime, Time, Time, u64); |
385 | option_glib_newtype_from_to!(ClockTime, ffi::GST_CLOCK_TIME_NONE); |
386 | |
387 | // FIXME `functions in traits cannot be const` (rustc 1.64.0) |
388 | // rustdoc-stripper-ignore-next |
389 | /// `ClockTime` formatted value constructor trait. |
390 | pub trait TimeFormatConstructor { |
391 | // rustdoc-stripper-ignore-next |
392 | /// Builds a `ClockTime` formatted value from `self` interpreted as nano seconds. |
393 | fn nseconds(self) -> ClockTime; |
394 | |
395 | // rustdoc-stripper-ignore-next |
396 | /// Builds a `ClockTime` formatted value from `self` interpreted as micro seconds. |
397 | fn useconds(self) -> ClockTime; |
398 | |
399 | // rustdoc-stripper-ignore-next |
400 | /// Builds a `ClockTime` formatted value from `self` interpreted as milli seconds. |
401 | fn mseconds(self) -> ClockTime; |
402 | |
403 | // rustdoc-stripper-ignore-next |
404 | /// Builds a `ClockTime` formatted value from `self` interpreted as seconds. |
405 | fn seconds(self) -> ClockTime; |
406 | |
407 | // rustdoc-stripper-ignore-next |
408 | /// Builds a `ClockTime` formatted value from `self` interpreted as minutes. |
409 | fn minutes(self) -> ClockTime; |
410 | |
411 | // rustdoc-stripper-ignore-next |
412 | /// Builds a `ClockTime` formatted value from `self` interpreted as hours. |
413 | fn hours(self) -> ClockTime; |
414 | } |
415 | |
416 | impl TimeFormatConstructor for u64 { |
417 | #[track_caller ] |
418 | #[inline ] |
419 | fn nseconds(self) -> ClockTime { |
420 | ClockTime::from_nseconds(self) |
421 | } |
422 | |
423 | #[track_caller ] |
424 | #[inline ] |
425 | fn useconds(self) -> ClockTime { |
426 | ClockTime::from_useconds(self) |
427 | } |
428 | |
429 | #[track_caller ] |
430 | #[inline ] |
431 | fn mseconds(self) -> ClockTime { |
432 | ClockTime::from_mseconds(self) |
433 | } |
434 | |
435 | #[track_caller ] |
436 | #[inline ] |
437 | fn seconds(self) -> ClockTime { |
438 | ClockTime::from_seconds(self) |
439 | } |
440 | |
441 | #[track_caller ] |
442 | #[inline ] |
443 | fn minutes(self) -> ClockTime { |
444 | ClockTime::from_seconds(self * 60) |
445 | } |
446 | |
447 | #[track_caller ] |
448 | #[inline ] |
449 | fn hours(self) -> ClockTime { |
450 | ClockTime::from_seconds(self * 60 * 60) |
451 | } |
452 | } |
453 | |
454 | impl glib::value::ValueType for ClockTime { |
455 | type Type = Self; |
456 | } |
457 | |
458 | pub enum ClockTimeValueTypeOrNoneChecker {} |
459 | |
460 | unsafe impl glib::value::ValueTypeChecker for ClockTimeValueTypeOrNoneChecker { |
461 | type Error = glib::value::ValueTypeMismatchOrNoneError<glib::value::ValueTypeMismatchError>; |
462 | |
463 | #[inline ] |
464 | fn check(value: &glib::Value) -> Result<(), Self::Error> { |
465 | skip_assert_initialized!(); |
466 | glib::value::GenericValueTypeChecker::<ClockTime>::check(value)?; |
467 | |
468 | let gct: u64 = unsafe { glib::gobject_ffi::g_value_get_uint64(value.to_glib_none().0) }; |
469 | if gct == ffi::GST_CLOCK_TIME_NONE { |
470 | return Err(glib::value::ValueTypeMismatchOrNoneError::UnexpectedNone); |
471 | } |
472 | |
473 | Ok(()) |
474 | } |
475 | } |
476 | |
477 | unsafe impl<'a> glib::value::FromValue<'a> for ClockTime { |
478 | type Checker = ClockTimeValueTypeOrNoneChecker; |
479 | |
480 | #[inline ] |
481 | unsafe fn from_value(value: &glib::Value) -> ClockTime { |
482 | skip_assert_initialized!(); |
483 | ClockTime(glib::gobject_ffi::g_value_get_uint64( |
484 | value.to_glib_none().0, |
485 | )) |
486 | } |
487 | } |
488 | |
489 | impl glib::value::ToValue for ClockTime { |
490 | #[inline ] |
491 | fn to_value(&self) -> glib::Value { |
492 | let mut value: Value = glib::Value::for_value_type::<ClockTime>(); |
493 | let gct: u64 = self.into_glib(); |
494 | if gct == ffi::GST_CLOCK_TIME_NONE { |
495 | crate::warning!( |
496 | crate::CAT_RUST, |
497 | "converting a defined `ClockTime` with value `GST_CLOCK_TIME_NONE` to `Value`, this is probably not what you wanted." , |
498 | ); |
499 | } |
500 | unsafe { glib::gobject_ffi::g_value_set_uint64(value:value.to_glib_none_mut().0, v_uint64:gct) } |
501 | value |
502 | } |
503 | |
504 | #[inline ] |
505 | fn value_type(&self) -> glib::Type { |
506 | Self::static_type() |
507 | } |
508 | } |
509 | |
510 | impl glib::value::ToValueOptional for ClockTime { |
511 | #[inline ] |
512 | fn to_value_optional(opt: Option<&Self>) -> glib::Value { |
513 | skip_assert_initialized!(); |
514 | let mut value: Value = glib::Value::for_value_type::<ClockTime>(); |
515 | let inner: u64 = opt.map(|inner| inner.0).unwrap_or(default:ffi::GST_CLOCK_TIME_NONE); |
516 | unsafe { glib::gobject_ffi::g_value_set_uint64(value:value.to_glib_none_mut().0, v_uint64:inner) }; |
517 | |
518 | value |
519 | } |
520 | } |
521 | |
522 | impl From<ClockTime> for glib::Value { |
523 | #[inline ] |
524 | fn from(v: ClockTime) -> glib::Value { |
525 | glib::value::ToValue::to_value(&v) |
526 | } |
527 | } |
528 | |
529 | #[doc (hidden)] |
530 | impl glib::StaticType for ClockTime { |
531 | #[inline ] |
532 | fn static_type() -> glib::Type { |
533 | <u64 as glib::StaticType>::static_type() |
534 | } |
535 | } |
536 | |
537 | impl glib::HasParamSpec for ClockTime { |
538 | type ParamSpec = glib::ParamSpecUInt64; |
539 | type SetValue = Self; |
540 | type BuilderFn = fn(&str) -> glib::ParamSpecUInt64Builder; |
541 | |
542 | fn param_spec_builder() -> Self::BuilderFn { |
543 | Self::ParamSpec::builder |
544 | } |
545 | } |
546 | |
547 | #[derive (Debug)] |
548 | pub struct DurationError; |
549 | |
550 | impl fmt::Display for DurationError { |
551 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
552 | write!(fmt, "out of range conversion from Duration attempted" ) |
553 | } |
554 | } |
555 | |
556 | impl std::error::Error for DurationError {} |
557 | |
558 | impl TryFrom<Duration> for ClockTime { |
559 | type Error = DurationError; |
560 | |
561 | #[inline ] |
562 | fn try_from(d: Duration) -> Result<Self, Self::Error> { |
563 | skip_assert_initialized!(); |
564 | |
565 | let nanos: u128 = d.as_nanos(); |
566 | |
567 | // Note: `std::u64::MAX` is `ClockTime::NONE`. |
568 | if nanos >= std::u64::MAX as u128 { |
569 | return Err(DurationError); |
570 | } |
571 | |
572 | Ok(ClockTime::from_nseconds(nanos as u64)) |
573 | } |
574 | } |
575 | |
576 | impl From<ClockTime> for Duration { |
577 | #[inline ] |
578 | fn from(t: ClockTime) -> Self { |
579 | skip_assert_initialized!(); |
580 | |
581 | Duration::from_nanos(t.nseconds()) |
582 | } |
583 | } |
584 | |
585 | impl_common_ops_for_newtype_uint!(ClockTime, u64); |
586 | impl_signed_div_mul!(ClockTime, u64); |
587 | impl_signed_int_into_signed!(ClockTime, u64); |
588 | |
589 | // rustdoc-stripper-ignore-next |
590 | /// Tell [`pad_clocktime`] what kind of time we're formatting |
591 | enum Sign { |
592 | // rustdoc-stripper-ignore-next |
593 | /// An undefined time (`None`) |
594 | Undefined, |
595 | |
596 | // rustdoc-stripper-ignore-next |
597 | /// A non-negative time (zero or greater) |
598 | NonNegative, |
599 | |
600 | // For a future ClockTimeDiff formatting |
601 | #[allow (dead_code)] |
602 | // rustdoc-stripper-ignore-next |
603 | /// A negative time (below zero) |
604 | Negative, |
605 | } |
606 | |
607 | // Derived from libcore `Formatter::pad_integral` (same APACHE v2 + MIT licenses) |
608 | // |
609 | // TODO: Would be useful for formatting ClockTimeDiff |
610 | // if it was a new type instead of an alias for i64 |
611 | // |
612 | // rustdoc-stripper-ignore-next |
613 | /// Performs the correct padding for a clock time which has already been |
614 | /// emitted into a str, as by [`write_clocktime`]. The str should *not* |
615 | /// contain the sign; that will be added by this method. |
616 | fn pad_clocktime(f: &mut fmt::Formatter<'_>, sign: Sign, buf: &str) -> fmt::Result { |
617 | skip_assert_initialized!(); |
618 | use std::fmt::{Alignment, Write}; |
619 | |
620 | use self::Sign::*; |
621 | |
622 | // Start by determining how we're padding, gathering |
623 | // settings from the Formatter and the Sign |
624 | |
625 | // Choose the fill character |
626 | let sign_aware_zero_pad = f.sign_aware_zero_pad(); |
627 | let fill_char = match sign { |
628 | Undefined if sign_aware_zero_pad => '-' , // Zero-padding an undefined time |
629 | _ if sign_aware_zero_pad => '0' , // Zero-padding a valid time |
630 | _ => f.fill(), // Otherwise, pad with the user-chosen character |
631 | }; |
632 | |
633 | // Choose the sign character |
634 | let sign_plus = f.sign_plus(); |
635 | let sign_char = match sign { |
636 | Undefined if sign_plus => Some(fill_char), // User requested sign, time is undefined |
637 | NonNegative if sign_plus => Some('+' ), // User requested sign, time is zero or above |
638 | Negative => Some('-' ), // Time is below zero |
639 | _ => None, // Otherwise, add no sign |
640 | }; |
641 | |
642 | // Our minimum width is the value's width, plus 1 for the sign if present |
643 | let width = buf.len() + sign_char.map_or(0, |_| 1); |
644 | |
645 | // Subtract the minimum width from the requested width to get the padding, |
646 | // taking care not to allow wrapping due to underflow |
647 | let padding = f.width().unwrap_or(0).saturating_sub(width); |
648 | |
649 | // Split the required padding into the three possible parts |
650 | let align = f.align().unwrap_or(Alignment::Right); |
651 | let (pre_padding, zero_padding, post_padding) = match align { |
652 | _ if sign_aware_zero_pad => (0, padding, 0), // Zero-padding: Pad between sign and value |
653 | Alignment::Left => (0, 0, padding), // Align left: Pad on the right side |
654 | Alignment::Right => (padding, 0, 0), // Align right: Pad on the left side |
655 | |
656 | // Align center: Split equally between left and right side |
657 | // If the required padding is odd, the right side gets one more char |
658 | Alignment::Center => (padding / 2, 0, (padding + 1) / 2), |
659 | }; |
660 | |
661 | // And now for the actual writing |
662 | |
663 | for _ in 0..pre_padding { |
664 | f.write_char(fill_char)?; // Left padding |
665 | } |
666 | if let Some(c) = sign_char { |
667 | f.write_char(c)?; // ------- Sign character |
668 | } |
669 | for _ in 0..zero_padding { |
670 | f.write_char(fill_char)?; // Padding between sign and value |
671 | } |
672 | f.write_str(buf)?; // ---------- Value |
673 | for _ in 0..post_padding { |
674 | f.write_char(fill_char)?; // Right padding |
675 | } |
676 | |
677 | Ok(()) |
678 | } |
679 | |
680 | // rustdoc-stripper-ignore-next |
681 | /// Writes an unpadded, signless clocktime string with the given precision |
682 | fn write_clocktime<W: io::Write>( |
683 | mut writer: W, |
684 | clocktime: Option<ClockTime>, |
685 | precision: usize, |
686 | ) -> io::Result<()> { |
687 | skip_assert_initialized!(); |
688 | let precision = std::cmp::min(9, precision); |
689 | |
690 | if let Some(ns) = clocktime.map(ClockTime::nseconds) { |
691 | // Split the time into parts |
692 | let (s, ns) = num_integer::div_rem(ns, 1_000_000_000); |
693 | let (m, s) = num_integer::div_rem(s, 60); |
694 | let (h, m) = num_integer::div_rem(m, 60); |
695 | |
696 | // Write HH:MM:SS |
697 | write!(writer, " {h}: {m:02}: {s:02}" )?; |
698 | |
699 | if precision > 0 { |
700 | // Format the nanoseconds into a stack-allocated string |
701 | // The value is zero-padded so always 9 digits long |
702 | let mut buf = [0u8; 9]; |
703 | write!(&mut buf[..], " {ns:09}" ).unwrap(); |
704 | let buf_str = std::str::from_utf8(&buf[..]).unwrap(); |
705 | |
706 | // Write decimal point and a prefix of the nanoseconds for more precision |
707 | write!(writer, ". {buf_str:.precision$}" )?; |
708 | } |
709 | } else { |
710 | // Undefined time |
711 | |
712 | // Write HH:MM:SS, but invalid |
713 | write!(writer, "--:--:--" )?; |
714 | |
715 | if precision > 0 { |
716 | // Write decimal point and dashes for more precision |
717 | write!(writer, ". {:->p$}" , "" , p = precision)?; |
718 | } |
719 | } |
720 | |
721 | Ok(()) |
722 | } |
723 | |
724 | fn fmt_opt_clock_time(ct: Option<ClockTime>, f: &mut fmt::Formatter) -> fmt::Result { |
725 | skip_assert_initialized!(); |
726 | let precision: usize = f.precision().unwrap_or(default:9); |
727 | |
728 | // What the maximum time (u64::MAX - 1) would format to |
729 | const MAX_SIZE: usize = "5124095:34:33.709551614" .len(); |
730 | |
731 | // Write the unpadded clocktime value into a stack-allocated string |
732 | let mut buf: [u8; 23] = [0u8; MAX_SIZE]; |
733 | let mut cursor: Cursor<&mut [u8]> = io::Cursor::new(&mut buf[..]); |
734 | write_clocktime(&mut cursor, clocktime:ct, precision).unwrap(); |
735 | let pos: usize = cursor.position() as usize; |
736 | let buf_str: &str = std::str::from_utf8(&buf[..pos]).unwrap(); |
737 | |
738 | let sign: Sign = if ct.is_some() { |
739 | Sign::NonNegative |
740 | } else { |
741 | Sign::Undefined |
742 | }; |
743 | |
744 | pad_clocktime(f, sign, buf_str) |
745 | } |
746 | |
747 | impl fmt::Display for ClockTime { |
748 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
749 | fmt_opt_clock_time(ct:Some(*self), f) |
750 | } |
751 | } |
752 | |
753 | impl fmt::Debug for ClockTime { |
754 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
755 | fmt::Display::fmt(self, f) |
756 | } |
757 | } |
758 | |
759 | pub struct DisplayableOptClockTime(Option<ClockTime>); |
760 | |
761 | impl fmt::Display for DisplayableOptClockTime { |
762 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
763 | fmt_opt_clock_time(self.0, f) |
764 | } |
765 | } |
766 | |
767 | impl fmt::Debug for DisplayableOptClockTime { |
768 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
769 | fmt::Display::fmt(self, f) |
770 | } |
771 | } |
772 | |
773 | impl crate::utils::Displayable for Option<ClockTime> { |
774 | type DisplayImpl = DisplayableOptClockTime; |
775 | |
776 | fn display(self) -> DisplayableOptClockTime { |
777 | DisplayableOptClockTime(self) |
778 | } |
779 | } |
780 | |
781 | impl crate::utils::Displayable for ClockTime { |
782 | type DisplayImpl = ClockTime; |
783 | |
784 | fn display(self) -> ClockTime { |
785 | self |
786 | } |
787 | } |
788 | |
789 | impl std::iter::Sum for ClockTime { |
790 | fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { |
791 | skip_assert_initialized!(); |
792 | iter.fold(init:ClockTime::ZERO, |a: ClockTime, b: ClockTime| a + b) |
793 | } |
794 | } |
795 | |
796 | #[cfg (test)] |
797 | mod tests { |
798 | use opt_ops::prelude::*; |
799 | |
800 | use super::*; |
801 | use crate::format::{Signed, UnsignedIntoSigned}; |
802 | |
803 | const CT_1: ClockTime = ClockTime::from_nseconds(1); |
804 | const CT_2: ClockTime = ClockTime::from_nseconds(2); |
805 | const CT_3: ClockTime = ClockTime::from_nseconds(3); |
806 | const CT_10: ClockTime = ClockTime::from_nseconds(10); |
807 | const CT_20: ClockTime = ClockTime::from_nseconds(20); |
808 | const CT_30: ClockTime = ClockTime::from_nseconds(30); |
809 | |
810 | const P_CT_0: Signed<ClockTime> = Signed::Positive(ClockTime::ZERO); |
811 | const P_CT_NONE: Option<Signed<ClockTime>> = None; |
812 | const P_CT_1: Signed<ClockTime> = Signed::Positive(ClockTime::from_nseconds(1)); |
813 | const P_CT_2: Signed<ClockTime> = Signed::Positive(ClockTime::from_nseconds(2)); |
814 | const P_CT_3: Signed<ClockTime> = Signed::Positive(ClockTime::from_nseconds(3)); |
815 | const N_CT_1: Signed<ClockTime> = Signed::Negative(ClockTime::from_nseconds(1)); |
816 | const N_CT_2: Signed<ClockTime> = Signed::Negative(ClockTime::from_nseconds(2)); |
817 | const N_CT_3: Signed<ClockTime> = Signed::Negative(ClockTime::from_nseconds(3)); |
818 | |
819 | #[test ] |
820 | fn opt_time_clock() { |
821 | assert_eq!(CT_1.into_glib(), 1); |
822 | assert_eq!(Some(CT_1).into_glib(), 1); |
823 | assert_eq!(ClockTime::NONE.into_glib(), ffi::GST_CLOCK_TIME_NONE); |
824 | |
825 | let ct_1_from: ClockTime = unsafe { try_from_glib(1u64) }.unwrap(); |
826 | assert_eq!(ct_1_from, CT_1); |
827 | |
828 | let opt_ct_some: Option<ClockTime> = unsafe { from_glib(1u64) }; |
829 | assert_eq!(opt_ct_some, Some(CT_1)); |
830 | |
831 | let ct_none: Option<ClockTime> = unsafe { from_glib(ffi::GST_CLOCK_TIME_NONE) }; |
832 | assert_eq!(ct_none, None); |
833 | } |
834 | |
835 | #[test ] |
836 | #[allow (clippy::eq_op, clippy::op_ref)] |
837 | fn ops() { |
838 | assert_eq!(CT_10 + CT_20, CT_30); |
839 | assert_eq!(CT_30 - CT_20, CT_10); |
840 | assert_eq!(CT_30 - CT_30, ClockTime::ZERO); |
841 | assert_eq!(CT_10 * 3, CT_30); |
842 | assert_eq!(3 * CT_10, CT_30); |
843 | assert_eq!(CT_20 / 2, CT_10); |
844 | assert_eq!(CT_20 / CT_2, 10); |
845 | assert_eq!(CT_30.nseconds(), 30); |
846 | |
847 | assert_eq!(P_CT_1 + P_CT_2, P_CT_3); |
848 | assert_eq!(P_CT_3 + N_CT_2, P_CT_1); |
849 | assert_eq!(P_CT_2 + N_CT_3, N_CT_1); |
850 | assert_eq!(N_CT_3 + P_CT_1, N_CT_2); |
851 | assert_eq!(N_CT_2 + P_CT_3, P_CT_1); |
852 | assert_eq!(N_CT_2 + N_CT_1, N_CT_3); |
853 | |
854 | assert_eq!(CT_1 + P_CT_2, P_CT_3); |
855 | assert_eq!(P_CT_1 + CT_2, P_CT_3); |
856 | assert_eq!(CT_3 + N_CT_1, P_CT_2); |
857 | assert_eq!(N_CT_1 + CT_2, P_CT_1); |
858 | |
859 | assert_eq!(P_CT_3 - P_CT_2, P_CT_1); |
860 | assert_eq!(P_CT_2 - P_CT_3, N_CT_1); |
861 | assert_eq!(P_CT_2 - N_CT_1, P_CT_3); |
862 | assert_eq!(N_CT_2 - P_CT_1, N_CT_3); |
863 | assert_eq!(N_CT_3 - N_CT_1, N_CT_2); |
864 | |
865 | assert_eq!(CT_3 - P_CT_2, P_CT_1); |
866 | assert_eq!(P_CT_3 - CT_2, P_CT_1); |
867 | assert_eq!(N_CT_2 - CT_1, N_CT_3); |
868 | assert_eq!(CT_2 - N_CT_1, P_CT_3); |
869 | |
870 | assert_eq!(P_CT_1 * 2i64, P_CT_2); |
871 | assert_eq!(P_CT_1 * -2i64, N_CT_2); |
872 | assert_eq!(N_CT_1 * 2i64, N_CT_2); |
873 | assert_eq!(N_CT_1 * -2i64, P_CT_2); |
874 | |
875 | assert_eq!(2i64 * P_CT_1, P_CT_2); |
876 | assert_eq!(-2i64 * P_CT_1, N_CT_2); |
877 | |
878 | assert_eq!(P_CT_1 * 2u64, P_CT_2); |
879 | assert_eq!(N_CT_1 * 2u64, N_CT_2); |
880 | |
881 | assert_eq!(P_CT_2 / 2i64, P_CT_1); |
882 | assert_eq!(P_CT_2 / -2i64, N_CT_1); |
883 | assert_eq!(N_CT_2 / 2i64, N_CT_1); |
884 | assert_eq!(N_CT_2 / -2i64, P_CT_1); |
885 | |
886 | assert_eq!(P_CT_2 / N_CT_2, Signed::Negative(1)); |
887 | |
888 | assert_eq!(P_CT_2 / 2u64, P_CT_1); |
889 | assert_eq!(N_CT_2 / 2u64, N_CT_1); |
890 | |
891 | assert_eq!(P_CT_3 % 2i64, P_CT_1); |
892 | assert_eq!(P_CT_3 % -2i64, P_CT_1); |
893 | assert_eq!(N_CT_3 % 2i64, N_CT_1); |
894 | assert_eq!(N_CT_3 % -2i64, N_CT_1); |
895 | |
896 | assert_eq!(N_CT_3 % N_CT_2, N_CT_1); |
897 | |
898 | assert_eq!(P_CT_3 % 2u64, P_CT_1); |
899 | assert_eq!(N_CT_3 % 2u64, N_CT_1); |
900 | } |
901 | |
902 | #[test ] |
903 | fn checked_ops() { |
904 | assert_eq!(CT_1.checked_add(CT_1), Some(CT_2)); |
905 | assert_eq!(P_CT_1.checked_add(P_CT_2), Some(P_CT_3)); |
906 | assert_eq!(P_CT_3.checked_add(N_CT_2), Some(P_CT_1)); |
907 | assert_eq!(P_CT_2.checked_add(N_CT_3), Some(N_CT_1)); |
908 | assert_eq!(N_CT_3.checked_add(P_CT_1), Some(N_CT_2)); |
909 | assert_eq!(N_CT_2.checked_add(P_CT_3), Some(P_CT_1)); |
910 | assert_eq!(N_CT_2.checked_add(N_CT_1), Some(N_CT_3)); |
911 | |
912 | assert_eq!(CT_1.opt_checked_add(CT_1), Ok(Some(CT_2))); |
913 | assert_eq!(CT_1.opt_checked_add(Some(CT_1)), Ok(Some(CT_2))); |
914 | assert_eq!(Some(CT_1).opt_checked_add(Some(CT_1)), Ok(Some(CT_2))); |
915 | assert_eq!(CT_1.opt_checked_add(ClockTime::NONE), Ok(None)); |
916 | assert_eq!(Some(CT_1).opt_checked_add(ClockTime::NONE), Ok(None)); |
917 | |
918 | assert_eq!(CT_1.opt_checked_add(P_CT_1), Ok(Some(P_CT_2))); |
919 | assert_eq!(N_CT_3.opt_checked_add(CT_1), Ok(Some(N_CT_2))); |
920 | |
921 | assert!(ClockTime::MAX.checked_add(CT_1).is_none()); |
922 | assert_eq!( |
923 | ClockTime::MAX.opt_checked_add(Some(CT_1)), |
924 | Err(opt_ops::Error::Overflow) |
925 | ); |
926 | |
927 | assert_eq!(P_CT_1.opt_checked_add(P_CT_1), Ok(Some(P_CT_2))); |
928 | assert_eq!(P_CT_1.opt_checked_add(Some(N_CT_2)), Ok(Some(N_CT_1))); |
929 | assert_eq!(Some(P_CT_1).opt_checked_add(Some(P_CT_1)), Ok(Some(P_CT_2))); |
930 | assert_eq!(P_CT_1.opt_checked_add(ClockTime::NONE), Ok(None)); |
931 | assert_eq!(Some(N_CT_1).opt_checked_add(ClockTime::NONE), Ok(None)); |
932 | |
933 | assert_eq!( |
934 | ClockTime::MAX.into_positive().opt_checked_add(Some(P_CT_1)), |
935 | Err(opt_ops::Error::Overflow) |
936 | ); |
937 | |
938 | assert_eq!(CT_2.checked_sub(CT_1), Some(CT_1)); |
939 | assert_eq!(P_CT_3.checked_sub(P_CT_2), Some(P_CT_1)); |
940 | assert_eq!(P_CT_2.checked_sub(P_CT_3), Some(N_CT_1)); |
941 | assert_eq!(P_CT_2.checked_sub(N_CT_1), Some(P_CT_3)); |
942 | assert_eq!(N_CT_2.checked_sub(P_CT_1), Some(N_CT_3)); |
943 | assert_eq!(N_CT_3.checked_sub(N_CT_1), Some(N_CT_2)); |
944 | assert_eq!(N_CT_2.checked_sub(N_CT_3), Some(P_CT_1)); |
945 | |
946 | assert_eq!(CT_2.opt_checked_sub(CT_1), Ok(Some(CT_1))); |
947 | assert_eq!(CT_2.opt_checked_sub(Some(CT_1)), Ok(Some(CT_1))); |
948 | assert_eq!(Some(CT_2).opt_checked_sub(CT_1), Ok(Some(CT_1))); |
949 | assert_eq!(Some(CT_2).opt_checked_sub(Some(CT_1)), Ok(Some(CT_1))); |
950 | assert_eq!(CT_2.opt_checked_sub(ClockTime::NONE), Ok(None)); |
951 | assert_eq!(Some(CT_2).opt_checked_sub(ClockTime::NONE), Ok(None)); |
952 | |
953 | assert_eq!(P_CT_2.opt_checked_sub(CT_1), Ok(Some(P_CT_1))); |
954 | assert_eq!(N_CT_2.opt_checked_sub(CT_1), Ok(Some(N_CT_3))); |
955 | |
956 | assert!(CT_1.checked_sub(CT_2).is_none()); |
957 | assert_eq!( |
958 | Some(CT_1).opt_checked_sub(CT_2), |
959 | Err(opt_ops::Error::Overflow) |
960 | ); |
961 | |
962 | assert_eq!(P_CT_2.opt_checked_sub(Some(N_CT_1)), Ok(Some(P_CT_3))); |
963 | assert_eq!(Some(N_CT_2).opt_checked_sub(P_CT_1), Ok(Some(N_CT_3))); |
964 | |
965 | assert_eq!(CT_1.checked_mul(2), Some(CT_2)); |
966 | assert_eq!(Some(CT_1).opt_checked_mul(2), Ok(Some(CT_2))); |
967 | assert_eq!(1u64.opt_checked_mul(Some(CT_2)), Ok(Some(CT_2))); |
968 | assert_eq!(P_CT_1.checked_mul(2), Some(P_CT_2)); |
969 | assert_eq!(P_CT_1.checked_mul(-2), Some(N_CT_2)); |
970 | assert_eq!(N_CT_1.checked_mul(2), Some(N_CT_2)); |
971 | assert_eq!(N_CT_1.checked_mul(-2), Some(P_CT_2)); |
972 | |
973 | assert_eq!(Some(P_CT_1).opt_checked_mul(-2i64), Ok(Some(N_CT_2))); |
974 | assert_eq!(N_CT_1.opt_checked_mul(2u64), Ok(Some(N_CT_2))); |
975 | |
976 | assert_eq!((-2i64).opt_checked_mul(Some(P_CT_1)), Ok(Some(N_CT_2))); |
977 | |
978 | assert_eq!(P_CT_1.checked_mul_unsigned(2u64), Some(P_CT_2)); |
979 | assert_eq!(N_CT_1.checked_mul_unsigned(2u64), Some(N_CT_2)); |
980 | |
981 | assert_eq!(CT_3.checked_div(3), Some(CT_1)); |
982 | assert_eq!(P_CT_3.checked_div(3), Some(P_CT_1)); |
983 | assert_eq!(P_CT_3.checked_div(-3), Some(N_CT_1)); |
984 | assert_eq!(N_CT_3.checked_div(3), Some(N_CT_1)); |
985 | assert_eq!(N_CT_3.checked_div(-3), Some(P_CT_1)); |
986 | |
987 | assert_eq!(Some(CT_3).opt_checked_div(CT_3), Ok(Some(1))); |
988 | |
989 | assert_eq!(Some(P_CT_3).opt_checked_div(-3i64), Ok(Some(N_CT_1))); |
990 | assert_eq!(N_CT_3.opt_checked_div(3u64), Ok(Some(N_CT_1))); |
991 | |
992 | assert_eq!(P_CT_3.checked_div_unsigned(3u64), Some(P_CT_1)); |
993 | assert_eq!(N_CT_3.checked_div_unsigned(3u64), Some(N_CT_1)); |
994 | } |
995 | |
996 | #[test ] |
997 | fn overflowing_ops() { |
998 | assert_eq!(CT_1.overflowing_add(CT_2), (CT_3, false)); |
999 | assert_eq!(CT_1.opt_overflowing_add(Some(CT_2)), Some((CT_3, false))); |
1000 | assert_eq!(Some(CT_1).opt_overflowing_add(CT_2), Some((CT_3, false))); |
1001 | assert_eq!( |
1002 | Some(CT_1).opt_overflowing_add(Some(CT_2)), |
1003 | Some((CT_3, false)) |
1004 | ); |
1005 | |
1006 | assert_eq!(ClockTime::NONE.opt_overflowing_add(CT_2), None); |
1007 | assert_eq!(CT_1.opt_overflowing_add(ClockTime::NONE), None); |
1008 | |
1009 | assert_eq!( |
1010 | ClockTime::MAX.overflowing_add(CT_1), |
1011 | (ClockTime::ZERO, true) |
1012 | ); |
1013 | assert_eq!( |
1014 | Some(ClockTime::MAX).opt_overflowing_add(Some(CT_1)), |
1015 | Some((ClockTime::ZERO, true)), |
1016 | ); |
1017 | |
1018 | assert_eq!(CT_3.overflowing_sub(CT_2), (CT_1, false)); |
1019 | assert_eq!(CT_3.opt_overflowing_sub(Some(CT_2)), Some((CT_1, false))); |
1020 | assert_eq!(Some(CT_3).opt_overflowing_sub(CT_2), Some((CT_1, false))); |
1021 | assert_eq!( |
1022 | Some(CT_3).opt_overflowing_sub(Some(CT_2)), |
1023 | Some((CT_1, false)) |
1024 | ); |
1025 | assert_eq!( |
1026 | Some(CT_3).opt_overflowing_sub(&Some(CT_2)), |
1027 | Some((CT_1, false)) |
1028 | ); |
1029 | assert_eq!(ClockTime::NONE.opt_overflowing_sub(CT_2), None); |
1030 | assert_eq!(CT_2.opt_overflowing_sub(ClockTime::NONE), None); |
1031 | |
1032 | assert_eq!(CT_1.overflowing_sub(CT_2), (ClockTime::MAX, true)); |
1033 | assert_eq!( |
1034 | Some(CT_1).opt_overflowing_sub(CT_2), |
1035 | Some((ClockTime::MAX, true)) |
1036 | ); |
1037 | } |
1038 | |
1039 | #[test ] |
1040 | fn saturating_ops() { |
1041 | let p_ct_max: Signed<ClockTime> = ClockTime::MAX.into_positive(); |
1042 | let n_ct_max: Signed<ClockTime> = ClockTime::MAX.into_negative(); |
1043 | |
1044 | assert_eq!(CT_1.saturating_add(CT_2), CT_3); |
1045 | assert_eq!(P_CT_1.saturating_add(P_CT_2), P_CT_3); |
1046 | assert_eq!(P_CT_2.saturating_add(N_CT_3), N_CT_1); |
1047 | assert_eq!(P_CT_3.saturating_add(N_CT_2), P_CT_1); |
1048 | assert_eq!(N_CT_3.saturating_add(P_CT_1), N_CT_2); |
1049 | assert_eq!(N_CT_2.saturating_add(P_CT_3), P_CT_1); |
1050 | assert_eq!(N_CT_2.saturating_add(N_CT_1), N_CT_3); |
1051 | |
1052 | assert_eq!(CT_1.opt_saturating_add(Some(CT_2)), Some(CT_3)); |
1053 | assert_eq!(Some(CT_1).opt_saturating_add(Some(CT_2)), Some(CT_3)); |
1054 | assert_eq!(Some(CT_1).opt_saturating_add(ClockTime::NONE), None); |
1055 | |
1056 | assert_eq!(P_CT_1.opt_saturating_add(Some(CT_2)), Some(P_CT_3)); |
1057 | assert_eq!(Some(CT_1).opt_saturating_add(P_CT_2), Some(P_CT_3)); |
1058 | |
1059 | assert_eq!(ClockTime::MAX.saturating_add(CT_1), ClockTime::MAX); |
1060 | assert_eq!( |
1061 | Some(ClockTime::MAX).opt_saturating_add(Some(CT_1)), |
1062 | Some(ClockTime::MAX) |
1063 | ); |
1064 | assert_eq!(p_ct_max.saturating_add(P_CT_1), p_ct_max); |
1065 | |
1066 | assert_eq!(CT_3.saturating_sub(CT_2), CT_1); |
1067 | assert_eq!(P_CT_3.saturating_sub(P_CT_2), P_CT_1); |
1068 | assert_eq!(P_CT_2.saturating_sub(P_CT_3), N_CT_1); |
1069 | assert_eq!(P_CT_2.saturating_sub(N_CT_1), P_CT_3); |
1070 | assert_eq!(N_CT_2.saturating_sub(P_CT_1), N_CT_3); |
1071 | assert_eq!(N_CT_3.saturating_sub(N_CT_1), N_CT_2); |
1072 | assert_eq!(N_CT_2.saturating_sub(N_CT_3), P_CT_1); |
1073 | |
1074 | assert_eq!(CT_3.opt_saturating_sub(Some(CT_2)), Some(CT_1)); |
1075 | assert_eq!(Some(CT_3).opt_saturating_sub(Some(CT_2)), Some(CT_1)); |
1076 | assert_eq!(Some(CT_3).opt_saturating_sub(ClockTime::NONE), None); |
1077 | |
1078 | assert_eq!(P_CT_2.opt_saturating_sub(Some(CT_3)), Some(N_CT_1)); |
1079 | assert_eq!(Some(CT_3).opt_saturating_sub(P_CT_2), Some(P_CT_1)); |
1080 | |
1081 | assert!(CT_1.saturating_sub(CT_2).is_zero()); |
1082 | assert_eq!(P_CT_1.saturating_sub(P_CT_2), N_CT_1); |
1083 | assert_eq!( |
1084 | Some(CT_1).opt_saturating_sub(Some(CT_2)), |
1085 | Some(ClockTime::ZERO) |
1086 | ); |
1087 | |
1088 | assert_eq!(CT_1.saturating_mul(2), CT_2); |
1089 | assert_eq!(ClockTime::MAX.saturating_mul(2), ClockTime::MAX); |
1090 | |
1091 | assert_eq!(P_CT_1.saturating_mul(2), P_CT_2); |
1092 | assert_eq!(P_CT_1.saturating_mul(-2), N_CT_2); |
1093 | assert_eq!(N_CT_1.saturating_mul(2), N_CT_2); |
1094 | assert_eq!(N_CT_1.saturating_mul(-2), P_CT_2); |
1095 | |
1096 | assert_eq!(Some(N_CT_1).opt_saturating_mul(-2i64), Some(P_CT_2)); |
1097 | assert_eq!((-2i64).opt_saturating_mul(Some(N_CT_1)), Some(P_CT_2)); |
1098 | |
1099 | assert_eq!(P_CT_1.saturating_mul_unsigned(2u64), P_CT_2); |
1100 | assert_eq!(N_CT_1.saturating_mul_unsigned(2u64), N_CT_2); |
1101 | |
1102 | assert_eq!(p_ct_max.saturating_mul(2), p_ct_max); |
1103 | assert_eq!(n_ct_max.saturating_mul(2), n_ct_max); |
1104 | |
1105 | assert_eq!(Some(2i64).opt_saturating_mul(p_ct_max), Some(p_ct_max)); |
1106 | assert_eq!(2u64.opt_saturating_mul(Some(n_ct_max)), Some(n_ct_max)); |
1107 | |
1108 | assert_eq!(p_ct_max.saturating_mul_unsigned(2u64), p_ct_max); |
1109 | assert_eq!(n_ct_max.saturating_mul_unsigned(2u64), n_ct_max); |
1110 | } |
1111 | |
1112 | #[test ] |
1113 | fn wrapping_ops() { |
1114 | assert_eq!(CT_1.wrapping_add(CT_2), CT_3); |
1115 | assert_eq!(CT_1.opt_wrapping_add(CT_2), Some(CT_3)); |
1116 | assert_eq!(Some(CT_1).opt_wrapping_add(CT_2), Some(CT_3)); |
1117 | assert_eq!(Some(CT_1).opt_wrapping_add(Some(CT_2)), Some(CT_3)); |
1118 | assert_eq!(Some(CT_1).opt_wrapping_add(None), None); |
1119 | |
1120 | assert_eq!(ClockTime::MAX.wrapping_add(CT_1), ClockTime::ZERO); |
1121 | assert_eq!( |
1122 | Some(ClockTime::MAX).opt_wrapping_add(Some(CT_1)), |
1123 | Some(ClockTime::ZERO) |
1124 | ); |
1125 | |
1126 | assert_eq!(CT_3.wrapping_sub(CT_2), CT_1); |
1127 | assert_eq!(CT_3.opt_wrapping_sub(CT_2), Some(CT_1)); |
1128 | assert_eq!(Some(CT_3).opt_wrapping_sub(CT_2), Some(CT_1)); |
1129 | assert_eq!(Some(CT_3).opt_wrapping_sub(Some(CT_2)), Some(CT_1)); |
1130 | assert_eq!(Some(CT_3).opt_wrapping_sub(ClockTime::NONE), None); |
1131 | |
1132 | assert_eq!(CT_1.wrapping_sub(CT_2), ClockTime::MAX); |
1133 | assert_eq!( |
1134 | Some(CT_1).opt_wrapping_sub(Some(CT_2)), |
1135 | Some(ClockTime::MAX) |
1136 | ); |
1137 | } |
1138 | |
1139 | #[test ] |
1140 | fn mul_div_ops() { |
1141 | use muldiv::MulDiv; |
1142 | |
1143 | assert_eq!(CT_1.mul_div_floor(7, 3), Some(CT_2)); |
1144 | |
1145 | assert_eq!(P_CT_1.mul_div_floor(7u64, 3), Some(P_CT_2)); |
1146 | assert_eq!(P_CT_1.mul_div_floor(-7i64, 3), Some(N_CT_2)); |
1147 | assert_eq!(P_CT_1.mul_div_floor(7i64, -3), Some(N_CT_2)); |
1148 | assert_eq!(P_CT_1.mul_div_floor(-7i64, -3), Some(P_CT_2)); |
1149 | |
1150 | assert_eq!(N_CT_1.mul_div_floor(7u64, 3), Some(N_CT_2)); |
1151 | assert_eq!(N_CT_1.mul_div_floor(-7i64, 3), Some(P_CT_2)); |
1152 | assert_eq!(N_CT_1.mul_div_floor(7i64, -3), Some(P_CT_2)); |
1153 | assert_eq!(N_CT_1.mul_div_floor(-7i64, -3), Some(N_CT_2)); |
1154 | |
1155 | assert_eq!(CT_1.mul_div_round(10, 3), Some(CT_3)); |
1156 | assert_eq!(CT_1.mul_div_round(8, 3), Some(CT_3)); |
1157 | |
1158 | assert_eq!(P_CT_1.mul_div_round(10u64, 3), Some(P_CT_3)); |
1159 | assert_eq!(P_CT_1.mul_div_round(8u64, 3), Some(P_CT_3)); |
1160 | assert_eq!(P_CT_1.mul_div_round(-10i64, 3), Some(N_CT_3)); |
1161 | assert_eq!(P_CT_1.mul_div_round(-8i64, 3), Some(N_CT_3)); |
1162 | assert_eq!(P_CT_1.mul_div_round(10i64, -3), Some(N_CT_3)); |
1163 | assert_eq!(P_CT_1.mul_div_round(-10i64, -3), Some(P_CT_3)); |
1164 | |
1165 | assert_eq!(N_CT_1.mul_div_round(10u64, 3), Some(N_CT_3)); |
1166 | assert_eq!(N_CT_1.mul_div_round(-10i64, 3), Some(P_CT_3)); |
1167 | assert_eq!(N_CT_1.mul_div_round(10i64, -3), Some(P_CT_3)); |
1168 | assert_eq!(N_CT_1.mul_div_round(-10i64, -3), Some(N_CT_3)); |
1169 | |
1170 | assert_eq!(CT_1.mul_div_ceil(7, 3), Some(CT_3)); |
1171 | |
1172 | assert_eq!(P_CT_1.mul_div_ceil(7u64, 3), Some(P_CT_3)); |
1173 | assert_eq!(P_CT_1.mul_div_ceil(-7i64, 3), Some(N_CT_3)); |
1174 | assert_eq!(P_CT_1.mul_div_ceil(7i64, -3), Some(N_CT_3)); |
1175 | assert_eq!(P_CT_1.mul_div_ceil(-7i64, -3), Some(P_CT_3)); |
1176 | |
1177 | assert_eq!(N_CT_1.mul_div_ceil(7u64, 3), Some(N_CT_3)); |
1178 | assert_eq!(N_CT_1.mul_div_ceil(-7i64, 3), Some(P_CT_3)); |
1179 | assert_eq!(N_CT_1.mul_div_ceil(7i64, -3), Some(P_CT_3)); |
1180 | assert_eq!(N_CT_1.mul_div_ceil(-7i64, -3), Some(N_CT_3)); |
1181 | } |
1182 | |
1183 | #[test ] |
1184 | #[allow (clippy::nonminimal_bool)] |
1185 | fn comp() { |
1186 | assert!(ClockTime::ZERO < CT_2); |
1187 | assert!(Some(ClockTime::ZERO) < Some(CT_2)); |
1188 | assert!(CT_2 < CT_3); |
1189 | assert!(Some(CT_2) < Some(CT_3)); |
1190 | assert!(ClockTime::ZERO < CT_3); |
1191 | assert!(Some(ClockTime::ZERO) < Some(CT_3)); |
1192 | |
1193 | assert_eq!(CT_2, CT_2); |
1194 | assert_ne!(CT_3, CT_2); |
1195 | |
1196 | assert!(ClockTime::ZERO.into_positive() < P_CT_1); |
1197 | assert!(ClockTime::ZERO.into_positive() > N_CT_1); |
1198 | assert!(P_CT_1 < P_CT_2); |
1199 | assert!(P_CT_1 > N_CT_2); |
1200 | assert!(N_CT_1 < P_CT_2); |
1201 | assert!(N_CT_3 < N_CT_2); |
1202 | |
1203 | assert!(P_CT_1 < CT_2); |
1204 | assert!(CT_1 < P_CT_2); |
1205 | assert!(N_CT_2 < CT_1); |
1206 | assert!(CT_1 > N_CT_2); |
1207 | |
1208 | assert_eq!(CT_2, P_CT_2); |
1209 | assert_ne!(N_CT_3, CT_3); |
1210 | |
1211 | assert_eq!(Some(CT_2).opt_lt(Some(CT_3)), Some(true)); |
1212 | assert_eq!(Some(CT_3).opt_lt(CT_2), Some(false)); |
1213 | assert_eq!(Some(CT_2).opt_le(Some(CT_3)), Some(true)); |
1214 | assert_eq!(Some(CT_3).opt_le(CT_3), Some(true)); |
1215 | |
1216 | assert_eq!(Some(P_CT_2).opt_lt(Some(P_CT_3)), Some(true)); |
1217 | assert_eq!(Some(P_CT_3).opt_lt(P_CT_2), Some(false)); |
1218 | assert_eq!(Some(P_CT_2).opt_le(Some(P_CT_3)), Some(true)); |
1219 | assert_eq!(Some(P_CT_3).opt_le(P_CT_3), Some(true)); |
1220 | |
1221 | assert_eq!(Some(P_CT_0).opt_lt(P_CT_NONE), None); |
1222 | assert_eq!(P_CT_NONE.opt_lt(P_CT_0), None); |
1223 | |
1224 | assert_eq!(Some(N_CT_3).opt_lt(Some(N_CT_2)), Some(true)); |
1225 | assert_eq!(Some(N_CT_2).opt_lt(N_CT_3), Some(false)); |
1226 | assert_eq!(Some(N_CT_3).opt_le(Some(N_CT_2)), Some(true)); |
1227 | assert_eq!(Some(N_CT_3).opt_le(N_CT_3), Some(true)); |
1228 | |
1229 | assert_eq!(Some(P_CT_2).opt_lt(N_CT_3), Some(false)); |
1230 | assert_eq!(Some(N_CT_3).opt_lt(Some(P_CT_2)), Some(true)); |
1231 | |
1232 | assert!(CT_3 > CT_2); |
1233 | assert!(Some(CT_3) > Some(CT_2)); |
1234 | assert!(CT_2 > ClockTime::ZERO); |
1235 | assert!(Some(CT_2) > Some(ClockTime::ZERO)); |
1236 | assert!(CT_3 > ClockTime::ZERO); |
1237 | assert!(Some(CT_3) > Some(ClockTime::ZERO)); |
1238 | |
1239 | assert!(!(ClockTime::NONE > None)); |
1240 | // This doesn't work due to the `PartialOrd` impl on `Option<T>` |
1241 | //assert_eq!(Some(ClockTime::ZERO) > ClockTime::ZERO, false); |
1242 | assert!(!(Some(ClockTime::ZERO) < ClockTime::NONE)); |
1243 | assert_eq!(Some(CT_3).opt_gt(Some(CT_2)), Some(true)); |
1244 | assert_eq!(Some(CT_3).opt_ge(Some(CT_2)), Some(true)); |
1245 | assert_eq!(Some(CT_3).opt_ge(CT_3), Some(true)); |
1246 | |
1247 | assert_eq!(Some(P_CT_3).opt_gt(Some(P_CT_2)), Some(true)); |
1248 | assert_eq!(Some(P_CT_3).opt_ge(Some(P_CT_2)), Some(true)); |
1249 | assert_eq!(Some(P_CT_3).opt_ge(P_CT_3), Some(true)); |
1250 | |
1251 | assert_eq!(Some(P_CT_0).opt_gt(P_CT_NONE), None); |
1252 | assert_eq!(P_CT_NONE.opt_gt(P_CT_0), None); |
1253 | |
1254 | assert_eq!(Some(N_CT_3).opt_gt(Some(N_CT_2)), Some(false)); |
1255 | assert_eq!(Some(N_CT_3).opt_ge(Some(N_CT_2)), Some(false)); |
1256 | assert_eq!(Some(N_CT_3).opt_ge(N_CT_3), Some(true)); |
1257 | |
1258 | assert_eq!(Some(P_CT_2).opt_gt(N_CT_3), Some(true)); |
1259 | assert_eq!(Some(N_CT_3).opt_gt(Some(P_CT_2)), Some(false)); |
1260 | |
1261 | assert!(!(ClockTime::NONE < None)); |
1262 | assert!(!(ClockTime::NONE > None)); |
1263 | |
1264 | // This doesn't work due to the `PartialOrd` impl on `Option<T>` |
1265 | //assert!(Some(ClockTime::ZERO) > ClockTime::NONE, false); |
1266 | // Use opt_gt instead. |
1267 | assert_eq!(Some(ClockTime::ZERO).opt_gt(ClockTime::NONE), None); |
1268 | assert_eq!(ClockTime::ZERO.opt_gt(ClockTime::NONE), None); |
1269 | assert_eq!(ClockTime::ZERO.opt_ge(ClockTime::NONE), None); |
1270 | assert_eq!(ClockTime::NONE.opt_gt(Some(ClockTime::ZERO)), None); |
1271 | assert_eq!(ClockTime::NONE.opt_gt(ClockTime::ZERO), None); |
1272 | assert_eq!(ClockTime::NONE.opt_ge(ClockTime::ZERO), None); |
1273 | |
1274 | assert!(!(Some(ClockTime::ZERO) < ClockTime::NONE)); |
1275 | assert_eq!(Some(ClockTime::ZERO).opt_lt(ClockTime::NONE), None); |
1276 | assert_eq!(Some(ClockTime::ZERO).opt_le(ClockTime::NONE), None); |
1277 | |
1278 | assert_eq!(CT_3.opt_min(CT_2), Some(CT_2)); |
1279 | assert_eq!(CT_3.opt_min(Some(CT_2)), Some(CT_2)); |
1280 | assert_eq!(Some(CT_3).opt_min(Some(CT_2)), Some(CT_2)); |
1281 | assert_eq!(ClockTime::NONE.opt_min(Some(CT_2)), None); |
1282 | assert_eq!(Some(CT_3).opt_min(ClockTime::NONE), None); |
1283 | |
1284 | assert_eq!(P_CT_3.opt_min(P_CT_2), Some(P_CT_2)); |
1285 | assert_eq!(P_CT_2.opt_min(P_CT_3), Some(P_CT_2)); |
1286 | assert_eq!(N_CT_3.opt_min(N_CT_2), Some(N_CT_3)); |
1287 | assert_eq!(N_CT_2.opt_min(N_CT_3), Some(N_CT_3)); |
1288 | assert_eq!(P_CT_2.opt_min(N_CT_3), Some(N_CT_3)); |
1289 | |
1290 | assert_eq!(CT_3.opt_max(CT_2), Some(CT_3)); |
1291 | assert_eq!(CT_3.opt_max(Some(CT_2)), Some(CT_3)); |
1292 | assert_eq!(Some(CT_3).opt_max(Some(CT_2)), Some(CT_3)); |
1293 | assert_eq!(ClockTime::NONE.opt_max(Some(CT_2)), None); |
1294 | assert_eq!(Some(CT_3).opt_max(ClockTime::NONE), None); |
1295 | |
1296 | assert_eq!(P_CT_3.opt_max(P_CT_2), Some(P_CT_3)); |
1297 | assert_eq!(P_CT_2.opt_max(P_CT_3), Some(P_CT_3)); |
1298 | assert_eq!(N_CT_3.opt_max(N_CT_2), Some(N_CT_2)); |
1299 | assert_eq!(N_CT_2.opt_max(N_CT_3), Some(N_CT_2)); |
1300 | assert_eq!(P_CT_2.opt_max(N_CT_3), Some(P_CT_2)); |
1301 | } |
1302 | |
1303 | #[test ] |
1304 | fn display() { |
1305 | let none = Option::<ClockTime>::None; |
1306 | let some = Some(45_834_908_569_837 * ClockTime::NSECOND); |
1307 | let lots = ClockTime::from_nseconds(std::u64::MAX - 1); |
1308 | |
1309 | // Simple |
1310 | |
1311 | assert_eq!(format!(" {:.0}" , DisplayableOptClockTime(none)), "--:--:--" ); |
1312 | assert_eq!( |
1313 | format!(" {:.3}" , DisplayableOptClockTime(none)), |
1314 | "--:--:--.---" |
1315 | ); |
1316 | assert_eq!( |
1317 | format!(" {}" , DisplayableOptClockTime(none)), |
1318 | "--:--:--.---------" |
1319 | ); |
1320 | |
1321 | assert_eq!(format!(" {:.0}" , DisplayableOptClockTime(some)), "12:43:54" ); |
1322 | assert_eq!( |
1323 | format!(" {:.3}" , DisplayableOptClockTime(some)), |
1324 | "12:43:54.908" |
1325 | ); |
1326 | assert_eq!( |
1327 | format!(" {}" , DisplayableOptClockTime(some)), |
1328 | "12:43:54.908569837" |
1329 | ); |
1330 | |
1331 | assert_eq!(format!(" {lots:.0}" ), "5124095:34:33" ); |
1332 | assert_eq!(format!(" {lots:.3}" ), "5124095:34:33.709" ); |
1333 | assert_eq!(format!(" {lots}" ), "5124095:34:33.709551614" ); |
1334 | |
1335 | // Precision caps at 9 |
1336 | assert_eq!( |
1337 | format!(" {:.10}" , DisplayableOptClockTime(none)), |
1338 | "--:--:--.---------" |
1339 | ); |
1340 | assert_eq!( |
1341 | format!(" {:.10}" , DisplayableOptClockTime(some)), |
1342 | "12:43:54.908569837" |
1343 | ); |
1344 | assert_eq!(format!(" {lots:.10}" ), "5124095:34:33.709551614" ); |
1345 | |
1346 | // Short width |
1347 | |
1348 | assert_eq!(format!(" {:4.0}" , DisplayableOptClockTime(none)), "--:--:--" ); |
1349 | assert_eq!( |
1350 | format!(" {:4.3}" , DisplayableOptClockTime(none)), |
1351 | "--:--:--.---" |
1352 | ); |
1353 | assert_eq!( |
1354 | format!(" {:4}" , DisplayableOptClockTime(none)), |
1355 | "--:--:--.---------" |
1356 | ); |
1357 | |
1358 | assert_eq!(format!(" {:4.0}" , DisplayableOptClockTime(some)), "12:43:54" ); |
1359 | assert_eq!( |
1360 | format!(" {:4.3}" , DisplayableOptClockTime(some)), |
1361 | "12:43:54.908" |
1362 | ); |
1363 | assert_eq!( |
1364 | format!(" {:4}" , DisplayableOptClockTime(some)), |
1365 | "12:43:54.908569837" |
1366 | ); |
1367 | |
1368 | assert_eq!(format!(" {lots:4.0}" ), "5124095:34:33" ); |
1369 | assert_eq!(format!(" {lots:4.3}" ), "5124095:34:33.709" ); |
1370 | assert_eq!(format!(" {lots:4}" ), "5124095:34:33.709551614" ); |
1371 | |
1372 | // Simple padding |
1373 | |
1374 | assert_eq!( |
1375 | format!(" {:>9.0}" , DisplayableOptClockTime(none)), |
1376 | " --:--:--" |
1377 | ); |
1378 | assert_eq!( |
1379 | format!(" {:<9.0}" , DisplayableOptClockTime(none)), |
1380 | "--:--:-- " |
1381 | ); |
1382 | assert_eq!( |
1383 | format!(" {:^10.0}" , DisplayableOptClockTime(none)), |
1384 | " --:--:-- " |
1385 | ); |
1386 | assert_eq!( |
1387 | format!(" {:>13.3}" , DisplayableOptClockTime(none)), |
1388 | " --:--:--.---" |
1389 | ); |
1390 | assert_eq!( |
1391 | format!(" {:<13.3}" , DisplayableOptClockTime(none)), |
1392 | "--:--:--.--- " |
1393 | ); |
1394 | assert_eq!( |
1395 | format!(" {:^14.3}" , DisplayableOptClockTime(none)), |
1396 | " --:--:--.--- " |
1397 | ); |
1398 | assert_eq!( |
1399 | format!(" {:>19}" , DisplayableOptClockTime(none)), |
1400 | " --:--:--.---------" |
1401 | ); |
1402 | assert_eq!( |
1403 | format!(" {:<19}" , DisplayableOptClockTime(none)), |
1404 | "--:--:--.--------- " |
1405 | ); |
1406 | assert_eq!( |
1407 | format!(" {:^20}" , DisplayableOptClockTime(none)), |
1408 | " --:--:--.--------- " |
1409 | ); |
1410 | |
1411 | assert_eq!( |
1412 | format!(" {:>9.0}" , DisplayableOptClockTime(some)), |
1413 | " 12:43:54" |
1414 | ); |
1415 | assert_eq!( |
1416 | format!(" {:<9.0}" , DisplayableOptClockTime(some)), |
1417 | "12:43:54 " |
1418 | ); |
1419 | assert_eq!( |
1420 | format!(" {:^10.0}" , DisplayableOptClockTime(some)), |
1421 | " 12:43:54 " |
1422 | ); |
1423 | assert_eq!( |
1424 | format!(" {:>13.3}" , DisplayableOptClockTime(some)), |
1425 | " 12:43:54.908" |
1426 | ); |
1427 | assert_eq!( |
1428 | format!(" {:<13.3}" , DisplayableOptClockTime(some)), |
1429 | "12:43:54.908 " |
1430 | ); |
1431 | assert_eq!( |
1432 | format!(" {:^14.3}" , DisplayableOptClockTime(some)), |
1433 | " 12:43:54.908 " |
1434 | ); |
1435 | assert_eq!( |
1436 | format!(" {:>19}" , DisplayableOptClockTime(some)), |
1437 | " 12:43:54.908569837" |
1438 | ); |
1439 | assert_eq!( |
1440 | format!(" {:<19}" , DisplayableOptClockTime(some)), |
1441 | "12:43:54.908569837 " |
1442 | ); |
1443 | assert_eq!( |
1444 | format!(" {:^20}" , DisplayableOptClockTime(some)), |
1445 | " 12:43:54.908569837 " |
1446 | ); |
1447 | |
1448 | assert_eq!(format!(" {lots:>14.0}" ), " 5124095:34:33" ); |
1449 | assert_eq!(format!(" {lots:<14.0}" ), "5124095:34:33 " ); |
1450 | assert_eq!(format!(" {lots:^15.0}" ), " 5124095:34:33 " ); |
1451 | assert_eq!(format!(" {lots:>18.3}" ), " 5124095:34:33.709" ); |
1452 | assert_eq!(format!(" {lots:<18.3}" ), "5124095:34:33.709 " ); |
1453 | assert_eq!(format!(" {lots:^19.3}" ), " 5124095:34:33.709 " ); |
1454 | assert_eq!(format!(" {lots:>24}" ), " 5124095:34:33.709551614" ); |
1455 | assert_eq!(format!(" {lots:<24}" ), "5124095:34:33.709551614 " ); |
1456 | assert_eq!(format!(" {lots:^25}" ), " 5124095:34:33.709551614 " ); |
1457 | |
1458 | // Padding with sign or zero-extension |
1459 | |
1460 | assert_eq!( |
1461 | format!(" {:+11.0}" , DisplayableOptClockTime(none)), |
1462 | " --:--:--" |
1463 | ); |
1464 | assert_eq!( |
1465 | format!(" {:011.0}" , DisplayableOptClockTime(none)), |
1466 | "-----:--:--" |
1467 | ); |
1468 | assert_eq!( |
1469 | format!(" {:+011.0}" , DisplayableOptClockTime(none)), |
1470 | "-----:--:--" |
1471 | ); |
1472 | assert_eq!( |
1473 | format!(" {:+15.3}" , DisplayableOptClockTime(none)), |
1474 | " --:--:--.---" |
1475 | ); |
1476 | assert_eq!( |
1477 | format!(" {:015.3}" , DisplayableOptClockTime(none)), |
1478 | "-----:--:--.---" |
1479 | ); |
1480 | assert_eq!( |
1481 | format!(" {:+015.3}" , DisplayableOptClockTime(none)), |
1482 | "-----:--:--.---" |
1483 | ); |
1484 | assert_eq!( |
1485 | format!(" {:+21}" , DisplayableOptClockTime(none)), |
1486 | " --:--:--.---------" |
1487 | ); |
1488 | assert_eq!( |
1489 | format!(" {:021}" , DisplayableOptClockTime(none)), |
1490 | "-----:--:--.---------" |
1491 | ); |
1492 | assert_eq!( |
1493 | format!(" {:+021}" , DisplayableOptClockTime(none)), |
1494 | "-----:--:--.---------" |
1495 | ); |
1496 | |
1497 | assert_eq!( |
1498 | format!(" {:+11.0}" , DisplayableOptClockTime(some)), |
1499 | " +12:43:54" |
1500 | ); |
1501 | assert_eq!( |
1502 | format!(" {:011.0}" , DisplayableOptClockTime(some)), |
1503 | "00012:43:54" |
1504 | ); |
1505 | assert_eq!( |
1506 | format!(" {:+011.0}" , DisplayableOptClockTime(some)), |
1507 | "+0012:43:54" |
1508 | ); |
1509 | assert_eq!( |
1510 | format!(" {:+15.3}" , DisplayableOptClockTime(some)), |
1511 | " +12:43:54.908" |
1512 | ); |
1513 | assert_eq!( |
1514 | format!(" {:015.3}" , DisplayableOptClockTime(some)), |
1515 | "00012:43:54.908" |
1516 | ); |
1517 | assert_eq!( |
1518 | format!(" {:+015.3}" , DisplayableOptClockTime(some)), |
1519 | "+0012:43:54.908" |
1520 | ); |
1521 | assert_eq!( |
1522 | format!(" {:+21}" , DisplayableOptClockTime(some)), |
1523 | " +12:43:54.908569837" |
1524 | ); |
1525 | assert_eq!( |
1526 | format!(" {:021}" , DisplayableOptClockTime(some)), |
1527 | "00012:43:54.908569837" |
1528 | ); |
1529 | assert_eq!( |
1530 | format!(" {:+021}" , DisplayableOptClockTime(some)), |
1531 | "+0012:43:54.908569837" |
1532 | ); |
1533 | |
1534 | assert_eq!(format!(" {lots:+16.0}" ), " +5124095:34:33" ); |
1535 | assert_eq!(format!(" {lots:016.0}" ), "0005124095:34:33" ); |
1536 | assert_eq!(format!(" {lots:+016.0}" ), "+005124095:34:33" ); |
1537 | assert_eq!(format!(" {lots:+20.3}" ), " +5124095:34:33.709" ); |
1538 | assert_eq!(format!(" {lots:020.3}" ), "0005124095:34:33.709" ); |
1539 | assert_eq!(format!(" {lots:+020.3}" ), "+005124095:34:33.709" ); |
1540 | assert_eq!(format!(" {lots:+26}" ), " +5124095:34:33.709551614" ); |
1541 | assert_eq!(format!(" {lots:026}" ), "0005124095:34:33.709551614" ); |
1542 | assert_eq!(format!(" {lots:+026}" ), "+005124095:34:33.709551614" ); |
1543 | } |
1544 | |
1545 | #[test ] |
1546 | fn iter_sum() { |
1547 | let s: ClockTime = vec![ClockTime::from_seconds(1), ClockTime::from_seconds(2)] |
1548 | .into_iter() |
1549 | .sum(); |
1550 | assert_eq!(s, ClockTime::from_seconds(3)); |
1551 | } |
1552 | |
1553 | #[test ] |
1554 | #[should_panic ] |
1555 | fn attempt_to_build_from_clock_time_none() { |
1556 | let _ = ClockTime::from_nseconds(ffi::GST_CLOCK_TIME_NONE); |
1557 | } |
1558 | |
1559 | #[test ] |
1560 | #[should_panic ] |
1561 | fn attempt_to_build_from_u64max() { |
1562 | let _ = ClockTime::from_nseconds(u64::MAX); |
1563 | } |
1564 | |
1565 | #[test ] |
1566 | fn try_into_signed() { |
1567 | let time = crate::Signed::Positive(ClockTime::from_nseconds(0)); |
1568 | assert_eq!(i64::try_from(time), Ok(0)); |
1569 | |
1570 | let time = crate::Signed::Positive(ClockTime::from_nseconds(123)); |
1571 | assert_eq!(i64::try_from(time), Ok(123)); |
1572 | |
1573 | let time = crate::Signed::Positive(ClockTime::from_nseconds(u64::MAX - 1)); |
1574 | assert!(i64::try_from(time).is_err()); |
1575 | |
1576 | let time = crate::Signed::Positive(ClockTime::from_nseconds(u64::MAX >> 1)); |
1577 | assert_eq!(i64::MAX as i128, (u64::MAX >> 1) as i128); |
1578 | assert_eq!(i64::try_from(time), Ok(i64::MAX)); |
1579 | |
1580 | let time = crate::Signed::Negative(ClockTime::from_nseconds(0)); |
1581 | assert_eq!(i64::try_from(time), Ok(0)); |
1582 | |
1583 | let time = crate::Signed::Negative(ClockTime::from_nseconds(123)); |
1584 | assert_eq!(i64::try_from(time), Ok(-123)); |
1585 | |
1586 | let time = crate::Signed::Negative(ClockTime::from_nseconds(u64::MAX - 1)); |
1587 | assert!(i64::try_from(time).is_err()); |
1588 | |
1589 | let time = crate::Signed::Negative(ClockTime::from_nseconds(u64::MAX >> 1)); |
1590 | assert_eq!(i64::MIN as i128 + 1, -((u64::MAX >> 1) as i128)); |
1591 | assert_eq!(i64::try_from(time), Ok(i64::MIN + 1)); |
1592 | |
1593 | let time = crate::Signed::Negative(ClockTime::from_nseconds((u64::MAX >> 1) + 1)); |
1594 | assert_eq!(i64::MIN as i128, -(((u64::MAX >> 1) + 1) as i128)); |
1595 | assert_eq!(i64::try_from(time), Ok(i64::MIN)); |
1596 | } |
1597 | |
1598 | #[test ] |
1599 | fn properties_macro_usage() { |
1600 | use super::ClockTime; |
1601 | use glib::{prelude::*, subclass::prelude::*}; |
1602 | use std::cell::Cell; |
1603 | |
1604 | #[derive (Default, glib::Properties)] |
1605 | #[properties(wrapper_type = TestObject)] |
1606 | pub struct TestObjectImp { |
1607 | #[property(get, set)] |
1608 | clock_time: Cell<ClockTime>, |
1609 | #[property(get, set)] |
1610 | optional_clock_time: Cell<Option<ClockTime>>, |
1611 | } |
1612 | |
1613 | #[glib::object_subclass ] |
1614 | impl ObjectSubclass for TestObjectImp { |
1615 | const NAME: &'static str = "GstTestObject" ; |
1616 | type Type = TestObject; |
1617 | } |
1618 | |
1619 | impl ObjectImpl for TestObjectImp { |
1620 | fn properties() -> &'static [glib::ParamSpec] { |
1621 | Self::derived_properties() |
1622 | } |
1623 | |
1624 | fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { |
1625 | self.derived_set_property(id, value, pspec); |
1626 | } |
1627 | |
1628 | fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { |
1629 | self.derived_property(id, pspec) |
1630 | } |
1631 | } |
1632 | |
1633 | glib::wrapper! { |
1634 | pub struct TestObject(ObjectSubclass<TestObjectImp>); |
1635 | } |
1636 | |
1637 | let obj: TestObject = glib::Object::new(); |
1638 | |
1639 | assert_eq!(obj.clock_time(), ClockTime::default()); |
1640 | obj.set_clock_time(ClockTime::MAX); |
1641 | assert_eq!(obj.clock_time(), ClockTime::MAX); |
1642 | |
1643 | assert_eq!(obj.optional_clock_time(), None); |
1644 | obj.set_optional_clock_time(ClockTime::MAX); |
1645 | assert_eq!(obj.optional_clock_time(), Some(ClockTime::MAX)); |
1646 | } |
1647 | |
1648 | #[test ] |
1649 | fn seconds_float() { |
1650 | let res = ClockTime::ZERO; |
1651 | assert_eq!(res.seconds_f32(), 0.0); |
1652 | assert_eq!(res.seconds_f64(), 0.0); |
1653 | |
1654 | let res = ClockTime::from_nseconds(2_700_000_000); |
1655 | assert_eq!(res.seconds_f32(), 2.7); |
1656 | assert_eq!(res.seconds_f64(), 2.7); |
1657 | |
1658 | let res = ClockTime::MAX; |
1659 | assert_eq!(res.seconds_f32(), 18_446_744_073.709_553); |
1660 | assert_eq!(res.seconds_f64(), 18_446_744_073.709_553); |
1661 | } |
1662 | |
1663 | #[test ] |
1664 | fn seconds_float_signed() { |
1665 | let pos = Signed::Positive(ClockTime::ZERO); |
1666 | assert_eq!(pos.seconds_f32(), 0.0); |
1667 | assert_eq!(pos.seconds_f64(), 0.0); |
1668 | let neg = Signed::Negative(ClockTime::ZERO); |
1669 | assert_eq!(neg.seconds_f32(), 0.0); |
1670 | assert_eq!(neg.seconds_f64(), 0.0); |
1671 | |
1672 | let pos = Signed::Positive(ClockTime::from_nseconds(2_700_000_000)); |
1673 | assert_eq!(pos.seconds_f32(), 2.7); |
1674 | assert_eq!(pos.seconds_f64(), 2.7); |
1675 | let neg = Signed::Negative(ClockTime::from_nseconds(2_700_000_000)); |
1676 | assert_eq!(neg.seconds_f32(), -2.7); |
1677 | assert_eq!(neg.seconds_f64(), -2.7); |
1678 | |
1679 | let pos = Signed::Positive(ClockTime::MAX); |
1680 | assert_eq!(pos.seconds_f32(), 18_446_744_073.709_553); |
1681 | assert_eq!(pos.seconds_f64(), 18_446_744_073.709_553); |
1682 | let neg = Signed::Negative(ClockTime::MAX); |
1683 | assert_eq!(neg.seconds_f32(), -18_446_744_073.709_553); |
1684 | assert_eq!(neg.seconds_f64(), -18_446_744_073.709_553); |
1685 | } |
1686 | |
1687 | #[test ] |
1688 | fn try_from_seconds_f32() { |
1689 | let res = ClockTime::try_from_seconds_f32(0.0); |
1690 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1691 | let res = ClockTime::try_from_seconds_f32(1e-20); |
1692 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1693 | let res = ClockTime::try_from_seconds_f32(4.2e-7); |
1694 | assert_eq!(res, Ok(ClockTime::from_nseconds(420))); |
1695 | let res = ClockTime::try_from_seconds_f32(2.7); |
1696 | assert_eq!(res, Ok(ClockTime::from_nseconds(2_700_000_048))); |
1697 | // subnormal float: |
1698 | let res = ClockTime::try_from_seconds_f32(f32::from_bits(1)); |
1699 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1700 | |
1701 | // the conversion uses rounding with tie resolution to even |
1702 | let res = ClockTime::try_from_seconds_f32(0.999e-9); |
1703 | assert_eq!(res, Ok(ClockTime::from_nseconds(1))); |
1704 | |
1705 | let res = ClockTime::try_from_seconds_f32(-5.0); |
1706 | assert!(res.is_err()); |
1707 | let res = ClockTime::try_from_seconds_f32(f32::NAN); |
1708 | assert!(res.is_err()); |
1709 | let res = ClockTime::try_from_seconds_f32(2e19); |
1710 | assert!(res.is_err()); |
1711 | |
1712 | // this float represents exactly 976562.5e-9 |
1713 | let val = f32::from_bits(0x3A80_0000); |
1714 | let res = ClockTime::try_from_seconds_f32(val); |
1715 | assert_eq!(res, Ok(ClockTime::from_nseconds(976_562))); |
1716 | |
1717 | // this float represents exactly 2929687.5e-9 |
1718 | let val = f32::from_bits(0x3B40_0000); |
1719 | let res = ClockTime::try_from_seconds_f32(val); |
1720 | assert_eq!(res, Ok(ClockTime::from_nseconds(2_929_688))); |
1721 | |
1722 | // this float represents exactly 1.000_976_562_5 |
1723 | let val = f32::from_bits(0x3F802000); |
1724 | let res = ClockTime::try_from_seconds_f32(val); |
1725 | assert_eq!(res, Ok(ClockTime::from_nseconds(1_000_976_562))); |
1726 | |
1727 | // this float represents exactly 1.002_929_687_5 |
1728 | let val = f32::from_bits(0x3F806000); |
1729 | let res = ClockTime::try_from_seconds_f32(val); |
1730 | assert_eq!(res, Ok(ClockTime::from_nseconds(1_002_929_688))); |
1731 | } |
1732 | |
1733 | #[test ] |
1734 | fn try_from_seconds_f64() { |
1735 | let res = ClockTime::try_from_seconds_f64(0.0); |
1736 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1737 | let res = ClockTime::try_from_seconds_f64(1e-20); |
1738 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1739 | let res = ClockTime::try_from_seconds_f64(4.2e-7); |
1740 | assert_eq!(res, Ok(ClockTime::from_nseconds(420))); |
1741 | let res = ClockTime::try_from_seconds_f64(2.7); |
1742 | assert_eq!(res, Ok(ClockTime::from_nseconds(2_700_000_000))); |
1743 | // subnormal float: |
1744 | let res = ClockTime::try_from_seconds_f64(f64::from_bits(1)); |
1745 | assert_eq!(res, Ok(ClockTime::ZERO)); |
1746 | |
1747 | // the conversion uses rounding with tie resolution to even |
1748 | let res = ClockTime::try_from_seconds_f64(0.999e-9); |
1749 | assert_eq!(res, Ok(ClockTime::from_nseconds(1))); |
1750 | let res = ClockTime::try_from_seconds_f64(0.999_999_999_499); |
1751 | assert_eq!(res, Ok(ClockTime::from_nseconds(999_999_999))); |
1752 | let res = ClockTime::try_from_seconds_f64(0.999_999_999_501); |
1753 | assert_eq!(res, Ok(ClockTime::from_seconds(1))); |
1754 | let res = ClockTime::try_from_seconds_f64(42.999_999_999_499); |
1755 | assert_eq!(res, Ok(ClockTime::from_nseconds(42_999_999_999))); |
1756 | let res = ClockTime::try_from_seconds_f64(42.999_999_999_501); |
1757 | assert_eq!(res, Ok(ClockTime::from_seconds(43))); |
1758 | |
1759 | let res = ClockTime::try_from_seconds_f64(-5.0); |
1760 | assert!(res.is_err()); |
1761 | let res = ClockTime::try_from_seconds_f64(f64::NAN); |
1762 | assert!(res.is_err()); |
1763 | let res = ClockTime::try_from_seconds_f64(2e19); |
1764 | assert!(res.is_err()); |
1765 | |
1766 | // this float represents exactly 976562.5e-9 |
1767 | let val = f64::from_bits(0x3F50_0000_0000_0000); |
1768 | let res = ClockTime::try_from_seconds_f64(val); |
1769 | assert_eq!(res, Ok(ClockTime::from_nseconds(976_562))); |
1770 | |
1771 | // this float represents exactly 2929687.5e-9 |
1772 | let val = f64::from_bits(0x3F68_0000_0000_0000); |
1773 | let res = ClockTime::try_from_seconds_f64(val); |
1774 | assert_eq!(res, Ok(ClockTime::from_nseconds(2_929_688))); |
1775 | |
1776 | // this float represents exactly 1.000_976_562_5 |
1777 | let val = f64::from_bits(0x3FF0_0400_0000_0000); |
1778 | let res = ClockTime::try_from_seconds_f64(val); |
1779 | assert_eq!(res, Ok(ClockTime::from_nseconds(1_000_976_562))); |
1780 | |
1781 | // this float represents exactly 1.002_929_687_5 |
1782 | let val = f64::from_bits(0x3FF0_0C00_0000_0000); |
1783 | let res = ClockTime::try_from_seconds_f64(val); |
1784 | assert_eq!(res, Ok(ClockTime::from_nseconds(1_002_929_688))); |
1785 | } |
1786 | |
1787 | #[test ] |
1788 | fn try_from_seconds_f32_signed() { |
1789 | let pos = Signed::<ClockTime>::from_seconds_f32(5.0); |
1790 | assert!(pos.is_positive()); |
1791 | |
1792 | let neg = Signed::<ClockTime>::from_seconds_f32(-5.0); |
1793 | assert!(neg.is_negative()); |
1794 | } |
1795 | |
1796 | #[test ] |
1797 | fn try_from_seconds_f64_signed() { |
1798 | let pos = Signed::<ClockTime>::from_seconds_f64(5.0); |
1799 | assert!(pos.is_positive()); |
1800 | |
1801 | let neg = Signed::<ClockTime>::from_seconds_f64(-5.0); |
1802 | assert!(neg.is_negative()); |
1803 | } |
1804 | |
1805 | #[test ] |
1806 | fn absdiff() { |
1807 | let t1 = ClockTime::from_seconds(10); |
1808 | let t2 = ClockTime::from_seconds(4); |
1809 | |
1810 | let d = ClockTime::from_seconds(6); |
1811 | |
1812 | assert_eq!(t1.absdiff(t2), d); |
1813 | assert_eq!(t2.absdiff(t1), d); |
1814 | } |
1815 | } |
1816 | |