Ronald Kinard
8 years ago
committed by
GitHub
5 changed files with 1215 additions and 2 deletions
@ -0,0 +1,270 @@
@@ -0,0 +1,270 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use cmp::Ordering; |
||||
use libc; |
||||
use time::Duration; |
||||
|
||||
pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; |
||||
|
||||
const NSEC_PER_SEC: u64 = 1_000_000_000; |
||||
|
||||
#[derive(Copy, Clone)] |
||||
struct Timespec { |
||||
t: libc::timespec, |
||||
} |
||||
|
||||
impl Timespec { |
||||
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { |
||||
if self >= other { |
||||
Ok(if self.t.tv_nsec >= other.t.tv_nsec { |
||||
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, |
||||
(self.t.tv_nsec - other.t.tv_nsec) as u32) |
||||
} else { |
||||
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, |
||||
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - |
||||
other.t.tv_nsec as u32) |
||||
}) |
||||
} else { |
||||
match other.sub_timespec(self) { |
||||
Ok(d) => Err(d), |
||||
Err(d) => Ok(d), |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn add_duration(&self, other: &Duration) -> Timespec { |
||||
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); |
||||
let mut secs = secs.expect("overflow when adding duration to time"); |
||||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
// in a u32.
|
||||
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; |
||||
if nsec >= NSEC_PER_SEC as u32 { |
||||
nsec -= NSEC_PER_SEC as u32; |
||||
secs = secs.checked_add(1).expect("overflow when adding \ |
||||
duration to time"); |
||||
} |
||||
Timespec { |
||||
t: libc::timespec { |
||||
tv_sec: secs as libc::time_t, |
||||
tv_nsec: nsec as libc::c_long, |
||||
}, |
||||
} |
||||
} |
||||
|
||||
fn sub_duration(&self, other: &Duration) -> Timespec { |
||||
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); |
||||
let mut secs = secs.expect("overflow when subtracting duration \ |
||||
from time"); |
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; |
||||
if nsec < 0 { |
||||
nsec += NSEC_PER_SEC as i32; |
||||
secs = secs.checked_sub(1).expect("overflow when subtracting \ |
||||
duration from time"); |
||||
} |
||||
Timespec { |
||||
t: libc::timespec { |
||||
tv_sec: secs as libc::time_t, |
||||
tv_nsec: nsec as libc::c_long, |
||||
}, |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl PartialEq for Timespec { |
||||
fn eq(&self, other: &Timespec) -> bool { |
||||
self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec |
||||
} |
||||
} |
||||
|
||||
impl Eq for Timespec {} |
||||
|
||||
impl PartialOrd for Timespec { |
||||
fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> { |
||||
Some(self.cmp(other)) |
||||
} |
||||
} |
||||
|
||||
impl Ord for Timespec { |
||||
fn cmp(&self, other: &Timespec) -> Ordering { |
||||
let me = (self.t.tv_sec, self.t.tv_nsec); |
||||
let other = (other.t.tv_sec, other.t.tv_nsec); |
||||
me.cmp(&other) |
||||
} |
||||
} |
||||
|
||||
mod inner { |
||||
use fmt; |
||||
use libc; |
||||
use sys::cvt; |
||||
use sys_common::mul_div_u64; |
||||
use time::Duration; |
||||
|
||||
use super::NSEC_PER_SEC; |
||||
use super::Timespec; |
||||
|
||||
use spin; |
||||
use libctru; |
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] |
||||
pub struct Instant { |
||||
t: u64 |
||||
} |
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||
pub struct SystemTime { |
||||
t: Timespec, |
||||
} |
||||
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime { |
||||
t: Timespec { |
||||
t: libc::timespec { |
||||
tv_sec: 0, |
||||
tv_nsec: 0, |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
impl Instant { |
||||
pub fn now() -> Instant { |
||||
Instant { t: ctr_absolute_time() } |
||||
} |
||||
|
||||
pub fn sub_instant(&self, other: &Instant) -> Duration { |
||||
let info = info(); |
||||
let diff = self.t.checked_sub(other.t) |
||||
.expect("second instant is later than self"); |
||||
let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64); |
||||
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32) |
||||
} |
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant { |
||||
Instant { |
||||
t: self.t.checked_add(dur2intervals(other)) |
||||
.expect("overflow when adding duration to instant"), |
||||
} |
||||
} |
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant { |
||||
Instant { |
||||
t: self.t.checked_sub(dur2intervals(other)) |
||||
.expect("overflow when adding duration to instant"), |
||||
} |
||||
} |
||||
} |
||||
|
||||
// The initial system tick after which all Instants occur
|
||||
static TICK: spin::Once<u64> = spin::Once::new(); |
||||
|
||||
// A source of monotonic time based on ticks of the 3DS CPU. Returns the
|
||||
// number of system ticks elapsed since an arbitrary point in the past
|
||||
fn ctr_absolute_time() -> u64 { |
||||
let first_tick = get_first_tick(); |
||||
let current_tick = get_system_tick(); |
||||
current_tick - first_tick |
||||
} |
||||
|
||||
// The first time this function is called, it generates and returns the
|
||||
// initial system tick used to create Instants
|
||||
//
|
||||
// subsequent calls to this function return the previously generated
|
||||
// tick value
|
||||
fn get_first_tick() -> u64 { |
||||
*TICK.call_once(get_system_tick) |
||||
} |
||||
|
||||
// Gets the current system tick
|
||||
#[inline] |
||||
fn get_system_tick() -> u64 { |
||||
unsafe { libctru::svc::svcGetSystemTick() } |
||||
} |
||||
|
||||
// A struct representing the clock speed of the 3DS
|
||||
struct CtrClockInfo { |
||||
numer: u32, |
||||
denom: u32, |
||||
} |
||||
|
||||
// Initializes the CtrClockInfo struct
|
||||
//
|
||||
// Note that svcGetSystemTick always runs at 268MHz (268,111,856Hz), even
|
||||
// on a New 3DS running in 804MHz mode
|
||||
//
|
||||
// See https://www.3dbrew.org/wiki/Hardware#Common_hardware
|
||||
fn info() -> CtrClockInfo { |
||||
CtrClockInfo { |
||||
numer: 1_000_000_000, |
||||
denom: 268_111_856, |
||||
} |
||||
} |
||||
|
||||
fn dur2intervals(dur: &Duration) -> u64 { |
||||
let info = info(); |
||||
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { |
||||
nanos.checked_add(dur.subsec_nanos() as u64) |
||||
}).expect("overflow converting duration to nanoseconds"); |
||||
mul_div_u64(nanos, info.denom as u64, info.numer as u64) |
||||
} |
||||
|
||||
impl SystemTime { |
||||
pub fn now() -> SystemTime { |
||||
use ptr; |
||||
|
||||
let mut s = libc::timeval { |
||||
tv_sec: 0, |
||||
tv_usec: 0, |
||||
}; |
||||
cvt(unsafe { |
||||
libc::gettimeofday(&mut s, ptr::null_mut()) |
||||
}).unwrap(); |
||||
return SystemTime::from(s) |
||||
} |
||||
|
||||
pub fn sub_time(&self, other: &SystemTime) |
||||
-> Result<Duration, Duration> { |
||||
self.t.sub_timespec(&other.t) |
||||
} |
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime { |
||||
SystemTime { t: self.t.add_duration(other) } |
||||
} |
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime { |
||||
SystemTime { t: self.t.sub_duration(other) } |
||||
} |
||||
} |
||||
|
||||
impl From<libc::timeval> for SystemTime { |
||||
fn from(t: libc::timeval) -> SystemTime { |
||||
SystemTime::from(libc::timespec { |
||||
tv_sec: t.tv_sec, |
||||
tv_nsec: (t.tv_usec * 1000) as libc::c_long, |
||||
}) |
||||
} |
||||
} |
||||
|
||||
impl From<libc::timespec> for SystemTime { |
||||
fn from(t: libc::timespec) -> SystemTime { |
||||
SystemTime { t: Timespec { t: t } } |
||||
} |
||||
} |
||||
|
||||
impl fmt::Debug for SystemTime { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
f.debug_struct("SystemTime") |
||||
.field("tv_sec", &self.t.t.tv_sec) |
||||
.field("tv_nsec", &self.t.t.tv_nsec) |
||||
.finish() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,420 @@
@@ -0,0 +1,420 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; |
||||
|
||||
const NANOS_PER_SEC: u32 = 1_000_000_000; |
||||
const NANOS_PER_MILLI: u32 = 1_000_000; |
||||
const MILLIS_PER_SEC: u64 = 1_000; |
||||
|
||||
/// A duration type to represent a span of time, typically used for system
|
||||
/// timeouts.
|
||||
///
|
||||
/// Each duration is composed of a number of seconds and nanosecond precision.
|
||||
/// APIs binding a system timeout will typically round up the nanosecond
|
||||
/// precision if the underlying system does not support that level of precision.
|
||||
///
|
||||
/// Durations implement many common traits, including `Add`, `Sub`, and other
|
||||
/// ops traits. Currently a duration may only be inspected for its number of
|
||||
/// seconds and its nanosecond precision.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let five_seconds = Duration::new(5, 0);
|
||||
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
|
||||
///
|
||||
/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
|
||||
/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
|
||||
///
|
||||
/// let ten_millis = Duration::from_millis(10);
|
||||
/// ```
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] |
||||
pub struct Duration { |
||||
secs: u64, |
||||
nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
|
||||
} |
||||
|
||||
impl Duration { |
||||
/// Creates a new `Duration` from the specified number of seconds and
|
||||
/// additional nanosecond precision.
|
||||
///
|
||||
/// If the nanoseconds is greater than 1 billion (the number of nanoseconds
|
||||
/// in a second), then it will carry over into the seconds provided.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This constructor will panic if the carry from the nanoseconds overflows
|
||||
/// the seconds counter.
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[inline] |
||||
pub fn new(secs: u64, nanos: u32) -> Duration { |
||||
let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) |
||||
.expect("overflow in Duration::new"); |
||||
let nanos = nanos % NANOS_PER_SEC; |
||||
Duration { secs: secs, nanos: nanos } |
||||
} |
||||
|
||||
/// Creates a new `Duration` from the specified number of seconds.
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[inline] |
||||
pub fn from_secs(secs: u64) -> Duration { |
||||
Duration { secs: secs, nanos: 0 } |
||||
} |
||||
|
||||
/// Creates a new `Duration` from the specified number of milliseconds.
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[inline] |
||||
pub fn from_millis(millis: u64) -> Duration { |
||||
let secs = millis / MILLIS_PER_SEC; |
||||
let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI; |
||||
Duration { secs: secs, nanos: nanos } |
||||
} |
||||
|
||||
/// Returns the number of whole seconds represented by this duration.
|
||||
///
|
||||
/// The extra precision represented by this duration is ignored (i.e. extra
|
||||
/// nanoseconds are not represented in the returned value).
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[inline] |
||||
pub fn as_secs(&self) -> u64 { self.secs } |
||||
|
||||
/// Returns the nanosecond precision represented by this duration.
|
||||
///
|
||||
/// This method does **not** return the length of the duration when
|
||||
/// represented by nanoseconds. The returned number always represents a
|
||||
/// fractional portion of a second (i.e. it is less than one billion).
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
#[inline] |
||||
pub fn subsec_nanos(&self) -> u32 { self.nanos } |
||||
|
||||
/// Checked duration addition. Computes `self + other`, returning `None`
|
||||
/// if overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_checked_ops)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
|
||||
/// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||
#[inline] |
||||
pub fn checked_add(self, rhs: Duration) -> Option<Duration> { |
||||
if let Some(mut secs) = self.secs.checked_add(rhs.secs) { |
||||
let mut nanos = self.nanos + rhs.nanos; |
||||
if nanos >= NANOS_PER_SEC { |
||||
nanos -= NANOS_PER_SEC; |
||||
if let Some(new_secs) = secs.checked_add(1) { |
||||
secs = new_secs; |
||||
} else { |
||||
return None; |
||||
} |
||||
} |
||||
debug_assert!(nanos < NANOS_PER_SEC); |
||||
Some(Duration { |
||||
secs: secs, |
||||
nanos: nanos, |
||||
}) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
|
||||
/// Checked duration subtraction. Computes `self + other`, returning `None`
|
||||
/// if the result would be negative or if underflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_checked_ops)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
|
||||
/// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||
#[inline] |
||||
pub fn checked_sub(self, rhs: Duration) -> Option<Duration> { |
||||
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { |
||||
let nanos = if self.nanos >= rhs.nanos { |
||||
self.nanos - rhs.nanos |
||||
} else { |
||||
if let Some(sub_secs) = secs.checked_sub(1) { |
||||
secs = sub_secs; |
||||
self.nanos + NANOS_PER_SEC - rhs.nanos |
||||
} else { |
||||
return None; |
||||
} |
||||
}; |
||||
debug_assert!(nanos < NANOS_PER_SEC); |
||||
Some(Duration { secs: secs, nanos: nanos }) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
|
||||
/// Checked duration multiplication. Computes `self * other`, returning
|
||||
/// `None` if underflow or overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_checked_ops)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
|
||||
/// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||
#[inline] |
||||
pub fn checked_mul(self, rhs: u32) -> Option<Duration> { |
||||
// Multiply nanoseconds as u64, because it cannot overflow that way.
|
||||
let total_nanos = self.nanos as u64 * rhs as u64; |
||||
let extra_secs = total_nanos / (NANOS_PER_SEC as u64); |
||||
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; |
||||
if let Some(secs) = self.secs |
||||
.checked_mul(rhs as u64) |
||||
.and_then(|s| s.checked_add(extra_secs)) { |
||||
debug_assert!(nanos < NANOS_PER_SEC); |
||||
Some(Duration { |
||||
secs: secs, |
||||
nanos: nanos, |
||||
}) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
|
||||
/// Checked duration division. Computes `self / other`, returning `None`
|
||||
/// if `other == 0` or the operation results in underflow or overflow.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_checked_ops)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
|
||||
/// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
|
||||
/// assert_eq!(Duration::new(2, 0).checked_div(0), None);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||
#[inline] |
||||
pub fn checked_div(self, rhs: u32) -> Option<Duration> { |
||||
if rhs != 0 { |
||||
let secs = self.secs / (rhs as u64); |
||||
let carry = self.secs - secs * (rhs as u64); |
||||
let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); |
||||
let nanos = self.nanos / rhs + (extra_nanos as u32); |
||||
debug_assert!(nanos < NANOS_PER_SEC); |
||||
Some(Duration { secs: secs, nanos: nanos }) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
impl Add for Duration { |
||||
type Output = Duration; |
||||
|
||||
fn add(self, rhs: Duration) -> Duration { |
||||
self.checked_add(rhs).expect("overflow when adding durations") |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl AddAssign for Duration { |
||||
fn add_assign(&mut self, rhs: Duration) { |
||||
*self = *self + rhs; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
impl Sub for Duration { |
||||
type Output = Duration; |
||||
|
||||
fn sub(self, rhs: Duration) -> Duration { |
||||
self.checked_sub(rhs).expect("overflow when subtracting durations") |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl SubAssign for Duration { |
||||
fn sub_assign(&mut self, rhs: Duration) { |
||||
*self = *self - rhs; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
impl Mul<u32> for Duration { |
||||
type Output = Duration; |
||||
|
||||
fn mul(self, rhs: u32) -> Duration { |
||||
self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl MulAssign<u32> for Duration { |
||||
fn mul_assign(&mut self, rhs: u32) { |
||||
*self = *self * rhs; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "duration", since = "1.3.0")] |
||||
impl Div<u32> for Duration { |
||||
type Output = Duration; |
||||
|
||||
fn div(self, rhs: u32) -> Duration { |
||||
self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl DivAssign<u32> for Duration { |
||||
fn div_assign(&mut self, rhs: u32) { |
||||
*self = *self / rhs; |
||||
} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use super::Duration; |
||||
|
||||
#[test] |
||||
fn creation() { |
||||
assert!(Duration::from_secs(1) != Duration::from_secs(0)); |
||||
assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), |
||||
Duration::from_secs(3)); |
||||
assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), |
||||
Duration::new(4, 10 * 1_000_000)); |
||||
assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); |
||||
} |
||||
|
||||
#[test] |
||||
fn secs() { |
||||
assert_eq!(Duration::new(0, 0).as_secs(), 0); |
||||
assert_eq!(Duration::from_secs(1).as_secs(), 1); |
||||
assert_eq!(Duration::from_millis(999).as_secs(), 0); |
||||
assert_eq!(Duration::from_millis(1001).as_secs(), 1); |
||||
} |
||||
|
||||
#[test] |
||||
fn nanos() { |
||||
assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); |
||||
assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); |
||||
assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); |
||||
assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); |
||||
assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); |
||||
assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); |
||||
} |
||||
|
||||
#[test] |
||||
fn add() { |
||||
assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), |
||||
Duration::new(0, 1)); |
||||
assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), |
||||
Duration::new(1, 1)); |
||||
} |
||||
|
||||
#[test] |
||||
fn checked_add() { |
||||
assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), |
||||
Some(Duration::new(0, 1))); |
||||
assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), |
||||
Some(Duration::new(1, 1))); |
||||
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn sub() { |
||||
assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), |
||||
Duration::new(0, 1)); |
||||
assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), |
||||
Duration::new(0, 1)); |
||||
assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), |
||||
Duration::new(0, 999_999_999)); |
||||
} |
||||
|
||||
#[test] |
||||
fn checked_sub() { |
||||
let zero = Duration::new(0, 0); |
||||
let one_nano = Duration::new(0, 1); |
||||
let one_sec = Duration::new(1, 0); |
||||
assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); |
||||
assert_eq!(one_sec.checked_sub(one_nano), |
||||
Some(Duration::new(0, 999_999_999))); |
||||
assert_eq!(zero.checked_sub(one_nano), None); |
||||
assert_eq!(zero.checked_sub(one_sec), None); |
||||
} |
||||
|
||||
#[test] #[should_panic] |
||||
fn sub_bad1() { |
||||
Duration::new(0, 0) - Duration::new(0, 1); |
||||
} |
||||
|
||||
#[test] #[should_panic] |
||||
fn sub_bad2() { |
||||
Duration::new(0, 0) - Duration::new(1, 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn mul() { |
||||
assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); |
||||
assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); |
||||
assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); |
||||
assert_eq!(Duration::new(0, 500_000_001) * 4000, |
||||
Duration::new(2000, 4000)); |
||||
} |
||||
|
||||
#[test] |
||||
fn checked_mul() { |
||||
assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); |
||||
assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); |
||||
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); |
||||
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), |
||||
Some(Duration::new(2000, 4000))); |
||||
assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn div() { |
||||
assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); |
||||
assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); |
||||
assert_eq!(Duration::new(99, 999_999_000) / 100, |
||||
Duration::new(0, 999_999_990)); |
||||
} |
||||
|
||||
#[test] |
||||
fn checked_div() { |
||||
assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); |
||||
assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); |
||||
assert_eq!(Duration::new(2, 0).checked_div(0), None); |
||||
} |
||||
} |
@ -0,0 +1,447 @@
@@ -0,0 +1,447 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Temporal quantification.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```
|
||||
//! use std::time::Duration;
|
||||
//!
|
||||
//! let five_seconds = Duration::new(5, 0);
|
||||
//! // both declarations are equivalent
|
||||
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "time", since = "1.3.0")] |
||||
|
||||
use error::Error; |
||||
use fmt; |
||||
use ops::{Add, Sub, AddAssign, SubAssign}; |
||||
use sys::time; |
||||
use sys_common::FromInner; |
||||
|
||||
#[stable(feature = "time", since = "1.3.0")] |
||||
pub use self::duration::Duration; |
||||
|
||||
mod duration; |
||||
|
||||
/// A measurement of a monotonically increasing clock.
|
||||
/// Opaque and useful only with `Duration`.
|
||||
///
|
||||
/// Instants are always guaranteed to be greater than any previously measured
|
||||
/// instant when created, and are often useful for tasks such as measuring
|
||||
/// benchmarks or timing how long an operation takes.
|
||||
///
|
||||
/// Note, however, that instants are not guaranteed to be **steady**. In other
|
||||
/// words, each tick of the underlying clock may not be the same length (e.g.
|
||||
/// some seconds may be longer than others). An instant may jump forwards or
|
||||
/// experience time dilation (slow down or speed up), but it will never go
|
||||
/// backwards.
|
||||
///
|
||||
/// Instants are opaque types that can only be compared to one another. There is
|
||||
/// no method to get "the number of seconds" from an instant. Instead, it only
|
||||
/// allows measuring the duration between two instants (or comparing two
|
||||
/// instants).
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, Instant};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let now = Instant::now();
|
||||
///
|
||||
/// // we sleep for 2 seconds
|
||||
/// sleep(Duration::new(2, 0));
|
||||
/// // it prints '2'
|
||||
/// println!("{}", now.elapsed().as_secs());
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub struct Instant(time::Instant); |
||||
|
||||
/// A measurement of the system clock, useful for talking to
|
||||
/// external entities like the file system or other processes.
|
||||
///
|
||||
/// Distinct from the `Instant` type, this time measurement **is not
|
||||
/// monotonic**. This means that you can save a file to the file system, then
|
||||
/// save another file to the file system, **and the second file has a
|
||||
/// `SystemTime` measurement earlier than the first**. In other words, an
|
||||
/// operation that happens after another operation in real time may have an
|
||||
/// earlier `SystemTime`!
|
||||
///
|
||||
/// Consequently, comparing two `SystemTime` instances to learn about the
|
||||
/// duration between them returns a `Result` instead of an infallible `Duration`
|
||||
/// to indicate that this sort of time drift may happen and needs to be handled.
|
||||
///
|
||||
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
|
||||
/// constant is provided in this module as an anchor in time to learn
|
||||
/// information about a `SystemTime`. By calculating the duration from this
|
||||
/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
|
||||
/// or perhaps some other string representation.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let now = SystemTime::now();
|
||||
///
|
||||
/// // we sleep for 2 seconds
|
||||
/// sleep(Duration::new(2, 0));
|
||||
/// match now.elapsed() {
|
||||
/// Ok(elapsed) => {
|
||||
/// // it prints '2'
|
||||
/// println!("{}", elapsed.as_secs());
|
||||
/// }
|
||||
/// Err(e) => {
|
||||
/// // an error occured!
|
||||
/// println!("Error: {:?}", e);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub struct SystemTime(time::SystemTime); |
||||
|
||||
/// An error returned from the `duration_since` method on `SystemTime`,
|
||||
/// used to learn how far in the opposite direction a system time lies.
|
||||
#[derive(Clone, Debug)] |
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub struct SystemTimeError(Duration); |
||||
|
||||
impl Instant { |
||||
/// Returns an instant corresponding to "now".
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn now() -> Instant { |
||||
Instant(time::Instant::now()) |
||||
} |
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `earlier` is later than `self`, which should
|
||||
/// only be possible if `earlier` was created after `self`. Because
|
||||
/// `Instant` is monotonic, the only time that this should happen should be
|
||||
/// a bug.
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn duration_since(&self, earlier: Instant) -> Duration { |
||||
self.0.sub_instant(&earlier.0) |
||||
} |
||||
|
||||
/// Returns the amount of time elapsed since this instant was created.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function may panic if the current time is earlier than this
|
||||
/// instant, which is something that can happen if an `Instant` is
|
||||
/// produced synthetically.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread::sleep;
|
||||
/// use std::time::{Duration, Instant};
|
||||
///
|
||||
/// let instant = Instant::now();
|
||||
/// let three_secs = Duration::from_secs(3);
|
||||
/// sleep(three_secs);
|
||||
/// assert!(instant.elapsed() >= three_secs);
|
||||
/// ```
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn elapsed(&self) -> Duration { |
||||
Instant::now() - *self |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Add<Duration> for Instant { |
||||
type Output = Instant; |
||||
|
||||
fn add(self, other: Duration) -> Instant { |
||||
Instant(self.0.add_duration(&other)) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl AddAssign<Duration> for Instant { |
||||
fn add_assign(&mut self, other: Duration) { |
||||
*self = *self + other; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Sub<Duration> for Instant { |
||||
type Output = Instant; |
||||
|
||||
fn sub(self, other: Duration) -> Instant { |
||||
Instant(self.0.sub_duration(&other)) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl SubAssign<Duration> for Instant { |
||||
fn sub_assign(&mut self, other: Duration) { |
||||
*self = *self - other; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Sub<Instant> for Instant { |
||||
type Output = Duration; |
||||
|
||||
fn sub(self, other: Instant) -> Duration { |
||||
self.duration_since(other) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl fmt::Debug for Instant { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
self.0.fmt(f) |
||||
} |
||||
} |
||||
|
||||
impl SystemTime { |
||||
/// Returns the system time corresponding to "now".
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn now() -> SystemTime { |
||||
SystemTime(time::SystemTime::now()) |
||||
} |
||||
|
||||
/// Returns the amount of time elapsed from an earlier point in time.
|
||||
///
|
||||
/// This function may fail because measurements taken earlier are not
|
||||
/// guaranteed to always be before later measurements (due to anomalies such
|
||||
/// as the system clock being adjusted either forwards or backwards).
|
||||
///
|
||||
/// If successful, `Ok(Duration)` is returned where the duration represents
|
||||
/// the amount of time elapsed from the specified measurement to this one.
|
||||
///
|
||||
/// Returns an `Err` if `earlier` is later than `self`, and the error
|
||||
/// contains how far from `self` the time is.
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn duration_since(&self, earlier: SystemTime) |
||||
-> Result<Duration, SystemTimeError> { |
||||
self.0.sub_time(&earlier.0).map_err(SystemTimeError) |
||||
} |
||||
|
||||
/// Returns the amount of time elapsed since this system time was created.
|
||||
///
|
||||
/// This function may fail as the underlying system clock is susceptible to
|
||||
/// drift and updates (e.g. the system clock could go backwards), so this
|
||||
/// function may not always succeed. If successful, `Ok(duration)` is
|
||||
/// returned where the duration represents the amount of time elapsed from
|
||||
/// this time measurement to the current time.
|
||||
///
|
||||
/// Returns an `Err` if `self` is later than the current system time, and
|
||||
/// the error contains how far from the current system time `self` is.
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> { |
||||
SystemTime::now().duration_since(*self) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Add<Duration> for SystemTime { |
||||
type Output = SystemTime; |
||||
|
||||
fn add(self, dur: Duration) -> SystemTime { |
||||
SystemTime(self.0.add_duration(&dur)) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl AddAssign<Duration> for SystemTime { |
||||
fn add_assign(&mut self, other: Duration) { |
||||
*self = *self + other; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Sub<Duration> for SystemTime { |
||||
type Output = SystemTime; |
||||
|
||||
fn sub(self, dur: Duration) -> SystemTime { |
||||
SystemTime(self.0.sub_duration(&dur)) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||
impl SubAssign<Duration> for SystemTime { |
||||
fn sub_assign(&mut self, other: Duration) { |
||||
*self = *self - other; |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl fmt::Debug for SystemTime { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
self.0.fmt(f) |
||||
} |
||||
} |
||||
|
||||
/// An anchor in time which can be used to create new `SystemTime` instances or
|
||||
/// learn about where in time a `SystemTime` lies.
|
||||
///
|
||||
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
|
||||
/// respect to the system clock. Using `duration_since` on an existing
|
||||
/// `SystemTime` instance can tell how far away from this point in time a
|
||||
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
|
||||
/// `SystemTime` instance to represent another fixed point in time.
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); |
||||
|
||||
impl SystemTimeError { |
||||
/// Returns the positive duration which represents how far forward the
|
||||
/// second system time was from the first.
|
||||
///
|
||||
/// A `SystemTimeError` is returned from the `duration_since`
|
||||
/// operation whenever the second system time represents a point later
|
||||
/// in time than the `self` of the method call.
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
pub fn duration(&self) -> Duration { |
||||
self.0 |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl Error for SystemTimeError { |
||||
fn description(&self) -> &str { "other time was not earlier than self" } |
||||
} |
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")] |
||||
impl fmt::Display for SystemTimeError { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
write!(f, "second time provided was later than self") |
||||
} |
||||
} |
||||
|
||||
impl FromInner<time::SystemTime> for SystemTime { |
||||
fn from_inner(time: time::SystemTime) -> SystemTime { |
||||
SystemTime(time) |
||||
} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; |
||||
|
||||
macro_rules! assert_almost_eq { |
||||
($a:expr, $b:expr) => ({ |
||||
let (a, b) = ($a, $b); |
||||
if a != b { |
||||
let (a, b) = if a > b {(a, b)} else {(b, a)}; |
||||
assert!(a - Duration::new(0, 100) <= b); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
#[test] |
||||
fn instant_monotonic() { |
||||
let a = Instant::now(); |
||||
let b = Instant::now(); |
||||
assert!(b >= a); |
||||
} |
||||
|
||||
#[test] |
||||
fn instant_elapsed() { |
||||
let a = Instant::now(); |
||||
a.elapsed(); |
||||
} |
||||
|
||||
#[test] |
||||
fn instant_math() { |
||||
let a = Instant::now(); |
||||
let b = Instant::now(); |
||||
let dur = b.duration_since(a); |
||||
assert_almost_eq!(b - dur, a); |
||||
assert_almost_eq!(a + dur, b); |
||||
|
||||
let second = Duration::new(1, 0); |
||||
assert_almost_eq!(a - second + second, a); |
||||
} |
||||
|
||||
#[test] |
||||
#[should_panic] |
||||
fn instant_duration_panic() { |
||||
let a = Instant::now(); |
||||
(a - Duration::new(1, 0)).duration_since(a); |
||||
} |
||||
|
||||
#[test] |
||||
fn system_time_math() { |
||||
let a = SystemTime::now(); |
||||
let b = SystemTime::now(); |
||||
match b.duration_since(a) { |
||||
Ok(dur) if dur == Duration::new(0, 0) => { |
||||
assert_almost_eq!(a, b); |
||||
} |
||||
Ok(dur) => { |
||||
assert!(b > a); |
||||
assert_almost_eq!(b - dur, a); |
||||
assert_almost_eq!(a + dur, b); |
||||
} |
||||
Err(dur) => { |
||||
let dur = dur.duration(); |
||||
assert!(a > b); |
||||
assert_almost_eq!(b + dur, a); |
||||
assert_almost_eq!(b - dur, a); |
||||
} |
||||
} |
||||
|
||||
let second = Duration::new(1, 0); |
||||
assert_almost_eq!(a.duration_since(a - second).unwrap(), second); |
||||
assert_almost_eq!(a.duration_since(a + second).unwrap_err() |
||||
.duration(), second); |
||||
|
||||
assert_almost_eq!(a - second + second, a); |
||||
|
||||
let eighty_years = second * 60 * 60 * 24 * 365 * 80; |
||||
assert_almost_eq!(a - eighty_years + eighty_years, a); |
||||
assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a); |
||||
|
||||
let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); |
||||
let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) |
||||
+ Duration::new(0, 500_000_000); |
||||
assert_eq!(one_second_from_epoch, one_second_from_epoch2); |
||||
} |
||||
|
||||
#[test] |
||||
fn system_time_elapsed() { |
||||
let a = SystemTime::now(); |
||||
drop(a.elapsed()); |
||||
} |
||||
|
||||
#[test] |
||||
fn since_epoch() { |
||||
let ts = SystemTime::now(); |
||||
let a = ts.duration_since(UNIX_EPOCH).unwrap(); |
||||
let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap(); |
||||
assert!(b > a); |
||||
assert_eq!(b - a, Duration::new(1, 0)); |
||||
|
||||
// let's assume that we're all running computers later than 2000
|
||||
let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30; |
||||
assert!(a > thirty_years); |
||||
|
||||
// let's assume that we're all running computers earlier than 2090.
|
||||
// Should give us ~70 years to fix this!
|
||||
let hundred_twenty_years = thirty_years * 4; |
||||
assert!(a < hundred_twenty_years); |
||||
} |
||||
} |
Loading…
Reference in new issue