<commit_before>use templates::*;
use board::*;
use piece_move::{MoveFlag, BitMove, PreMoveInfo};
use bit_twiddles::*;
use magic_helper::MagicHelper;

// TODO:
// MoveGen Classifications:
// Evasions, Captures, Quiets, Quiet_checks, Evasions, Non Evasions, Legal
//
// Evasions: Board is currently in check; Generate moves that move the king or Block the attack
// Captures: This Move captures something;
// Quiets: Moves that do not capture a piece
// Non-Evasions: Board is currently in check; Generate moves that do not move the king

// Pieces not needed special considerations when generating (basically everything but pawns)
const STANDARD_PIECES: [Piece; 5] = [Piece::B, Piece::N, Piece::R, Piece::Q, Piece::K];

pub struct MoveGen<'a> {
    movelist: Vec<BitMove>,
    board: &'a Board,
    magic: &'static MagicHelper<'static,'static>,
    turn: Player,
    them: Player,
    occ: BitBoard,
    us_occ: BitBoard,
    them_occ: BitBoard,
}

impl <'a> MoveGen<'a> {
    pub fn generate_all(chessboard: &Board) -> Vec<BitMove> {
        let mut movegen = MoveGen::get_self(&chessboard);
        movegen.gen_all();
        movegen.movelist
    }

    fn get_self(chessboard: &'a Board) -> Self {
        MoveGen {
            movelist: Vec::with_capacity(25),
            board: &chessboard,
            magic: chessboard.magic_helper,
            turn: chessboard.turn(),
            them: other_player(chessboard.turn()),
            occ: chessboard.get_occupied(),
            us_occ: chessboard.get_occupied_player(chessboard.turn()),
            them_occ: chessboard.get_occupied_player(other_player(chessboard.turn()))}
    }

    fn generate_castling(&mut self) {
        unimplemented!();
    }

    fn create_promotions(&mut self, dst: SQ, src: SQ, is_capture: bool) {
        let prom_pieces = [Piece::Q, Piece::N, Piece::R, Piece::B];
        for piece in prom_pieces.into_iter() {
            if is_capture {
                self.movelist.push(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Promotion {capture: true, prom: piece.clone()},
                }));
            } else {
                self.movelist.push(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Promotion {capture: false, prom: piece.clone()},
                }));
            }
        }
    }

    fn pawn_moves(&mut self) {
        unimplemented!();
    }

    // Return the moves Bitboard
    #[inline]
    fn moves_bb(&self, piece: Piece, square: SQ) -> BitBoard {
        assert!(sq_is_okay(square));
        assert_ne!(piece, Piece::P);
        match piece {
            Piece::P => panic!(),
            Piece::N => self.magic.knight_moves(square),
            Piece::B => self.magic.bishop_moves(self.occ,square),
            Piece::R => self.magic.rook_moves(self.occ,square),
            Piece::Q => self.magic.queen_moves(self.occ,square),
            Piece::K => self.magic.king_moves(square)
        }
    }

    fn gen_all(&mut self) {
        for piece in STANDARD_PIECES.into_iter() {
            self.gen_non_pawn_moves(piece.clone());
        }
        self.generate_castling();
        self.pawn_moves();
    }

    fn gen_non_pawn_moves(&mut self, piece: Piece) {
        let mut piece_bb: BitBoard = self.board.piece_bb(self.turn, piece);
        while piece_bb != 0 {
            let b: BitBoard = lsb(piece_bb);
            let src: SQ = bb_to_sq(b);
            let moves_bb: BitBoard = self.moves_bb(piece, src) & !self.us_occ;
            let mut captures_bb: BitBoard = moves_bb & self.them_occ;
            let mut non_captures_bb: BitBoard = moves_bb & !self.them_occ;
            self.move_append_from_bb(&mut captures_bb, src, MoveFlag::Capture {ep_capture:false});
            self.move_append_from_bb(&mut non_captures_bb, src, MoveFlag::QuietMove );
            piece_bb &= !b;
        }
    }

    #[inline]
    fn move_append_from_bb(&mut self, bits: &mut BitBoard, src: SQ, move_flag: MoveFlag) {
        while *bits != 0 {
            let bit: BitBoard = lsb(*bits);
            let b_move = BitMove::init(PreMoveInfo{
                src: src,
                dst: bb_to_sq(bit),
                flags: move_flag,
            });
            if self.board.legal_move(b_move) {
                self.movelist.push(b_move);
            }
            *bits &= !bit;
        }
    }
}
<commit_msg>Draft Version of move generation complete<commit_after>use templates::*;
use board::*;
use piece_move::{MoveFlag, BitMove, PreMoveInfo};
use bit_twiddles::*;
use magic_helper::MagicHelper;

// TODO:
// MoveGen Classifications:
// Evasions, Captures, Quiets, Quiet_checks, Evasions, Non Evasions, Legal
//
// Evasions: Board is currently in check; Generate moves that move the king or Block the attack
// Captures: This Move captures something;
// Quiets: Moves that do not capture a piece
// Non-Evasions: Board is currently in check; Generate moves that do not move the king

// Pieces not needed special considerations when generating (basically everything but pawns)
const STANDARD_PIECES: [Piece; 4] = [Piece::B, Piece::N, Piece::R, Piece::Q];

pub struct MoveGen<'a> {
    movelist: Vec<BitMove>,
    board: &'a Board,
    magic: &'static MagicHelper<'static,'static>,
    turn: Player,
    them: Player,
    occ: BitBoard,
    us_occ: BitBoard,
    them_occ: BitBoard,
}

impl <'a> MoveGen<'a> {
    pub fn gen(chessboard: &Board) -> Vec<BitMove> {
        let mut movegen = MoveGen::get_self(&chessboard);
        if chessboard.in_check() {
            movegen.generate_evasions();
        } else {
            movegen.generate(GenTypes::Legal);
        }
        movegen.movelist
    }

    fn get_self(chessboard: &'a Board) -> Self {
        MoveGen {
            movelist: Vec::with_capacity(25),
            board: &chessboard,
            magic: chessboard.magic_helper,
            turn: chessboard.turn(),
            them: other_player(chessboard.turn()),
            occ: chessboard.get_occupied(),
            us_occ: chessboard.get_occupied_player(chessboard.turn()),
            them_occ: chessboard.get_occupied_player(other_player(chessboard.turn()))}
    }

    // Generate Based on gen_type
    // Helper function, as make assumptions
    fn generate(&mut self, gen_type: GenTypes) {
        match gen_type {
            GenTypes::Legal => {
                self.generate_castling(u64::max_value());
                self.gen_non_pawn_king(u64::max_value());
                self.generate_king_moves(u64::max_value());
                self.generate_castling(u64::max_value());
                self.generate_pawn_moves(u64::max_value(),GenTypes::Legal);
            },
            GenTypes::Evasions => {
                self.generate_evasions();
            },
            GenTypes::Captures => { unimplemented!() },
            GenTypes::Quiets => { unimplemented!() },
            GenTypes::NonEvasions => { unimplemented!() },
            GenTypes::QuietChecks => { unimplemented!() },
        }
    }

    fn generate_evasions(&mut self) {
        let ksq: SQ = self.board.king_sq(self.turn);

        let mut slider_attacks: BitBoard = 0;
        let mut sliders = self.board.checkers() & (self.board.piece_bb(self.them,Piece::Q)
                                                    | self.board.piece_bb(self.them,Piece::R)
                                                    | self.board.piece_bb(self.them,Piece::B));

        while sliders != 0 {
            let check_sq: SQ = bit_scan_forward(sliders);
            slider_attacks |= self.magic.line_bb(check_sq,ksq) ^ sq_to_bb(check_sq);
            sliders &= !(sq_to_bb(check_sq));
        }

        let mut k_moves: BitBoard = self.magic.king_moves(ksq) & !slider_attacks & !self.us_occ;

        let mut captures_bb: BitBoard = k_moves & self.them_occ;
        let mut non_captures_bb: BitBoard = k_moves & !self.them_occ;
        self.move_append_from_bb(&mut captures_bb, ksq, MoveFlag::Capture {ep_capture:false});
        self.move_append_from_bb(&mut non_captures_bb, ksq, MoveFlag::QuietMove );

        if !more_than_one(self.board.checkers()) {
            let checking_sq: SQ = bit_scan_forward(self.board.checkers());
            let target: BitBoard = self.magic.between_bb(checking_sq,ksq) | sq_to_bb(checking_sq);
            self.generate_pawn_moves(target,GenTypes::Evasions);
            self.gen_non_pawn_king(target);
        }
    }

