<commit_before>use consumer::*;
use producer::*;
use std::rc::Rc;
use stream::*;

pub struct IterStream<I> {
    iterator: I,
}

pub struct IterStreamRef<I> {
    iterator: I,
}

pub struct IterStreamRefMut<I> {
    iterator: I,
}

impl<I, T> Stream<T> for IterStream<I>
    where I: Iterator<Item = T> + 'static
{
    fn consume<C: Consumer<T>>(self, mut consumer: C) {
        let producer = Rc::new(Producer::new());

        consumer.init(producer.clone());

        if producer.is_closed() {
            return;
        }

        for i in self.iterator {
            consumer.emit(i);
            if producer.is_closed() {
                return;
            }
        }
    }
}

impl<I, T> StreamRef<T> for IterStreamRef<I>
    where I: Iterator<Item = T> + 'static
{
    fn consume<C: ConsumerRef<T>>(self, mut consumer: C) {
        let producer = Rc::new(Producer::new());

        consumer.init(producer.clone());

        if producer.is_closed() {
            return;
        }

        for i in self.iterator {
            consumer.emit(&i);
            if producer.is_closed() {
                return;
            }
        }
    }
}

impl<I, T> StreamRefMut<T> for IterStreamRefMut<I>
    where I: Iterator<Item = T> + 'static
{
    fn consume<C: ConsumerRefMut<T>>(self, mut consumer: C) {
        let producer = Rc::new(Producer::new());

        consumer.init(producer.clone());

        if producer.is_closed() {
            return;
        }

        for mut i in self.iterator {
            consumer.emit(&mut i);
            if producer.is_closed() {
                return;
            }
        }
    }
}

pub trait ToStream: Iterator {
    /// Convert an iterator to a `Stream`.
    ///
    /// # Examples
    ///
    /// ```
    /// use asyncplify::*;
    ///
    /// let mut sum = 0;
    ///
    /// (0..5)
    ///     .to_stream()
    ///     .tap(|v| sum += *v)
    ///     .subscribe();
    ///
    /// assert!(sum == 10, "sum (0 + 1 + 2 + 3 + 4) = {}", sum);
    /// ```
    fn to_stream(self) -> IterStream<Self>
        where Self: Sized
    {
        IterStream { iterator: self }
    }

    fn to_stream_ref(self) -> IterStreamRef<Self>
        where Self: Sized
    {
        IterStreamRef { iterator: self }
    }

    fn to_stream_ref_mut(self) -> IterStreamRefMut<Self>
        where Self: Sized
    {
        IterStreamRefMut { iterator: self }
    }
}

impl<I> ToStream for I where I: Iterator {}
<commit_msg>Simplification of the ToStream operator<commit_after>use consumer::*;
use producer::*;
use std::rc::Rc;
use stream::*;

/// Represent a stream on an iterator.
pub struct IterStream<I> {
    iterator: I,
}

impl<I, T> Stream<T> for IterStream<I>
    where I: Iterator<Item = T>
{
    fn consume<C: Consumer<T>>(self, mut consumer: C) {
        let producer = Rc::new(Producer::new());

        consumer.init(producer.clone());

        if producer.is_closed() {
            return;
        }

        for i in self.iterator {
            consumer.emit(i);
            if producer.is_closed() {
                return;
            }
        }
    }
}

/// Extend the Iterator trait with stream conversion operators
pub trait ToStream: Iterator {
    /// Convert an iterator to a `Stream`.
    ///
    /// # Examples
    ///
    /// ```
    /// use asyncplify::*;
    ///
    /// let vec = (0..5)
    ///     .to_stream()
    ///     .into_vec();
    ///
    /// assert!(vec == [0, 1, 2, 3, 4], "vec = {:?}", vec);
    /// ```
    fn to_stream(self) -> IterStream<Self>
        where Self: Sized
    {
        IterStream { iterator: self }
    }
}

impl<I> ToStream for I where I: Iterator {}
<|endoftext|>


<commit_before>// An Iterator adapter that walks through all the elements in the Iterator,
// converts them to Strings and joins them to one big String, seperated by
// some seperator string slice.
trait StringJoiner {
  fn join(&mut self, sep: &str) -> String;
}

// Implement it for all Iterators with Elements convertable into a String
impl<A: ToString, T: Iterator<A>> StringJoiner for T {
  fn join(&mut self, sep: &str) -> String {
    match self.next() {
      Some(elem) => {
        let mut output = elem.to_string();
        for elem in *self {
          output.push_str(sep);
          output.push_str(elem.to_string().as_slice());
        }
        output
      }
      None => String::new()
    }
  }
}

#[test]
fn test_join() {
  let many = vec![1u,2,3];
  let one  = vec![1u];
  let none: Vec<uint> = vec![];

  assert_eq!(many.iter().join(", ").as_slice(), "1, 2, 3");
  assert_eq!(one .iter().join(", ").as_slice(), "1");
  assert_eq!(none.iter().join(", ").as_slice(), "");
}
<commit_msg>ultra-trivial style fix ;)<commit_after>// An Iterator adapter that walks through all the elements in the Iterator,
// converts them to Strings and joins them to one big String, seperated by
// some seperator string slice.
trait StringJoiner {
  fn join(&mut self, sep: &str) -> String;
}

// Implement it for all Iterators with Elements convertable into a String
impl<A: ToString, T: Iterator<A>> StringJoiner for T {
  fn join(&mut self, sep: &str) -> String {
    match self.next() {
      Some(elem) => {
        let mut output = elem.to_string();
        for elem in *self {
          output.push_str(sep);
          output.push_str(elem.to_string().as_slice());
        }
        output
      }
      None => String::new()
    }
  }
}

#[test]
fn test_join() {
  let many = vec![1u,2,3];
  let  one = vec![1u];
  let none: Vec<uint> = vec![];

  assert_eq!(many.iter().join(", ").as_slice(), "1, 2, 3");
  assert_eq!(one .iter().join(", ").as_slice(), "1");
  assert_eq!(none.iter().join(", ").as_slice(), "");
}
<|endoftext|>


<commit_before>//! Defines the `MoveGenerator` trait.

use std::mem::uninitialized;
use std::cmp::max;
use uci::SetOption;
use board::*;
use moves::*;
use value::*;
use evaluator::Evaluator;
use utils::bitsets::*;
use utils::BoardGeometry;

/// A trait for move generators.
///
/// A `MoveGenerator` holds a chess position and can:
///
/// * Generate all legal moves, or a subset of all legal moves in the
///   current position.
///
/// * Perform static exchange evaluation for the generated moves.
///
/// * Play a selected move and take it back.
///
/// * Provide a static evaluator bound to the current position.
///
/// * Calculate Zobrist hashes.
///
/// **Important note:** `MoveGenerator` is unaware of repeating
/// positions and rule-50.
pub trait MoveGenerator: Sized + Send + Clone + SetOption {
    /// The type of static evaluator that the implementation works
    /// with.
    type Evaluator: Evaluator;

    /// Creates a new instance, consuming the supplied `Board`
    /// instance.
    ///
    /// Returns `None` if the position is illegal.
    fn from_board(board: Board) -> Option<Self>;

    /// Returns the Zobrist hash value for the underlying `Board`
    /// instance.
    ///
    /// Zobrist hashing is a technique to transform a board position
    /// into a number of a fixed length, with an equal distribution
    /// over all possible numbers, invented by Albert Zobrist. The key
    /// property of this method is that two similar positions generate
    /// entirely different hash numbers.
    ///
    /// **Important note:** This method will be relatively slow if the
    /// implementation calculates the hash value "from
    /// scratch". Inspect the implementation before using `hash` in
    /// time-critical paths. (See `do_move`.)
    fn hash(&self) -> u64;

    /// Returns a reference to the underlying `Board` instance.
    #[inline(always)]
    fn board(&self) -> &Board;

    /// Returns a bitboard with all pieces of color `us` that attack
    /// `square`.
    fn attacks_to(&self, us: Color, square: Square) -> Bitboard;

    /// Returns a bitboard with all enemy pieces that attack the king.
    ///
    /// **Important note:** The bitboard of checkers is calculated on
    /// the first call to `checkers`, and is stored in case another
    /// call is made before doing/undoing any moves. In that case
    /// `checkers` returns the saved bitboard instead of
    /// re-calculating it, thus saving time.
    fn checkers(&self) -> Bitboard;

