Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to own TimeOffset time to deal with signed offset. #1

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ pub mod unix;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Timestamp {
pub seconds: libc::time_t,
/// Nanos must be between 0 and 999999999 inclusive
pub nanos: u32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct TimeOffset {
pub seconds: libc::time_t,
/// Nanos must be between 0 and 999999999 inclusive
pub nanos: u32,
pub subnanos: u32,
}

/// Indicate whether a leap second must be applied
Expand Down Expand Up @@ -56,7 +63,7 @@ pub trait Clock {

/// Change the current time of the clock by an offset.
/// Returns the time at which the change was applied.
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error>;
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error>;

/// Change the indicators for upcoming leap seconds.
fn set_leap_seconds(&self, leap_status: LeapIndicator) -> Result<(), Self::Error>;
Expand Down
40 changes: 19 additions & 21 deletions src/unix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Clock, LeapIndicator, Timestamp};
use crate::{Clock, LeapIndicator, TimeOffset, Timestamp};
use std::{
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
path::Path,
Expand Down Expand Up @@ -157,17 +157,14 @@ impl UnixClock {
}

#[cfg_attr(target_os = "linux", allow(unused))]
fn step_clock_by_timespec(&self, offset: Duration) -> Result<Timestamp, Error> {
let offset_secs = offset.as_secs();
let offset_nanos = offset.subsec_nanos();

fn step_clock_by_timespec(&self, offset: TimeOffset) -> Result<Timestamp, Error> {
let mut timespec = self.clock_gettime()?;

// see https://github.com/rust-lang/libc/issues/1848
#[cfg_attr(target_env = "musl", allow(deprecated))]
{
timespec.tv_sec += offset_secs as libc::time_t;
timespec.tv_nsec += offset_nanos as libc::c_long;
timespec.tv_sec += offset.seconds as libc::time_t;
timespec.tv_nsec += offset.nanos as libc::c_long;
}

self.clock_settime(timespec)?;
Expand All @@ -191,13 +188,13 @@ impl UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock_timex(offset: Duration) -> libc::timex {
fn step_clock_timex(offset: TimeOffset) -> libc::timex {
// we provide the offset in nanoseconds
let modes = libc::ADJ_SETOFFSET | libc::ADJ_NANO;

let time = libc::timeval {
tv_sec: offset.as_secs() as _,
tv_usec: offset.subsec_nanos() as libc::suseconds_t,
tv_sec: offset.seconds,
tv_usec: offset.nanos as libc::suseconds_t,
};

libc::timex {
Expand All @@ -208,7 +205,7 @@ impl UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock_by_timex(&self, offset: Duration) -> Result<Timestamp, Error> {
fn step_clock_by_timex(&self, offset: TimeOffset) -> Result<Timestamp, Error> {
let mut timex = Self::step_clock_timex(offset);
self.adjtime(&mut timex)?;
self.extract_current_time(&timex)
Expand Down Expand Up @@ -378,12 +375,12 @@ impl Clock for UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error> {
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error> {
self.step_clock_by_timex(offset)
}

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error> {
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error> {
self.step_clock_by_timespec(offset)
}

Expand Down Expand Up @@ -537,7 +534,6 @@ fn current_time_timespec(timespec: libc::timespec, precision: Precision) -> Time
Timestamp {
seconds,
nanos: nanos as u32,
subnanos: 0,
}
}

Expand All @@ -551,11 +547,7 @@ fn current_time_timeval(timespec: libc::timeval, precision: Precision) -> Timest
.unwrap_or_default(),
};

Timestamp {
seconds,
nanos,
subnanos: 0,
}
Timestamp { seconds, nanos }
}

const EMPTY_TIMESPEC: libc::timespec = libc::timespec {
Expand Down Expand Up @@ -694,7 +686,10 @@ mod tests {
#[ignore = "requires permissions, useful for testing permissions"]
fn step_clock() {
UnixClock::CLOCK_REALTIME
.step_clock(Duration::new(0, 0))
.step_clock(TimeOffset {
seconds: 0,
nanos: 0,
})
.unwrap();
}

Expand Down Expand Up @@ -743,7 +738,10 @@ mod tests {
#[cfg(target_os = "linux")]
#[test]
fn test_step_clock() {
let offset = Duration::from_secs_f64(1.2);
let offset = TimeOffset {
seconds: 1,
nanos: 200000000,
};
let timex = UnixClock::step_clock_timex(offset);

assert_eq!(timex.modes, libc::ADJ_SETOFFSET | libc::ADJ_NANO);
Expand Down
Loading