    fn generate_king_moves(&mut self, target: BitBoard) {
        self.moves_per_piece(Piece::K, target);
    }

    fn generate_castling(&mut self, target: BitBoard) {
        self.castling_side(target,CastleType::QueenSide);
        self.castling_side(target,CastleType::KingSide);
    }

    fn castling_side(&mut self, target: BitBoard, side: CastleType) {
        if !self.board.castle_impeded(side) && self.board.can_castle(self.turn,side) {
            let king_side: bool = {side == CastleType::KingSide};

            let ksq: SQ = self.board.king_sq(self.turn);
            let r_from: SQ = self.board.castling_rook_square(side);
            let k_to = relative_square(self.turn, if king_side {
                Square::G1 as SQ
            } else {
                Square::C1 as SQ
            });

            let enemies: BitBoard = self.them_occ;
            let direction: Box<Fn(SQ) -> SQ> = if king_side {
                Box::new(|x: SQ| x.wrapping_sub(1))
            } else {
                Box::new(|x: SQ| x.wrapping_add(1))
            };

            let mut s: SQ = k_to;
            let mut can_castle: bool = true;
            'outer: while s != ksq {
                let attackers = self.board.attackers_to(s,self.occ) & enemies;
                if attackers != 0 {
                    can_castle = false;
                    break 'outer;
                }
                s = direction(s);
            }
            if can_castle {
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: ksq,
                    dst: r_from,
                    flags: MoveFlag::Castle {king_side: king_side},
                }));
            }

        }
    }

    fn gen_non_pawn_king(&mut self, target: BitBoard) {
        for piece in STANDARD_PIECES.into_iter() {
            self.moves_per_piece(piece.clone(), target);
        }
    }

    fn moves_per_piece(&mut self, piece: Piece, target: BitBoard) {
        let mut piece_bb: BitBoard = self.board.piece_bb(self.turn, piece);
        while piece_bb != 0 {
            let b: BitBoard = lsb(piece_bb);
            let src: SQ = bb_to_sq(b);
            let moves_bb: BitBoard = self.moves_bb(piece, src) & !self.us_occ & target;
            let mut captures_bb: BitBoard = moves_bb & self.them_occ;
            let mut non_captures_bb: BitBoard = moves_bb & !self.them_occ;
            self.move_append_from_bb(&mut captures_bb, src, MoveFlag::Capture {ep_capture:false});
            self.move_append_from_bb(&mut non_captures_bb, src, MoveFlag::QuietMove );
            piece_bb &= !b;
        }
    }

    fn generate_pawn_moves(&mut self, target: BitBoard, gen_type: GenTypes) {
        let rank_8: BitBoard = if self.turn == Player::White {RANK_8} else {RANK_1};
        let rank_7: BitBoard = if self.turn == Player::White {RANK_7} else {RANK_2};
        let rank_3: BitBoard = if self.turn == Player::White {RANK_3} else {RANK_6};

        let down: Box<Fn(SQ) -> SQ> = if self.turn == Player::White {
            Box::new(|x: SQ| x.wrapping_sub(8))
        } else {
            Box::new(|x: SQ| x.wrapping_add(8))
        };
        let up: Box<Fn(SQ) -> SQ> = if self.turn == Player::White {
            Box::new(|x: SQ| x.wrapping_add(8))
        } else {
            Box::new(|x: SQ| x.wrapping_sub(8))
        };
        let left_down: Box<Fn(SQ) -> SQ> = if self.turn == Player::White {
            Box::new(|x: SQ| x.wrapping_sub(9))
        } else {
            Box::new(|x: SQ| x.wrapping_add(9))
        };
        let right_down: Box<Fn(SQ) -> SQ> = if self.turn == Player::White {
            Box::new(|x: SQ| x.wrapping_sub(7))
        } else {
            Box::new(|x: SQ| x.wrapping_add(7))
        };

        let shift_up: Box<Fn(u64) -> u64> = if self.turn == Player::White {
            Box::new(|x: u64| x.wrapping_shl(8))
        } else {
            Box::new(|x: u64| x.wrapping_shr(8))
        };
        let shift_left_up: Box<Fn(u64) -> u64> = if self.turn == Player::White {
            Box::new(|x: u64| (x & !FILE_A).wrapping_shl(7) )
        } else {
            Box::new(|x: u64| (x & !FILE_H).wrapping_shr(7))
        };
        let shift_right_up: Box<Fn(u64) -> u64> = if self.turn == Player::White {
            Box::new(|x: u64| (x & !FILE_H).wrapping_shl(9))
        } else {
            Box::new(|x: u64| (x & !FILE_A).wrapping_shr(9))
        };

        let all_pawns: BitBoard = self.board.piece_bb(self.turn,Piece::P);
        let pawns_rank_7: BitBoard = all_pawns & rank_7;
        let pawns_not_rank_7: BitBoard = all_pawns & !rank_7;

        let mut empty_squares: BitBoard = 0;

        let enemies: BitBoard = if gen_type == GenTypes::Evasions {
            self.them_occ & target
        } else if gen_type == GenTypes::Captures {
            target
        } else {
            self.them_occ
        };

        // Single and Double Pawn Pushes
        if gen_type != GenTypes::Captures {
            empty_squares = if gen_type == GenTypes::Quiets || gen_type == GenTypes::QuietChecks {
                target
            } else { !self.occ };

            let mut push_one: BitBoard = empty_squares & shift_up(pawns_not_rank_7) & target;
            let mut push_two: BitBoard = shift_up(push_one & rank_3) & empty_squares & target;

            if gen_type == GenTypes::Evasions {
                push_one &= target;
                push_two &= target;
            }

            if gen_type == GenTypes::QuietChecks {
                let ksq: SQ = self.board.king_sq(self.them);
                push_one &= self.magic.pawn_attacks_from(ksq, self.them);
                push_two &= self.magic.pawn_attacks_from(ksq, self.them);

                let dc_candidates: BitBoard = self.board.discovered_check_candidates();
                if pawns_not_rank_7 & dc_candidates != 0 {
                    let dc1: BitBoard = shift_up(pawns_not_rank_7 & dc_candidates) & empty_squares & !file_bb(ksq);
                    let dc2: BitBoard = shift_up(rank_3 & dc_candidates) & empty_squares;

                    push_one |= dc1;
                    push_two |= dc2;
                }
            }

            while push_one != 0 {
                let bit: BitBoard = lsb(push_one);
                let dst: SQ = bb_to_sq(bit);
                let src: SQ = down(dst);
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::QuietMove,
                }));
                push_one &= !bit;
            }

            while push_two != 0 {
                let bit: BitBoard = lsb(push_two);
                let dst: SQ = bb_to_sq(bit);
                let src: SQ = down(down(dst));
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::DoublePawnPush,
                }));
                push_two &= !bit;
            }
        }

        // Promotions
        if pawns_rank_7 != 0 && (gen_type != GenTypes::Evasions || (target & rank_8) != 0){
            if gen_type == GenTypes::Captures {
                empty_squares = !self.them_occ;
            } else if gen_type == GenTypes::Evasions {
                empty_squares &= target;
            }

            let mut no_promo: BitBoard = shift_up(pawns_rank_7) & empty_squares;
            let mut left_cap_promo: BitBoard = shift_left_up(pawns_rank_7) & enemies;
            let mut right_cap_promo: BitBoard = shift_right_up(pawns_rank_7) & enemies;

            while no_promo != 0 {
                let bit = lsb(no_promo);
                let dst: SQ = bb_to_sq(bit);
                self.create_promotions(dst, down(dst), false);
                no_promo &= !bit;
            }

            while left_cap_promo != 0 {
                let bit = lsb(left_cap_promo);
                let dst: SQ = bb_to_sq(bit);
                self.create_promotions(dst, right_down(dst), true);
                left_cap_promo &= !bit;
            }

            while right_cap_promo != 0 {
                let bit = lsb(right_cap_promo);
                let dst: SQ = bb_to_sq(bit);
                self.create_promotions(dst, left_down(dst), true);
                right_cap_promo &= !bit;
            }
        }

        // Captures
        if gen_type == GenTypes::Captures || gen_type == GenTypes::Evasions
            || gen_type == GenTypes::NonEvasions || gen_type == GenTypes::Legal {

            let mut left_cap: BitBoard = shift_left_up(pawns_not_rank_7) & enemies;
            let mut right_cap: BitBoard = shift_right_up(pawns_not_rank_7) & enemies;

            while left_cap != 0 {
                let bit = lsb(left_cap);
                let dst: SQ = bb_to_sq(bit);
                let src: SQ = right_down(dst);
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Capture {ep_capture: false}}));
                left_cap &= !bit;
            }

            while right_cap != 0 {
                let bit = lsb(right_cap);
                let dst: SQ = bb_to_sq(bit);
                let src: SQ = left_down(dst);
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Capture {ep_capture: false}}));
                right_cap &= !bit;
            }

            if self.board.ep_square() != NO_SQ {
                let ep_sq: SQ = self.board.ep_square();
                assert_eq!(rank_of_sq(ep_sq), relative_rank(self.turn,Rank::R6));
                if gen_type != GenTypes::Evasions || target & sq_to_bb(down(ep_sq)) != 0 {
                    left_cap = pawns_not_rank_7 & self.magic.pawn_attacks_from(ep_sq, self.them);

                    while left_cap != 0 {
                        let bit = lsb(left_cap);
                        let src: SQ = bb_to_sq(bit);
                        self.check_and_add(BitMove::init(PreMoveInfo {
                            src: src,
                            dst: down(ep_sq),
                            flags: MoveFlag::Capture { ep_capture: false }
                        }));
                        left_cap &= !bit;
                    }
                }
            }
        }
    }

    fn create_promotions(&mut self, dst: SQ, src: SQ, is_capture: bool) {
        let prom_pieces = [Piece::Q, Piece::N, Piece::R, Piece::B];
        for piece in prom_pieces.into_iter() {
            if is_capture {
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Promotion {capture: true, prom: piece.clone()},
                }));
            } else {
                self.check_and_add(BitMove::init(PreMoveInfo {
                    src: src,
                    dst: dst,
                    flags: MoveFlag::Promotion {capture: false, prom: piece.clone()},
                }));
            }
        }
    }

    // Return the moves Bitboard
    #[inline]
    fn moves_bb(&self, piece: Piece, square: SQ) -> BitBoard {
        assert!(sq_is_okay(square));
        assert_ne!(piece, Piece::P);
        match piece {
            Piece::P => panic!(),
            Piece::N => self.magic.knight_moves(square),
            Piece::B => self.magic.bishop_moves(self.occ,square),
            Piece::R => self.magic.rook_moves(self.occ,square),
            Piece::Q => self.magic.queen_moves(self.occ,square),
            Piece::K => self.magic.king_moves(square)
        }
    }

    #[inline]
    fn move_append_from_bb(&mut self, bits: &mut BitBoard, src: SQ, move_flag: MoveFlag) {
        while *bits != 0 {
            let bit: BitBoard = lsb(*bits);
            let b_move = BitMove::init(PreMoveInfo{
                src: src,
                dst: bb_to_sq(bit),
                flags: move_flag,
            });
            self.check_and_add(b_move);
            *bits &= !bit;
        }
    }

    fn check_and_add(&mut self, b_move: BitMove) {
        if self.board.legal_move(b_move) {
            self.movelist.push(b_move);
        }
    }
}
<|endoftext|>


