<commit_before>//! Types for compile-time endianity.

use byteorder;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, Index, Range, RangeFrom, RangeTo};

/// A trait describing the endianity of some buffer.
///
/// All interesting methods are from the `byteorder` crate's `ByteOrder`
/// trait. All methods are static. You shouldn't instantiate concrete objects
/// that implement this trait, it is just used as compile-time phantom data.
pub trait Endianity
    : byteorder::ByteOrder + Debug + Clone + Copy + PartialEq + Eq {
}

/// Little endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LittleEndian {}

impl byteorder::ByteOrder for LittleEndian {
    fn read_u16(buf: &[u8]) -> u16 {
        byteorder::LittleEndian::read_u16(buf)
    }
    fn read_u32(buf: &[u8]) -> u32 {
        byteorder::LittleEndian::read_u32(buf)
    }
    fn read_u64(buf: &[u8]) -> u64 {
        byteorder::LittleEndian::read_u64(buf)
    }
    fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
        byteorder::LittleEndian::read_uint(buf, nbytes)
    }
    fn write_u16(buf: &mut [u8], n: u16) {
        byteorder::LittleEndian::write_u16(buf, n)
    }
    fn write_u32(buf: &mut [u8], n: u32) {
        byteorder::LittleEndian::write_u32(buf, n)
    }
    fn write_u64(buf: &mut [u8], n: u64) {
        byteorder::LittleEndian::write_u64(buf, n)
    }
    fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
        byteorder::LittleEndian::write_uint(buf, n, nbytes)
    }
}

impl Endianity for LittleEndian {}

/// Big endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BigEndian {}

impl byteorder::ByteOrder for BigEndian {
    fn read_u16(buf: &[u8]) -> u16 {
        byteorder::BigEndian::read_u16(buf)
    }
    fn read_u32(buf: &[u8]) -> u32 {
        byteorder::BigEndian::read_u32(buf)
    }
    fn read_u64(buf: &[u8]) -> u64 {
        byteorder::BigEndian::read_u64(buf)
    }
    fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
        byteorder::BigEndian::read_uint(buf, nbytes)
    }
    fn write_u16(buf: &mut [u8], n: u16) {
        byteorder::BigEndian::write_u16(buf, n)
    }
    fn write_u32(buf: &mut [u8], n: u32) {
        byteorder::BigEndian::write_u32(buf, n)
    }
    fn write_u64(buf: &mut [u8], n: u64) {
        byteorder::BigEndian::write_u64(buf, n)
    }
    fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
        byteorder::BigEndian::write_uint(buf, n, nbytes)
    }
}

impl Endianity for BigEndian {}

/// The native endianity for the target platform.
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;

/// A `&[u8]` slice with compile-time endianity metadata.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EndianBuf<'input, Endian>(pub &'input [u8], pub PhantomData<Endian>)
    where Endian: Endianity;

impl<'input, Endian> EndianBuf<'input, Endian>
    where Endian: Endianity
{
    /// Construct a new `EndianBuf` with the given buffer.
    pub fn new(buf: &'input [u8]) -> EndianBuf<'input, Endian> {
        EndianBuf(buf, PhantomData)
    }
}

/// # Range Methods
///
/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
/// implement `Index<Range<usize>>` to return a new `EndianBuf` the way we would
/// like to. Instead, we abandon fancy indexing operators and have these plain
/// old methods.
impl<'input, Endian> EndianBuf<'input, Endian>
    where Endian: Endianity
{
    /// Take the given `start..end` range of the underlying buffer and return a
    /// new `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range(1..3),
    ///            EndianBuf::new(&buf[1..3]));
    /// ```
    pub fn range(&self, idx: Range<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }

    /// Take the given `start..` range of the underlying buffer and return a new
    /// `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range_from(2..),
    ///            EndianBuf::new(&buf[2..]));
    /// ```
    pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }

    /// Take the given `..end` range of the underlying buffer and return a new
    /// `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range_to(..3),
    ///            EndianBuf::new(&buf[..3]));
    /// ```
    pub fn range_to(&self, idx: RangeTo<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }
}

impl<'input, Endian> Index<usize> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Output = u8;
    fn index(&self, idx: usize) -> &Self::Output {
        &self.0[idx]
    }
}

impl<'input, Endian> Index<RangeFrom<usize>> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Output = [u8];
    fn index(&self, idx: RangeFrom<usize>) -> &Self::Output {
        &self.0[idx]
    }
}

impl<'input, Endian> Deref for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Target = [u8];
    fn deref(&self) -> &Self::Target {
        self.0
    }
}

impl<'input, Endian> Into<&'input [u8]> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    fn into(self) -> &'input [u8] {
        self.0
    }
}
<commit_msg>Add EndianBuf::[try_]split_at to partition an EndianBuf at an index<commit_after>//! Types for compile-time endianity.

use byteorder;
use parser::{Error, Result};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, Index, Range, RangeFrom, RangeTo};

/// A trait describing the endianity of some buffer.
///
/// All interesting methods are from the `byteorder` crate's `ByteOrder`
/// trait. All methods are static. You shouldn't instantiate concrete objects
/// that implement this trait, it is just used as compile-time phantom data.
pub trait Endianity
    : byteorder::ByteOrder + Debug + Clone + Copy + PartialEq + Eq {
}

/// Little endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LittleEndian {}

impl byteorder::ByteOrder for LittleEndian {
    fn read_u16(buf: &[u8]) -> u16 {
        byteorder::LittleEndian::read_u16(buf)
    }
    fn read_u32(buf: &[u8]) -> u32 {
        byteorder::LittleEndian::read_u32(buf)
    }
    fn read_u64(buf: &[u8]) -> u64 {
        byteorder::LittleEndian::read_u64(buf)
    }
    fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
        byteorder::LittleEndian::read_uint(buf, nbytes)
    }
    fn write_u16(buf: &mut [u8], n: u16) {
        byteorder::LittleEndian::write_u16(buf, n)
    }
    fn write_u32(buf: &mut [u8], n: u32) {
        byteorder::LittleEndian::write_u32(buf, n)
    }
    fn write_u64(buf: &mut [u8], n: u64) {
        byteorder::LittleEndian::write_u64(buf, n)
    }
    fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
        byteorder::LittleEndian::write_uint(buf, n, nbytes)
    }
}

impl Endianity for LittleEndian {}

/// Big endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BigEndian {}

impl byteorder::ByteOrder for BigEndian {
    fn read_u16(buf: &[u8]) -> u16 {
        byteorder::BigEndian::read_u16(buf)
    }
    fn read_u32(buf: &[u8]) -> u32 {
        byteorder::BigEndian::read_u32(buf)
    }
    fn read_u64(buf: &[u8]) -> u64 {
        byteorder::BigEndian::read_u64(buf)
    }
    fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
        byteorder::BigEndian::read_uint(buf, nbytes)
    }
    fn write_u16(buf: &mut [u8], n: u16) {
        byteorder::BigEndian::write_u16(buf, n)
    }
    fn write_u32(buf: &mut [u8], n: u32) {
        byteorder::BigEndian::write_u32(buf, n)
    }
    fn write_u64(buf: &mut [u8], n: u64) {
        byteorder::BigEndian::write_u64(buf, n)
    }
    fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
        byteorder::BigEndian::write_uint(buf, n, nbytes)
    }
}

impl Endianity for BigEndian {}

/// The native endianity for the target platform.
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;

/// A `&[u8]` slice with compile-time endianity metadata.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EndianBuf<'input, Endian>(pub &'input [u8], pub PhantomData<Endian>)
    where Endian: Endianity;

