<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Integer and floating-point number formatting

// FIXME: #6220 Implement floating point formatting

use prelude::v1::*;

use fmt;
use num::Zero;
use ops::{Div, Rem, Sub};
use str;
use slice;
use ptr;
use mem;

#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
           Sub<Output=Self> + Copy {
    fn from_u8(u: u8) -> Self;
    fn to_u8(&self) -> u8;
    fn to_u32(&self) -> u32;
    fn to_u64(&self) -> u64;
}

macro_rules! doit {
    ($($t:ident)*) => ($(impl Int for $t {
        fn from_u8(u: u8) -> $t { u as $t }
        fn to_u8(&self) -> u8 { *self as u8 }
        fn to_u32(&self) -> u32 { *self as u32 }
        fn to_u64(&self) -> u64 { *self as u64 }
    })*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

/// A type that represents a specific radix
#[doc(hidden)]
trait GenericRadix {
    /// The number of digits.
    fn base(&self) -> u8;

    /// A radix-specific prefix string.
    fn prefix(&self) -> &'static str {
        ""
    }

    /// Converts an integer to corresponding radix digit.
    fn digit(&self, x: u8) -> u8;

    /// Format an integer using the radix using a formatter.
    fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
        // The radix can be as low as 2, so we need a buffer of at least 64
        // characters for a base 2 number.
        let zero = T::zero();
        let is_positive = x >= zero;
        let mut buf = [0; 64];
        let mut curr = buf.len();
        let base = T::from_u8(self.base());
        if is_positive {
            // Accumulate each digit of the number from the least significant
            // to the most significant figure.
            for byte in buf.iter_mut().rev() {
                let n = x % base;              // Get the current place value.
                x = x / base;                  // Deaccumulate the number.
                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                curr -= 1;
                if x == zero {
                    // No more digits left to accumulate.
                    break
                };
            }
        } else {
            // Do the same as above, but accounting for two's complement.
            for byte in buf.iter_mut().rev() {
                let n = zero - (x % base);     // Get the current place value.
                x = x / base;                  // Deaccumulate the number.
                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                curr -= 1;
                if x == zero {
                    break
                };        // No more digits left to accumulate.
            }
        }
        let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
        f.pad_integral(is_positive, self.prefix(), buf)
    }
}

/// A binary (base 2) radix
#[derive(Clone, PartialEq)]
struct Binary;

/// An octal (base 8) radix
#[derive(Clone, PartialEq)]
struct Octal;

/// A decimal (base 10) radix
#[derive(Clone, PartialEq)]
struct Decimal;

/// A hexadecimal (base 16) radix, formatted with lower-case characters
#[derive(Clone, PartialEq)]
struct LowerHex;

/// A hexadecimal (base 16) radix, formatted with upper-case characters
#[derive(Clone, PartialEq)]
struct UpperHex;

macro_rules! radix {
    ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
        impl GenericRadix for $T {
            fn base(&self) -> u8 { $base }
            fn prefix(&self) -> &'static str { $prefix }
            fn digit(&self, x: u8) -> u8 {
                match x {
                    $($x => $conv,)+
                    x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
                }
            }
        }
    }
}

radix! { Binary,    2, "0b", x @  0 ...  2 => b'0' + x }
radix! { Octal,     8, "0o", x @  0 ...  7 => b'0' + x }
radix! { Decimal,  10, "",   x @  0 ...  9 => b'0' + x }
radix! { LowerHex, 16, "0x", x @  0 ...  9 => b'0' + x,
                             x @ 10 ... 15 => b'a' + (x - 10) }
radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
                             x @ 10 ... 15 => b'A' + (x - 10) }

/// A radix with in the range of `2..36`.
#[derive(Clone, Copy, PartialEq)]
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
pub struct Radix {
    base: u8,
}

impl Radix {
    fn new(base: u8) -> Radix {
        assert!(2 <= base && base <= 36,
                "the base must be in the range of 2..36: {}",
                base);
        Radix { base: base }
    }
}

impl GenericRadix for Radix {
    fn base(&self) -> u8 {
        self.base
    }
    fn digit(&self, x: u8) -> u8 {
        match x {
            x @  0 ... 9 => b'0' + x,
            x if x < self.base() => b'a' + (x - 10),
            x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
        }
    }
}

/// A helper type for formatting radixes.
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
#[derive(Copy, Clone)]
pub struct RadixFmt<T, R>(T, R);

/// Constructs a radix formatter in the range of `2..36`.
///
/// # Examples
///
/// ```
/// #![feature(fmt_radix)]
///
/// use std::fmt::radix;
/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
/// ```
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
    RadixFmt(x, Radix::new(base))
}

macro_rules! radix_fmt {
    ($T:ty as $U:ty, $fmt:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Debug for RadixFmt<$T, Radix> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt::Display::fmt(self, f)
            }
        }
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Display for RadixFmt<$T, Radix> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self { RadixFmt(ref x, radix) => radix.$fmt(*x as $U, f) }
            }
        }
    }
}

macro_rules! int_base {
    ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::$Trait for $T {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                $Radix.fmt_int(*self as $U, f)
            }
        }
    }
}

macro_rules! debug {
    ($T:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Debug for $T {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt::Display::fmt(self, f)
            }
        }
    }
}

macro_rules! integer {
    ($Int:ident, $Uint:ident) => {
        int_base! { Binary   for $Int as $Uint  -> Binary }
        int_base! { Octal    for $Int as $Uint  -> Octal }
        int_base! { LowerHex for $Int as $Uint  -> LowerHex }
        int_base! { UpperHex for $Int as $Uint  -> UpperHex }
        radix_fmt! { $Int as $Int, fmt_int }
        debug! { $Int }

        int_base! { Binary   for $Uint as $Uint -> Binary }
        int_base! { Octal    for $Uint as $Uint -> Octal }
        int_base! { LowerHex for $Uint as $Uint -> LowerHex }
        int_base! { UpperHex for $Uint as $Uint -> UpperHex }
        radix_fmt! { $Uint as $Uint, fmt_int }
        debug! { $Uint }
    }
}
integer! { isize, usize }
integer! { i8, u8 }
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

macro_rules! impl_Display {
    ($($t:ident),*: $conv_fn:ident) => ($(
    impl fmt::Display for $t {
        #[allow(unused_comparisons)]
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let is_positive = *self >= 0;
            let mut n = if is_positive {
                self.$conv_fn()
            } else {
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!self.$conv_fn()).wrapping_add(1)
            };
            let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + 48;
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }
            }

            let buf_slice = unsafe {
                str::from_utf8_unchecked(
                    slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
            };
            f.pad_integral(is_positive, "", buf_slice)
        }
    })*);
}

impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
#[cfg(target_pointer_width = "32")]
impl_Display!(isize, usize: to_u32);
#[cfg(target_pointer_width = "64")]
impl_Display!(isize, usize: to_u64);
<commit_msg>Fix comment gone astray<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Integer and floating-point number formatting

// FIXME: #6220 Implement floating point formatting

use prelude::v1::*;

use fmt;
use num::Zero;
use ops::{Div, Rem, Sub};
use str;
use slice;
use ptr;
use mem;

#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
           Sub<Output=Self> + Copy {
    fn from_u8(u: u8) -> Self;
    fn to_u8(&self) -> u8;
    fn to_u32(&self) -> u32;
    fn to_u64(&self) -> u64;
}

macro_rules! doit {
    ($($t:ident)*) => ($(impl Int for $t {
        fn from_u8(u: u8) -> $t { u as $t }
        fn to_u8(&self) -> u8 { *self as u8 }
        fn to_u32(&self) -> u32 { *self as u32 }
        fn to_u64(&self) -> u64 { *self as u64 }
    })*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

/// A type that represents a specific radix
#[doc(hidden)]
trait GenericRadix {
    /// The number of digits.
    fn base(&self) -> u8;

    /// A radix-specific prefix string.
    fn prefix(&self) -> &'static str {
        ""
    }

    /// Converts an integer to corresponding radix digit.
    fn digit(&self, x: u8) -> u8;

    /// Format an integer using the radix using a formatter.
    fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
        // The radix can be as low as 2, so we need a buffer of at least 64
        // characters for a base 2 number.
        let zero = T::zero();
        let is_positive = x >= zero;
        let mut buf = [0; 64];
        let mut curr = buf.len();
        let base = T::from_u8(self.base());
        if is_positive {
            // Accumulate each digit of the number from the least significant
            // to the most significant figure.
            for byte in buf.iter_mut().rev() {
                let n = x % base;              // Get the current place value.
                x = x / base;                  // Deaccumulate the number.
                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                curr -= 1;
                if x == zero {
                    // No more digits left to accumulate.
                    break
                };
            }
        } else {
            // Do the same as above, but accounting for two's complement.
            for byte in buf.iter_mut().rev() {
                let n = zero - (x % base);     // Get the current place value.
                x = x / base;                  // Deaccumulate the number.
                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                curr -= 1;
                if x == zero {
                    // No more digits left to accumulate.
                    break
                };
            }
        }
        let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
        f.pad_integral(is_positive, self.prefix(), buf)
    }
}

