<commit_before>// 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.

pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};

const NSEC_PER_SEC: u64 = 1_000_000_000;

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sync::Once;
    use sys::cvt;
    use sys_common::mul_div_u64;
    use time::Duration;

    const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;

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

    #[derive(Copy, Clone)]
    pub struct SystemTime {
        t: libc::timeval,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: libc::timeval {
            tv_sec: 0,
            tv_usec: 0,
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: unsafe { libc::mach_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"),
            }
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            let mut s = SystemTime {
                t: libc::timeval {
                    tv_sec: 0,
                    tv_usec: 0,
                },
            };
            cvt(unsafe {
                libc::gettimeofday(&mut s.t, 0 as *mut _)
            }).unwrap();
            return s
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_usec >= other.t.tv_usec {
                    Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 -
                                   other.t.tv_usec as u32) * 1000)
                } else {
                    Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
                                   other.t.tv_usec as u32) * 1000)
                })
            } else {
                match other.sub_time(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            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 usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
            if usec > USEC_PER_SEC as u32 {
                usec -= USEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            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 usec = self.t.tv_usec as i32 -
                           (other.subsec_nanos() / 1000) as i32;
            if usec < 0 {
                usec += USEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }
    }

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

    impl Eq for SystemTime {}

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

    impl Ord for SystemTime {
        fn cmp(&self, other: &SystemTime) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_usec);
            let other = (other.t.tv_sec, other.t.tv_usec);
            me.cmp(&other)
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.tv_sec)
             .field("tv_usec", &self.t.tv_usec)
             .finish()
        }
    }

    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)
    }

    fn info() -> &'static libc::mach_timebase_info {
        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
            numer: 0,
            denom: 0,
        };
        static ONCE: Once = Once::new();

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

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sys::cvt;
    use time::Duration;

    #[derive(Copy, Clone)]
    struct Timespec {
        t: libc::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 {
        pub fn now() -> Instant {
            Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
        }

        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 SystemTime {
        pub fn now() -> SystemTime {
            SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
        }

        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 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()
        }
    }

    impl Timespec {
        pub fn now(clock: libc::c_int) -> Timespec {
            let mut t = Timespec {
                t: libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            };
            cvt(unsafe {
                libc::clock_gettime(clock, &mut t.t)
            }).unwrap();
            t
        }

        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)
        }
    }
}
<commit_msg>Fix the time overflow on mac as well<commit_after>// 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.

pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};

const NSEC_PER_SEC: u64 = 1_000_000_000;

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sync::Once;
    use sys::cvt;
    use sys_common::mul_div_u64;
    use time::Duration;

    const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;

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

    #[derive(Copy, Clone)]
    pub struct SystemTime {
        t: libc::timeval,
    }

    pub const UNIX_EPOCH: SystemTime = SystemTime {
        t: libc::timeval {
            tv_sec: 0,
            tv_usec: 0,
        },
    };

    impl Instant {
        pub fn now() -> Instant {
            Instant { t: unsafe { libc::mach_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"),
            }
        }
    }

    impl SystemTime {
        pub fn now() -> SystemTime {
            let mut s = SystemTime {
                t: libc::timeval {
                    tv_sec: 0,
                    tv_usec: 0,
                },
            };
            cvt(unsafe {
                libc::gettimeofday(&mut s.t, 0 as *mut _)
            }).unwrap();
            return s
        }

        pub fn sub_time(&self, other: &SystemTime)
                        -> Result<Duration, Duration> {
            if self >= other {
                Ok(if self.t.tv_usec >= other.t.tv_usec {
                    Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 -
                                   other.t.tv_usec as u32) * 1000)
                } else {
                    Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64,
                                  (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
                                   other.t.tv_usec as u32) * 1000)
                })
            } else {
                match other.sub_time(self) {
                    Ok(d) => Err(d),
                    Err(d) => Ok(d),
                }
            }
        }

        pub fn add_duration(&self, other: &Duration) -> SystemTime {
            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 usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
            if usec >= USEC_PER_SEC as u32 {
                usec -= USEC_PER_SEC as u32;
                secs = secs.checked_add(1).expect("overflow when adding \
                                                   duration to time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }

        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
            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 usec = self.t.tv_usec as i32 -
                           (other.subsec_nanos() / 1000) as i32;
            if usec < 0 {
                usec += USEC_PER_SEC as i32;
                secs = secs.checked_sub(1).expect("overflow when subtracting \
                                                   duration from time");
            }
            SystemTime {
                t: libc::timeval {
                    tv_sec: secs as libc::time_t,
                    tv_usec: usec as libc::suseconds_t,
                },
            }
        }
    }

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

    impl Eq for SystemTime {}

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

    impl Ord for SystemTime {
        fn cmp(&self, other: &SystemTime) -> Ordering {
            let me = (self.t.tv_sec, self.t.tv_usec);
            let other = (other.t.tv_sec, other.t.tv_usec);
            me.cmp(&other)
        }
    }

    impl fmt::Debug for SystemTime {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.tv_sec)
             .field("tv_usec", &self.t.tv_usec)
             .finish()
        }
    }

    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)
    }

    fn info() -> &'static libc::mach_timebase_info {
        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
            numer: 0,
            denom: 0,
        };
        static ONCE: Once = Once::new();

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

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
    use cmp::Ordering;
    use fmt;
    use libc;
    use super::NSEC_PER_SEC;
    use sys::cvt;
    use time::Duration;

    #[derive(Copy, Clone)]
    struct Timespec {
        t: libc::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 {
        pub fn now() -> Instant {
            Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
        }

        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 SystemTime {
        pub fn now() -> SystemTime {
            SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
        }

        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 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()
        }
    }

    impl Timespec {
        pub fn now(clock: libc::c_int) -> Timespec {
            let mut t = Timespec {
                t: libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            };
            cvt(unsafe {
                libc::clock_gettime(clock, &mut t.t)
            }).unwrap();
            t
        }

        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)
        }
    }
}
<|endoftext|>


<commit_before>use std::io::timer;
use std::io::stdio;

fn main() {
  stdio::print("Loading...");
  stdio::flush();
  timer::sleep(1000);
  for num in range(0, 1000) {
    stdio::print("\r\x1b[K" + num.to_str());
    stdio::flush();
    timer::sleep(100);
  }
}<commit_msg>Add basic REPL<commit_after>use std::io::timer;
use std::io::stdio;

