aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src
diff options
context:
space:
mode:
authorFenrir <[email protected]>2017-02-02 20:53:27 -0700
committerFenrir <[email protected]>2017-02-18 18:04:15 -0700
commit2ed837f8e17cfbaf9bf823eeb92fe1eac22c6159 (patch)
treede5e1d52afdbc71b1dec80053824d9b60cde3592 /ctr-std/src
parentMerge pull request #19 from FenrirWolf/thread_local (diff)
downloadctru-rs-2ed837f8e17cfbaf9bf823eeb92fe1eac22c6159.tar.xz
ctru-rs-2ed837f8e17cfbaf9bf823eeb92fe1eac22c6159.zip
ctr-std: Add Time module
Diffstat (limited to 'ctr-std/src')
-rw-r--r--ctr-std/src/lib.rs2
-rw-r--r--ctr-std/src/sys/unix/mod.rs78
-rw-r--r--ctr-std/src/sys/unix/time.rs239
-rw-r--r--ctr-std/src/time/duration.rs420
-rw-r--r--ctr-std/src/time/mod.rs447
5 files changed, 1184 insertions, 2 deletions
diff --git a/ctr-std/src/lib.rs b/ctr-std/src/lib.rs
index e0058f5..eebca4e 100644
--- a/ctr-std/src/lib.rs
+++ b/ctr-std/src/lib.rs
@@ -14,6 +14,7 @@
#![feature(int_error_internals)]
#![feature(lang_items)]
#![feature(macro_reexport)]
+#![feature(oom)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(raw)]
@@ -148,6 +149,7 @@ pub mod num;
pub mod os;
pub mod path;
pub mod sync;
+pub mod time;
// Platform-abstraction modules
#[macro_use]
diff --git a/ctr-std/src/sys/unix/mod.rs b/ctr-std/src/sys/unix/mod.rs
index 13639eb..27c428d 100644
--- a/ctr-std/src/sys/unix/mod.rs
+++ b/ctr-std/src/sys/unix/mod.rs
@@ -10,6 +10,9 @@
#![allow(missing_docs, bad_style)]
+use io::{self, ErrorKind};
+use libc;
+
pub mod ext;
pub mod fast_thread_local;
pub mod memchr;
@@ -17,9 +20,45 @@ pub mod os;
pub mod os_str;
pub mod path;
pub mod thread_local;
+pub mod time;
-use io::ErrorKind;
-use libc;
+#[cfg(not(test))]
+pub fn init() {
+ use alloc::oom;
+
+ // By default, some platforms will send a *signal* when an EPIPE error
+ // would otherwise be delivered. This runtime doesn't install a SIGPIPE
+ // handler, causing it to kill the program, which isn't exactly what we
+ // want!
+ //
+ // Hence, we set SIGPIPE to ignore when the program starts up in order
+ // to prevent this problem.
+ unsafe {
+ reset_sigpipe();
+ }
+
+ oom::set_oom_handler(oom_handler);
+
+ // A nicer handler for out-of-memory situations than the default one. This
+ // one prints a message to stderr before aborting. It is critical that this
+ // code does not allocate any memory since we are in an OOM situation. Any
+ // errors are ignored while printing since there's nothing we can do about
+ // them and we are about to exit anyways.
+ fn oom_handler() -> ! {
+ use intrinsics;
+ let msg = "fatal runtime error: out of memory\n";
+ unsafe {
+ libc::write(libc::STDERR_FILENO,
+ msg.as_ptr() as *const libc::c_void,
+ msg.len());
+ intrinsics::abort();
+ }
+ }
+
+ // I don't think we have signal handling on the 3DS, so let's leave this
+ // blank for now
+ unsafe fn reset_sigpipe() {}
+}
pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno as libc::c_int {
@@ -47,6 +86,41 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
}
}
+#[doc(hidden)]
+pub trait IsMinusOne {
+ fn is_minus_one(&self) -> bool;
+}
+
+macro_rules! impl_is_minus_one {
+ ($($t:ident)*) => ($(impl IsMinusOne for $t {
+ fn is_minus_one(&self) -> bool {
+ *self == -1
+ }
+ })*)
+}
+
+impl_is_minus_one! { i8 i16 i32 i64 isize }
+
+pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
+ if t.is_minus_one() {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(t)
+ }
+}
+
+pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
+ where T: IsMinusOne,
+ F: FnMut() -> T
+{
+ loop {
+ match cvt(f()) {
+ Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+ other => return other,
+ }
+ }
+}
+
pub unsafe fn abort_internal() -> ! {
::libc::abort()
}
diff --git a/ctr-std/src/sys/unix/time.rs b/ctr-std/src/sys/unix/time.rs
new file mode 100644
index 0000000..3eea581
--- /dev/null
+++ b/ctr-std/src/sys/unix/time.rs
@@ -0,0 +1,239 @@
+// 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 time::Duration;
+
+ use super::Timespec;
+
+ #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+ pub struct Instant {
+ t: Timespec,
+ }
+
+ #[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 {
+ // devkitARM does not expose monotonic time functions or types,
+ // so we fall back to constructing Instant with gettimeofday(2)
+ pub fn now() -> Instant {
+ use ptr;
+
+ let mut s = libc::timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ };
+ cvt(unsafe {
+ libc::gettimeofday(&mut s, ptr::null_mut())
+ }).unwrap();
+ return Instant::from(s)
+ }
+
+ pub fn sub_instant(&self, other: &Instant) -> Duration {
+ self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
+ panic!("other was less than the current instant")
+ })
+ }
+
+ pub fn add_duration(&self, other: &Duration) -> Instant {
+ Instant { t: self.t.add_duration(other) }
+ }
+
+ pub fn sub_duration(&self, other: &Duration) -> Instant {
+ Instant { t: self.t.sub_duration(other) }
+ }
+ }
+
+ impl fmt::Debug for Instant {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Instant")
+ .field("tv_sec", &self.t.t.tv_sec)
+ .field("tv_nsec", &self.t.t.tv_nsec)
+ .finish()
+ }
+ }
+
+ impl From<libc::timeval> for Instant {
+ fn from(t: libc::timeval) -> Instant {
+ Instant::from(libc::timespec {
+ tv_sec: t.tv_sec,
+ tv_nsec: (t.tv_usec * 1000) as libc::c_long,
+ })
+ }
+ }
+
+ impl From<libc::timespec> for Instant {
+ fn from(t: libc::timespec) -> Instant {
+ Instant { t: Timespec { t: t } }
+ }
+ }
+
+ 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()
+ }
+ }
+}
diff --git a/ctr-std/src/time/duration.rs b/ctr-std/src/time/duration.rs
new file mode 100644
index 0000000..41d675b
--- /dev/null
+++ b/ctr-std/src/time/duration.rs
@@ -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);
+ }
+}
diff --git a/ctr-std/src/time/mod.rs b/ctr-std/src/time/mod.rs
new file mode 100644
index 0000000..6854f1e
--- /dev/null
+++ b/ctr-std/src/time/mod.rs
@@ -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);
+ }
+}