<commit_before>//! Network interface name resolution.
//!
//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
//! or "socan1" into device numbers.

use libc::{c_uint, if_nametoindex};
use std::ffi::{CString, NulError};
use ::Error;

/// Resolve an interface into a interface number.
pub fn name_to_index(name: &str) -> Result<c_uint, Error> {
    let name = match CString::new(name) {
        Err(e) => match e { NulError(..) => {
            // A NulError indicates that a '\0' was found inside the string,
            // making it impossible to create valid C-String. To avoid having
            // to create a new error type for this rather rare case,
            // nix::Error's invalid_argument() constructor is used.
            //
            // We match the NulError individually here to ensure to avoid
            // accidentally returning invalid_argument() for errors other than
            // NulError (which currently don't exist).
            return Err(Error::invalid_argument());
        }},
        Ok(s) => s
    };

    let if_index;
    unsafe {
        if_index = if_nametoindex(name.as_ptr());
    }

    if if_index == 0 { Err(Error::last()) } else { Ok(if_index) }
}
<commit_msg>Use nix::Result explicitly.<commit_after>//! Network interface name resolution.
//!
//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
//! or "socan1" into device numbers.

use libc::{c_uint, if_nametoindex};
use std::ffi::{CString, NulError};
use ::{Result, Error};

/// Resolve an interface into a interface number.
pub fn name_to_index(name: &str) -> Result<c_uint> {
    let name = match CString::new(name) {
        Err(e) => match e { NulError(..) => {
            // A NulError indicates that a '\0' was found inside the string,
            // making it impossible to create valid C-String. To avoid having
            // to create a new error type for this rather rare case,
            // nix::Error's invalid_argument() constructor is used.
            //
            // We match the NulError individually here to ensure to avoid
            // accidentally returning invalid_argument() for errors other than
            // NulError (which currently don't exist).
            return Err(Error::invalid_argument());
        }},
        Ok(s) => s
    };

    let if_index;
    unsafe {
        if_index = if_nametoindex(name.as_ptr());
    }

    if if_index == 0 { Err(Error::last()) } else { Ok(if_index) }
}
<|endoftext|>


<commit_before>pub fn format_numeral(n: f64, format: &str) -> String {
    if format.contains(":") {
        format_time(n, format)
    } else {
        format_number(n, format)
    }
}

pub fn unformat_numeral(string: &str) -> f64 {
    if string.contains(":") {
        unformat_time(string)
    } else {
        unformat_number(string)
    }
}

#[allow(unused_variables)]
fn format_number(n: f64, format: &str) -> String {
    unimplemented!()
}

#[allow(unused_variables)]
fn unformat_number(string: &str) -> f64 {
    unimplemented!()
}

#[allow(unused_variables)]
fn format_time(n: f64, format: &str) -> String {
    let hours: f64 = (n/60./60.).floor();
    let minutes = ((n - (hours * 60. * 60.))/60.).floor();
    let seconds = (n - (hours * 60. * 60.) - (minutes * 60.)).round();

    let hours_string = hours.to_string();

    let minutes_string = & if minutes < 10. {
        "0".to_string() + &minutes.to_string()
    } else {
        minutes.to_string()
    };

    let seconds_string = & if seconds < 10. {
        "0".to_string() + &seconds.to_string()
    } else {
        seconds.to_string()
    };

    hours_string + ":" + minutes_string + ":" + seconds_string
}

fn unformat_time(string: &str) -> f64 {
    let split = string.split(":");
    let time_array: Vec<&str> = split.collect();
    let mut seconds = 0.0;

    if time_array.len() == 3 {
        // hours
        seconds = seconds + (time_array[0].parse::<f64>().unwrap() * 60.0 * 60.0);
        // minutes
        seconds = seconds + (time_array[1].parse::<f64>().unwrap() * 60.0);
        // seconds
        seconds = seconds + (time_array[2].parse::<f64>().unwrap());
    } else if time_array.len() == 2 {
        // minutes
        seconds = seconds + (time_array[0].parse::<f64>().unwrap() * 60.0);
        // seconds
        seconds = seconds + (time_array[1].parse::<f64>().unwrap());
    }
    seconds
}