struct Shell {
    cmd_prompt: ~str,
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
        }
    }

    fn start(&mut self) {
        let mut stdin = stdio::stdin();
        loop {
            stdio::print(self.cmd_prompt);
            stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""      =>  { continue; }
                "\u274c"  =>  { return; }
                // _       =>  { self.line(cmd_line); }
                _ => { println!("You just ran {}", cmd_line) }
            }
        }
    }
}

fn main() {
    Shell::new("\U0001f41a \U0001f4b2 ").start();
}
<|endoftext|>


<commit_before>//! Importers for RAW volume files. A raw volume file is the raw bytes of
//! volume data in little endian, with X increasing first, then Y, then Z.

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::iter;
use std::mem;
use std::path::Path;

use num::{self, NumCast};

use crate::vec3::Vec3i;
use crate::vol::Volume;

/// Import a RAW volume file with the set dimensions. The volume data is
/// expected to be of type T which should be a primitive scalar type
pub fn import<T: NumCast>(path: &Path, dims: Vec3i) -> Volume {
    let mut f = match File::open(&path) {
        Ok(f) => BufReader::new(f),
        Err(e) => panic!("Error opening volume `{:?}`: {}", path, e),
    };
    let mut data: Vec<_> = iter::repeat(0u8)
        .take((dims.x * dims.y * dims.z) as usize * mem::size_of::<T>())
        .collect();
    f.read_exact(&mut data[..])
        .expect("Failed to read entire RAW volume");
    let data: Vec<f32> = data
        .chunks(mem::size_of::<T>())
        .map(|x| unsafe { mem::transmute_copy::<u8, T>(&x[0]) })
        .map(|x| num::cast(x).unwrap())
        .collect();
    let mut volume = Volume::new(dims);
    volume.set_region(&data[..], Vec3i::broadcast(0), dims);
    volume
}
<commit_msg>fix clippy failure found by weekly job<commit_after>//! Importers for RAW volume files. A raw volume file is the raw bytes of
//! volume data in little endian, with X increasing first, then Y, then Z.

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::iter;
use std::mem;
use std::path::Path;

use num::{self, NumCast};

use crate::vec3::Vec3i;
use crate::vol::Volume;

/// Import a RAW volume file with the set dimensions. The volume data is
/// expected to be of type T which should be a primitive scalar type
pub fn import<T: NumCast>(path: &Path, dims: Vec3i) -> Volume {
    let mut f = match File::open(path) {
        Ok(f) => BufReader::new(f),
        Err(e) => panic!("Error opening volume `{:?}`: {}", path, e),
    };
    let mut data: Vec<_> = iter::repeat(0u8)
        .take((dims.x * dims.y * dims.z) as usize * mem::size_of::<T>())
        .collect();
    f.read_exact(&mut data[..])
        .expect("Failed to read entire RAW volume");
    let data: Vec<f32> = data
        .chunks(mem::size_of::<T>())
        .map(|x| unsafe { mem::transmute_copy::<u8, T>(&x[0]) })
        .map(|x| num::cast(x).unwrap())
        .collect();
    let mut volume = Volume::new(dims);
    volume.set_region(&data[..], Vec3i::broadcast(0), dims);
    volume
}
<|endoftext|>


<commit_before>// The code below is a stub. Just enough to satisfy the compiler.
// In order to pass the tests you can add-to or change any of this code.

#[derive(Debug)]
pub struct Duration;

impl From<u64> for Duration {
    fn from(s: u64) -> Self {
        unimplemented!("s, measured in seconds: {}", s)
    }
}

pub trait Planet {
    fn years_during(d: &Duration) -> f64 {
        unimplemented!(
            "convert a duration ({:?}) to the number of years on this planet for that duration",
            d,
        );
    }
}

pub struct Mercury;
pub struct Venus;
pub struct Earth;
pub struct Mars;
pub struct Jupiter;
pub struct Saturn;
pub struct Uranus;
pub struct Neptune;

impl Planet for Mercury {}
impl Planet for Venus {}
impl Planet for Earth {}
impl Planet for Mars {}
impl Planet for Jupiter {}
impl Planet for Saturn {}
impl Planet for Uranus {}
impl Planet for Neptune {}
<commit_msg>Pass first test<commit_after>#[derive(Debug)]
pub struct Duration {
    seconds: u64,
}

impl From<u64> for Duration {
    fn from(seconds: u64) -> Self {
        return Self { seconds };
    }
}

pub trait Planet {
    fn years_during(duration: &Duration) -> f64 {
        unimplemented!(
            "convert a duration ({:?}) to the number of years on this planet for that duration",
            duration,
        );
    }
}

pub struct Mercury;
pub struct Venus;
pub struct Earth;
pub struct Mars;
pub struct Jupiter;
pub struct Saturn;
pub struct Uranus;
pub struct Neptune;

impl Planet for Mercury {}
impl Planet for Venus {}
impl Planet for Earth {
    fn years_during(duration: &Duration) -> f64 {
        const SECONDS_IN_EARTH_YEAR: f64 = 31557600.0;
        return duration.seconds as f64 / SECONDS_IN_EARTH_YEAR;
    }
}
impl Planet for Mars {}
impl Planet for Jupiter {}
impl Planet for Saturn {}
impl Planet for Uranus {}
impl Planet for Neptune {}
<|endoftext|>


<commit_before>//! `Middleware` to normalize request's URI

use actix_service::{Service, Transform};
use futures::future::{self, FutureResult};
use regex::Regex;

use crate::service::{ServiceRequest, ServiceResponse};
use crate::Error;

#[derive(Default, Clone, Copy)]
/// `Middleware` to normalize request's URI in place
///
/// Performs following:
///
/// - Merges multiple slashes into one.
pub struct NormalizePath;

impl<S> Transform<S> for NormalizePath
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse, Error = Error>,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse;
    type Error = Error;
    type InitError = ();
    type Transform = NormalizePathNormalization<S>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        future::ok(NormalizePathNormalization {
            service,
            merge_slash: Regex::new("//+").unwrap(),
        })
    }
}

pub struct NormalizePathNormalization<S> {
    service: S,
    merge_slash: Regex,
}

