<commit_before>use core::*;
use bitboard::*;
use moves::*;
use board::*;
use tables::*;

use std::collections::HashMap;

bitflags! {
    pub struct CastlingRights: u32 {
        const WHITE_KINGSIDE  = 0b0001;
        const WHITE_QUEENSIDE = 0b0010;
        const BLACK_KINGSIDE  = 0b0100;
        const BLACK_QUEENSIDE = 0b1000;
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Game {
    pub board: Board,
    pub to_move: Color,
    pub ep_square: Option<Square>,
    pub castling_rights: CastlingRights,
    pub fifty_move_count: u32,
    pub moves: u32
}

impl Game {
    pub fn starting_position() -> Game {
        Game {
            board: Board::starting_position(),
            to_move: Color::White,
            ep_square: None,
            castling_rights: CastlingRights::all(),
            fifty_move_count: 0,
            moves: 1,
        }
    }

    pub fn empty_position() -> Game {
        Game {
            board: Board::empty_position(),
            to_move: Color::White,
            ep_square: None,
            castling_rights: CastlingRights::empty(),
            fifty_move_count: 0,
            moves: 1
        }
    }

    pub fn from_fen(fen: &'static str) -> Option<Game> {
        let words: Vec<&str> = fen.split(' ').collect();

        if words.len() != 6 {
            return None;
        }

        let mut game = Game::empty_position();

        use PieceType::*;
        use Color::*;

        { // build up the game board
            let mut current_square: Square = Square::new(63);

            let decrement_square = |sq: &mut Square, n: u32| {
                if sq.unwrap() > 0 {
                    *sq = Square::new(sq.unwrap() - n);
                }
            };

            let mut add_piece = |color: Color, piece: PieceType, sq: &mut Square| {
                game.board.set_piece_bit(color, piece, *sq);
                decrement_square(sq, 1);
            };

            for ch in words[0].chars() {
                match ch {
                    'p' => add_piece(Black , Pawn   , &mut current_square) ,
                    'n' => add_piece(Black , Knight , &mut current_square) ,
                    'b' => add_piece(Black , Bishop , &mut current_square) ,
                    'r' => add_piece(Black , Rook   , &mut current_square) ,
                    'q' => add_piece(Black , Queen  , &mut current_square) ,
                    'k' => add_piece(Black , King   , &mut current_square) ,
                    'P' => add_piece(White , Pawn   , &mut current_square) ,
                    'N' => add_piece(White , Knight , &mut current_square) ,
                    'B' => add_piece(White , Bishop , &mut current_square) ,
                    'R' => add_piece(White , Rook   , &mut current_square) ,
                    'Q' => add_piece(White , Queen  , &mut current_square) ,
                    'K' => add_piece(White , King   , &mut current_square) ,
                    '1' => decrement_square(&mut current_square, 1),
                    '2' => decrement_square(&mut current_square, 2),
                    '3' => decrement_square(&mut current_square, 3),
                    '4' => decrement_square(&mut current_square, 4),
                    '5' => decrement_square(&mut current_square, 5),
                    '6' => decrement_square(&mut current_square, 6),
                    '7' => decrement_square(&mut current_square, 7),
                    '8' => decrement_square(&mut current_square, 8),
                    '/' => {},
                    _ => return None
                }
            }
        }

        match words[1] {
            "w" => game.to_move = White,
            "b" => game.to_move = Black,
            _ => return None
        }

        for ch in words[2].chars() {
            match ch {
                'K' => game.castling_rights |= CastlingRights::WHITE_KINGSIDE,
                'Q' => game.castling_rights |= CastlingRights::WHITE_QUEENSIDE,
                'k' => game.castling_rights |= CastlingRights::BLACK_KINGSIDE,
                'q' => game.castling_rights |= CastlingRights::BLACK_QUEENSIDE,
                '-' => {},
                _ => return None
            }
        }

        match words[3] {
            "-" => game.ep_square = None,
            _ => match Square::from_algebraic(words[3]) {
                None => return None,
                Some(sq) => game.ep_square = Some(sq)
            }
        }

        match words[4].parse::<u32>() {
            Err(_) => return None,
            Ok(x) => game.fifty_move_count = x
        }

        match words[5].parse::<u32>() {
            Err(_) => return None,
            Ok(x) => game.moves = x
        }

        return Some(game);
    }

    pub fn generate_moves(&self, move_buffer: &mut Vec<Move>) {
        move_buffer.clear();

        use Color::*;
        use PieceType::*;

        let friendly_color   = self.to_move;
        let opponent_color  = !friendly_color;

        let empty_squares   = self.board.unoccupied();
        let all_pieces      = self.board.occupied();
        let friendly_pieces = self.board.occupied_by(friendly_color);
        let opponent_pieces = self.board.occupied_by(!friendly_color);

        let king_square     = self.board.get_king_square(friendly_color);
        let king_attackers = self.board.attackers(king_square, opponent_color);
        let checkers = king_attackers.population();
        let in_check = checkers > 0;
        let king_moves = KING_TABLE[king_square.idx()];
        let king_danger_squares = self.board.attacked(!friendly_color, true);

        if checkers > 1 {
            for to in king_moves & empty_squares & !king_danger_squares {
                move_buffer.push(Move::new(king_square, to, QUIET_FLAG));
            }
            return;
        }

        let mut capture_mask = opponent_pieces;
        let mut quiet_mask = empty_squares;

        if checkers == 1 {
            capture_mask = king_attackers;

            let checker_square = king_attackers.bitscan_forward();
            if self.board.piece_at(checker_square).unwrap().ptype.is_slider() {
                quiet_mask = ray_between_squares(king_square, checker_square);
            } else {
                quiet_mask = Bitboard::new(0);
            }
        }

        let not_king_bit = !king_square.bitrep();

        let mut pinned_diagonally = Bitboard::new(0);
        let mut pinned_nondiagonally = Bitboard::new(0);
        {
            let opRQ = self.board.get_pieces(opponent_color, Rook) | self.board.get_pieces(opponent_color, Queen);
            let mut pinner = xray_rook_attacks(all_pieces, friendly_pieces, king_square) & opRQ;
            for pinner_square in pinner {
                let connecting_bits = ray_between_squares(king_square, pinner_square);
                let pinned_bit = connecting_bits & friendly_pieces;
                assert!(pinned_bit.population() == 1);
                pinned_nondiagonally |= pinned_bit;
            }

            let opBQ = self.board.get_pieces(opponent_color, Bishop) | self.board.get_pieces(opponent_color, Queen);
            pinner = xray_bishop_attacks(all_pieces, friendly_pieces, king_square) & opBQ;
            for pinner_square in pinner {
                let connecting_bits = ray_between_squares(king_square, pinner_square);
                let pinned_bit = connecting_bits & friendly_pieces;
                assert!(pinned_bit.population() == 1);
                pinned_diagonally |= pinned_bit;
            }
        }

        let pinned = pinned_diagonally | pinned_nondiagonally;

        // MOVE GENERATION FOR UNPINNED PIECES

        /*********/
        /* PAWNS */
        /*********/
        {
            let unpinned_pawns = self.board.get_pieces(friendly_color, Pawn) & !pinned;
            let advanced_pawns = if friendly_color == White { unpinned_pawns.shifted_up() } else { unpinned_pawns.shifted_down() };
            let double_advanced_pawns = if friendly_color == White { advanced_pawns.shifted_up() } else { advanced_pawns.shifted_down() };
            let delta_pawn_single_push: i32 = if self.to_move == White { -8 } else { 8 };
            let delta_pawn_double_push: i32 = if self.to_move == White { -16 } else { 16 };
            let double_pawn_push_rank = if self.to_move == White { RANK4 } else { RANK5 };
            let promotion_rank = if self.to_move == White { 8 } else { 1 };

            // single pushes (and promotions)
            for to in advanced_pawns & empty_squares & quiet_mask
            {
                let from = Square::new((to.unwrap() as i32 + delta_pawn_single_push) as u32);

                if to.rank() == promotion_rank {
                    move_buffer.push(Move::new(from, to, BISHOP_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, KNIGHT_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, ROOK_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, QUEEN_PROMO_FLAG));
                } else {
                    move_buffer.push(Move::new(from, to, QUIET_FLAG));
                }
            }

            // double pushes
            for to in double_advanced_pawns & empty_squares & double_pawn_push_rank & quiet_mask {

                let from = Square::new((to.unwrap() as i32 + delta_pawn_double_push) as u32);

                move_buffer.push(Move::new(from, to, DOUBLE_PAWN_PUSH_FLAG));
            }

            // captures (and capture-promotions)
            for from in unpinned_pawns
            {
                let pawn_attack_pattern = PAWN_ATTACKS[friendly_color as usize][from.idx()];
                let capturable_squares = match self.ep_square {
                    None => opponent_pieces,
                    Some(ep) => opponent_pieces | ep.bitrep()
                };

                for to in pawn_attack_pattern & capturable_squares & capture_mask
                {
                    if to.rank() == promotion_rank {
                        move_buffer.push(Move::new(from, to, BISHOP_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, KNIGHT_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, ROOK_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, QUEEN_PROMO_CAPTURE_FLAG));
                    } else if self.ep_square.is_some() && self.ep_square.unwrap() == to {
                        // TODO: test for discovered checks after ep capture!
                        move_buffer.push(Move::new(from, to, EP_CAPTURE_FLAG));
                    } else {
                        move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
                    }
                }
            }

        }

        /***********/
        /* KNIGHTS */
        /***********/
        {
            for from in self.board.get_pieces(friendly_color, Knight) & !pinned
            {
                let knight_moves = KNIGHT_TABLE[from.idx()];

                /* quiets */
                for to in knight_moves & empty_squares & quiet_mask {
                    move_buffer.push(Move::new(from, to, QUIET_FLAG));
                }

                /* captures */
                for to in knight_moves & opponent_pieces & capture_mask {
                    move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
                }
            }
        }

        /***********/
        /* BISHOPS */
        /***********/

        for from in self.board.get_pieces(friendly_color, Bishop) & !pinned
        {
            let bishop_moves = get_bishop_rays(from, all_pieces);

            /* quiets */
            for to in bishop_moves & empty_squares & quiet_mask {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in bishop_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /*********/
        /* ROOKS */
        /*********/

        for from in self.board.get_pieces(friendly_color, Rook) & !pinned
        {
            let rook_moves = get_rook_rays(from, all_pieces);

            /* quiets */
            for to in rook_moves & empty_squares & quiet_mask {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in rook_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /*********/
        /* QUEEN */
        /*********/

        for from in self.board.get_pieces(friendly_color, Queen) & !pinned
        {
            let queen_moves = get_queen_rays(from, all_pieces);

            /* quiets */
            for to in queen_moves & empty_squares {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in queen_moves & opponent_pieces {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /********/
        /* KING */
        /********/

        {
            /* quiets */
            for to in king_moves & empty_squares & !king_danger_squares {
                move_buffer.push(Move::new(king_square, to, QUIET_FLAG));
            }

            /* captures */
            for to in king_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(king_square, to, CAPTURE_FLAG));
            }

            /* castling */
            let has_kingside_castle_rights = self.castling_rights.intersects(CastlingRights::WHITE_KINGSIDE);
            let has_queenside_castle_rights = self.castling_rights.intersects(CastlingRights::WHITE_QUEENSIDE);

            if has_kingside_castle_rights && !in_check {
                let kingside_castle_path_open = (all_pieces & WHITE_KINGSIDE_CASTLE_BITS).empty();

                if kingside_castle_path_open {
                    let mut castle_path_is_safe: bool = true;

                    if (WHITE_KINGSIDE_CASTLE_BITS & king_danger_squares).nonempty() {
                        castle_path_is_safe = false;
                    }

                    if castle_path_is_safe {
                        move_buffer.push(Move::new(king_square, Square::new(1), KING_CASTLE_FLAG));
                    }
                }
            }

            if has_queenside_castle_rights && !in_check {
                let queenside_castle_path_open = (all_pieces & WHITE_QUEENSIDE_CASTLE_BITS).empty();

                if queenside_castle_path_open {
                    let mut castle_path_is_safe: bool = true;

                    if (WHITE_QUEENSIDE_CASTLE_BITS & king_danger_squares).nonempty() {
                        castle_path_is_safe = false;
                    }

                    if castle_path_is_safe {
                        move_buffer.push(Move::new(king_square, Square::new(5), QUEEN_CASTLE_FLAG));
                    }
                }
            }
        }
    }
}
<commit_msg>more streamlining of EP capture generation<commit_after>use core::*;
use bitboard::*;
use moves::*;
use board::*;
use tables::*;

use std::collections::HashMap;

bitflags! {
    pub struct CastlingRights: u32 {
        const WHITE_KINGSIDE  = 0b0001;
        const WHITE_QUEENSIDE = 0b0010;
        const BLACK_KINGSIDE  = 0b0100;
        const BLACK_QUEENSIDE = 0b1000;
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Game {
    pub board: Board,
    pub to_move: Color,
    pub ep_square: Option<Square>,
    pub castling_rights: CastlingRights,
    pub fifty_move_count: u32,
    pub moves: u32
}

impl Game {
    pub fn starting_position() -> Game {
        Game {
            board: Board::starting_position(),
            to_move: Color::White,
            ep_square: None,
            castling_rights: CastlingRights::all(),
            fifty_move_count: 0,
            moves: 1,
        }
    }

    pub fn empty_position() -> Game {
        Game {
            board: Board::empty_position(),
            to_move: Color::White,
            ep_square: None,
            castling_rights: CastlingRights::empty(),
            fifty_move_count: 0,
            moves: 1
        }
    }

    pub fn from_fen(fen: &'static str) -> Option<Game> {
        let words: Vec<&str> = fen.split(' ').collect();

        if words.len() != 6 {
            return None;
        }

        let mut game = Game::empty_position();

        use PieceType::*;
        use Color::*;

        { // build up the game board
            let mut current_square: Square = Square::new(63);

            let decrement_square = |sq: &mut Square, n: u32| {
                if sq.unwrap() > 0 {
                    *sq = Square::new(sq.unwrap() - n);
                }
            };

            let mut add_piece = |color: Color, piece: PieceType, sq: &mut Square| {
                game.board.set_piece_bit(color, piece, *sq);
                decrement_square(sq, 1);
            };

            for ch in words[0].chars() {
                match ch {
                    'p' => add_piece(Black , Pawn   , &mut current_square) ,
                    'n' => add_piece(Black , Knight , &mut current_square) ,
                    'b' => add_piece(Black , Bishop , &mut current_square) ,
                    'r' => add_piece(Black , Rook   , &mut current_square) ,
                    'q' => add_piece(Black , Queen  , &mut current_square) ,
                    'k' => add_piece(Black , King   , &mut current_square) ,
                    'P' => add_piece(White , Pawn   , &mut current_square) ,
                    'N' => add_piece(White , Knight , &mut current_square) ,
                    'B' => add_piece(White , Bishop , &mut current_square) ,
                    'R' => add_piece(White , Rook   , &mut current_square) ,
                    'Q' => add_piece(White , Queen  , &mut current_square) ,
                    'K' => add_piece(White , King   , &mut current_square) ,
                    '1' => decrement_square(&mut current_square, 1),
                    '2' => decrement_square(&mut current_square, 2),
                    '3' => decrement_square(&mut current_square, 3),
                    '4' => decrement_square(&mut current_square, 4),
                    '5' => decrement_square(&mut current_square, 5),
                    '6' => decrement_square(&mut current_square, 6),
                    '7' => decrement_square(&mut current_square, 7),
                    '8' => decrement_square(&mut current_square, 8),
                    '/' => {},
                    _ => return None
                }
            }
        }

        match words[1] {
            "w" => game.to_move = White,
            "b" => game.to_move = Black,
            _ => return None
        }

        for ch in words[2].chars() {
            match ch {
                'K' => game.castling_rights |= CastlingRights::WHITE_KINGSIDE,
                'Q' => game.castling_rights |= CastlingRights::WHITE_QUEENSIDE,
                'k' => game.castling_rights |= CastlingRights::BLACK_KINGSIDE,
                'q' => game.castling_rights |= CastlingRights::BLACK_QUEENSIDE,
                '-' => {},
                _ => return None
            }
        }

        match words[3] {
            "-" => game.ep_square = None,
            _ => match Square::from_algebraic(words[3]) {
                None => return None,
                Some(sq) => game.ep_square = Some(sq)
            }
        }

        match words[4].parse::<u32>() {
            Err(_) => return None,
            Ok(x) => game.fifty_move_count = x
        }

        match words[5].parse::<u32>() {
            Err(_) => return None,
            Ok(x) => game.moves = x
        }

        return Some(game);
    }

    pub fn generate_moves(&self, move_buffer: &mut Vec<Move>) {
        move_buffer.clear();

        use Color::*;
        use PieceType::*;

        let friendly_color   = self.to_move;
        let opponent_color  = !friendly_color;

        let empty_squares   = self.board.unoccupied();
        let all_pieces      = self.board.occupied();
        let friendly_pieces = self.board.occupied_by(friendly_color);
        let opponent_pieces = self.board.occupied_by(!friendly_color);

        let king_square     = self.board.get_king_square(friendly_color);
        let king_attackers = self.board.attackers(king_square, opponent_color);
        let checkers = king_attackers.population();
        let in_check = checkers > 0;
        let king_moves = KING_TABLE[king_square.idx()];
        let king_danger_squares = self.board.attacked(!friendly_color, true);

        if checkers > 1 {
            for to in king_moves & empty_squares & !king_danger_squares {
                move_buffer.push(Move::new(king_square, to, QUIET_FLAG));
            }
            return;
        }

        let mut capture_mask = opponent_pieces;
        let mut quiet_mask = empty_squares;

        if checkers == 1 {
            capture_mask = king_attackers;

            let checker_square = king_attackers.bitscan_forward();
            if self.board.piece_at(checker_square).unwrap().ptype.is_slider() {
                quiet_mask = ray_between_squares(king_square, checker_square);
            } else {
                quiet_mask = Bitboard::new(0);
            }
        }

        let not_king_bit = !king_square.bitrep();

        let mut pinned_diagonally = Bitboard::new(0);
        let mut pinned_nondiagonally = Bitboard::new(0);
        {
            let opRQ = self.board.get_pieces(opponent_color, Rook) | self.board.get_pieces(opponent_color, Queen);
            let mut pinner = xray_rook_attacks(all_pieces, friendly_pieces, king_square) & opRQ;
            for pinner_square in pinner {
                let connecting_bits = ray_between_squares(king_square, pinner_square);
                let pinned_bit = connecting_bits & friendly_pieces;
                assert!(pinned_bit.population() == 1);
                pinned_nondiagonally |= pinned_bit;
            }

            let opBQ = self.board.get_pieces(opponent_color, Bishop) | self.board.get_pieces(opponent_color, Queen);
            pinner = xray_bishop_attacks(all_pieces, friendly_pieces, king_square) & opBQ;
            for pinner_square in pinner {
                let connecting_bits = ray_between_squares(king_square, pinner_square);
                let pinned_bit = connecting_bits & friendly_pieces;
                assert!(pinned_bit.population() == 1);
                pinned_diagonally |= pinned_bit;
            }
        }

        let pinned = pinned_diagonally | pinned_nondiagonally;

        // MOVE GENERATION FOR UNPINNED PIECES

        /*********/
        /* PAWNS */
        /*********/
        {
            let unpinned_pawns = self.board.get_pieces(friendly_color, Pawn) & !pinned;
            let advanced_pawns = if friendly_color == White { unpinned_pawns.shifted_up() } else { unpinned_pawns.shifted_down() };
            let double_advanced_pawns = if friendly_color == White { advanced_pawns.shifted_up() } else { advanced_pawns.shifted_down() };
            let delta_pawn_single_push: i32 = if self.to_move == White { -8 } else { 8 };
            let delta_pawn_double_push: i32 = if self.to_move == White { -16 } else { 16 };
            let double_pawn_push_rank = if self.to_move == White { RANK4 } else { RANK5 };
            let promotion_rank = if self.to_move == White { 8 } else { 1 };

            // single pushes (and promotions)
            for to in advanced_pawns & empty_squares & quiet_mask
            {
                let from = Square::new((to.unwrap() as i32 + delta_pawn_single_push) as u32);

                if to.rank() == promotion_rank {
                    move_buffer.push(Move::new(from, to, BISHOP_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, KNIGHT_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, ROOK_PROMO_FLAG));
                    move_buffer.push(Move::new(from, to, QUEEN_PROMO_FLAG));
                } else {
                    move_buffer.push(Move::new(from, to, QUIET_FLAG));
                }
            }

            // double pushes
            for to in double_advanced_pawns & empty_squares & double_pawn_push_rank & quiet_mask {

                let from = Square::new((to.unwrap() as i32 + delta_pawn_double_push) as u32);

                move_buffer.push(Move::new(from, to, DOUBLE_PAWN_PUSH_FLAG));
            }

            // captures (and capture-promotions)
            for from in unpinned_pawns
            {
                let pawn_attack_pattern = PAWN_ATTACKS[friendly_color as usize][from.idx()] & capture_mask;

                for to in pawn_attack_pattern & opponent_pieces
                {
                    if to.rank() == promotion_rank {
                        move_buffer.push(Move::new(from, to, BISHOP_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, KNIGHT_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, ROOK_PROMO_CAPTURE_FLAG));
                        move_buffer.push(Move::new(from, to, QUEEN_PROMO_CAPTURE_FLAG));
                    } else {
                        move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
                    }
                }

                match self.ep_square {
                    Some(sq) => if (pawn_attack_pattern & sq.bitrep()).nonempty() {
                                    move_buffer.push(Move::new(from, sq, EP_CAPTURE_FLAG));
                                },
                    None => {}
                }
            }
        }

        /***********/
        /* KNIGHTS */
        /***********/
        {
            for from in self.board.get_pieces(friendly_color, Knight) & !pinned
            {
                let knight_moves = KNIGHT_TABLE[from.idx()];

                /* quiets */
                for to in knight_moves & empty_squares & quiet_mask {
                    move_buffer.push(Move::new(from, to, QUIET_FLAG));
                }

                /* captures */
                for to in knight_moves & opponent_pieces & capture_mask {
                    move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
                }
            }
        }

        /***********/
        /* BISHOPS */
        /***********/

        for from in self.board.get_pieces(friendly_color, Bishop) & !pinned
        {
            let bishop_moves = get_bishop_rays(from, all_pieces);

            /* quiets */
            for to in bishop_moves & empty_squares & quiet_mask {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in bishop_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /*********/
        /* ROOKS */
        /*********/

        for from in self.board.get_pieces(friendly_color, Rook) & !pinned
        {
            let rook_moves = get_rook_rays(from, all_pieces);

            /* quiets */
            for to in rook_moves & empty_squares & quiet_mask {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in rook_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /*********/
        /* QUEEN */
        /*********/

        for from in self.board.get_pieces(friendly_color, Queen) & !pinned
        {
            let queen_moves = get_queen_rays(from, all_pieces);

            /* quiets */
            for to in queen_moves & empty_squares {
                move_buffer.push(Move::new(from, to, QUIET_FLAG));
            }

            /* captures */
            for to in queen_moves & opponent_pieces {
                move_buffer.push(Move::new(from, to, CAPTURE_FLAG));
            }
        }

        /********/
        /* KING */
        /********/

        {
            /* quiets */
            for to in king_moves & empty_squares & !king_danger_squares {
                move_buffer.push(Move::new(king_square, to, QUIET_FLAG));
            }

            /* captures */
            for to in king_moves & opponent_pieces & capture_mask {
                move_buffer.push(Move::new(king_square, to, CAPTURE_FLAG));
            }

            /* castling */
            let has_kingside_castle_rights = self.castling_rights.intersects(CastlingRights::WHITE_KINGSIDE);
            let has_queenside_castle_rights = self.castling_rights.intersects(CastlingRights::WHITE_QUEENSIDE);

            if has_kingside_castle_rights && !in_check {
                let kingside_castle_path_open = (all_pieces & WHITE_KINGSIDE_CASTLE_BITS).empty();

                if kingside_castle_path_open {
                    let mut castle_path_is_safe: bool = true;

                    if (WHITE_KINGSIDE_CASTLE_BITS & king_danger_squares).nonempty() {
                        castle_path_is_safe = false;
                    }

                    if castle_path_is_safe {
                        move_buffer.push(Move::new(king_square, Square::new(1), KING_CASTLE_FLAG));
                    }
                }
            }

            if has_queenside_castle_rights && !in_check {
                let queenside_castle_path_open = (all_pieces & WHITE_QUEENSIDE_CASTLE_BITS).empty();

                if queenside_castle_path_open {
                    let mut castle_path_is_safe: bool = true;

                    if (WHITE_QUEENSIDE_CASTLE_BITS & king_danger_squares).nonempty() {
                        castle_path_is_safe = false;
                    }

                    if castle_path_is_safe {
                        move_buffer.push(Move::new(king_square, Square::new(5), QUEEN_CASTLE_FLAG));
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// This file is part of sokoban-rs
// Copyright 2015 Sébastien Watteau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

/// Represents a direction.
#[derive(Copy, Clone)]
pub enum Direction {
    /// Up
    Up,
    /// Down
    Down,
    /// Left
    Left,
    /// Right
    Right,
}

/// Represents a position in the world.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Position(i32, i32);

impl Position {
    /// Creates a new position with the given column and row.
    pub fn new(row: i32, col: i32) -> Position {
        Position(row, col)
    }

    /// Returns the position that is next to this one in the given direction.
    pub fn neighbor(&self, dir: Direction) -> Position {
        match dir {
            Direction::Up => Position(self.0 - 1, self.1),
            Direction::Down => Position(self.0 + 1, self.1),
            Direction::Left => Position(self.0, self.1 - 1),
            Direction::Right => Position(self.0, self.1 + 1),
        }
    }

    /// Returns the row number.
    pub fn row(&self) -> i32 {
        self.0
    }

    /// Returns the column number.
    pub fn column(&self) -> i32 {
        self.1
    }
}

/// Represents the state of the level.
#[derive(Clone)]
pub struct Level {
    /// The level's title
    title: String,
    /// The player's position
    player: Position,
    /// The current number of steps
    steps: i32,
    /// The positions of the walls
    walls: HashSet<Position>,
    /// The positions of the boxes
    boxes: HashSet<Position>,
    /// The positions of the squares
    squares: HashSet<Position>,
}

impl Level {
    /// Moves the player in the given direction if possible.
    pub fn step(&mut self, dir: Direction) {
        let next_to_player = self.player.neighbor(dir);
        if self.is_free(&next_to_player) {
            self.move_player(next_to_player);
        } else if self.is_box(&next_to_player) {
            let next_to_box = next_to_player.neighbor(dir);
            if self.is_free(&next_to_box) {
                self.move_box(&next_to_player, next_to_box);
                self.move_player(next_to_player);
            }
        }
    }

    /// Returns the current number of steps.
    pub fn get_steps(&self) -> i32 {
        self.steps
    }

    /// Returns true if the level is completed.
    pub fn is_completed(&self) -> bool {
        self.squares.difference(&self.boxes).count() == 0
    }

    /// Returns true if the given location is free.
    pub fn is_free(&self, pos: &Position) -> bool {
        !self.walls.contains(pos) && !self.boxes.contains(pos)
    }

    /// Returns true if there is a box at the given position.
    pub fn is_box(&self, pos: &Position) -> bool {
        self.boxes.contains(pos)
    }

    /// Returns true if the player is at the given position.
    pub fn is_player(&self, pos: &Position) -> bool {
        self.player == *pos
    }

    /// Returns true if there is a square at the given position.
    pub fn is_square(&self, pos: &Position) -> bool {
        self.squares.contains(pos)
    }

    /// returns true if there is a wall at the given position.
    pub fn is_wall(&self, pos: &Position) -> bool {
        self.walls.contains(pos)
    }

    /// Returns the number of columns and rows of this level.
    pub fn extents(&self) -> (i32, i32) {
        let (mut w, mut h) = (self.player.column(), self.player.row());
        for pos in self.walls.iter().chain(self.squares.iter()).chain(self.boxes.iter()) {
            if pos.column() > w {
                w = pos.column();
            }
            if pos.row() > h {
                h = pos.row();
            }
        }
        (w + 1, h + 1)
    }

    /// Returns the title
    pub fn title(&self) -> &str {
        &self.title
    }

    /// Changes the title
    pub fn set_title<S: Into<String>>(&mut self, title: S) {
        self.title = title.into();
    }

    /// moves the player to the given position.
    fn move_player(&mut self, pos: Position) {
        if pos != self.player {
            self.player = pos;
            self.steps += 1;
        }
    }

    /// moves a box from a position to another position.
    fn move_box(&mut self, from: &Position, to: Position) {
        if self.boxes.remove(from) {
            self.boxes.insert(to);
        }
    }
}

/// Represents an error due to reading an invalid character.
#[derive(Debug)]
pub struct InvalidChar(char, Position);

impl Display for InvalidChar {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let InvalidChar(c, pos) = *self;
        write!(f, "invalid character `{}' at row {}, column {}", c, pos.row(), pos.column())
    }
}

impl FromStr for Level {
    type Err = InvalidChar;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut level = Level {
            title: String::new(),
            player: Position(0, 0),
            steps: 0,
            walls: HashSet::new(),
            boxes: HashSet::new(),
            squares: HashSet::new(),
        };

        let (mut row, mut col) = (0, 0);
        for c in s.chars() {
            let pos = Position(row, col);
            match c {
                '\n' => {
                    row += 1;
                    col = -1;
                },
                '#' => {
                    level.walls.insert(pos);
                },
                '.' => {
                    level.squares.insert(pos);
                },
                '$' => {
                    level.boxes.insert(pos);
                },
                '@' => {
                    level.player = pos;
                },
                '+' => {
                    level.player = pos;
                    level.squares.insert(pos);
                },
                '*' => {
                    level.boxes.insert(pos);
                    level.squares.insert(pos);
                },
                ' ' => {},
                _ => {
                    return Err(InvalidChar(c, pos));
                }
            }
            col += 1;
        }

        Ok(level)
    }
}
<commit_msg>Calculate the extents of the level only once, at creation time<commit_after>// This file is part of sokoban-rs
// Copyright 2015 Sébastien Watteau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

/// Represents a direction.
#[derive(Copy, Clone)]
pub enum Direction {
    /// Up
    Up,
    /// Down
    Down,
    /// Left
    Left,
    /// Right
    Right,
}

/// Represents a position in the world.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Position(i32, i32);

impl Position {
    /// Creates a new position with the given column and row.
    pub fn new(row: i32, col: i32) -> Position {
        Position(row, col)
    }

    /// Returns the position that is next to this one in the given direction.
    pub fn neighbor(&self, dir: Direction) -> Position {
        match dir {
            Direction::Up => Position(self.0 - 1, self.1),
            Direction::Down => Position(self.0 + 1, self.1),
            Direction::Left => Position(self.0, self.1 - 1),
            Direction::Right => Position(self.0, self.1 + 1),
        }
    }

    /// Returns the row number.
    pub fn row(&self) -> i32 {
        self.0
    }

    /// Returns the column number.
    pub fn column(&self) -> i32 {
        self.1
    }
}

/// Represents the state of the level.
#[derive(Clone)]
pub struct Level {
    /// The level's title
    title: String,
    /// The player's position
    player: Position,
    /// The current number of steps
    steps: i32,
    /// The positions of the walls
    walls: HashSet<Position>,
    /// The positions of the boxes
    boxes: HashSet<Position>,
    /// The positions of the squares
    squares: HashSet<Position>,
    /// The number of columns and rows in the level
    extents: (i32, i32),
}

impl Level {
    /// Moves the player in the given direction if possible.
    pub fn step(&mut self, dir: Direction) {
        let next_to_player = self.player.neighbor(dir);
        if self.is_free(&next_to_player) {
            self.move_player(next_to_player);
        } else if self.is_box(&next_to_player) {
            let next_to_box = next_to_player.neighbor(dir);
            if self.is_free(&next_to_box) {
                self.move_box(&next_to_player, next_to_box);
                self.move_player(next_to_player);
            }
        }
    }

    /// Returns the current number of steps.
    pub fn get_steps(&self) -> i32 {
        self.steps
    }

    /// Returns true if the level is completed.
    pub fn is_completed(&self) -> bool {
        self.squares.difference(&self.boxes).count() == 0
    }

    /// Returns true if the given location is free.
    pub fn is_free(&self, pos: &Position) -> bool {
        !self.walls.contains(pos) && !self.boxes.contains(pos)
    }

    /// Returns true if there is a box at the given position.
    pub fn is_box(&self, pos: &Position) -> bool {
        self.boxes.contains(pos)
    }

    /// Returns true if the player is at the given position.
    pub fn is_player(&self, pos: &Position) -> bool {
        self.player == *pos
    }

    /// Returns true if there is a square at the given position.
    pub fn is_square(&self, pos: &Position) -> bool {
        self.squares.contains(pos)
    }

    /// returns true if there is a wall at the given position.
    pub fn is_wall(&self, pos: &Position) -> bool {
        self.walls.contains(pos)
    }

    /// Returns the number of columns and rows of this level.
    pub fn extents(&self) -> (i32, i32) {
        self.extents
    }

    /// Returns the title
    pub fn title(&self) -> &str {
        &self.title
    }

    /// Changes the title
    pub fn set_title<S: Into<String>>(&mut self, title: S) {
        self.title = title.into();
    }

    /// moves the player to the given position.
    fn move_player(&mut self, pos: Position) {
        if pos != self.player {
            self.player = pos;
            self.steps += 1;
        }
    }

    /// moves a box from a position to another position.
    fn move_box(&mut self, from: &Position, to: Position) {
        if self.boxes.remove(from) {
            self.boxes.insert(to);
        }
    }
}

/// Represents an error due to reading an invalid character.
#[derive(Debug)]
pub struct InvalidChar(char, Position);

impl Display for InvalidChar {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let InvalidChar(c, pos) = *self;
        write!(f, "invalid character `{}' at row {}, column {}", c, pos.row(), pos.column())
    }
}

impl FromStr for Level {
    type Err = InvalidChar;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut level = Level {
            title: String::new(),
            player: Position(0, 0),
            steps: 0,
            walls: HashSet::new(),
            boxes: HashSet::new(),
            squares: HashSet::new(),
            extents: (0, 0),
        };

        let (mut row, mut col) = (0, 0);
        for c in s.chars() {
            let pos = Position(row, col);
            match c {
                '\n' => {
                    row += 1;
                    col = -1;
                },
                '#' => {
                    level.walls.insert(pos);
                },
                '.' => {
                    level.squares.insert(pos);
                },
                '$' => {
                    level.boxes.insert(pos);
                },
                '@' => {
                    level.player = pos;
                },
                '+' => {
                    level.player = pos;
                    level.squares.insert(pos);
                },
                '*' => {
                    level.boxes.insert(pos);
                    level.squares.insert(pos);
                },
                ' ' => {},
                _ => {
                    return Err(InvalidChar(c, pos));
                }
            }
            col += 1;
        }

        // Calculate the extents of the level
        let (mut w, mut h) = (level.player.column(), level.player.row());
        for pos in level.walls.iter().chain(level.squares.iter()).chain(level.boxes.iter()) {
            if pos.column() > w {
                w = pos.column();
            }
            if pos.row() > h {
                h = pos.row();
            }
        }
        level.extents = (w + 1, h + 1);

        Ok(level)
    }
}
<|endoftext|>


<commit_before>extern crate libloading as libl;

use std::collections::HashMap;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_uint, c_void};

fn to_c_str<T: Into<Vec<u8>>>(t: T) -> *const c_char {
    CString::new(t).unwrap().as_ptr() as *const c_char
}

pub struct CoreClr {
    host_handle: *const c_void,
    domain_id: c_uint
}

pub type CoreClrInitializeFn = unsafe extern fn(
    *const c_char,
    *const c_char,
    c_int,
    *const *const c_char,
    *const *const c_char,
    *const *const c_void,
    *const c_uint) -> c_int;

impl CoreClr {
    pub fn init(
        exe_path: &str,
        app_domain_friendly_name: &str,
        properties_option: Option<HashMap<&str, &str>>) -> libl::Result<CoreClr>
    {
        let host_handle = 0 as *const c_void;
        let host_handle_ref = &host_handle as *const *const c_void;

        let domain_id = 0 as c_uint;
        let domain_id_ref = &domain_id as *const c_uint;

        let exe_path_raw = to_c_str(exe_path);
        let app_domain_friendly_name_raw = to_c_str(app_domain_friendly_name);

        let properties = properties_option.unwrap_or_else(HashMap::new);
        let properties_count = properties.len() as c_int;

        let properties_keys: Vec<*const c_char> = properties.keys()
                .map(|&k| to_c_str(k))
                .collect();

        let properties_values: Vec<*const c_char> = properties.values()
                .map(|&v| to_c_str(v))
                .collect();

        let properties_keys_ref = &properties_keys[0] as *const *const c_char;
        let properties_values_ref = &properties_values[0] as *const *const c_char;

        let coreclr_library = libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0")?;

        unsafe {
            let coreclr_initialize_fn: libl::Symbol<CoreClrInitializeFn> = coreclr_library.get(b"coreclr_initialize")?;

            assert_eq!(
                coreclr_initialize_fn(
                    exe_path_raw,
                    app_domain_friendly_name_raw,
                    properties_count,
                    properties_keys_ref,
                    properties_values_ref,
                    host_handle_ref,
                    domain_id_ref), 0);
        }

        Ok(CoreClr {
            host_handle: host_handle,
            domain_id: domain_id
        })
    }
}<commit_msg>Added consuming shutdown function<commit_after>extern crate libloading as libl;

use std::collections::HashMap;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_uint, c_void};

fn to_c_str<T: Into<Vec<u8>>>(t: T) -> *const c_char {
    CString::new(t).unwrap().as_ptr() as *const c_char
}

pub struct CoreClr {
    host_handle: *const c_void,
    domain_id: c_uint
}

pub type CoreClrInitializeFn = unsafe extern fn(
    *const c_char,
    *const c_char,
    c_int,
    *const *const c_char,
    *const *const c_char,
    *const *const c_void,
    *const c_uint) -> c_int;

pub type CoreClrShutdownFn = unsafe extern fn(*const c_void, c_uint);

impl CoreClr {
    pub fn init(
        exe_path: &str,
        app_domain_friendly_name: &str,
        properties_option: Option<HashMap<&str, &str>>) -> libl::Result<CoreClr>
    {
        let host_handle = 0 as *const c_void;
        let host_handle_ref = &host_handle as *const *const c_void;

        let domain_id = 0 as c_uint;
        let domain_id_ref = &domain_id as *const c_uint;

        let exe_path_raw = to_c_str(exe_path);
        let app_domain_friendly_name_raw = to_c_str(app_domain_friendly_name);

        let properties = properties_option.unwrap_or_else(HashMap::new);
        let properties_count = properties.len() as c_int;

        let properties_keys: Vec<*const c_char> = properties.keys()
                .map(|&k| to_c_str(k))
                .collect();

        let properties_values: Vec<*const c_char> = properties.values()
                .map(|&v| to_c_str(v))
                .collect();

        let properties_keys_ref = &properties_keys[0] as *const *const c_char;
        let properties_values_ref = &properties_values[0] as *const *const c_char;

        let coreclr_library = libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0")?;

        unsafe {
            let coreclr_initialize_fn: libl::Symbol<CoreClrInitializeFn> = coreclr_library.get(b"coreclr_initialize")?;

            assert_eq!(
                coreclr_initialize_fn(
                    exe_path_raw,
                    app_domain_friendly_name_raw,
                    properties_count,
                    properties_keys_ref,
                    properties_values_ref,
                    host_handle_ref,
                    domain_id_ref), 0);
        }

        Ok(CoreClr {
            host_handle: host_handle,
            domain_id: domain_id
        })
    }

    pub fn shutdown(self: Self) -> libl::Result<()> {
        let coreclr_library = libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0")?;

        unsafe {
            let coreclr_shutdown_fn: libl::Symbol<CoreClrShutdownFn> = coreclr_library.get(b"coreclr_shutdown")?;
            assert_eq!(coreclr_shutdown_fn(self.host_handle, self.domain_id), 0)
        }

        Ok(())
    }
}<|endoftext|>


<commit_before>use gigasecond;

use chrono::{TimeZone, Utc};

#[test]
fn test_date() {
    let start_date = Utc.ymd(2011, 4, 25).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2043, 1, 1).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_another_date() {
    let start_date = Utc.ymd(1977, 6, 13).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2009, 2, 19).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_third_date() {
    let start_date = Utc.ymd(1959, 7, 19).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(1991, 3, 27).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_datetime() {
    let start_date = Utc.ymd(2015, 1, 24).and_hms(22, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2046, 10, 2).and_hms(23, 46, 40)
    );
}

#[test]
#[ignore]
fn test_another_datetime() {
    let start_date = Utc.ymd(2015, 1, 24).and_hms(23, 59, 59);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2046, 10, 3).and_hms(1, 46, 39)
    );
}
<commit_msg>gigasecond: Remove no-op import from tests (#955)<commit_after>use chrono::{TimeZone, Utc};

#[test]
fn test_date() {
    let start_date = Utc.ymd(2011, 4, 25).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2043, 1, 1).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_another_date() {
    let start_date = Utc.ymd(1977, 6, 13).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2009, 2, 19).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_third_date() {
    let start_date = Utc.ymd(1959, 7, 19).and_hms(0, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(1991, 3, 27).and_hms(1, 46, 40)
    );
}

#[test]
#[ignore]
fn test_datetime() {
    let start_date = Utc.ymd(2015, 1, 24).and_hms(22, 0, 0);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2046, 10, 2).and_hms(23, 46, 40)
    );
}

#[test]
#[ignore]
fn test_another_datetime() {
    let start_date = Utc.ymd(2015, 1, 24).and_hms(23, 59, 59);

    assert_eq!(
        gigasecond::after(start_date),
        Utc.ymd(2046, 10, 3).and_hms(1, 46, 39)
    );
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015 The Robigalia Project Developers
 * Licensed under the Apache License, Version 2.0
 * <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT
 * license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
 * at your option. All files in the project carrying such
 * notice may not be copied, modified, or distributed except
 * according to those terms.
 */
#![no_std]
#![feature(asm)]
#![feature(thread_local)]
#![allow(bad_style, unused_parens, unused_assignments)]

// NB: this mimics the logic in build.rs
#[cfg(not(any(
    all(target_arch = "arm", target_pointer_width = "32"),
    all(target_arch = "riscv32"),
    all(target_arch = "x86"),
    all(target_arch = "x86_64"),
)))]
use architecture_not_supported_sorry;

pub use seL4_BreakpointAccess::*;
pub use seL4_BreakpointType::*;
pub use seL4_Error::*;
pub use seL4_LookupFailureType::*;
pub use seL4_ObjectType::*;

use core::mem::size_of;

// XXX: These can't be repr(C), but it needs to "match an int" according to the comments on
// SEL4_FORCE_LONG_ENUM. There's no single type that matches in Rust, so it needs to be
// per-architecture. We use a macro to define them all in one whack, with the invoker providing
// only what the size of the enums ought to be. Each arch then invokes it.
macro_rules! error_types {
    ($int_width:ident) => {
        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_Error {
            seL4_NoError = 0,
            seL4_InvalidArgument,
            seL4_InvalidCapability,
            seL4_IllegalOperation,
            seL4_RangeError,
            seL4_AlignmentError,
            seL4_FailedLookup,
            seL4_TruncatedMessage,
            seL4_DeleteFirst,
            seL4_RevokeFirst,
            seL4_NotEnoughMemory,
            // XXX: Code depends on this being the last variant
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_LookupFailureType {
            seL4_NoFailure = 0,
            seL4_InvalidRoot,
            seL4_MissingCapability,
            seL4_DepthMismatch,
            seL4_GuardMismatch,
            // XXX: Code depends on this being the last variant
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_BreakpointType {
            seL4_DataBreakpoint = 0,
            seL4_InstructionBreakpoint,
            seL4_SingleStep,
            seL4_SoftwareBreakRequest,
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_BreakpointAccess {
            seL4_BreakOnRead = 0,
            seL4_BreakOnWrite,
            seL4_BreakOnReadWrite,
        }
    };
}

pub type seL4_Word = usize;
pub type seL4_CPtr = usize;

#[cfg(target_arch = "x86")]
include!("arch/x86.rs");

#[cfg(target_arch = "x86_64")]
include!("arch/x86_64.rs");

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!("arch/arm.rs");

#[cfg(target_arch = "riscv32")]
include!("arch/riscv.rs");

#[cfg(all(target_arch = "x86"))]
include!(concat!(env!("OUT_DIR"), "/ia32_invocation.rs"));

#[cfg(all(target_arch = "x86_64"))]
include!(concat!(env!("OUT_DIR"), "/x86_64_invocation.rs"));

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!(concat!(env!("OUT_DIR"), "/aarch32_invocation.rs"));

#[cfg(target_arch = "riscv32")]
include!(concat!(env!("OUT_DIR"), "/riscv32_invocation.rs"));

#[cfg(all(target_arch = "x86"))]
include!(concat!(env!("OUT_DIR"), "/ia32_syscall_stub.rs"));

#[cfg(all(target_arch = "x86_64"))]
include!(concat!(env!("OUT_DIR"), "/x86_64_syscall_stub.rs"));

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!(concat!(env!("OUT_DIR"), "/aarch32_syscall_stub.rs"));

#[cfg(target_arch = "riscv32")]
include!(concat!(env!("OUT_DIR"), "/riscv32_syscall_stub.rs"));

#[cfg(target_pointer_width = "32")]
include!(concat!(env!("OUT_DIR"), "/types32.rs"));

#[cfg(target_pointer_width = "64")]
include!(concat!(env!("OUT_DIR"), "/types64.rs"));

include!(concat!(env!("OUT_DIR"), "/syscalls.rs"));

// Well-known types from libsel4/include/sel4/types.h

pub type seL4_NodeId = seL4_Word;
pub type seL4_PAddr = seL4_Word;
pub type seL4_Domain = seL4_Word;

pub type seL4_CNode = seL4_CPtr;
pub type seL4_IRQHandler = seL4_CPtr;
pub type seL4_IRQControl = seL4_CPtr;
pub type seL4_TCB = seL4_CPtr;
pub type seL4_Untyped = seL4_CPtr;
pub type seL4_DomainSet = seL4_CPtr;
pub type seL4_SchedContext = seL4_CPtr;
pub type seL4_SchedControl = seL4_CPtr;

// TODO(sleffler): seL4 uses seL4_Uint64 but it's not defined for us
pub type seL4_Time = u64;

pub const seL4_MsgLengthBits: usize = 7;
pub const seL4_MsgMaxLength: usize = 120;
pub const seL4_MsgExtraCapBits: usize = 2;
pub const seL4_MsgMaxExtraCaps: usize = (1usize << seL4_MsgExtraCapBits) - 1;

#[derive(Copy, Debug)]
/// Buffer used to store received IPC messages
pub struct seL4_IPCBuffer {
    /// Message tag
    ///
    /// The kernel does not initialize this.
    pub tag: seL4_MessageInfo,
    /// Message contents
    ///
    /// The kernel only initializes the bytes which were not able to fit into physical registers.
    pub msg: [seL4_Word; seL4_MsgMaxLength],
    /// Arbitrary user data.
    ///
    /// The seL4 C libraries expect this to be a pointer to the IPC buffer in the thread's VSpace.,
    /// but this doesn't really matter.
    pub userData: seL4_Word,
    /// Capabilities to transfer (if sending) or unwrapped badges
    pub caps_or_badges: [seL4_Word; seL4_MsgMaxExtraCaps],
    /// CPtr to a CNode in the thread's CSpace from which to find the receive slot
    pub receiveCNode: seL4_CPtr,
    /// CPtr to the receive slot, relative to receiveCNode
    pub receiveIndex: seL4_CPtr,
    /// Number of bits of receiveIndex to use
    pub receiveDepth: seL4_Word,
}

impl ::core::clone::Clone for seL4_IPCBuffer {
    fn clone(&self) -> Self {
        *self
    }
}

/* bootinfo */

pub static seL4_CapNull: seL4_Word = 0; /* null cap */
pub static seL4_CapInitThreadTCB: seL4_Word = 1; /* initial thread's TCB cap */
pub static seL4_CapInitThreadCNode: seL4_Word = 2; /* initial thread's root CNode cap */
pub static seL4_CapInitThreadVSpace: seL4_Word = 3; /* initial thread's VSpace cap */
pub static seL4_CapIRQControl: seL4_Word = 4; /* global IRQ controller cap */
pub static seL4_CapASIDControl: seL4_Word = 5; /* global ASID controller cap */
pub static seL4_CapInitThreadASIDPool: seL4_Word = 6; /* initial thread's ASID pool cap */
pub static seL4_CapIOPort: seL4_Word = 7; /* global IO port cap (null cap if not supported) */
pub static seL4_CapIOSpace: seL4_Word = 8; /* global IO space cap (null cap if no IOMMU support) */
pub static seL4_CapBootInfoFrame: seL4_Word = 9; /* bootinfo frame cap */
pub static seL4_CapInitThreadIPCBuffer: seL4_Word = 10; /* initial thread's IPC buffer frame cap */
pub static seL4_CapDomain: seL4_Word = 11; /* global domain controller cap */

#[repr(C, packed)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// A half-open [start..end) range of slots
pub struct seL4_SlotRegion {
    /// First CNode slot position of the region
    pub start: seL4_Word,
    /// First CNode slot position after the region
    pub end: seL4_Word, /* first CNode slot position AFTER region */
}

#[repr(C, packed)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct seL4_UntypedDesc {
    /// Physical address corresponding of the untyped object's backing memory
    pub paddr: seL4_Word,
    pub padding1: u8,
    pub padding2: u8,
    /// log2 size of the region of memory backing the untyped object
    pub sizeBits: u8,
    /// Whether the backing memory corresponds to some device memory
    pub isDevice: u8,
}

// explicitly *not* Copy. the array at the end is tricky to handle.

#[repr(C, packed)]
// #[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
//#[derive(Debug, PartialEq, Eq)]
pub struct seL4_BootInfo {
    /// Length of any additional bootinfo information
    pub extraLen: seL4_Word,
    /// ID [0..numNodes-1] of the current node (0 if uniprocessor)
    pub nodeID: seL4_Word,
    /// Number of seL4 nodes (1 if uniprocessor)
    pub numNodes: seL4_Word,
    /// Number of IOMMU PT levels (0 if no IOMMU support)
    pub numIOPTLevels: seL4_Word,
    /// pointer to root task's IPC buffer */
    pub ipcBuffer: *mut seL4_IPCBuffer,
    /// Empty slots (null caps)
    pub empty: seL4_SlotRegion,
    /// Frames shared between nodes
    pub sharedFrames: seL4_SlotRegion,
    /// Frame caps used for the loaded ELF image of the root task
    pub userImageFrames: seL4_SlotRegion,
    /// PD caps used for the loaded ELF image of the root task
    pub userImagePaging: seL4_SlotRegion,
    /// IOSpace caps for ARM SMMU
    pub ioSpaceCaps: seL4_SlotRegion,
    /// Caps fr anypages used to back the additional bootinfo information
    pub extraBIPages: seL4_SlotRegion,
    /// log2 size of root task's CNode
    pub initThreadCNodeSizeBits: u8,
    /// Root task's domain ID
    pub initThreadDomain: u32,

    #[cfg(feature = "SEL4_CONFIG_KERNEL_MCS")]
    // Caps to sched_control for each node
    pub schedcontrol: seL4_SlotRegion,

    /// Untyped object caps
    pub untyped: seL4_SlotRegion,
    /// Information about each untyped cap
    ///
    /// *Note*! This is actually an array! The actual length depends on kernel configuration which
    /// we have no way of knowing at this point. Use the `untyped_descs` method.
    pub untypedList: seL4_UntypedDesc,
}

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct seL4_BootInfoHeader {
    /// Identifier of the following chunk
    pub id: seL4_Word,
    /// Length of the chunk
    pub len: seL4_Word,
}

impl seL4_BootInfo {
    /// This is safe if you don't mutate the `untyped` field and corrupt its length.
    pub unsafe fn untyped_descs(&self) -> &[seL4_UntypedDesc] {
        let len = self.untyped.end - self.untyped.start;
        // sanity check that the number of untypeds doesn't extend past the end of the page
        debug_assert!(
            len <= (4096 - size_of::<seL4_BootInfo>() + size_of::<seL4_UntypedDesc>())
                / size_of::<seL4_UntypedDesc>()
        );
        core::slice::from_raw_parts(&self.untypedList, len)
    }
}
<commit_msg>sel4-sys: root thread slot assignments are const, not static<commit_after>/* Copyright (c) 2015 The Robigalia Project Developers
 * Licensed under the Apache License, Version 2.0
 * <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT
 * license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
 * at your option. All files in the project carrying such
 * notice may not be copied, modified, or distributed except
 * according to those terms.
 */
#![no_std]
#![feature(asm)]
#![feature(thread_local)]
#![allow(bad_style, unused_parens, unused_assignments)]

// NB: this mimics the logic in build.rs
#[cfg(not(any(
    all(target_arch = "arm", target_pointer_width = "32"),
    all(target_arch = "riscv32"),
    all(target_arch = "x86"),
    all(target_arch = "x86_64"),
)))]
use architecture_not_supported_sorry;

pub use seL4_BreakpointAccess::*;
pub use seL4_BreakpointType::*;
pub use seL4_Error::*;
pub use seL4_LookupFailureType::*;
pub use seL4_ObjectType::*;

use core::mem::size_of;

// XXX: These can't be repr(C), but it needs to "match an int" according to the comments on
// SEL4_FORCE_LONG_ENUM. There's no single type that matches in Rust, so it needs to be
// per-architecture. We use a macro to define them all in one whack, with the invoker providing
// only what the size of the enums ought to be. Each arch then invokes it.
macro_rules! error_types {
    ($int_width:ident) => {
        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_Error {
            seL4_NoError = 0,
            seL4_InvalidArgument,
            seL4_InvalidCapability,
            seL4_IllegalOperation,
            seL4_RangeError,
            seL4_AlignmentError,
            seL4_FailedLookup,
            seL4_TruncatedMessage,
            seL4_DeleteFirst,
            seL4_RevokeFirst,
            seL4_NotEnoughMemory,
            // XXX: Code depends on this being the last variant
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_LookupFailureType {
            seL4_NoFailure = 0,
            seL4_InvalidRoot,
            seL4_MissingCapability,
            seL4_DepthMismatch,
            seL4_GuardMismatch,
            // XXX: Code depends on this being the last variant
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_BreakpointType {
            seL4_DataBreakpoint = 0,
            seL4_InstructionBreakpoint,
            seL4_SingleStep,
            seL4_SoftwareBreakRequest,
        }

        #[repr($int_width)]
        #[derive(Debug, Copy, Clone, PartialEq, Eq)]
        pub enum seL4_BreakpointAccess {
            seL4_BreakOnRead = 0,
            seL4_BreakOnWrite,
            seL4_BreakOnReadWrite,
        }
    };
}

// NB: potentially arch-dependent
pub type seL4_Word = usize;
pub type seL4_CPtr = usize;

#[cfg(target_arch = "x86")]
include!("arch/x86.rs");

#[cfg(target_arch = "x86_64")]
include!("arch/x86_64.rs");

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!("arch/arm.rs");

#[cfg(target_arch = "riscv32")]
include!("arch/riscv.rs");

#[cfg(all(target_arch = "x86"))]
include!(concat!(env!("OUT_DIR"), "/ia32_invocation.rs"));

#[cfg(all(target_arch = "x86_64"))]
include!(concat!(env!("OUT_DIR"), "/x86_64_invocation.rs"));

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!(concat!(env!("OUT_DIR"), "/aarch32_invocation.rs"));

#[cfg(target_arch = "riscv32")]
include!(concat!(env!("OUT_DIR"), "/riscv32_invocation.rs"));

#[cfg(all(target_arch = "x86"))]
include!(concat!(env!("OUT_DIR"), "/ia32_syscall_stub.rs"));

#[cfg(all(target_arch = "x86_64"))]
include!(concat!(env!("OUT_DIR"), "/x86_64_syscall_stub.rs"));

#[cfg(all(target_arch = "arm", target_pointer_width = "32"))]
include!(concat!(env!("OUT_DIR"), "/aarch32_syscall_stub.rs"));

#[cfg(target_arch = "riscv32")]
include!(concat!(env!("OUT_DIR"), "/riscv32_syscall_stub.rs"));

#[cfg(target_pointer_width = "32")]
include!(concat!(env!("OUT_DIR"), "/types32.rs"));

#[cfg(target_pointer_width = "64")]
include!(concat!(env!("OUT_DIR"), "/types64.rs"));

include!(concat!(env!("OUT_DIR"), "/syscalls.rs"));

// Well-known types from libsel4/include/sel4/types.h

pub type seL4_NodeId = seL4_Word;
pub type seL4_PAddr = seL4_Word;
pub type seL4_Domain = seL4_Word;

pub type seL4_CNode = seL4_CPtr;
pub type seL4_IRQHandler = seL4_CPtr;
pub type seL4_IRQControl = seL4_CPtr;
pub type seL4_TCB = seL4_CPtr;
pub type seL4_Untyped = seL4_CPtr;
pub type seL4_DomainSet = seL4_CPtr;
pub type seL4_SchedContext = seL4_CPtr;
pub type seL4_SchedControl = seL4_CPtr;

// TODO(sleffler): seL4 uses seL4_Uint64 but it's not defined for us
pub type seL4_Time = u64;

pub const seL4_MsgLengthBits: usize = 7;
pub const seL4_MsgMaxLength: usize = 120;
pub const seL4_MsgExtraCapBits: usize = 2;
pub const seL4_MsgMaxExtraCaps: usize = (1usize << seL4_MsgExtraCapBits) - 1;

#[derive(Copy, Debug)]
/// Buffer used to store received IPC messages
pub struct seL4_IPCBuffer {
    /// Message tag
    ///
    /// The kernel does not initialize this.
    pub tag: seL4_MessageInfo,
    /// Message contents
    ///
    /// The kernel only initializes the bytes which were not able to fit into physical registers.
    pub msg: [seL4_Word; seL4_MsgMaxLength],
    /// Arbitrary user data.
    ///
    /// The seL4 C libraries expect this to be a pointer to the IPC buffer in the thread's VSpace.,
    /// but this doesn't really matter.
    pub userData: seL4_Word,
    /// Capabilities to transfer (if sending) or unwrapped badges
    pub caps_or_badges: [seL4_Word; seL4_MsgMaxExtraCaps],
    /// CPtr to a CNode in the thread's CSpace from which to find the receive slot
    pub receiveCNode: seL4_CPtr,
    /// CPtr to the receive slot, relative to receiveCNode
    pub receiveIndex: seL4_CPtr,
    /// Number of bits of receiveIndex to use
    pub receiveDepth: seL4_Word,
}

impl ::core::clone::Clone for seL4_IPCBuffer {
    fn clone(&self) -> Self {
        *self
    }
}

// Bootinfo

// Fixed cap slots for root thread.
pub const seL4_CapNull: seL4_Word = 0; // null cap
pub const seL4_CapInitThreadTCB: seL4_Word = 1; // initial thread's TCB
pub const seL4_CapInitThreadCNode: seL4_Word = 2; // initial thread's root CNode
pub const seL4_CapInitThreadVSpace: seL4_Word = 3; // initial thread's VSpace
pub const seL4_CapIRQControl: seL4_Word = 4; // global IRQ controller
pub const seL4_CapASIDControl: seL4_Word = 5; // global ASID controller
pub const seL4_CapInitThreadASIDPool: seL4_Word = 6; // initial thread's ASID pool
pub const seL4_CapIOPort: seL4_Word = 7; // global IO port (null if not supported)
pub const seL4_CapIOSpace: seL4_Word = 8; // global IO space (null if no IOMMU support)
pub const seL4_CapBootInfoFrame: seL4_Word = 9; // bootinfo frame
pub const seL4_CapInitThreadIPCBuffer: seL4_Word = 10; // initial thread's IPC buffer frame
pub const seL4_CapDomain: seL4_Word = 11; // global domain controller

#[repr(C, packed)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// A half-open [start..end) range of slots
pub struct seL4_SlotRegion {
    /// First CNode slot position of the region
    pub start: seL4_Word,
    /// First CNode slot position after the region
    pub end: seL4_Word, /* first CNode slot position AFTER region */
}

#[repr(C, packed)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct seL4_UntypedDesc {
    /// Physical address corresponding of the untyped object's backing memory
    pub paddr: seL4_Word,
    pub padding1: u8,
    pub padding2: u8,
    /// log2 size of the region of memory backing the untyped object
    pub sizeBits: u8,
    /// Whether the backing memory corresponds to some device memory
    pub isDevice: u8,
}

// explicitly *not* Copy. the array at the end is tricky to handle.

#[repr(C, packed)]
// #[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
//#[derive(Debug, PartialEq, Eq)]
pub struct seL4_BootInfo {
    /// Length of any additional bootinfo information
    pub extraLen: seL4_Word,
    /// ID [0..numNodes-1] of the current node (0 if uniprocessor)
    pub nodeID: seL4_Word,
    /// Number of seL4 nodes (1 if uniprocessor)
    pub numNodes: seL4_Word,
    /// Number of IOMMU PT levels (0 if no IOMMU support)
    pub numIOPTLevels: seL4_Word,
    /// pointer to root task's IPC buffer */
    pub ipcBuffer: *mut seL4_IPCBuffer,
    /// Empty slots (null caps)
    pub empty: seL4_SlotRegion,
    /// Frames shared between nodes
    pub sharedFrames: seL4_SlotRegion,
    /// Frame caps used for the loaded ELF image of the root task
    pub userImageFrames: seL4_SlotRegion,
    /// PD caps used for the loaded ELF image of the root task
    pub userImagePaging: seL4_SlotRegion,
    /// IOSpace caps for ARM SMMU
    pub ioSpaceCaps: seL4_SlotRegion,
    /// Caps fr anypages used to back the additional bootinfo information
    pub extraBIPages: seL4_SlotRegion,
    /// log2 size of root task's CNode
    pub initThreadCNodeSizeBits: u8,
    /// Root task's domain ID
    pub initThreadDomain: u32,

    #[cfg(feature = "SEL4_CONFIG_KERNEL_MCS")]
    // Caps to sched_control for each node
    pub schedcontrol: seL4_SlotRegion,

    /// Untyped object caps
    pub untyped: seL4_SlotRegion,
    /// Information about each untyped cap
    ///
    /// *Note*! This is actually an array! The actual length depends on kernel configuration which
    /// we have no way of knowing at this point. Use the `untyped_descs` method.
    pub untypedList: seL4_UntypedDesc,
}

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct seL4_BootInfoHeader {
    /// Identifier of the following chunk
    pub id: seL4_Word,
    /// Length of the chunk
    pub len: seL4_Word,
}

impl seL4_BootInfo {
    /// This is safe if you don't mutate the `untyped` field and corrupt its length.
    pub unsafe fn untyped_descs(&self) -> &[seL4_UntypedDesc] {
        let len = self.untyped.end - self.untyped.start;
        // sanity check that the number of untypeds doesn't extend past the end of the page
        debug_assert!(
            len <= (4096 - size_of::<seL4_BootInfo>() + size_of::<seL4_UntypedDesc>())
                / size_of::<seL4_UntypedDesc>()
        );
        core::slice::from_raw_parts(&self.untypedList, len)
    }
}
<|endoftext|>


<commit_before>//! Coredump implementation of the Space API server.
//!
//! Start this via the commandline:
//!
//!     ./coredump_status [-p PORT] [-i IP]
extern crate env_logger;
extern crate docopt;
extern crate rustc_serialize;
extern crate spaceapi_server;

mod utils;

use std::env;
use docopt::Docopt;
use spaceapi_server::SpaceapiServer;
use spaceapi_server::api;
use spaceapi_server::modifiers::StateFromPeopleNowPresent;
use spaceapi_server::api::sensors::{TemperatureSensorTemplate, PeopleNowPresentSensorTemplate};
use spaceapi_server::api::Optional::{Value, Absent};
use utils::Ipv4;

static USAGE: &'static str = "
Usage: coredump_status [-p PORT] [-i IP]

Options:
    -p PORT  The port to listen on [default: 3000].
    -i IP    The ipv4 address to listen on [default: 127.0.0.1].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: Ipv4,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    env_logger::init().unwrap();

    // Parse arguments
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    let host = args.flag_i.ip;
    let port = args.flag_p;

    // Create new Status instance
    let mut status = api::Status::new(
        "coredump",
        "https://www.coredump.ch/logo.png",
        "https://www.coredump.ch/",
        api::Location {
            address: Value("Zürcherstrasse 6, 8640 Rapperswil, Switzerland".into()),
            lat: 47.22939,
            lon: 8.82041,
        },
        api::Contact {
            irc: Value("irc://freenode.net/#coredump".into()),
            twitter: Value("@coredump_ch".into()),
            email: Value("vorstand@lists.coredump.ch".into()),
            phone: Absent,
            sip: Absent,
            keymasters: Absent,
            facebook: Absent,
            google: Absent,
            identica: Absent,
            foursquare: Absent,
            ml: Absent,
            jabber: Absent,
            issue_mail: Absent,
        },
        vec![
            "email".into(),
            "twitter".into(),
        ],
    );

    // Add optional data
    status.spacefed = Value(api::Spacefed {
        spacenet: false,
        spacesaml: false,
        spacephone: false,
    });
    status.feeds = Value(api::Feeds {
        blog: Value(api::Feed {
            _type: Value("rss".into()),
            url: "https://www.coredump.ch/feed/".into(),
        }),
        wiki: Absent,
        calendar: Absent,
        flickr: Absent,
    });
    status.projects = Value(vec![
        "https://www.coredump.ch/projekte/".into(),
        "https://forum.coredump.ch/c/projects".into(),
        "https://github.com/coredump-ch/".into(),
    ]);
    status.cam = Value(vec![
        "https://webcam.coredump.ch/cams/ultimaker_0.jpg".into(),
    ]);
    status.state.message = Value("Open Mondays from 20:00".into());

    // Redis connection info
    let redis_host: String = env::var("REDIS_HOST")
        .unwrap_or("127.0.0.1".to_string());
    let redis_port: u16 = env::var("REDIS_PORT")
        .unwrap_or("6379".to_string()).parse().unwrap_or(6379);
    let redis_db: i64 = env::var("REDIS_DB")
        .unwrap_or("0".to_string()).parse().unwrap_or(0);
    let redis_url = format!("redis://{}:{}/{}", redis_host, redis_port, redis_db);

    // Set up server
    let mut server = SpaceapiServer::new((host, port), status, &*redis_url,
                                         vec![Box::new(StateFromPeopleNowPresent)])
                         .expect("Could not initialize server");

    // Register sensors
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".into(),
        location: "Hackerspace".into(),
        name: Value("Raspberry CPU".into()),
        description: Absent,
    }), "temperature_raspi".into());
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".into(),
        location: "Hackerspace".into(),
        name: Value("Room Temperature".into()),
        description: Absent,
    }), "temperature_room".into());
    server.register_sensor(Box::new(PeopleNowPresentSensorTemplate {
        location: Value("Hackerspace".into()),
        name: Absent,
        description: Absent,
        names: Absent,
    }), "people_now_present".into());

    // Serve!
    server.serve().expect("Could not start the server");
}
<commit_msg>Update logo url (#105)<commit_after>//! Coredump implementation of the Space API server.
//!
//! Start this via the commandline:
//!
//!     ./coredump_status [-p PORT] [-i IP]
extern crate env_logger;
extern crate docopt;
extern crate rustc_serialize;
extern crate spaceapi_server;

mod utils;

use std::env;
use docopt::Docopt;
use spaceapi_server::SpaceapiServer;
use spaceapi_server::api;
use spaceapi_server::modifiers::StateFromPeopleNowPresent;
use spaceapi_server::api::sensors::{TemperatureSensorTemplate, PeopleNowPresentSensorTemplate};
use spaceapi_server::api::Optional::{Value, Absent};
use utils::Ipv4;

static USAGE: &'static str = "
Usage: coredump_status [-p PORT] [-i IP]

Options:
    -p PORT  The port to listen on [default: 3000].
    -i IP    The ipv4 address to listen on [default: 127.0.0.1].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: Ipv4,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    env_logger::init().unwrap();

    // Parse arguments
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    let host = args.flag_i.ip;
    let port = args.flag_p;

    // Create new Status instance
    let mut status = api::Status::new(
        "coredump",
        "https://www.coredump.ch/wp-content/uploads/2016/11/logo.png",
        "https://www.coredump.ch/",
        api::Location {
            address: Value("Zürcherstrasse 6, 8640 Rapperswil, Switzerland".into()),
            lat: 47.22939,
            lon: 8.82041,
        },
        api::Contact {
            irc: Value("irc://freenode.net/#coredump".into()),
            twitter: Value("@coredump_ch".into()),
            email: Value("vorstand@lists.coredump.ch".into()),
            phone: Absent,
            sip: Absent,
            keymasters: Absent,
            facebook: Absent,
            google: Absent,
            identica: Absent,
            foursquare: Absent,
            ml: Absent,
            jabber: Absent,
            issue_mail: Absent,
        },
        vec![
            "email".into(),
            "twitter".into(),
        ],
    );

    // Add optional data
    status.spacefed = Value(api::Spacefed {
        spacenet: false,
        spacesaml: false,
        spacephone: false,
    });
    status.feeds = Value(api::Feeds {
        blog: Value(api::Feed {
            _type: Value("rss".into()),
            url: "https://www.coredump.ch/feed/".into(),
        }),
        wiki: Absent,
        calendar: Absent,
        flickr: Absent,
    });
    status.projects = Value(vec![
        "https://www.coredump.ch/projekte/".into(),
        "https://forum.coredump.ch/c/projects".into(),
        "https://github.com/coredump-ch/".into(),
    ]);
    status.cam = Value(vec![
        "https://webcam.coredump.ch/cams/ultimaker_0.jpg".into(),
    ]);
    status.state.message = Value("Open Mondays from 20:00".into());

    // Redis connection info
    let redis_host: String = env::var("REDIS_HOST")
        .unwrap_or("127.0.0.1".to_string());
    let redis_port: u16 = env::var("REDIS_PORT")
        .unwrap_or("6379".to_string()).parse().unwrap_or(6379);
    let redis_db: i64 = env::var("REDIS_DB")
        .unwrap_or("0".to_string()).parse().unwrap_or(0);
    let redis_url = format!("redis://{}:{}/{}", redis_host, redis_port, redis_db);

    // Set up server
    let mut server = SpaceapiServer::new((host, port), status, &*redis_url,
                                         vec![Box::new(StateFromPeopleNowPresent)])
                         .expect("Could not initialize server");

    // Register sensors
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".into(),
        location: "Hackerspace".into(),
        name: Value("Raspberry CPU".into()),
        description: Absent,
    }), "temperature_raspi".into());
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".into(),
        location: "Hackerspace".into(),
        name: Value("Room Temperature".into()),
        description: Absent,
    }), "temperature_room".into());
    server.register_sensor(Box::new(PeopleNowPresentSensorTemplate {
        location: Value("Hackerspace".into()),
        name: Absent,
        description: Absent,
        names: Absent,
    }), "people_now_present".into());

    // Serve!
    server.serve().expect("Could not start the server");
}
<|endoftext|>


