<commit_before>use num::{PrimInt, Signed};
use num::traits::CheckedShr;
use std::mem;
use std::cmp::{min};

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  let divisor = T::one() << shift;
  let mask = divisor - T::one();
  if (input & mask) << 1 == divisor {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + (divisor >> 1)) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// Each coefficient, except the constant one, must obey coefficient.abs() <= T::max_value() >> shift.
/// The constant coefficient must obey coefficient.abs() <= T::max_value() - (T::max_value() >> shift),
/// i.e. be small enough that you can add one of the other coefficients to it without overflowing.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_at_small_input <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  let half = (T::one() << shift) >> 1;
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_at_small_input must be in the range [-0.5, 0.5]");

  if coefficients.len () == 0 {return T::zero()}

  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

/// Translate a polynomial horizontally, letting it take inputs relative to a given input instead of relative to 0.
///
/// This is equivalent to replacing its coefficients with its Taylor coefficients at the given input.
/// This is equivalent to translating the graph *left* by the given input amount.
///
/// For constant polynomials, this is a no-op.
///
/// Otherwise, to avoid overflow, each term, when evaluating at the given input,
/// must obey term.abs() <= T::max_value() >> (coefficients.len() - 1).
/// If this condition is broken, translate_polynomial() returns Err and makes no changes.
pub fn translate_polynomial <T: PrimInt + Signed + CheckedShr> (coefficients: &mut [T], input: T)->Result <(),()> {
  if coefficients.len() <= 1 {return Ok(());}
  if !safe_to_translate_polynomial_to (coefficients, input, |_| T::max_value()) {return Err (())}
  translate_polynomial_unchecked (coefficients, input) ;
  Ok (())
}

/// Same as translate_polynomial(), but assume no overflow will occur.
///
/// Useful in performance-critical code when you already know there won't be overflow,
/// such as in the range returned by conservative_safe_polynomial_translation_range.
pub fn translate_polynomial_unchecked <T: PrimInt + Signed> (coefficients: &mut [T], input: T) {
  coefficients.reverse();
  for index in 0..coefficients.len() {
    let coefficient = mem::replace (&mut coefficients [index], T::zero());
    for derivative in (1..(index + 1)).rev() {
      coefficients [derivative] = coefficients [derivative]*input + coefficients [derivative - 1]
    }
    coefficients [0] = coefficients [0]*input + coefficient
  }
}

pub fn safe_to_translate_polynomial_to <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: & [T], input: T, maximum: MaximumFn)->bool {
  if coefficients.len() <= 1 {return true;}
  let mut factor = T::one();
  let input = input.abs();
  let sum_safety_shift = coefficients.len() as u32 - 1;
  let mut running_maximum = T::max_value();
  for (power, coefficient) in coefficients.iter().enumerate() {
    running_maximum = min (running_maximum, maximum (power).checked_shr (sum_safety_shift).unwrap_or (T::zero()));
    if coefficient == &T::min_value() {return false;}
    match coefficient.abs().checked_mul (&factor) {
      None => return false,
      Some (term) => if term > running_maximum {return false;},
    }
    if power + 1 < coefficients.len() { match factor.checked_mul (&input) {
      None => return false,
      Some (next_factor) => factor = next_factor,
    }}
  }
  true
}

/// Find the range of inputs to which the polynomial can safely be translated.
///
/// Magnitudes <= result are safe to translate to; magnitudes > result aren't.
/// If even the initial value is out of bounds, this function returns -1.
///
/// The third argument can impose a stricter maximum on the resulting coefficients.
pub fn exact_safe_polynomial_translation_range <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: & [T], maximum: MaximumFn)->T {
  if coefficients.len() <= 1 || coefficients [1..].iter().all (| coefficient | coefficient == &T::zero()) {return T::max_value()}
  // if we know that there's at least one nonzero non-constant coefficient, T::max_value is never legal, so we can pick a min that definitely legal and a max that's definitely not
  let mut min = -T::one();
  let mut max = T::max_value();
  while min + T::one() < max {
    let mid = (min >> 1u32) + (max >> 1u32) + (min & max & T::one());
    if safe_to_translate_polynomial_to (coefficients, mid, & maximum) {
      min = mid;
    } else {
      max = mid;
    }
  }
  min
}

/// Find a range of inputs to which the polynomial can safely be translated.
///
/// Magnitudes <= result are safe to translate to.
/// Magnitudes >= result*2 aren't.
/// If even the initial value is out of bounds, this function returns -1.
///
/// The third argument can impose a stricter maximum on the resulting coefficients.
///
/// This function is much faster than exact_safe_polynomial_translation_range, at the cost of being less precise.
pub fn conservative_safe_polynomial_translation_range <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: &mut [T], maximum: MaximumFn)->T {
  if coefficients.len() <= 1 {return T::max_value()}
  let sum_safety_shift = coefficients.len() as u32 - 1;
  let mut running_maximum = T::max_value();
  let mut result_shift = mem::size_of::<T>()*8 - 2;
  for (power, coefficient) in coefficients.iter().enumerate() {
    let magnitude = coefficient.abs();
    running_maximum = min (running_maximum, maximum (power).checked_shr (sum_safety_shift).unwrap_or (T::zero()));
    while magnitude > (running_maximum >> (result_shift*power)) {
      if result_shift == 0 {return -T::one();}
      result_shift -= 1;
    }
  }
  T::one() << result_shift
}

#[cfg (test)]
mod tests {
  use super::*;
  use num::{Zero, One, FromPrimitive};
  use num::bigint::BigInt;
  use num::rational::{Ratio, BigRational};
  use rand::distributions::Distribution;
  use rand::distributions::range::{Range};
  use rand::{Rng, SeedableRng};

  fn evaluate_polynomial_exactly <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->BigRational
    where BigInt: From <Coefficient> + From <T> {
    let mut result: BigRational = Ratio::zero();
    let input = Ratio::new(BigInt::from (input), BigInt::one() << shift);
    for coefficient in coefficients.iter().rev() {
      result = result*&input + BigInt::from(*coefficient);
    }
    result
  }

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  #[test]
  fn test_evaluate_polynomial_at_small_input() {
    let mut generator =::rand::chacha::ChaChaRng::from_seed ([33; 32]) ;
    for shift in 0..5 {
      let shift = 1 << shift;
      let half = 1i64 << (shift - 1);
      let maximum = i64::max_value() >> shift;
      let constant_maximum = i64::max_value() - maximum;
      let range = Range::new_inclusive (- maximum, maximum) ;
      let constant_range = Range::new_inclusive (- constant_maximum, constant_maximum);
      let mut test_inputs = vec![- half, - half + 1, - 1, 0, 1, half - 1, half];
      if half > 2 {for _ in 0..6 {test_inputs.push (generator.gen_range (- half + 2, half - 1));}}
      for _ in 0..40 {
        let mut coefficients = vec![constant_range.sample (&mut generator)];
        while generator.gen() {coefficients.push (range.sample (&mut generator));}
        for input in test_inputs.iter() {
          let result = evaluate_polynomial_at_small_input (& coefficients,*input, shift);

          let perfect_result = evaluate_polynomial_exactly (& coefficients,*input, shift);
          let difference = Ratio::from_integer (FromPrimitive::from_i64 (result).unwrap()) - perfect_result;
          assert!(difference < Ratio::from_integer (FromPrimitive::from_i64 (1).unwrap()));
        }
      }
    }
  }

  quickcheck! {
    fn safe_translation_range_is_safe (coefficients_and_maxima: Vec<(i64, i64)>)->bool {
      let coefficients: Vec<_> = coefficients_and_maxima.iter().map (| & (coefficient,_) | coefficient).collect();
      let maxima = | index: usize | coefficients_and_maxima [index].1;
      let range = exact_safe_polynomial_translation_range (& coefficients, maxima);
      println!( "{:?}", range);
      range < 0 || safe_to_translate_polynomial_to (& coefficients, range, maxima)
    }
  }
}
<commit_msg>Wrote another test, which passes<commit_after>use num::{PrimInt, Signed};
use num::traits::CheckedShr;
use std::mem;
use std::cmp::{min};

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  let divisor = T::one() << shift;
  let mask = divisor - T::one();
  if (input & mask) << 1 == divisor {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + (divisor >> 1)) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// Each coefficient, except the constant one, must obey coefficient.abs() <= T::max_value() >> shift.
/// The constant coefficient must obey coefficient.abs() <= T::max_value() - (T::max_value() >> shift),
/// i.e. be small enough that you can add one of the other coefficients to it without overflowing.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_at_small_input <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  let half = (T::one() << shift) >> 1;
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_at_small_input must be in the range [-0.5, 0.5]");

  if coefficients.len () == 0 {return T::zero()}

  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

/// Translate a polynomial horizontally, letting it take inputs relative to a given input instead of relative to 0.
///
/// This is equivalent to replacing its coefficients with its Taylor coefficients at the given input.
/// This is equivalent to translating the graph *left* by the given input amount.
///
/// For constant polynomials, this is a no-op.
///
/// Otherwise, to avoid overflow, each term, when evaluating at the given input,
/// must obey term.abs() <= T::max_value() >> (coefficients.len() - 1).
/// If this condition is broken, translate_polynomial() returns Err and makes no changes.
pub fn translate_polynomial <T: PrimInt + Signed + CheckedShr> (coefficients: &mut [T], input: T)->Result <(),()> {
  if coefficients.len() <= 1 {return Ok(());}
  if !safe_to_translate_polynomial_to (coefficients, input, |_| T::max_value()) {return Err (())}
  translate_polynomial_unchecked (coefficients, input) ;
  Ok (())
}