impl<'input, Endian> EndianBuf<'input, Endian>
    where Endian: Endianity
{
    /// Construct a new `EndianBuf` with the given buffer.
    pub fn new(buf: &'input [u8]) -> EndianBuf<'input, Endian> {
        EndianBuf(buf, PhantomData)
    }

    /// Split the buffer in two at the given index, resulting in the tuple where
    /// the first item has range [0, idx), and the second has range
    /// [idx, len). Panics if the index is out of bounds.
    #[inline]
    pub fn split_at(&self, idx: usize) -> (EndianBuf<'input, Endian>, EndianBuf<'input, Endian>) {
        (self.range_to(..idx), self.range_from(idx..))
    }

    /// The same as `split_at`, but returns a `Result` rather than panicking
    /// when the index is out of bounds.
    #[inline]
    pub fn try_split_at(&self,
                        idx: usize)
                        -> Result<(EndianBuf<'input, Endian>, EndianBuf<'input, Endian>)> {
        if idx > self.len() {
            Err(Error::BadLength)
        } else {
            Ok(self.split_at(idx))
        }
    }
}

/// # Range Methods
///
/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
/// implement `Index<Range<usize>>` to return a new `EndianBuf` the way we would
/// like to. Instead, we abandon fancy indexing operators and have these plain
/// old methods.
impl<'input, Endian> EndianBuf<'input, Endian>
    where Endian: Endianity
{
    /// Take the given `start..end` range of the underlying buffer and return a
    /// new `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range(1..3),
    ///            EndianBuf::new(&buf[1..3]));
    /// ```
    pub fn range(&self, idx: Range<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }

    /// Take the given `start..` range of the underlying buffer and return a new
    /// `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range_from(2..),
    ///            EndianBuf::new(&buf[2..]));
    /// ```
    pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }

    /// Take the given `..end` range of the underlying buffer and return a new
    /// `EndianBuf`.
    ///
    /// ```
    /// use gimli::{EndianBuf, LittleEndian};
    ///
    /// let buf = [0x01, 0x02, 0x03, 0x04];
    /// let endian_buf = EndianBuf::<LittleEndian>::new(&buf);
    /// assert_eq!(endian_buf.range_to(..3),
    ///            EndianBuf::new(&buf[..3]));
    /// ```
    pub fn range_to(&self, idx: RangeTo<usize>) -> EndianBuf<'input, Endian> {
        EndianBuf(&self.0[idx], self.1)
    }
}

impl<'input, Endian> Index<usize> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Output = u8;
    fn index(&self, idx: usize) -> &Self::Output {
        &self.0[idx]
    }
}

impl<'input, Endian> Index<RangeFrom<usize>> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Output = [u8];
    fn index(&self, idx: RangeFrom<usize>) -> &Self::Output {
        &self.0[idx]
    }
}

impl<'input, Endian> Deref for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    type Target = [u8];
    fn deref(&self) -> &Self::Target {
        self.0
    }
}

impl<'input, Endian> Into<&'input [u8]> for EndianBuf<'input, Endian>
    where Endian: Endianity
{
    fn into(self) -> &'input [u8] {
        self.0
    }
}

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

    #[test]
    fn test_endian_buf_split_at() {
        let buf = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
        let eb = EndianBuf::<NativeEndian>::new(&buf);
        assert_eq!(eb.split_at(3),
                   (EndianBuf::new(&buf[..3]), EndianBuf::new(&buf[3..])));
    }

    #[test]
    #[should_panic]
    fn test_endian_buf_split_at_out_of_bounds() {
        let buf = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
        let eb = EndianBuf::<NativeEndian>::new(&buf);
        eb.split_at(30);
    }

    #[test]
    fn test_endian_buf_try_split_at() {
        let buf = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
        let eb = EndianBuf::<NativeEndian>::new(&buf);
        assert_eq!(eb.try_split_at(3),
                   Ok((EndianBuf::new(&buf[..3]), EndianBuf::new(&buf[3..]))));
    }

    #[test]
    fn test_endian_buf_try_split_at_out_of_bounds() {
        let buf = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
        let eb = EndianBuf::<NativeEndian>::new(&buf);
        assert_eq!(Err(Error::BadLength), eb.try_split_at(30));
    }
}
<|endoftext|>


<commit_before>use board_logic::{Board, BoardMarker, Point, Stone};

#[derive(Debug, PartialEq)]
pub enum Direction {
    Horizontal,
    Vertical,
    Diagonal, // ´\´
    AntiDiagonal, // ´/´
}

pub fn is_five(board: &Board, marker: BoardMarker) -> Option<Direction> {
    // OK this will be hard, let's do it.

    let mut n_line = 1;
    { // Horizontal
        debug!("Horiz right:");
        debug!("\tStart: {}", marker.point.x+1);
        'right: for i in marker.point.x+1..board.boardsize {
            if board.getxy(i, marker.point.y).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'right;
            }
        }
        debug!("Horiz left:");
        debug!("\tStart: {}", marker.point.x-1);
        'left: for i in (0..marker.point.x).rev() {
            if board.getxy(i, marker.point.y).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'left;
            }
        }

        if n_line >= 4 {
            debug!("Horizontal Line length: {}", n_line);
            return Some(Direction::Horizontal);
        }
        n_line=0;
    }
    { // Vertical
        debug!("Vert down:");
        debug!("\tStart: {}", marker.point.y+1);
        'down: for i in marker.point.y+1..board.boardsize {
            if board.getxy(marker.point.x, i).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'down;
            }
        }
        debug!("Vert up: ");
        debug!("\tStart: {}", marker.point.x-1);
        'up: for i in (0..marker.point.y).rev() { // if it is suppossed to be 0..y+1 or 0..y is not clear
            if board.getxy(marker.point.x, i).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'up;
            }
        }

        debug!("Vertical line length: {}", n_line);
        if n_line >= 4 {
            return Some(Direction::Vertical);
        }
        n_line = 0;
    }
    Option::None
}

#[cfg(test)]
mod tests {
    use super::*;
    use board_logic::{Board, BoardMarker, Stone, Point};

    #[test]
    #[ignore]
    fn check_if_illegal_move() {
        let positions: Vec<Point> = [7 * 15 + 7, 7 * 15 + 6, 6 * 15 + 6, 5 * 15 + 7]
                .iter().map(|d| Point::from_1d(*d, 15)).collect();
        let illegal = Point::from_1d(7 * 15 + 5, 15);
        println!("{:?}", illegal);
    }

    #[test]
    fn is_horizontal_five_in_a_row() {
        let mut board = Board::new(15);
        let y = 7u32;
        let p1 = BoardMarker { point: Point::new(4, y), color: Stone::Black };
        for x in (0..4) {
            board.set_point(Point::new(x, y), Stone::Black);
        }

        let p2 = BoardMarker { point: Point::new(8, y + 2), color: Stone::White };
        for x in (7..12).filter(|x| *x != 8) {
            board.set_point(Point::new(x, y + 2), Stone::White);
        }
        println!("test:is_horizontal_five_in_a_row:\n{}\nChecks,{:?} and {:?}",
                 board.board, p1, p2);

        assert_eq!(is_five(&board, p1), Some(Direction::Horizontal));
        assert_eq!(is_five(&board, p2), Some(Direction::Horizontal));
    }

    #[test]
    fn is_vertical_five_in_a_row() {
        let mut board = Board::new(15);
        let x = 7u32;
        let p1 = BoardMarker { point: Point::new(x, 4), color: Stone::Black };
        for y in (0..4) {
            board.set_point(Point::new(x, y), Stone::Black);
        }

        let p2 = BoardMarker { point: Point::new(x + 2, 8), color: Stone::White };
        for y in (7..12).filter(|y| *y != 8) {
            board.set_point(Point::new(x+2, y), Stone::White);
        }
        println!("test:is_horizontal_five_in_a_row:\n{}\nChecks,{:?} and {:?}",
                 board.board, p1, p2);

        assert_eq!(is_five(&board, p1), Some(Direction::Vertical));
        assert_eq!(is_five(&board, p2), Some(Direction::Vertical));
    }

}
<commit_msg>Changed result type (WIP)<commit_after>use board_logic::{Board, BoardMarker};

#[derive(Debug, PartialEq)]
pub enum Direction {
    Horizontal,
    Vertical,
    Diagonal, // ´\´
    AntiDiagonal, // ´/´
}

#[derive(PartialEq, Debug)]
pub enum EvalError {
    NoMatch,
    OutOfBounds,
}

pub fn is_five(board: &Board, marker: BoardMarker) -> Result<Direction, EvalError> {
    // OK this will be hard, let's do it.

    let mut n_line = 1;
    { // Horizontal
        debug!("Horiz right:");
        debug!("\tStart: {}", marker.point.x+1);
        'right: for i in marker.point.x+1..board.boardsize {
            if board.getxy(i, marker.point.y).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'right;
            }
        }
        debug!("Horiz left:");
        debug!("\tStart: {}", marker.point.x-1);
        'left: for i in (0..marker.point.x).rev() {
            if board.getxy(i, marker.point.y+200).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'left;
            }
        }

        if n_line >= 4 {
            debug!("Horizontal Line length: {}", n_line);
            return Ok(Direction::Horizontal);
        }
        n_line=0;
    }
    { // Vertical
        debug!("Vert down:");
        debug!("\tStart: {}", marker.point.y+1);
        'down: for i in marker.point.y+1..board.boardsize {
            if board.getxy(marker.point.x, i).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'down;
            }
        }
        debug!("Vert up: ");
        debug!("\tStart: {}", marker.point.x-1);
        'up: for i in (0..marker.point.y).rev() { // if it is suppossed to be 0..y+1 or 0..y is not clear
            if board.getxy(marker.point.x, i).unwrap().color == marker.color {
                n_line += 1;
            } else {
                debug!("\tEnd: {}", i);
                break 'up;
            }
        }

        debug!("Vertical line length: {}", n_line);
        if n_line >= 4 {
            return Ok(Direction::Vertical);
        }
        n_line = 0;
    }
    { // Diagonal '\'
        debug!("Diagonal down:");
        debug!("\tStart: {}_{}", marker.point.x+1, marker.point.y+1);
    }
    Err(EvalError::NoMatch)
}