    /// Returns a reference to a static evaluator bound to the current
    /// position.
    fn evaluator(&self) -> &Self::Evaluator;

    /// Generates all legal moves, possibly including some
    /// pseudo-legal moves too.
    ///
    /// The moves are added to `moves`. All generated moves with
    /// pieces other than the king will be legal. Some of the
    /// generated king's moves may be illegal because the destination
    /// square is under attack. This arrangement has two important
    /// advantages:
    ///
    /// * `do_move` can do its work without knowing the set of
    ///   checkers and pinned pieces, so there is no need to keep
    ///   those around.
    ///
    /// * A beta cut-off may make the verification that king's
    ///   destination square is not under attack unnecessary, thus
    ///   saving time.
    ///
    /// **Note:** A pseudo-legal move is a move that is otherwise
    /// legal, except it might leave the king in check.
    fn generate_all<T: AddMove>(&self, moves: &mut T);

    /// Generates moves for the quiescence search.
    ///
    /// The moves are added to `moves`. This method always generates a
    /// **subset** of the moves generated by `generate_all`:
    ///
    /// * If the king is in check, all legal moves are included.
    ///
    /// * Captures and pawn promotions to queen are always included.
    ///
    /// * If `generate_checks` is `true`, moves that give check are
    ///   included too. Discovered checks and checks given by castling
    ///   can be omitted for speed.
    fn generate_forcing<T: AddMove>(&self, generate_checks: bool, moves: &mut T);

    /// Checks if `move_digest` represents a pseudo-legal move.
    ///
    /// If a move `m` exists that would be generated by
    /// `generate_all` if called for the current position on the
    /// board, and for that move `m.digest() == move_digest`, this
    /// method will return `Some(m)`. Otherwise it will return
    /// `None`. This is useful when playing moves from the
    /// transposition table, without calling `generate_all`.
    fn try_move_digest(&self, move_digest: MoveDigest) -> Option<Move>;

    /// Returns a null move.
    ///
    /// "Null move" is a pseudo-move that changes only the side to
    /// move. It is sometimes useful to include a speculative null
    /// move in the search tree so as to achieve more aggressive
    /// pruning. Null moves are represented as king's moves for which
    /// the origin and destination squares are the same.
    fn null_move(&self) -> Move;

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and an `u64` value is returned, which should
    /// be XOR-ed with old board's hash value to obtain new board's
    /// hash value. If the move is illegal, `None` is returned without
    /// updating the board. The move passed to this method **must**
    /// have been generated by `generate_all`, `generate_forcing`,
    /// `try_move_digest`, or `null_move` methods for the current
    /// position on the board.
    ///
    /// The moves generated by the `null_move` method are
    /// exceptions. For them `do_move` will return `None` if and only
    /// if the king is in check.
    fn do_move(&mut self, m: Move) -> Option<u64>;

    /// Takes back last played move.
    ///
    /// The move passed to this method **must** be the last move passed
    /// to `do_move`.
    fn undo_move(&mut self, m: Move);

    /// Returns the likely evaluation change (material) to be lost or
    /// gained as a result of a given move.
    ///
    /// This method performs static exchange evaluation (SEE). It
    /// examines the consequence of a series of exchanges on the
    /// destination square after a given move. A positive returned
    /// value indicates a "winning" move. For example, "PxQ" will
    /// always be a win, since the pawn side can choose to stop the
    /// exchange after its pawn is recaptured, and still be ahead. SEE
    /// is just an evaluation calculated without actually trying moves
    /// on the board, and therefore the returned value might be
    /// incorrect.
    ///
    /// The move passed to this method must have been generated by
    /// `generate_all`, `generate_forcing`, `try_move_digest`, or
    /// `null_move` methods for the current position on the board.
    fn evaluate_move(&self, m: Move) -> Value {
        debug_assert!(m.played_piece() < PIECE_NONE);
        debug_assert!(m.captured_piece() <= PIECE_NONE);
        const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

        // This is the square on which all the action takes place.
        let exchange_square = m.dest_square();

        unsafe {
            let geometry = BoardGeometry::get();
            let behind_blocker: &[Bitboard; 64] = geometry.squares_behind_blocker
                                                          .get_unchecked(exchange_square);
            let piece_type: &[Bitboard; 6] = &self.board().pieces.piece_type;
            let color: &[Bitboard; 2] = &self.board().pieces.color;
            let straight_sliders = piece_type[QUEEN] | piece_type[ROOK];
            let diag_sliders = piece_type[QUEEN] | piece_type[BISHOP];

            // `may_xray` holds the set of pieces that may block attacks
            // from other pieces. We will consider adding new
            // attackers/defenders every time a piece from the `may_xray`
            // set makes a capture.
            //
            // TODO: This is probably not necessary if `bitscan_1bit`
            // is translated to 1 instruction. Otherwise, it probably
            // saves few CPU cycles.
            let may_xray = piece_type[PAWN] | straight_sliders | diag_sliders;

            // These variables will be updated on each capture:
            let mut us = self.board().to_move;
            let mut depth = 0;
            let mut piece;
            let mut orig_square_bb = 1 << m.orig_square();
            let mut attackers_and_defenders = self.attacks_to(WHITE, exchange_square) |
                                              self.attacks_to(BLACK, exchange_square);

            // The `gain` array will hold the total material gained at
            // each `depth`, from the viewpoint of the side that made the
            // last capture (`us`).
            let mut gain: [Value; 34] = uninitialized();
            gain[0] = if m.move_type() == MOVE_PROMOTION {
                piece = Move::piece_from_aux_data(m.aux_data());
                PIECE_VALUES[m.captured_piece()] + PIECE_VALUES[piece] - PIECE_VALUES[PAWN]
            } else {
                piece = m.played_piece();
                *PIECE_VALUES.get_unchecked(m.captured_piece())
            };

            // Examine the possible exchanges, fill the `gain` array.
            'exchange: while orig_square_bb != 0 {
                let current_gain = *gain.get_unchecked(depth);

                // Store a speculative value that will be used if the
                // captured piece happens to be defended.
                let speculative_gain: &mut Value = gain.get_unchecked_mut(depth + 1);
                *speculative_gain = *PIECE_VALUES.get_unchecked(piece) - current_gain;

                if max(-current_gain, *speculative_gain) < 0 {
                    // The side that made the last capture wins even if
                    // the captured piece happens to be defended. So, we
                    // stop here to save precious CPU cycles. Note that
                    // here we may happen to return an incorrect SEE
                    // value, but the sign will be correct, which is by
                    // far the most important information.
                    break;
                }

                // Register that capturing piece's origin square is now vacant.
                attackers_and_defenders &= !orig_square_bb;

                // Consider adding new attackers/defenders, now that
                // capturing piece's origin square is vacant.
                if orig_square_bb & may_xray != 0 {
                    let behind = self.board().occupied &
                                 *behind_blocker.get_unchecked(bitscan_1bit(orig_square_bb));
                    if behind & (straight_sliders | diag_sliders) != 0 {
                        attackers_and_defenders |=
                            match behind & straight_sliders &
                                  geometry.attacks_from_unsafe(ROOK, exchange_square, behind) {
                                0 => {
                                    // Not a straight slider, possibly a diagonal slider.
                                    behind & diag_sliders &
                                    geometry.attacks_from_unsafe(BISHOP, exchange_square, behind)
                                }
                                bb => {
                                    // A straight slider.
                                    bb
                                }
                            };
                    }
                }

                // Change the side to move.
                us ^= 1;

                // Find the next piece to enter the exchange. (The least
                // valuable piece belonging to the side to move.)
                let candidates = attackers_and_defenders & *color.get_unchecked(us);
                if candidates != 0 {
                    for p in (KING..PIECE_NONE).rev() {
                        let bb = candidates & piece_type[p];
                        if bb != 0 {
                            depth += 1;
                            piece = p;
                            orig_square_bb = ls1b(bb);
                            continue 'exchange;
                        }
                    }
                }
                break 'exchange;
            }

            // Negamax the `gain` array for the final static exchange
            // evaluation. (The `gain` array actually represents an unary
            // tree, at each node of which the player can either continue
            // the exchange or back off.)
            while depth > 0 {
                *gain.get_unchecked_mut(depth - 1) = -max(-*gain.get_unchecked(depth - 1),
                                                          *gain.get_unchecked(depth));
                depth -= 1;
            }
            gain[0]
        }
    }
}
<commit_msg>kill may_xray<commit_after>//! Defines the `MoveGenerator` trait.