/// Same as translate_polynomial(), but assume no overflow will occur.
///
/// Useful in performance-critical code when you already know there won't be overflow,
/// such as in the range returned by conservative_safe_polynomial_translation_range.
pub fn translate_polynomial_unchecked <T: PrimInt + Signed> (coefficients: &mut [T], input: T) {
  coefficients.reverse();
  for index in 0..coefficients.len() {
    let coefficient = mem::replace (&mut coefficients [index], T::zero());
    for derivative in (1..(index + 1)).rev() {
      coefficients [derivative] = coefficients [derivative]*input + coefficients [derivative - 1]
    }
    coefficients [0] = coefficients [0]*input + coefficient
  }
}

pub fn safe_to_translate_polynomial_to <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: & [T], input: T, maximum: MaximumFn)->bool {
  if coefficients.len() <= 1 {return true;}
  let mut factor = T::one();
  let input = input.abs();
  let sum_safety_shift = coefficients.len() as u32 - 1;
  let mut running_maximum = T::max_value();
  for (power, coefficient) in coefficients.iter().enumerate() {
    running_maximum = min (running_maximum, maximum (power).checked_shr (sum_safety_shift).unwrap_or (T::zero()));
    if coefficient == &T::min_value() {return false;}
    match coefficient.abs().checked_mul (&factor) {
      None => return false,
      Some (term) => if term > running_maximum {return false;},
    }
    if power + 1 < coefficients.len() { match factor.checked_mul (&input) {
      None => return false,
      Some (next_factor) => factor = next_factor,
    }}
  }
  true
}

/// Find the range of inputs to which the polynomial can safely be translated.
///
/// Magnitudes <= result are safe to translate to; magnitudes > result aren't.
/// If even the initial value is out of bounds, this function returns -1.
///
/// The third argument can impose a stricter maximum on the resulting coefficients.
pub fn exact_safe_polynomial_translation_range <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: & [T], maximum: MaximumFn)->T {
  if coefficients.len() <= 1 || coefficients [1..].iter().all (| coefficient | coefficient == &T::zero()) {return T::max_value()}
  // if we know that there's at least one nonzero non-constant coefficient, T::max_value is never legal, so we can pick a min that definitely legal and a max that's definitely not
  let mut min = -T::one();
  let mut max = T::max_value();
  while min + T::one() < max {
    let mid = (min >> 1u32) + (max >> 1u32) + (min & max & T::one());
    if safe_to_translate_polynomial_to (coefficients, mid, & maximum) {
      min = mid;
    } else {
      max = mid;
    }
  }
  min
}

/// Find a range of inputs to which the polynomial can safely be translated.
///
/// Magnitudes <= result are safe to translate to.
/// Magnitudes >= result*2 aren't.
/// If even the initial value is out of bounds, this function returns -1.
///
/// The third argument can impose a stricter maximum on the resulting coefficients.
///
/// This function is much faster than exact_safe_polynomial_translation_range, at the cost of being less precise.
pub fn conservative_safe_polynomial_translation_range <T: PrimInt + Signed + CheckedShr, MaximumFn: Fn (usize)->T> (coefficients: &mut [T], maximum: MaximumFn)->T {
  if coefficients.len() <= 1 {return T::max_value()}
  let sum_safety_shift = coefficients.len() as u32 - 1;
  let mut running_maximum = T::max_value();
  let mut result_shift = mem::size_of::<T>()*8 - 2;
  for (power, coefficient) in coefficients.iter().enumerate() {
    let magnitude = coefficient.abs();
    running_maximum = min (running_maximum, maximum (power).checked_shr (sum_safety_shift).unwrap_or (T::zero()));
    while magnitude > (running_maximum >> (result_shift*power)) {
      if result_shift == 0 {return -T::one();}
      result_shift -= 1;
    }
  }
  T::one() << result_shift
}

#[cfg (test)]
mod tests {
  use super::*;
  use num::{Zero, One, FromPrimitive};
  use num::bigint::BigInt;
  use num::rational::{Ratio, BigRational};
  use rand::distributions::Distribution;
  use rand::distributions::range::{Range};
  use rand::{Rng, SeedableRng};

  fn evaluate_polynomial_exactly <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->BigRational
    where BigInt: From <Coefficient> + From <T> {
    let mut result: BigRational = Ratio::zero();
    let input = Ratio::new(BigInt::from (input), BigInt::one() << shift);
    for coefficient in coefficients.iter().rev() {
      result = result*&input + BigInt::from(*coefficient);
    }
    result
  }

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  #[test]
  fn test_evaluate_polynomial_at_small_input() {
    let mut generator =::rand::chacha::ChaChaRng::from_seed ([33; 32]) ;
    for shift in 0..5 {
      let shift = 1 << shift;
      let half = 1i64 << (shift - 1);
      let maximum = i64::max_value() >> shift;
      let constant_maximum = i64::max_value() - maximum;
      let range = Range::new_inclusive (- maximum, maximum) ;
      let constant_range = Range::new_inclusive (- constant_maximum, constant_maximum);
      let mut test_inputs = vec![- half, - half + 1, - 1, 0, 1, half - 1, half];
      if half > 2 {for _ in 0..6 {test_inputs.push (generator.gen_range (- half + 2, half - 1));}}
      for _ in 0..40 {
        let mut coefficients = vec![constant_range.sample (&mut generator)];
        while generator.gen() {coefficients.push (range.sample (&mut generator));}
        for input in test_inputs.iter() {
          let result = evaluate_polynomial_at_small_input (& coefficients,*input, shift);

          let perfect_result = evaluate_polynomial_exactly (& coefficients,*input, shift);
          let difference = Ratio::from_integer (FromPrimitive::from_i64 (result).unwrap()) - perfect_result;
          assert!(difference < Ratio::from_integer (FromPrimitive::from_i64 (1).unwrap()));
        }
      }
    }
  }

  quickcheck! {
    fn exact_safe_translation_range_is_safe (coefficients_and_maxima: Vec<(i64, i64)>)->bool {
      let coefficients: Vec<_> = coefficients_and_maxima.iter().map (| & (coefficient,_) | coefficient).collect();
      let maxima = | index: usize | coefficients_and_maxima [index].1;
      let range = exact_safe_polynomial_translation_range (& coefficients, maxima);
      println!( "{:?}", range);
      range < 0 || safe_to_translate_polynomial_to (& coefficients, range, maxima)
    }

    fn exact_safe_translation_range_is_maximal (coefficients_and_maxima: Vec<(i64, i64)>)->bool {
      let coefficients: Vec<_> = coefficients_and_maxima.iter().map (| & (coefficient,_) | coefficient).collect();
      let maxima = | index: usize | coefficients_and_maxima [index].1;
      let range = exact_safe_polynomial_translation_range (& coefficients, maxima);
      println!( "{:?}", range);
      range == i64::max_value() || !safe_to_translate_polynomial_to (& coefficients, range + 1, maxima)
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>codegen: start improving test<commit_after><|endoftext|>


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

//! Numeric traits for generic mathematics
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
       html_root_url = "https://rust-num.github.io/num/",
       html_playground_url = "http://play.integer32.com/")]

use std::ops::{Add, Sub, Mul, Div, Rem};

pub use bounds::Bounded;
pub use float::{Float, FloatConst};
pub use identities::{Zero, One, zero, one};
pub use ops::checked::*;
pub use ops::wrapping::*;
pub use ops::saturating::Saturating;
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
pub use cast::*;
pub use int::PrimInt;
pub use pow::{pow, checked_pow};

pub mod identities;
pub mod sign;
pub mod ops;
pub mod bounds;
pub mod float;
pub mod cast;
pub mod int;
pub mod pow;

/// The base trait for numeric types
pub trait Num: PartialEq + Zero + One
    + Add<Output = Self> + Sub<Output = Self>
    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
{
    type FromStrRadixErr;

    /// Convert from a string and radix <= 36.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use num_traits::Num;
    ///
    /// let result = <i32 as Num>::from_str_radix("27", 10);
    /// assert_eq!(result, Ok(27));
    ///
    /// let result = <i32 as Num>::from_str_radix("foo", 10);
    /// assert!(result.is_err());
    /// ```
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}

macro_rules! int_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ::std::num::ParseIntError;
            #[inline]
            fn from_str_radix(s: &str, radix: u32)
                              -> Result<Self, ::std::num::ParseIntError>
            {
                <$t>::from_str_radix(s, radix)
            }
        }
    )*)
}
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);

#[derive(Debug)]
pub enum FloatErrorKind {
    Empty,
    Invalid,
}
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
// so there's not really any way for us to reuse it.
#[derive(Debug)]
pub struct ParseFloatError {
    pub kind: FloatErrorKind,
}

// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
macro_rules! float_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ParseFloatError;

            fn from_str_radix(src: &str, radix: u32)
                              -> Result<Self, Self::FromStrRadixErr>
            {
                use self::FloatErrorKind::*;
                use self::ParseFloatError as PFE;

                // Special values
                match src {
                    "inf"   => return Ok(Float::infinity()),
                    "-inf"  => return Ok(Float::neg_infinity()),
                    "NaN"   => return Ok(Float::nan()),
                    _       => {},
                }

                fn slice_shift_char(src: &str) -> Option<(char, &str)> {
                    src.chars().nth(0).map(|ch| (ch, &src[1..]))
                }

                let (is_positive, src) =  match slice_shift_char(src) {
                    None             => return Err(PFE { kind: Empty }),
                    Some(('-', ""))  => return Err(PFE { kind: Empty }),
                    Some(('-', src)) => (false, src),
                    Some((_, _))     => (true,  src),
                };

                // The significand to accumulate
                let mut sig = if is_positive { 0.0 } else { -0.0 };
                // Necessary to detect overflow
                let mut prev_sig = sig;
                let mut cs = src.chars().enumerate();
                // Exponent prefix and exponent index offset
                let mut exp_info = None::<(char, usize)>;

                // Parse the integer part of the significand
                for (i, c) in cs.by_ref() {
                    match c.to_digit(radix) {
                        Some(digit) => {
                            // shift significand one digit left
                            sig = sig * (radix as $t);

                            // add/subtract current digit depending on sign
                            if is_positive {
                                sig = sig + ((digit as isize) as $t);
                            } else {
                                sig = sig - ((digit as isize) as $t);
                            }

                            // Detect overflow by comparing to last value, except
                            // if we've not seen any non-zero digits.
                            if prev_sig != 0.0 {
                                if is_positive && sig <= prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig >= prev_sig
                                    { return Ok(Float::neg_infinity()); }

                                // Detect overflow by reversing the shift-and-add process
                                if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
                                    { return Ok(Float::infinity()); }
                                if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
                                    { return Ok(Float::neg_infinity()); }
                            }
                            prev_sig = sig;
                        },
                        None => match c {
                            'e' | 'E' | 'p' | 'P' => {
                                exp_info = Some((c, i + 1));
                                break;  // start of exponent
                            },
                            '.' => {
                                break;  // start of fractional part
                            },
                            _ => {
                                return Err(PFE { kind: Invalid });
                            },
                        },
                    }
                }

                // If we are not yet at the exponent parse the fractional
                // part of the significand
                if exp_info.is_none() {
                    let mut power = 1.0;
                    for (i, c) in cs.by_ref() {
                        match c.to_digit(radix) {
                            Some(digit) => {
                                // Decrease power one order of magnitude
                                power = power / (radix as $t);
                                // add/subtract current digit depending on sign
                                sig = if is_positive {
                                    sig + (digit as $t) * power
                                } else {
                                    sig - (digit as $t) * power
                                };
                                // Detect overflow by comparing to last value
                                if is_positive && sig < prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig > prev_sig
                                    { return Ok(Float::neg_infinity()); }
                                prev_sig = sig;
                            },
                            None => match c {
                                'e' | 'E' | 'p' | 'P' => {
                                    exp_info = Some((c, i + 1));
                                    break; // start of exponent
                                },
                                _ => {
                                    return Err(PFE { kind: Invalid });
                                },
                            },
                        }
                    }
                }

                // Parse and calculate the exponent
                let exp = match exp_info {
                    Some((c, offset)) => {
                        let base = match c {
                            'E' | 'e' if radix == 10 => 10.0,
                            'P' | 'p' if radix == 16 => 2.0,
                            _ => return Err(PFE { kind: Invalid }),
                        };

                        // Parse the exponent as decimal integer
                        let src = &src[offset..];
                        let (is_positive, exp) = match slice_shift_char(src) {
                            Some(('-', src)) => (false, src.parse::<usize>()),
                            Some(('+', src)) => (true,  src.parse::<usize>()),
                            Some((_, _))     => (true,  src.parse::<usize>()),
                            None             => return Err(PFE { kind: Invalid }),
                        };

                        match (is_positive, exp) {
                            (true,  Ok(exp)) => base.powi(exp as i32),
                            (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
                            (_, Err(_))      => return Err(PFE { kind: Invalid }),
                        }
                    },
                    None => 1.0, // no exponent
                };

                Ok(sig * exp)
            }
        }
    )*)
}
float_trait_impl!(Num for f32 f64);

/// A value bounded by a minimum and a maximum
///
/// If input is less than min then min is returned, if input is greater than max then max is
/// returned.  Otherwise input is returned.
#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
    debug_assert!(min <= max, "min must be less than max");
    if input < min {
        min
    } else if input > max {
        max
    } else {
        input
    }
}

#[test]
fn clamp_test() {
    // Int test
    assert_eq!(1, clamp(1, -1, 2));
    assert_eq!(-1, clamp(-2, -1, 2));
    assert_eq!(2, clamp(3, -1, 2));

    // Float test
    assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
    assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
    assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
}

#[test]
fn from_str_radix_unwrap() {
    // The Result error must impl Debug to allow unwrap()

    let i: i32 = Num::from_str_radix("0", 10).unwrap();
    assert_eq!(i, 0);

    let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
    assert_eq!(f, 0.0);
}
<commit_msg>Update lib.rs<commit_after>// Copyright 2013-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.

//! Numeric traits for generic mathematics
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
       html_root_url = "https://rust-num.github.io/num/",
       html_playground_url = "http://play.integer32.com/")]

use std::ops::{Add, Sub, Mul, Div, Rem};

pub use bounds::Bounded;
pub use float::{Float, FloatConst};
pub use identities::{Zero, One, zero, one};
pub use ops::checked::*;
pub use ops::wrapping::*;
pub use ops::saturating::Saturating;
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
pub use cast::*;
pub use int::PrimInt;
pub use pow::{pow, checked_pow};

pub mod identities;
pub mod sign;
pub mod ops;
pub mod bounds;
pub mod float;
pub mod cast;
pub mod int;
pub mod pow;

/// The base trait for numeric types
pub trait Num: PartialEq + Zero + One
    + Add<Output = Self> + Sub<Output = Self>
    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
{
    type FromStrRadixErr;

    /// Convert from a string and radix <= 36.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use num_traits::Num;
    ///
    /// let result = <i32 as Num>::from_str_radix("27", 10);
    /// assert_eq!(result, Ok(27));
    ///
    /// let result = <i32 as Num>::from_str_radix("foo", 10);
    /// assert!(result.is_err());
    /// ```
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}

macro_rules! int_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ::std::num::ParseIntError;
            #[inline]
            fn from_str_radix(s: &str, radix: u32)
                              -> Result<Self, ::std::num::ParseIntError>
            {
                <$t>::from_str_radix(s, radix)
            }
        }
    )*)
}
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);

#[derive(Debug)]
pub enum FloatErrorKind {
    Empty,
    Invalid,
}
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
// so there's not really any way for us to reuse it.
#[derive(Debug)]
pub struct ParseFloatError {
    pub kind: FloatErrorKind,
}

// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
macro_rules! float_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ParseFloatError;

            fn from_str_radix(src: &str, radix: u32)
                              -> Result<Self, Self::FromStrRadixErr>
            {
                use self::FloatErrorKind::*;
                use self::ParseFloatError as PFE;

                // Special values
                match src {
                    "inf"   => return Ok(Float::infinity()),
                    "-inf"  => return Ok(Float::neg_infinity()),
                    "NaN"   => return Ok(Float::nan()),
                    _       => {},
                }

                fn slice_shift_char(src: &str) -> Option<(char, &str)> {
                    src.chars().nth(0).map(|ch| (ch, &src[1..]))
                }

                let (is_positive, src) =  match slice_shift_char(src) {
                    None             => return Err(PFE { kind: Empty }),
                    Some(('-', ""))  => return Err(PFE { kind: Empty }),
                    Some(('-', src)) => (false, src),
                    Some((_, _))     => (true,  src),
                };

                // The significand to accumulate
                let mut sig = if is_positive { 0.0 } else { -0.0 };
                // Necessary to detect overflow
                let mut prev_sig = sig;
                let mut cs = src.chars().enumerate();
                // Exponent prefix and exponent index offset
                let mut exp_info = None::<(char, usize)>;

                // Parse the integer part of the significand
                for (i, c) in cs.by_ref() {
                    match c.to_digit(radix) {
                        Some(digit) => {
                            // shift significand one digit left
                            sig = sig * (radix as $t);

                            // add/subtract current digit depending on sign
                            if is_positive {
                                sig = sig + ((digit as isize) as $t);
                            } else {
                                sig = sig - ((digit as isize) as $t);
                            }

                            // Detect overflow by comparing to last value, except
                            // if we've not seen any non-zero digits.
                            if prev_sig != 0.0 {
                                if is_positive && sig <= prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig >= prev_sig
                                    { return Ok(Float::neg_infinity()); }

                                // Detect overflow by reversing the shift-and-add process
                                if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
                                    { return Ok(Float::infinity()); }
                                if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
                                    { return Ok(Float::neg_infinity()); }
                            }
                            prev_sig = sig;
                        },
                        None => match c {
                            'e' | 'E' | 'p' | 'P' => {
                                exp_info = Some((c, i + 1));
                                break;  // start of exponent
                            },
                            '.' => {
                                break;  // start of fractional part
                            },
                            _ => {
                                return Err(PFE { kind: Invalid });
                            },
                        },
                    }
                }

                // If we are not yet at the exponent parse the fractional
                // part of the significand
                if exp_info.is_none() {
                    let mut power = 1.0;
                    for (i, c) in cs.by_ref() {
                        match c.to_digit(radix) {
                            Some(digit) => {
                                // Decrease power one order of magnitude
                                power = power / (radix as $t);
                                // add/subtract current digit depending on sign
                                sig = if is_positive {
                                    sig + (digit as $t) * power
                                } else {
                                    sig - (digit as $t) * power
                                };
                                // Detect overflow by comparing to last value
                                if is_positive && sig < prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig > prev_sig
                                    { return Ok(Float::neg_infinity()); }
                                prev_sig = sig;
                            },
                            None => match c {
                                'e' | 'E' | 'p' | 'P' => {
                                    exp_info = Some((c, i + 1));
                                    break; // start of exponent
                                },
                                _ => {
                                    return Err(PFE { kind: Invalid });
                                },
                            },
                        }
                    }
                }

                // Parse and calculate the exponent
                let exp = match exp_info {
                    Some((c, offset)) => {
                        let base = match c {
                            'E' | 'e' if radix == 10 => 10.0,
                            'P' | 'p' if radix == 16 => 2.0,
                            _ => return Err(PFE { kind: Invalid }),
                        };

                        // Parse the exponent as decimal integer
                        let src = &src[offset..];
                        let (is_positive, exp) = match slice_shift_char(src) {
                            Some(('-', src)) => (false, src.parse::<usize>()),
                            Some(('+', src)) => (true,  src.parse::<usize>()),
                            Some((_, _))     => (true,  src.parse::<usize>()),
                            None             => return Err(PFE { kind: Invalid }),
                        };

                        match (is_positive, exp) {
                            (true,  Ok(exp)) => base.powi(exp as i32),
                            (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
                            (_, Err(_))      => return Err(PFE { kind: Invalid }),
                        }
                    },
                    None => 1.0, // no exponent
                };

                Ok(sig * exp)
            }
        }
    )*)
}
float_trait_impl!(Num for f32 f64);