impl<S> Service for NormalizePathNormalization<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse, Error = Error>,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse;
    type Error = Error;
    type Future = S::Future;

    fn poll_ready(&mut self) -> futures::Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
        let head = req.head_mut();

        let path = head.uri.path();
        let original_len = path.len();
        let path = self.merge_slash.replace_all(path, "/");

        if original_len != path.len() {
            head.uri = path.parse().unwrap();
        }

        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_service::FnService;

    use super::*;
    use crate::dev::ServiceRequest;
    use crate::test::{block_on, TestRequest};
    use crate::HttpResponse;

    #[test]
    fn test_in_place_normalization() {
        let srv = FnService::new(|req: ServiceRequest| {
            assert_eq!("/v1/something/", req.path());
            req.into_response(HttpResponse::Ok().finish())
        });

        let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();

        let req = TestRequest::with_uri("/v1//something////").to_srv_request();
        let res = block_on(normalize.call(req)).unwrap();
        assert!(res.status().is_success());
    }

    #[test]
    fn should_normalize_nothing() {
        const URI: &str = "/v1/something/";

        let srv = FnService::new(|req: ServiceRequest| {
            assert_eq!(URI, req.path());
            req.into_response(HttpResponse::Ok().finish())
        });

        let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = block_on(normalize.call(req)).unwrap();
        assert!(res.status().is_success());
    }

}
<commit_msg>Add doctest to verify NormalizePath middleware (#809)<commit_after>//! `Middleware` to normalize request's URI

use actix_service::{Service, Transform};
use futures::future::{self, FutureResult};
use regex::Regex;

use crate::service::{ServiceRequest, ServiceResponse};
use crate::Error;

#[derive(Default, Clone, Copy)]
/// `Middleware` to normalize request's URI in place
///
/// Performs following:
///
/// - Merges multiple slashes into one.
///
/// ```rust
/// use actix_web::{web, http, middleware, App, HttpResponse};
///
/// fn main() {
///     let app = App::new()
///         .wrap(middleware::NormalizePath)
///         .service(
///             web::resource("/test")
///                 .route(web::get().to(|| HttpResponse::Ok()))
///                 .route(web::method(http::Method::HEAD).to(|| HttpResponse::MethodNotAllowed()))
///         );
/// }
/// ```

pub struct NormalizePath;

impl<S, B> Transform<S> for NormalizePath
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = NormalizePathNormalization<S>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        future::ok(NormalizePathNormalization {
            service,
            merge_slash: Regex::new("//+").unwrap(),
        })
    }
}

pub struct NormalizePathNormalization<S> {
    service: S,
    merge_slash: Regex,
}

impl<S, B> Service for NormalizePathNormalization<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = S::Future;

    fn poll_ready(&mut self) -> futures::Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
        let head = req.head_mut();

        let path = head.uri.path();
        let original_len = path.len();
        let path = self.merge_slash.replace_all(path, "/");

        if original_len != path.len() {
            head.uri = path.parse().unwrap();
        }

        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_service::FnService;

    use super::*;
    use crate::dev::ServiceRequest;
    use crate::test::{block_on, TestRequest};
    use crate::HttpResponse;

    #[test]
    fn test_in_place_normalization() {
        let srv = FnService::new(|req: ServiceRequest| {
            assert_eq!("/v1/something/", req.path());
            req.into_response(HttpResponse::Ok().finish())
        });

        let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();

        let req = TestRequest::with_uri("/v1//something////").to_srv_request();
        let res = block_on(normalize.call(req)).unwrap();
        assert!(res.status().is_success());
    }

    #[test]
    fn should_normalize_nothing() {
        const URI: &str = "/v1/something/";

        let srv = FnService::new(|req: ServiceRequest| {
            assert_eq!(URI, req.path());
            req.into_response(HttpResponse::Ok().finish())
        });

        let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = block_on(normalize.call(req)).unwrap();
        assert!(res.status().is_success());
    }

}
<|endoftext|>


<commit_before>#!/bin/bash
#![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc
pushd $(dirname "$0")/../
source scripts/config.sh
RUSTC="$(pwd)/build/bin/cg_clif"
popd
PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/

//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
//! profiles.
//!
//! Usage: ./filter_profile.rs <profile in stackcollapse format> <output file>
//!
//! This file is specially crafted to be both a valid bash script and valid rust source file. If
//! executed as bash script this will run the rust source using cg_clif in JIT mode.

use std::io::Write;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let profile_name = std::env::var("PROFILE").unwrap();
    let output_name = std::env::var("OUTPUT").unwrap();
    if profile_name.is_empty() || output_name.is_empty() {
        println!("Usage: ./filter_profile.rs <profile in stackcollapse format> <output file>");
        std::process::exit(1);
    }
    let profile = std::fs::read_to_string(profile_name)
        .map_err(|err| format!("Failed to read profile {}", err))?;
    let mut output = std::fs::OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(output_name)?;

    for line in profile.lines() {
        let mut stack = &line[..line.rfind(" ").unwrap()];
        let count = &line[line.rfind(" ").unwrap() + 1..];

        // Filter away uninteresting samples
        if !stack.contains("rustc_codegen_cranelift") {
            continue;
        }

        if stack.contains("rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items")
            || stack.contains("rustc_incremental::assert_dep_graph::assert_dep_graph")
            || stack.contains("rustc_symbol_mangling::test::report_symbol_names")
        {
            continue;
        }

        // Trim start
        if let Some(index) = stack.find("rustc_interface::passes::configure_and_expand") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::passes::analysis") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::passes::start_codegen") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::queries::Linker::link") {
            stack = &stack[index..];
        }

        if let Some(index) = stack.find("rustc_codegen_cranelift::driver::aot::module_codegen") {
            stack = &stack[index..];
        }

        // Trim end
        const MALLOC: &str = "malloc";
        if let Some(index) = stack.find(MALLOC) {
            stack = &stack[..index + MALLOC.len()];
        }

        const FREE: &str = "free";
        if let Some(index) = stack.find(FREE) {
            stack = &stack[..index + FREE.len()];
        }

        const TYPECK_ITEM_BODIES: &str = "rustc_typeck::check::typeck_item_bodies";
        if let Some(index) = stack.find(TYPECK_ITEM_BODIES) {
            stack = &stack[..index + TYPECK_ITEM_BODIES.len()];
        }

        const COLLECT_AND_PARTITION_MONO_ITEMS: &str =
            "rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items";
        if let Some(index) = stack.find(COLLECT_AND_PARTITION_MONO_ITEMS) {
            stack = &stack[..index + COLLECT_AND_PARTITION_MONO_ITEMS.len()];
        }

        const ASSERT_DEP_GRAPH: &str = "rustc_incremental::assert_dep_graph::assert_dep_graph";
        if let Some(index) = stack.find(ASSERT_DEP_GRAPH) {
            stack = &stack[..index + ASSERT_DEP_GRAPH.len()];
        }

        const REPORT_SYMBOL_NAMES: &str = "rustc_symbol_mangling::test::report_symbol_names";
        if let Some(index) = stack.find(REPORT_SYMBOL_NAMES) {
            stack = &stack[..index + REPORT_SYMBOL_NAMES.len()];
        }

        const ENCODE_METADATA: &str = "rustc_middle::ty::context::TyCtxt::encode_metadata";
        if let Some(index) = stack.find(ENCODE_METADATA) {
            stack = &stack[..index + ENCODE_METADATA.len()];
        }

        const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::subst_and_normalize_erasing_regions";
        if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) {
            stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()];
        }

        const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::normalize_erasing_late_bound_regions";
        if let Some(index) = stack.find(NORMALIZE_ERASING_LATE_BOUND_REGIONS) {
            stack = &stack[..index + NORMALIZE_ERASING_LATE_BOUND_REGIONS.len()];
        }

        const INST_BUILD: &str = "<cranelift_frontend::frontend::FuncInstBuilder as cranelift_codegen::ir::builder::InstBuilderBase>::build";
        if let Some(index) = stack.find(INST_BUILD) {
            stack = &stack[..index + INST_BUILD.len()];
        }

        output.write_all(stack.as_bytes())?;
        output.write_all(&*b" ")?;
        output.write_all(count.as_bytes())?;
        output.write_all(&*b"\n")?;
    }

    Ok(())
}
<commit_msg>Move monomorphize code to its own crate.<commit_after>#!/bin/bash
#![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc
pushd $(dirname "$0")/../
source scripts/config.sh
RUSTC="$(pwd)/build/bin/cg_clif"
popd
PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/