use std::mem::uninitialized;
use std::cmp::max;
use uci::SetOption;
use board::*;
use moves::*;
use value::*;
use evaluator::Evaluator;
use utils::bitsets::*;
use utils::BoardGeometry;

/// A trait for move generators.
///
/// A `MoveGenerator` holds a chess position and can:
///
/// * Generate all legal moves, or a subset of all legal moves in the
///   current position.
///
/// * Perform static exchange evaluation for the generated moves.
///
/// * Play a selected move and take it back.
///
/// * Provide a static evaluator bound to the current position.
///
/// * Calculate Zobrist hashes.
///
/// **Important note:** `MoveGenerator` is unaware of repeating
/// positions and rule-50.
pub trait MoveGenerator: Sized + Send + Clone + SetOption {
    /// The type of static evaluator that the implementation works
    /// with.
    type Evaluator: Evaluator;

    /// Creates a new instance, consuming the supplied `Board`
    /// instance.
    ///
    /// Returns `None` if the position is illegal.
    fn from_board(board: Board) -> Option<Self>;

    /// Returns the Zobrist hash value for the underlying `Board`
    /// instance.
    ///
    /// Zobrist hashing is a technique to transform a board position
    /// into a number of a fixed length, with an equal distribution
    /// over all possible numbers, invented by Albert Zobrist. The key
    /// property of this method is that two similar positions generate
    /// entirely different hash numbers.
    ///
    /// **Important note:** This method will be relatively slow if the
    /// implementation calculates the hash value "from
    /// scratch". Inspect the implementation before using `hash` in
    /// time-critical paths. (See `do_move`.)
    fn hash(&self) -> u64;

    /// Returns a reference to the underlying `Board` instance.
    #[inline(always)]
    fn board(&self) -> &Board;

    /// Returns a bitboard with all pieces of color `us` that attack
    /// `square`.
    fn attacks_to(&self, us: Color, square: Square) -> Bitboard;

    /// Returns a bitboard with all enemy pieces that attack the king.
    ///
    /// **Important note:** The bitboard of checkers is calculated on
    /// the first call to `checkers`, and is stored in case another
    /// call is made before doing/undoing any moves. In that case
    /// `checkers` returns the saved bitboard instead of
    /// re-calculating it, thus saving time.
    fn checkers(&self) -> Bitboard;

    /// Returns a reference to a static evaluator bound to the current
    /// position.
    fn evaluator(&self) -> &Self::Evaluator;

    /// Generates all legal moves, possibly including some
    /// pseudo-legal moves too.
    ///
    /// The moves are added to `moves`. All generated moves with
    /// pieces other than the king will be legal. Some of the
    /// generated king's moves may be illegal because the destination
    /// square is under attack. This arrangement has two important
    /// advantages:
    ///
    /// * `do_move` can do its work without knowing the set of
    ///   checkers and pinned pieces, so there is no need to keep
    ///   those around.
    ///
    /// * A beta cut-off may make the verification that king's
    ///   destination square is not under attack unnecessary, thus
    ///   saving time.
    ///
    /// **Note:** A pseudo-legal move is a move that is otherwise
    /// legal, except it might leave the king in check.
    fn generate_all<T: AddMove>(&self, moves: &mut T);

    /// Generates moves for the quiescence search.
    ///
    /// The moves are added to `moves`. This method always generates a
    /// **subset** of the moves generated by `generate_all`:
    ///
    /// * If the king is in check, all legal moves are included.
    ///
    /// * Captures and pawn promotions to queen are always included.
    ///
    /// * If `generate_checks` is `true`, moves that give check are
    ///   included too. Discovered checks and checks given by castling
    ///   can be omitted for speed.
    fn generate_forcing<T: AddMove>(&self, generate_checks: bool, moves: &mut T);

    /// Checks if `move_digest` represents a pseudo-legal move.
    ///
    /// If a move `m` exists that would be generated by
    /// `generate_all` if called for the current position on the
    /// board, and for that move `m.digest() == move_digest`, this
    /// method will return `Some(m)`. Otherwise it will return
    /// `None`. This is useful when playing moves from the
    /// transposition table, without calling `generate_all`.
    fn try_move_digest(&self, move_digest: MoveDigest) -> Option<Move>;

    /// Returns a null move.
    ///
    /// "Null move" is a pseudo-move that changes only the side to
    /// move. It is sometimes useful to include a speculative null
    /// move in the search tree so as to achieve more aggressive
    /// pruning. Null moves are represented as king's moves for which
    /// the origin and destination squares are the same.
    fn null_move(&self) -> Move;

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and an `u64` value is returned, which should
    /// be XOR-ed with old board's hash value to obtain new board's
    /// hash value. If the move is illegal, `None` is returned without
    /// updating the board. The move passed to this method **must**
    /// have been generated by `generate_all`, `generate_forcing`,
    /// `try_move_digest`, or `null_move` methods for the current
    /// position on the board.
    ///
    /// The moves generated by the `null_move` method are
    /// exceptions. For them `do_move` will return `None` if and only
    /// if the king is in check.
    fn do_move(&mut self, m: Move) -> Option<u64>;

    /// Takes back last played move.
    ///
    /// The move passed to this method **must** be the last move passed
    /// to `do_move`.
    fn undo_move(&mut self, m: Move);

    /// Returns the likely evaluation change (material) to be lost or
    /// gained as a result of a given move.
    ///
    /// This method performs static exchange evaluation (SEE). It
    /// examines the consequence of a series of exchanges on the
    /// destination square after a given move. A positive returned
    /// value indicates a "winning" move. For example, "PxQ" will
    /// always be a win, since the pawn side can choose to stop the
    /// exchange after its pawn is recaptured, and still be ahead. SEE
    /// is just an evaluation calculated without actually trying moves
    /// on the board, and therefore the returned value might be
    /// incorrect.
    ///
    /// The move passed to this method must have been generated by
    /// `generate_all`, `generate_forcing`, `try_move_digest`, or
    /// `null_move` methods for the current position on the board.
    fn evaluate_move(&self, m: Move) -> Value {
        debug_assert!(m.played_piece() < PIECE_NONE);
        debug_assert!(m.captured_piece() <= PIECE_NONE);
        const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

        // This is the square on which all the action takes place.
        let exchange_square = m.dest_square();

        unsafe {
            let geometry = BoardGeometry::get();
            let behind_blocker: &[Bitboard; 64] = geometry.squares_behind_blocker
                                                          .get_unchecked(exchange_square);
            let piece_type: &[Bitboard; 6] = &self.board().pieces.piece_type;
            let color: &[Bitboard; 2] = &self.board().pieces.color;
            let straight_sliders = piece_type[QUEEN] | piece_type[ROOK];
            let diag_sliders = piece_type[QUEEN] | piece_type[BISHOP];

            // These variables will be updated on each capture:
            let mut us = self.board().to_move;
            let mut depth = 0;
            let mut piece;
            let mut orig_square_bb = 1 << m.orig_square();
            let mut attackers_and_defenders = self.attacks_to(WHITE, exchange_square) |
                                              self.attacks_to(BLACK, exchange_square);

            // The `gain` array will hold the total material gained at
            // each `depth`, from the viewpoint of the side that made the
            // last capture (`us`).
            let mut gain: [Value; 34] = uninitialized();
            gain[0] = if m.move_type() == MOVE_PROMOTION {
                piece = Move::piece_from_aux_data(m.aux_data());
                PIECE_VALUES[m.captured_piece()] + PIECE_VALUES[piece] - PIECE_VALUES[PAWN]
            } else {
                piece = m.played_piece();
                *PIECE_VALUES.get_unchecked(m.captured_piece())
            };

            // Examine the possible exchanges, fill the `gain` array.
            'exchange: while orig_square_bb != 0 {
                let current_gain = *gain.get_unchecked(depth);

                // Store a speculative value that will be used if the
                // captured piece happens to be defended.
                let speculative_gain: &mut Value = gain.get_unchecked_mut(depth + 1);
                *speculative_gain = *PIECE_VALUES.get_unchecked(piece) - current_gain;

                if max(-current_gain, *speculative_gain) < 0 {
                    // The side that made the last capture wins even if
                    // the captured piece happens to be defended. So, we
                    // stop here to save precious CPU cycles. Note that
                    // here we may happen to return an incorrect SEE
                    // value, but the sign will be correct, which is by
                    // far the most important information.
                    break;
                }

                // Register that capturing piece's origin square is now vacant.
                attackers_and_defenders &= !orig_square_bb;

                // Consider adding new attackers/defenders, now that
                // capturing piece's origin square is vacant.
                let behind = self.board().occupied &
                             *behind_blocker.get_unchecked(bitscan_1bit(orig_square_bb));
                if behind & (straight_sliders | diag_sliders) != 0 {
                    attackers_and_defenders |=
                        match behind & straight_sliders &
                              geometry.attacks_from_unsafe(ROOK, exchange_square, behind) {
                            0 => {
                                // Not a straight slider, possibly a diagonal slider.
                                behind & diag_sliders &
                                geometry.attacks_from_unsafe(BISHOP, exchange_square, behind)
                            }
                            bb => {
                                // A straight slider.
                                bb
                            }
                        };
                }

                // Change the side to move.
                us ^= 1;

                // Find the next piece to enter the exchange. (The least
                // valuable piece belonging to the side to move.)
                let candidates = attackers_and_defenders & *color.get_unchecked(us);
                if candidates != 0 {
                    for p in (KING..PIECE_NONE).rev() {
                        let bb = candidates & piece_type[p];
                        if bb != 0 {
                            depth += 1;
                            piece = p;
                            orig_square_bb = ls1b(bb);
                            continue 'exchange;
                        }
                    }
                }
                break 'exchange;
            }

            // Negamax the `gain` array for the final static exchange
            // evaluation. (The `gain` array actually represents an unary
            // tree, at each node of which the player can either continue
            // the exchange or back off.)
            while depth > 0 {
                *gain.get_unchecked_mut(depth - 1) = -max(-*gain.get_unchecked(depth - 1),
                                                          *gain.get_unchecked(depth));
                depth -= 1;
            }
            gain[0]
        }
    }
}
<|endoftext|>