/// A binary (base 2) radix
#[derive(Clone, PartialEq)]
struct Binary;

/// An octal (base 8) radix
#[derive(Clone, PartialEq)]
struct Octal;

/// A decimal (base 10) radix
#[derive(Clone, PartialEq)]
struct Decimal;

/// A hexadecimal (base 16) radix, formatted with lower-case characters
#[derive(Clone, PartialEq)]
struct LowerHex;

/// A hexadecimal (base 16) radix, formatted with upper-case characters
#[derive(Clone, PartialEq)]
struct UpperHex;

macro_rules! radix {
    ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
        impl GenericRadix for $T {
            fn base(&self) -> u8 { $base }
            fn prefix(&self) -> &'static str { $prefix }
            fn digit(&self, x: u8) -> u8 {
                match x {
                    $($x => $conv,)+
                    x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
                }
            }
        }
    }
}

radix! { Binary,    2, "0b", x @  0 ...  2 => b'0' + x }
radix! { Octal,     8, "0o", x @  0 ...  7 => b'0' + x }
radix! { Decimal,  10, "",   x @  0 ...  9 => b'0' + x }
radix! { LowerHex, 16, "0x", x @  0 ...  9 => b'0' + x,
                             x @ 10 ... 15 => b'a' + (x - 10) }
radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
                             x @ 10 ... 15 => b'A' + (x - 10) }

/// A radix with in the range of `2..36`.
#[derive(Clone, Copy, PartialEq)]
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
pub struct Radix {
    base: u8,
}

impl Radix {
    fn new(base: u8) -> Radix {
        assert!(2 <= base && base <= 36,
                "the base must be in the range of 2..36: {}",
                base);
        Radix { base: base }
    }
}

impl GenericRadix for Radix {
    fn base(&self) -> u8 {
        self.base
    }
    fn digit(&self, x: u8) -> u8 {
        match x {
            x @  0 ... 9 => b'0' + x,
            x if x < self.base() => b'a' + (x - 10),
            x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
        }
    }
}

/// A helper type for formatting radixes.
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
#[derive(Copy, Clone)]
pub struct RadixFmt<T, R>(T, R);

/// Constructs a radix formatter in the range of `2..36`.
///
/// # Examples
///
/// ```
/// #![feature(fmt_radix)]
///
/// use std::fmt::radix;
/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
/// ```
#[unstable(feature = "fmt_radix",
           reason = "may be renamed or move to a different module",
           issue = "27728")]
pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
    RadixFmt(x, Radix::new(base))
}

macro_rules! radix_fmt {
    ($T:ty as $U:ty, $fmt:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Debug for RadixFmt<$T, Radix> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt::Display::fmt(self, f)
            }
        }
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Display for RadixFmt<$T, Radix> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self { RadixFmt(ref x, radix) => radix.$fmt(*x as $U, f) }
            }
        }
    }
}

macro_rules! int_base {
    ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::$Trait for $T {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                $Radix.fmt_int(*self as $U, f)
            }
        }
    }
}

macro_rules! debug {
    ($T:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl fmt::Debug for $T {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt::Display::fmt(self, f)
            }
        }
    }
}

macro_rules! integer {
    ($Int:ident, $Uint:ident) => {
        int_base! { Binary   for $Int as $Uint  -> Binary }
        int_base! { Octal    for $Int as $Uint  -> Octal }
        int_base! { LowerHex for $Int as $Uint  -> LowerHex }
        int_base! { UpperHex for $Int as $Uint  -> UpperHex }
        radix_fmt! { $Int as $Int, fmt_int }
        debug! { $Int }

        int_base! { Binary   for $Uint as $Uint -> Binary }
        int_base! { Octal    for $Uint as $Uint -> Octal }
        int_base! { LowerHex for $Uint as $Uint -> LowerHex }
        int_base! { UpperHex for $Uint as $Uint -> UpperHex }
        radix_fmt! { $Uint as $Uint, fmt_int }
        debug! { $Uint }
    }
}
integer! { isize, usize }
integer! { i8, u8 }
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

macro_rules! impl_Display {
    ($($t:ident),*: $conv_fn:ident) => ($(
    impl fmt::Display for $t {
        #[allow(unused_comparisons)]
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let is_positive = *self >= 0;
            let mut n = if is_positive {
                self.$conv_fn()
            } else {
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!self.$conv_fn()).wrapping_add(1)
            };
            let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + 48;
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }
            }

            let buf_slice = unsafe {
                str::from_utf8_unchecked(
                    slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
            };
            f.pad_integral(is_positive, "", buf_slice)
        }
    })*);
}

impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
#[cfg(target_pointer_width = "32")]
impl_Display!(isize, usize: to_u32);
#[cfg(target_pointer_width = "64")]
impl_Display!(isize, usize: to_u64);
<|endoftext|>


<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use graphics::math::{transform_pos, rotate_radians};
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use rand::distributions::{Range, IndependentSample, Normal};
use rand::distributions::range::SampleRange;
use std::f64::consts::PI;
use intersect::{lines_intersect, point_in};
use point::Point;

use config::Config;

pub fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (theta.sin() * r, -theta.cos() * r);
}

fn random<T: SampleRange + PartialOrd>(low: T, high: T, mut rng: &mut Rng) -> T {
    return Range::new(low, high).ind_sample(&mut rng);
}

pub fn wrapped_add(a: f64, b: f64, bound: f64) -> f64 {
    (a + b + bound) % bound
}

#[derive(Clone)]
pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [[5.0, 7.0], [-5.0, 7.0], [0.0, -13.0]];

impl Spaceship {
    pub fn new(config: &Config) -> Spaceship {
        return Spaceship {
            x: config.width() / 2.0,
            y: config.height() / 2.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(&SPACESHIP_POINTS,
                                 ds,
                                 t.trans(self.x, self.y)
                                  .rot_rad(self.theta),
                                 gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v * dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse) * dt * 100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx * new_dx + new_dy * new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left) * dt * 100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        let rotation_matrix = rotate_radians(self.theta);
        let points: Vec<[f64; 2]> = SPACESHIP_POINTS.iter()
                                                    .map(|p| transform_pos(rotation_matrix, *p))
                                                    .collect();
        return points.iter()
                     .zip(points.iter().cycle().skip(1))
                     .map(|(p1, p2)| {
                         [p1[0] + self.x, p1[1] + self.y, p2[0] + self.x, p2[1] + self.y]
                     })
                     .collect();
    }

    pub fn collides<I: Iterator<Item = [f64; 4]>>(&self, edges: I) -> bool {
        let edges_vec: Vec<[f64; 4]> = edges.collect();
        return self.edges().iter().any(|edge| {
            edges_vec.iter().any(|other_edge| lines_intersect(*edge, *other_edge))
        });
    }
}

#[derive(Clone, Debug)]
pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet {
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin() * v * dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos() * v * dt + y_max) % y_max;
        self.distance += v * dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }

    pub fn coords(&self) -> Point {
        return Point::new(self.x, self.y);
    }

    pub fn collides(&self, astroid: &Astroid) -> bool {
        return point_in(self.coords(), astroid.edges().iter().cloned());
    }
}

#[derive(Clone)]
pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    size: i64,
    border: Vec<[f64; 4]>,
}

const ASTROID_LARGE: i64 = 3;

impl Astroid {
    pub fn large_new(config: &Config, mut rng: &mut Rng) -> Astroid {
        return Self::new(ASTROID_LARGE, config, rng);
    }

    fn random_start(max: f64, gap: f64, mut rng: &mut Rng) -> f64 {
        if random(0, 2, rng) == 0 {
            return random(0.0, max / 2.0 - gap, rng);
        } else {
            return random(max / 2.0 + gap, max, rng);
        }
    }

