Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  sys.rs   Sprache: unbekannt

 
#![allow(bad_style)]

pub use self::inner::*;

#[cfg(any(
    all(target_arch = "wasm32", not(target_os = "emscripten")),
    target_env = "sgx"
))]
mod common {
    use Tm;

    pub fn time_to_tm(ts: i64, tm: &mut Tm) {
        let leapyear = |year| -> bool {
            year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
        };

        static _ytab: [[i64; 12]; 2] = [
            [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
            [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
        ];

        let mut year = 1970;

        let dayclock = ts % 86400;
        let mut dayno = ts / 86400;

        tm.tm_sec = (dayclock % 60) as i32;
        tm.tm_min = ((dayclock % 3600) / 60) as i32;
        tm.tm_hour = (dayclock / 3600) as i32;
        tm.tm_wday = ((dayno + 4) % 7) as i32;
        loop {
            let yearsize = if leapyear(year) {
                366
            } else {
                365
            };
            if dayno >= yearsize {
                    dayno -= yearsize;
                    year += 1;
            } else {
                break;
            }
        }
        tm.tm_year = (year - 1900) as i32;
        tm.tm_yday = dayno as i32;
        let mut mon = 0;
        while dayno >= _ytab[if leapyear(year) { 1 } else { 0 }][mon] {
                dayno -= _ytab[if leapyear(year) { 1 } else { 0 }][mon];
                mon += 1;
        }
        tm.tm_mon = mon as i32;
        tm.tm_mday = dayno as i32 + 1;
        tm.tm_isdst = 0;
    }

    pub fn tm_to_time(tm: &Tm) -> i64 {
        let mut y = tm.tm_year as i64 + 1900;
        let mut m = tm.tm_mon as i64 + 1;
        if m <= 2 {
            y -= 1;
            m += 12;
        }
        let d = tm.tm_mday as i64;
        let h = tm.tm_hour as i64;
        let mi = tm.tm_min as i64;
        let s = tm.tm_sec as i64;
        (365*y + y/4 - y/100 + y/400 + 3*(m+1)/5 + 30*m + d - 719561)
            * 86400 + 3600 * h + 60 * mi + s
    }
}

#[cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))]
mod inner {
    use std::ops::{Add, Sub};
    use Tm;
    use Duration;
    use super::common::{time_to_tm, tm_to_time};

    #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
    pub struct SteadyTime;

    pub fn time_to_utc_tm(sec: i64, tm: &mut Tm) {
        time_to_tm(sec, tm);
    }

    pub fn time_to_local_tm(sec: i64, tm: &mut Tm) {
        // FIXME: Add timezone logic
        time_to_tm(sec, tm);
    }

    pub fn utc_tm_to_time(tm: &Tm) -> i64 {
        tm_to_time(tm)
    }

    pub fn local_tm_to_time(tm: &Tm) -> i64 {
        // FIXME: Add timezone logic
        tm_to_time(tm)
    }

    pub fn get_time() -> (i64, i32) {
        unimplemented!()
    }

    pub fn get_precise_ns() -> u64 {
        unimplemented!()
    }

    impl SteadyTime {
        pub fn now() -> SteadyTime {
            unimplemented!()
        }
    }

    impl Sub for SteadyTime {
        type Output = Duration;
        fn sub(self, _other: SteadyTime) -> Duration {
            unimplemented!()
        }
    }

    impl Sub<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn sub(self, _other: Duration) -> SteadyTime {
          unimplemented!()
        }
    }

    impl Add<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn add(self, _other: Duration) -> SteadyTime {
            unimplemented!()
        }
    }
}

#[cfg(target_os = "wasi")]
mod inner {
    use std::ops::{Add, Sub};
    use Tm;
    use Duration;
    use super::common::{time_to_tm, tm_to_time};
    use wasi::{clock_time_get, CLOCKID_MONOTONIC, CLOCKID_REALTIME};