<commit_before>extern crate rust_guessing_game;

use std::io;
use std::rand;

use rust_guessing_game::my_funcs;

#[cfg(not(test))]
fn main() {
    println!("Guess the magic number!");
    let magic_number = ( rand::random::<uint>() % 100u ) + 1u;
    loop {
        let input = io::stdin().read_line().ok().expect("That was bad input");
        let input_optoin_uint: Option<uint> = from_str(input.as_slice().trim());
        let input_uint = match input_optoin_uint {
            Some(num) => num,
            None      => {
                println!("Please input a number");
                continue;
            }
        };
        match my_funcs::compaire(input_uint, magic_number) {
            Less    => println!("Guess higher."),
            Greater => println!("Guess lower."),
            Equal   => {
                println!("You win!");
                return
            },
        }
    }
}
<commit_msg>Fix error in spelling<commit_after>extern crate rust_guessing_game;

use std::io;
use std::rand;

use rust_guessing_game::my_funcs;

#[cfg(not(test))]
fn main() {
    println!("Guess the magic number!");
    let magic_number = ( rand::random::<uint>() % 100u ) + 1u;
    loop {
        let input = io::stdin().read_line().ok().expect("That was bad input");
        let input_optoin_uint: Option<uint> = from_str(input.as_slice().trim());
        let input_uint = match input_optoin_uint {
            Some(num) => num,
            None      => {
                println!("Please input a number");
                continue;
            }
        };
        match my_funcs::compare(input_uint, magic_number) {
            Less    => println!("Guess higher."),
            Greater => println!("Guess lower."),
            Equal   => {
                println!("You win!");
                return
            },
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston_window;

use piston_window::*;

fn main() {
    let window: PistonWindow = WindowSettings::new(
            "colors",
            [600, 600]
        )
        .exit_on_esc(true)
        .build()
        .unwrap();

    let target_color = [1.0, 0.0, 0.0, 1.0];
    let mut mouse_position = (0.0, 0.0);

    for e in window {
        e.draw_2d(|c, g| {
           clear(target_color, g);

           let playing_surface = Ellipse::new([1.0, 1.0, 1.0, 1.0]);
           playing_surface.draw([50.0, 50.0, 500.0, 500.0], &c.draw_state, c.transform, g);

           let candidate1 = Ellipse::new(target_color);
           candidate1.draw([300.0, 300.0, 100.0, 100.0], &c.draw_state, c.transform, g);

           let candidate2 = Ellipse::new([0.0, 1.0, 0.0, 1.0]);
           candidate2.draw([100.0, 200.0, 100.0, 100.0], &c.draw_state, c.transform, g);

           let candidate3 = Ellipse::new([0.0, 0.0, 1.0, 1.0]);
           candidate3.draw([300.0, 100.0, 100.0, 100.0], &c.draw_state, c.transform, g);
        });
        e.mouse_cursor(|x, y| {
            mouse_position = (x, y);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                println!("press {:?}", mouse_position);
            }
        };

    }
}
<commit_msg>Math is hard. Let's switch to rectangles<commit_after>extern crate piston_window;

use piston_window::*;

fn main() {
    let window: PistonWindow = WindowSettings::new(
            "colors",
            [600, 600]
        )
        .exit_on_esc(true)
        .build()
        .unwrap();

    let target_color = [1.0, 0.0, 0.0, 1.0];
    let mut mouse_position = (0.0, 0.0);

    for e in window {
        e.draw_2d(|c, g| {
           clear(target_color, g);

           let playing_surface = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
           playing_surface.draw([50.0, 50.0, 500.0, 500.0], &c.draw_state, c.transform, g);

           let candidate1 = Rectangle::new(target_color);
           candidate1.draw([300.0, 300.0, 100.0, 100.0], &c.draw_state, c.transform, g);

           let candidate2 = Rectangle::new([0.0, 1.0, 0.0, 1.0]);
           candidate2.draw([100.0, 200.0, 100.0, 100.0], &c.draw_state, c.transform, g);

           let candidate3 = Rectangle::new([0.0, 0.0, 1.0, 1.0]);
           candidate3.draw([300.0, 100.0, 100.0, 100.0], &c.draw_state, c.transform, g);
        });
        e.mouse_cursor(|x, y| {
            mouse_position = (x, y);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                println!("press {:?}", mouse_position);
            }
        };

    }
}
<|endoftext|>