#[test]
fn test_format_time() {
    let time = format_numeral(3600.0, "00:00:00");
    assert_eq!(time, "1:00:00");
}

#[test]
fn test_unformat_time() {
    let number = unformat_numeral("1:00:00");
    assert_eq!(number, 3600.0);
}
<commit_msg>refactor(numeral.rs): refactor unformat_time()<commit_after>pub fn format_numeral(n: f64, format: &str) -> String {
    if format.contains(":") {
        format_time(n, format)
    } else {
        format_number(n, format)
    }
}

pub fn unformat_numeral(string: &str) -> f64 {
    if string.contains(":") {
        unformat_time(string)
    } else {
        unformat_number(string)
    }
}

#[allow(unused_variables)]
fn format_number(n: f64, format: &str) -> String {
    unimplemented!()
}

#[allow(unused_variables)]
fn unformat_number(string: &str) -> f64 {
    unimplemented!()
}

#[allow(unused_variables)]
fn format_time(n: f64, format: &str) -> String {
    let hours: f64 = (n/60./60.).floor();
    let minutes = ((n - (hours * 60. * 60.))/60.).floor();
    let seconds = (n - (hours * 60. * 60.) - (minutes * 60.)).round();

    let hours_string = hours.to_string();

    let minutes_string = & if minutes < 10. {
        "0".to_string() + &minutes.to_string()
    } else {
        minutes.to_string()
    };

    let seconds_string = & if seconds < 10. {
        "0".to_string() + &seconds.to_string()
    } else {
        seconds.to_string()
    };

    hours_string + ":" + minutes_string + ":" + seconds_string
}

fn unformat_time(string: &str) -> f64 {
    let splitted: Vec<&str> = string.split(":").collect();
    let time_array: Vec<f64> = splitted.iter().map(|element| element.parse::<f64>().unwrap() ).collect();

    match time_array.len() {
        // hours + minutes + seconds
        3 => (time_array[0] * 60.0 * 60.0) + (time_array[1] * 60.0) + time_array[2],

        // minutes + seconds
        2 => (time_array[0] * 60.0) + time_array[1],

        // else
        _ => unimplemented!()
    }
}

#[test]
fn test_format_time() {
    let time = format_numeral(3600.0, "00:00:00");
    assert_eq!(time, "1:00:00");
}

#[test]
fn test_unformat_time() {
    let number = unformat_numeral("1:00:00");
    assert_eq!(number, 3600.0);
}
<|endoftext|>


<commit_before>mod add;
mod build;
mod cmin;
mod fmt;
mod init;
mod list;
mod run;
mod tmin;

pub use self::{
    add::Add, build::Build, cmin::Cmin, fmt::Fmt, init::Init, list::List, run::Run, tmin::Tmin,
};

use std::fmt as stdfmt;
use std::str::FromStr;
use structopt::StructOpt;

#[derive(Debug, Clone, Copy)]
pub enum Sanitizer {
    Address,
    Leak,
    Memory,
    Thread,
    None,
}

impl stdfmt::Display for Sanitizer {
    fn fmt(&self, f: &mut stdfmt::Formatter) -> stdfmt::Result {
        write!(
            f,
            "{}",
            match self {
                Sanitizer::Address => "address",
                Sanitizer::Leak => "leak",
                Sanitizer::Memory => "memory",
                Sanitizer::Thread => "thread",
                Sanitizer::None => "",
            }
        )
    }
}

impl FromStr for Sanitizer {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "address" => Ok(Sanitizer::Address),
            "leak" => Ok(Sanitizer::Leak),
            "memory" => Ok(Sanitizer::Memory),
            "thread" => Ok(Sanitizer::Thread),
            "none" => Ok(Sanitizer::None),
            _ => Err(format!("unknown sanitizer: {}", s)),
        }
    }
}

#[derive(Clone, Debug, StructOpt)]
pub struct BuildOptions {
    #[structopt(short = "D", long = "dev", conflicts_with = "release")]
    /// Build artifacts in development mode, without optimizations
    pub dev: bool,

    #[structopt(short = "O", long = "release", conflicts_with = "debug")]
    /// Build artifacts in release mode, with optimizations
    pub release: bool,

    #[structopt(short = "a", long = "debug-assertions")]
    /// Build artifacts with debug assertions enabled (default if not -O)
    pub debug_assertions: bool,

    /// Build target with verbose output from `cargo build`
    #[structopt(short = "v", long = "verbose")]
    pub verbose: bool,

    #[structopt(long = "no-default-features")]
    /// Build artifacts with default Cargo features disabled
    pub no_default_features: bool,

    #[structopt(
        long = "all-features",
        conflicts_with = "no-default-features",
        conflicts_with = "features"
    )]
    /// Build artifacts with all Cargo features enabled
    pub all_features: bool,

    #[structopt(long = "features")]
    /// Build artifacts with given Cargo feature enabled
    pub features: Option<String>,

    #[structopt(
        short = "s",
        long = "sanitizer",
        possible_values(&["address", "leak", "memory", "thread", "none"]),
        default_value = "address",
    )]
    /// Use a specific sanitizer
    pub sanitizer: Sanitizer,

    #[structopt(
        name = "triple",
        long = "target",
        default_value(crate::utils::default_target())
    )]
    /// Target triple of the fuzz target
    pub triple: String,

    #[structopt(short = "Z", value_name = "FLAG")]
    /// Unstable (nightly-only) flags to Cargo
    pub unstable_flags: Vec<String>,
}
<commit_msg>Document that --debug-assertions also enables overflow checks<commit_after>mod add;
mod build;
mod cmin;
mod fmt;
mod init;
mod list;
mod run;
mod tmin;

pub use self::{
    add::Add, build::Build, cmin::Cmin, fmt::Fmt, init::Init, list::List, run::Run, tmin::Tmin,
};

use std::fmt as stdfmt;
use std::str::FromStr;
use structopt::StructOpt;

#[derive(Debug, Clone, Copy)]
pub enum Sanitizer {
    Address,
    Leak,
    Memory,
    Thread,
    None,
}

impl stdfmt::Display for Sanitizer {
    fn fmt(&self, f: &mut stdfmt::Formatter) -> stdfmt::Result {
        write!(
            f,
            "{}",
            match self {
                Sanitizer::Address => "address",
                Sanitizer::Leak => "leak",
                Sanitizer::Memory => "memory",
                Sanitizer::Thread => "thread",
                Sanitizer::None => "",
            }
        )
    }
}

impl FromStr for Sanitizer {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "address" => Ok(Sanitizer::Address),
            "leak" => Ok(Sanitizer::Leak),
            "memory" => Ok(Sanitizer::Memory),
            "thread" => Ok(Sanitizer::Thread),
            "none" => Ok(Sanitizer::None),
            _ => Err(format!("unknown sanitizer: {}", s)),
        }
    }
}

#[derive(Clone, Debug, StructOpt)]
pub struct BuildOptions {
    #[structopt(short = "D", long = "dev", conflicts_with = "release")]
    /// Build artifacts in development mode, without optimizations
    pub dev: bool,

    #[structopt(short = "O", long = "release", conflicts_with = "debug")]
    /// Build artifacts in release mode, with optimizations
    pub release: bool,

    #[structopt(short = "a", long = "debug-assertions")]
    /// Build artifacts with debug assertions and overflow checks enabled (default if not -O)
    pub debug_assertions: bool,

    /// Build target with verbose output from `cargo build`
    #[structopt(short = "v", long = "verbose")]
    pub verbose: bool,

    #[structopt(long = "no-default-features")]
    /// Build artifacts with default Cargo features disabled
    pub no_default_features: bool,

    #[structopt(
        long = "all-features",
        conflicts_with = "no-default-features",
        conflicts_with = "features"
    )]
    /// Build artifacts with all Cargo features enabled
    pub all_features: bool,

    #[structopt(long = "features")]
    /// Build artifacts with given Cargo feature enabled
    pub features: Option<String>,

    #[structopt(
        short = "s",
        long = "sanitizer",
        possible_values(&["address", "leak", "memory", "thread", "none"]),
        default_value = "address",
    )]
    /// Use a specific sanitizer
    pub sanitizer: Sanitizer,

    #[structopt(
        name = "triple",
        long = "target",
        default_value(crate::utils::default_target())
    )]
    /// Target triple of the fuzz target
    pub triple: String,

    #[structopt(short = "Z", value_name = "FLAG")]
    /// Unstable (nightly-only) flags to Cargo
    pub unstable_flags: Vec<String>,
}
<|endoftext|>