#[cfg(test)]
mod tests {
    use super::*;
    use board_logic::{Board, BoardMarker, Stone, Point};

    #[test]
    #[ignore]
    fn check_if_illegal_move() {
        let mut board = Board::new(15);
        for pos in [7 * 15 + 7, 7 * 15 + 6, 6 * 15 + 6, 5 * 15 + 7].iter() {
            board.set_point(Point::from_1d(*pos, 15), Stone::Black);
        }

        let illegal = Point::from_1d(7 * 15 + 5, 15);
        println!("{:?}", illegal);
    }

    #[test]
    fn is_horizontal_five_in_a_row() {
        let mut board = Board::new(15);
        let y = 7u32;
        let p1 = BoardMarker { point: Point::new(4, y), color: Stone::Black };
        for x in 0..4 {
            board.set_point(Point::new(x, y), Stone::Black);
        }

        let p2 = BoardMarker { point: Point::new(8, y + 2), color: Stone::White };
        for x in (7..12).filter(|x| *x != 8) {
            board.set_point(Point::new(x, y + 2), Stone::White);
        }
        println!("\n{}\nChecks,{:?} and {:?}",
                 board.board, p1, p2);

        assert_eq!(is_five(&board, p1), Ok(Direction::Horizontal));
        // assert_eq!(is_five(&board, p2).unwrap(), Direction::Horizontal);
    }

    #[test]
    fn is_vertical_five_in_a_row() {
        let mut board = Board::new(15);
        let x = 7u32;
        let p1 = BoardMarker { point: Point::new(x, 4), color: Stone::Black };
        for y in 0..4 {
            board.set_point(Point::new(x, y), Stone::Black);
        }

        let p2 = BoardMarker { point: Point::new(x + 2, 8), color: Stone::White };
        for y in (7..12).filter(|y| *y != 8) {
            board.set_point(Point::new(x+2, y), Stone::White);
        }
        println!("\n{}\nChecks; {:?} and {:?}",
                 board.board, p1, p2);

        assert_eq!(is_five(&board, p1), Ok(Direction::Vertical));
        assert_eq!(is_five(&board, p2), Ok(Direction::Vertical));
    }
    #[test]
    fn is_diagonal_five_in_a_row() {
        let mut board = Board::new(15);
        // A diagonal is '\'
        for pos in [7*15 + 2u32, 8*15+3u32, 9*15+4u32, 10*15+5u32].iter() {
            board.set_point(Point::from_1d(*pos, 15), Stone::Black);
        }
        let p1 = BoardMarker { point: Point::from_1d(11*15+6, 15), color: Stone::Black };
        println!("\n{}\nChecks; {:?}",
                 board.board, p1);

        assert_eq!(is_five(&board, p1), Ok(Direction::Diagonal));
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::mem;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::atomic::Ordering::{Acquire, Release};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use select::CaseId;
use select::handle::{self, Handle};
use util::Backoff;

/// Waiting strategy in an exchange operation.
enum Wait {
    /// Yield once and then time out.
    YieldOnce,

    /// Wait until an optional deadline.
    Until(Option<Instant>),
}

/// Enumeration of possible exchange errors.
pub enum ExchangeError<T> {
    /// The exchange operation timed out.
    Timeout(T),

    /// The exchanger was disconnected.
    Disconnected(T),
}

/// Inner representation of an exchanger.
///
/// This data structure is wrapped in a mutex.
struct Inner<T> {
    /// There are two wait queues, one per side.
    wait_queues: [WaitQueue<T>; 2],

    /// `true` if the exchanger is closed.
    closed: bool,
}

/// A two-sided exchanger.
///
/// This is a concurrent data structure with two sides: left and right. A thread can offer a
/// message on one side, and if there is another thread waiting on the opposite side at the same
/// time, they exchange messages.
///
/// Instead of *offering* a concrete message for excahnge, a thread can also *promise* a message.
/// If another thread pairs up with the promise on the opposite end, then it will wait until the
/// promise is fulfilled. The thread that promised the message must in the end fulfill it. A
/// promise can also be revoked if nobody is waiting for it.
pub struct Exchanger<T> {
    inner: Mutex<Inner<T>>,
}

impl<T> Exchanger<T> {
    /// Returns a new exchanger.
    pub fn new() -> Self {
        Exchanger {
            inner: Mutex::new(Inner {
                wait_queues: [WaitQueue::new(), WaitQueue::new()],
                closed: false,
            }),
        }
    }

    /// Returns the left side of the exchanger.
    pub fn left(&self) -> Side<T> {
        Side {
            index: 0,
            exchanger: self,
        }
    }

    /// Returns the right side of the exchanger.
    pub fn right(&self) -> Side<T> {
        Side {
            index: 1,
            exchanger: self,
        }
    }

    /// Closes the exchanger and wakes up all currently blocked operations on it.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.closed {
            false
        } else {
            inner.closed = true;
            inner.wait_queues[0].abort_all();
            inner.wait_queues[1].abort_all();
            true
        }
    }

    /// Returns `true` if the exchanger is closed.
    pub fn is_closed(&self) -> bool {
        self.inner.lock().closed
    }
}

/// One side of an exchanger.
pub struct Side<'a, T: 'a> {
    /// The index is 0 or 1.
    index: usize,

    /// A reference to the parent exchanger.
    exchanger: &'a Exchanger<T>,
}

impl<'a, T> Side<'a, T> {
    /// Promises a message for exchange.
    pub fn promise(&self, case_id: CaseId) {
        self.exchanger.inner.lock().wait_queues[self.index].promise(case_id);
    }

    /// Revokes the previously made promise.
    ///
    /// This method should be called right after the case is aborted.
    pub fn revoke(&self, case_id: CaseId) {
        self.exchanger.inner.lock().wait_queues[self.index].remove(case_id);
    }

    /// Fulfills the previously made promise.
    pub fn fulfill(&self, msg: T) -> T {
        // Wait until the requesting thread gives us a pointer to its `Request`.
        let req = LOCAL.with(|local| {
            let mut backoff = Backoff::new();
            loop {
                let ptr = local.request_ptr.swap(0, Acquire) as *const Request<T>;
                if !ptr.is_null() {
                    break ptr;
                }
                backoff.step();
            }
        });

        unsafe {
            // First, make a clone of the requesting thread's `Handle`.
            let handle = (*req).handle.clone();

            // Exchange the messages and then notify the requesting thread that it can pick up our
            // message.
            let m = (*req).packet.exchange(msg);
            (*req).handle.try_select(CaseId::abort());

            // Wake up the requesting thread.
            handle.unpark();

            // Return the exchanged message.
            m
        }
    }

    /// Exchanges `msg` if there is an offer or promise on the opposite side.
    pub fn try_exchange(
        &self,
        msg: T,
        case_id: CaseId,
    ) -> Result<T, ExchangeError<T>> {
        self.exchange(msg, Wait::YieldOnce, case_id)
    }

    /// Exchanges `msg`, waiting until the specified `deadline`.
    pub fn exchange_until(
        &self,
        msg: T,
        deadline: Option<Instant>,
        case_id: CaseId,
    ) -> Result<T, ExchangeError<T>> {
        self.exchange(msg, Wait::Until(deadline), case_id)
    }

    /// Returns `true` if there is an offer or promise on the opposite side.
    pub fn can_notify(&self) -> bool {
        self.exchanger.inner.lock().wait_queues[self.index].can_notify()
    }