    pub fn new(size: i64, config: &Config, mut rng: &mut Rng) -> Astroid {
        let radius = (size * 5) as f64;
        return Astroid {
            x: Astroid::random_start(config.width(), config.astroid_gap_distance(), &mut rng),
            y: Astroid::random_start(config.height(), config.astroid_gap_distance(), &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: random(0.0, 2.0 * PI, &mut rng),
            size: size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    fn exploded(&self, mut rng: &mut Rng) -> Astroid {
        let new_size = self.size - 1;
        let radius = (new_size * 5) as f64;
        let theta_range = Normal::new(0.0, PI / 2.0);
        let d_theta = theta_range.ind_sample(&mut rng);
        let theta = self.theta + d_theta;
        return Astroid {
            x: self.x + random(-5.0, 5.0, &mut rng),
            y: self.y + random(-5.0, 5.0, &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: theta,
            size: new_size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    pub fn explode(&self, mut rng: &mut Rng) -> Vec<Astroid> {
        if self.size <= 1 {
            vec![]
        } else {
            vec![self.exploded(rng), self.exploded(rng)]
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin() * self.v * dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos() * self.v * dt + y_max) % y_max;
    }

    pub fn create_border(mut rng: &mut Rng, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius / 5.0;
        let point_count = random(8, 12, &mut rng);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = random(0.0, 2.0 * PI, &mut rng);
        let corner_i_to_theta = |i| theta_0 + 2.0 * PI * i as f64 / point_count as f64;
        for theta in (1..point_count + 1).map(corner_i_to_theta) {
            let distance = radius + random(-spread, spread, &mut rng);
            points.push(to_cartesian(theta, distance));
        }
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return self.border
                   .iter()
                   .map(|edge| {
                       [edge[0] + self.x, edge[1] + self.y, edge[2] + self.x, edge[3] + self.y]
                   })
                   .collect();
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::f64::consts::PI;
    use expectest::prelude::*;

    #[test]
    fn test_wrapped_add() {
        assert_eq!(wrapped_add(1.0, 1.0, 10.0), 2.0);
        assert_eq!(wrapped_add(1.0, 10.0, 10.0), 1.0);
        assert_eq!(wrapped_add(1.0, -5.0, 10.0), 6.0);
    }

    fn expect_both_close_to((r, theta): (f64, f64), (x_expected, y_expected): (f64, f64)) {
        match to_cartesian(r, theta) {
            (x, y) => {
                expect!(x_expected).to(be_close_to(x));
                expect!(y_expected).to(be_close_to(y));
            }
        }
    }

    #[test]
    fn test_to_cartesian() {
        expect_both_close_to((0.0, 1.0), (0.0, -1.0));
        expect_both_close_to((PI / 2.0, 1.0), (1.0, 0.0));
    }
}
<commit_msg>Refactor go functions to use wrapped_add<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use graphics::math::{transform_pos, rotate_radians};
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use rand::distributions::{Range, IndependentSample, Normal};
use rand::distributions::range::SampleRange;
use std::f64::consts::PI;
use intersect::{lines_intersect, point_in};
use point::Point;

use config::Config;

pub fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (theta.sin() * r, -theta.cos() * r);
}

fn random<T: SampleRange + PartialOrd>(low: T, high: T, mut rng: &mut Rng) -> T {
    return Range::new(low, high).ind_sample(&mut rng);
}

pub fn wrapped_add(a: f64, b: f64, bound: f64) -> f64 {
    (a + b + bound) % bound
}

#[derive(Clone)]
pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [[5.0, 7.0], [-5.0, 7.0], [0.0, -13.0]];

impl Spaceship {
    pub fn new(config: &Config) -> Spaceship {
        return Spaceship {
            x: config.width() / 2.0,
            y: config.height() / 2.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(&SPACESHIP_POINTS,
                                 ds,
                                 t.trans(self.x, self.y)
                                  .rot_rad(self.theta),
                                 gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v * dt);
        self.x = wrapped_add(self.x, dx, x_max);
        self.y = wrapped_add(self.y, dy, y_max);
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse) * dt * 100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx * new_dx + new_dy * new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left) * dt * 100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        let rotation_matrix = rotate_radians(self.theta);
        let points: Vec<[f64; 2]> = SPACESHIP_POINTS.iter()
                                                    .map(|p| transform_pos(rotation_matrix, *p))
                                                    .collect();
        return points.iter()
                     .zip(points.iter().cycle().skip(1))
                     .map(|(p1, p2)| {
                         [p1[0] + self.x, p1[1] + self.y, p2[0] + self.x, p2[1] + self.y]
                     })
                     .collect();
    }

    pub fn collides<I: Iterator<Item = [f64; 4]>>(&self, edges: I) -> bool {
        let edges_vec: Vec<[f64; 4]> = edges.collect();
        return self.edges().iter().any(|edge| {
            edges_vec.iter().any(|other_edge| lines_intersect(*edge, *other_edge))
        });
    }
}

#[derive(Clone, Debug)]
pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet {
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = wrapped_add(self.x, self.theta.sin() * v * dt, x_max);
        self.y = wrapped_add(self.y, -self.theta.cos() * v * dt, y_max);
        self.distance += v * dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }

    pub fn coords(&self) -> Point {
        return Point::new(self.x, self.y);
    }

    pub fn collides(&self, astroid: &Astroid) -> bool {
        return point_in(self.coords(), astroid.edges().iter().cloned());
    }
}

#[derive(Clone)]
pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    size: i64,
    border: Vec<[f64; 4]>,
}

const ASTROID_LARGE: i64 = 3;

impl Astroid {
    pub fn large_new(config: &Config, mut rng: &mut Rng) -> Astroid {
        return Self::new(ASTROID_LARGE, config, rng);
    }

    fn random_start(max: f64, gap: f64, mut rng: &mut Rng) -> f64 {
        if random(0, 2, rng) == 0 {
            return random(0.0, max / 2.0 - gap, rng);
        } else {
            return random(max / 2.0 + gap, max, rng);
        }
    }

    pub fn new(size: i64, config: &Config, mut rng: &mut Rng) -> Astroid {
        let radius = (size * 5) as f64;
        return Astroid {
            x: Astroid::random_start(config.width(), config.astroid_gap_distance(), &mut rng),
            y: Astroid::random_start(config.height(), config.astroid_gap_distance(), &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: random(0.0, 2.0 * PI, &mut rng),
            size: size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    fn exploded(&self, mut rng: &mut Rng) -> Astroid {
        let new_size = self.size - 1;
        let radius = (new_size * 5) as f64;
        let theta_range = Normal::new(0.0, PI / 2.0);
        let d_theta = theta_range.ind_sample(&mut rng);
        let theta = self.theta + d_theta;
        return Astroid {
            x: self.x + random(-5.0, 5.0, &mut rng),
            y: self.y + random(-5.0, 5.0, &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: theta,
            size: new_size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    pub fn explode(&self, mut rng: &mut Rng) -> Vec<Astroid> {
        if self.size <= 1 {
            vec![]
        } else {
            vec![self.exploded(rng), self.exploded(rng)]
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = wrapped_add(self.x, self.theta.sin() * self.v * dt, x_max);
        self.y = wrapped_add(self.y, -self.theta.cos() * self.v * dt, y_max);
    }

    pub fn create_border(mut rng: &mut Rng, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius / 5.0;
        let point_count = random(8, 12, &mut rng);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = random(0.0, 2.0 * PI, &mut rng);
        let corner_i_to_theta = |i| theta_0 + 2.0 * PI * i as f64 / point_count as f64;
        for theta in (1..point_count + 1).map(corner_i_to_theta) {
            let distance = radius + random(-spread, spread, &mut rng);
            points.push(to_cartesian(theta, distance));
        }
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return self.border
                   .iter()
                   .map(|edge| {
                       [edge[0] + self.x, edge[1] + self.y, edge[2] + self.x, edge[3] + self.y]
                   })
                   .collect();
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::f64::consts::PI;
    use expectest::prelude::*;

    #[test]
    fn test_wrapped_add() {
        assert_eq!(wrapped_add(1.0, 1.0, 10.0), 2.0);
        assert_eq!(wrapped_add(1.0, 10.0, 10.0), 1.0);
        assert_eq!(wrapped_add(1.0, -5.0, 10.0), 6.0);
    }

    fn expect_both_close_to((r, theta): (f64, f64), (x_expected, y_expected): (f64, f64)) {
        match to_cartesian(r, theta) {
            (x, y) => {
                expect!(x_expected).to(be_close_to(x));
                expect!(y_expected).to(be_close_to(y));
            }
        }
    }

    #[test]
    fn test_to_cartesian() {
        expect_both_close_to((0.0, 1.0), (0.0, -1.0));
        expect_both_close_to((PI / 2.0, 1.0), (1.0, 0.0));
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{os, result};
use std::c_str::ToCStr;
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use extra::getopts::groups::getopts;
use syntax::ast_util::*;
use syntax::codemap::{dummy_sp, spanned};
use syntax::ext::base::ExtCtxt;
use syntax::{ast, attr, codemap, diagnostic, fold};
use syntax::attr::AttrMetaMethods;
use rustc::back::link::output_type_exe;
use rustc::driver::session::{lib_crate, bin_crate};
use context::Ctx;
use package_id::PkgId;
use search::find_library_in_search_path;
use path_util::target_library_in_workspace;
pub use target::{OutputType, Main, Lib, Bench, Test};

// It would be nice to have the list of commands in just one place -- for example,
// you could update the match in rustpkg.rc but forget to update this list. I think
// that should be fixed.
static COMMANDS: &'static [&'static str] =
    &["build", "clean", "do", "info", "install", "list", "prefer", "test", "uninstall",
      "unprefer"];

pub type ExitCode = int; // For now

pub struct Pkg {
    id: PkgId,
    bins: ~[~str],
    libs: ~[~str],
}

impl ToStr for Pkg {
    fn to_str(&self) -> ~str {
        self.id.to_str()
    }
}

pub fn root() -> Path {
    match filesearch::get_rustpkg_root() {
        result::Ok(path) => path,
        result::Err(err) => fail!(err)
    }
}

pub fn is_cmd(cmd: &str) -> bool {
    COMMANDS.iter().any(|&c| c == cmd)
}

struct ListenerFn {
    cmds: ~[~str],
    span: codemap::span,
    path: ~[ast::ident]
}

struct ReadyCtx {
    sess: session::Session,
    crate: @ast::Crate,
    ext_cx: @ExtCtxt,
    path: ~[ast::ident],
    fns: ~[ListenerFn]
}

fn fold_mod(_ctx: @mut ReadyCtx,
            m: &ast::_mod,
            fold: @fold::ast_fold) -> ast::_mod {
    fn strip_main(item: @ast::item) -> @ast::item {
        @ast::item {
            attrs: do item.attrs.iter().filter_map |attr| {
                if "main" != attr.name() {
                    Some(*attr)
                } else {
                    None
                }
            }.collect(),
            .. (*item).clone()
        }
    }

    fold::noop_fold_mod(&ast::_mod {
        items: do m.items.map |item| {
            strip_main(*item)
        },
        .. (*m).clone()
    }, fold)
}

fn fold_item(ctx: @mut ReadyCtx,
             item: @ast::item,
             fold: @fold::ast_fold) -> Option<@ast::item> {
    ctx.path.push(item.ident);

    let mut cmds = ~[];
    let mut had_pkg_do = false;

    for attr in item.attrs.iter() {
        if "pkg_do" == attr.name() {
            had_pkg_do = true;
            match attr.node.value.node {
                ast::MetaList(_, ref mis) => {
                    for mi in mis.iter() {
                        match mi.node {
                            ast::MetaWord(cmd) => cmds.push(cmd.to_owned()),
                            _ => {}
                        };
                    }
                }
                _ => cmds.push(~"build")
            }
        }
    }

    if had_pkg_do {
        ctx.fns.push(ListenerFn {
            cmds: cmds,
            span: item.span,
            path: /*bad*/ctx.path.clone()
        });
    }

    let res = fold::noop_fold_item(item, fold);

    ctx.path.pop();

    res
}

/// Generate/filter main function, add the list of commands, etc.
pub fn ready_crate(sess: session::Session,
                   crate: @ast::Crate) -> @ast::Crate {
    let ctx = @mut ReadyCtx {
        sess: sess,
        crate: crate,
        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
        path: ~[],
        fns: ~[]
    };
    let precursor = @fold::AstFoldFns {
        // fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
        fold_item: |a, b| fold_item(ctx, a, b),
        fold_mod: |a, b| fold_mod(ctx, a, b),
        .. *fold::default_ast_fold()
    };

    let fold = fold::make_fold(precursor);

    @fold.fold_crate(crate)
}

// FIXME (#4432): Use workcache to only compile when needed
pub fn compile_input(ctxt: &Ctx,
                     pkg_id: &PkgId,
                     in_file: &Path,
                     out_dir: &Path,
                     flags: &[~str],
                     cfgs: &[~str],
                     opt: bool,
                     what: OutputType) -> bool {

    let workspace = out_dir.pop().pop();

    assert!(in_file.components.len() > 1);
    let input = driver::file_input((*in_file).clone());
    debug!("compile_input: %s / %?", in_file.to_str(), what);
    // tjc: by default, use the package ID name as the link name
    // not sure if we should support anything else

    let binary = os::args()[0].to_managed();

    debug!("flags: %s", flags.connect(" "));
    debug!("cfgs: %s", cfgs.connect(" "));
    debug!("compile_input's sysroot = %?", ctxt.sysroot_opt);

    let crate_type = match what {
        Lib => lib_crate,
        Test | Bench | Main => bin_crate
    };
    let matches = getopts(debug_flags()
                          + match what {
                              Lib => ~[~"--lib"],
                              // --test compiles both #[test] and #[bench] fns
                              Test | Bench => ~[~"--test"],
                              Main => ~[]
                          }
                          + flags
                          + cfgs.flat_map(|c| { ~[~"--cfg", (*c).clone()] }),
                          driver::optgroups()).unwrap();
    let options = @session::options {
        crate_type: crate_type,
        optimize: if opt { session::Aggressive } else { session::No },
        test: what == Test || what == Bench,
        maybe_sysroot: ctxt.sysroot_opt,
        addl_lib_search_paths: @mut (~[(*out_dir).clone()]),
        // output_type should be conditional
        output_type: output_type_exe, // Use this to get a library? That's weird
        .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
    };

    let addl_lib_search_paths = @mut options.addl_lib_search_paths;
    // Make sure all the library directories actually exist, since the linker will complain
    // otherwise
    for p in addl_lib_search_paths.iter() {
        assert!(os::path_is_dir(p));
    }

    let sess = driver::build_session(options, diagnostic::emit);

    // Infer dependencies that rustpkg needs to build, by scanning for
    // `extern mod` directives.
    let cfg = driver::build_configuration(sess, binary, &input);
    let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
    crate = driver::phase_2_configure_and_expand(sess, cfg, crate);

    // Not really right. Should search other workspaces too, and the installed
    // database (which doesn't exist yet)
    find_and_install_dependencies(ctxt, sess, &workspace, crate,
                                  |p| {
                                      debug!("a dependency: %s", p.to_str());
                                      // Pass the directory containing a dependency
                                      // as an additional lib search path
                                      addl_lib_search_paths.push(p);
                                  });

    // Inject the link attributes so we get the right package name and version
    if attr::find_linkage_metas(crate.attrs).is_empty() {
        let short_name_to_use = match what {
            Test  => fmt!("%stest", pkg_id.short_name),
            Bench => fmt!("%sbench", pkg_id.short_name),
            _     => pkg_id.short_name.clone()
        };
        debug!("Injecting link name: %s", short_name_to_use);
        let link_options =
            ~[attr::mk_name_value_item_str(@"name", short_name_to_use.to_managed()),
              attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())];

        crate = @ast::Crate {
            attrs: ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))],
            .. (*crate).clone()
        };
    }

    debug!("calling compile_crate_from_input, out_dir = %s,
           building_library = %?", out_dir.to_str(), sess.building_library);
    compile_crate_from_input(&input, out_dir, sess, crate);
    true
}

// Should use workcache to avoid recompiling when not necessary
// Should also rename this to something better
// If crate_opt is present, then finish compilation. If it's None, then
// call compile_upto and return the crate
// also, too many arguments
pub fn compile_crate_from_input(input: &driver::input,
                                build_dir: &Path,
                                sess: session::Session,
                                crate: @ast::Crate) {
    debug!("Calling build_output_filenames with %s, building library? %?",
           build_dir.to_str(), sess.building_library);

    // bad copy
    let outputs = driver::build_output_filenames(input, &Some((*build_dir).clone()), &None,
                                                 crate.attrs, sess);

    debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
    debug!("additional libraries:");
    for lib in sess.opts.addl_lib_search_paths.iter() {
        debug!("an additional library: %s", lib.to_str());
    }
    let analysis = driver::phase_3_run_analysis_passes(sess, crate);
    let translation = driver::phase_4_translate_to_llvm(sess, crate,
                                                        &analysis,
                                                        outputs);
    driver::phase_5_run_llvm_passes(sess, &translation, outputs);
    if driver::stop_after_phase_5(sess) { return; }
    driver::phase_6_link_output(sess, &translation, outputs);
}

#[cfg(windows)]
pub fn exe_suffix() -> ~str { ~".exe" }

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn exe_suffix() -> ~str { ~"" }

// Called by build_crates
// FIXME (#4432): Use workcache to only compile when needed
pub fn compile_crate(ctxt: &Ctx, pkg_id: &PkgId,
                     crate: &Path, dir: &Path,
                     flags: &[~str], cfgs: &[~str], opt: bool,
                     what: OutputType) -> bool {
    debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str());
    debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str());
    for fl in flags.iter() {
        debug!("+++ %s", *fl);
    }
    compile_input(ctxt, pkg_id, crate, dir, flags, cfgs, opt, what)
}

/// Collect all `extern mod` directives in `c`, then
/// try to install their targets, failing if any target
/// can't be found.
pub fn find_and_install_dependencies(ctxt: &Ctx,
                                 sess: session::Session,
                                 workspace: &Path,
                                 c: &ast::Crate,
                                 save: @fn(Path)
                                ) {
    // :-(
    debug!("In find_and_install_dependencies...");
    let my_workspace = (*workspace).clone();
    let my_ctxt      = *ctxt;
    do c.each_view_item() |vi: &ast::view_item| {
        debug!("A view item!");
        match vi.node {
            // ignore metadata, I guess
            ast::view_item_extern_mod(lib_ident, _, _) => {
                match my_ctxt.sysroot_opt {
                    Some(ref x) => debug!("sysroot: %s", x.to_str()),
                    None => debug!("No sysroot given")
                };
                let lib_name = sess.str_of(lib_ident);
                match find_library_in_search_path(my_ctxt.sysroot_opt, lib_name) {
                    Some(installed_path) => {
                        debug!("It exists: %s", installed_path.to_str());
                    }
                    None => {
                        // Try to install it
                        let pkg_id = PkgId::new(lib_name, &os::getcwd());
                        my_ctxt.install(&my_workspace, &pkg_id);
                        // Also, add an additional search path
                        debug!("let installed_path...")
                        let installed_path = target_library_in_workspace(&pkg_id,
                                                                         &my_workspace).pop();
                        debug!("Great, I installed %s, and it's in %s",
                               lib_name, installed_path.to_str());
                        save(installed_path);
                    }
                }
            }
            // Ignore `use`s
            _ => ()
        }
        true
    };
}

#[cfg(windows)]
pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
    /* FIXME (#1768): Investigate how to do this on win32
       Node wraps symlinks by having a .bat,
       but that won't work with minGW. */

    false
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn link_exe(src: &Path, dest: &Path) -> bool {
    use std::libc;
    unsafe {
        do src.to_c_str().with_ref |src_buf| {
            do dest.to_c_str().with_ref |dest_buf| {
                libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
                    libc::chmod(dest_buf, 755) == 0 as libc::c_int
            }
        }
    }
}

pub fn mk_string_lit(s: @str) -> ast::lit {
    spanned {
        node: ast::lit_str(s),
        span: dummy_sp()
    }
}

#[cfg(test)]
mod test {
    use super::is_cmd;

    #[test]
    fn test_is_cmd() {
        assert!(is_cmd("build"));
        assert!(is_cmd("clean"));
        assert!(is_cmd("do"));
        assert!(is_cmd("info"));
        assert!(is_cmd("install"));
        assert!(is_cmd("prefer"));
        assert!(is_cmd("test"));
        assert!(is_cmd("uninstall"));
        assert!(is_cmd("unprefer"));
    }

}

// tjc: cheesy
fn debug_flags() -> ~[~str] { ~[] }
// static DEBUG_FLAGS: ~[~str] = ~[~"-Z", ~"time-passes"];
<commit_msg>rustpkg: another fix for windows<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{os, result};
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use extra::getopts::groups::getopts;
use syntax::ast_util::*;
use syntax::codemap::{dummy_sp, spanned};
use syntax::ext::base::ExtCtxt;
use syntax::{ast, attr, codemap, diagnostic, fold};
use syntax::attr::AttrMetaMethods;
use rustc::back::link::output_type_exe;
use rustc::driver::session::{lib_crate, bin_crate};
use context::Ctx;
use package_id::PkgId;
use search::find_library_in_search_path;
use path_util::target_library_in_workspace;
pub use target::{OutputType, Main, Lib, Bench, Test};

// It would be nice to have the list of commands in just one place -- for example,
// you could update the match in rustpkg.rc but forget to update this list. I think
// that should be fixed.
static COMMANDS: &'static [&'static str] =
    &["build", "clean", "do", "info", "install", "list", "prefer", "test", "uninstall",
      "unprefer"];

pub type ExitCode = int; // For now

pub struct Pkg {
    id: PkgId,
    bins: ~[~str],
    libs: ~[~str],
}

impl ToStr for Pkg {
    fn to_str(&self) -> ~str {
        self.id.to_str()
    }
}

pub fn root() -> Path {
    match filesearch::get_rustpkg_root() {
        result::Ok(path) => path,
        result::Err(err) => fail!(err)
    }
}

pub fn is_cmd(cmd: &str) -> bool {
    COMMANDS.iter().any(|&c| c == cmd)
}

struct ListenerFn {
    cmds: ~[~str],
    span: codemap::span,
    path: ~[ast::ident]
}

struct ReadyCtx {
    sess: session::Session,
    crate: @ast::Crate,
    ext_cx: @ExtCtxt,
    path: ~[ast::ident],
    fns: ~[ListenerFn]
}

fn fold_mod(_ctx: @mut ReadyCtx,
            m: &ast::_mod,
            fold: @fold::ast_fold) -> ast::_mod {
    fn strip_main(item: @ast::item) -> @ast::item {
        @ast::item {
            attrs: do item.attrs.iter().filter_map |attr| {
                if "main" != attr.name() {
                    Some(*attr)
                } else {
                    None
                }
            }.collect(),
            .. (*item).clone()
        }
    }

    fold::noop_fold_mod(&ast::_mod {
        items: do m.items.map |item| {
            strip_main(*item)
        },
        .. (*m).clone()
    }, fold)
}

fn fold_item(ctx: @mut ReadyCtx,
             item: @ast::item,
             fold: @fold::ast_fold) -> Option<@ast::item> {
    ctx.path.push(item.ident);

    let mut cmds = ~[];
    let mut had_pkg_do = false;

    for attr in item.attrs.iter() {
        if "pkg_do" == attr.name() {
            had_pkg_do = true;
            match attr.node.value.node {
                ast::MetaList(_, ref mis) => {
                    for mi in mis.iter() {
                        match mi.node {
                            ast::MetaWord(cmd) => cmds.push(cmd.to_owned()),
                            _ => {}
                        };
                    }
                }
                _ => cmds.push(~"build")
            }
        }
    }

    if had_pkg_do {
        ctx.fns.push(ListenerFn {
            cmds: cmds,
            span: item.span,
            path: /*bad*/ctx.path.clone()
        });
    }

    let res = fold::noop_fold_item(item, fold);

    ctx.path.pop();

    res
}

/// Generate/filter main function, add the list of commands, etc.
pub fn ready_crate(sess: session::Session,
                   crate: @ast::Crate) -> @ast::Crate {
    let ctx = @mut ReadyCtx {
        sess: sess,
        crate: crate,
        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
        path: ~[],
        fns: ~[]
    };
    let precursor = @fold::AstFoldFns {
        // fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
        fold_item: |a, b| fold_item(ctx, a, b),
        fold_mod: |a, b| fold_mod(ctx, a, b),
        .. *fold::default_ast_fold()
    };

    let fold = fold::make_fold(precursor);

    @fold.fold_crate(crate)
}

// FIXME (#4432): Use workcache to only compile when needed
pub fn compile_input(ctxt: &Ctx,
                     pkg_id: &PkgId,
                     in_file: &Path,
                     out_dir: &Path,
                     flags: &[~str],
                     cfgs: &[~str],
                     opt: bool,
                     what: OutputType) -> bool {

    let workspace = out_dir.pop().pop();

    assert!(in_file.components.len() > 1);
    let input = driver::file_input((*in_file).clone());
    debug!("compile_input: %s / %?", in_file.to_str(), what);
    // tjc: by default, use the package ID name as the link name
    // not sure if we should support anything else

    let binary = os::args()[0].to_managed();

    debug!("flags: %s", flags.connect(" "));
    debug!("cfgs: %s", cfgs.connect(" "));
    debug!("compile_input's sysroot = %?", ctxt.sysroot_opt);

    let crate_type = match what {
        Lib => lib_crate,
        Test | Bench | Main => bin_crate
    };
    let matches = getopts(debug_flags()
                          + match what {
                              Lib => ~[~"--lib"],
                              // --test compiles both #[test] and #[bench] fns
                              Test | Bench => ~[~"--test"],
                              Main => ~[]
                          }
                          + flags
                          + cfgs.flat_map(|c| { ~[~"--cfg", (*c).clone()] }),
                          driver::optgroups()).unwrap();
    let options = @session::options {
        crate_type: crate_type,
        optimize: if opt { session::Aggressive } else { session::No },
        test: what == Test || what == Bench,
        maybe_sysroot: ctxt.sysroot_opt,
        addl_lib_search_paths: @mut (~[(*out_dir).clone()]),
        // output_type should be conditional
        output_type: output_type_exe, // Use this to get a library? That's weird
        .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
    };

    let addl_lib_search_paths = @mut options.addl_lib_search_paths;
    // Make sure all the library directories actually exist, since the linker will complain
    // otherwise
    for p in addl_lib_search_paths.iter() {
        assert!(os::path_is_dir(p));
    }

    let sess = driver::build_session(options, diagnostic::emit);

    // Infer dependencies that rustpkg needs to build, by scanning for
    // `extern mod` directives.
    let cfg = driver::build_configuration(sess, binary, &input);
    let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
    crate = driver::phase_2_configure_and_expand(sess, cfg, crate);

    // Not really right. Should search other workspaces too, and the installed
    // database (which doesn't exist yet)
    find_and_install_dependencies(ctxt, sess, &workspace, crate,
                                  |p| {
                                      debug!("a dependency: %s", p.to_str());
                                      // Pass the directory containing a dependency
                                      // as an additional lib search path
                                      addl_lib_search_paths.push(p);
                                  });

    // Inject the link attributes so we get the right package name and version
    if attr::find_linkage_metas(crate.attrs).is_empty() {
        let short_name_to_use = match what {
            Test  => fmt!("%stest", pkg_id.short_name),
            Bench => fmt!("%sbench", pkg_id.short_name),
            _     => pkg_id.short_name.clone()
        };
        debug!("Injecting link name: %s", short_name_to_use);
        let link_options =
            ~[attr::mk_name_value_item_str(@"name", short_name_to_use.to_managed()),
              attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())];

        crate = @ast::Crate {
            attrs: ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))],
            .. (*crate).clone()
        };
    }

    debug!("calling compile_crate_from_input, out_dir = %s,
           building_library = %?", out_dir.to_str(), sess.building_library);
    compile_crate_from_input(&input, out_dir, sess, crate);
    true
}

// Should use workcache to avoid recompiling when not necessary
// Should also rename this to something better
// If crate_opt is present, then finish compilation. If it's None, then
// call compile_upto and return the crate
// also, too many arguments
pub fn compile_crate_from_input(input: &driver::input,
                                build_dir: &Path,
                                sess: session::Session,
                                crate: @ast::Crate) {
    debug!("Calling build_output_filenames with %s, building library? %?",
           build_dir.to_str(), sess.building_library);

    // bad copy
    let outputs = driver::build_output_filenames(input, &Some((*build_dir).clone()), &None,
                                                 crate.attrs, sess);

    debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
    debug!("additional libraries:");
    for lib in sess.opts.addl_lib_search_paths.iter() {
        debug!("an additional library: %s", lib.to_str());
    }
    let analysis = driver::phase_3_run_analysis_passes(sess, crate);
    let translation = driver::phase_4_translate_to_llvm(sess, crate,
                                                        &analysis,
                                                        outputs);
    driver::phase_5_run_llvm_passes(sess, &translation, outputs);
    if driver::stop_after_phase_5(sess) { return; }
    driver::phase_6_link_output(sess, &translation, outputs);
}

#[cfg(windows)]
pub fn exe_suffix() -> ~str { ~".exe" }

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn exe_suffix() -> ~str { ~"" }

// Called by build_crates
// FIXME (#4432): Use workcache to only compile when needed
pub fn compile_crate(ctxt: &Ctx, pkg_id: &PkgId,
                     crate: &Path, dir: &Path,
                     flags: &[~str], cfgs: &[~str], opt: bool,
                     what: OutputType) -> bool {
    debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str());
    debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str());
    for fl in flags.iter() {
        debug!("+++ %s", *fl);
    }
    compile_input(ctxt, pkg_id, crate, dir, flags, cfgs, opt, what)
}

/// Collect all `extern mod` directives in `c`, then
/// try to install their targets, failing if any target
/// can't be found.
pub fn find_and_install_dependencies(ctxt: &Ctx,
                                 sess: session::Session,
                                 workspace: &Path,
                                 c: &ast::Crate,
                                 save: @fn(Path)
                                ) {
    // :-(
    debug!("In find_and_install_dependencies...");
    let my_workspace = (*workspace).clone();
    let my_ctxt      = *ctxt;
    do c.each_view_item() |vi: &ast::view_item| {
        debug!("A view item!");
        match vi.node {
            // ignore metadata, I guess
            ast::view_item_extern_mod(lib_ident, _, _) => {
                match my_ctxt.sysroot_opt {
                    Some(ref x) => debug!("sysroot: %s", x.to_str()),
                    None => debug!("No sysroot given")
                };
                let lib_name = sess.str_of(lib_ident);
                match find_library_in_search_path(my_ctxt.sysroot_opt, lib_name) {
                    Some(installed_path) => {
                        debug!("It exists: %s", installed_path.to_str());
                    }
                    None => {
                        // Try to install it
                        let pkg_id = PkgId::new(lib_name, &os::getcwd());
                        my_ctxt.install(&my_workspace, &pkg_id);
                        // Also, add an additional search path
                        debug!("let installed_path...")
                        let installed_path = target_library_in_workspace(&pkg_id,
                                                                         &my_workspace).pop();
                        debug!("Great, I installed %s, and it's in %s",
                               lib_name, installed_path.to_str());
                        save(installed_path);
                    }
                }
            }
            // Ignore `use`s
            _ => ()
        }
        true
    };
}

#[cfg(windows)]
pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
    /* FIXME (#1768): Investigate how to do this on win32
       Node wraps symlinks by having a .bat,
       but that won't work with minGW. */