<commit_before>//! Decoding of netpbm image formats (pbm, pgm, ppm and pam).
//!
//! The formats pbm, pgm and ppm are fully supported. The pam decoder recognizes the tuple types
//! `BLACKANDWHITE`, `GRAYSCALE` and `RGB` and explicitely recognizes but rejects their `_ALPHA`
//! variants for now as alpha color types are unsupported.
pub use self::decoder::PNMDecoder;
pub use self::encoder::PNMEncoder;
pub use self::header::{PNMHeader, PNMSubtype, SampleEncoding};
pub use self::header::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};
use self::autobreak::AutoBreak;
use self::header::HeaderRecord;

mod autobreak;
mod decoder;
mod encoder;
mod header;

#[cfg(test)]
mod tests {
    use super::*;
    use color::ColorType;
    use image::{DecodingResult, ImageDecoder};

    fn execute_roundtrip_default(buffer: &[u8], width: u32, height: u32, color: ColorType) {
        let mut encoded_buffer = Vec::new();

        {
            let mut encoder = PNMEncoder::new(&mut encoded_buffer);
            encoder.encode(buffer, width, height, color)
                .expect("Failed to encode the image buffer");
        }

        let (header, loaded_color, loaded_image) = {
            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
            let colortype = decoder.colortype()
                .expect("Failed to decode color type");
            let image = decoder.read_image()
                .expect("Failed to decode the image");
            let (_, header) = decoder.into_inner();
            (header, colortype, image)
        };

        assert_eq!(header.width(), width);
        assert_eq!(header.height(), height);
        assert_eq!(loaded_color, color);
        match loaded_image {
            DecodingResult::U8(ref data) if data.as_slice() == buffer => (),
            _ => panic!("Loaded image buffer deviates from original! {:?}", loaded_image),
        }
    }

    fn execute_roundtrip_with_subtype(
        buffer: &[u8], width: u32, height: u32, color: ColorType, subtype: PNMSubtype) {
        let mut encoded_buffer = Vec::new();

        {
            let mut encoder = PNMEncoder::new(&mut encoded_buffer)
                .with_subtype(subtype);
            encoder.encode(buffer, width, height, color)
                .expect("Failed to encode the image buffer");
        }

        let (header, loaded_color, loaded_image) = {
            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
            let colortype = decoder.colortype()
                .expect("Failed to decode color type");
            let image = decoder.read_image()
                .expect("Failed to decode the image");
            let (_, header) = decoder.into_inner();
            (header, colortype, image)
        };

        assert_eq!(header.width(), width);
        assert_eq!(header.height(), height);
        assert_eq!(header.subtype(), subtype);
        assert_eq!(loaded_color, color);
        match loaded_image {
            DecodingResult::U8(ref data) if data.as_slice() == buffer => (),
            _ => panic!("Loaded image buffer deviates from original! {:?}", loaded_image),
        }
    }

    #[test]
    fn roundtrip_rgb() {
        let buf: [u8; 27] = [
              0,   0,   0,
              0,   0, 255,
              0, 255,   0,
              0, 255, 255,
            255,   0,   0,
            255,   0, 255,
            255, 255,   0,
            255, 255, 255,
            255, 255, 255,
        ];
        execute_roundtrip_default(&buf, 3, 3, ColorType::RGB(8));
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8), PNMSubtype::ArbitraryMap);
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8),
            PNMSubtype::Pixmap(SampleEncoding::Binary));
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8),
            PNMSubtype::Pixmap(SampleEncoding::Ascii));
    }

}
<commit_msg>Test u16 encoding roundtrip<commit_after>//! Decoding of netpbm image formats (pbm, pgm, ppm and pam).
//!
//! The formats pbm, pgm and ppm are fully supported. The pam decoder recognizes the tuple types
//! `BLACKANDWHITE`, `GRAYSCALE` and `RGB` and explicitely recognizes but rejects their `_ALPHA`
//! variants for now as alpha color types are unsupported.
pub use self::decoder::PNMDecoder;
pub use self::encoder::PNMEncoder;
pub use self::header::{PNMHeader, PNMSubtype, SampleEncoding};
pub use self::header::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};
use self::autobreak::AutoBreak;
use self::header::HeaderRecord;

mod autobreak;
mod decoder;
mod encoder;
mod header;

#[cfg(test)]
mod tests {
    use super::*;
    use color::ColorType;
    use image::{DecodingResult, ImageDecoder};

    fn execute_roundtrip_default(buffer: &[u8], width: u32, height: u32, color: ColorType) {
        let mut encoded_buffer = Vec::new();

        {
            let mut encoder = PNMEncoder::new(&mut encoded_buffer);
            encoder.encode(buffer, width, height, color)
                .expect("Failed to encode the image buffer");
        }

        let (header, loaded_color, loaded_image) = {
            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
            let colortype = decoder.colortype()
                .expect("Failed to decode color type");
            let image = decoder.read_image()
                .expect("Failed to decode the image");
            let (_, header) = decoder.into_inner();
            (header, colortype, image)
        };

        assert_eq!(header.width(), width);
        assert_eq!(header.height(), height);
        assert_eq!(loaded_color, color);
        match loaded_image {
            DecodingResult::U8(ref data) if data.as_slice() == buffer => (),
            _ => panic!("Loaded image buffer deviates from original! {:?}", loaded_image),
        }
    }

    fn execute_roundtrip_with_subtype(
        buffer: &[u8], width: u32, height: u32, color: ColorType, subtype: PNMSubtype) {
        let mut encoded_buffer = Vec::new();

        {
            let mut encoder = PNMEncoder::new(&mut encoded_buffer)
                .with_subtype(subtype);
            encoder.encode(buffer, width, height, color)
                .expect("Failed to encode the image buffer");
        }

        let (header, loaded_color, loaded_image) = {
            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
            let colortype = decoder.colortype()
                .expect("Failed to decode color type");
            let image = decoder.read_image()
                .expect("Failed to decode the image");
            let (_, header) = decoder.into_inner();
            (header, colortype, image)
        };

        assert_eq!(header.width(), width);
        assert_eq!(header.height(), height);
        assert_eq!(header.subtype(), subtype);
        assert_eq!(loaded_color, color);
        match loaded_image {
            DecodingResult::U8(ref data) if data.as_slice() == buffer => (),
            _ => panic!("Loaded image buffer deviates from original! {:?}", loaded_image),
        }
    }

    fn execute_roundtrip_u16(buffer: &[u16], width: u32, height: u32, color: ColorType) {
        let mut encoded_buffer = Vec::new();

        {
            let mut encoder = PNMEncoder::new(&mut encoded_buffer);
            encoder.encode(buffer, width, height, color)
                .expect("Failed to encode the image buffer");
        }

        let (header, loaded_color, loaded_image) = {
            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
            let colortype = decoder.colortype()
                .expect("Failed to decode color type");
            let image = decoder.read_image()
                .expect("Failed to decode the image");
            let (_, header) = decoder.into_inner();
            (header, colortype, image)
        };

        assert_eq!(header.width(), width);
        assert_eq!(header.height(), height);
        assert_eq!(loaded_color, color);
        match loaded_image {
            DecodingResult::U16(ref data) if data.as_slice() == buffer => (),
            _ => panic!("Loaded image buffer deviates from original! {:?}", loaded_image),
        }
    }