    /// Exchanges `msg` with the specified `wait` strategy.
    fn exchange(
        &self,
        mut msg: T,
        wait: Wait,
        case_id: CaseId,
    ) -> Result<T, ExchangeError<T>> {
        loop {
            // Allocate a packet on the stack.
            let packet;
            {
                let mut inner = self.exchanger.inner.lock();
                if inner.closed {
                    return Err(ExchangeError::Disconnected(msg));
                }

                // If there's someone on the other side, exchange messages with it.
                if let Some(case) = inner.wait_queues[self.index ^ 1].pop() {
                    drop(inner);
                    return Ok(case.exchange(msg));
                }

                // Promise a packet with the message.
                handle::current_reset();
                packet = Packet::new(msg);
                inner.wait_queues[self.index].offer(&packet, case_id);
            }

            // Wait until the timeout and then try aborting the case.
            let timed_out = match wait {
                Wait::YieldOnce => {
                    thread::yield_now();
                    handle::current_try_select(CaseId::abort())
                },
                Wait::Until(deadline) => {
                    !handle::current_wait_until(deadline)
                },
            };

            // If someone requested the promised message...
            if handle::current_selected() != CaseId::abort() {
                // Wait until the message is taken and return.
                packet.wait();
                return Ok(packet.into_inner());
            }

            // Revoke the promise.
            let mut inner = self.exchanger.inner.lock();
            inner.wait_queues[self.index].remove(case_id);
            msg = packet.into_inner();

            // If we timed out, return.
            if timed_out {
                return Err(ExchangeError::Timeout(msg));
            }

            // Otherwise, another thread must have woken us up. Let's try again.
        }
    }
}

/// An entry in a wait queue.
enum Entry<T> {
    /// Offers a concrete message.
    Offer {
        handle: Handle,
        packet: *const Packet<T>,
        case_id: CaseId,
    },
    /// Promises a message.
    Promise {
        local: Arc<Local>,
        case_id: CaseId,
    },
}

impl<T> Entry<T> {
    /// Exchange `msg` with this entry and wake it up.
    fn exchange(&self, msg: T) -> T {
        match *self {
            // This is an offer.
            // We can exchange messages immediately.
            Entry::Offer {
                ref handle, packet, ..
            } => {
                let m = unsafe { (*packet).exchange(msg) };
                handle.unpark();
                m
            }

            // This is a promise.
            // We must request the message and then wait until the promise is fulfilled.
            Entry::Promise { ref local, .. } => {
                // Reset the current thread's selection case.
                handle::current_reset();

                // Create a request on the stack and register it in the owner of this entry.
                let req = Request::new(msg);
                local.request_ptr.store(&req as *const _ as usize, Release);

                // Wake up the owner of this entry.
                local.handle.unpark();

                // Wait until our selection case is woken.
                handle::current_wait_until(None);

                // Extract the received message from the request.
                req.packet.into_inner()
            }
        }
    }

    /// Returns the handle associated with the owner of this entry.
    fn handle(&self) -> &Handle {
        match *self {
            Entry::Offer { ref handle, .. } => handle,
            Entry::Promise { ref local, .. } => &local.handle,
        }
    }

    /// Returns the case ID associated with this entry.
    fn case_id(&self) -> CaseId {
        match *self {
            Entry::Offer { case_id, .. } => case_id,
            Entry::Promise { case_id, .. } => case_id,
        }
    }
}

/// A wait queue in which blocked selection cases are registered.
struct WaitQueue<T> {
    cases: VecDeque<Entry<T>>,
}

impl<T> WaitQueue<T> {
    /// Creates a new `WaitQueue`.
    fn new() -> Self {
        WaitQueue {
            cases: VecDeque::new(),
        }
    }

    /// Attempts to fire one case owned by another thread and returns it on success.
    fn pop(&mut self) -> Option<Entry<T>> {
        let thread_id = current_thread_id();

        for i in 0..self.cases.len() {
            if self.cases[i].handle().thread_id() != thread_id {
                if self.cases[i].handle().try_select(self.cases[i].case_id()) {
                    let case = self.cases.remove(i).unwrap();
                    self.maybe_shrink();
                    return Some(case);
                }
            }
        }

        None
    }

    /// Inserts an *offer* case owned by the current thread with `case_id`.
    fn offer(&mut self, packet: *const Packet<T>, case_id: CaseId) {
        self.cases.push_back(Entry::Offer {
            handle: handle::current(),
            packet,
            case_id,
        });
    }

    /// Inserts a *promise* case owned by the current thread with `case_id`.
    fn promise(&mut self, case_id: CaseId) {
        self.cases.push_back(Entry::Promise {
            local: LOCAL.with(|l| l.clone()),
            case_id,
        });
    }

    /// Removes a case owned by the current thread with `case_id`.
    fn remove(&mut self, case_id: CaseId) {
        let thread_id = current_thread_id();

        if let Some((i, _)) = self.cases.iter().enumerate().find(|&(_, case)| {
            case.case_id() == case_id && case.handle().thread_id() == thread_id
        }) {
            self.cases.remove(i);
            self.maybe_shrink();
        }
    }

    /// Returns `true` if there exists a case which isn't owned by the current thread.
    fn can_notify(&self) -> bool {
        let thread_id = current_thread_id();

        for i in 0..self.cases.len() {
            if self.cases[i].handle().thread_id() != thread_id {
                return true;
            }
        }
        false
    }

    /// Aborts all cases and unparks threads which own them.
    fn abort_all(&mut self) {
        for case in self.cases.drain(..) {
            case.handle().try_select(CaseId::abort());
            case.handle().unpark();
        }
        self.maybe_shrink();
    }

    /// Shrinks the internal buffer if its capacity is underused.
    fn maybe_shrink(&mut self) {
        if self.cases.capacity() > 32 && self.cases.capacity() / 2 > self.cases.len() {
            self.cases.shrink_to_fit();
        }
    }
}

impl<T> Drop for WaitQueue<T> {
    fn drop(&mut self) {
        debug_assert!(self.cases.is_empty());
    }
}

thread_local! {
    static THREAD_ID: thread::ThreadId = thread::current().id();
}

/// Returns the current thread ID.
///
/// This is much faster than calling `std::thread::current().id()`.
fn current_thread_id() -> thread::ThreadId {
    THREAD_ID.with(|id| *id)
}

thread_local! {
    static LOCAL: Arc<Local> = Arc::new(Local {
        handle: handle::current(),
        request_ptr: AtomicUsize::new(0),
    });
}

/// Thread-local structure that contains a slot for the `Request` pointer.
struct Local {
    /// The handle associated with this thread.
    handle: Handle,

    /// A slot into which another thread may store a pointer to its `Request`.
    request_ptr: AtomicUsize,
}

/// A request for promised message.
struct Request<T> {
    /// The handle associated with the requestor.
    handle: Handle,

    /// The message for exchange.
    packet: Packet<T>,
}

impl<T> Request<T> {
    /// Creates a new request owned by the current thread for exchanging `msg`.
    fn new(msg: T) -> Self {
        Request {
            handle: handle::current(),
            packet: Packet::new(msg),
        }
    }
}

/// A one-time only packet for exchanging messages.
///
/// A message can be exchanged for the one inside the packet only once.
struct Packet<T> {
    /// The mutex-protected message.
    msg: Mutex<Option<T>>,

    /// This will become `true` when the message is exchanged.
    ready: AtomicBool,
}

impl<T> Packet<T> {
    /// Creates a new packet containing `msg`.
    fn new(msg: T) -> Self {
        Packet {
            msg: Mutex::new(Some(msg)),
            ready: AtomicBool::new(false),
        }
    }

    /// Exchanges `msg` for the one inside the packet.
    fn exchange(&self, msg: T) -> T {
        let r = mem::replace(&mut *self.msg.try_lock().unwrap(), Some(msg));
        self.ready.store(true, Release);
        r.unwrap()
    }

    /// Extracts the message inside the packet.
    fn into_inner(self) -> T {
        self.msg.try_lock().unwrap().take().unwrap()
    }

    /// Spin-waits until the message inside the packet is exchanged.
    fn wait(&self) {
        let mut backoff = Backoff::new();
        while !self.ready.load(Acquire) {
            backoff.step();
        }
    }
}
<commit_msg>Reformat code<commit_after>use std::collections::VecDeque;
use std::mem;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::atomic::Ordering::{Acquire, Release};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use select::CaseId;
use select::handle::{self, Handle};
use util::Backoff;

/// Waiting strategy in an exchange operation.
enum Wait {
    /// Yield once and then time out.
    YieldOnce,

    /// Wait until an optional deadline.
    Until(Option<Instant>),
}

/// Enumeration of possible exchange errors.
pub enum ExchangeError<T> {
    /// The exchange operation timed out.
    Timeout(T),

    /// The exchanger was disconnected.
    Disconnected(T),
}

/// Inner representation of an exchanger.
///
/// This data structure is wrapped in a mutex.
struct Inner<T> {
    /// There are two wait queues, one per side.
    wait_queues: [WaitQueue<T>; 2],

    /// `true` if the exchanger is closed.
    closed: bool,
}