    #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
    pub struct SteadyTime {
        t: u64
    }

    pub fn time_to_utc_tm(sec: i64, tm: &mut Tm) {
        time_to_tm(sec, tm);
    }

    pub fn time_to_local_tm(sec: i64, tm: &mut Tm) {
        // FIXME: Add timezone logic
        time_to_tm(sec, tm);
    }

    pub fn utc_tm_to_time(tm: &Tm) -> i64 {
        tm_to_time(tm)
    }

    pub fn local_tm_to_time(tm: &Tm) -> i64 {
        // FIXME: Add timezone logic
        tm_to_time(tm)
    }

    pub fn get_time() -> (i64, i32) {
        let ts = get_precise_ns();
        (
            ts as i64 / 1_000_000_000,
            (ts as i64 % 1_000_000_000) as i32,
        )
    }

    pub fn get_precise_ns() -> u64 {
        unsafe { clock_time_get(CLOCKID_REALTIME, 1_000_000_000) }
            .expect("Host doesn't implement a real-time clock")
    }

    impl SteadyTime {
        pub fn now() -> SteadyTime {
            SteadyTime {
                t: unsafe { clock_time_get(CLOCKID_MONOTONIC, 1_000_000_000) }
                    .expect("Host doesn't implement a monotonic clock"),
            }
        }
    }

    impl Sub for SteadyTime {
        type Output = Duration;
        fn sub(self, other: SteadyTime) -> Duration {
            Duration::nanoseconds(self.t as i64 - other.t as i64)
        }
    }

    impl Sub<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn sub(self, other: Duration) -> SteadyTime {
            self + -other
        }
    }

    impl Add<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn add(self, other: Duration) -> SteadyTime {
            let delta = other.num_nanoseconds().unwrap();
            SteadyTime {
                t: (self.t as i64 + delta) as u64,
            }
        }
    }
}

#[cfg(target_env = "sgx")]
mod inner {
    use std::ops::{Add, Sub};
    use Tm;
    use Duration;
    use super::common::{time_to_tm, tm_to_time};
    use std::time::SystemTime;

    /// The number of nanoseconds in seconds.
    const NANOS_PER_SEC: u64 = 1_000_000_000;

    #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
    pub struct SteadyTime {
        t: Duration
    }

    pub fn time_to_utc_tm(sec: i64, tm: &mut Tm) {
        time_to_tm(sec, tm);
    }

    pub fn time_to_local_tm(sec: i64, tm: &mut Tm) {
        // FIXME: Add timezone logic
        time_to_tm(sec, tm);
    }

    pub fn utc_tm_to_time(tm: &Tm) -> i64 {
        tm_to_time(tm)
    }

    pub fn local_tm_to_time(tm: &Tm) -> i64 {
        // FIXME: Add timezone logic
        tm_to_time(tm)
    }

    pub fn get_time() -> (i64, i32) {
        SteadyTime::now().t.raw()
    }

    pub fn get_precise_ns() -> u64 {
        // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system
        // clock is adjusted backward.
        let std_duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
        std_duration.as_secs() * NANOS_PER_SEC + std_duration.subsec_nanos() as u64
    }

    impl SteadyTime {
        pub fn now() -> SteadyTime {
            // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system
            // clock is adjusted backward.
            let std_duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
            // This unwrap is safe because duration is well within the limits of i64.
            let duration = Duration::from_std(std_duration).unwrap();
            SteadyTime { t: duration }
        }
    }

    impl Sub for SteadyTime {
        type Output = Duration;
        fn sub(self, other: SteadyTime) -> Duration {
            self.t - other.t
        }
    }

    impl Sub<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn sub(self, other: Duration) -> SteadyTime {
            SteadyTime { t: self.t - other }
        }
    }

    impl Add<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn add(self, other: Duration) -> SteadyTime {
            SteadyTime { t: self.t + other }
        }
    }
}