    false
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn link_exe(src: &Path, dest: &Path) -> bool {
    use std::c_str::ToCStr;
    use std::libc;

    unsafe {
        do src.to_c_str().with_ref |src_buf| {
            do dest.to_c_str().with_ref |dest_buf| {
                libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
                    libc::chmod(dest_buf, 755) == 0 as libc::c_int
            }
        }
    }
}

pub fn mk_string_lit(s: @str) -> ast::lit {
    spanned {
        node: ast::lit_str(s),
        span: dummy_sp()
    }
}

#[cfg(test)]
mod test {
    use super::is_cmd;

    #[test]
    fn test_is_cmd() {
        assert!(is_cmd("build"));
        assert!(is_cmd("clean"));
        assert!(is_cmd("do"));
        assert!(is_cmd("info"));
        assert!(is_cmd("install"));
        assert!(is_cmd("prefer"));
        assert!(is_cmd("test"));
        assert!(is_cmd("uninstall"));
        assert!(is_cmd("unprefer"));
    }

}

// tjc: cheesy
fn debug_flags() -> ~[~str] { ~[] }
// static DEBUG_FLAGS: ~[~str] = ~[~"-Z", ~"time-passes"];
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::vec::Vec;
// use std::io::{Read, Write};
use std::collections::VecDeque;
use std::option::Option;

use mio::{Token, EventLoop, EventSet, PollOpt, TryRead, TryWrite};
use mio::tcp::TcpStream;
use bytes::{Buf, MutBuf, ByteBuf, MutByteBuf, alloc};

use raftserver::{Result, ConnData};
use raftserver::server::Server;
use raftserver::handler::ServerHandler;
use util::codec;

pub struct Conn {
    pub sock: TcpStream,
    pub token: Token,
    pub interest: EventSet,