<commit_before>use num_complex::Complex;
use std::marker::PhantomData;

/// Holds information about how to partition the access to a slice to get aligned
/// reads/writes to the largest portion of the slice.
pub struct SimdPartition<T> {
    /// Left part of the slice which must not be accessed with SIMD operations
    pub left: usize,
    /// Right  part of the slice which must not be accessed with SIMD operations
    right: usize,
    len: usize,
    data_type: PhantomData<T>,
}

/// Iterator around the left and right side of a vector.
pub struct EdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    left: *mut T,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> EdgeIteratorMut<'a, T> {
    pub fn new(slice: &mut [T], left: usize, right: usize) -> impl Iterator<Item = &mut T> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            EdgeIteratorMut {
                pos: start,
                left: start.offset(left - 1),
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for EdgeIteratorMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                self.pos = self.pos.offset(1);
                Some(value)
            }
        }
    }
}

/// Iterator with index around the left and right side of a vector.
pub struct IndexedEdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    idx: isize,
    left: *mut T,
    right_idx: isize,
    right: *mut T,
    end: *mut T,
    _marker: std::marker::PhantomData<&'a mut T>,
}

impl<'a, T> IndexedEdgeIteratorMut<'a, T> {
    pub fn new(
        slice: &mut [T],
        left: usize,
        right: usize,
    ) -> impl Iterator<Item = (isize, &mut T)> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            IndexedEdgeIteratorMut {
                pos: start,
                idx: 0,
                left: start.offset(left - 1),
                right_idx: len - right,
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: std::marker::PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for IndexedEdgeIteratorMut<'a, T> {
    type Item = (isize, &'a mut T);

    fn next(&mut self) -> Option<(isize, &'a mut T)> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
                self.idx = self.right_idx;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                let idx = self.idx;
                self.pos = self.pos.offset(1);
                self.idx += 1;
                Some((idx, value))
            }
        }
    }
}

/// Creates an iterator for the first `left` and last `right` elements in a slice
fn create_edge_iter_mut<T>(
    slice: &mut [T],
    right: usize,
    left: usize,
    len: usize,
) -> impl Iterator<Item = &mut T> {
    let (left_values, right_values) = slice.split_at_mut(left);
    let right = right - left;
    let right_len = len - left;

    left_values
        .iter_mut()
        .chain(right_values[right..right_len].iter_mut())
}

impl<T> SimdPartition<T> {
    pub fn new_all_scalar(len: usize) -> Self {
        Self {
            left: len,
            right: 0,
            len,
            data_type: PhantomData,
        }
    }

    pub fn new_simd(left: usize, right: usize, len: usize) -> Self {
        Self {
            left,
            right,
            len,
            data_type: PhantomData,
        }
    }

    /// Iterator over the left and right side of the slice.
    pub fn edge_iter<'a>(&self, slice: &'a [T]) -> impl Iterator<Item = &'a T> {
        slice[0..self.left]
            .iter()
            .chain(slice[self.len - self.right..self.len].iter())
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter<'a>(&self, slice: &'a [Complex<T>]) -> impl Iterator<Item = &'a Complex<T>> {
        slice[0..self.left / 2]
            .iter()
            .chain(slice[self.len / 2 - self.right / 2..self.len / 2].iter())
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn edge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len], self.left, self.right)
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter_mut<'a>(
        &self,
        slice: &'a mut [Complex<T>],
    ) -> impl Iterator<Item = &'a mut Complex<T>> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn redge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Gets the center of a slice.
    pub fn center<'a>(&self, slice: &'a [T]) -> &'a [T] {
        if self.left == self.len {
            &[]
        } else {
            &slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice.
    pub fn center_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice, expects the real part of complex data.
    pub fn rcenter_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left / 2..self.len / 2 - self.right / 2]
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EdgeIteratorMut, IndexedEdgeIteratorMut};

    #[test]
    fn edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for n in EdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n;
        }

        let expected = vec![-1, -2, 3, 4, 5, 6, -7, -8, -9];
        assert_eq!(&data, &expected);
    }

    #[test]
    fn indexed_edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for (idx, n) in IndexedEdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n - 10 * (idx + 1);
        }

        let expected = vec![-11, -22, 3, 4, 5, 6, -77, -88, -99];
        assert_eq!(&data, &expected);
    }
}
<commit_msg>Fixed build error on Rust stable<commit_after>use num_complex::Complex;
use std::marker::PhantomData;

/// Holds information about how to partition the access to a slice to get aligned
/// reads/writes to the largest portion of the slice.
pub struct SimdPartition<T> {
    /// Left part of the slice which must not be accessed with SIMD operations
    pub left: usize,
    /// Right  part of the slice which must not be accessed with SIMD operations
    right: usize,
    len: usize,
    data_type: PhantomData<T>,
}

/// Iterator around the left and right side of a vector.
pub struct EdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    left: *mut T,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> EdgeIteratorMut<'a, T> {
    pub fn new(slice: &mut [T], left: usize, right: usize) -> impl Iterator<Item = &mut T> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            EdgeIteratorMut {
                pos: start,
                left: start.offset(left - 1),
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for EdgeIteratorMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                self.pos = self.pos.offset(1);
                Some(value)
            }
        }
    }
}

/// Iterator with index around the left and right side of a vector.
pub struct IndexedEdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    idx: isize,
    left: *mut T,
    right_idx: isize,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> IndexedEdgeIteratorMut<'a, T> {
    pub fn new(
        slice: &mut [T],
        left: usize,
        right: usize,
    ) -> impl Iterator<Item = (isize, &mut T)> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            IndexedEdgeIteratorMut {
                pos: start,
                idx: 0,
                left: start.offset(left - 1),
                right_idx: len - right,
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for IndexedEdgeIteratorMut<'a, T> {
    type Item = (isize, &'a mut T);

    fn next(&mut self) -> Option<(isize, &'a mut T)> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
                self.idx = self.right_idx;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                let idx = self.idx;
                self.pos = self.pos.offset(1);
                self.idx += 1;
                Some((idx, value))
            }
        }
    }
}

/// Creates an iterator for the first `left` and last `right` elements in a slice
fn create_edge_iter_mut<T>(
    slice: &mut [T],
    right: usize,
    left: usize,
    len: usize,
) -> impl Iterator<Item = &mut T> {
    let (left_values, right_values) = slice.split_at_mut(left);
    let right = right - left;
    let right_len = len - left;

    left_values
        .iter_mut()
        .chain(right_values[right..right_len].iter_mut())
}