//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
//! profiles.
//!
//! Usage: ./filter_profile.rs <profile in stackcollapse format> <output file>
//!
//! This file is specially crafted to be both a valid bash script and valid rust source file. If
//! executed as bash script this will run the rust source using cg_clif in JIT mode.

use std::io::Write;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let profile_name = std::env::var("PROFILE").unwrap();
    let output_name = std::env::var("OUTPUT").unwrap();
    if profile_name.is_empty() || output_name.is_empty() {
        println!("Usage: ./filter_profile.rs <profile in stackcollapse format> <output file>");
        std::process::exit(1);
    }
    let profile = std::fs::read_to_string(profile_name)
        .map_err(|err| format!("Failed to read profile {}", err))?;
    let mut output = std::fs::OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(output_name)?;

    for line in profile.lines() {
        let mut stack = &line[..line.rfind(" ").unwrap()];
        let count = &line[line.rfind(" ").unwrap() + 1..];

        // Filter away uninteresting samples
        if !stack.contains("rustc_codegen_cranelift") {
            continue;
        }

        if stack.contains("rustc_monomorphize::partitioning::collect_and_partition_mono_items")
            || stack.contains("rustc_incremental::assert_dep_graph::assert_dep_graph")
            || stack.contains("rustc_symbol_mangling::test::report_symbol_names")
        {
            continue;
        }

        // Trim start
        if let Some(index) = stack.find("rustc_interface::passes::configure_and_expand") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::passes::analysis") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::passes::start_codegen") {
            stack = &stack[index..];
        } else if let Some(index) = stack.find("rustc_interface::queries::Linker::link") {
            stack = &stack[index..];
        }

        if let Some(index) = stack.find("rustc_codegen_cranelift::driver::aot::module_codegen") {
            stack = &stack[index..];
        }

        // Trim end
        const MALLOC: &str = "malloc";
        if let Some(index) = stack.find(MALLOC) {
            stack = &stack[..index + MALLOC.len()];
        }

        const FREE: &str = "free";
        if let Some(index) = stack.find(FREE) {
            stack = &stack[..index + FREE.len()];
        }

        const TYPECK_ITEM_BODIES: &str = "rustc_typeck::check::typeck_item_bodies";
        if let Some(index) = stack.find(TYPECK_ITEM_BODIES) {
            stack = &stack[..index + TYPECK_ITEM_BODIES.len()];
        }

        const COLLECT_AND_PARTITION_MONO_ITEMS: &str =
            "rustc_monomorphize::partitioning::collect_and_partition_mono_items";
        if let Some(index) = stack.find(COLLECT_AND_PARTITION_MONO_ITEMS) {
            stack = &stack[..index + COLLECT_AND_PARTITION_MONO_ITEMS.len()];
        }

        const ASSERT_DEP_GRAPH: &str = "rustc_incremental::assert_dep_graph::assert_dep_graph";
        if let Some(index) = stack.find(ASSERT_DEP_GRAPH) {
            stack = &stack[..index + ASSERT_DEP_GRAPH.len()];
        }

        const REPORT_SYMBOL_NAMES: &str = "rustc_symbol_mangling::test::report_symbol_names";
        if let Some(index) = stack.find(REPORT_SYMBOL_NAMES) {
            stack = &stack[..index + REPORT_SYMBOL_NAMES.len()];
        }

        const ENCODE_METADATA: &str = "rustc_middle::ty::context::TyCtxt::encode_metadata";
        if let Some(index) = stack.find(ENCODE_METADATA) {
            stack = &stack[..index + ENCODE_METADATA.len()];
        }

        const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::subst_and_normalize_erasing_regions";
        if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) {
            stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()];
        }

        const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::normalize_erasing_late_bound_regions";
        if let Some(index) = stack.find(NORMALIZE_ERASING_LATE_BOUND_REGIONS) {
            stack = &stack[..index + NORMALIZE_ERASING_LATE_BOUND_REGIONS.len()];
        }

        const INST_BUILD: &str = "<cranelift_frontend::frontend::FuncInstBuilder as cranelift_codegen::ir::builder::InstBuilderBase>::build";
        if let Some(index) = stack.find(INST_BUILD) {
            stack = &stack[..index + INST_BUILD.len()];
        }

        output.write_all(stack.as_bytes())?;
        output.write_all(&*b" ")?;
        output.write_all(count.as_bytes())?;
        output.write_all(&*b"\n")?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate mio;
extern crate rand;

use mio::tcp::*;
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::*;

trait QuoteProviderImpl {
  fn get_quote(&self, usize) -> String;
  fn get_random_quote(&self) -> String;
  fn new() -> Self;
}

struct QuoteProvider {
  quotes: Vec<String>,
}

impl QuoteProviderImpl for QuoteProvider {

  fn get_quote(&self, index: usize) -> String {
    //todo: pointers not clones?
    self.quotes[index].clone()
  }

  fn get_random_quote(&self) -> String {
    //todo: cache rng for improved perf
    let mut rng = thread_rng();
    let index: usize = rng.gen_range(0, self.quotes.len());
    self.get_quote(index)
  }

