124 pub(super) struct Timestamp { |
124 pub(super) struct Timestamp { |
125 seconds: I64Be, |
125 seconds: I64Be, |
126 |
126 |
127 /// In `0 .. 1_000_000_000`. |
127 /// In `0 .. 1_000_000_000`. |
128 /// |
128 /// |
129 /// This timestamp is later or earlier than `(seconds, 0)` by this many |
129 /// This timestamp is after `(seconds, 0)` by this many nanoseconds. |
130 /// nanoseconds, if `seconds` is non-negative or negative, respectively. |
|
131 nanoseconds: U32Be, |
130 nanoseconds: U32Be, |
132 } |
131 } |
133 |
132 |
134 /// Counted in bytes from the start of the file |
133 /// Counted in bytes from the start of the file |
135 /// |
134 /// |
444 } |
443 } |
445 } |
444 } |
446 |
445 |
447 impl From<SystemTime> for Timestamp { |
446 impl From<SystemTime> for Timestamp { |
448 fn from(system_time: SystemTime) -> Self { |
447 fn from(system_time: SystemTime) -> Self { |
|
448 // On Unix, `SystemTime` is a wrapper for the `timespec` C struct: |
|
449 // https://www.gnu.org/software/libc/manual/html_node/Time-Types.html#index-struct-timespec |
|
450 // We want to effectively access its fields, but the Rust standard |
|
451 // library does not expose them. The best we can do is: |
449 let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) { |
452 let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) { |
450 Ok(duration) => { |
453 Ok(duration) => { |
451 (duration.as_secs() as i64, duration.subsec_nanos()) |
454 (duration.as_secs() as i64, duration.subsec_nanos()) |
452 } |
455 } |
453 Err(error) => { |
456 Err(error) => { |
|
457 // `system_time` is before `UNIX_EPOCH`. |
|
458 // We need to undo this algorithm: |
|
459 // https://github.com/rust-lang/rust/blob/6bed1f0bc3cc50c10aab26d5f94b16a00776b8a5/library/std/src/sys/unix/time.rs#L40-L41 |
454 let negative = error.duration(); |
460 let negative = error.duration(); |
455 (-(negative.as_secs() as i64), negative.subsec_nanos()) |
461 let negative_secs = negative.as_secs() as i64; |
|
462 let negative_nanos = negative.subsec_nanos(); |
|
463 if negative_nanos == 0 { |
|
464 (-negative_secs, 0) |
|
465 } else { |
|
466 // For example if `system_time` was 4.3 seconds before |
|
467 // the Unix epoch we get a Duration that represents |
|
468 // `(-4, -0.3)` but we want `(-5, +0.7)`: |
|
469 const NSEC_PER_SEC: u32 = 1_000_000_000; |
|
470 (-1 - negative_secs, NSEC_PER_SEC - negative_nanos) |
|
471 } |
456 } |
472 } |
457 }; |
473 }; |
458 Timestamp { |
474 Timestamp { |
459 seconds: secs.into(), |
475 seconds: secs.into(), |
460 nanoseconds: nanos.into(), |
476 nanoseconds: nanos.into(), |