    // message header
    last_msg_id: u64,
    header: MutByteBuf,
    // message
    payload: Option<MutByteBuf>,

    // write buffer, including msg header already.
    res: VecDeque<ByteBuf>,
}

fn try_read_data<T: TryRead, B: MutBuf>(r: &mut T, buf: &mut B) -> Result<()> {
    if buf.remaining() == 0 {
        return Ok(());
    }

    // TODO: use try_read_buf directly if we can solve the compile problem.
    unsafe {
        // header is not full read, we will try read more.
        let n = try!(r.try_read(buf.mut_bytes()));
        match n {
            None => {
                // nothing to do here now, but should we return an error or panic?
                error!("connection read None data");
            }
            Some(n) => buf.advance(n),
        }
    }

    Ok(())
}

fn try_write_data<T: TryWrite, B: Buf>(w: &mut T, buf: &mut B) -> Result<()> {
    // TODO: use try_write_buf directly if I can solve the compile problem.
    let n = try!(w.try_write(buf.bytes()));
    match n {
        None => {}
        Some(n) => buf.advance(n),
    }

    Ok(())
}

fn create_mem_buf(s: usize) -> MutByteBuf {
    unsafe {
        ByteBuf::from_mem_ref(alloc::heap(s.next_power_of_two()), s as u32, 0, s as u32).flip()
    }
}

impl Conn {
    pub fn new(sock: TcpStream, token: Token) -> Conn {
        Conn {
            sock: sock,
            token: token,
            interest: EventSet::readable(),
            header: create_mem_buf(codec::MSG_HEADER_LEN),
            payload: None,
            res: VecDeque::new(),
            last_msg_id: 0,
        }
    }