  fn new() -> QuoteProvider {
    let mut quotes: Vec<String> = Vec::new();
    println!("Reading wisdom...");
    //todo: check exists
    //todo: pass in as arg
    let path = "../../src/server/wisdom.txt";
    let result = File::open(path);
    match result {
        Ok(file) => {
            let reader = BufReader::new(file);
            for line in reader.lines {
                match line {
                    Ok (line_str) => {
                        if line_str.len() > 0 {
                            quotes.push(line_str);
                        } else {
                            println!("Skipped blank line in file.");
                        }
                    },
                    Err(e) => println!("Invalid line. Skipping... {:?}",e)
                }
            }

        },
        Err(e) => println!("Failed to open wisdom file {:?}. {:?}", path, e)
    }

    QuoteProvider {quotes: quotes}
  }
}

const SERVER: mio::Token = mio::Token(0);

struct Pong {
    server: TcpListener,
}

impl mio::Handler for Pong {
    type Timeout = ();
    type Message = ();

    fn readable(&mut self, event_loop: &mut mio::EventLoop<Pong>, token: mio::Token, hint: mio::ReadHint) {
        match token {
            SERVER => {
                println!("the server socket is ready to accept a connection");
                match self.server.accept() {
                    Ok(Some(connection)) => {
                        println!("accepted a socket, exiting program");
                        event_loop.shutdown();
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready");
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        event_loop.shutdown();
                    }
                }
            }
            _ => panic!("Received unknown token"),
        }
    }
}

fn main() {

    let quote_provider: QuoteProvider = QuoteProviderImpl::new();
    println!("Sample quote: {:?}", quote_provider.get_random_quote());

    let address = "0.0.0.0:6567".parse().unwrap();
    let server = TcpListener::bind(&address).unwrap();

    let mut event_loop = mio::EventLoop::new().unwrap();
    let _ = event_loop.register(&server, SERVER);

    println!("running pingpong server");
    let _ = event_loop.run(&mut Pong { server: server });
}<commit_msg>tcp working. udp in progress<commit_after>extern crate mio;
extern crate rand;

use mio::{EventLoop,Token,TryWrite};
use mio::tcp::*;
use mio::udp::*;
use mio::buf::*;
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::*;

trait QuoteProviderImpl {
  fn get_quote(&self, usize) -> String;
  fn get_random_quote(&self) -> String;
  fn new() -> Self;
}

struct QuoteProvider {
  quotes: Vec<String>,
}

impl QuoteProviderImpl for QuoteProvider {

  fn get_quote(&self, index: usize) -> String {
    //todo: pointers not clones?
    self.quotes[index].clone()
  }

  fn get_random_quote(&self) -> String {
    //todo: cache rng for improved perf
    let mut rng = thread_rng();
    let index: usize = rng.gen_range(0, self.quotes.len());
    self.get_quote(index)
  }

  fn new() -> QuoteProvider {
    let mut quotes: Vec<String> = Vec::new();
    println!("Reading wisdom...");
    //todo: check exists
    //todo: pass in as arg
    let path = "../../src/server/wisdom.txt";
    let result = File::open(path);
    match result {
        Ok(file) => {
            let reader = BufReader::new(file);
            for line in reader.lines() {
                match line {
                    Ok (line_str) => {
                        if line_str.len() > 0 {
                            quotes.push(line_str + "\r\n");
                        } else {
                            println!("Skipped blank line in file.");
                        }
                    },
                    Err(e) => println!("Invalid line. Skipping... {:?}",e)
                }
            }

        },
        Err(e) => println!("Failed to open wisdom file {:?}. {:?}", path, e)
    }

    QuoteProvider {quotes: quotes}
  }
}

const TCP_SERVER: mio::Token = mio::Token(0);
const UDP_SERVER: mio::Token = mio::Token(1);

struct Pong {
    tcp_server: TcpListener,
    udp_server: UdpSocket,
    quote_provider: QuoteProvider
}

impl mio::Handler for Pong {
    type Timeout = ();
    type Message = ();

    fn readable(&mut self, event_loop: &mut mio::EventLoop<Pong>, token: mio::Token, hint: mio::ReadHint) {
        match token {
            TCP_SERVER => {
                println!("the server socket is ready to accept a TCP connection");
                match self.tcp_server.accept() {
                    Ok(Some(mut connection)) => {
                        println!("accepted a socket {:?}", connection);
                        let quote = self.quote_provider.get_random_quote();
                        connection.write_slice(quote.as_bytes());
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready");
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        event_loop.shutdown();
                    }
                }
            }
            UDP_SERVER => {
                println!("the server socket is ready to accept a UDP connection");
                //let mut buf = [0, ..10];
                match self.udp_server.recv_from(buf) {
                    Ok((amt, src)) => {
                        // Send a reply to the socket we received data from
                        //let buf = buf.mut_slice_to(amt);
                        //buf.reverse();
                        //self.udp_server.send_to(buf, src);
                    }
                    Err(e) => println!("couldn't receive a datagram: {}", e)
                }
            }
            _ => panic!("Received unknown token"),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Pong>, token: Token) {
        match token {
            TCP_SERVER => println!("received writable for token 0"),
            _ => panic!("Unexpected token")
        };
    }
}

fn main() {

    let quote_provider: QuoteProvider = QuoteProviderImpl::new();
    println!("Sample quote: {:?}", quote_provider.get_random_quote());

    let address = "0.0.0.0:6567".parse().unwrap();
    let tcp_server = TcpListener::bind(&address).unwrap();
    let udp_server = UdpSocket::v4().unwrap();
    udp_server.bind(&address);

    let mut event_loop = mio::EventLoop::new().unwrap();
    let _ = event_loop.register(&tcp_server, TCP_SERVER);

    println!("running pingpong server");
    let _ = event_loop.run(&mut Pong
    {
        tcp_server: tcp_server,
        udp_server: udp_server,
        quote_provider: quote_provider
    });

    drop(udp_server); // close the socket
    drop(tcp_server);

}<|endoftext|>


<commit_before>use gl;
use gl::types::*;
use texture::{Texture2dBinder, TextureCubeMapBinder};
use uniform_data::{UniformDatum, UniformDatumType, UniformPrimitiveType};
use types::GLError;

unsafe fn _active_texture(idx: u32) {
    gl::ActiveTexture(gl::TEXTURE0 + (idx as GLenum));
    dbg_gl_error! {
        GLError::InvalidEnum => "`texture` is out of bounds (expected to be GL_TEXTUREi, 0 <= i < GL_MAX_TEXTURE_IMAGE_UNITS)",
        _ => "Unknown error"
    }
}

pub trait TextureUnit {
    fn idx() -> u32;