/// A two-sided exchanger.
///
/// This is a concurrent data structure with two sides: left and right. A thread can offer a
/// message on one side, and if there is another thread waiting on the opposite side at the same
/// time, they exchange messages.
///
/// Instead of *offering* a concrete message for excahnge, a thread can also *promise* a message.
/// If another thread pairs up with the promise on the opposite end, then it will wait until the
/// promise is fulfilled. The thread that promised the message must in the end fulfill it. A
/// promise can also be revoked if nobody is waiting for it.
pub struct Exchanger<T> {
    inner: Mutex<Inner<T>>,
}

impl<T> Exchanger<T> {
    /// Returns a new exchanger.
    pub fn new() -> Self {
        Exchanger {
            inner: Mutex::new(Inner {
                wait_queues: [WaitQueue::new(), WaitQueue::new()],
                closed: false,
            }),
        }
    }

    /// Returns the left side of the exchanger.
    pub fn left(&self) -> Side<T> {
        Side {
            index: 0,
            exchanger: self,
        }
    }

    /// Returns the right side of the exchanger.
    pub fn right(&self) -> Side<T> {
        Side {
            index: 1,
            exchanger: self,
        }
    }

    /// Closes the exchanger and wakes up all currently blocked operations on it.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.closed {
            false
        } else {
            inner.closed = true;
            inner.wait_queues[0].abort_all();
            inner.wait_queues[1].abort_all();
            true
        }
    }

    /// Returns `true` if the exchanger is closed.
    pub fn is_closed(&self) -> bool {
        self.inner.lock().closed
    }
}

/// One side of an exchanger.
pub struct Side<'a, T: 'a> {
    /// The index is 0 or 1.
    index: usize,

    /// A reference to the parent exchanger.
    exchanger: &'a Exchanger<T>,
}

impl<'a, T> Side<'a, T> {
    /// Promises a message for exchange.
    pub fn promise(&self, case_id: CaseId) {
        self.exchanger.inner.lock().wait_queues[self.index].promise(case_id);
    }

    /// Revokes the previously made promise.
    ///
    /// This method should be called right after the case is aborted.
    pub fn revoke(&self, case_id: CaseId) {
        self.exchanger.inner.lock().wait_queues[self.index].remove(case_id);
    }

    /// Fulfills the previously made promise.
    pub fn fulfill(&self, msg: T) -> T {
        // Wait until the requesting thread gives us a pointer to its `Request`.
        let req = LOCAL.with(|local| {
            let mut backoff = Backoff::new();
            loop {
                let ptr = local.request_ptr.swap(0, Acquire) as *const Request<T>;
                if !ptr.is_null() {
                    break ptr;
                }
                backoff.step();
            }
        });

        unsafe {
            // First, make a clone of the requesting thread's `Handle`.
            let handle = (*req).handle.clone();

            // Exchange the messages and then notify the requesting thread that it can pick up our
            // message.
            let m = (*req).packet.exchange(msg);
            (*req).handle.try_select(CaseId::abort());

            // Wake up the requesting thread.
            handle.unpark();

            // Return the exchanged message.
            m
        }
    }

    /// Exchanges `msg` if there is an offer or promise on the opposite side.
    pub fn try_exchange(&self, msg: T, case_id: CaseId) -> Result<T, ExchangeError<T>> {
        self.exchange(msg, Wait::YieldOnce, case_id)
    }

    /// Exchanges `msg`, waiting until the specified `deadline`.
    pub fn exchange_until(
        &self,
        msg: T,
        deadline: Option<Instant>,
        case_id: CaseId,
    ) -> Result<T, ExchangeError<T>> {
        self.exchange(msg, Wait::Until(deadline), case_id)
    }

    /// Returns `true` if there is an offer or promise on the opposite side.
    pub fn can_notify(&self) -> bool {
        self.exchanger.inner.lock().wait_queues[self.index].can_notify()
    }

    /// Exchanges `msg` with the specified `wait` strategy.
    fn exchange(&self, mut msg: T, wait: Wait, case_id: CaseId) -> Result<T, ExchangeError<T>> {
        loop {
            // Allocate a packet on the stack.
            let packet;
            {
                let mut inner = self.exchanger.inner.lock();
                if inner.closed {
                    return Err(ExchangeError::Disconnected(msg));
                }

                // If there's someone on the other side, exchange messages with it.
                if let Some(case) = inner.wait_queues[self.index ^ 1].pop() {
                    drop(inner);
                    return Ok(case.exchange(msg));
                }

                // Promise a packet with the message.
                handle::current_reset();
                packet = Packet::new(msg);
                inner.wait_queues[self.index].offer(&packet, case_id);
            }

            // Wait until the timeout and then try aborting the case.
            let timed_out = match wait {
                Wait::YieldOnce => {
                    thread::yield_now();
                    handle::current_try_select(CaseId::abort())
                }
                Wait::Until(deadline) => !handle::current_wait_until(deadline),
            };

            // If someone requested the promised message...
            if handle::current_selected() != CaseId::abort() {
                // Wait until the message is taken and return.
                packet.wait();
                return Ok(packet.into_inner());
            }

            // Revoke the promise.
            let mut inner = self.exchanger.inner.lock();
            inner.wait_queues[self.index].remove(case_id);
            msg = packet.into_inner();

            // If we timed out, return.
            if timed_out {
                return Err(ExchangeError::Timeout(msg));
            }

            // Otherwise, another thread must have woken us up. Let's try again.
        }
    }
}

/// An entry in a wait queue.
enum Entry<T> {
    /// Offers a concrete message.
    Offer {
        handle: Handle,
        packet: *const Packet<T>,
        case_id: CaseId,
    },
    /// Promises a message.
    Promise {
        local: Arc<Local>,
        case_id: CaseId,
    },
}

impl<T> Entry<T> {
    /// Exchange `msg` with this entry and wake it up.
    fn exchange(&self, msg: T) -> T {
        match *self {
            // This is an offer.
            // We can exchange messages immediately.
            Entry::Offer {
                ref handle, packet, ..
            } => {
                let m = unsafe { (*packet).exchange(msg) };
                handle.unpark();
                m
            }

            // This is a promise.
            // We must request the message and then wait until the promise is fulfilled.
            Entry::Promise { ref local, .. } => {
                // Reset the current thread's selection case.
                handle::current_reset();

                // Create a request on the stack and register it in the owner of this entry.
                let req = Request::new(msg);
                local.request_ptr.store(&req as *const _ as usize, Release);

                // Wake up the owner of this entry.
                local.handle.unpark();

                // Wait until our selection case is woken.
                handle::current_wait_until(None);

                // Extract the received message from the request.
                req.packet.into_inner()
            }
        }
    }

    /// Returns the handle associated with the owner of this entry.
    fn handle(&self) -> &Handle {
        match *self {
            Entry::Offer { ref handle, .. } => handle,
            Entry::Promise { ref local, .. } => &local.handle,
        }
    }

    /// Returns the case ID associated with this entry.
    fn case_id(&self) -> CaseId {
        match *self {
            Entry::Offer { case_id, .. } | Entry::Promise { case_id, .. } => case_id,
        }
    }
}

/// A wait queue in which blocked selection cases are registered.
struct WaitQueue<T> {
    cases: VecDeque<Entry<T>>,
}

impl<T> WaitQueue<T> {
    /// Creates a new `WaitQueue`.
    fn new() -> Self {
        WaitQueue {
            cases: VecDeque::new(),
        }
    }

    /// Attempts to fire one case owned by another thread and returns it on success.
    fn pop(&mut self) -> Option<Entry<T>> {
        let thread_id = current_thread_id();

        for i in 0..self.cases.len() {
            if self.cases[i].handle().thread_id() != thread_id {
                if self.cases[i].handle().try_select(self.cases[i].case_id()) {
                    let case = self.cases.remove(i).unwrap();
                    self.maybe_shrink();
                    return Some(case);
                }
            }
        }

        None
    }

    /// Inserts an *offer* case owned by the current thread with `case_id`.
    fn offer(&mut self, packet: *const Packet<T>, case_id: CaseId) {
        self.cases.push_back(Entry::Offer {
            handle: handle::current(),
            packet,
            case_id,
        });
    }

    /// Inserts a *promise* case owned by the current thread with `case_id`.
    fn promise(&mut self, case_id: CaseId) {
        self.cases.push_back(Entry::Promise {
            local: LOCAL.with(|l| l.clone()),
            case_id,
        });
    }

    /// Removes a case owned by the current thread with `case_id`.
    fn remove(&mut self, case_id: CaseId) {
        let thread_id = current_thread_id();

        if let Some((i, _)) = self.cases.iter().enumerate().find(|&(_, case)| {
            case.case_id() == case_id && case.handle().thread_id() == thread_id
        }) {
            self.cases.remove(i);
            self.maybe_shrink();
        }
    }