    pub fn reregister<T: ServerHandler>(&mut self,
                                        event_loop: &mut EventLoop<Server<T>>)
                                        -> Result<()> {
        try!(event_loop.reregister(&self.sock,
                                   self.token,
                                   self.interest,
                                   PollOpt::edge() | PollOpt::oneshot()));
        Ok(())
    }

    pub fn reregister_writeable<T: ServerHandler>(&mut self,
                                                  event_loop: &mut EventLoop<Server<T>>)
                                                  -> Result<()> {
        self.interest.insert(EventSet::writable());
        return self.reregister(event_loop);
    }

    pub fn read<T: ServerHandler>(&mut self,
                                  event_loop: &mut EventLoop<Server<T>>)
                                  -> Result<(Vec<ConnData>)> {
        let mut bufs = vec![];

        loop {
            // Because we use the edge trigger, so here we must read whole data.
            if self.payload.is_none() {
                try!(try_read_data(&mut self.sock, &mut self.header));
                if self.header.remaining() > 0 {
                    // we need to read more data for header
                    break;
                }

                // we have already read whole header, parse it and begin to read payload.
                let (msg_id, payload_len) = try!(codec::decode_msg_header(self.header
                                                                              .bytes()));
                self.last_msg_id = msg_id;
                self.payload = Some(create_mem_buf(payload_len));
            }

            // payload here can't be None.
            let mut payload = self.payload.take().unwrap();
            try!(try_read_data(&mut self.sock, &mut payload));
            if payload.remaining() > 0 {
                // we need to read more data for payload
                self.payload = Some(payload);
                break;
            }

            bufs.push(ConnData {
                token: self.token,
                msg_id: self.last_msg_id,
                data: payload.flip(),
            });

            self.header.clear();
        }

        try!(self.reregister(event_loop));

        Ok((bufs))
    }