#[cfg(unix)]
mod inner {
    use libc::{self, time_t};
    use std::mem;
    use std::io;
    use Tm;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub use self::mac::*;
    #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
    pub use self::unix::*;

    #[cfg(any(target_os = "solaris", target_os = "illumos"))]
    extern {
        static timezone: time_t;
        static altzone: time_t;
    }

    fn rust_tm_to_tm(rust_tm: &Tm, tm: &mut libc::tm) {
        tm.tm_sec = rust_tm.tm_sec;
        tm.tm_min = rust_tm.tm_min;
        tm.tm_hour = rust_tm.tm_hour;
        tm.tm_mday = rust_tm.tm_mday;
        tm.tm_mon = rust_tm.tm_mon;
        tm.tm_year = rust_tm.tm_year;
        tm.tm_wday = rust_tm.tm_wday;
        tm.tm_yday = rust_tm.tm_yday;
        tm.tm_isdst = rust_tm.tm_isdst;
    }

    fn tm_to_rust_tm(tm: &libc::tm, utcoff: i32, rust_tm: &mut Tm) {
        rust_tm.tm_sec = tm.tm_sec;
        rust_tm.tm_min = tm.tm_min;
        rust_tm.tm_hour = tm.tm_hour;
        rust_tm.tm_mday = tm.tm_mday;
        rust_tm.tm_mon = tm.tm_mon;
        rust_tm.tm_year = tm.tm_year;
        rust_tm.tm_wday = tm.tm_wday;
        rust_tm.tm_yday = tm.tm_yday;
        rust_tm.tm_isdst = tm.tm_isdst;
        rust_tm.tm_utcoff = utcoff;
    }

    #[cfg(any(target_os = "nacl", target_os = "solaris", target_os = "illumos"))]
    unsafe fn timegm(tm: *mut libc::tm) -> time_t {
        use std::env::{set_var, var_os, remove_var};
        extern {
            fn tzset();
        }

        let ret;

        let current_tz = var_os("TZ");
        set_var("TZ", "UTC");
        tzset();

        ret = libc::mktime(tm);

        if let Some(tz) = current_tz {
            set_var("TZ", tz);
        } else {
            remove_var("TZ");
        }
        tzset();

        ret
    }

    pub fn time_to_utc_tm(sec: i64, tm: &mut Tm) {
        unsafe {
            let sec = sec as time_t;
            let mut out = mem::zeroed();
            if libc::gmtime_r(&sec, &mut out).is_null() {
                panic!("gmtime_r failed: {}", io::Error::last_os_error());
            }
            tm_to_rust_tm(&out, 0, tm);
        }
    }

    pub fn time_to_local_tm(sec: i64, tm: &mut Tm) {
        unsafe {
            let sec = sec as time_t;
            let mut out = mem::zeroed();
            if libc::localtime_r(&sec, &mut out).is_null() {
                panic!("localtime_r failed: {}", io::Error::last_os_error());
            }
            #[cfg(any(target_os = "solaris", target_os = "illumos"))]
            let gmtoff = {
                ::tzset();
                // < 0 means we don't know; assume we're not in DST.
                if out.tm_isdst == 0 {
                    // timezone is seconds west of UTC, tm_gmtoff is seconds east
                    -timezone
                } else if out.tm_isdst > 0 {
                    -altzone
                } else {
                    -timezone
                }
            };
            #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
            let gmtoff = out.tm_gmtoff;
            tm_to_rust_tm(&out, gmtoff as i32, tm);
        }
    }