    /// Returns `true` if there exists a case which isn't owned by the current thread.
    fn can_notify(&self) -> bool {
        let thread_id = current_thread_id();

        for i in 0..self.cases.len() {
            if self.cases[i].handle().thread_id() != thread_id {
                return true;
            }
        }
        false
    }

    /// Aborts all cases and unparks threads which own them.
    fn abort_all(&mut self) {
        for case in self.cases.drain(..) {
            case.handle().try_select(CaseId::abort());
            case.handle().unpark();
        }
        self.maybe_shrink();
    }

    /// Shrinks the internal buffer if its capacity is underused.
    fn maybe_shrink(&mut self) {
        if self.cases.capacity() > 32 && self.cases.capacity() / 2 > self.cases.len() {
            self.cases.shrink_to_fit();
        }
    }
}

impl<T> Drop for WaitQueue<T> {
    fn drop(&mut self) {
        debug_assert!(self.cases.is_empty());
    }
}

thread_local! {
    static THREAD_ID: thread::ThreadId = thread::current().id();
}

/// Returns the current thread ID.
///
/// This is much faster than calling `std::thread::current().id()`.
fn current_thread_id() -> thread::ThreadId {
    THREAD_ID.with(|id| *id)
}

thread_local! {
    static LOCAL: Arc<Local> = Arc::new(Local {
        handle: handle::current(),
        request_ptr: AtomicUsize::new(0),
    });
}

/// Thread-local structure that contains a slot for the `Request` pointer.
struct Local {
    /// The handle associated with this thread.
    handle: Handle,

    /// A slot into which another thread may store a pointer to its `Request`.
    request_ptr: AtomicUsize,
}

/// A request for promised message.
struct Request<T> {
    /// The handle associated with the requestor.
    handle: Handle,

    /// The message for exchange.
    packet: Packet<T>,
}

impl<T> Request<T> {
    /// Creates a new request owned by the current thread for exchanging `msg`.
    fn new(msg: T) -> Self {
        Request {
            handle: handle::current(),
            packet: Packet::new(msg),
        }
    }
}

/// A one-time only packet for exchanging messages.
///
/// A message can be exchanged for the one inside the packet only once.
struct Packet<T> {
    /// The mutex-protected message.
    msg: Mutex<Option<T>>,

    /// This will become `true` when the message is exchanged.
    ready: AtomicBool,
}

impl<T> Packet<T> {
    /// Creates a new packet containing `msg`.
    fn new(msg: T) -> Self {
        Packet {
            msg: Mutex::new(Some(msg)),
            ready: AtomicBool::new(false),
        }
    }

    /// Exchanges `msg` for the one inside the packet.
    fn exchange(&self, msg: T) -> T {
        let r = mem::replace(&mut *self.msg.try_lock().unwrap(), Some(msg));
        self.ready.store(true, Release);
        r.unwrap()
    }

    /// Extracts the message inside the packet.
    fn into_inner(self) -> T {
        self.msg.try_lock().unwrap().take().unwrap()
    }

    /// Spin-waits until the message inside the packet is exchanged.
    fn wait(&self) {
        let mut backoff = Backoff::new();
        while !self.ready.load(Acquire) {
            backoff.step();
        }
    }
}
<|endoftext|>


<commit_before>
use piston_window::*;
use piston_window::character::CharacterCache;

use game::block::Block;
use game::config::Config;
use game::render_options::RenderOptions;
use game::tetromino::Tetromino;

pub struct Grid {
    pub boxes: [[Option<Block>; 10]; 22],
    overlay: [[Option<Block>; 10]; 22],
    border: rectangle::Rectangle,
    block: rectangle::Rectangle,
}

impl Grid {
    pub fn new() -> Grid {
        Grid {
            boxes: [[None; 10]; 22],
            overlay: [[None; 10]; 22],
            border: rectangle::Rectangle::new([1.0; 4]),
            block: rectangle::Rectangle::new([0.0, 0.0, 0.0, 1.0]),
        }
    }

    pub fn apply_tetromino(&mut self, tetromino: &Tetromino, config: &Config) {
        // Clear the overlay
        self.overlay = [[None; 10]; 22];

        // Iterate over the blocks in the active Tetromino and apply them
        // to the overlay
        for y in 0..4 {
            for x in 0..4 {
                if let Some(ref block) = tetromino.blocks[y][x] {
                    let x = (tetromino.x + x as i32) as usize;
                    let y = (tetromino.y + y as i32) as usize;

                    if x >= 10 || y >= 22 {
                        continue;
                    }

                    self.overlay[y][x] = Some(*block);

                    // If the shadow is enabled, also store that in the overlay
                    if config.shadow_enabled {
                        let (shadow_x, shadow_y) = tetromino.find_landing_xy(&self.boxes);
                        let shadow_x = (shadow_x + x as i32) as usize;
                        let shadow_y = (shadow_y + y as i32) as usize;

                        if let Some(ref shadow) = tetromino.shadow[y][x] {
                            self.overlay[shadow_y][shadow_x] = Some(*shadow);
                        }
                    }
                }
            }
        }
    }

    /// Permanently stores the Tetromino in the grid
    pub fn store_tetromino(&mut self, tetromino: &Tetromino) {
        for y in 0..4 {
            for x in 0..4 {
                if let Some(ref block) = tetromino.blocks[y][x] {
                    let x = (tetromino.x + x as i32) as usize;
                    let y = (tetromino.y + y as i32) as usize;

                    if x >= 10 || y >= 22 {
                        continue;
                    }

                    self.boxes[y][x] = Some(*block);
                }
            }
        }
    }

    /// Removes complete lines from the grid
    pub fn remove_complete_lines(&mut self, config: &Config) -> u32 {
        // Pointer to where we're currently writing lines
        let mut y_mut = (config.grid_size.1 - 1) as usize;
        let mut cleared_lines = 0;

        for y in (0..config.grid_size.1).rev() {
            // If every column in this row has a block,
            // we consider it "complete"
            let complete = self.boxes[y as usize].iter().all(|block| block.is_some());

            // If this is not a complete line, copy it
            // into the currently pointed line
            if !complete {
                self.boxes[y_mut] = self.boxes[y as usize];
                y_mut -= 1;
                if y_mut == 0 {
                    break;
                }
            } else {
                cleared_lines += 1;
            }
        }

        cleared_lines
    }

    pub fn render<'a, G, C>(&self, options: &mut RenderOptions<'a, G, C>, e: &Event)
        where C: CharacterCache,
              G: Graphics<Texture = <C as CharacterCache>::Texture>
    {
        let grid_offset = options.config.grid_offset;
        let tile_size = options.config.tile_size;

        // Draw the "border" first
        self.border.draw([(grid_offset - 2.0) as f64,
                          (grid_offset - 2.0) as f64,
                          (tile_size * 10.0 + 4.0) as f64,
                          (tile_size * 20.0 + 4.0) as f64],
                         &Default::default(),
                         options.context.transform,
                         options.graphics);

        // Start drawing the grid from 2 onwards. The official Tetris rules
        // state that the grid is 10x22 but the top two rows are hidden
        for y in 2..options.config.grid_size.1 {
            for x in 0..options.config.grid_size.0 {
                let x = x as usize;
                let y = y as usize;

                let adjusted_y = y - 2;
                if let Some(ref block) = self.overlay[y][x] {
                    block.render(x, y, options.config, options.context, options.graphics, e);
                    continue;
                }

                match self.boxes[y as usize][x as usize] {
                    Some(ref block) => {
                        block.render(x, y, options.config, options.context, options.graphics, e);
                    }
                    None => {
                        self.block.draw([x as f64 * tile_size + grid_offset,
                                         adjusted_y as f64 * tile_size + grid_offset,
                                         tile_size as f64,
                                         tile_size as f64],
                                        &Default::default(),
                                        options.context.transform,
                                        options.graphics);
                    }
                };
            }
        }
    }
}
<commit_msg>Fixed the shadow panic<commit_after>
use piston_window::*;
use piston_window::character::CharacterCache;

use game::block::Block;
use game::config::Config;
use game::render_options::RenderOptions;
use game::tetromino::Tetromino;

pub struct Grid {
    pub boxes: [[Option<Block>; 10]; 22],
    overlay: [[Option<Block>; 10]; 22],
    border: rectangle::Rectangle,
    block: rectangle::Rectangle,
}

impl Grid {
    pub fn new() -> Grid {
        Grid {
            boxes: [[None; 10]; 22],
            overlay: [[None; 10]; 22],
            border: rectangle::Rectangle::new([1.0; 4]),
            block: rectangle::Rectangle::new([0.0, 0.0, 0.0, 1.0]),
        }
    }