    pub fn write<T: ServerHandler>(&mut self, event_loop: &mut EventLoop<Server<T>>) -> Result<()> {
        while !self.res.is_empty() {
            let mut buf = self.res.pop_front().unwrap();

            try!(try_write_data(&mut self.sock, &mut buf));

            if buf.remaining() > 0 {
                // well, we don't write all, and need re-write later.
                self.res.push_front(buf);
                break;
            }
        }

        if self.res.is_empty() {
            // no data for writing.
            self.interest.remove(EventSet::writable());
        } else {
            // need to write next time.
            self.interest.insert(EventSet::writable());
        }

        return self.reregister(event_loop);
    }

    pub fn append_write_buf(&mut self, msg: ConnData) {
        self.res.push_back(msg.encode_to_buf());
    }
}
<commit_msg>raftserver: use front_mut instead of pop first.<commit_after>#![allow(dead_code)]

use std::vec::Vec;
// use std::io::{Read, Write};
use std::collections::VecDeque;
use std::option::Option;

use mio::{Token, EventLoop, EventSet, PollOpt, TryRead, TryWrite};
use mio::tcp::TcpStream;
use bytes::{Buf, MutBuf, ByteBuf, MutByteBuf, alloc};

use raftserver::{Result, ConnData};
use raftserver::server::Server;
use raftserver::handler::ServerHandler;
use util::codec;

pub struct Conn {
    pub sock: TcpStream,
    pub token: Token,
    pub interest: EventSet,

    // message header
    last_msg_id: u64,
    header: MutByteBuf,
    // message
    payload: Option<MutByteBuf>,

    // write buffer, including msg header already.
    res: VecDeque<ByteBuf>,
}

fn try_read_data<T: TryRead, B: MutBuf>(r: &mut T, buf: &mut B) -> Result<()> {
    if buf.remaining() == 0 {
        return Ok(());
    }

    // TODO: use try_read_buf directly if we can solve the compile problem.
    unsafe {
        // header is not full read, we will try read more.
        let n = try!(r.try_read(buf.mut_bytes()));
        match n {
            None => {
                // nothing to do here now, but should we return an error or panic?
                error!("connection read None data");
            }
            Some(n) => buf.advance(n),
        }
    }

    Ok(())
}

fn create_mem_buf(s: usize) -> MutByteBuf {
    unsafe {
        ByteBuf::from_mem_ref(alloc::heap(s.next_power_of_two()), s as u32, 0, s as u32).flip()
    }
}

impl Conn {
    pub fn new(sock: TcpStream, token: Token) -> Conn {
        Conn {
            sock: sock,
            token: token,
            interest: EventSet::readable(),
            header: create_mem_buf(codec::MSG_HEADER_LEN),
            payload: None,
            res: VecDeque::new(),
            last_msg_id: 0,
        }
    }

    pub fn reregister<T: ServerHandler>(&mut self,
                                        event_loop: &mut EventLoop<Server<T>>)
                                        -> Result<()> {
        try!(event_loop.reregister(&self.sock,
                                   self.token,
                                   self.interest,
                                   PollOpt::edge() | PollOpt::oneshot()));
        Ok(())
    }

    pub fn reregister_writeable<T: ServerHandler>(&mut self,
                                                  event_loop: &mut EventLoop<Server<T>>)
                                                  -> Result<()> {
        self.interest.insert(EventSet::writable());
        return self.reregister(event_loop);
    }

    pub fn read<T: ServerHandler>(&mut self,
                                  event_loop: &mut EventLoop<Server<T>>)
                                  -> Result<(Vec<ConnData>)> {
        let mut bufs = vec![];

        loop {
            // Because we use the edge trigger, so here we must read whole data.
            if self.payload.is_none() {
                try!(try_read_data(&mut self.sock, &mut self.header));
                if self.header.remaining() > 0 {
                    // we need to read more data for header
                    break;
                }

                // we have already read whole header, parse it and begin to read payload.
                let (msg_id, payload_len) = try!(codec::decode_msg_header(self.header
                                                                              .bytes()));
                self.last_msg_id = msg_id;
                self.payload = Some(create_mem_buf(payload_len));
            }

            // payload here can't be None.
            let mut payload = self.payload.take().unwrap();
            try!(try_read_data(&mut self.sock, &mut payload));
            if payload.remaining() > 0 {
                // we need to read more data for payload
                self.payload = Some(payload);
                break;
            }

            bufs.push(ConnData {
                token: self.token,
                msg_id: self.last_msg_id,
                data: payload.flip(),
            });

            self.header.clear();
        }

        try!(self.reregister(event_loop));

        Ok((bufs))
    }

    fn write_buf(&mut self) -> Result<usize> {
        // we check empty before.
        let mut buf = self.res.front_mut().unwrap();

        let n = try!(self.sock.try_write(buf.bytes()));
        match n {
            None => {}
            Some(n) => buf.advance(n),
        }

        Ok(buf.remaining())
    }

    pub fn write<T: ServerHandler>(&mut self, event_loop: &mut EventLoop<Server<T>>) -> Result<()> {
        while !self.res.is_empty() {
            let remaining = try!(self.write_buf());

            if remaining > 0 {
                // well, we don't write all, and need re-write later.
                break;
            }
            self.res.pop_front();
        }

        if self.res.is_empty() {
            // no data for writing.
            self.interest.remove(EventSet::writable());
        } else {
            // need to write next time.
            self.interest.insert(EventSet::writable());
        }

        return self.reregister(event_loop);
    }

    pub fn append_write_buf(&mut self, msg: ConnData) {
        self.res.push_back(msg.encode_to_buf());
    }
}
<|endoftext|>


<commit_before>use tensor::Tensor;
use traits::TensorTrait;
use std::ops::{Add, Sub, Mul, Div, Rem, Neg, BitAnd, BitOr, BitXor};

// T <op> &T
macro_rules! add_impl {
    ($trait:ident, $func_name:ident, $func_name_with_mul:ident) => (
        // T <op> T
        impl<T: TensorTrait + $trait<Output=T>> $trait for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: Self::Output) -> Self::Output {
                if rhs.is_scalar() {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        let mut data = self.slice_mut();
                        let v: T = rhs.scalar_value() as T;
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    self
                } else if self.is_scalar() {
                    let mut t = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        assert_eq!(self.shape, rhs.shape);
                        let mut data = self.slice_mut();
                        for i in 0..n {
                            data[i] = data[i].$func_name(rhs.data[i]);
                        }
                    }
                    self
                }
            }
        }

        // T <op> &T
        impl<'a, T: TensorTrait + $trait<Output=T>> $trait<&'a Tensor<T>> for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: &Self::Output) -> Self::Output {
                if rhs.is_scalar() {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        let mut data = self.slice_mut();
                        let v = rhs.scalar_value();
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    self
                } else if self.is_scalar() {
                    let mut t: Tensor<T> = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        assert_eq!(self.shape, rhs.shape);
                        let mut data = self.slice_mut();
                        for i in 0..n {
                            data[i] = data[i].$func_name(rhs.data[i]);
                        }
                    }
                    self
                }
            }
        }

        // T <op> &T  (with out)
        impl<T: TensorTrait + $trait<Output=T>> Tensor<T> {
            pub fn $func_name_with_mul(&self, rhs: &Tensor<T>, out: &mut Tensor<T>) -> () {
                out.canonize_inplace();
                if rhs.is_scalar() {
                    assert!(out.shape() == self.shape());
                    let n = out.size();
                    let mut data = out.slice_mut();
                    let v = rhs.scalar_value();
                    for i in 0..n {
                        data[i] = data[i].$func_name(v);
                    }
                } else if self.is_scalar() {
                    assert!(out.shape() == rhs.shape());
                    let mut data = out.slice_mut();
                    let v = self.scalar_value();
                    for i in 0..rhs.size() {
                        data[i] = v.$func_name(rhs.data[i]);
                    }
                } else {
                    assert_eq!(self.shape, rhs.shape);
                    let n = out.size();
                    let mut data = out.slice_mut();
                    for i in 0..n {
                        data[i] = self.data[i].$func_name(rhs.data[i]);
                    }
                }
            }
        }

        // &T <op> &T
        impl<'a, T: TensorTrait + $trait<Output=T>> $trait<&'a Tensor<T>> for &'a Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(self, rhs: &Self::Output) -> Self::Output {
                //println!("$fname &T + &T");
                if rhs.is_scalar() {
                    //let mut t = self.clone();
                    //let mut t: Tensor<T> = Tensor::empty(&self.shape);
                    let mut t = self.canonize();
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = rhs.scalar_value();
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    t
                } else if self.is_scalar() {
                    let mut t = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    assert_eq!(self.shape, rhs.shape);
                    //let mut t: Tensor<T> = Tensor::empty(&self.shape);
                    let mut t = self.canonize();
                    {
                        let mut data = t.slice_mut();
                        for (i, v) in rhs.iter().enumerate() {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    t
                }
            }
        }

        // T <op> S
        impl<T: TensorTrait + $trait<Output=T>> $trait<T> for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: T) -> Self::Output {
                self.canonize_inplace();
                {
                    let n = self.size();
                    let mut data = self.slice_mut();
                    for i in 0..n {
                        data[i] = data[i].$func_name(rhs);
                    }
                }
                self
            }
        }
    )
}