/// A value bounded by a minimum and a maximum
///
/// If input is less than min then min is returned, if input is greater than max then max is
/// returned.  Otherwise input is returned.
#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
    debug_assert!(min <= max, "min must be less than or equal to max");
    if input < min {
        min
    } else if input > max {
        max
    } else {
        input
    }
}

#[test]
fn clamp_test() {
    // Int test
    assert_eq!(1, clamp(1, -1, 2));
    assert_eq!(-1, clamp(-2, -1, 2));
    assert_eq!(2, clamp(3, -1, 2));

    // Float test
    assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
    assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
    assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
}

#[test]
fn from_str_radix_unwrap() {
    // The Result error must impl Debug to allow unwrap()

    let i: i32 = Num::from_str_radix("0", 10).unwrap();
    assert_eq!(i, 0);

    let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
    assert_eq!(f, 0.0);
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//

use cpu::interrupts::pics;
use cpu::interrupts::idt::Idt;

use cpu::context::InterruptFrame;
use cpu::dtable::DTable;

//==--------------------------------------------------------------------------==
// Top-level interrupt handling

/// Initialize interrupt handling.
///
/// This function initializes the PICs, populates the IDT with interrupt
/// handlers, loads the IDT pointer, and enables interrupts.
///
/// This is called from the kernel during the init process.
pub unsafe fn initialize() {

    pics::initialize();
   // TODO: consider loading double-fault handler before anything else in case
   //       a double fault occurs during init?
    IDT.load();         // Load the IDT pointer
    //
    // debug!("Testing interrupt handling");
    // asm!("int $0" :: "N" (0xff));

    Idt::enable_interrupts(); // enable interrupts

}

macro_rules! exception_inner {
    ($title:expr, $kind:expr, $source:expr, $f:expr) => {
        use vga::{CONSOLE, Color};
        use core::fmt::Write;
        let _ = write!( CONSOLE.lock()
                               .set_colors(Color::White, Color::Blue)
                      , "EVERYTHING IS FINE: {}{} at {:p}\n\
                         Source: {}.\nThis is fine.\n\n\
                         {:?}"
                         , $title, $kind
                         , (*$f).rip
                         , $source
                         , *$f);
    };
    ($title:expr, $kind:expr, $source:expr, $f:expr, $e:expr) => {
        use vga::{CONSOLE, Color};
        use core::fmt::Write;
        let _ = write!( CONSOLE.lock()
                               .set_colors(Color::White, Color::Blue)
                      , "EVERYTHING IS FINE: {}{} at {:p}\n\
                         Source: {}.\n
                         Error code: {:x}\nThis is fine.\n\n\
                         {:?}"
                         , $title, $kind
                         , (*$f).rip
                         , $source
                         , $e
                         , *$f);
    };
}

macro_rules! exceptions {
    ( idt: $idt:expr, $($tail:tt)+ ) => {
        exceptions! {  @impl $idt, $($tail)+  }
    };
    ( @impl $i:expr, fault: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
        #[doc=$title]
        extern "x86-interrupt" fn $name(frame: &InterruptFrame) {
            exception_inner! ($title, "Fault", $source, frame);
            loop {}
        }
        $i.$name.set_handler($name as InterruptHandler);
        exceptions! {  @impl  $i, $($tail)* }
    };
     ( @impl $i:expr, fault (code): $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
        #[doc=$title]
        extern "x86-interrupt" fn $name( frame: &InterruptFrame
                                       , error_code: usize) {
           exception_inner! ($title, "Fault", $source, frame, error_code);
           loop {}
       }
       $i.$name.set_handler($name as ErrorCodeHandler);
       exceptions! { @impl $i, $($tail)* };
   };
     ( @impl $i:expr, trap: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
         #[doc=$title]
         extern "x86-interrupt" fn $name(frame: &InterruptFrame) {
             exception_inner! ($title, "Trap", $source, frame);
         }
         $i.$name.set_handler($name as InterruptHandler)
           .set_trap();
         exceptions! { @impl $i, $($tail)* };
     };
      ( @impl $i:expr, ) => {};

}

lazy_static! {
    static ref IDT: Idt = {
        let mut idt = Idt::new();
        use cpu::interrupts::*;

        // TODO: log each handler as it's added to the IDT? that way we can
        //       trace faults occurring during IDT population (if any)
        //          - eliza, 5/22/2017
        exceptions! { idt: idt,
            fault: divide_by_zero, "Divide by Zero Error",
                   "DIV or IDIV instruction",
            fault: nmi, "Non-Maskable Interrupt",
                  "Non-maskable external interrupt",
            trap: overflow, "Overflow", "INTO instruction",
            fault: bound_exceeded, "BOUND range exceeded",
                  "BOUND instruction",
            fault: undefined_opcode, "Undefined Opcode",
                   "UD2 instruction or reserved opcode",
            fault: device_not_available, "Device Not Available"
                 , "Floating-point or WAIT/FWAIT instruction \
                    (no math coprocessor)",
            fault (code): double_fault, "Double Fault"
                 , "Any instruction that can generate an exception, a NMI, or \
                    an INTR",
            fault (code): invalid_tss, "Invalid TSS"
                 , "Task switch or TSS access",
            fault (code): segment_not_present, "Segment Not Present"
                 , "Loading segment registers or accessing \
                    system segments",
            fault (code): general_protection_fault, "General Protection Fault"
                 , "Any memory reference or other protection checks",
            fault (code): stack_segment_fault, "Stack Segment Fault"
                 , "Stack operations and SS register loads",
            fault: floating_point_error
                 , "x87 FPU Floating-Point Error (Math Fault)"
                 , "x87 FPU floating-point or WAIT/FWAIT instruction",
            fault: machine_check, "Machine Check"
                 , "Model-dependent (probably hardware!)",
            fault (code): alignment_check, "Alignment Check"
                 , "Any data reference in memory",
            fault: simd_fp_exception, "SIMD Floating-Point Exception"
                 , "SSE/SSE2/SSE3 floating-point instructions",
        };

        idt.breakpoint.set_handler(breakpoint as InterruptHandler);
        idt.page_fault.set_handler(page_fault as ErrorCodeHandler);

        for vector in idt.interrupts.iter_mut() {
            vector.set_handler(empty_handler as InterruptHandler);
        }

        idt[0x20].set_handler(timer as InterruptHandler);
        idt[0x21].set_handler(keyboard as InterruptHandler);
        idt[0xff].set_handler(test as InterruptHandler);

        kinfoln!( dots: " . . ", target: "Adding interrupt handlers to IDT"
                , "[ OKAY ]");
        idt
    };
}

#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn keyboard(_frame: &InterruptFrame) {
    use io::keyboard;

    // println!("keyboard happened");
    if let Some(input) = keyboard::read_char() {
        if input == '\r' {
            println!("");
        } else {
            print!("{}", input);
        }
    }
   // send the PICs the end interrupt signal
   unsafe {
       pics::end_pic_interrupt(0x21);
   }
}

#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn breakpoint(frame: &InterruptFrame) {
    println!("Breakpoint! Frame: {:#?}", frame);
   // send the PICs the end interrupt signal
   unsafe {
       pics::end_pic_interrupt(0x03);
   }
}

/// Empty dummy handler for undefined interrupts.
#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn empty_handler(_frame: &InterruptFrame) {
    // TODO: it would be nice to know *which vector* the dummy interrupt
    //      fired on, for debugging purposes...
    //          - eliza, 05/25/2017
    debug!("an empty interrupt fired!")
}
<commit_msg>refac(interrupts): use Gate::from explicitly<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//

use cpu::interrupts::pics;
use cpu::interrupts::idt::{Gate, Idt};

use cpu::context::InterruptFrame;
use cpu::dtable::DTable;

//==--------------------------------------------------------------------------==
// Top-level interrupt handling

/// Initialize interrupt handling.
///
/// This function initializes the PICs, populates the IDT with interrupt
/// handlers, loads the IDT pointer, and enables interrupts.
///
/// This is called from the kernel during the init process.
pub unsafe fn initialize() {

    pics::initialize();
   // TODO: consider loading double-fault handler before anything else in case
   //       a double fault occurs during init?
    IDT.load();         // Load the IDT pointer
    //
    // debug!("Testing interrupt handling");
    // asm!("int $0" :: "N" (0xff));

    Idt::enable_interrupts(); // enable interrupts

}

macro_rules! exception_inner {
    ($title:expr, $kind:expr, $source:expr, $f:expr) => {
        use vga::{CONSOLE, Color};
        use core::fmt::Write;
        let _ = write!( CONSOLE.lock()
                               .set_colors(Color::White, Color::Blue)
                      , "EVERYTHING IS FINE: {}{} at {:p}\n\
                         Source: {}.\nThis is fine.\n\n\
                         {:?}"
                         , $title, $kind
                         , (*$f).rip
                         , $source
                         , *$f);
    };
    ($title:expr, $kind:expr, $source:expr, $f:expr, $e:expr) => {
        use vga::{CONSOLE, Color};
        use core::fmt::Write;
        let _ = write!( CONSOLE.lock()
                               .set_colors(Color::White, Color::Blue)
                      , "EVERYTHING IS FINE: {}{} at {:p}\n\
                         Source: {}.\n
                         Error code: {:x}\nThis is fine.\n\n\
                         {:?}"
                         , $title, $kind
                         , (*$f).rip
                         , $source
                         , $e
                         , *$f);
    };
}