    pub fn apply_tetromino(&mut self, tetromino: &Tetromino, config: &Config) {
        // Clear the overlay
        self.overlay = [[None; 10]; 22];

        // Iterate over the blocks in the active Tetromino and apply them
        // to the overlay
        for y in 0..4 {
            for x in 0..4 {
                if let Some(ref block) = tetromino.blocks[y][x] {
                    let tetromino_x = (tetromino.x + x as i32) as usize;
                    let tetromino_y = (tetromino.y + y as i32) as usize;

                    if x >= 10 || y >= 22 {
                        continue;
                    }

                    self.overlay[tetromino_y][tetromino_x] = Some(*block);

                    // If the shadow is enabled, also store that in the overlay
                    if config.shadow_enabled {
                        let (shadow_x, shadow_y) = tetromino.find_landing_xy(&self.boxes);
                        let shadow_x = (shadow_x + x as i32) as usize;
                        let shadow_y = (shadow_y + y as i32) as usize;

                        if let Some(ref shadow) = tetromino.shadow[y][x] {
                            self.overlay[shadow_y][shadow_x] = Some(*shadow);
                        }
                    }
                }
            }
        }
    }

    /// Permanently stores the Tetromino in the grid
    pub fn store_tetromino(&mut self, tetromino: &Tetromino) {
        for y in 0..4 {
            for x in 0..4 {
                if let Some(ref block) = tetromino.blocks[y][x] {
                    let x = (tetromino.x + x as i32) as usize;
                    let y = (tetromino.y + y as i32) as usize;

                    if x >= 10 || y >= 22 {
                        continue;
                    }

                    self.boxes[y][x] = Some(*block);
                }
            }
        }
    }

    /// Removes complete lines from the grid
    pub fn remove_complete_lines(&mut self, config: &Config) -> u32 {
        // Pointer to where we're currently writing lines
        let mut y_mut = (config.grid_size.1 - 1) as usize;
        let mut cleared_lines = 0;

        for y in (0..config.grid_size.1).rev() {
            // If every column in this row has a block,
            // we consider it "complete"
            let complete = self.boxes[y as usize].iter().all(|block| block.is_some());

            // If this is not a complete line, copy it
            // into the currently pointed line
            if !complete {
                self.boxes[y_mut] = self.boxes[y as usize];
                y_mut -= 1;
                if y_mut == 0 {
                    break;
                }
            } else {
                cleared_lines += 1;
            }
        }

        cleared_lines
    }

    pub fn render<'a, G, C>(&self, options: &mut RenderOptions<'a, G, C>, e: &Event)
        where C: CharacterCache,
              G: Graphics<Texture = <C as CharacterCache>::Texture>
    {
        let grid_offset = options.config.grid_offset;
        let tile_size = options.config.tile_size;

        // Draw the "border" first
        self.border.draw([(grid_offset - 2.0) as f64,
                          (grid_offset - 2.0) as f64,
                          (tile_size * 10.0 + 4.0) as f64,
                          (tile_size * 20.0 + 4.0) as f64],
                         &Default::default(),
                         options.context.transform,
                         options.graphics);

        // Start drawing the grid from 2 onwards. The official Tetris rules
        // state that the grid is 10x22 but the top two rows are hidden
        for y in 2..options.config.grid_size.1 {
            for x in 0..options.config.grid_size.0 {
                let x = x as usize;
                let y = y as usize;

                let adjusted_y = y - 2;
                if let Some(ref block) = self.overlay[y][x] {
                    block.render(x, y, options.config, options.context, options.graphics, e);
                    continue;
                }

                match self.boxes[y as usize][x as usize] {
                    Some(ref block) => {
                        block.render(x, y, options.config, options.context, options.graphics, e);
                    }
                    None => {
                        self.block.draw([x as f64 * tile_size + grid_offset,
                                         adjusted_y as f64 * tile_size + grid_offset,
                                         tile_size as f64,
                                         tile_size as f64],
                                        &Default::default(),
                                        options.context.transform,
                                        options.graphics);
                    }
                };
            }
        }
    }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification,
        managed_heap_memory)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *const c_void;
type In6Addr = [u8, ..16];

#[repr(C)]
struct GeoIPLookup_ {
    netmask: c_int
}

impl GeoIPLookup_ {
    fn new() -> GeoIPLookup_ {
        GeoIPLookup_ {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *const c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup_) -> *const c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup_) -> *const c_char;
    fn GeoIP_record_by_ipnum(db: GeoIP_, ipnum: c_ulong) -> *const GeoIPRecord_;
    fn GeoIP_record_by_ipnum_v6(db: GeoIP_, ipnum: In6Addr) -> *const GeoIPRecord_;
    fn GeoIPRecord_delete(gir: *const GeoIPRecord_);
    fn GeoIP_set_charset(db: GeoIP_, charset: c_int) -> c_int;
}

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

#[repr(C)]
pub struct GeoIPRecord_ {
    country_code: *const c_char,
    country_code3: *const c_char,
    country_name: *const c_char,
    region: *const c_char,
    city: *const c_char,
    postal_code: *const c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *const c_char,
    netmask: c_int
}

pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