// Any operation supported on T should be supported on Tensor<T>, as long as T supports TensorTrait
add_impl!(Add, add, add_with_out);
add_impl!(Sub, sub, sub_with_out);
add_impl!(Mul, mul, mul_with_out);
add_impl!(Div, div, div_with_out);
add_impl!(Rem, rem, rem_with_out);

add_impl!(BitAnd, bitand, bitand_with_out);
add_impl!(BitOr, bitor, bitor_with_out);
add_impl!(BitXor, bitxor, bitxor_with_out);

// -T
impl<T: TensorTrait + Neg<Output=T>> Neg for Tensor<T> {
    type Output = Tensor<T>;
    fn neg(mut self) -> Self::Output {
        self.canonize_inplace();
        {
            let n = self.size();
            let mut data = self.slice_mut();
            for i in 0..n {
                data[i] = -data[i];
            }
        }
        self
    }
}

// -&T
impl<'a, T: TensorTrait + Neg<Output=T>> Neg for &'a Tensor<T> {
    type Output = Tensor<T>;
    fn neg(self) -> Self::Output {
        let mut t = Tensor::empty(&self.shape);
        {
            let mut data = t.slice_mut();
            for (i, v) in self.iter().enumerate() {
                data[i] = -v;
            }
        }
        t
    }
}

/*
#[test]
fn test_negate1() {
    let t0 = tensor![1.0, 10.0; 23.0, -4.0];
    let t1 = -&t0;

    let ta = tensor![-1.0, -10.0; -23.0, 4.0];
    assert!(t1 == ta);
}

#[test]
fn test_negate2() {
    let t0 = Tensor::range(120).reshape(&[5, 4, 2, 3]);
    let t1 = t0.index(&[AxisIndex::Index(3),
                        AxisIndex::StridedSlice(Some(3), None, -2),
                        AxisIndex::Index(1),
                        AxisIndex::StridedSlice(None, None, 2)]);
    let t2 = -&t1;

    let ta = tensor![-93, -95; -81, -83];
    assert!(t2 == ta);
}
*/
<commit_msg>Avoid keyword trait<commit_after>use tensor::Tensor;
use traits::TensorTrait;
use std::ops::{Add, Sub, Mul, Div, Rem, Neg, BitAnd, BitOr, BitXor};

// T <op> &T
macro_rules! add_impl {
    ($trait_name:ident, $func_name:ident, $func_name_with_mul:ident) => (
        // T <op> T
        impl<T: TensorTrait + $trait_name<Output=T>> $trait_name for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: Self::Output) -> Self::Output {
                if rhs.is_scalar() {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        let mut data = self.slice_mut();
                        let v: T = rhs.scalar_value() as T;
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    self
                } else if self.is_scalar() {
                    let mut t = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        assert_eq!(self.shape, rhs.shape);
                        let mut data = self.slice_mut();
                        for i in 0..n {
                            data[i] = data[i].$func_name(rhs.data[i]);
                        }
                    }
                    self
                }
            }
        }

        // T <op> &T
        impl<'a, T: TensorTrait + $trait_name<Output=T>> $trait_name<&'a Tensor<T>> for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: &Self::Output) -> Self::Output {
                if rhs.is_scalar() {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        let mut data = self.slice_mut();
                        let v = rhs.scalar_value();
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    self
                } else if self.is_scalar() {
                    let mut t: Tensor<T> = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    self.canonize_inplace();
                    {
                        let n = self.size();
                        assert_eq!(self.shape, rhs.shape);
                        let mut data = self.slice_mut();
                        for i in 0..n {
                            data[i] = data[i].$func_name(rhs.data[i]);
                        }
                    }
                    self
                }
            }
        }

        // T <op> &T  (with out)
        impl<T: TensorTrait + $trait_name<Output=T>> Tensor<T> {
            pub fn $func_name_with_mul(&self, rhs: &Tensor<T>, out: &mut Tensor<T>) -> () {
                out.canonize_inplace();
                if rhs.is_scalar() {
                    assert!(out.shape() == self.shape());
                    let n = out.size();
                    let mut data = out.slice_mut();
                    let v = rhs.scalar_value();
                    for i in 0..n {
                        data[i] = data[i].$func_name(v);
                    }
                } else if self.is_scalar() {
                    assert!(out.shape() == rhs.shape());
                    let mut data = out.slice_mut();
                    let v = self.scalar_value();
                    for i in 0..rhs.size() {
                        data[i] = v.$func_name(rhs.data[i]);
                    }
                } else {
                    assert_eq!(self.shape, rhs.shape);
                    let n = out.size();
                    let mut data = out.slice_mut();
                    for i in 0..n {
                        data[i] = self.data[i].$func_name(rhs.data[i]);
                    }
                }
            }
        }

        // &T <op> &T
        impl<'a, T: TensorTrait + $trait_name<Output=T>> $trait_name<&'a Tensor<T>> for &'a Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(self, rhs: &Self::Output) -> Self::Output {
                //println!("$fname &T + &T");
                if rhs.is_scalar() {
                    //let mut t = self.clone();
                    //let mut t: Tensor<T> = Tensor::empty(&self.shape);
                    let mut t = self.canonize();
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = rhs.scalar_value();
                        for i in 0..n {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    t
                } else if self.is_scalar() {
                    let mut t = Tensor::empty(&rhs.shape);
                    {
                        let n = t.size();
                        let mut data = t.slice_mut();
                        let v = self.scalar_value();
                        for i in 0..n {
                            data[i] = v.$func_name(rhs.data[i]);
                        }
                    }
                    t
                } else {
                    assert_eq!(self.shape, rhs.shape);
                    //let mut t: Tensor<T> = Tensor::empty(&self.shape);
                    let mut t = self.canonize();
                    {
                        let mut data = t.slice_mut();
                        for (i, v) in rhs.iter().enumerate() {
                            data[i] = data[i].$func_name(v);
                        }
                    }
                    t
                }
            }
        }

        // T <op> S
        impl<T: TensorTrait + $trait_name<Output=T>> $trait_name<T> for Tensor<T> {
            type Output = Tensor<T>;
            fn $func_name(mut self, rhs: T) -> Self::Output {
                self.canonize_inplace();
                {
                    let n = self.size();
                    let mut data = self.slice_mut();
                    for i in 0..n {
                        data[i] = data[i].$func_name(rhs);
                    }
                }
                self
            }
        }
    )
}

// Any operation supported on T should be supported on Tensor<T>, as long as T supports TensorTrait
add_impl!(Add, add, add_with_out);
add_impl!(Sub, sub, sub_with_out);
add_impl!(Mul, mul, mul_with_out);
add_impl!(Div, div, div_with_out);
add_impl!(Rem, rem, rem_with_out);

add_impl!(BitAnd, bitand, bitand_with_out);
add_impl!(BitOr, bitor, bitor_with_out);
add_impl!(BitXor, bitxor, bitxor_with_out);

// -T
impl<T: TensorTrait + Neg<Output=T>> Neg for Tensor<T> {
    type Output = Tensor<T>;
    fn neg(mut self) -> Self::Output {
        self.canonize_inplace();
        {
            let n = self.size();
            let mut data = self.slice_mut();
            for i in 0..n {
                data[i] = -data[i];
            }
        }
        self
    }
}

// -&T
impl<'a, T: TensorTrait + Neg<Output=T>> Neg for &'a Tensor<T> {
    type Output = Tensor<T>;
    fn neg(self) -> Self::Output {
        let mut t = Tensor::empty(&self.shape);
        {
            let mut data = t.slice_mut();
            for (i, v) in self.iter().enumerate() {
                data[i] = -v;
            }
        }
        t
    }
}

/*
#[test]
fn test_negate1() {
    let t0 = tensor![1.0, 10.0; 23.0, -4.0];
    let t1 = -&t0;

    let ta = tensor![-1.0, -10.0; -23.0, 4.0];
    assert!(t1 == ta);
}

#[test]
fn test_negate2() {
    let t0 = Tensor::range(120).reshape(&[5, 4, 2, 3]);
    let t1 = t0.index(&[AxisIndex::Index(3),
                        AxisIndex::StridedSlice(Some(3), None, -2),
                        AxisIndex::Index(1),
                        AxisIndex::StridedSlice(None, None, 2)]);
    let t2 = -&t1;

    let ta = tensor![-93, -95; -81, -83];
    assert!(t2 == ta);
}
*/
<|endoftext|>