impl<T> SimdPartition<T> {
    pub fn new_all_scalar(len: usize) -> Self {
        Self {
            left: len,
            right: 0,
            len,
            data_type: PhantomData,
        }
    }

    pub fn new_simd(left: usize, right: usize, len: usize) -> Self {
        Self {
            left,
            right,
            len,
            data_type: PhantomData,
        }
    }

    /// Iterator over the left and right side of the slice.
    pub fn edge_iter<'a>(&self, slice: &'a [T]) -> impl Iterator<Item = &'a T> {
        slice[0..self.left]
            .iter()
            .chain(slice[self.len - self.right..self.len].iter())
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter<'a>(&self, slice: &'a [Complex<T>]) -> impl Iterator<Item = &'a Complex<T>> {
        slice[0..self.left / 2]
            .iter()
            .chain(slice[self.len / 2 - self.right / 2..self.len / 2].iter())
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn edge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len], self.left, self.right)
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter_mut<'a>(
        &self,
        slice: &'a mut [Complex<T>],
    ) -> impl Iterator<Item = &'a mut Complex<T>> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn redge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Gets the center of a slice.
    pub fn center<'a>(&self, slice: &'a [T]) -> &'a [T] {
        if self.left == self.len {
            &[]
        } else {
            &slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice.
    pub fn center_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice, expects the real part of complex data.
    pub fn rcenter_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left / 2..self.len / 2 - self.right / 2]
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EdgeIteratorMut, IndexedEdgeIteratorMut};

    #[test]
    fn edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for n in EdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n;
        }

        let expected = vec![-1, -2, 3, 4, 5, 6, -7, -8, -9];
        assert_eq!(&data, &expected);
    }

    #[test]
    fn indexed_edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for (idx, n) in IndexedEdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n - 10 * (idx + 1);
        }

        let expected = vec![-11, -22, 3, 4, 5, 6, -77, -88, -99];
        assert_eq!(&data, &expected);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::path::build_path;
use super::super::helpers::oauth2;
use super::super::results::{BearerResult, BearerError};

fn read_stdin(message: &str) -> BearerResult<String> {
    print!("{}", message);
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    match io::stdin().read_line(&mut buffer) {
        Ok(_) => Ok(buffer.trim().to_string()),
        Err(err) => Err(BearerError::IOError(format!("{}", err))),
    }
}

pub fn register(config_dir: &str, client_name: &str) -> BearerResult<()> {

    debug!("Registering new client {} in directory {}",
           client_name,
           config_dir);
    let (_, exists) = build_path(config_dir, client_name)?;
    if exists {
        return Err(BearerError::ValueError(format!("Client {} already registered", client_name)));
    }
    println!("Before continue, register the a client with the following url to the OAuth2 \
              Provider:");
    println!("");
    println!("http://localhost:6750/callback");
    println!("");
    println!("Ensure your port is not already open by another service.");
    println!("If the provider require a https url, please run an https reverse proxy before \
              continue.");
    println!("");
    let server_url = read_stdin("Enter the OAuth2.0 Server Url: ")?;
    let client_id = read_stdin("Enter the Client Id: ")?;
    let secret = read_stdin("Enter the Client Secret: ")?;

    let mut config = Config::new(config_dir,
                                 client_name,
                                 server_url.as_str(),
                                 client_id.as_str(),
                                 secret.as_str())?;

    debug!("Start server to retrieve tokens");
    let tokens = oauth2::get_tokens(&config)?;
    debug!("Token retrieved: {:?}", tokens);
    config.set_tokens(tokens);
    config.write()
}
<commit_msg>Add missing message to user on client registration<commit_after>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::path::build_path;
use super::super::helpers::oauth2;
use super::super::results::{BearerResult, BearerError};

fn read_stdin(message: &str) -> BearerResult<String> {
    print!("{}", message);
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    match io::stdin().read_line(&mut buffer) {
        Ok(_) => Ok(buffer.trim().to_string()),
        Err(err) => Err(BearerError::IOError(format!("{}", err))),
    }
}

pub fn register(config_dir: &str, client_name: &str) -> BearerResult<()> {

    debug!("Registering new client {} in directory {}",
           client_name,
           config_dir);
    let (_, exists) = build_path(config_dir, client_name)?;
    if exists {
        return Err(BearerError::ValueError(format!("Client {} already registered", client_name)));
    }
    println!("Before continue, register the a client with the following url to the OAuth2 \
              Provider:");
    println!("");
    println!("http://localhost:6750/callback");
    println!("");
    println!("Ensure your port is not already open by another service.");
    println!("If the provider require a https url, please run an https reverse proxy before \
              continue.");
    println!("");
    let server_url = read_stdin("Enter the OAuth2.0 Server Url: ")?;
    let client_id = read_stdin("Enter the Client Id: ")?;
    let secret = read_stdin("Enter the Client Secret: ")?;

    let mut config = Config::new(config_dir,
                                 client_name,
                                 server_url.as_str(),
                                 client_id.as_str(),
                                 secret.as_str())?;

    println!("");
    println!("Visit to finish the configuration: http://localhost:6750/callback");

    debug!("Start server to retrieve tokens");
    let tokens = oauth2::get_tokens(&config)?;
    debug!("Token retrieved: {:?}", tokens);
    config.set_tokens(tokens);
    config.write()?;
    println!("Tokens retrieved succesfully");
    Ok(())
}
<|endoftext|>


<commit_before>use std;
use rustc;

// -*- rust -*-
import core::{option, str, vec, result};
import result::{ok, err};
import std::{io, getopts};
import io::writer_util;
import option::{some, none};
import getopts::{opt_present};
import rustc::driver::driver::*;
import rustc::syntax::codemap;
import rustc::driver::diagnostic;