    pub fn utc_tm_to_time(rust_tm: &Tm) -> i64 {
        #[cfg(all(target_os = "android", target_pointer_width = "32"))]
        use libc::timegm64 as timegm;
        #[cfg(not(any(
            all(target_os = "android", target_pointer_width = "32"),
            target_os = "nacl",
            target_os = "solaris",
            target_os = "illumos"
        )))]
        use libc::timegm;

        let mut tm = unsafe { mem::zeroed() };
        rust_tm_to_tm(rust_tm, &mut tm);
        unsafe { timegm(&mut tm) as i64 }
    }

    pub fn local_tm_to_time(rust_tm: &Tm) -> i64 {
        let mut tm = unsafe { mem::zeroed() };
        rust_tm_to_tm(rust_tm, &mut tm);
        unsafe { libc::mktime(&mut tm) as i64 }
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    mod mac {
        #[allow(deprecated)]
        use libc::{self, timeval, mach_timebase_info};
        #[allow(deprecated)]
        use std::sync::{Once, ONCE_INIT};
        use std::ops::{Add, Sub};
        use Duration;

        #[allow(deprecated)]
        fn info() -> &'static mach_timebase_info {
            static mut INFO: mach_timebase_info = mach_timebase_info {
                numer: 0,
                denom: 0,
            };
            static ONCE: Once = ONCE_INIT;

            unsafe {
                ONCE.call_once(|| {
                    mach_timebase_info(&mut INFO);
                });
                &INFO
            }
        }

        pub fn get_time() -> (i64, i32) {
            use std::ptr;
            let mut tv = timeval { tv_sec: 0, tv_usec: 0 };
            unsafe { libc::gettimeofday(&mut tv, ptr::null_mut()); }
            (tv.tv_sec as i64, tv.tv_usec * 1000)
        }

        #[allow(deprecated)]
        #[inline]
        pub fn get_precise_ns() -> u64 {
            unsafe {
                let time = libc::mach_absolute_time();
                let info = info();
                time * info.numer as u64 / info.denom as u64
            }
        }

        #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
        pub struct SteadyTime { t: u64 }

        impl SteadyTime {
            pub fn now() -> SteadyTime {
                SteadyTime { t: get_precise_ns() }
            }
        }
        impl Sub for SteadyTime {
            type Output = Duration;
            fn sub(self, other: SteadyTime) -> Duration {
                Duration::nanoseconds(self.t as i64 - other.t as i64)
            }
        }
        impl Sub<Duration> for SteadyTime {
            type Output = SteadyTime;
            fn sub(self, other: Duration) -> SteadyTime {
                self + -other
            }
        }
        impl Add<Duration> for SteadyTime {
            type Output = SteadyTime;
            fn add(self, other: Duration) -> SteadyTime {
                let delta = other.num_nanoseconds().unwrap();
                SteadyTime {
                    t: (self.t as i64 + delta) as u64
                }
            }
        }
    }

    #[cfg(test)]
    pub struct TzReset;

    #[cfg(test)]
    pub fn set_los_angeles_time_zone() -> TzReset {
        use std::env;
        env::set_var("TZ", "America/Los_Angeles");
        ::tzset();
        TzReset
    }

    #[cfg(test)]
    pub fn set_london_with_dst_time_zone() -> TzReset {
        use std::env;
        env::set_var("TZ", "Europe/London");
        ::tzset();
        TzReset
    }

    #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
    mod unix {
        use std::fmt;
        use std::cmp::Ordering;
        use std::mem::zeroed;
        use std::ops::{Add, Sub};
        use libc;

        use Duration;

        pub fn get_time() -> (i64, i32) {
            // SAFETY: libc::timespec is zero initializable.
            let mut tv: libc::timespec = unsafe { zeroed() };
            unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut tv); }
            (tv.tv_sec as i64, tv.tv_nsec as i32)
        }

        pub fn get_precise_ns() -> u64 {
            // SAFETY: libc::timespec is zero initializable.
            let mut ts: libc::timespec = unsafe { zeroed() };
            unsafe {
                libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
            }
            (ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)
        }

        #[derive(Copy)]
        pub struct SteadyTime {
            t: libc::timespec,
        }

        impl fmt::Debug for SteadyTime {
            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                write!(fmt, "SteadyTime {{ tv_sec: {:?}, tv_nsec: {:?} }}",
                       self.t.tv_sec, self.t.tv_nsec)
            }
        }

        impl Clone for SteadyTime {
            fn clone(&self) -> SteadyTime {
                SteadyTime { t: self.t }
            }
        }

        impl SteadyTime {
            pub fn now() -> SteadyTime {
                let mut t = SteadyTime {
                    // SAFETY: libc::timespec is zero initializable.
                    t: unsafe { zeroed() }
                };
                unsafe {
                    assert_eq!(0, libc::clock_gettime(libc::CLOCK_MONOTONIC,
                                                      &mut t.t));
                }
                t
            }
        }

        impl Sub for SteadyTime {
            type Output = Duration;
            fn sub(self, other: SteadyTime) -> Duration {
                if self.t.tv_nsec >= other.t.tv_nsec {
                    Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) +
                        Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64)
                } else {
                    Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) +
                        Duration::nanoseconds(self.t.tv_nsec as i64 + ::NSEC_PER_SEC as i64 -
                                              other.t.tv_nsec as i64)
                }
            }
        }

        impl Sub<Duration> for SteadyTime {
            type Output = SteadyTime;
            fn sub(self, other: Duration) -> SteadyTime {
                self + -other
            }
        }

        impl Add<Duration> for SteadyTime {
            type Output = SteadyTime;
            fn add(mut self, other: Duration) -> SteadyTime {
                let seconds = other.num_seconds();
                let nanoseconds = other - Duration::seconds(seconds);
                let nanoseconds = nanoseconds.num_nanoseconds().unwrap();

                #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
                type nsec = i64;
                #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
                type nsec = libc::c_long;

                self.t.tv_sec += seconds as libc::time_t;
                self.t.tv_nsec += nanoseconds as nsec;
                if self.t.tv_nsec >= ::NSEC_PER_SEC as nsec {
                    self.t.tv_nsec -= ::NSEC_PER_SEC as nsec;
                    self.t.tv_sec += 1;
                } else if self.t.tv_nsec < 0 {
                    self.t.tv_sec -= 1;
                    self.t.tv_nsec += ::NSEC_PER_SEC as nsec;
                }
                self
            }
        }

        impl PartialOrd for SteadyTime {
            fn partial_cmp(&self, other: &SteadyTime) -> Option<Ordering> {
                Some(self.cmp(other))
            }
        }

        impl Ord for SteadyTime {
            fn cmp(&self, other: &SteadyTime) -> Ordering {
                match self.t.tv_sec.cmp(&other.t.tv_sec) {
                    Ordering::Equal => self.t.tv_nsec.cmp(&other.t.tv_nsec),
                    ord => ord
                }
            }
        }

        impl PartialEq for SteadyTime {
            fn eq(&self, other: &SteadyTime) -> bool {
                self.t.tv_sec == other.t.tv_sec &&
                    self.t.tv_nsec == other.t.tv_nsec
            }
        }

        impl Eq for SteadyTime {}

    }
}