macro_rules! exceptions {
    ( idt: $idt:expr, $($tail:tt)+ ) => {
        exceptions! {  @impl $idt, $($tail)+  }
    };
    ( @impl $i:expr, fault: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
        #[doc=$title]
        extern "x86-interrupt" fn $name(frame: &InterruptFrame) {
            exception_inner! ($title, "Fault", $source, frame);
            loop {}
        }
        $i.$name = Gate::from($name as InterruptHandler);
        exceptions! {  @impl  $i, $($tail)* }
    };
     ( @impl $i:expr, fault (code): $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
        #[doc=$title]
        extern "x86-interrupt" fn $name( frame: &InterruptFrame
                                       , error_code: usize) {
           exception_inner! ($title, "Fault", $source, frame, error_code);
           loop {}
       }
       $i.$name = Gate::from($name as ErrorCodeHandler);
       exceptions! { @impl $i, $($tail)* };
   };
     ( @impl $i:expr, trap: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {
         #[doc=$title]
         extern "x86-interrupt" fn $name(frame: &InterruptFrame) {
             exception_inner! ($title, "Trap", $source, frame);
         }
         $i.$name = Gate::from($name as InterruptHandler);
         $i.$name.set_trap();
         exceptions! { @impl $i, $($tail)* };
     };
      ( @impl $i:expr, ) => {};

}

lazy_static! {
    static ref IDT: Idt = {
        let mut idt = Idt::new();
        use cpu::interrupts::*;

        // TODO: log each handler as it's added to the IDT? that way we can
        //       trace faults occurring during IDT population (if any)
        //          - eliza, 5/22/2017
        exceptions! { idt: idt,
            fault: divide_by_zero, "Divide by Zero Error",
                   "DIV or IDIV instruction",
            fault: nmi, "Non-Maskable Interrupt",
                  "Non-maskable external interrupt",
            trap: overflow, "Overflow", "INTO instruction",
            fault: bound_exceeded, "BOUND range exceeded",
                  "BOUND instruction",
            fault: undefined_opcode, "Undefined Opcode",
                   "UD2 instruction or reserved opcode",
            fault: device_not_available, "Device Not Available"
                 , "Floating-point or WAIT/FWAIT instruction \
                    (no math coprocessor)",
            fault (code): double_fault, "Double Fault"
                 , "Any instruction that can generate an exception, a NMI, or \
                    an INTR",
            fault (code): invalid_tss, "Invalid TSS"
                 , "Task switch or TSS access",
            fault (code): segment_not_present, "Segment Not Present"
                 , "Loading segment registers or accessing \
                    system segments",
            fault (code): general_protection_fault, "General Protection Fault"
                 , "Any memory reference or other protection checks",
            fault (code): stack_segment_fault, "Stack Segment Fault"
                 , "Stack operations and SS register loads",
            fault: floating_point_error
                 , "x87 FPU Floating-Point Error (Math Fault)"
                 , "x87 FPU floating-point or WAIT/FWAIT instruction",
            fault: machine_check, "Machine Check"
                 , "Model-dependent (probably hardware!)",
            fault (code): alignment_check, "Alignment Check"
                 , "Any data reference in memory",
            fault: simd_fp_exception, "SIMD Floating-Point Exception"
                 , "SSE/SSE2/SSE3 floating-point instructions",
        };

        idt.breakpoint = Gate::from(breakpoint as InterruptHandler);
        idt.page_fault = Gate::from(page_fault as ErrorCodeHandler);

        for vector in idt.interrupts.iter_mut() {
            *vector = Gate::from(empty_handler as InterruptHandler);
        }

        idt[0x20] = Gate::from(timer as InterruptHandler);
        idt[0x21] = Gate::from(keyboard as InterruptHandler);
        idt[0xff] = Gate::from(test as InterruptHandler);

        kinfoln!( dots: " . . ", target: "Adding interrupt handlers to IDT"
                , "[ OKAY ]");
        idt
    };
}

#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn keyboard(_frame: &InterruptFrame) {
    use io::keyboard;

    // println!("keyboard happened");
    if let Some(input) = keyboard::read_char() {
        if input == '\r' {
            println!("");
        } else {
            print!("{}", input);
        }
    }
   // send the PICs the end interrupt signal
   unsafe {
       pics::end_pic_interrupt(0x21);
   }
}

#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn breakpoint(frame: &InterruptFrame) {
    println!("Breakpoint! Frame: {:#?}", frame);
   // send the PICs the end interrupt signal
   unsafe {
       pics::end_pic_interrupt(0x03);
   }
}

/// Empty dummy handler for undefined interrupts.
#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn empty_handler(_frame: &InterruptFrame) {
    // TODO: it would be nice to know *which vector* the dummy interrupt
    //      fired on, for debugging purposes...
    //          - eliza, 05/25/2017
    debug!("an empty interrupt fired!")
}
<|endoftext|>


<commit_before>use bot::BotEnv;
use commands::*;
use listeners::*;

use lalafell::listeners::CommandListener;

use serenity::prelude::RwLock;
use serenity::model::prelude::*;
use serenity::client::{EventHandler, Context};
use serenity::client::bridge::gateway::event::ShardStageUpdateEvent;

use serde_json::Value;

use std::sync::Arc;
use std::collections::HashMap;

pub struct Handler {
  listeners: Vec<Box<EventHandler + Send + Sync>>
}

impl Handler {
  pub fn new(env: &Arc<BotEnv>) -> Self {
    let listeners: Vec<Box<EventHandler + Send + Sync>> = vec![
      box command_listener(env),
      box GuildsExt,
      box ReactionAuthorize,
      box Timeouts,
      box PollTagger,
      box AutoReplyListener::default(),
      box TemporaryRolesListener,
      box PartyFinder::default(),
      box Music,
      box RandomPresenceListener,
      box Log::default()
    ];
    Handler { listeners }
  }
}

macro_rules! handler {
  ($name:ident, $($param:ident: $kind:ty),+) => {
    fn $name(&self, $($param: $kind),+) {
      for listener in &self.listeners {
        listener.$name($($param.clone()),+);
      }
    }
  }
}

impl EventHandler for Handler {
  handler!(cached, param1: Context, param2: Vec < GuildId >);
  handler!(category_create, param1: Context, param2: Arc < RwLock < ChannelCategory > >);
  handler!(category_delete, param1: Context, param2: Arc < RwLock < ChannelCategory > >);
  handler!(channel_create, param1: Context, param2: Arc < RwLock < GuildChannel > >);
  handler!(channel_delete, param1: Context, param2: Arc < RwLock < GuildChannel > >);
  handler!(channel_pins_update, param1: Context, param2: ChannelPinsUpdateEvent);
  handler!(channel_recipient_addition, param1: Context, param2: ChannelId, param3: User);
  handler!(channel_recipient_removal, param1: Context, param2: ChannelId, param3: User);
  handler!(channel_update, param1: Context, param2: Option < Channel >, param3: Channel);
  handler!(guild_ban_addition, param1: Context, param2: GuildId, param3: User);
  handler!(guild_ban_removal, param1: Context, param2: GuildId, param3: User);
  handler!(guild_create, param1: Context, param2: Guild, param3: bool);
  handler!(guild_delete, param1: Context, param2: PartialGuild, param3: Option < Arc < RwLock < Guild > > >);
  handler!(guild_emojis_update, param1: Context, param2: GuildId, param3: HashMap < EmojiId , Emoji >);
  handler!(guild_integrations_update, param1: Context, param2: GuildId);
  handler!(guild_member_addition, param1: Context, param2: GuildId, param3: Member);
  handler!(guild_member_removal, param1: Context, param2: GuildId, param3: User, param4: Option < Member >);
  handler!(guild_member_update, param1: Context, param2: Option < Member >, param3: Member);
  handler!(guild_members_chunk, param1: Context, param2: GuildId, param3: HashMap < UserId , Member >);
  handler!(guild_role_create, param1: Context, param2: GuildId, param3: Role);
  handler!(guild_role_delete, param1: Context, param2: GuildId, param3: RoleId, param4: Option < Role >);
  handler!(guild_role_update, param1: Context, param2: GuildId, param3: Option < Role >, param4: Role);
  handler!(guild_unavailable, param1: Context, param2: GuildId);
  handler!(guild_update, param1: Context, param2: Option < Arc < RwLock < Guild > > >, param3: PartialGuild);
  handler!(message_delete_bulk, param1: Context, param2: ChannelId, param3: Vec < MessageId >);
  handler!(message_delete, param1: Context, param2: ChannelId, param3: MessageId);
  handler!(message_update, param1: Context, param2: MessageUpdateEvent);
  handler!(message, param1: Context, param2: Message);
  handler!(presence_replace, param1: Context, param2: Vec < Presence >);
  handler!(presence_update, param1: Context, param2: PresenceUpdateEvent);
  handler!(private_channel_create, param1: Context, param2: Arc < RwLock < PrivateChannel > >);
  handler!(reaction_add, param1: Context, param2: Reaction);
  handler!(reaction_remove_all, param1: Context, param2: ChannelId, param3: MessageId);
  handler!(reaction_remove, param1: Context, param2: Reaction);
  handler!(ready, param1: Context, param2: Ready);
  handler!(resume, param1: Context, param2: ResumedEvent);
  handler!(shard_stage_update, param1: Context, param2: ShardStageUpdateEvent);
  handler!(typing_start, param1: Context, param2: TypingStartEvent);
  handler!(unknown, param1: Context, param2: String, param3: Value);
  handler!(user_update, param1: Context, param2: CurrentUser, param3: CurrentUser);
  handler!(voice_server_update, param1: Context, param2: VoiceServerUpdateEvent);
  handler!(voice_state_update, param1: Context, param2: Option < GuildId >, param3: VoiceState);
  handler!(webhook_update, param1: Context, param2: GuildId, param3: ChannelId);
}

macro_rules! command_listener {
  (env => $env:expr, $($($alias:expr),+ => $name:ident),+) => {{
    let mut command_listener = CommandListener::new("!");
    $(
      command_listener.add_command(&[$($alias),*], box $name::new(Arc::clone($env)));
    )*
    command_listener
  }}
}

fn command_listener<'a>(env: &Arc<BotEnv>) -> CommandListener<'a> {
  command_listener! {
    env => env,
    "archive" => ArchiveCommand,
    "autotag" => AutoTagCommand,
    "blob" => BlobCommand,
    "bot" => ActualBotCommand,
    "configure", "config" => ConfigureCommand,
    "ephemeralmessage", "ephemeral" => EphemeralMessageCommand,
    "fflogs" => FfLogsCommand,
    "imagedump", "dump" => ImageDumpCommand,
    "mention" => MentionCommand,
    "music" => MusicCommand,
    "partyfinder", "pf" => PartyFinderCommand,
    "ping" => PingCommand,
    "poll" => PollCommand,
    "pollresults" => PollResultsCommand,
    "queuetag" => QueueTagCommand,
    "race" => RaceCommand,
    "randomreaction", "reaction" => RandomReactionCommand,
    "referencecount" => ReferenceCountCommand,
    "reload", "reloadconfig" => ReloadConfigCommand,
    "search" => SearchCommand,
    "tag" => TagCommand,
    "temporaryrole", "temprole" => TemporaryRoleCommand,
    "timeout" => TimeoutCommand,
    "untimeout" => UntimeoutCommand,
    "updatetag" => UpdateTagCommand,
    "updatetags" => UpdateTagsCommand,
    "verify" => VerifyCommand,
    "version" => VersionCommand,
    "viewtag" => ViewTagCommand
  }
}
<commit_msg>refactor: remove unfinished pf command for release<commit_after>use bot::BotEnv;
use commands::*;
use listeners::*;

use lalafell::listeners::CommandListener;

use serenity::prelude::RwLock;
use serenity::model::prelude::*;
use serenity::client::{EventHandler, Context};
use serenity::client::bridge::gateway::event::ShardStageUpdateEvent;

use serde_json::Value;

use std::sync::Arc;
use std::collections::HashMap;

pub struct Handler {
  listeners: Vec<Box<EventHandler + Send + Sync>>
}

impl Handler {
  pub fn new(env: &Arc<BotEnv>) -> Self {
    let listeners: Vec<Box<EventHandler + Send + Sync>> = vec![
      box command_listener(env),
      box GuildsExt,
      box ReactionAuthorize,
      box Timeouts,
      box PollTagger,
      box AutoReplyListener::default(),
      box TemporaryRolesListener,
      box PartyFinder::default(),
      box Music,
      box RandomPresenceListener,
      box Log::default()
    ];
    Handler { listeners }
  }
}

macro_rules! handler {
  ($name:ident, $($param:ident: $kind:ty),+) => {
    fn $name(&self, $($param: $kind),+) {
      for listener in &self.listeners {
        listener.$name($($param.clone()),+);
      }
    }
  }
}

impl EventHandler for Handler {
  handler!(cached, param1: Context, param2: Vec < GuildId >);
  handler!(category_create, param1: Context, param2: Arc < RwLock < ChannelCategory > >);
  handler!(category_delete, param1: Context, param2: Arc < RwLock < ChannelCategory > >);
  handler!(channel_create, param1: Context, param2: Arc < RwLock < GuildChannel > >);
  handler!(channel_delete, param1: Context, param2: Arc < RwLock < GuildChannel > >);
  handler!(channel_pins_update, param1: Context, param2: ChannelPinsUpdateEvent);
  handler!(channel_recipient_addition, param1: Context, param2: ChannelId, param3: User);
  handler!(channel_recipient_removal, param1: Context, param2: ChannelId, param3: User);
  handler!(channel_update, param1: Context, param2: Option < Channel >, param3: Channel);
  handler!(guild_ban_addition, param1: Context, param2: GuildId, param3: User);
  handler!(guild_ban_removal, param1: Context, param2: GuildId, param3: User);
  handler!(guild_create, param1: Context, param2: Guild, param3: bool);
  handler!(guild_delete, param1: Context, param2: PartialGuild, param3: Option < Arc < RwLock < Guild > > >);
  handler!(guild_emojis_update, param1: Context, param2: GuildId, param3: HashMap < EmojiId , Emoji >);
  handler!(guild_integrations_update, param1: Context, param2: GuildId);
  handler!(guild_member_addition, param1: Context, param2: GuildId, param3: Member);
  handler!(guild_member_removal, param1: Context, param2: GuildId, param3: User, param4: Option < Member >);
  handler!(guild_member_update, param1: Context, param2: Option < Member >, param3: Member);
  handler!(guild_members_chunk, param1: Context, param2: GuildId, param3: HashMap < UserId , Member >);
  handler!(guild_role_create, param1: Context, param2: GuildId, param3: Role);
  handler!(guild_role_delete, param1: Context, param2: GuildId, param3: RoleId, param4: Option < Role >);
  handler!(guild_role_update, param1: Context, param2: GuildId, param3: Option < Role >, param4: Role);
  handler!(guild_unavailable, param1: Context, param2: GuildId);
  handler!(guild_update, param1: Context, param2: Option < Arc < RwLock < Guild > > >, param3: PartialGuild);
  handler!(message_delete_bulk, param1: Context, param2: ChannelId, param3: Vec < MessageId >);
  handler!(message_delete, param1: Context, param2: ChannelId, param3: MessageId);
  handler!(message_update, param1: Context, param2: MessageUpdateEvent);
  handler!(message, param1: Context, param2: Message);
  handler!(presence_replace, param1: Context, param2: Vec < Presence >);
  handler!(presence_update, param1: Context, param2: PresenceUpdateEvent);
  handler!(private_channel_create, param1: Context, param2: Arc < RwLock < PrivateChannel > >);
  handler!(reaction_add, param1: Context, param2: Reaction);
  handler!(reaction_remove_all, param1: Context, param2: ChannelId, param3: MessageId);
  handler!(reaction_remove, param1: Context, param2: Reaction);
  handler!(ready, param1: Context, param2: Ready);
  handler!(resume, param1: Context, param2: ResumedEvent);
  handler!(shard_stage_update, param1: Context, param2: ShardStageUpdateEvent);
  handler!(typing_start, param1: Context, param2: TypingStartEvent);
  handler!(unknown, param1: Context, param2: String, param3: Value);
  handler!(user_update, param1: Context, param2: CurrentUser, param3: CurrentUser);
  handler!(voice_server_update, param1: Context, param2: VoiceServerUpdateEvent);
  handler!(voice_state_update, param1: Context, param2: Option < GuildId >, param3: VoiceState);
  handler!(webhook_update, param1: Context, param2: GuildId, param3: ChannelId);
}

macro_rules! command_listener {
  (env => $env:expr, $($($alias:expr),+ => $name:ident),+) => {{
    let mut command_listener = CommandListener::new("!");
    $(
      command_listener.add_command(&[$($alias),*], box $name::new(Arc::clone($env)));
    )*
    command_listener
  }}
}