    #[test]
    fn roundtrip_rgb() {
        let buf: [u8; 27] = [
              0,   0,   0,
              0,   0, 255,
              0, 255,   0,
              0, 255, 255,
            255,   0,   0,
            255,   0, 255,
            255, 255,   0,
            255, 255, 255,
            255, 255, 255,
        ];
        execute_roundtrip_default(&buf, 3, 3, ColorType::RGB(8));
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8), PNMSubtype::ArbitraryMap);
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8),
            PNMSubtype::Pixmap(SampleEncoding::Binary));
        execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::RGB(8),
            PNMSubtype::Pixmap(SampleEncoding::Ascii));
    }

    #[test]
    fn roundtrip_u16() {
        let buf: [u16; 6] = [
            0, 1, 0xFFFF, 0x1234, 0x3412, 0xBEAF,
        ];

        execute_roundtrip_u16(&buf, 6, 1, ColorType::Gray(16));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Add,
};
use default::Default;
use vector::ops::*;
use vector::Vector;

impl<'a, T> Add<&'a Vector<T>> for &'a Vector<T>
    where T: Axpy + Copy + Default
{
    type Output = Vec<T>;

    fn add(self, rhs: &Vector<T>) -> Vec<T> {
        let mut v: Vec<T> = self.into();
        let scale = Default::one();

        Axpy::axpy(&scale, rhs, &mut v);
        Vec::from(v)
    }
}

#[cfg(test)]
mod tests {
    use Vector;

    #[test]
    fn add() {
        let x = vec![1f32, 2f32];
        let y = vec![3f32, 4f32];

        let z = &x as &Vector<_> + &y;

        assert_eq!(&z, &vec![4f32, 6f32]);
    }
}
<commit_msg>Transpose operator<commit_after>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Add,
    BitXor,
};
use default::Default;
use vector::ops::*;
use vector::Vector;
use transpose::{
    Marker,
    Trans,
};

impl<'a, T> BitXor<Marker> for &'a Vector<T>
{
    type Output = Trans<&'a Vector<T>>;

    fn bitxor(self, m: Marker) -> Trans<&'a Vector<T>> {
        match m {
            Marker::T => Trans::T(self),
            Marker::H => Trans::H(self),
        }
    }
}

impl<'a, T> Add<&'a Vector<T>> for &'a Vector<T>
    where T: Axpy + Copy + Default
{
    type Output = Vec<T>;

    fn add(self, rhs: &Vector<T>) -> Vec<T> {
        let mut v: Vec<T> = self.into();
        let scale = Default::one();

        Axpy::axpy(&scale, rhs, &mut v);
        Vec::from(v)
    }
}

#[cfg(test)]
mod tests {
    use Vector;

    #[test]
    fn add() {
        let x = vec![1f32, 2f32];
        let y = vec![3f32, 4f32];

        let z = &x as &Vector<_> + &y;

        assert_eq!(&z, &vec![4f32, 6f32]);
    }
}
<|endoftext|>


<commit_before>use super::{varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64};
use crate::{config::Endian, enc::write::Writer, error::EncodeError};

pub fn varint_encode_i16<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i16,
) -> Result<(), EncodeError> {
    varint_encode_u16(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i16::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u16) * 2 + 1
        } else {
            (val as u16) * 2
        },
    )
}

pub fn varint_encode_i32<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i32,
) -> Result<(), EncodeError> {
    varint_encode_u32(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i32::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u32) * 2 + 1
        } else {
            (val as u32) * 2
        },
    )
}

pub fn varint_encode_i64<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i64,
) -> Result<(), EncodeError> {
    varint_encode_u64(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i64::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u64) * 2 + 1
        } else {
            (val as u64) * 2
        },
    )
}

pub fn varint_encode_i128<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i128,
) -> Result<(), EncodeError> {
    varint_encode_u128(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i128::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u128) * 2 + 1
        } else {
            (val as u128) * 2
        },
    )
}

pub fn varint_encode_isize<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: isize,
) -> Result<(), EncodeError> {
    // isize is being encoded as a i64
    varint_encode_i64(writer, endian, val as i64)
}

#[test]
fn test_encode_i16() {
    // TODO
}

#[test]
fn test_encode_i32() {
    // TODO
}

#[test]
fn test_encode_i64() {
    // TODO
}

#[test]
fn test_encode_i128() {
    // TODO
}
<commit_msg>Added unit tests for encode_signed<commit_after>use super::{varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64};
use crate::{config::Endian, enc::write::Writer, error::EncodeError};

pub fn varint_encode_i16<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i16,
) -> Result<(), EncodeError> {
    varint_encode_u16(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i16::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u16) * 2 + 1
        } else {
            (val as u16) * 2
        },
    )
}

pub fn varint_encode_i32<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i32,
) -> Result<(), EncodeError> {
    varint_encode_u32(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i32::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u32) * 2 + 1
        } else {
            (val as u32) * 2
        },
    )
}

pub fn varint_encode_i64<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i64,
) -> Result<(), EncodeError> {
    varint_encode_u64(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i64::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u64) * 2 + 1
        } else {
            (val as u64) * 2
        },
    )
}

pub fn varint_encode_i128<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: i128,
) -> Result<(), EncodeError> {
    varint_encode_u128(
        writer,
        endian,
        if val < 0 {
            // let's avoid the edge case of i128::min_value()
            // !n is equal to `-n - 1`, so this is:
            // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
            !(val as u128) * 2 + 1
        } else {
            (val as u128) * 2
        },
    )
}

pub fn varint_encode_isize<W: Writer>(
    writer: &mut W,
    endian: Endian,
    val: isize,
) -> Result<(), EncodeError> {
    // isize is being encoded as a i64
    varint_encode_i64(writer, endian, val as i64)
}

#[test]
fn test_encode_i16() {
    let cases: &[(i16, &[u8], &[u8])] = &[
        (0, &[0], &[0]),
        (2, &[4], &[4]),
        (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]),
        (
            16_000,
            &[super::U16_BYTE, 0, 125],
            &[super::U16_BYTE, 125, 0],
        ),
        (
            i16::MAX - 1,
            &[super::U16_BYTE, 252, 255],
            &[super::U16_BYTE, 255, 252],
        ),
        (
            i16::MAX,
            &[super::U16_BYTE, 254, 255],
            &[super::U16_BYTE, 255, 254],
        ),
    ];

    use crate::enc::write::SliceWriter;
    let mut buffer = [0u8; 20];
    for &(value, expected_le, expected_be) in cases {
        std::dbg!(value);

        // Little endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i16(&mut writer, Endian::Little, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_le.len());
        assert_eq!(&buffer[..expected_le.len()], expected_le);

        // Big endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i16(&mut writer, Endian::Big, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_be.len());
        assert_eq!(&buffer[..expected_be.len()], expected_be);
    }
}

#[test]
fn test_encode_i32() {
    let cases: &[(i32, &[u8], &[u8])] = &[
        (0, &[0], &[0]),
        (2, &[4], &[4]),
        (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]),
        (
            16_000,
            &[super::U16_BYTE, 0, 125],
            &[super::U16_BYTE, 125, 0],
        ),
        (
            40_000,
            &[super::U32_BYTE, 128, 56, 1, 0],
            &[super::U32_BYTE, 0, 1, 56, 128],
        ),
        (
            i32::MAX - 1,
            &[super::U32_BYTE, 252, 255, 255, 255],
            &[super::U32_BYTE, 255, 255, 255, 252],
        ),
        (
            i32::MAX,
            &[super::U32_BYTE, 254, 255, 255, 255],
            &[super::U32_BYTE, 255, 255, 255, 254],
        ),
    ];

    use crate::enc::write::SliceWriter;
    let mut buffer = [0u8; 20];
    for &(value, expected_le, expected_be) in cases {
        std::dbg!(value);

        // Little endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i32(&mut writer, Endian::Little, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_le.len());
        assert_eq!(&buffer[..expected_le.len()], expected_le);

        // Big endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i32(&mut writer, Endian::Big, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_be.len());
        assert_eq!(&buffer[..expected_be.len()], expected_be);
    }
}