#[cfg(windows)]
#[allow(non_snake_case)]
mod inner {
    use std::io;
    use std::mem;
    #[allow(deprecated)]
    use std::sync::{Once, ONCE_INIT};
    use std::ops::{Add, Sub};
    use {Tm, Duration};

    use winapi::um::winnt::*;
    use winapi::shared::minwindef::*;
    use winapi::um::minwinbase::SYSTEMTIME;
    use winapi::um::profileapi::*;
    use winapi::um::timezoneapi::*;
    use winapi::um::sysinfoapi::GetSystemTimeAsFileTime;

    fn frequency() -> i64 {
        static mut FREQUENCY: i64 = 0;
        #[allow(deprecated)]
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                let mut l = i64_to_large_integer(0);
                QueryPerformanceFrequency(&mut l);
                FREQUENCY = large_integer_to_i64(l);
            });
            FREQUENCY
        }
    }

    fn i64_to_large_integer(i: i64) -> LARGE_INTEGER {
        unsafe {
            let mut large_integer: LARGE_INTEGER = mem::zeroed();
            *large_integer.QuadPart_mut() = i;
            large_integer
        }
    }

    fn large_integer_to_i64(l: LARGE_INTEGER) -> i64 {
        unsafe {
            *l.QuadPart()
        }
    }

    const HECTONANOSECS_IN_SEC: i64 = 10_000_000;
    const HECTONANOSEC_TO_UNIX_EPOCH: i64 = 11_644_473_600 * HECTONANOSECS_IN_SEC;

    fn time_to_file_time(sec: i64) -> FILETIME {
        let t = (((sec * HECTONANOSECS_IN_SEC) + HECTONANOSEC_TO_UNIX_EPOCH)) as u64;
        FILETIME {
            dwLowDateTime: t as DWORD,
            dwHighDateTime: (t >> 32) as DWORD
        }
    }

    fn file_time_as_u64(ft: &FILETIME) -> u64 {
        ((ft.dwHighDateTime as u64) << 32) | (ft.dwLowDateTime as u64)
    }

    fn file_time_to_nsec(ft: &FILETIME) -> i32 {
        let t = file_time_as_u64(ft) as i64;
        ((t % HECTONANOSECS_IN_SEC) * 100) as i32
    }

    fn file_time_to_unix_seconds(ft: &FILETIME) -> i64 {
        let t = file_time_as_u64(ft) as i64;
        ((t - HECTONANOSEC_TO_UNIX_EPOCH) / HECTONANOSECS_IN_SEC) as i64
    }

    fn system_time_to_file_time(sys: &SYSTEMTIME) -> FILETIME {
        unsafe {
            let mut ft = mem::zeroed();
            SystemTimeToFileTime(sys, &mut ft);
            ft
        }
    }

    fn tm_to_system_time(tm: &Tm) -> SYSTEMTIME {
        let mut sys: SYSTEMTIME = unsafe { mem::zeroed() };
        sys.wSecond = tm.tm_sec as WORD;
        sys.wMinute = tm.tm_min as WORD;
        sys.wHour = tm.tm_hour as WORD;
        sys.wDay = tm.tm_mday as WORD;
        sys.wDayOfWeek = tm.tm_wday as WORD;
        sys.wMonth = (tm.tm_mon + 1) as WORD;
        sys.wYear = (tm.tm_year + 1900) as WORD;
        sys
    }

    fn system_time_to_tm(sys: &SYSTEMTIME, tm: &mut Tm) {
        tm.tm_sec = sys.wSecond as i32;
        tm.tm_min = sys.wMinute as i32;
        tm.tm_hour = sys.wHour as i32;
        tm.tm_mday = sys.wDay as i32;
        tm.tm_wday = sys.wDayOfWeek as i32;
        tm.tm_mon = (sys.wMonth - 1) as i32;
        tm.tm_year = (sys.wYear - 1900) as i32;
        tm.tm_yday = yday(tm.tm_year, tm.tm_mon + 1, tm.tm_mday);

        fn yday(year: i32, month: i32, day: i32) -> i32 {
            let leap = if month > 2 {
                if year % 4 == 0 { 1 } else { 2 }
            } else {
                0
            };
            let july = if month > 7 { 1 } else { 0 };

            (month - 1) * 30 + month / 2 + (day - 1) - leap + july
        }
    }

    macro_rules! call {
        ($name:ident($($arg:expr),*)) => {
            if $name($($arg),*) == 0 {
                panic!(concat!(stringify!($name), " failed with: {}"),
                       io::Error::last_os_error());
            }
        }
    }

    pub fn time_to_utc_tm(sec: i64, tm: &mut Tm) {
        let mut out = unsafe { mem::zeroed() };
        let ft = time_to_file_time(sec);
        unsafe {
            call!(FileTimeToSystemTime(&ft, &mut out));
        }
        system_time_to_tm(&out, tm);
        tm.tm_utcoff = 0;
    }

    pub fn time_to_local_tm(sec: i64, tm: &mut Tm) {
        let ft = time_to_file_time(sec);
        unsafe {
            let mut utc = mem::zeroed();
            let mut local = mem::zeroed();
            call!(FileTimeToSystemTime(&ft, &mut utc));
            call!(SystemTimeToTzSpecificLocalTime(0 as *const _,
                                                  &mut utc, &mut local));
            system_time_to_tm(&local, tm);

            let local = system_time_to_file_time(&local);
            let local_sec = file_time_to_unix_seconds(&local);

            let mut tz = mem::zeroed();
            GetTimeZoneInformation(&mut tz);

            // SystemTimeToTzSpecificLocalTime already applied the biases so
            // check if it non standard
            tm.tm_utcoff = (local_sec - sec) as i32;
            tm.tm_isdst = if tm.tm_utcoff == -60 * (tz.Bias + tz.StandardBias) {
                0
            } else {
                1
            };
        }
    }

    pub fn utc_tm_to_time(tm: &Tm) -> i64 {
        unsafe {
            let mut ft = mem::zeroed();
            let sys_time = tm_to_system_time(tm);
            call!(SystemTimeToFileTime(&sys_time, &mut ft));
            file_time_to_unix_seconds(&ft)
        }
    }

    pub fn local_tm_to_time(tm: &Tm) -> i64 {
        unsafe {
            let mut ft = mem::zeroed();
            let mut utc = mem::zeroed();
            let mut sys_time = tm_to_system_time(tm);
            call!(TzSpecificLocalTimeToSystemTime(0 as *mut _,
                                                  &mut sys_time, &mut utc));
            call!(SystemTimeToFileTime(&utc, &mut ft));
            file_time_to_unix_seconds(&ft)
        }
    }

    pub fn get_time() -> (i64, i32) {
        unsafe {
            let mut ft = mem::zeroed();
            GetSystemTimeAsFileTime(&mut ft);
            (file_time_to_unix_seconds(&ft), file_time_to_nsec(&ft))
        }
    }

    pub fn get_precise_ns() -> u64 {
        let mut ticks = i64_to_large_integer(0);
        unsafe {
            assert!(QueryPerformanceCounter(&mut ticks) == 1);
        }
        mul_div_i64(large_integer_to_i64(ticks), 1000000000, frequency()) as u64

    }

    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
    pub struct SteadyTime {
        t: i64,
    }

    impl SteadyTime {
        pub fn now() -> SteadyTime {
            let mut l = i64_to_large_integer(0);
            unsafe { QueryPerformanceCounter(&mut l); }
            SteadyTime { t : large_integer_to_i64(l) }
        }
    }

    impl Sub for SteadyTime {
        type Output = Duration;
        fn sub(self, other: SteadyTime) -> Duration {
            let diff = self.t as i64 - other.t as i64;
            Duration::nanoseconds(mul_div_i64(diff, 1000000000,
                                              frequency()))
        }
    }

    impl Sub<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn sub(self, other: Duration) -> SteadyTime {
            self + -other
        }
    }

    impl Add<Duration> for SteadyTime {
        type Output = SteadyTime;
        fn add(mut self, other: Duration) -> SteadyTime {
            self.t += (other.num_microseconds().unwrap() * frequency() /
                       1_000_000) as i64;
            self
        }
    }

    #[cfg(test)]
    pub struct TzReset {
        old: TIME_ZONE_INFORMATION,
    }

    #[cfg(test)]
    impl Drop for TzReset {
        fn drop(&mut self) {
            unsafe {
                call!(SetTimeZoneInformation(&self.old));
            }
        }
    }

    #[cfg(test)]
    pub fn set_los_angeles_time_zone() -> TzReset {
        acquire_privileges();

        unsafe {
            let mut tz = mem::zeroed::<TIME_ZONE_INFORMATION>();
            GetTimeZoneInformation(&mut tz);
            let ret = TzReset { old: tz };
            tz.Bias = 60 * 8;
            call!(SetTimeZoneInformation(&tz));
            return ret
        }
    }

    #[cfg(test)]
    pub fn set_london_with_dst_time_zone() -> TzReset {
        acquire_privileges();

        unsafe {
            let mut tz = mem::zeroed::<TIME_ZONE_INFORMATION>();
            GetTimeZoneInformation(&mut tz);
            let ret = TzReset { old: tz };
            // Since date set precisely this is 2015's dates
            tz.Bias = 0;
            tz.DaylightBias = -60;
            tz.DaylightDate.wYear = 0;
            tz.DaylightDate.wMonth = 3;
            tz.DaylightDate.wDayOfWeek = 0;
            tz.DaylightDate.wDay = 5;
            tz.DaylightDate.wHour = 2;
            tz.StandardBias = 0;
            tz.StandardDate.wYear = 0;
            tz.StandardDate.wMonth = 10;
            tz.StandardDate.wDayOfWeek = 0;
            tz.StandardDate.wDay = 5;
            tz.StandardDate.wHour = 2;
            call!(SetTimeZoneInformation(&tz));
            return ret
        }
    }

    // Ensures that this process has the necessary privileges to set a new time
    // zone, and this is all transcribed from:
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%29.aspx
    #[cfg(test)]
    fn acquire_privileges() {
        use winapi::um::processthreadsapi::*;
        use winapi::um::winbase::LookupPrivilegeValueA;
        const SE_PRIVILEGE_ENABLED: DWORD = 2;
        #[allow(deprecated)]
        static INIT: Once = ONCE_INIT;

        // TODO: FIXME
        extern "system" {
            fn AdjustTokenPrivileges(
                TokenHandle: HANDLE, DisableAllPrivileges: BOOL, NewState: PTOKEN_PRIVILEGES,
                BufferLength: DWORD, PreviousState: PTOKEN_PRIVILEGES, ReturnLength: PDWORD,
            ) -> BOOL;
        }

        INIT.call_once(|| unsafe {
            let mut hToken = 0 as *mut _;
            call!(OpenProcessToken(GetCurrentProcess(),
                                   TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                                   &mut hToken));

            let mut tkp = mem::zeroed::<TOKEN_PRIVILEGES>();
            assert_eq!(tkp.Privileges.len(), 1);
            let c = ::std::ffi::CString::new("SeTimeZonePrivilege").unwrap();
            call!(LookupPrivilegeValueA(0 as *const _, c.as_ptr(),
                                        &mut tkp.Privileges[0].Luid));
            tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            tkp.PrivilegeCount = 1;
            call!(AdjustTokenPrivileges(hToken, FALSE, &mut tkp, 0,
                                        0 as *mut _, 0 as *mut _));
        });
    }



    // Computes (value*numer)/denom without overflow, as long as both
    // (numer*denom) and the overall result fit into i64 (which is the case
    // for our time conversions).
    fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
        let q = value / denom;
        let r = value % denom;
        // Decompose value as (value/denom*denom + value%denom),
        // substitute into (value*numer)/denom and simplify.
        // r < denom, so (denom*numer) is the upper bound of (r*numer)
        q * numer + r * numer / denom
    }

    #[test]
    fn test_muldiv() {
        assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
                   1_000_000_000_001_000);
        assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000),
                   -1_000_000_000_001_000);
        assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),
                   1_000_000_000_001_000);
        assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000),
                   -1_000_000_000_001_000);
        assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),
                   1_000_000_000_001_000);
    }
}

[ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge