<commit_before>#[cfg(feature = "bigdecimal")]
mod bigdecimal {
    extern crate bigdecimal;
    extern crate num_bigint;
    extern crate num_integer;
    extern crate num_traits;

    use self::bigdecimal::BigDecimal;
    use self::num_bigint::{BigInt, BigUint, Sign};
    use self::num_integer::Integer;
    use self::num_traits::{Signed, ToPrimitive, Zero};
    use std::io::prelude::*;

    use deserialize::{self, FromSql};
    use pg::data_types::PgNumeric;
    use pg::Pg;
    use serialize::{self, Output, ToSql};
    use sql_types::Numeric;

    #[cfg(feature = "unstable")]
    use std::convert::{TryFrom, TryInto};
    #[cfg(feature = "unstable")]
    use std::error::Error;

    /// Iterator over the digits of a big uint in base 10k.
    /// The digits will be returned in little endian order.
    struct ToBase10000(Option<BigUint>);

    impl Iterator for ToBase10000 {
        type Item = i16;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.take().map(|v| {
                let (div, rem) = v.div_rem(&BigUint::from(10_000u16));
                if !div.is_zero() {
                    self.0 = Some(div);
                }
                rem.to_i16().expect("10000 always fits in an i16")
            })
        }
    }

    fn pg_decimal_to_bigdecimal(numeric: &PgNumeric) -> deserialize::Result<BigDecimal> {
        let (sign, weight, scale, digits) = match *numeric {
            PgNumeric::Positive {
                weight,
                scale,
                ref digits,
            } => (Sign::Plus, weight, scale, digits),
            PgNumeric::Negative {
                weight,
                scale,
                ref digits,
            } => (Sign::Minus, weight, scale, digits),
            PgNumeric::NaN => return Err(Box::from("NaN is not (yet) supported in BigDecimal")),
        };

        let mut result = BigUint::default();
        let count = digits.len() as i64;
        for digit in digits {
            result *= BigUint::from(10_000u64);
            result += BigUint::from(*digit as u64);
        }
        // First digit got factor 10_000^(digits.len() - 1), but should get 10_000^weight
        let correction_exp = 4 * (i64::from(weight) - count + 1);
        let result = BigDecimal::new(BigInt::from_biguint(sign, result), -correction_exp)
            .with_scale(i64::from(scale));
        Ok(result)
    }

    #[cfg(feature = "unstable")]
    impl<'a> TryFrom<&'a PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self> {
            pg_decimal_to_bigdecimal(numeric)
        }
    }

    #[cfg(feature = "unstable")]
    impl TryFrom<PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
            (&numeric).try_into()
        }
    }

    impl<'a> From<&'a BigDecimal> for PgNumeric {
        fn from(decimal: &'a BigDecimal) -> Self {
            let (mut integer, scale) = decimal.as_bigint_and_exponent();
            let scale = scale as u16;
            integer = integer.abs();

            // Ensure that the decimal will always lie on a digit boundary
            for _ in 0..(4 - scale % 4) {
                // NOTE: Assignment to `mul` is intended to avoid `#[deny(assign_op_pattern)]` on nightly
                //       despite lack of `std::ops::MulAssign` impl for `BigInt`.
                let mul = integer * 10;
                integer = mul;
            }
            let integer = integer.to_biguint().expect("integer is always positive");

            let mut digits = ToBase10000(Some(integer)).collect::<Vec<_>>();
            digits.reverse();
            let digits_after_decimal = scale as u16 / 4 + 1;
            let weight = digits.len() as i16 - digits_after_decimal as i16 - 1;

            let unnecessary_zeroes = if weight >= 0 {
                let index_of_decimal = (weight + 1) as usize;
                digits
                    .get(index_of_decimal..)
                    .expect("enough digits exist")
                    .iter()
                    .rev()
                    .take_while(|i| i.is_zero())
                    .count()
            } else {
                0
            };

            let relevant_digits = digits.len() - unnecessary_zeroes;
            digits.truncate(relevant_digits);

            match decimal.sign() {
                Sign::Plus => PgNumeric::Positive {
                    digits,
                    scale,
                    weight,
                },
                Sign::Minus => PgNumeric::Negative {
                    digits,
                    scale,
                    weight,
                },
                Sign::NoSign => PgNumeric::Positive {
                    digits: vec![0],
                    scale: 0,
                    weight: 0,
                },
            }
        }
    }

    impl From<BigDecimal> for PgNumeric {
        fn from(bigdecimal: BigDecimal) -> Self {
            (&bigdecimal).into()
        }
    }

    impl ToSql<Numeric, Pg> for BigDecimal {
        fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
            let numeric = PgNumeric::from(self);
            ToSql::<Numeric, Pg>::to_sql(&numeric, out)
        }
    }

    impl FromSql<Numeric, Pg> for BigDecimal {
        fn from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self> {
            // FIXME: Use the TryFrom impl when try_from is stable
            let numeric = PgNumeric::from_sql(numeric)?;
            pg_decimal_to_bigdecimal(&numeric)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;
        use std::str::FromStr;

        #[test]
        fn bigdecimal_to_pgnumeric_converts_digits_to_base_10000() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![10],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 0],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 0,
                digits: vec![1, 0, 0],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_properly_adjusts_scale() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.0").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 2,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000.0001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 4,
                digits: vec![1, 0, 0, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("0.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: -1,
                scale: 1,
                digits: vec![1000],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_retains_sign() {
            let decimal = BigDecimal::from_str("123.456").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("-123.456").unwrap();
            let expected = PgNumeric::Negative {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        #[cfg(feature = "unstable")]
        fn pg_numeric_to_bigdecimal_works() {
            let expected = BigDecimal::from_str("123.456").unwrap();
            let pg_numeric = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);

            let expected = BigDecimal::from_str("-56.78").unwrap();
            let pg_numeric = PgNumeric::Negative {
                weight: 0,
                scale: 2,
                digits: vec![56, 7800],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);
        }
    }
}
<commit_msg>Use `allow` lint instead of changing syntax<commit_after>#[cfg(feature = "bigdecimal")]
mod bigdecimal {
    extern crate bigdecimal;
    extern crate num_bigint;
    extern crate num_integer;
    extern crate num_traits;

    use self::bigdecimal::BigDecimal;
    use self::num_bigint::{BigInt, BigUint, Sign};
    use self::num_integer::Integer;
    use self::num_traits::{Signed, ToPrimitive, Zero};
    use std::io::prelude::*;

    use deserialize::{self, FromSql};
    use pg::data_types::PgNumeric;
    use pg::Pg;
    use serialize::{self, Output, ToSql};
    use sql_types::Numeric;

    #[cfg(feature = "unstable")]
    use std::convert::{TryFrom, TryInto};
    #[cfg(feature = "unstable")]
    use std::error::Error;

    /// Iterator over the digits of a big uint in base 10k.
    /// The digits will be returned in little endian order.
    struct ToBase10000(Option<BigUint>);

    impl Iterator for ToBase10000 {
        type Item = i16;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.take().map(|v| {
                let (div, rem) = v.div_rem(&BigUint::from(10_000u16));
                if !div.is_zero() {
                    self.0 = Some(div);
                }
                rem.to_i16().expect("10000 always fits in an i16")
            })
        }
    }

    fn pg_decimal_to_bigdecimal(numeric: &PgNumeric) -> deserialize::Result<BigDecimal> {
        let (sign, weight, scale, digits) = match *numeric {
            PgNumeric::Positive {
                weight,
                scale,
                ref digits,
            } => (Sign::Plus, weight, scale, digits),
            PgNumeric::Negative {
                weight,
                scale,
                ref digits,
            } => (Sign::Minus, weight, scale, digits),
            PgNumeric::NaN => return Err(Box::from("NaN is not (yet) supported in BigDecimal")),
        };

        let mut result = BigUint::default();
        let count = digits.len() as i64;
        for digit in digits {
            result *= BigUint::from(10_000u64);
            result += BigUint::from(*digit as u64);
        }
        // First digit got factor 10_000^(digits.len() - 1), but should get 10_000^weight
        let correction_exp = 4 * (i64::from(weight) - count + 1);
        let result = BigDecimal::new(BigInt::from_biguint(sign, result), -correction_exp)
            .with_scale(i64::from(scale));
        Ok(result)
    }

    #[cfg(feature = "unstable")]
    impl<'a> TryFrom<&'a PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self> {
            pg_decimal_to_bigdecimal(numeric)
        }
    }

    #[cfg(feature = "unstable")]
    impl TryFrom<PgNumeric> for BigDecimal {
        type Error = Box<Error + Send + Sync>;

        fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
            (&numeric).try_into()
        }
    }

    impl<'a> From<&'a BigDecimal> for PgNumeric {
        fn from(decimal: &'a BigDecimal) -> Self {
            let (mut integer, scale) = decimal.as_bigint_and_exponent();
            let scale = scale as u16;
            integer = integer.abs();

            // Ensure that the decimal will always lie on a digit boundary
            for _ in 0..(4 - scale % 4) {
                #[allow(assign_op_pattern)] // No `std::ops::MulAssign` impl for `BigInt`
                integer = integer * 10;
            }
            let integer = integer.to_biguint().expect("integer is always positive");

            let mut digits = ToBase10000(Some(integer)).collect::<Vec<_>>();
            digits.reverse();
            let digits_after_decimal = scale as u16 / 4 + 1;
            let weight = digits.len() as i16 - digits_after_decimal as i16 - 1;

            let unnecessary_zeroes = if weight >= 0 {
                let index_of_decimal = (weight + 1) as usize;
                digits
                    .get(index_of_decimal..)
                    .expect("enough digits exist")
                    .iter()
                    .rev()
                    .take_while(|i| i.is_zero())
                    .count()
            } else {
                0
            };

            let relevant_digits = digits.len() - unnecessary_zeroes;
            digits.truncate(relevant_digits);

            match decimal.sign() {
                Sign::Plus => PgNumeric::Positive {
                    digits,
                    scale,
                    weight,
                },
                Sign::Minus => PgNumeric::Negative {
                    digits,
                    scale,
                    weight,
                },
                Sign::NoSign => PgNumeric::Positive {
                    digits: vec![0],
                    scale: 0,
                    weight: 0,
                },
            }
        }
    }

    impl From<BigDecimal> for PgNumeric {
        fn from(bigdecimal: BigDecimal) -> Self {
            (&bigdecimal).into()
        }
    }

    impl ToSql<Numeric, Pg> for BigDecimal {
        fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
            let numeric = PgNumeric::from(self);
            ToSql::<Numeric, Pg>::to_sql(&numeric, out)
        }
    }

    impl FromSql<Numeric, Pg> for BigDecimal {
        fn from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self> {
            // FIXME: Use the TryFrom impl when try_from is stable
            let numeric = PgNumeric::from_sql(numeric)?;
            pg_decimal_to_bigdecimal(&numeric)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;
        use std::str::FromStr;

        #[test]
        fn bigdecimal_to_pgnumeric_converts_digits_to_base_10000() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![10],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 0],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("10001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 1,
                scale: 0,
                digits: vec![1, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 0,
                digits: vec![1, 0, 0],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_properly_adjusts_scale() {
            let decimal = BigDecimal::from_str("1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 0,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.0").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 1,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("1.10").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 2,
                digits: vec![1, 1000],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("100000000.0001").unwrap();
            let expected = PgNumeric::Positive {
                weight: 2,
                scale: 4,
                digits: vec![1, 0, 0, 1],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("0.1").unwrap();
            let expected = PgNumeric::Positive {
                weight: -1,
                scale: 1,
                digits: vec![1000],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        fn bigdecimal_to_pg_numeric_retains_sign() {
            let decimal = BigDecimal::from_str("123.456").unwrap();
            let expected = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());

            let decimal = BigDecimal::from_str("-123.456").unwrap();
            let expected = PgNumeric::Negative {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            assert_eq!(expected, decimal.into());
        }

        #[test]
        #[cfg(feature = "unstable")]
        fn pg_numeric_to_bigdecimal_works() {
            let expected = BigDecimal::from_str("123.456").unwrap();
            let pg_numeric = PgNumeric::Positive {
                weight: 0,
                scale: 3,
                digits: vec![123, 4560],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);

            let expected = BigDecimal::from_str("-56.78").unwrap();
            let pg_numeric = PgNumeric::Negative {
                weight: 0,
                scale: 2,
                digits: vec![56, 7800],
            };
            let res: BigDecimal = pg_numeric.try_into().unwrap();
            assert_eq!(res, expected);
        }
    }
}
<|endoftext|>


<commit_before>#![deny(indirect_structural_match)]

#[derive(PartialEq, Eq)]
enum O<T> {
    Some(*const T), // Can also use PhantomData<T>
    None,
}

struct B;

const C: &[O<B>] = &[O::None];

fn main() {
    let x = O::None;
    match &[x][..] {
        C => (),
        _ => (),
    }
}
<commit_msg>FIXME: ignore test that ICEs<commit_after>// FIXME: This still ICEs.
//
// ignore-test

#![deny(indirect_structural_match)]

#[derive(PartialEq, Eq)]
enum O<T> {
    Some(*const T), // Can also use PhantomData<T>
    None,
}

struct B;

const C: &[O<B>] = &[O::None];

fn main() {
    let x = O::None;
    match &[x][..] {
        C => (),
        _ => (),
    }
}
<|endoftext|>


<commit_before>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is a pawn
/// promotion, otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn "en-passant file" is `NO_ENPASSANT_FILE`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `en_passant_file` is the
    /// vertical line on which there was a passing pawn before the
    /// move was played. `castling` are the castling rights before the
    /// move was played. `promoted_piece_code` should be a number
    /// between `0` and `3` and is used only when the `move_type` is a
    /// pawn promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Decodes the promoted piece type from the raw value of "aux
    /// data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Normal move type
pub const MOVE_NORMAL: MoveType = 0;

/// En-passant move type
pub const MOVE_ENPASSANT: MoveType = 1;

/// Pawn promotion move type
pub const MOVE_PROMOTION: MoveType = 2;

/// Castling move type
pub const MOVE_CASTLING: MoveType = 3;

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use position::castling_rights::CastlingRights;

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<commit_msg>more doc improvements<commit_after>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is a pawn
/// promotion, otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn, "en-passant file" should be `NO_ENPASSANT_FILE`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `castling` are the
    /// castling rights before the move was
    /// played. `promoted_piece_code` should be a number between `0`
    /// and `3` and is used only when the `move_type` is a pawn
    /// promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Decodes the promoted piece type from the raw value of "aux
    /// data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Normal move type
pub const MOVE_NORMAL: MoveType = 0;

/// En-passant move type
pub const MOVE_ENPASSANT: MoveType = 1;

/// Pawn promotion move type
pub const MOVE_PROMOTION: MoveType = 2;

/// Castling move type
pub const MOVE_CASTLING: MoveType = 3;

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use position::castling_rights::CastlingRights;

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
// TODO: Falsely triggers for async/await:
//   see https://github.com/rust-lang/rust-clippy/issues/5360
// clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use std::io;
use std::net::Ipv4Addr;

use futures::channel::mpsc;
use futures::{try_join, SinkExt, Stream, StreamExt};
use nails::execution::{stream_for, ChildInput, ChildOutput, ExitCode};
use nails::Config;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio::signal::unix::{signal, Signal, SignalKind};

pub enum NailgunClientError {
  PreConnect(String),
  PostConnect(String),
  BrokenPipe,
  KeyboardInterrupt,
}

fn handle_postconnect_stdio(err: io::Error, msg: &str) -> NailgunClientError {
  if err.kind() == io::ErrorKind::BrokenPipe {
    // A BrokenPipe error is a semi-expected error caused when stdout/stderr closes, and which
    // the Python runtime has a special error type and handling for.
    NailgunClientError::BrokenPipe
  } else {
    NailgunClientError::PostConnect(format!("{}: {}", msg, err))
  }
}

async fn handle_client_output(
  mut stdio_read: impl Stream<Item = ChildOutput> + Unpin,
  mut signal_stream: Signal,
  child: &mut nails::client::Child,
) -> Result<(), NailgunClientError> {
  let mut stdout = tokio::io::stdout();
  let mut stderr = tokio::io::stderr();
  let mut is_exiting = false;
  loop {
    tokio::select! {
      output = stdio_read.next() => {
        match output {
          Some(ChildOutput::Stdout(bytes)) => {
            stdout.write_all(&bytes).await.map_err(|err| handle_postconnect_stdio(err, "Failed to write to stdout"))?
          },
          Some(ChildOutput::Stderr(bytes)) => {
            stderr.write_all(&bytes).await.map_err(|err| handle_postconnect_stdio(err, "Failed to write to stderr"))?
          },
          None => break,
        }
      }
      _ = signal_stream.recv() => {
          if is_exiting {
              // This is the second signal: exit uncleanly to drop the child rather than waiting
              // further.
              return Err(NailgunClientError::KeyboardInterrupt);
          } else {
              // This is the first signal: trigger shutdown of the Child, which will request that
              // the server interrupt the run.
              child.shutdown().await;
              is_exiting = true;
          }
      }
    }
  }
  try_join!(stdout.flush(), stderr.flush())
    .map_err(|err| handle_postconnect_stdio(err, "Failed to flush stdio"))?;
  Ok(())
}

async fn handle_client_input(mut stdin_write: mpsc::Sender<ChildInput>) -> Result<(), io::Error> {
  use nails::execution::send_to_io;
  let mut stdin = stream_for(tokio::io::stdin());
  while let Some(input_bytes) = stdin.next().await {
    stdin_write
      .send(ChildInput::Stdin(input_bytes?))
      .await
      .map_err(send_to_io)?;
  }
  Ok(())
}

///
/// Execute the given command on the given localhost port.
///
/// This method installs (global!: see below) signal handling such that:
///   1. the first SIGINT will cause the client to attempt to exit gracefully.
///   2. the second SIGINT will eagerly exit the client without waiting for the server.
///
/// NB: This method installs a signal handler that will affect signal handling throughout the
/// entire process. Because of this, it should only be used in a process that is relatively
/// dedicated to the task of connecting to a nailgun server.
///
pub async fn client_execute(
  port: u16,
  command: String,
  args: Vec<String>,
  env: Vec<(String, String)>,
) -> Result<i32, NailgunClientError> {
  use nails::execution::{child_channel, Command};

  let working_dir =
    std::env::current_dir().map_err(|e| NailgunClientError::PreConnect(e.to_string()))?;

  let config = Config::default();
  let command = Command {
    command,
    args,
    env,
    working_dir,
  };

  let signal_stream = signal(SignalKind::interrupt()).map_err(|err| {
    NailgunClientError::PreConnect(format!("Failed to install interrupt handler: {}", err))
  })?;
  let socket = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), port))
    .await
    .map_err(|err| {
      NailgunClientError::PreConnect(format!("Failed to connect to localhost: {}", err))
    })?;

  let mut child = nails::client::handle_connection(config, socket, command, async {
    let (stdin_write, stdin_read) = child_channel::<ChildInput>();
    let _input_handler = tokio::spawn(handle_client_input(stdin_write));
    stdin_read
  })
  .await
  .map_err(|err| NailgunClientError::PreConnect(format!("Failed to start: {}", err)))?;

  handle_client_output(
    child.output_stream.take().unwrap(),
    signal_stream,
    &mut child,
  )
  .await?;

  let exit_code: ExitCode = child.wait().await.map_err(|err| {
    let err_str = match err.to_string().as_str() {
      "Client exited before the server's result could be returned." => {
        "The pantsd process was killed during the run.\n\nIf this was not intentionally done by you, \
          Pants may have been killed by the operating system due to memory overconsumption \
          (i.e. OOM-killed). You can set the global option `--pantsd-max-memory-usage` to reduce \
          Pantsd's memory consumption by retaining less in its in-memory cache \
          (run `./pants help-advanced global`). You can also disable pantsd with the global \
          option `--pantsd` to avoid persisting memory across Pants runs, although you will miss \
          out on additional caching.\n\nIf neither of those help, please consider filing a \
          GitHub issue or reaching out on Slack so that we can investigate the possible memory \
          overconsumption (https://www.pantsbuild.org/docs/getting-help)."
          .to_owned()
      }
      _ => format!("Failed during execution: {}", err),
    };
    NailgunClientError::PostConnect(err_str)
  })?;

  Ok(exit_code.0)
}
<commit_msg>Make the pantsd crash error message more precise. (#12512)<commit_after>// Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

#![deny(warnings)]
// Enable all clippy lints except for many of the pedantic ones. It's a shame this needs to be copied and pasted across crates, but there doesn't appear to be a way to include inner attributes from a common source.
#![deny(
  clippy::all,
  clippy::default_trait_access,
  clippy::expl_impl_clone_on_copy,
  clippy::if_not_else,
  clippy::needless_continue,
  clippy::unseparated_literal_suffix,
// TODO: Falsely triggers for async/await:
//   see https://github.com/rust-lang/rust-clippy/issues/5360
// clippy::used_underscore_binding
)]
// It is often more clear to show that nothing is being moved.
#![allow(clippy::match_ref_pats)]
// Subjective style.
#![allow(
  clippy::len_without_is_empty,
  clippy::redundant_field_names,
  clippy::too_many_arguments
)]
// Default isn't as big a deal as people seem to think it is.
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
// Arc<Mutex> can be more clear than needing to grok Orderings:
#![allow(clippy::mutex_atomic)]

use std::io;
use std::net::Ipv4Addr;

use futures::channel::mpsc;
use futures::{try_join, SinkExt, Stream, StreamExt};
use nails::execution::{stream_for, ChildInput, ChildOutput, ExitCode};
use nails::Config;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio::signal::unix::{signal, Signal, SignalKind};

pub enum NailgunClientError {
  PreConnect(String),
  PostConnect(String),
  BrokenPipe,
  KeyboardInterrupt,
}

fn handle_postconnect_stdio(err: io::Error, msg: &str) -> NailgunClientError {
  if err.kind() == io::ErrorKind::BrokenPipe {
    // A BrokenPipe error is a semi-expected error caused when stdout/stderr closes, and which
    // the Python runtime has a special error type and handling for.
    NailgunClientError::BrokenPipe
  } else {
    NailgunClientError::PostConnect(format!("{}: {}", msg, err))
  }
}

async fn handle_client_output(
  mut stdio_read: impl Stream<Item = ChildOutput> + Unpin,
  mut signal_stream: Signal,
  child: &mut nails::client::Child,
) -> Result<(), NailgunClientError> {
  let mut stdout = tokio::io::stdout();
  let mut stderr = tokio::io::stderr();
  let mut is_exiting = false;
  loop {
    tokio::select! {
      output = stdio_read.next() => {
        match output {
          Some(ChildOutput::Stdout(bytes)) => {
            stdout.write_all(&bytes).await.map_err(|err| handle_postconnect_stdio(err, "Failed to write to stdout"))?
          },
          Some(ChildOutput::Stderr(bytes)) => {
            stderr.write_all(&bytes).await.map_err(|err| handle_postconnect_stdio(err, "Failed to write to stderr"))?
          },
          None => break,
        }
      }
      _ = signal_stream.recv() => {
          if is_exiting {
              // This is the second signal: exit uncleanly to drop the child rather than waiting
              // further.
              return Err(NailgunClientError::KeyboardInterrupt);
          } else {
              // This is the first signal: trigger shutdown of the Child, which will request that
              // the server interrupt the run.
              child.shutdown().await;
              is_exiting = true;
          }
      }
    }
  }
  try_join!(stdout.flush(), stderr.flush())
    .map_err(|err| handle_postconnect_stdio(err, "Failed to flush stdio"))?;
  Ok(())
}

async fn handle_client_input(mut stdin_write: mpsc::Sender<ChildInput>) -> Result<(), io::Error> {
  use nails::execution::send_to_io;
  let mut stdin = stream_for(tokio::io::stdin());
  while let Some(input_bytes) = stdin.next().await {
    stdin_write
      .send(ChildInput::Stdin(input_bytes?))
      .await
      .map_err(send_to_io)?;
  }
  Ok(())
}

///
/// Execute the given command on the given localhost port.
///
/// This method installs (global!: see below) signal handling such that:
///   1. the first SIGINT will cause the client to attempt to exit gracefully.
///   2. the second SIGINT will eagerly exit the client without waiting for the server.
///
/// NB: This method installs a signal handler that will affect signal handling throughout the
/// entire process. Because of this, it should only be used in a process that is relatively
/// dedicated to the task of connecting to a nailgun server.
///
pub async fn client_execute(
  port: u16,
  command: String,
  args: Vec<String>,
  env: Vec<(String, String)>,
) -> Result<i32, NailgunClientError> {
  use nails::execution::{child_channel, Command};

  let working_dir =
    std::env::current_dir().map_err(|e| NailgunClientError::PreConnect(e.to_string()))?;

  let config = Config::default();
  let command = Command {
    command,
    args,
    env,
    working_dir,
  };

  let signal_stream = signal(SignalKind::interrupt()).map_err(|err| {
    NailgunClientError::PreConnect(format!("Failed to install interrupt handler: {}", err))
  })?;
  let socket = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), port))
    .await
    .map_err(|err| {
      NailgunClientError::PreConnect(format!("Failed to connect to localhost: {}", err))
    })?;

  let mut child = nails::client::handle_connection(config, socket, command, async {
    let (stdin_write, stdin_read) = child_channel::<ChildInput>();
    let _input_handler = tokio::spawn(handle_client_input(stdin_write));
    stdin_read
  })
  .await
  .map_err(|err| NailgunClientError::PreConnect(format!("Failed to start: {}", err)))?;

  handle_client_output(
    child.output_stream.take().unwrap(),
    signal_stream,
    &mut child,
  )
  .await?;

  let exit_code: ExitCode = child.wait().await.map_err(|err| {
    let err_str = match err.to_string().as_str() {
      "Client exited before the server's result could be returned." => {
        "The pantsd process was killed during the run.\n\nIf this was not intentionally done by you, \
          Pants may have been killed by the operating system due to memory overconsumption \
          (i.e. OOM-killed). You can set the global option `--pantsd-max-memory-usage` to reduce \
          Pantsd's memory consumption by retaining less in its in-memory cache \
          (run `./pants help-advanced global`). You can also disable pantsd with the global \
          option `--no-pantsd` to avoid persisting memory across Pants runs, although you will miss \
          out on additional caching.\n\nIf neither of those help, please consider filing a \
          GitHub issue or reaching out on Slack so that we can investigate the possible memory \
          overconsumption (https://www.pantsbuild.org/docs/getting-help)."
          .to_owned()
      }
      _ => format!("Failed during execution: {}", err),
    };
    NailgunClientError::PostConnect(err_str)
  })?;

  Ok(exit_code.0)
}
<|endoftext|>


<commit_before>//! 16-bit signed and unsigned font-units

/// 16-bit signed quantity in font design units.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FWord(i16);

/// 16-bit unsigned quantity in font design units.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UfWord(u16);

impl FWord {
    pub fn new(raw: i16) -> Self {
        Self(raw)
    }

    pub fn to_i16(self) -> i16 {
        self.0
    }
}

impl UfWord {
    pub fn new(raw: u16) -> Self {
        Self(raw)
    }

    pub fn to_u16(self) -> u16 {
        self.0
    }
}

impl std::fmt::Display for FWord {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl std::fmt::Display for UfWord {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

crate::newtype_scalar!(FWord, [u8; 2]);
crate::newtype_scalar!(UfWord, [u8; 2]);
//TODO: we can add addition/etc as needed
<commit_msg>[font-types] Add Fword/UfWord to_be_bytes<commit_after>//! 16-bit signed and unsigned font-units

/// 16-bit signed quantity in font design units.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FWord(i16);

/// 16-bit unsigned quantity in font design units.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UfWord(u16);

impl FWord {
    pub fn new(raw: i16) -> Self {
        Self(raw)
    }

    pub fn to_i16(self) -> i16 {
        self.0
    }

    /// The representation of this number as a big-endian byte array.
    pub fn to_be_bytes(self) -> [u8; 2] {
        self.0.to_be_bytes()
    }
}

impl UfWord {
    pub fn new(raw: u16) -> Self {
        Self(raw)
    }

    pub fn to_u16(self) -> u16 {
        self.0
    }

    /// The representation of this number as a big-endian byte array.
    pub fn to_be_bytes(self) -> [u8; 2] {
        self.0.to_be_bytes()
    }
}

impl std::fmt::Display for FWord {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl std::fmt::Display for UfWord {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

crate::newtype_scalar!(FWord, [u8; 2]);
crate::newtype_scalar!(UfWord, [u8; 2]);
//TODO: we can add addition/etc as needed
<|endoftext|>


<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate stdweb;
use stdweb::js_export;

extern crate kay;
use kay::ActorSystem;

extern crate citybound_common;
use citybound_common::*;

use std::panic;

// TODO: not thread safe for now
static mut SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

#[js_export]
pub fn start() {
    panic::set_hook(Box::new(|info| console!(error, info.to_string())));

    js!{ console.log("Before setup") }

    let mut system = kay::ActorSystem::new(kay::Networking::new(
        1,
        vec!["localhost:9999", "ws-client"],
        50_000,
        10,
        1,
    ));
    setup_all(&mut system);

    system.networking_connect();

    let browser_ui_id = citybound_common::browser_ui::BrowserUIID::spawn(&mut system.world());

    system.process_all_messages();

    js!{ console.log("After setup") }

    let mut main_loop = MainLoop {
        browser_ui_id,
        skip_turn: false,
    };

    unsafe { SYSTEM = Box::into_raw(Box::new(system)) };

    main_loop.frame();
}

#[derive(Copy, Clone)]
struct MainLoop {
    browser_ui_id: citybound_common::browser_ui::BrowserUIID,
    skip_turn: bool,
}

impl MainLoop {
    fn frame(&mut self) {
        let system = unsafe { &mut *SYSTEM };
        let world = &mut system.world();

        system.networking_send_and_receive();

        if !self.skip_turn {
            system.process_all_messages();

            self.browser_ui_id.on_frame(world);
            system.process_all_messages();

            system.networking_send_and_receive();
            system.process_all_messages();
        }

        js!{
            window.cbclient.setState(oldState => update(oldState, {
                system: {networkingTurns: {"$set":
                    @{system.networking_debug_all_n_turns()}
                }
            }}));

            window.cbclient.onFrame();
        }

        let mut next = self.clone();

        if self.skip_turn {
            next.skip_turn = false;
        } else {
            let maybe_sleep = system.networking_finish_turn();
            next.skip_turn = maybe_sleep.is_some();
        }

        ::stdweb::web::window().request_animation_frame(move |_| next.frame());
    }
}

mod planning_browser;
pub use planning_browser::*;
<commit_msg>Improve waiting for server in browser<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate stdweb;
use stdweb::js_export;

extern crate kay;
use kay::ActorSystem;

extern crate citybound_common;
use citybound_common::*;

use std::panic;

// TODO: not thread safe for now
static mut SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

#[js_export]
pub fn start() {
    panic::set_hook(Box::new(|info| console!(error, info.to_string())));

    js!{ console.log("Before setup") }

    let mut system = kay::ActorSystem::new(kay::Networking::new(
        1,
        vec!["localhost:9999", "ws-client"],
        50_000,
        10,
        1,
    ));
    setup_all(&mut system);

    system.networking_connect();

    let browser_ui_id = citybound_common::browser_ui::BrowserUIID::spawn(&mut system.world());

    system.process_all_messages();

    js!{ console.log("After setup") }

    let mut main_loop = MainLoop {
        browser_ui_id,
        skip_turns: 0,
    };

    unsafe { SYSTEM = Box::into_raw(Box::new(system)) };

    main_loop.frame();
}

#[derive(Copy, Clone)]
struct MainLoop {
    browser_ui_id: citybound_common::browser_ui::BrowserUIID,
    skip_turns: u32,
}

impl MainLoop {
    fn frame(&mut self) {
        let system = unsafe { &mut *SYSTEM };
        let world = &mut system.world();

        system.networking_send_and_receive();

        if self.skip_turns == 0 {
            system.process_all_messages();

            self.browser_ui_id.on_frame(world);
            system.process_all_messages();

            system.networking_send_and_receive();
            system.process_all_messages();
        }

        js!{
            window.cbclient.setState(oldState => update(oldState, {
                system: {networkingTurns: {"$set":
                    @{system.networking_debug_all_n_turns()}
                }
            }}));

            window.cbclient.onFrame();
        }

        let mut next = self.clone();

        if self.skip_turns > 0 {
            next.skip_turns -= 1;
        } else {
            let maybe_sleep = system.networking_finish_turn();
            next.skip_turns = if let Some(duration) = maybe_sleep {
                duration.subsec_millis()
            } else {
                0
            };
        }

        ::stdweb::web::window().request_animation_frame(move |_| next.frame());
    }
}

mod planning_browser;
pub use planning_browser::*;
<|endoftext|>


<commit_before>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, to: Rc<RefCell<Node>>) {
        match child.borrow().parent() {
            Some(old_parent) => {
                old_parent.borrow_mut().remove_child(child.clone());
            },
            None => {}
        }
        child.borrow_mut().parent = Some(Rc::downgrade(&to.clone()));
        to.borrow_mut().add_child(child.clone());
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    pub fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    Node::reparent(im.clone(), root2.clone());

    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}
<commit_msg>is_child_of with tests<commit_after>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, to: Rc<RefCell<Node>>) {
        match child.borrow().parent() {
            Some(old_parent) => {
                old_parent.borrow_mut().remove_child(child.clone());
            },
            None => {}
        }
        child.borrow_mut().parent = Some(Rc::downgrade(&to.clone()));
        to.borrow_mut().add_child(child.clone());
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    pub fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        assert!( self.id == child.parent().unwrap().borrow().id );
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    Node::reparent(im.clone(), root2.clone());

    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Combinations with and without replacement.

use std::cmp;

/// Calculate the number of combinations when choosing
/// k elements from n elements without replacement, multiplied by a scaling factor.
pub fn scaled_combinations(n: u64, k: u64, scale: f64) -> f64 {
    if k > n {
        0.0
    } else {
        let mut comb = scale;
        for j in 0..cmp::min(k, n - k) {
            comb /= (j + 1) as f64;
            comb *= (n - j) as f64;
        }
        comb
    }
}

/// Calculate the number of combinations when choosing
/// k elements from n elements without replacement.
/// This is also known as n over k, or the binomial coefficient.
pub fn combinations(n: u64, k: u64) -> f64 {
    scaled_combinations(n, k, 1.0)
}

/// Calculate the number of combinations when choosing
/// k elements from n elements with replacement.
pub fn combinations_with_repl(n: u64, k: u64) -> f64 {
    combinations(n + k - 1, k)
}

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

    #[test]
    fn test_comb() {
        assert_eq!(combinations(10, 3), 120.0);
        assert_eq!(combinations_with_repl(10, 3), 220.0);
        assert_eq!(combinations(200, 10), 22451004309013280.0);
    }

    #[test]
    fn test_comb_scaled() {
        assert!((scaled_combinations(150, 80, 1e-5) - 6.6643938163479384e+38).abs() < 0.0000001);
    }
}
<commit_msg>Add examples and time complexity to `stats::combinatorics` (#306)<commit_after>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Combinations with and without replacement.

use std::cmp;

/// Calculate the number of combinations when choosing
/// k elements from n elements without replacement, multiplied by a scaling factor.
/// Time complexity: O(min(k, n - k))
///
/// # Examples
/// ```
/// use bio::stats::combinatorics::scaled_combinations;
/// assert_eq!(scaled_combinations(5, 3, 0.5), 5.);
/// ```
pub fn scaled_combinations(n: u64, k: u64, scale: f64) -> f64 {
    if k > n {
        0.0
    } else {
        let mut comb = scale;
        for j in 0..cmp::min(k, n - k) {
            comb /= (j + 1) as f64;
            comb *= (n - j) as f64;
        }
        comb
    }
}

/// Calculate the number of combinations when choosing
/// k elements from n elements without replacement.
/// This is also known as n over k, or the binomial coefficient.
/// Time complexity: O(min(k, n - k))
///
/// # Examples
/// ```
/// use bio::stats::combinatorics::combinations;
/// assert_eq!(combinations(5, 3), 10.);
/// ```
pub fn combinations(n: u64, k: u64) -> f64 {
    scaled_combinations(n, k, 1.0)
}

/// Calculate the number of combinations when choosing
/// k elements from n elements with replacement.
/// Time complexity: O(min(k, n - k))
///
/// # Examples
/// ```
/// use bio::stats::combinatorics::combinations_with_repl;
/// assert_eq!(combinations_with_repl(5, 3), 35.);
/// ```
pub fn combinations_with_repl(n: u64, k: u64) -> f64 {
    combinations(n + k - 1, k)
}

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

    #[test]
    fn test_comb() {
        assert_eq!(combinations(10, 3), 120.0);
        assert_eq!(combinations_with_repl(10, 3), 220.0);
        assert_eq!(combinations(200, 10), 22451004309013280.0);
    }

    #[test]
    fn test_comb_scaled() {
        assert!((scaled_combinations(150, 80, 1e-5) - 6.6643938163479384e+38).abs() < 0.0000001);
    }
}
<|endoftext|>


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

/*

*/

extern mod std;
use std::map;
use core::mutable::Mut;
use core::hashmap::linear::*;
use core::io::WriterUtil;

struct Results {
    sequential_ints: float,
    random_ints: float,
    delete_ints: float,

    sequential_strings: float,
    random_strings: float,
    delete_strings: float
}

fn timed(result: &mut float,
         op: fn()) {
    let start = std::time::precise_time_s();
    op();
    let end = std::time::precise_time_s();
    *result = (end - start);
}

fn int_benchmarks<M: map::Map<uint, uint>>(make_map: fn() -> M,
                                           rng: @rand::Rng,
                                           num_keys: uint,
                                           results: &mut Results) {

    {
        let map = make_map();
        do timed(&mut results.sequential_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(i, i+1);
            }

            for uint::range(0, num_keys) |i| {
                assert map.get(i) == i+1;
            }
        }
    }

    {
        let map = make_map();
        do timed(&mut results.random_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(rng.next() as uint, i);
            }
        }
    }

    {
        let map = make_map();
        for uint::range(0, num_keys) |i| {
            map.insert(i, i);;
        }

        do timed(&mut results.delete_ints) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(i);
            }
        }
    }
}

fn str_benchmarks<M: map::Map<~str, uint>>(make_map: fn() -> M,
                                           rng: @rand::Rng,
                                           num_keys: uint,
                                           results: &mut Results) {
    {
        let map = make_map();
        do timed(&mut results.sequential_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                map.insert(s, i);
            }

            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                assert map.get(s) == i;
            }
        }
    }

    {
        let map = make_map();
        do timed(&mut results.random_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(rng.next() as uint, 10);
                map.insert(s, i);
            }
        }
    }

    {
        let map = make_map();
        for uint::range(0, num_keys) |i| {
            map.insert(uint::to_str(i, 10), i);
        }
        do timed(&mut results.delete_strings) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(uint::to_str(i, 10));
            }
        }
    }
}

fn write_header(header: &str) {
    io::stdout().write_str(header);
    io::stdout().write_str("\n");
}

fn write_row(label: &str, value: float) {
    io::stdout().write_str(fmt!("%30s %f s\n", label, value));
}

fn write_results(label: &str, results: &Results) {
    write_header(label);
    write_row("sequential_ints", results.sequential_ints);
    write_row("random_ints", results.random_ints);
    write_row("delete_ints", results.delete_ints);
    write_row("sequential_strings", results.sequential_strings);
    write_row("random_strings", results.random_strings);
    write_row("delete_strings", results.delete_strings);
}

fn empty_results() -> Results {
    Results {
        sequential_ints: 0f,
        random_ints: 0f,
        delete_ints: 0f,

        sequential_strings: 0f,
        random_strings: 0f,
        delete_strings: 0f,
    }
}

fn main() {
    let args = os::args();
    let num_keys = {
        if args.len() == 2 {
            uint::from_str(args[1]).get()
        } else {
            100 // woefully inadequate for any real measurement
        }
    };

    let seed = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    {
        let rng = rand::seeded_rng(&seed);
        let mut results = empty_results();
        int_benchmarks::<map::HashMap<uint, uint>>(
            map::HashMap, rng, num_keys, &mut results);
        str_benchmarks::<map::HashMap<~str, uint>>(
            map::HashMap, rng, num_keys, &mut results);
        write_results("libstd::map::hashmap", &results);
    }

    {
        let rng = rand::seeded_rng(&seed);
        let mut results = empty_results();
        int_benchmarks::<@Mut<LinearMap<uint, uint>>>(
            || @Mut(LinearMap::new()),
            rng, num_keys, &mut results);
        str_benchmarks::<@Mut<LinearMap<~str, uint>>>(
            || @Mut(LinearMap::new()),
            rng, num_keys, &mut results);
        write_results("libstd::map::hashmap", &results);
    }
}
<commit_msg>fix core-map.rs benchmark<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod std;
use std::map;
use std::treemap::TreeMap;
use core::hashmap::linear::*;
use core::io::WriterUtil;

struct Results {
    sequential_ints: float,
    random_ints: float,
    delete_ints: float,

    sequential_strings: float,
    random_strings: float,
    delete_strings: float
}

fn timed(result: &mut float,
         op: fn()) {
    let start = std::time::precise_time_s();
    op();
    let end = std::time::precise_time_s();
    *result = (end - start);
}

fn old_int_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {

    {
        let map = map::HashMap();
        do timed(&mut results.sequential_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(i, i+1);
            }

            for uint::range(0, num_keys) |i| {
                assert map.get(i) == i+1;
            }
        }
    }

    {
        let map = map::HashMap();
        do timed(&mut results.random_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(rng.next() as uint, i);
            }
        }
    }

    {
        let map = map::HashMap();
        for uint::range(0, num_keys) |i| {
            map.insert(i, i);;
        }

        do timed(&mut results.delete_ints) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(i);
            }
        }
    }
}

fn old_str_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {
    {
        let map = map::HashMap();
        do timed(&mut results.sequential_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                map.insert(s, i);
            }

            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                assert map.get(s) == i;
            }
        }
    }

    {
        let map = map::HashMap();
        do timed(&mut results.random_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(rng.next() as uint, 10);
                map.insert(s, i);
            }
        }
    }

    {
        let map = map::HashMap();
        for uint::range(0, num_keys) |i| {
            map.insert(uint::to_str(i, 10), i);
        }
        do timed(&mut results.delete_strings) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(uint::to_str(i, 10));
            }
        }
    }
}

fn linear_int_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {
    {
        let mut map = LinearMap::new();
        do timed(&mut results.sequential_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(i, i+1);
            }

            for uint::range(0, num_keys) |i| {
                assert map.find(&i).unwrap() == &(i+1);
            }
        }
    }

    {
        let mut map = LinearMap::new();
        do timed(&mut results.random_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(rng.next() as uint, i);
            }
        }
    }

    {
        let mut map = LinearMap::new();
        for uint::range(0, num_keys) |i| {
            map.insert(i, i);;
        }

        do timed(&mut results.delete_ints) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(&i);
            }
        }
    }
}

fn linear_str_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {
    {
        let mut map = LinearMap::new();
        do timed(&mut results.sequential_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                map.insert(s, i);
            }

            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                assert map.find(&s).unwrap() == &i;
            }
        }
    }

    {
        let mut map = LinearMap::new();
        do timed(&mut results.random_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(rng.next() as uint, 10);
                map.insert(s, i);
            }
        }
    }

    {
        let mut map = LinearMap::new();
        for uint::range(0, num_keys) |i| {
            map.insert(uint::to_str(i, 10), i);
        }
        do timed(&mut results.delete_strings) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(&uint::to_str(i, 10));
            }
        }
    }
}

fn tree_int_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {
    {
        let mut map = TreeMap::new();
        do timed(&mut results.sequential_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(i, i+1);
            }

            for uint::range(0, num_keys) |i| {
                assert map.find(&i).unwrap() == &(i+1);
            }
        }
    }

    {
        let mut map = TreeMap::new();
        do timed(&mut results.random_ints) {
            for uint::range(0, num_keys) |i| {
                map.insert(rng.next() as uint, i);
            }
        }
    }

    {
        let mut map = TreeMap::new();
        for uint::range(0, num_keys) |i| {
            map.insert(i, i);;
        }

        do timed(&mut results.delete_ints) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(&i);
            }
        }
    }
}

fn tree_str_benchmarks(rng: @rand::Rng, num_keys: uint, results: &mut Results) {
    {
        let mut map = TreeMap::new();
        do timed(&mut results.sequential_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                map.insert(s, i);
            }

            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(i, 10);
                assert map.find(&s).unwrap() == &i;
            }
        }
    }

    {
        let mut map = TreeMap::new();
        do timed(&mut results.random_strings) {
            for uint::range(0, num_keys) |i| {
                let s = uint::to_str(rng.next() as uint, 10);
                map.insert(s, i);
            }
        }
    }

    {
        let mut map = TreeMap::new();
        for uint::range(0, num_keys) |i| {
            map.insert(uint::to_str(i, 10), i);
        }
        do timed(&mut results.delete_strings) {
            for uint::range(0, num_keys) |i| {
                assert map.remove(&uint::to_str(i, 10));
            }
        }
    }
}

fn write_header(header: &str) {
    io::stdout().write_str(header);
    io::stdout().write_str("\n");
}

fn write_row(label: &str, value: float) {
    io::stdout().write_str(fmt!("%30s %f s\n", label, value));
}

fn write_results(label: &str, results: &Results) {
    write_header(label);
    write_row("sequential_ints", results.sequential_ints);
    write_row("random_ints", results.random_ints);
    write_row("delete_ints", results.delete_ints);
    write_row("sequential_strings", results.sequential_strings);
    write_row("random_strings", results.random_strings);
    write_row("delete_strings", results.delete_strings);
}

fn empty_results() -> Results {
    Results {
        sequential_ints: 0f,
        random_ints: 0f,
        delete_ints: 0f,

        sequential_strings: 0f,
        random_strings: 0f,
        delete_strings: 0f,
    }
}

fn main() {
    let args = os::args();
    let num_keys = {
        if args.len() == 2 {
            uint::from_str(args[1]).get()
        } else {
            100 // woefully inadequate for any real measurement
        }
    };

    let seed = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    {
        let rng = rand::seeded_rng(&seed);
        let mut results = empty_results();
        old_int_benchmarks(rng, num_keys, &mut results);
        old_str_benchmarks(rng, num_keys, &mut results);
        write_results("std::map::HashMap", &results);
    }

    {
        let rng = rand::seeded_rng(&seed);
        let mut results = empty_results();
        linear_int_benchmarks(rng, num_keys, &mut results);
        linear_str_benchmarks(rng, num_keys, &mut results);
        write_results("core::hashmap::linear::LinearMap", &results);
    }

    {
        let rng = rand::seeded_rng(&seed);
        let mut results = empty_results();
        tree_int_benchmarks(rng, num_keys, &mut results);
        tree_str_benchmarks(rng, num_keys, &mut results);
        write_results("std::treemap::TreeMap", &results);
    }
}
<|endoftext|>