#[test]
fn test_encode_i64() {
    let cases: &[(i64, &[u8], &[u8])] = &[
        (0, &[0], &[0]),
        (2, &[4], &[4]),
        (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]),
        (
            16_000,
            &[super::U16_BYTE, 0, 125],
            &[super::U16_BYTE, 125, 0],
        ),
        (
            40_000,
            &[super::U32_BYTE, 128, 56, 1, 0],
            &[super::U32_BYTE, 0, 1, 56, 128],
        ),
        (
            3_000_000_000,
            &[super::U64_BYTE, 0, 188, 160, 101, 1, 0, 0, 0],
            &[super::U64_BYTE, 0, 0, 0, 1, 101, 160, 188, 0],
        ),
        (
            i64::MAX - 1,
            &[super::U64_BYTE, 252, 255, 255, 255, 255, 255, 255, 255],
            &[super::U64_BYTE, 255, 255, 255, 255, 255, 255, 255, 252],
        ),
        (
            i64::MAX,
            &[super::U64_BYTE, 254, 255, 255, 255, 255, 255, 255, 255],
            &[super::U64_BYTE, 255, 255, 255, 255, 255, 255, 255, 254],
        ),
    ];

    use crate::enc::write::SliceWriter;
    let mut buffer = [0u8; 20];
    for &(value, expected_le, expected_be) in cases {
        std::dbg!(value);

        // Little endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i64(&mut writer, Endian::Little, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_le.len());
        assert_eq!(&buffer[..expected_le.len()], expected_le);

        // Big endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i64(&mut writer, Endian::Big, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_be.len());
        assert_eq!(&buffer[..expected_be.len()], expected_be);
    }
}

#[test]
fn test_encode_i128() {
    #[rustfmt::skip]
    let cases: &[(i128, &[u8], &[u8])] = &[
        (0, &[0], &[0]),
        (2, &[4], &[4]),
        (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]),
        (
            16_000,
            &[super::U16_BYTE, 0, 125],
            &[super::U16_BYTE, 125, 0],
        ),
        (
            40_000,
            &[super::U32_BYTE, 128, 56, 1, 0],
            &[super::U32_BYTE, 0, 1, 56, 128],
        ),
        (
            3_000_000_000,
            &[super::U64_BYTE, 0, 188, 160, 101, 1, 0, 0, 0],
            &[super::U64_BYTE, 0, 0, 0, 1, 101, 160, 188, 0],
        ),
        (
            11_000_000_000_000_000_000,
            &[
                super::U128_BYTE,
                0, 0, 152, 98, 112, 179, 79, 49,
                1, 0, 0, 0, 0, 0, 0, 0,
            ],
            &[
                super::U128_BYTE,
                0, 0, 0, 0, 0, 0, 0, 1,
                49, 79, 179, 112, 98, 152, 0, 0,
            ],
        ),
        (
            i128::MAX - 1,
            &[
                super::U128_BYTE,
                252, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 255,
            ],
            &[
                super::U128_BYTE,
                255, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 252,
            ],
        ),
        (
            i128::MAX,
            &[
                super::U128_BYTE,
                254, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 255,
            ],
            &[
                super::U128_BYTE,
                255, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 254,
            ],
        ),
    ];

    use crate::enc::write::SliceWriter;
    let mut buffer = [0u8; 20];
    for &(value, expected_le, expected_be) in cases {
        std::dbg!(value);

        // Little endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i128(&mut writer, Endian::Little, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_le.len());
        assert_eq!(&buffer[..expected_le.len()], expected_le);

        // Big endian
        let mut writer = SliceWriter::new(&mut buffer);
        varint_encode_i128(&mut writer, Endian::Big, value).unwrap();

        assert_eq!(writer.bytes_written(), expected_be.len());
        assert_eq!(&buffer[..expected_be.len()], expected_be);
    }
}
<|endoftext|>


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

use config::Config;

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

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

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

#[derive(PartialEq, Debug)]
pub struct GameObject {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
}

impl GameObject {
    fn new(x: f64, y: f64, v: f64, theta: f64) -> GameObject {
        GameObject {
            x: x,
            y: y,
            v: v,
            theta: theta,
        }
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

const ASTROID_LARGE: i64 = 3;

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn test_game_object_factories() {
        expect!(GameObject::new(2.0, 3.0, 5.0, 7.0)).to(be_equal_to(GameObject {
            x: 2.0,
            y: 3.0,
            v: 5.0,
            theta: 7.0,
        }));
    }
}
<commit_msg>Add v field to bullets<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use graphics::math::{transform_pos, rotate_radians};
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use rand::distributions::{Range, IndependentSample, Normal};
use rand::distributions::range::SampleRange;
use std::f64::consts::PI;
use intersect::{lines_intersect, point_in};
use point::Point;

use config::Config;

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

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

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

#[derive(PartialEq, Debug)]
pub struct GameObject {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
}

impl GameObject {
    fn new(x: f64, y: f64, v: f64, theta: f64) -> GameObject {
        GameObject {
            x: x,
            y: y,
            v: v,
            theta: theta,
        }
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

const ASTROID_LARGE: i64 = 3;

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn test_game_object_factories() {
        expect!(GameObject::new(2.0, 3.0, 5.0, 7.0)).to(be_equal_to(GameObject {
            x: 2.0,
            y: 3.0,
            v: 5.0,
            theta: 7.0,
        }));
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::OsStr;
use std::io;
use std::mem;
use std::ptr;
use std::time::Duration;

use std::os::windows::prelude::*;

use self::libc::c_void;

use super::ffi::*;
use ::{SerialDevice,SerialPortSettings};

/// A serial port implementation for Windows COM ports.
///
/// The port will be closed when the value is dropped.
pub struct COMPort {
    handle: HANDLE,
    timeout: Duration
}

unsafe impl Send for COMPort {}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial::windows::COMPort::open("COM1").unwrap();
    /// ```
    ///
    /// ## Errors
    ///
    /// * `NoDevice` if the device could not be opened. This could indicate that the device is
    ///   already in use.
    /// * `InvalidInput` if `port` is not a valid device name.
    /// * `Io` for any other I/O error while opening or initializing the device.
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> ::Result<Self> {
        let mut name: Vec<u16> = port.as_ref().encode_wide().collect();
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as HANDLE)
        };

        let timeout = Duration::from_millis(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(super::error::last_os_error())
        }
    }

    fn escape_comm_function(&mut self, function: DWORD) -> ::Result<()> {
        match unsafe { EscapeCommFunction(self.handle, function) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(())
        }
    }

    fn read_pin(&mut self, pin: DWORD) -> ::Result<bool> {
        let mut status: DWORD = unsafe { mem::uninitialized() };

        match unsafe { GetCommModemStatus(self.handle, &mut status) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(status & pin != 0)
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl AsRawHandle for COMPort {
    fn as_raw_handle(&self) -> RawHandle {
        unsafe {
            mem::transmute(self.handle)
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "Operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(())
        }
    }
}

impl SerialDevice for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> ::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(COMSettings { inner: dcb })

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> ::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(())
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> ::Result<()> {
        let milliseconds = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000;

        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: milliseconds as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(super::error::last_os_error());
        }

        self.timeout = timeout;
        Ok(())
    }

    fn set_rts(&mut self, level: bool) -> ::Result<()> {
        if level {
            self.escape_comm_function(SETRTS)
        }
        else {
            self.escape_comm_function(CLRRTS)
        }
    }

    fn set_dtr(&mut self, level: bool) -> ::Result<()> {
        if level {
            self.escape_comm_function(SETDTR)
        }
        else {
            self.escape_comm_function(CLRDTR)
        }
    }

    fn read_cts(&mut self) -> ::Result<bool> {
        self.read_pin(MS_CTS_ON)
    }

    fn read_dsr(&mut self) -> ::Result<bool> {
        self.read_pin(MS_DSR_ON)
    }

    fn read_ri(&mut self) -> ::Result<bool> {
        self.read_pin(MS_RING_ON)
    }

    fn read_cd(&mut self) -> ::Result<bool> {
        self.read_pin(MS_RLSD_ON)
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(::Baud110),
            CBR_300    => Some(::Baud300),
            CBR_600    => Some(::Baud600),
            CBR_1200   => Some(::Baud1200),
            CBR_2400   => Some(::Baud2400),
            CBR_4800   => Some(::Baud4800),
            CBR_9600   => Some(::Baud9600),
            CBR_14400  => Some(::BaudOther(14400)),
            CBR_19200  => Some(::Baud19200),
            CBR_38400  => Some(::Baud38400),
            CBR_56000  => Some(::BaudOther(56000)),
            CBR_57600  => Some(::Baud57600),
            CBR_115200 => Some(::Baud115200),
            CBR_128000 => Some(::BaudOther(128000)),
            CBR_256000 => Some(::BaudOther(256000)),
            n          => Some(::BaudOther(n as usize))
        }
    }