    fn active(&mut self) -> TextureUnitBinding {
        unsafe {
            _active_texture(Self::idx());
            TextureUnitBinding::current_at_idx(Self::idx())
        }
    }
}

// TODO: Use a macro, or const generic parameters:
// https://github.com/rust-lang/rfcs/issues/273
// https://github.com/rust-lang/rfcs/issues/1038
pub struct TextureUnit0;
pub struct TextureUnit1;
pub struct TextureUnit2;
pub struct TextureUnit3;
pub struct TextureUnit4;
pub struct TextureUnit5;
pub struct TextureUnit6;
pub struct TextureUnit7;

impl TextureUnit for TextureUnit0 { fn idx() -> u32 { 0 } }
impl TextureUnit for TextureUnit1 { fn idx() -> u32 { 1 } }
impl TextureUnit for TextureUnit2 { fn idx() -> u32 { 2 } }
impl TextureUnit for TextureUnit3 { fn idx() -> u32 { 3 } }
impl TextureUnit for TextureUnit4 { fn idx() -> u32 { 4 } }
impl TextureUnit for TextureUnit5 { fn idx() -> u32 { 5 } }
impl TextureUnit for TextureUnit6 { fn idx() -> u32 { 6 } }
impl TextureUnit for TextureUnit7 { fn idx() -> u32 { 7 } }

// NOTE: Ensure the number of each texture unit matches its index in the tuple
pub struct TextureUnits(pub TextureUnit0, pub TextureUnit1, pub TextureUnit2,
                        pub TextureUnit3, pub TextureUnit4, pub TextureUnit5,
                        pub TextureUnit6, pub TextureUnit7);

impl TextureUnits {
    pub unsafe fn current() -> TextureUnits {
        TextureUnits(TextureUnit0, TextureUnit1, TextureUnit2, TextureUnit3,
                     TextureUnit4, TextureUnit5, TextureUnit6, TextureUnit7)
    }

    pub unsafe fn active_nth(&self, idx: u32) -> TextureUnitBinding {
        _active_texture(idx);
        TextureUnitBinding::current_at_idx(idx)
    }
}

pub struct TextureUnitBinding {
    idx: u32,
    pub texture_2d: Texture2dBinder,
    pub texture_cube_map: TextureCubeMapBinder
}

impl TextureUnitBinding {
    unsafe fn current_at_idx(idx: u32) -> Self {
        TextureUnitBinding {
            idx: idx,
            texture_2d: Texture2dBinder,
            texture_cube_map: TextureCubeMapBinder
        }
    }

    pub fn gl_idx(&self) -> u32 {
        self.idx
    }

    pub fn sampler(&self) -> TextureSampler {
        TextureSampler { idx: self.idx as i32 }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct TextureSampler { idx: i32 }

unsafe impl UniformDatum for TextureSampler {
    fn uniform_datum_type() -> UniformDatumType {
        UniformDatumType::Vec1(UniformPrimitiveType::Int)
    }
}

#[macro_export]
macro_rules! bind_texture_cube_map {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_cube_map.bind($texture)
    }
}

#[macro_export]
macro_rules! bind_texture_2d {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_2d.bind($texture)
    }
}
<commit_msg>Replace `TextureUnits` with `TextureUnitsOf`<commit_after>use gl;
use gl::types::*;
use texture::{Texture2dBinder, TextureCubeMapBinder};
use uniform_data::{UniformDatum, UniformDatumType, UniformPrimitiveType};
use types::GLError;

unsafe fn _active_texture(idx: u32) {
    gl::ActiveTexture(gl::TEXTURE0 + (idx as GLenum));
    dbg_gl_error! {
        GLError::InvalidEnum => "`texture` is out of bounds (expected to be GL_TEXTUREi, 0 <= i < GL_MAX_TEXTURE_IMAGE_UNITS)",
        _ => "Unknown error"
    }
}

pub trait TextureUnit {
    fn idx() -> u32;

    fn active(&mut self) -> TextureUnitBinding {
        unsafe {
            _active_texture(Self::idx());
            TextureUnitBinding::current_at_idx(Self::idx())
        }
    }
}

// TODO: Use a macro, or const generic parameters:
// https://github.com/rust-lang/rfcs/issues/273
// https://github.com/rust-lang/rfcs/issues/1038
pub struct TextureUnit0;
pub struct TextureUnit1;
pub struct TextureUnit2;
pub struct TextureUnit3;
pub struct TextureUnit4;
pub struct TextureUnit5;
pub struct TextureUnit6;
pub struct TextureUnit7;

impl TextureUnit for TextureUnit0 { fn idx() -> u32 { 0 } }
impl TextureUnit for TextureUnit1 { fn idx() -> u32 { 1 } }
impl TextureUnit for TextureUnit2 { fn idx() -> u32 { 2 } }
impl TextureUnit for TextureUnit3 { fn idx() -> u32 { 3 } }
impl TextureUnit for TextureUnit4 { fn idx() -> u32 { 4 } }
impl TextureUnit for TextureUnit5 { fn idx() -> u32 { 5 } }
impl TextureUnit for TextureUnit6 { fn idx() -> u32 { 6 } }
impl TextureUnit for TextureUnit7 { fn idx() -> u32 { 7 } }

// NOTE: Ensure the number of each texture unit matches its index in the tuple
// TODO: Use macros + integer-level types to refactor this
pub struct TextureUnitsOf<T0, T1, T2, T3, T4, T5, T6, T7>(pub T0,
                                                          pub T1,
                                                          pub T2,
                                                          pub T3,
                                                          pub T4,
                                                          pub T5,
                                                          pub T6,
                                                          pub T7);

pub type TextureUnits = TextureUnitsOf<TextureUnit0,
                                       TextureUnit1,
                                       TextureUnit2,
                                       TextureUnit3,
                                       TextureUnit4,
                                       TextureUnit5,
                                       TextureUnit6,
                                       TextureUnit7>;

impl<T0, T1, T2, T3, T4, T5, T6, T7> TextureUnitsOf<T0,
                                                    T1,
                                                    T2,
                                                    T3,
                                                    T4,
                                                    T5,
                                                    T6,
                                                    T7>
{
    pub unsafe fn current() -> TextureUnits {
        TextureUnitsOf(TextureUnit0,
                       TextureUnit1,
                       TextureUnit2,
                       TextureUnit3,
                       TextureUnit4,
                       TextureUnit5,
                       TextureUnit6,
                       TextureUnit7)
    }

    pub unsafe fn active_nth(&self, idx: u32) -> TextureUnitBinding {
        _active_texture(idx);
        TextureUnitBinding::current_at_idx(idx)
    }
}

pub struct TextureUnitBinding {
    idx: u32,
    pub texture_2d: Texture2dBinder,
    pub texture_cube_map: TextureCubeMapBinder
}

impl TextureUnitBinding {
    unsafe fn current_at_idx(idx: u32) -> Self {
        TextureUnitBinding {
            idx: idx,
            texture_2d: Texture2dBinder,
            texture_cube_map: TextureCubeMapBinder
        }
    }

    pub fn gl_idx(&self) -> u32 {
        self.idx
    }

    pub fn sampler(&self) -> TextureSampler {
        TextureSampler { idx: self.idx as i32 }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct TextureSampler { idx: i32 }

unsafe impl UniformDatum for TextureSampler {
    fn uniform_datum_type() -> UniformDatumType {
        UniformDatumType::Vec1(UniformPrimitiveType::Int)
    }
}

#[macro_export]
macro_rules! bind_texture_cube_map {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_cube_map.bind($texture)
    }
}

#[macro_export]
macro_rules! bind_texture_2d {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_2d.bind($texture)
    }
}
<|endoftext|>


<commit_before>//! Targets the Nintendo Game Boy Advance (GBA),
//! a handheld game device from 2001.
//!
//! Please ping @Lokathor if changes are needed.
//!
//! The target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager
//!
//! **Important:** This target profile **does not** specify a linker script or the ROM header. You'll still need to provide these yourself to construct a final  binary. Generally you'd do this with something like `-Clink-arg=-Tmy_script.ld` and `-Clink-arg=my_crt.o`.

use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: "gba".to_string(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        /* Data layout args are '-' separated:
         * little endian
         * stack is 64-bit aligned (EABI)
         * pointers are 32-bit
         * i64 must be 64-bit aligned (EABI)
         * mangle names with ELF style
         * native integers are 32-bit
         * All other elements are default
         */
        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            linker: Some("arm-none-eabi-ld".to_string()),
            linker_is_gnu: true,

            // extra args passed to the external assembler
            asm_args: vec!["-mcpu=arm7tdmi".to_string(), "-mthumb-interwork".to_string()],

            cpu: "arm7tdmi".to_string(),

            // minimum extra features, these cannot be disabled via -C
            features: "+soft-float,+strict-align".to_string(),

            executables: true,

            relocation_model: RelocModel::Static,

            //function_sections: bool,
            //exe_suffix: String,
            main_needs_argc_argv: false,

            // if we have thread-local storage
            has_elf_tls: false,

            // don't have atomic compare-and-swap
            atomic_cas: false,

            // always just abort
            panic_strategy: PanicStrategy::Abort,

            // ABIs to not use
            unsupported_abis: super::arm_base::unsupported_abis(),

            // this is off just like in the `thumb_base`
            emit_debug_gdb_scripts: false,

            ..TargetOptions::default()
        },
    })
}
<commit_msg>Resolve https://github.com/rust-lang/rust/pull/74419#discussion_r456139741<commit_after>//! Targets the Nintendo Game Boy Advance (GBA),
//! a handheld game device from 2001.
//!
//! Please ping @Lokathor if changes are needed.
//!
//! The target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager
//!
//! **Important:** This target profile **does not** specify a linker script or the ROM header. You'll still need to provide these yourself to construct a final  binary. Generally you'd do this with something like `-Clink-arg=-Tmy_script.ld` and `-Clink-arg=my_crt.o`.

use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: "gba".to_string(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        /* Data layout args are '-' separated:
         * little endian
         * stack is 64-bit aligned (EABI)
         * pointers are 32-bit
         * i64 must be 64-bit aligned (EABI)
         * mangle names with ELF style
         * native integers are 32-bit
         * All other elements are default
         */
        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            linker: Some("arm-none-eabi-ld".to_string()),
            linker_is_gnu: true,

            // extra args passed to the external assembler
            asm_args: vec!["-mcpu=arm7tdmi".to_string(), "-mthumb-interwork".to_string()],

            cpu: "arm7tdmi".to_string(),

            // minimum extra features, these cannot be disabled via -C
            features: "+soft-float,+strict-align".to_string(),

            executables: true,

            relocation_model: RelocModel::Static,

            main_needs_argc_argv: false,

            // if we have thread-local storage
            has_elf_tls: false,

            // don't have atomic compare-and-swap
            atomic_cas: false,

            // always just abort
            panic_strategy: PanicStrategy::Abort,

            // ABIs to not use
            unsupported_abis: super::arm_base::unsupported_abis(),

            // this is off just like in the `thumb_base`
            emit_debug_gdb_scripts: false,

            ..TargetOptions::default()
        },
    })
}
<|endoftext|>


<commit_before>extern crate rustbox;

use cursor::Direction;
use buffer::Buffer;
use cursor::Cursor;
use uibuf::UIBuffer;

use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    pub top_line_num: uint,
    pub cursor: Cursor<'v>,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(path: Option<String>) -> View<'v> {
        let buffer = match path {
            Some(s) => Buffer::new_from_file(&Path::new(s)),
            None    => Buffer::new_empty(),
        };

        let term_width = utils::get_term_width();
        let term_height = utils::get_term_height();
        let uibuf = UIBuffer::new(term_width, term_height);
        let mut cursor = Cursor::new();
        cursor.set_line(Some(&buffer.lines[0]));

        View {
            buffer: buffer,
            top_line_num: 0,
            cursor: cursor,
            uibuf: uibuf,
            threshold: 5,
        }
    }

    /// Get the height of the view in which content can be drawn
    ///
    /// Excludes the status bar height
    pub fn get_internal_height(&self) -> uint {
        let term_height = utils::get_term_height();

        term_height - 2
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
    }

    pub fn draw(&mut self) {
        let height = self.get_internal_height();

        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index <= height {
                let ln = line.borrow();
                let data = ln.data.clone();
                for (ch_index, ch) in data.iter().enumerate() {
                    self.uibuf.update_cell_content(ch_index, index, *ch as char);
                }
            }
        }
        self.uibuf.draw_range(0, height+1);
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor.get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let term_height = utils::get_term_height();
        let term_width = utils::get_term_width();

        for index in range(0, term_width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, term_height-1, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(term_height-1, term_height);
    }

    pub fn draw_cursor(&self) {
        let offset = self.cursor.get_offset();
        let linenum = self.cursor.get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.cursor.move_right(); },
            Direction::Left  => { self.cursor.move_left(); },
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        self.set_cursor_line(prev_linenum);

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        self.set_cursor_line(next_linenum);

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_internal_height() as int;

        // TODO(greg) move this value
        // let threshold: int = 5;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn set_cursor_line(&mut self, linenum: uint) {
        let line = &self.buffer.lines[linenum];
        self.cursor.set_line(Some(line));
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor.get_position();

        if offset == 0 && direction.is_left() {
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.move_cursor_up();
            self.cursor.set_offset(offset);
            return
        }

        let line_len = self.cursor.get_line_length();
        if offset == line_len && direction.is_right() {
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor.delete_backward_char(),
            Direction::Right => self.cursor.delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor.insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor.get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor.set_offset(0);
    }
}