impl CityInfo {
    fn from_geoiprecord(res: &GeoIPRecord_) -> CityInfo {
        let country_code = unsafe { if res.country_code.is_null() {
            None
        } else {
            CString::new(res.country_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_code3 = unsafe { if res.country_code3.is_null() {
            None
        } else {
            CString::new(res.country_code3, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_name = unsafe { if res.country_name.is_null() {
            None
        } else {
            CString::new(res.country_name, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let region = unsafe { if res.region.is_null() {
            None
        } else {
            CString::new(res.region, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let city = unsafe { if res.city.is_null() {
            None
        } else {
            CString::new(res.city, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let postal_code = unsafe { if res.postal_code.is_null() {
            None
        } else {
            CString::new(res.postal_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let continent_code = unsafe { if res.continent_code.is_null() {
            None
        } else {
            CString::new(res.continent_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        CityInfo {
            country_code: country_code,
            country_code3: country_code3,
            country_name: country_name,
            region: region,
            city: city,
            postal_code: postal_code,
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: continent_code,
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { GeoIP_set_charset(db, UTF8 as c_int) } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIP { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_record_by_ipnum(self.db, ipnum)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_record_by_ipnum_v6(self.db, in6_addr)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let city_info = CityInfo::from_geoiprecord(&unsafe { *cres });
        unsafe { GeoIPRecord_delete(cres) };
        unsafe { std::mem::forget(cres) };
        Some(city_info)
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup_::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<commit_msg>-managed_heap_memory<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *const c_void;
type In6Addr = [u8, ..16];

#[repr(C)]
struct GeoIPLookup_ {
    netmask: c_int
}

impl GeoIPLookup_ {
    fn new() -> GeoIPLookup_ {
        GeoIPLookup_ {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *const c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup_) -> *const c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup_) -> *const c_char;
    fn GeoIP_record_by_ipnum(db: GeoIP_, ipnum: c_ulong) -> *const GeoIPRecord_;
    fn GeoIP_record_by_ipnum_v6(db: GeoIP_, ipnum: In6Addr) -> *const GeoIPRecord_;
    fn GeoIPRecord_delete(gir: *const GeoIPRecord_);
    fn GeoIP_set_charset(db: GeoIP_, charset: c_int) -> c_int;
}

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

#[repr(C)]
pub struct GeoIPRecord_ {
    country_code: *const c_char,
    country_code3: *const c_char,
    country_name: *const c_char,
    region: *const c_char,
    city: *const c_char,
    postal_code: *const c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *const c_char,
    netmask: c_int
}

pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

impl CityInfo {
    fn from_geoiprecord(res: &GeoIPRecord_) -> CityInfo {
        let country_code = unsafe { if res.country_code.is_null() {
            None
        } else {
            CString::new(res.country_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_code3 = unsafe { if res.country_code3.is_null() {
            None
        } else {
            CString::new(res.country_code3, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_name = unsafe { if res.country_name.is_null() {
            None
        } else {
            CString::new(res.country_name, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let region = unsafe { if res.region.is_null() {
            None
        } else {
            CString::new(res.region, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let city = unsafe { if res.city.is_null() {
            None
        } else {
            CString::new(res.city, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let postal_code = unsafe { if res.postal_code.is_null() {
            None
        } else {
            CString::new(res.postal_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let continent_code = unsafe { if res.continent_code.is_null() {
            None
        } else {
            CString::new(res.continent_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        CityInfo {
            country_code: country_code,
            country_code3: country_code3,
            country_name: country_name,
            region: region,
            city: city,
            postal_code: postal_code,
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: continent_code,
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { GeoIP_set_charset(db, UTF8 as c_int) } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIP { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_record_by_ipnum(self.db, ipnum)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_record_by_ipnum_v6(self.db, in6_addr)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let city_info = CityInfo::from_geoiprecord(&unsafe { *cres });
        unsafe { GeoIPRecord_delete(cres) };
        unsafe { std::mem::forget(cres) };
        Some(city_info)
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup_::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<|endoftext|>


<commit_before>extern crate gl;

pub mod builder;

/// Wrapper for a linked OpenGL Program.
///
/// Created using `ProgramBuilder` or `ProgramFromFileBuilder`.
pub struct Program {
    pub handle: u32,
}

impl Program {
    /// Wrapper for `glUseProgram`.
    pub fn bind(&self) {
        unsafe { gl::UseProgram(self.handle); }
    }

    /// Get the underlying OpenGL handle.
    pub fn handle(&self) -> u32 {
        return self.handle;
    }
}

impl Drop for Program {
    fn drop (&mut self) {
        unsafe { gl::DeleteProgram(self.handle); }
    }
}
<commit_msg>Hotfix for Program<commit_after>extern crate gl;

pub mod builder;

/// Wrapper for a linked OpenGL Program.
///
/// Created using `ProgramBuilder` or `ProgramFromFileBuilder`.
pub struct Program {
    handle: u32,
}

impl Program {
    /// Wrapper for `glUseProgram`.
    pub fn bind(&self) {
        unsafe { gl::UseProgram(self.handle); }
    }

    /// Get the underlying OpenGL handle.
    pub fn handle(&self) -> u32 {
        return self.handle;
    }
}

impl Drop for Program {
    fn drop (&mut self) {
        unsafe { gl::DeleteProgram(self.handle); }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate bloodhound;

use test::Bencher;
use std::path::PathBuf;
use bloodhound::matching::entry;
use bloodhound::matching::find;

#[bench]
fn bench_find(b: &mut Bencher) {
    let haystack = vec![
        entry::new("src/hound.rs".to_string()),
        entry::new("lib/hounds.rs".to_string()),
        entry::new("Houndfile".to_string())
    ];
    b.iter(|| find("match", &haystack, 5));
}

#[bench]
fn bench_similarity(b: &mut Bencher) {
    let entry = entry::new("bloodhound/src/matching.rs".to_string());
    b.iter(|| entry.similarity("matching.rs"));
}
<commit_msg>Remove unused matching benchmark<commit_after><|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

struct App {
    gl: GlGraphics,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [800, 600])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut app = App{gl: GlGraphics::new(opengl)};

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
    }
}
<commit_msg>Rendering white screen<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

struct App {
    gl: GlGraphics,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

        self.gl.draw(args.viewport(), |c, gl| {
            clear(WHITE, gl);
        });
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut app = App{gl: GlGraphics::new(opengl)};

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `GetHostState` request and response.
//!
//! This module provides a Cerberus command that allows the querying of
//! the reset state of the host processor protected by Cerberus.

use crate::io::Read;
use crate::io::Write;
use crate::mem::Arena;
use crate::protocol::wire::Error;
use crate::protocol::wire::FromWire;
use crate::protocol::wire::ToWire;
use crate::protocol::Command;
use crate::protocol::CommandType;
use crate::protocol::Request;
use crate::protocol::Response;

#[cfg(feature = "arbitrary-derive")]
use libfuzzer_sys::arbitrary::{self, Arbitrary};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// A command for requesting the host reset state
///
/// Corresponds to [`CommandType::GetHostState`].
pub enum GetHostState {}

impl<'a> Command<'a> for GetHostState {
    type Req = GetHostStateRequest;
    type Resp = GetHostStateResponse;
}

/// The [`GetHostState`] request.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GetHostStateRequest {
    port_id: u8,
}
make_fuzz_safe!(GetHostStateRequest);

impl Request<'_> for GetHostStateRequest {
    const TYPE: CommandType = CommandType::GetHostState;
}

impl<'a> FromWire<'a> for GetHostStateRequest {
    fn from_wire<R: Read, A: Arena>(mut r: R, _: &'a A) -> Result<Self, Error> {
        let port_id = r.read_le()?;
        Ok(Self { port_id })
    }
}

impl<'a> ToWire for GetHostStateRequest {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), Error> {
        w.write_le(self.port_id)?;
        Ok(())
    }
}

make_fuzz_safe! {
    /// The [`GetHostState`] response.
    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub struct GetHostStateResponse as GHSWrap {
        host_reset_state: HostResetState,
    }
}

wire_enum! {
    /// Host processor reset state
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum HostResetState: u8 {
        /// Host is running (out of reset)
        HostRunning = 0x00,
        /// Host is being held in reset
        HostInReset = 0x01,
        /// Host is not being held in reset, but is not running
        HostNotRunning = 0x02,
    }
}

impl<'a> Response<'a> for GetHostStateResponse {
    const TYPE: CommandType = CommandType::GetHostState;
}

impl<'a> FromWire<'a> for GetHostStateResponse {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        arena: &'a A,
    ) -> Result<Self, Error> {
        let host_reset_state = HostResetState::from_wire(&mut r, arena)?;
        Ok(Self { host_reset_state })
    }
}

impl ToWire for GetHostStateResponse {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), Error> {
        self.host_reset_state.to_wire(&mut w)?;
        Ok(())
    }
}

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

    round_trip_test! {
        request_round_trip: {
            bytes: &[0x7f],
            value: GetHostStateRequest {
                port_id: 0x7f,
            },
        },
        response_round_trip: {
            bytes: &[0x01],
            value: GetHostStateResponse {
                host_reset_state: HostResetState::HostInReset,
            },
        },
    }
}
<commit_msg>[protocol] Fix a build error in some configurations<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `GetHostState` request and response.
//!
//! This module provides a Cerberus command that allows the querying of
//! the reset state of the host processor protected by Cerberus.

use crate::io::Read;
use crate::io::Write;
use crate::mem::Arena;
use crate::protocol::wire::Error;
use crate::protocol::wire::FromWire;
use crate::protocol::wire::ToWire;
use crate::protocol::Command;
use crate::protocol::CommandType;
use crate::protocol::Request;
use crate::protocol::Response;

#[cfg(feature = "arbitrary-derive")]
use libfuzzer_sys::arbitrary::{self, Arbitrary};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// A command for requesting the host reset state.
///
/// Corresponds to [`CommandType::GetHostState`].
pub enum GetHostState {}

impl<'a> Command<'a> for GetHostState {
    type Req = GetHostStateRequest;
    type Resp = GetHostStateResponse;
}

/// The [`GetHostState`] request.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GetHostStateRequest {
    /// The port that the device whose reset counter is being looked up.
    pub port_id: u8,
}
make_fuzz_safe!(GetHostStateRequest);

impl Request<'_> for GetHostStateRequest {
    const TYPE: CommandType = CommandType::GetHostState;
}

impl<'a> FromWire<'a> for GetHostStateRequest {
    fn from_wire<R: Read, A: Arena>(mut r: R, _: &'a A) -> Result<Self, Error> {
        let port_id = r.read_le()?;
        Ok(Self { port_id })
    }
}

impl<'a> ToWire for GetHostStateRequest {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), Error> {
        w.write_le(self.port_id)?;
        Ok(())
    }
}

/// The [`GetHostState`] response.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GetHostStateResponse {
    /// The returned state.
    host_reset_state: HostResetState,
}
make_fuzz_safe!(GetHostStateResponse);

wire_enum! {
    /// Host processor reset state
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum HostResetState: u8 {
        /// Host is running (out of reset)
        HostRunning = 0x00,
        /// Host is being held in reset
        HostInReset = 0x01,
        /// Host is not being held in reset, but is not running
        HostNotRunning = 0x02,
    }
}

impl<'a> Response<'a> for GetHostStateResponse {
    const TYPE: CommandType = CommandType::GetHostState;
}

impl<'a> FromWire<'a> for GetHostStateResponse {
    fn from_wire<R: Read, A: Arena>(
        mut r: R,
        arena: &'a A,
    ) -> Result<Self, Error> {
        let host_reset_state = HostResetState::from_wire(&mut r, arena)?;
        Ok(Self { host_reset_state })
    }
}

impl ToWire for GetHostStateResponse {
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), Error> {
        self.host_reset_state.to_wire(&mut w)?;
        Ok(())
    }
}

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

    round_trip_test! {
        request_round_trip: {
            bytes: &[0x7f],
            value: GetHostStateRequest {
                port_id: 0x7f,
            },
        },
        response_round_trip: {
            bytes: &[0x01],
            value: GetHostStateResponse {
                host_reset_state: HostResetState::HostInReset,
            },
        },
    }
}
<|endoftext|>