    fn char_size(&self) -> Option<::CharSize> {
        match self.inner.ByteSize {
            5 => Some(::Bits5),
            6 => Some(::Bits6),
            7 => Some(::Bits7),
            8 => Some(::Bits8),
            _ => None
        }
    }

    fn parity(&self) -> Option<::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(::ParityOdd),
            EVENPARITY => Some(::ParityEven),
            NOPARITY   => Some(::ParityNone),
            _          => None
        }
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(::Stop2),
            ONESTOPBIT  => Some(::Stop1),
            _           => None
        }
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(::FlowSoftware)
        }
        else {
            Some(::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.inner.BaudRate = match baud_rate {
            ::Baud110      => CBR_110,
            ::Baud300      => CBR_300,
            ::Baud600      => CBR_600,
            ::Baud1200     => CBR_1200,
            ::Baud2400     => CBR_2400,
            ::Baud4800     => CBR_4800,
            ::Baud9600     => CBR_9600,
            ::Baud19200    => CBR_19200,
            ::Baud38400    => CBR_38400,
            ::Baud57600    => CBR_57600,
            ::Baud115200   => CBR_115200,
            ::BaudOther(n) => n as DWORD
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: ::CharSize) {
        self.inner.ByteSize = match char_size {
            ::Bits5 => 5,
            ::Bits6 => 6,
            ::Bits7 => 7,
            ::Bits8 => 8
        }
    }

    fn set_parity(&mut self, parity: ::Parity) {
        self.inner.Parity = match parity {
            ::ParityNone => NOPARITY,
            ::ParityOdd  => ODDPARITY,
            ::ParityEven => EVENPARITY
        }
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) {
        self.inner.StopBits = match stop_bits {
            ::Stop1 => ONESTOPBIT,
            ::Stop2 => TWOSTOPBITS
        }
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) {
        match flow_control {
            ::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            },
            ::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            },
            ::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<commit_msg>[closes #18] prepends Win32 device namespace to port names<commit_after>extern crate libc;

use std::ffi::OsStr;
use std::io;
use std::mem;
use std::ptr;
use std::time::Duration;

use std::os::windows::prelude::*;

use self::libc::c_void;

use super::ffi::*;
use ::{SerialDevice,SerialPortSettings};

/// A serial port implementation for Windows COM ports.
///
/// The port will be closed when the value is dropped.
pub struct COMPort {
    handle: HANDLE,
    timeout: Duration
}

unsafe impl Send for COMPort {}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial::windows::COMPort::open("COM1").unwrap();
    /// ```
    ///
    /// ## Errors
    ///
    /// * `NoDevice` if the device could not be opened. This could indicate that the device is
    ///   already in use.
    /// * `InvalidInput` if `port` is not a valid device name.
    /// * `Io` for any other I/O error while opening or initializing the device.
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> ::Result<Self> {
        let mut name = Vec::<u16>::new();

        name.extend(OsStr::new("\\\\.\\").encode_wide());
        name.extend(port.as_ref().encode_wide());
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as HANDLE)
        };

        let timeout = Duration::from_millis(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(super::error::last_os_error())
        }
    }

    fn escape_comm_function(&mut self, function: DWORD) -> ::Result<()> {
        match unsafe { EscapeCommFunction(self.handle, function) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(())
        }
    }

    fn read_pin(&mut self, pin: DWORD) -> ::Result<bool> {
        let mut status: DWORD = unsafe { mem::uninitialized() };

        match unsafe { GetCommModemStatus(self.handle, &mut status) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(status & pin != 0)
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl AsRawHandle for COMPort {
    fn as_raw_handle(&self) -> RawHandle {
        unsafe {
            mem::transmute(self.handle)
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "Operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(())
        }
    }
}

impl SerialDevice for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> ::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(COMSettings { inner: dcb })

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> ::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(super::error::last_os_error()),
            _ => Ok(())
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> ::Result<()> {
        let milliseconds = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000;

        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: milliseconds as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(super::error::last_os_error());
        }

        self.timeout = timeout;
        Ok(())
    }

    fn set_rts(&mut self, level: bool) -> ::Result<()> {
        if level {
            self.escape_comm_function(SETRTS)
        }
        else {
            self.escape_comm_function(CLRRTS)
        }
    }

    fn set_dtr(&mut self, level: bool) -> ::Result<()> {
        if level {
            self.escape_comm_function(SETDTR)
        }
        else {
            self.escape_comm_function(CLRDTR)
        }
    }

    fn read_cts(&mut self) -> ::Result<bool> {
        self.read_pin(MS_CTS_ON)
    }

    fn read_dsr(&mut self) -> ::Result<bool> {
        self.read_pin(MS_DSR_ON)
    }

    fn read_ri(&mut self) -> ::Result<bool> {
        self.read_pin(MS_RING_ON)
    }

    fn read_cd(&mut self) -> ::Result<bool> {
        self.read_pin(MS_RLSD_ON)
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(::Baud110),
            CBR_300    => Some(::Baud300),
            CBR_600    => Some(::Baud600),
            CBR_1200   => Some(::Baud1200),
            CBR_2400   => Some(::Baud2400),
            CBR_4800   => Some(::Baud4800),
            CBR_9600   => Some(::Baud9600),
            CBR_14400  => Some(::BaudOther(14400)),
            CBR_19200  => Some(::Baud19200),
            CBR_38400  => Some(::Baud38400),
            CBR_56000  => Some(::BaudOther(56000)),
            CBR_57600  => Some(::Baud57600),
            CBR_115200 => Some(::Baud115200),
            CBR_128000 => Some(::BaudOther(128000)),
            CBR_256000 => Some(::BaudOther(256000)),
            n          => Some(::BaudOther(n as usize))
        }
    }

    fn char_size(&self) -> Option<::CharSize> {
        match self.inner.ByteSize {
            5 => Some(::Bits5),
            6 => Some(::Bits6),
            7 => Some(::Bits7),
            8 => Some(::Bits8),
            _ => None
        }
    }

    fn parity(&self) -> Option<::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(::ParityOdd),
            EVENPARITY => Some(::ParityEven),
            NOPARITY   => Some(::ParityNone),
            _          => None
        }
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(::Stop2),
            ONESTOPBIT  => Some(::Stop1),
            _           => None
        }
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(::FlowSoftware)
        }
        else {
            Some(::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.inner.BaudRate = match baud_rate {
            ::Baud110      => CBR_110,
            ::Baud300      => CBR_300,
            ::Baud600      => CBR_600,
            ::Baud1200     => CBR_1200,
            ::Baud2400     => CBR_2400,
            ::Baud4800     => CBR_4800,
            ::Baud9600     => CBR_9600,
            ::Baud19200    => CBR_19200,
            ::Baud38400    => CBR_38400,
            ::Baud57600    => CBR_57600,
            ::Baud115200   => CBR_115200,
            ::BaudOther(n) => n as DWORD
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: ::CharSize) {
        self.inner.ByteSize = match char_size {
            ::Bits5 => 5,
            ::Bits6 => 6,
            ::Bits7 => 7,
            ::Bits8 => 8
        }
    }

    fn set_parity(&mut self, parity: ::Parity) {
        self.inner.Parity = match parity {
            ::ParityNone => NOPARITY,
            ::ParityOdd  => ODDPARITY,
            ::ParityEven => EVENPARITY
        }
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) {
        self.inner.StopBits = match stop_bits {
            ::Stop1 => ONESTOPBIT,
            ::Stop2 => TWOSTOPBITS
        }
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) {
        match flow_control {
            ::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            },
            ::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            },
            ::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<|endoftext|>