#[cfg(test)]
mod tests {

    use std::cell::RefCell;

    use buffer::{Line, Buffer};
    use cursor::{Cursor, Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils::data_from_str;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            cursor: Cursor::new(),
            uibuf: UIBuffer::new(50, 50),
            threshold: 5,
        };

        let first_line = RefCell::new(Line::new(data_from_str("test"), 0));
        let second_line = RefCell::new(Line::new(data_from_str("second"), 1));

        view.buffer.lines = vec!(first_line, second_line);
        view.cursor.set_line(Some(&view.buffer.lines[0]));

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor.get_linenum(), 1);
        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("second"));
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor.get_linenum(), 0);
        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("test"));
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor.get_offset(), 0);
        assert_eq!(view.cursor.get_line().borrow().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("ttest"));
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("testsecond"));
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.cursor.set_offset(4);
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("testsecond"));
    }
}
<commit_msg>Fixed line deletion issue when cursor is at 0-0<commit_after>extern crate rustbox;

use cursor::Direction;
use buffer::Buffer;
use cursor::Cursor;
use uibuf::UIBuffer;

use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    pub top_line_num: uint,
    pub cursor: Cursor<'v>,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(path: Option<String>) -> View<'v> {
        let buffer = match path {
            Some(s) => Buffer::new_from_file(&Path::new(s)),
            None    => Buffer::new_empty(),
        };

        let term_width = utils::get_term_width();
        let term_height = utils::get_term_height();
        let uibuf = UIBuffer::new(term_width, term_height);
        let mut cursor = Cursor::new();
        cursor.set_line(Some(&buffer.lines[0]));

        View {
            buffer: buffer,
            top_line_num: 0,
            cursor: cursor,
            uibuf: uibuf,
            threshold: 5,
        }
    }

    /// Get the height of the view in which content can be drawn
    ///
    /// Excludes the status bar height
    pub fn get_internal_height(&self) -> uint {
        let term_height = utils::get_term_height();

        term_height - 2
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
    }

    pub fn draw(&mut self) {
        let height = self.get_internal_height();

        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index <= height {
                let ln = line.borrow();
                let data = ln.data.clone();
                for (ch_index, ch) in data.iter().enumerate() {
                    self.uibuf.update_cell_content(ch_index, index, *ch as char);
                }
            }
        }
        self.uibuf.draw_range(0, height+1);
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor.get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let term_height = utils::get_term_height();
        let term_width = utils::get_term_width();

        for index in range(0, term_width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, term_height-1, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(term_height-1, term_height);
    }

    pub fn draw_cursor(&self) {
        let offset = self.cursor.get_offset();
        let linenum = self.cursor.get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.cursor.move_right(); },
            Direction::Left  => { self.cursor.move_left(); },
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        self.set_cursor_line(prev_linenum);

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        self.set_cursor_line(next_linenum);

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_internal_height() as int;

        // TODO(greg) move this value
        // let threshold: int = 5;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn set_cursor_line(&mut self, linenum: uint) {
        let line = &self.buffer.lines[linenum];
        self.cursor.set_line(Some(line));
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor.get_position();

        if offset == 0 && direction.is_left() {
            if line_num == 0 { return }
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.move_cursor_up();
            self.cursor.set_offset(offset);
            return
        }

        let line_len = self.cursor.get_line_length();
        if offset == line_len && direction.is_right() {
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor.delete_backward_char(),
            Direction::Right => self.cursor.delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor.insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor.get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor.set_offset(0);
    }
}

#[cfg(test)]
mod tests {

    use std::cell::RefCell;

    use buffer::{Line, Buffer};
    use cursor::{Cursor, Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils::data_from_str;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            cursor: Cursor::new(),
            uibuf: UIBuffer::new(50, 50),
            threshold: 5,
        };

        let first_line = RefCell::new(Line::new(data_from_str("test"), 0));
        let second_line = RefCell::new(Line::new(data_from_str("second"), 1));

        view.buffer.lines = vec!(first_line, second_line);
        view.cursor.set_line(Some(&view.buffer.lines[0]));

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor.get_linenum(), 1);
        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("second"));
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor.get_linenum(), 0);
        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("test"));
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor.get_offset(), 0);
        assert_eq!(view.cursor.get_line().borrow().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("ttest"));
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("testsecond"));
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.cursor.set_offset(4);
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, data_from_str("testsecond"));
    }
}
<|endoftext|>


<commit_before>use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: std::env::Args,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    let argv_remainder: Vec<String> = options.argv_remainder.collect();
    command.args(argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: std::env::Args) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));

    let argv_remainder: Vec<String> = args.collect();
    command.args(argv_remainder);

    command
}

fn init_command() -> Command {
    let mut args = std::env::args();
    args.next();

    let target = args.next().unwrap();
    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: None, //FIREFOX_PROFILE,
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: None, //KEIRA_PROFILE,
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => return simple_firejail_command("mpv", args),
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: None, //THUNDERBIRD_PROFILE,
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => return simple_firejail_command("vlc", args),
        "z" => return simple_firejail_command("zathura", args),
        _ => panic!(format!("no handler for ``{}''", target)),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<commit_msg>unner: address firejail issue no. 3219<commit_after>use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: std::env::Args,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg("--ignore=seccomp");
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    let argv_remainder: Vec<String> = options.argv_remainder.collect();
    command.args(argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: std::env::Args) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));

    let argv_remainder: Vec<String> = args.collect();
    command.args(argv_remainder);

    command
}

fn init_command() -> Command {
    let mut args = std::env::args();
    args.next();

    let target = args.next().unwrap();
    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(KEIRA_PROFILE),
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => return simple_firejail_command("mpv", args),
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(THUNDERBIRD_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => return simple_firejail_command("vlc", args),
        "z" => return simple_firejail_command("zathura", args),
        _ => panic!(format!("no handler for ``{}''", target)),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<|endoftext|>