fn version(argv0: str) {
    let vers = "unknown version";
    let env_vers = #env["CFG_VERSION"];
    if str::byte_len(env_vers) != 0u { vers = env_vers; }
    io::stdout().write_str(#fmt["%s %s\n", argv0, vers]);
    io::stdout().write_str(#fmt["host: %s\n", host_triple()]);
}

fn usage(argv0: str) {
    io::stdout().write_str(#fmt["usage: %s [options] <input>\n", argv0] +
                               "
options:

    -h --help          display this message
    -v --version       print version info and exit

    -o <filename>      write output to <filename>
    --out-dir <dir>    write output to compiler-chosen filename in <dir>
    --lib              compile a library crate
    --bin              compile an executable crate (default)
    --static           use or produce static libraries
    --no-core          omit the 'core' library (used and imported by default)
    --pretty [type]    pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --no-verify        suppress LLVM verification step (slight speedup)
    --parse-only       parse only; do not compile, assemble, or link
    --no-trans         run all passes except translation; no output
    -g                 produce debug info
    --opt-level <lvl>  optimize with possible levels 0-3
    -O                 equivalent to --opt-level=2
    -S                 compile only; do not assemble or link
    --no-asm-comments  do not add comments into the assembly source
    -c                 compile and assemble, but do not link
    --emit-llvm        produce an LLVM bitcode file
    --save-temps       write intermediate files in addition to normal output
    --stats            gather and report various compilation statistics
    --cfg <cfgspec>    configure the compilation environment
    --time-passes      time the individual phases of the compiler
    --time-llvm-passes time the individual phases of the LLVM backend
    --sysroot <path>   override the system root
    --target <triple>  target to compile for (default: host triple)
    --test             build test harness
    --gc               garbage collect shared data (experimental/temporary)
    --warn-unused-imports
                       warn about unnecessary imports

");
}

fn run_compiler(args: [str], demitter: diagnostic::emitter) {
    // Don't display log spew by default. Can override with RUST_LOG.
    logging::console_off();

    let args = args, binary = vec::shift(args);

    if vec::len(args) == 0u { usage(binary); ret; }

    let match =
        alt getopts::getopts(args, opts()) {
          ok(m) { m }
          err(f) {
            early_error(demitter, getopts::fail_str(f))
          }
        };
    if opt_present(match, "h") || opt_present(match, "help") {
        usage(binary);
        ret;
    }
    if opt_present(match, "v") || opt_present(match, "version") {
        version(binary);
        ret;
    }
    let ifile = alt vec::len(match.free) {
      0u { early_error(demitter, "No input filename given.") }
      1u { match.free[0] }
      _ { early_error(demitter, "Multiple input filenames provided.") }
    };

    let sopts = build_session_options(match, demitter);
    let sess = build_session(sopts, ifile, demitter);
    let odir = getopts::opt_maybe_str(match, "out-dir");
    let ofile = getopts::opt_maybe_str(match, "o");
    let cfg = build_configuration(sess, binary, ifile);
    let pretty =
        option::map(getopts::opt_default(match, "pretty",
                                         "normal"),
                    bind parse_pretty(sess, _));
    alt pretty {
      some::<pp_mode>(ppm) { pretty_print_input(sess, cfg, ifile, ppm); ret; }
      none::<pp_mode>. {/* continue */ }
    }
    let ls = opt_present(match, "ls");
    if ls {
        list_metadata(sess, ifile, io::stdout());
        ret;
    }

    compile_input(sess, cfg, ifile, odir, ofile);
}

/*
This is a sanity check that any failure of the compiler is performed
through the diagnostic module and reported properly - we shouldn't be calling
plain-old-fail on any execution path that might be taken. Since we have
console logging off by default, hitting a plain fail statement would make the
compiler silently exit, which would be terrible.

This method wraps the compiler in a subtask and injects a function into the
diagnostic emitter which records when we hit a fatal error. If the task
fails without recording a fatal error then we've encountered a compiler
bug and need to present an error.
*/
fn monitor(f: fn~(diagnostic::emitter)) {
    tag monitor_msg {
        fatal;
        done;
    };

    let p = comm::port();
    let ch = comm::chan(p);

    alt task::try  {||

        task::unsupervise();

        // The 'diagnostics emitter'. Every error, warning, etc. should
        // go through this function.
        let demitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
                           msg: str, lvl: diagnostic::level) {
            if lvl == diagnostic::fatal {
                comm::send(ch, fatal);
            }
            diagnostic::emit(cmsp, msg, lvl);
        };

        resource finally(ch: comm::chan<monitor_msg>) {
            comm::send(ch, done);
        }

        let _finally = finally(ch);

        f(demitter)
    } {
        result::ok(_) { /* fallthrough */ }
        result::err(_) {
            // Task failed without emitting a fatal diagnostic
            if comm::recv(p) == done {
                diagnostic::emit(
                    none,
                    diagnostic::ice_msg("unexpected failure"),
                    diagnostic::error);
            }
            // Fail so the process returns a failure code
            fail;
        }
    }
}

fn main(args: [str]) {
    monitor {|demitter|
        run_compiler(args, demitter);
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>rustc: Output a note about how to debug unexpected failures<commit_after>use std;
use rustc;

// -*- rust -*-
import core::{option, str, vec, result};
import result::{ok, err};
import std::{io, getopts};
import io::writer_util;
import option::{some, none};
import getopts::{opt_present};
import rustc::driver::driver::*;
import rustc::syntax::codemap;
import rustc::driver::diagnostic;

fn version(argv0: str) {
    let vers = "unknown version";
    let env_vers = #env["CFG_VERSION"];
    if str::byte_len(env_vers) != 0u { vers = env_vers; }
    io::stdout().write_str(#fmt["%s %s\n", argv0, vers]);
    io::stdout().write_str(#fmt["host: %s\n", host_triple()]);
}

fn usage(argv0: str) {
    io::stdout().write_str(#fmt["usage: %s [options] <input>\n", argv0] +
                               "
options:

    -h --help          display this message
    -v --version       print version info and exit

    -o <filename>      write output to <filename>
    --out-dir <dir>    write output to compiler-chosen filename in <dir>
    --lib              compile a library crate
    --bin              compile an executable crate (default)
    --static           use or produce static libraries
    --no-core          omit the 'core' library (used and imported by default)
    --pretty [type]    pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --no-verify        suppress LLVM verification step (slight speedup)
    --parse-only       parse only; do not compile, assemble, or link
    --no-trans         run all passes except translation; no output
    -g                 produce debug info
    --opt-level <lvl>  optimize with possible levels 0-3
    -O                 equivalent to --opt-level=2
    -S                 compile only; do not assemble or link
    --no-asm-comments  do not add comments into the assembly source
    -c                 compile and assemble, but do not link
    --emit-llvm        produce an LLVM bitcode file
    --save-temps       write intermediate files in addition to normal output
    --stats            gather and report various compilation statistics
    --cfg <cfgspec>    configure the compilation environment
    --time-passes      time the individual phases of the compiler
    --time-llvm-passes time the individual phases of the LLVM backend
    --sysroot <path>   override the system root
    --target <triple>  target to compile for (default: host triple)
    --test             build test harness
    --gc               garbage collect shared data (experimental/temporary)
    --warn-unused-imports
                       warn about unnecessary imports

");
}

fn run_compiler(args: [str], demitter: diagnostic::emitter) {
    // Don't display log spew by default. Can override with RUST_LOG.
    logging::console_off();

    let args = args, binary = vec::shift(args);

    if vec::len(args) == 0u { usage(binary); ret; }

    let match =
        alt getopts::getopts(args, opts()) {
          ok(m) { m }
          err(f) {
            early_error(demitter, getopts::fail_str(f))
          }
        };
    if opt_present(match, "h") || opt_present(match, "help") {
        usage(binary);
        ret;
    }
    if opt_present(match, "v") || opt_present(match, "version") {
        version(binary);
        ret;
    }
    let ifile = alt vec::len(match.free) {
      0u { early_error(demitter, "No input filename given.") }
      1u { match.free[0] }
      _ { early_error(demitter, "Multiple input filenames provided.") }
    };

    let sopts = build_session_options(match, demitter);
    let sess = build_session(sopts, ifile, demitter);
    let odir = getopts::opt_maybe_str(match, "out-dir");
    let ofile = getopts::opt_maybe_str(match, "o");
    let cfg = build_configuration(sess, binary, ifile);
    let pretty =
        option::map(getopts::opt_default(match, "pretty",
                                         "normal"),
                    bind parse_pretty(sess, _));
    alt pretty {
      some::<pp_mode>(ppm) { pretty_print_input(sess, cfg, ifile, ppm); ret; }
      none::<pp_mode>. {/* continue */ }
    }
    let ls = opt_present(match, "ls");
    if ls {
        list_metadata(sess, ifile, io::stdout());
        ret;
    }

    compile_input(sess, cfg, ifile, odir, ofile);
}

/*
This is a sanity check that any failure of the compiler is performed
through the diagnostic module and reported properly - we shouldn't be calling
plain-old-fail on any execution path that might be taken. Since we have
console logging off by default, hitting a plain fail statement would make the
compiler silently exit, which would be terrible.

This method wraps the compiler in a subtask and injects a function into the
diagnostic emitter which records when we hit a fatal error. If the task
fails without recording a fatal error then we've encountered a compiler
bug and need to present an error.
*/
fn monitor(f: fn~(diagnostic::emitter)) {
    tag monitor_msg {
        fatal;
        done;
    };

    let p = comm::port();
    let ch = comm::chan(p);

    alt task::try  {||

        task::unsupervise();

        // The 'diagnostics emitter'. Every error, warning, etc. should
        // go through this function.
        let demitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
                           msg: str, lvl: diagnostic::level) {
            if lvl == diagnostic::fatal {
                comm::send(ch, fatal);
            }
            diagnostic::emit(cmsp, msg, lvl);
        };

        resource finally(ch: comm::chan<monitor_msg>) {
            comm::send(ch, done);
        }

        let _finally = finally(ch);

        f(demitter)
    } {
        result::ok(_) { /* fallthrough */ }
        result::err(_) {
            // Task failed without emitting a fatal diagnostic
            if comm::recv(p) == done {
                diagnostic::emit(
                    none,
                    diagnostic::ice_msg("unexpected failure"),
                    diagnostic::error);
                let note = "The compiler hit an unexpected failure path. \
                            This is a bug. Try running with \
                            RUST_LOG=rustc=0,::rt::backtrace \
                            to get further details and report the results \
                            to github.com/mozilla/rust/issues";
                diagnostic::emit(none, note, diagnostic::note);
            }
            // Fail so the process returns a failure code
            fail;
        }
    }
}

fn main(args: [str]) {
    monitor {|demitter|
        run_compiler(args, demitter);
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=QtCore", osx_framework);
    println!("cargo:rustc-link-lib{}=QtNetwork", osx_framework);
    println!("cargo:rustc-link-lib{}=QtGui", osx_framework);
    println!("cargo:rustc-link-lib{}=QtQml", osx_framework);
    println!("cargo:rustc-link-lib{}=QtWidgets", osx_framework);

    println!("cargo:rustc-flags=-l stdc++");
}
<commit_msg>libqmlbind-sys: On Linux, Qt librairies contain "5", fix on build.rs<commit_after>use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };
    // On Linux, libraries are name "Qt5Core", not "QtCore" as on OSX
    let linux_qt_lib_ver = if target.contains("linux") { "5" }
                           else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=Qt{}Core", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Network", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Gui", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Qml", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Widgets", osx_framework, linux_qt_lib_ver);

    println!("cargo:rustc-flags=-l stdc++");
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use mimir;

use geojson;
use geo;
use std::rc::Rc;

#[derive(Serialize, Deserialize, Debug)]
pub struct Geocoding {
    version: String,
    query: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Feature {
    #[serde(rename = "type")]
    pub feature_type: String,
    pub geometry: geojson::Geometry,
    pub properties: Properties,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Properties {
    pub geocoding: GeocodingResponse,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct GeocodingResponse {
    pub id: String,
    #[serde(rename = "type")]
    pub place_type: String, // FIXME: use an enum?
    pub label: Option<String>,
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub housenumber: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub street: Option<String>,
    pub postcode: Option<String>,
    pub city: Option<String>,
    pub citycode: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<u32>,
    // pub accuracy: Option<i32>,
    // pub district: Option<String>,
    // pub county: Option<String>,
    // pub state: Option<String>,
    // pub country: Option<String>,
    // pub geohash: Option<String>,
    pub administrative_regions: Vec<Rc<mimir::Admin>>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub poi_types: Vec<mimir::PoiType>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub properties: Vec<mimir::Property>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub address: Option<Box<GeocodingResponse>>,
}

trait ToGeom {
    fn to_geom(&self) -> geojson::Geometry;
}

impl ToGeom for mimir::Place {
    fn to_geom(&self) -> geojson::Geometry {
        match self {
            &mimir::Place::Admin(ref admin) => admin.coord.to_geom(),
            &mimir::Place::Street(ref street) => street.coord.to_geom(),
            &mimir::Place::Addr(ref addr) => addr.coord.to_geom(),
            &mimir::Place::Poi(ref poi) => poi.coord.to_geom(),
            &mimir::Place::Stop(ref stop) => stop.coord.to_geom(),
        }
    }
}

impl ToGeom for geo::Coordinate<f64> {
    fn to_geom(&self) -> geojson::Geometry {
        geojson::Geometry::new(geojson::Value::Point(vec![self.x, self.y]))
    }
}

impl From<mimir::Place> for Feature {
    fn from(other: mimir::Place) -> Feature {
        let geom = other.to_geom();
        let geocoding = match other {
            mimir::Place::Admin(admin) => GeocodingResponse::from(admin),
            mimir::Place::Street(street) => GeocodingResponse::from(street),
            mimir::Place::Addr(addr) => GeocodingResponse::from(addr),
            mimir::Place::Poi(poi) => GeocodingResponse::from(poi),
            mimir::Place::Stop(poi) => GeocodingResponse::from(poi),
        };
        Feature {
            feature_type: "Feature".to_string(),
            geometry: geom,
            properties: Properties {
                geocoding: geocoding,
            },
        }
    }
}

impl From<mimir::Admin> for GeocodingResponse {
    fn from(other: mimir::Admin) -> GeocodingResponse {
        let type_ = other.admin_type.to_string();
        let name = Some(other.name);
        let insee = Some(other.insee);
        let level = Some(other.level); //might be used for type_ and become useless
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let label = Some(other.label);
        GeocodingResponse {
            id: other.id,
            citycode: insee,
            level: level,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: None,
            administrative_regions: vec![],
            poi_types: vec![],
            properties: vec![],
            address: None,
        }
    }
}

fn get_city_name(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    // for the moment for the 'postcode' and the 'city', we take first admin
    // that has a postcode
    // TODO: change this (with a 'city tag in the admin ?')
    admins
        .iter()
        .find(|a| !a.zip_codes.is_empty())
        .or_else(|| admins.iter().next())
        .map(|admin| admin.name.clone())
}

fn get_citycode(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    admins
        .iter()
        .find(|a| !a.zip_codes.is_empty())
        .or_else(|| admins.iter().next())
        .map(|admin| admin.insee.clone())
}

impl From<mimir::Street> for GeocodingResponse {
    fn from(other: mimir::Street) -> GeocodingResponse {
        let type_ = "street".to_string();
        let name = Some(other.street_name);
        let label = Some(other.label);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name.clone(),
            postcode: postcode,
            label: label,
            housenumber: None,
            street: name,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
        }
    }
}

impl From<mimir::Addr> for GeocodingResponse {
    fn from(other: mimir::Addr) -> GeocodingResponse {
        let type_ = "house".to_string();
        let label = Some(other.label);
        let housenumber = Some(other.house_number.to_string());
        let street_name = Some(other.street.street_name.to_string());
        let name = Some(format!(
            "{} {}",
            other.house_number, other.street.street_name
        ));
        let admins = other.street.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: housenumber,
            street: street_name,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
        }
    }
}

impl From<mimir::Poi> for GeocodingResponse {
    fn from(other: mimir::Poi) -> GeocodingResponse {
        let type_ = "poi".to_string();
        let label = Some(other.label);
        let name = Some(other.name);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins,
            poi_types: vec![other.poi_type],
            properties: other.properties,
            address: match other.address {
                Some(mimir::Address::Addr(addr)) => Some(Box::new(GeocodingResponse::from(addr))),
                Some(mimir::Address::Street(street)) => {
                    Some(Box::new(GeocodingResponse::from(street)))
                }
                _ => None,
            },
        }
    }
}

impl From<mimir::Stop> for GeocodingResponse {
    fn from(other: mimir::Stop) -> GeocodingResponse {
        let type_ = "public_transport:stop_area".to_string();
        let label = Some(other.label);
        let name = Some(other.name);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Autocomplete {
    #[serde(rename = "type")]
    format_type: String,
    geocoding: Geocoding,
    features: Vec<Feature>,
}

impl Autocomplete {
    pub fn new(q: String, features: Vec<Feature>) -> Autocomplete {
        // TODO couldn't we mode this function ? in Autocomplete ?
        Autocomplete {
            format_type: "FeatureCollection".to_string(),
            geocoding: Geocoding {
                version: "0.1.0".to_string(),
                query: Some(q),
            },
            features: features,
        }
    }
}

impl From<Vec<mimir::Place>> for Autocomplete {
    fn from(places: Vec<mimir::Place>) -> Autocomplete {
        Autocomplete::new(
            "".to_string(),
            places.into_iter().map(|p| Feature::from(p)).collect(),
        )
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Coord {
    pub lat: f64,
    pub lon: f64,
}

pub mod v1 {
    use mimir;
    use rs_es;

    // Note: I think this should be in api.rs but with the serde stuff it's easier for all
    // serde struct to be in the same file

    #[derive(Serialize, Deserialize, Debug)]
    pub struct EndPoint {
        pub description: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct CustomError {
        pub short: String,
        pub long: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub enum V1Reponse {
        Error(CustomError),
        Response { description: String },
    }
    #[derive(Debug)]
    pub enum AutocompleteResponse {
        Error(CustomError),
        Autocomplete(super::Autocomplete),
    }

    use serde;
    impl serde::Serialize for AutocompleteResponse {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            match self {
                &AutocompleteResponse::Autocomplete(ref a) => serializer.serialize_some(a),
                &AutocompleteResponse::Error(ref e) => serializer.serialize_some(e),
            }
        }
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Status {
        pub version: String,
        pub es: String,
        pub status: String,
    }

    impl From<Result<Vec<mimir::Place>, rs_es::error::EsError>> for AutocompleteResponse {
        fn from(r: Result<Vec<mimir::Place>, rs_es::error::EsError>) -> AutocompleteResponse {
            match r {
                Ok(places) => AutocompleteResponse::Autocomplete(super::Autocomplete::from(places)),
                Err(e) => AutocompleteResponse::Error(CustomError {
                    short: "query error".to_string(),
                    long: format!("invalid query {:?}", e),
                }),
            }
        }
    }
}
<commit_msg>commercial_modes and physical_modes in bragi output<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use mimir;

use geojson;
use geo;
use std::rc::Rc;

#[derive(Serialize, Deserialize, Debug)]
pub struct Geocoding {
    version: String,
    query: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Feature {
    #[serde(rename = "type")]
    pub feature_type: String,
    pub geometry: geojson::Geometry,
    pub properties: Properties,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Properties {
    pub geocoding: GeocodingResponse,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct GeocodingResponse {
    pub id: String,
    #[serde(rename = "type")]
    pub place_type: String, // FIXME: use an enum?
    pub label: Option<String>,
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub housenumber: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub street: Option<String>,
    pub postcode: Option<String>,
    pub city: Option<String>,
    pub citycode: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<u32>,
    // pub accuracy: Option<i32>,
    // pub district: Option<String>,
    // pub county: Option<String>,
    // pub state: Option<String>,
    // pub country: Option<String>,
    // pub geohash: Option<String>,
    pub administrative_regions: Vec<Rc<mimir::Admin>>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub poi_types: Vec<mimir::PoiType>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub properties: Vec<mimir::Property>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub address: Option<Box<GeocodingResponse>>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub commercial_modes: Vec<mimir::CommercialMode>,
    #[serde(skip_serializing_if = "Vec::is_empty", default)]
    pub physical_modes: Vec<mimir::PhysicalMode>,
}

trait ToGeom {
    fn to_geom(&self) -> geojson::Geometry;
}

impl ToGeom for mimir::Place {
    fn to_geom(&self) -> geojson::Geometry {
        match self {
            &mimir::Place::Admin(ref admin) => admin.coord.to_geom(),
            &mimir::Place::Street(ref street) => street.coord.to_geom(),
            &mimir::Place::Addr(ref addr) => addr.coord.to_geom(),
            &mimir::Place::Poi(ref poi) => poi.coord.to_geom(),
            &mimir::Place::Stop(ref stop) => stop.coord.to_geom(),
        }
    }
}

impl ToGeom for geo::Coordinate<f64> {
    fn to_geom(&self) -> geojson::Geometry {
        geojson::Geometry::new(geojson::Value::Point(vec![self.x, self.y]))
    }
}

impl From<mimir::Place> for Feature {
    fn from(other: mimir::Place) -> Feature {
        let geom = other.to_geom();
        let geocoding = match other {
            mimir::Place::Admin(admin) => GeocodingResponse::from(admin),
            mimir::Place::Street(street) => GeocodingResponse::from(street),
            mimir::Place::Addr(addr) => GeocodingResponse::from(addr),
            mimir::Place::Poi(poi) => GeocodingResponse::from(poi),
            mimir::Place::Stop(poi) => GeocodingResponse::from(poi),
        };
        Feature {
            feature_type: "Feature".to_string(),
            geometry: geom,
            properties: Properties {
                geocoding: geocoding,
            },
        }
    }
}

impl From<mimir::Admin> for GeocodingResponse {
    fn from(other: mimir::Admin) -> GeocodingResponse {
        let type_ = other.admin_type.to_string();
        let name = Some(other.name);
        let insee = Some(other.insee);
        let level = Some(other.level); //might be used for type_ and become useless
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let label = Some(other.label);
        GeocodingResponse {
            id: other.id,
            citycode: insee,
            level: level,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: None,
            administrative_regions: vec![],
            poi_types: vec![],
            properties: vec![],
            address: None,
            commercial_modes: vec![],
            physical_modes: vec![],
        }
    }
}

fn get_city_name(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    // for the moment for the 'postcode' and the 'city', we take first admin
    // that has a postcode
    // TODO: change this (with a 'city tag in the admin ?')
    admins
        .iter()
        .find(|a| !a.zip_codes.is_empty())
        .or_else(|| admins.iter().next())
        .map(|admin| admin.name.clone())
}

fn get_citycode(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    admins
        .iter()
        .find(|a| !a.zip_codes.is_empty())
        .or_else(|| admins.iter().next())
        .map(|admin| admin.insee.clone())
}

impl From<mimir::Street> for GeocodingResponse {
    fn from(other: mimir::Street) -> GeocodingResponse {
        let type_ = "street".to_string();
        let name = Some(other.street_name);
        let label = Some(other.label);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name.clone(),
            postcode: postcode,
            label: label,
            housenumber: None,
            street: name,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
            commercial_modes: vec![],
            physical_modes: vec![],
        }
    }
}

impl From<mimir::Addr> for GeocodingResponse {
    fn from(other: mimir::Addr) -> GeocodingResponse {
        let type_ = "house".to_string();
        let label = Some(other.label);
        let housenumber = Some(other.house_number.to_string());
        let street_name = Some(other.street.street_name.to_string());
        let name = Some(format!(
            "{} {}",
            other.house_number, other.street.street_name
        ));
        let admins = other.street.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: housenumber,
            street: street_name,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
            commercial_modes: vec![],
            physical_modes: vec![],
        }
    }
}

impl From<mimir::Poi> for GeocodingResponse {
    fn from(other: mimir::Poi) -> GeocodingResponse {
        let type_ = "poi".to_string();
        let label = Some(other.label);
        let name = Some(other.name);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins,
            poi_types: vec![other.poi_type],
            properties: other.properties,
            address: match other.address {
                Some(mimir::Address::Addr(addr)) => Some(Box::new(GeocodingResponse::from(addr))),
                Some(mimir::Address::Street(street)) => {
                    Some(Box::new(GeocodingResponse::from(street)))
                }
                _ => None,
            },
            commercial_modes: vec![],
            physical_modes: vec![],
        }
    }
}

impl From<mimir::Stop> for GeocodingResponse {
    fn from(other: mimir::Stop) -> GeocodingResponse {
        let type_ = "public_transport:stop_area".to_string();
        let label = Some(other.label);
        let name = Some(other.name);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() {
            None
        } else {
            Some(other.zip_codes.join(";"))
        };
        let citycode = get_citycode(&admins);

        GeocodingResponse {
            id: other.id,
            citycode: citycode,
            level: None,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins,
            poi_types: vec![],
            properties: vec![],
            address: None,
            commercial_modes: other.commercial_modes,
            physical_modes: other.physical_modes,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Autocomplete {
    #[serde(rename = "type")]
    format_type: String,
    geocoding: Geocoding,
    features: Vec<Feature>,
}

impl Autocomplete {
    pub fn new(q: String, features: Vec<Feature>) -> Autocomplete {
        // TODO couldn't we mode this function ? in Autocomplete ?
        Autocomplete {
            format_type: "FeatureCollection".to_string(),
            geocoding: Geocoding {
                version: "0.1.0".to_string(),
                query: Some(q),
            },
            features: features,
        }
    }
}

impl From<Vec<mimir::Place>> for Autocomplete {
    fn from(places: Vec<mimir::Place>) -> Autocomplete {
        Autocomplete::new(
            "".to_string(),
            places.into_iter().map(|p| Feature::from(p)).collect(),
        )
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Coord {
    pub lat: f64,
    pub lon: f64,
}

pub mod v1 {
    use mimir;
    use rs_es;

    // Note: I think this should be in api.rs but with the serde stuff it's easier for all
    // serde struct to be in the same file

    #[derive(Serialize, Deserialize, Debug)]
    pub struct EndPoint {
        pub description: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct CustomError {
        pub short: String,
        pub long: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub enum V1Reponse {
        Error(CustomError),
        Response { description: String },
    }
    #[derive(Debug)]
    pub enum AutocompleteResponse {
        Error(CustomError),
        Autocomplete(super::Autocomplete),
    }

    use serde;
    impl serde::Serialize for AutocompleteResponse {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            match self {
                &AutocompleteResponse::Autocomplete(ref a) => serializer.serialize_some(a),
                &AutocompleteResponse::Error(ref e) => serializer.serialize_some(e),
            }
        }
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Status {
        pub version: String,
        pub es: String,
        pub status: String,
    }

    impl From<Result<Vec<mimir::Place>, rs_es::error::EsError>> for AutocompleteResponse {
        fn from(r: Result<Vec<mimir::Place>, rs_es::error::EsError>) -> AutocompleteResponse {
            match r {
                Ok(places) => AutocompleteResponse::Autocomplete(super::Autocomplete::from(places)),
                Err(e) => AutocompleteResponse::Error(CustomError {
                    short: "query error".to_string(),
                    long: format!("invalid query {:?}", e),
                }),
            }
        }
    }
}
<|endoftext|>