fn command_listener<'a>(env: &Arc<BotEnv>) -> CommandListener<'a> {
  command_listener! {
    env => env,
    "archive" => ArchiveCommand,
    "autotag" => AutoTagCommand,
    "blob" => BlobCommand,
    "bot" => ActualBotCommand,
    "configure", "config" => ConfigureCommand,
    "ephemeralmessage", "ephemeral" => EphemeralMessageCommand,
    "fflogs" => FfLogsCommand,
    "imagedump", "dump" => ImageDumpCommand,
    "mention" => MentionCommand,
    "music" => MusicCommand,
    // "partyfinder", "pf" => PartyFinderCommand,
    "ping" => PingCommand,
    "poll" => PollCommand,
    "pollresults" => PollResultsCommand,
    "queuetag" => QueueTagCommand,
    "race" => RaceCommand,
    "randomreaction", "reaction" => RandomReactionCommand,
    "referencecount" => ReferenceCountCommand,
    "reload", "reloadconfig" => ReloadConfigCommand,
    "search" => SearchCommand,
    "tag" => TagCommand,
    "temporaryrole", "temprole" => TemporaryRoleCommand,
    "timeout" => TimeoutCommand,
    "untimeout" => UntimeoutCommand,
    "updatetag" => UpdateTagCommand,
    "updatetags" => UpdateTagsCommand,
    "verify" => VerifyCommand,
    "version" => VersionCommand,
    "viewtag" => ViewTagCommand
  }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate differential_evolution;
extern crate rand;

#[cfg(test)]
mod tests {
    use test::Bencher;
    use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, ChaChaRng};
    use rand::{OsRng, weak_rng, thread_rng};
    use differential_evolution::{Population, Settings};

    fn setup<F: Fn(&[f32]) -> f32, R: Rng>(dim: usize,
                                                 cost_fn: F,
                                                 rng: R)
                                                 -> Population<F, R> {
        let s = Settings::min_max_rng(vec![(-100.0, 100.0); dim], cost_fn, rng);
        Population::from_settings(s)
    }

    #[bench]
    fn bench_square_fitness_opt(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_thread_rng(b: &mut Bencher) {
        let mut pop = setup(5, |_| 1.234, thread_rng());
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_xor_shift(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_chacha(b: &mut Bencher) {
        let rng: ChaChaRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_isaac(b: &mut Bencher) {
        let rng: IsaacRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_isaac64(b: &mut Bencher) {
        let rng: Isaac64Rng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_std(b: &mut Bencher) {
        let rng: StdRng = StdRng::new().unwrap();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_osrng(b: &mut Bencher) {
        let rng: OsRng = OsRng::new().unwrap();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_weak_rng(b: &mut Bencher) {
        let rng = weak_rng();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }
}
<commit_msg>copyright<commit_after>// Copyright 2016 Martin Ankerl.
//
// 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.

#![feature(test)]

extern crate test;
extern crate differential_evolution;
extern crate rand;

#[cfg(test)]
mod tests {
    use test::Bencher;
    use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, ChaChaRng};
    use rand::{OsRng, weak_rng, thread_rng};
    use differential_evolution::{Population, Settings};

    fn setup<F: Fn(&[f32]) -> f32, R: Rng>(dim: usize,
                                                 cost_fn: F,
                                                 rng: R)
                                                 -> Population<F, R> {
        let s = Settings::min_max_rng(vec![(-100.0, 100.0); dim], cost_fn, rng);
        Population::from_settings(s)
    }

    #[bench]
    fn bench_square_fitness_opt(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_thread_rng(b: &mut Bencher) {
        let mut pop = setup(5, |_| 1.234, thread_rng());
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_xor_shift(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_chacha(b: &mut Bencher) {
        let rng: ChaChaRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_isaac(b: &mut Bencher) {
        let rng: IsaacRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_isaac64(b: &mut Bencher) {
        let rng: Isaac64Rng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_std(b: &mut Bencher) {
        let rng: StdRng = StdRng::new().unwrap();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_osrng(b: &mut Bencher) {
        let rng: OsRng = OsRng::new().unwrap();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }

    #[bench]
    fn rand_weak_rng(b: &mut Bencher) {
        let rng = weak_rng();
        let mut pop = setup(5, |_| 1.234, rng);
        b.iter(|| pop.next());
    }
}
<|endoftext|>


<commit_before>use extra::url::Url;
use method::Method;
use std::rt::io::{Reader, Writer};
use std::rt::io::net::get_host_addresses;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::rt::io::net::tcp::TcpStream;
use buffer::BufferedStream;
use headers::request::HeaderCollection;
use headers::host::Host;

use client::response::ResponseReader;

/*impl ResponseReader {
    {
        let mut buf = [0u8, ..2000];
        match stream.read(buf) {
            None => fail!("Read error :-("),  // conditions for error interception, again
            Some(bytes_read) => {
                println(str::from_bytes(buf.slice_to(bytes_read)));
            }
        }

        match response {
            Some(response) => Ok(response),
            None => Err(self),
        }
    }
}*/

pub struct RequestWriter<S> {
    // The place to write to (typically a TCP stream, rt::io::net::tcp::TcpStream)
    priv stream: Option<BufferedStream<S>>,
    priv headers_written: bool,

    /// The originating IP address of the request.
    remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Host,  // Now headers.host

    /// The headers sent with the request.
    headers: ~HeaderCollection,

    /// The HTTP method for the request.
    method: Method,

    /// The URL being requested.
    url: Url,
}

/// Low-level HTTP request writing support
///
/// Moderately hacky, and due to current limitations in the TcpStream arrangement reading cannot
/// take place until writing is completed.
///
/// At present, this only supports making one request per connection.
impl<S: Reader + Writer> RequestWriter<S> {
    /// Create a `RequestWriter` writing to the specified location
    pub fn new(method: Method, url: Url) -> RequestWriter<S> {
        let host = match url.port {
            None => Host {
                name: url.host.to_owned(),
                port: None,
            },
            Some(ref p) => Host {
                name: url.host.to_owned(),
                port: Some(FromStr::from_str(*p).expect("You didn’t aught to give a bad port!")),
                // TODO: fix extra::url to use u16 rather than ~str
            },
        };

        let remote_addr = url_to_socket_addr(&url);
        info!("using ip address %s for %s", remote_addr.to_str(), url.host);

        fn url_to_socket_addr(url: &Url) -> SocketAddr {
            // Just grab the first IPv4 address
            let addrs = get_host_addresses(url.host);
            // TODO: Error handling
            let addrs = addrs.unwrap();
            let addr = do addrs.move_iter().find |&a| {
                match a {
                    Ipv4Addr(*) => true,
                    _ => false
                }
            };

            // TODO: Error handling
            let addr = addr.unwrap();

            let port = url.port.clone().unwrap_or_default(~"80");
            let port = FromStr::from_str(port);
            // TODO: Error handling
            let port = port.unwrap();

            SocketAddr {
                ip: addr,
                port: port
            }
        }

        let mut request = RequestWriter {
            stream: None,
            headers_written: false,
            remote_addr: Some(remote_addr),
            headers: ~HeaderCollection::new(),
            method: method,
            url: url,
        };
        request.headers.host = Some(host);
        request
    }
}

impl RequestWriter<TcpStream> {

    /// Connect to the remote host if not already connected.
    pub fn try_connect(&mut self) {
        if self.stream.is_none() {
            self.connect();
        }
    }

    /// Connect to the remote host; fails if already connected.
    /// Returns ``true`` upon success and ``false`` upon failure (also use conditions).
    pub fn connect(&mut self) -> bool {
        if !self.stream.is_none() {
            fail!("I don't think you meant to call connect() twice, you know.");
        }

        self.stream = match self.remote_addr {
            Some(addr) => match TcpStream::connect(addr) {
                Some(stream) => Some(BufferedStream::new(stream, false)),
                None => return false,
            },
            None => fail!("connect() called before remote_addr was set"),
        };
        true
    }

    /// Write the Request-Line and headers of the response, if we have not already done so.
    pub fn try_write_headers(&mut self) {
        if !self.headers_written {
            self.write_headers();
        }
    }

    /// Write the Status-Line and headers of the response, in preparation for writing the body.
    ///
    /// If the headers have already been written, this will fail. See also `try_write_headers`.
    pub fn write_headers(&mut self) {
        // This marks the beginning of the response (RFC2616 §5)
        if self.headers_written {
            fail!("RequestWriter.write_headers() called, but headers already written");
        }
        if self.stream.is_none() && !self.connect() {
            fail!("Uh oh, failed to connect!"); // TODO: condition
        }

        // Write the Request-Line (RFC2616 §5.1)
        // TODO: get to the point where we can say HTTP/1.1 with good conscience
        // XXX: Rust's current lack of statement-duration lifetime handling prevents this from being
        // one statement ("error: borrowed value does not live long enough")
        // TODO: don't send the entire URL; just url.{path, query}
        let s = fmt!("%s %s HTTP/1.0\r\n", self.method.to_str(), self.url.to_str());
        self.stream.write(s.as_bytes());

        self.headers.write_all(&mut self.stream);
        self.headers_written = true;
    }

    // FIXME: ~self rather than self to work around a Rust bug in by-val self at present leading to
    // a segfault on calling construct().
    pub fn read_response(~self) -> Result<ResponseReader<TcpStream>, ~RequestWriter<TcpStream>> {
        let mut mut_self = self;
        mut_self.try_write_headers();
        mut_self.flush();
        match mut_self.stream.take() {
            Some(stream) => ResponseReader::construct(stream, mut_self),
            None => Err(mut_self), // TODO: raise condition
        }
    }
}

impl Writer for RequestWriter<TcpStream> {
    fn write(&mut self, buf: &[u8]) {
        if (!self.headers_written) {
            self.write_headers();
        }
        self.stream.write(buf);
    }

    fn flush(&mut self) {
        self.stream.flush();
    }
}
<commit_msg>updated unwrap_or_default syntax<commit_after>use extra::url::Url;
use method::Method;
use std::rt::io::{Reader, Writer};
use std::rt::io::net::get_host_addresses;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::rt::io::net::tcp::TcpStream;
use buffer::BufferedStream;
use headers::request::HeaderCollection;
use headers::host::Host;

use client::response::ResponseReader;

/*impl ResponseReader {
    {
        let mut buf = [0u8, ..2000];
        match stream.read(buf) {
            None => fail!("Read error :-("),  // conditions for error interception, again
            Some(bytes_read) => {
                println(str::from_bytes(buf.slice_to(bytes_read)));
            }
        }

        match response {
            Some(response) => Ok(response),
            None => Err(self),
        }
    }
}*/

pub struct RequestWriter<S> {
    // The place to write to (typically a TCP stream, rt::io::net::tcp::TcpStream)
    priv stream: Option<BufferedStream<S>>,
    priv headers_written: bool,

    /// The originating IP address of the request.
    remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Host,  // Now headers.host

    /// The headers sent with the request.
    headers: ~HeaderCollection,

    /// The HTTP method for the request.
    method: Method,

    /// The URL being requested.
    url: Url,
}

/// Low-level HTTP request writing support
///
/// Moderately hacky, and due to current limitations in the TcpStream arrangement reading cannot
/// take place until writing is completed.
///
/// At present, this only supports making one request per connection.
impl<S: Reader + Writer> RequestWriter<S> {
    /// Create a `RequestWriter` writing to the specified location
    pub fn new(method: Method, url: Url) -> RequestWriter<S> {
        let host = match url.port {
            None => Host {
                name: url.host.to_owned(),
                port: None,
            },
            Some(ref p) => Host {
                name: url.host.to_owned(),
                port: Some(FromStr::from_str(*p).expect("You didn’t aught to give a bad port!")),
                // TODO: fix extra::url to use u16 rather than ~str
            },
        };

        let remote_addr = url_to_socket_addr(&url);
        info!("using ip address %s for %s", remote_addr.to_str(), url.host);

        fn url_to_socket_addr(url: &Url) -> SocketAddr {
            // Just grab the first IPv4 address
            let addrs = get_host_addresses(url.host);
            // TODO: Error handling
            let addrs = addrs.unwrap();
            let addr = do addrs.move_iter().find |&a| {
                match a {
                    Ipv4Addr(*) => true,
                    _ => false
                }
            };

            // TODO: Error handling
            let addr = addr.unwrap();

            let port = url.port.clone().unwrap_or(~"80");
            let port = FromStr::from_str(port);
            // TODO: Error handling
            let port = port.unwrap();

            SocketAddr {
                ip: addr,
                port: port
            }
        }

        let mut request = RequestWriter {
            stream: None,
            headers_written: false,
            remote_addr: Some(remote_addr),
            headers: ~HeaderCollection::new(),
            method: method,
            url: url,
        };
        request.headers.host = Some(host);
        request
    }
}

impl RequestWriter<TcpStream> {

    /// Connect to the remote host if not already connected.
    pub fn try_connect(&mut self) {
        if self.stream.is_none() {
            self.connect();
        }
    }

    /// Connect to the remote host; fails if already connected.
    /// Returns ``true`` upon success and ``false`` upon failure (also use conditions).
    pub fn connect(&mut self) -> bool {
        if !self.stream.is_none() {
            fail!("I don't think you meant to call connect() twice, you know.");
        }

        self.stream = match self.remote_addr {
            Some(addr) => match TcpStream::connect(addr) {
                Some(stream) => Some(BufferedStream::new(stream, false)),
                None => return false,
            },
            None => fail!("connect() called before remote_addr was set"),
        };
        true
    }

    /// Write the Request-Line and headers of the response, if we have not already done so.
    pub fn try_write_headers(&mut self) {
        if !self.headers_written {
            self.write_headers();
        }
    }

    /// Write the Status-Line and headers of the response, in preparation for writing the body.
    ///
    /// If the headers have already been written, this will fail. See also `try_write_headers`.
    pub fn write_headers(&mut self) {
        // This marks the beginning of the response (RFC2616 §5)
        if self.headers_written {
            fail!("RequestWriter.write_headers() called, but headers already written");
        }
        if self.stream.is_none() && !self.connect() {
            fail!("Uh oh, failed to connect!"); // TODO: condition
        }

        // Write the Request-Line (RFC2616 §5.1)
        // TODO: get to the point where we can say HTTP/1.1 with good conscience
        // XXX: Rust's current lack of statement-duration lifetime handling prevents this from being
        // one statement ("error: borrowed value does not live long enough")
        // TODO: don't send the entire URL; just url.{path, query}
        let s = fmt!("%s %s HTTP/1.0\r\n", self.method.to_str(), self.url.to_str());
        self.stream.write(s.as_bytes());

        self.headers.write_all(&mut self.stream);
        self.headers_written = true;
    }

    // FIXME: ~self rather than self to work around a Rust bug in by-val self at present leading to
    // a segfault on calling construct().
    pub fn read_response(~self) -> Result<ResponseReader<TcpStream>, ~RequestWriter<TcpStream>> {
        let mut mut_self = self;
        mut_self.try_write_headers();
        mut_self.flush();
        match mut_self.stream.take() {
            Some(stream) => ResponseReader::construct(stream, mut_self),
            None => Err(mut_self), // TODO: raise condition
        }
    }
}

impl Writer for RequestWriter<TcpStream> {
    fn write(&mut self, buf: &[u8]) {
        if (!self.headers_written) {
            self.write_headers();
        }
        self.stream.write(buf);
    }

    fn flush(&mut self) {
        self.stream.flush();
    }
}
<|endoftext|>


<commit_before>//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy.

use crate::hir::{def::Def, HirId, Path, QPath, Ty, TyKind};
use crate::lint::{
    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
};
use errors::Applicability;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::Ident;

declare_lint! {
    pub DEFAULT_HASH_TYPES,
    Allow,
    "forbid HashMap and HashSet and suggest the FxHash* variants"
}

pub struct DefaultHashTypes {
    map: FxHashMap<String, String>,
}

impl DefaultHashTypes {
    pub fn new() -> Self {
        let mut map = FxHashMap::default();
        map.insert("HashMap".to_string(), "FxHashMap".to_string());
        map.insert("HashSet".to_string(), "FxHashSet".to_string());
        Self { map }
    }
}

impl LintPass for DefaultHashTypes {
    fn get_lints(&self) -> LintArray {
        lint_array!(DEFAULT_HASH_TYPES)
    }

    fn name(&self) -> &'static str {
        "DefaultHashTypes"
    }
}

impl EarlyLintPass for DefaultHashTypes {
    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
        let ident_string = ident.to_string();
        if let Some(replace) = self.map.get(&ident_string) {
            let msg = format!(
                "Prefer {} over {}, it has better performance",
                replace, ident_string
            );
            let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
            db.span_suggestion(
                ident.span,
                "use",
                replace.to_string(),
                Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
            );
            db.note(&format!(
                "a `use rustc_data_structures::fx::{}` may be necessary",
                replace
            ))
            .emit();
        }
    }
}

declare_lint! {
    pub USAGE_OF_TY_TYKIND,
    Allow,
    "Usage of `ty::TyKind` outside of the `ty::sty` module"
}

pub struct TyKindUsage;

impl LintPass for TyKindUsage {
    fn get_lints(&self) -> LintArray {
        lint_array!(USAGE_OF_TY_TYKIND)
    }

    fn name(&self) -> &'static str {
        "TyKindUsage"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
    fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
        let segments_iter = path.segments.iter().rev().skip(1).rev();

        if let Some(last) = segments_iter.clone().last() {
            if last.ident.as_str() == "TyKind" {
                let path = Path {
                    span: path.span.with_hi(last.ident.span.hi()),
                    def: path.def,
                    segments: segments_iter.cloned().collect(),
                };

                match last.def {
                    Some(Def::Err) => (),
                    Some(def)
                        if def
                            .def_id()
                            .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"]) =>
                    {
                        cx.struct_span_lint(
                            USAGE_OF_TY_TYKIND,
                            path.span,
                            "usage of `ty::TyKind::<kind>`",
                        )
                        .span_suggestion(
                            path.span,
                            "try using ty::<kind> directly",
                            "ty".to_string(),
                            Applicability::MaybeIncorrect, // ty maybe needs an import
                        )
                        .emit();
                    }
                    _ => (),
                }
            }
        }
    }

    fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
        if let TyKind::Path(qpath) = &ty.node {
            if let QPath::Resolved(_, path) = qpath {
                if let Some(last) = path.segments.iter().last() {
                    if last.ident.as_str() == "TyKind" {
                        if let Some(def) = last.def {
                            if def
                                .def_id()
                                .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
                            {
                                cx.struct_span_lint(
                                    USAGE_OF_TY_TYKIND,
                                    path.span,
                                    "usage of `ty::TyKind`",
                                )
                                .help("try using `ty::Ty` instead")
                                .emit();
                            }
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Deduplicate code in TyKind lint<commit_after>//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy.

use crate::hir::{HirId, Path, PathSegment, QPath, Ty, TyKind};
use crate::lint::{
    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
};
use errors::Applicability;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::Ident;

declare_lint! {
    pub DEFAULT_HASH_TYPES,
    Allow,
    "forbid HashMap and HashSet and suggest the FxHash* variants"
}

pub struct DefaultHashTypes {
    map: FxHashMap<String, String>,
}

impl DefaultHashTypes {
    pub fn new() -> Self {
        let mut map = FxHashMap::default();
        map.insert("HashMap".to_string(), "FxHashMap".to_string());
        map.insert("HashSet".to_string(), "FxHashSet".to_string());
        Self { map }
    }
}

impl LintPass for DefaultHashTypes {
    fn get_lints(&self) -> LintArray {
        lint_array!(DEFAULT_HASH_TYPES)
    }

    fn name(&self) -> &'static str {
        "DefaultHashTypes"
    }
}

impl EarlyLintPass for DefaultHashTypes {
    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
        let ident_string = ident.to_string();
        if let Some(replace) = self.map.get(&ident_string) {
            let msg = format!(
                "Prefer {} over {}, it has better performance",
                replace, ident_string
            );
            let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
            db.span_suggestion(
                ident.span,
                "use",
                replace.to_string(),
                Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
            );
            db.note(&format!(
                "a `use rustc_data_structures::fx::{}` may be necessary",
                replace
            ))
            .emit();
        }
    }
}

declare_lint! {
    pub USAGE_OF_TY_TYKIND,
    Allow,
    "Usage of `ty::TyKind` outside of the `ty::sty` module"
}

pub struct TyKindUsage;

impl LintPass for TyKindUsage {
    fn get_lints(&self) -> LintArray {
        lint_array!(USAGE_OF_TY_TYKIND)
    }

    fn name(&self) -> &'static str {
        "TyKindUsage"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
    fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
        let segments = path.segments.iter().rev().skip(1).rev();

        if let Some(last) = segments.last() {
            let span = path.span.with_hi(last.ident.span.hi());
            if lint_ty_kind_usage(cx, last) {
                cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, "usage of `ty::TyKind::<kind>`")
                    .span_suggestion(
                        span,
                        "try using ty::<kind> directly",
                        "ty".to_string(),
                        Applicability::MaybeIncorrect, // ty maybe needs an import
                    )
                    .emit();
            }
        }
    }

    fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
        if let TyKind::Path(qpath) = &ty.node {
            if let QPath::Resolved(_, path) = qpath {
                if let Some(last) = path.segments.iter().last() {
                    if lint_ty_kind_usage(cx, last) {
                        cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, "usage of `ty::TyKind`")
                            .help("try using `ty::Ty` instead")
                            .emit();
                    }
                }
            }
        }
    }
}

fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
    if segment.ident.as_str() == "TyKind" {
        if let Some(def) = segment.def {
            if let Some(did) = def.opt_def_id() {
                return did.match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"]);
            }
        }
    }

    false
}
<|endoftext|>