<commit_before>#[cfg(not(test))] pub const WIDTH: usize = 5;
#[cfg(not(test))] pub const HEIGHT: usize = 5;
#[cfg(not(test))] pub const X_ROW: usize = 4;

#[cfg(test)] pub const WIDTH: usize = 4;
#[cfg(test)] pub const HEIGHT: usize = 3;
#[cfg(test)] pub const X_ROW: usize = 2;

pub struct Game {
    turns: u32,
    current_turn: Player,
    winner: Option<Player>,
    field: Field,
}

impl Game {
    pub fn new() -> Game {
        Game {
            turns: 0,
            current_turn: Player::Red,
            winner : None,
		    field: Field::new(),
		}
    }

    pub fn current_turn(&self) -> Player {
        self.current_turn
    }

    pub fn winner(&self) -> Option<Player> {
        self.winner
    }

    pub fn make_turn(&mut self, column: usize) -> Result<(), GameError> {
        if self.winner.is_some() { return Err(GameError::AlreadyEnded); }
        try!(self.field.throw_token(column, self.current_turn));
        self.winner = self.field.win_check();
        self.turns += 1;
        self.current_turn = self.current_turn.next();
        Ok(())
    }

    pub fn current_state(&self) -> &[Option<Player>; WIDTH * HEIGHT] {
        &self.field.cells
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GameError {
    NoSuchColumn,
    ColumnIsFull,
    AlreadyEnded,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Player {
    Red,
    Blue,
}

impl Player {
    fn next(self) -> Player {
        match self {
            Player::Red => Player::Blue,
            Player::Blue => Player::Red,
        }
    }
}

pub struct Field {
    cells: [Option<Player>; WIDTH * HEIGHT],
}

impl Field {

    pub fn with_cells(cells: [Option<Player>; WIDTH * HEIGHT]) -> Field {
        Field {
            cells: cells,
        }
    }

    pub fn free_columns(&self) -> Option<Vec<usize>> {
        let mut res = Vec::new();

        for (index, Column { cells }) in self.columns().enumerate() {
            if cells.iter().any(|x| x.is_none()) {
                res.push(index);
            }
        }

        if res.is_empty() { None } else { Some(res) }
    }

    fn new() -> Field {
        Field {
		    cells: [None; (WIDTH * HEIGHT) as usize],
		}
    }

    fn throw_token(&mut self, column_index: usize, player: Player) -> Result<(), GameError> {
        if column_index > WIDTH { return Err(GameError::NoSuchColumn); }
        let Column { cells } = Columns::index(&self.cells, column_index).next().unwrap();
        let row_index = try!( cells.iter().position(|x| x.is_none() ).ok_or(GameError::ColumnIsFull) );
        let position = row_index * WIDTH + column_index;
        self.cells[position] = Some(player);
        Ok(())
    }

    fn win_check(&self) -> Option<Player> {
        for Row { cells } in self.rows() {
            match Field::max_series(&cells[..]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        for Column { cells } in self.columns() {
            match Field::max_series(&cells[..]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        for Diagonal { cells, length } in self.diagonals() {
            match Field::max_series(&cells[0..length]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        None
    }

    fn rows<'a>(&'a self) -> Rows<'a>{
        Rows::new(&self.cells)
    }

    fn columns<'a, 'b>(&'a self) -> Columns<'a> {
        Columns::new(&self.cells)
    }

    fn diagonals<'a>(&'a self) -> Diagonals<'a> {
        Diagonals::new(&self.cells)
    }

    fn max_series(cells: &[Option<Player>]) -> (Option<Player>, usize) {
        const RED: Option<Player> = Some(Player::Red);
        const BLUE: Option<Player> = Some(Player::Blue);
        let mut red_max = 0;
        let mut blue_max = 0;
        let mut prev_player = None;
        let mut series = 0;

        for curr_player in cells.iter() {
            match (*curr_player, prev_player) {
                (Some(_), None) => { series = 1; },
                (RED, RED) | (BLUE, BLUE) => { series += 1; },
                (None, RED) | (BLUE, RED) => {
					if series > red_max { red_max = series; }
					series = 1;
				},
                (None, BLUE) | (RED, BLUE) => {
					if series > blue_max { blue_max = series; }
					series = 1;
				},
                _ => {}
            }
            prev_player = *curr_player;
        }

        match prev_player {
            BLUE => if series > blue_max { blue_max = series; },
            RED  => if series > red_max { red_max = series; },
            _ => {},
        }

        if red_max == blue_max { return (None, red_max); }
        if red_max > blue_max { return (RED, red_max); } else { return (BLUE, blue_max); }
    }
}

struct Rows<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_row: usize,
}

impl<'a> Rows<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Rows<'a> {
        Rows {
		    field: field,
		    current_row: 0,
		}
    }

    fn index(field: &'a [Option<Player>; WIDTH * HEIGHT], index: usize) -> Rows<'a> {
        Rows {
		    field: field,
		    current_row: index,
		}
    }
}

impl<'a> Iterator for Rows<'a> {
    type Item = Row;

    fn next(&mut self) -> Option<Row> {
        if self.current_row < HEIGHT {
            let from = self.current_row * WIDTH;
            let to = from + WIDTH;
            let mut cells = [None; WIDTH];
            for (val, index) in (&self.field[from .. to]).iter().zip(0..WIDTH) {
                cells[index] = *val;
            }
            self.current_row += 1;
            Some( Row { cells: cells} )
        } else {
            None
        }
    }
}

struct Row {
    cells: [Option<Player>; WIDTH],
}

struct Columns<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_column: usize,
}

impl<'a> Columns<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Columns<'a> {
        Columns {
		    field: field,
			current_column: 0,
		}
    }

    fn index(field: &'a [Option<Player>; WIDTH * HEIGHT], index: usize) -> Columns<'a> {
        Columns {
            field: field,
            current_column: index,
		}
    }
}

impl<'a> Iterator for Columns<'a> {
    type Item = Column;

    fn next(&mut self) -> Option<Column> {
        if self.current_column < WIDTH {
            let mut cells = [None; HEIGHT];
            for i in 0..HEIGHT {
                let index: usize = (i * WIDTH as usize) + self.current_column as usize;
                cells[i] = self.field[index];
            }
            self.current_column += 1;
            Some( Column { cells: cells} )
        } else {
            None
        }
    }
}

struct Column {
    cells: [Option<Player>; HEIGHT],
}

struct Diagonals<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_diagonal : usize,
    total_diagonals: usize,
}

impl<'a> Diagonals<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Diagonals<'a> {
        Diagonals {
		    field: field,
		    current_diagonal: 0,
		    total_diagonals: WIDTH + HEIGHT - 3,
		}
    }
}

impl<'a> Iterator for Diagonals<'a> {
    type Item = Diagonal;

    fn next(&mut self) -> Option<Diagonal> {
        if WIDTH == 1 || HEIGHT == 1 { return None; }
        if self.total_diagonals >= self.current_diagonal { return None; }
        None
    }
}

struct Diagonal {
    cells: [Option<Player>; WIDTH + HEIGHT],
    length: usize,
}

#[test]
fn test_diagonal_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_row_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(0).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_column_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(0).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_max_series() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    assert_eq!(Field::max_series(&[]), (None, 0));
    assert_eq!(Field::max_series(&[None, None]), (None, 0));
    assert_eq!(Field::max_series(&[red]), (red, 1));
    assert_eq!(Field::max_series(&[blue]), (blue, 1));
    assert_eq!(Field::max_series(&[red, blue]), (None, 1));
    assert_eq!(Field::max_series(&[red, red, blue]), (red, 2));
    assert_eq!(Field::max_series(&[red, red, None, red, red, red]), (red, 3));
    assert_eq!(Field::max_series(&[blue, blue, None, red, red, red]), (red, 3));
    assert_eq!(Field::max_series(&[blue, blue, None, red, red, red, blue, blue, blue]), (None, 3));
}

#[test]
fn test_rows_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];
    let mut rows = Rows::new(cells);
    let row1 = rows.next().unwrap();
    let row2 = rows.next().unwrap();
    let row3 = rows.next().unwrap();
    assert!(rows.next().is_none());

    assert_eq!(row1.cells, [red,  None, blue, None] );
    assert_eq!(row2.cells, [None, red,  blue, red] );
    assert_eq!(row3.cells, [None, None, None, None] );
}

#[test]
fn test_columns_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];

    let mut columns = Columns::new(&cells);
    let column1 = columns.next().unwrap();
    let column2 = columns.next().unwrap();
    let column3 = columns.next().unwrap();
    let column4 = columns.next().unwrap();
    assert!(columns.next().is_none());

    assert_eq!(column1.cells, [red,  None, None] );
    assert_eq!(column2.cells, [None, red,  None] );
    assert_eq!(column3.cells, [blue, blue, None] );
    assert_eq!(column4.cells, [None, red,  None] );
}

#[test]
fn test_diagonal_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];

	let mut diagonals = Diagonals::new(&cells);
	let d1 = diagonals.next().unwrap();
	let d2 = diagonals.next().unwrap();
	let d3 = diagonals.next().unwrap();
	let d4 = diagonals.next().unwrap();

	let d5 = diagonals.next().unwrap();
	let d6 = diagonals.next().unwrap();
	let d7 = diagonals.next().unwrap();
	let d8 = diagonals.next().unwrap();

	assert!( diagonals.next().is_none() );

	fn check(d: Diagonal, cells: [Option<Player>; WIDTH + HEIGHT], length: usize) {
	    assert_eq!((d.cells, d.length), (cells, length) );
	}

	check(d1, [None, None, None, None, None, None, None], 2);
	check(d2, [blue, red, None, None, None, None, None], 3);
	check(d3, [None, blue, None, None, None, None, None], 3);
	check(d4, [red, None, None, None, None, None, None], 2);

	check(d5, [None, None, None, None, None, None, None], 2);
	check(d6, [red, red, None, None, None, None, None], 3);
	check(d7, [None, blue, None, None, None, None, None], 3);
	check(d8, [blue, red, None, None, None, None, None], 2);

}
<commit_msg>Added 'is_full' method to Game<commit_after>#[cfg(not(test))] pub const WIDTH: usize = 5;
#[cfg(not(test))] pub const HEIGHT: usize = 5;
#[cfg(not(test))] pub const X_ROW: usize = 4;

#[cfg(test)] pub const WIDTH: usize = 4;
#[cfg(test)] pub const HEIGHT: usize = 3;
#[cfg(test)] pub const X_ROW: usize = 2;

pub struct Game {
    turns: u32,
    current_turn: Player,
    winner: Option<Player>,
    field: Field,
}

impl Game {
    pub fn new() -> Game {
        Game {
            turns: 0,
            current_turn: Player::Red,
            winner : None,
		    field: Field::new(),
		}
    }

    pub fn current_turn(&self) -> Player {
        self.current_turn
    }

    pub fn winner(&self) -> Option<Player> {
        self.winner
    }

    pub fn is_full(&self) -> bool {
        self.turns as usize == WIDTH * HEIGHT
    }

    pub fn make_turn(&mut self, column: usize) -> Result<(), GameError> {
        if self.winner.is_some() { return Err(GameError::AlreadyEnded); }
        try!(self.field.throw_token(column, self.current_turn));
        self.winner = self.field.win_check();
        self.turns += 1;
        self.current_turn = self.current_turn.next();
        Ok(())
    }

    pub fn current_state(&self) -> &[Option<Player>; WIDTH * HEIGHT] {
        &self.field.cells
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GameError {
    NoSuchColumn,
    ColumnIsFull,
    AlreadyEnded,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Player {
    Red,
    Blue,
}

impl Player {
    fn next(self) -> Player {
        match self {
            Player::Red => Player::Blue,
            Player::Blue => Player::Red,
        }
    }
}

pub struct Field {
    cells: [Option<Player>; WIDTH * HEIGHT],
}

impl Field {

    pub fn with_cells(cells: [Option<Player>; WIDTH * HEIGHT]) -> Field {
        Field {
            cells: cells,
        }
    }

    pub fn free_columns(&self) -> Option<Vec<usize>> {
        let mut res = Vec::new();

        for (index, Column { cells }) in self.columns().enumerate() {
            if cells.iter().any(|x| x.is_none()) {
                res.push(index);
            }
        }

        if res.is_empty() { None } else { Some(res) }
    }

    fn new() -> Field {
        Field {
		    cells: [None; (WIDTH * HEIGHT) as usize],
		}
    }

    fn throw_token(&mut self, column_index: usize, player: Player) -> Result<(), GameError> {
        if column_index > WIDTH { return Err(GameError::NoSuchColumn); }
        let Column { cells } = Columns::index(&self.cells, column_index).next().unwrap();
        let row_index = try!( cells.iter().position(|x| x.is_none() ).ok_or(GameError::ColumnIsFull) );
        let position = row_index * WIDTH + column_index;
        self.cells[position] = Some(player);
        Ok(())
    }

    fn win_check(&self) -> Option<Player> {
        for Row { cells } in self.rows() {
            match Field::max_series(&cells[..]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        for Column { cells } in self.columns() {
            match Field::max_series(&cells[..]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        for Diagonal { cells, length } in self.diagonals() {
            match Field::max_series(&cells[0..length]) {
                (Some(player), length) => {
                	if length >= X_ROW {
                	    return Some(player);
                	}
                },
                _ => {}
            }
        }

        None
    }

    fn rows<'a>(&'a self) -> Rows<'a>{
        Rows::new(&self.cells)
    }

    fn columns<'a, 'b>(&'a self) -> Columns<'a> {
        Columns::new(&self.cells)
    }

    fn diagonals<'a>(&'a self) -> Diagonals<'a> {
        Diagonals::new(&self.cells)
    }

    fn max_series(cells: &[Option<Player>]) -> (Option<Player>, usize) {
        const RED: Option<Player> = Some(Player::Red);
        const BLUE: Option<Player> = Some(Player::Blue);
        let mut red_max = 0;
        let mut blue_max = 0;
        let mut prev_player = None;
        let mut series = 0;

        for curr_player in cells.iter() {
            match (*curr_player, prev_player) {
                (Some(_), None) => { series = 1; },
                (RED, RED) | (BLUE, BLUE) => { series += 1; },
                (None, RED) | (BLUE, RED) => {
					if series > red_max { red_max = series; }
					series = 1;
				},
                (None, BLUE) | (RED, BLUE) => {
					if series > blue_max { blue_max = series; }
					series = 1;
				},
                _ => {}
            }
            prev_player = *curr_player;
        }

        match prev_player {
            BLUE => if series > blue_max { blue_max = series; },
            RED  => if series > red_max { red_max = series; },
            _ => {},
        }

        if red_max == blue_max { return (None, red_max); }
        if red_max > blue_max { return (RED, red_max); } else { return (BLUE, blue_max); }
    }
}

struct Rows<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_row: usize,
}

impl<'a> Rows<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Rows<'a> {
        Rows {
		    field: field,
		    current_row: 0,
		}
    }

    fn index(field: &'a [Option<Player>; WIDTH * HEIGHT], index: usize) -> Rows<'a> {
        Rows {
		    field: field,
		    current_row: index,
		}
    }
}

impl<'a> Iterator for Rows<'a> {
    type Item = Row;

    fn next(&mut self) -> Option<Row> {
        if self.current_row < HEIGHT {
            let from = self.current_row * WIDTH;
            let to = from + WIDTH;
            let mut cells = [None; WIDTH];
            for (val, index) in (&self.field[from .. to]).iter().zip(0..WIDTH) {
                cells[index] = *val;
            }
            self.current_row += 1;
            Some( Row { cells: cells} )
        } else {
            None
        }
    }
}

struct Row {
    cells: [Option<Player>; WIDTH],
}

struct Columns<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_column: usize,
}

impl<'a> Columns<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Columns<'a> {
        Columns {
		    field: field,
			current_column: 0,
		}
    }

    fn index(field: &'a [Option<Player>; WIDTH * HEIGHT], index: usize) -> Columns<'a> {
        Columns {
            field: field,
            current_column: index,
		}
    }
}

impl<'a> Iterator for Columns<'a> {
    type Item = Column;

    fn next(&mut self) -> Option<Column> {
        if self.current_column < WIDTH {
            let mut cells = [None; HEIGHT];
            for i in 0..HEIGHT {
                let index: usize = (i * WIDTH as usize) + self.current_column as usize;
                cells[i] = self.field[index];
            }
            self.current_column += 1;
            Some( Column { cells: cells} )
        } else {
            None
        }
    }
}

struct Column {
    cells: [Option<Player>; HEIGHT],
}

struct Diagonals<'a> {
    field: &'a [Option<Player>; WIDTH * HEIGHT],
    current_diagonal : usize,
    total_diagonals: usize,
}

impl<'a> Diagonals<'a> {
    fn new(field: &'a [Option<Player>; WIDTH * HEIGHT]) -> Diagonals<'a> {
        Diagonals {
		    field: field,
		    current_diagonal: 0,
		    total_diagonals: WIDTH + HEIGHT - 3,
		}
    }
}

impl<'a> Iterator for Diagonals<'a> {
    type Item = Diagonal;

    fn next(&mut self) -> Option<Diagonal> {
        if WIDTH == 1 || HEIGHT == 1 { return None; }
        if self.total_diagonals >= self.current_diagonal { return None; }
        None
    }
}

struct Diagonal {
    cells: [Option<Player>; WIDTH + HEIGHT],
    length: usize,
}

#[test]
fn test_diagonal_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_row_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(0).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_column_win() {
    let mut game = Game::new();
    game.make_turn(0).unwrap();
    println!("");
    println!("{:?}", &game.field.cells);
    game.make_turn(1).unwrap();
    println!("{:?}", &game.field.cells);
    game.make_turn(0).unwrap();
    println!("{:?}", &game.field.cells);
    assert_eq!(game.win_check(), Some(Player::Red) );
    assert_eq!(game.make_turn(0), Err(GameError::AlreadyEnded) );
}

#[test]
fn test_max_series() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    assert_eq!(Field::max_series(&[]), (None, 0));
    assert_eq!(Field::max_series(&[None, None]), (None, 0));
    assert_eq!(Field::max_series(&[red]), (red, 1));
    assert_eq!(Field::max_series(&[blue]), (blue, 1));
    assert_eq!(Field::max_series(&[red, blue]), (None, 1));
    assert_eq!(Field::max_series(&[red, red, blue]), (red, 2));
    assert_eq!(Field::max_series(&[red, red, None, red, red, red]), (red, 3));
    assert_eq!(Field::max_series(&[blue, blue, None, red, red, red]), (red, 3));
    assert_eq!(Field::max_series(&[blue, blue, None, red, red, red, blue, blue, blue]), (None, 3));
}

#[test]
fn test_rows_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];
    let mut rows = Rows::new(cells);
    let row1 = rows.next().unwrap();
    let row2 = rows.next().unwrap();
    let row3 = rows.next().unwrap();
    assert!(rows.next().is_none());

    assert_eq!(row1.cells, [red,  None, blue, None] );
    assert_eq!(row2.cells, [None, red,  blue, red] );
    assert_eq!(row3.cells, [None, None, None, None] );
}

#[test]
fn test_columns_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];

    let mut columns = Columns::new(&cells);
    let column1 = columns.next().unwrap();
    let column2 = columns.next().unwrap();
    let column3 = columns.next().unwrap();
    let column4 = columns.next().unwrap();
    assert!(columns.next().is_none());

    assert_eq!(column1.cells, [red,  None, None] );
    assert_eq!(column2.cells, [None, red,  None] );
    assert_eq!(column3.cells, [blue, blue, None] );
    assert_eq!(column4.cells, [None, red,  None] );
}

#[test]
fn test_diagonal_iterator() {
    let red = Some(Player::Red);
    let blue = Some(Player::Blue);
    let cells = &[red,  None, blue, None,
    			  None, red,  blue, red,
    			  None, None, None, None,];

	let mut diagonals = Diagonals::new(&cells);
	let d1 = diagonals.next().unwrap();
	let d2 = diagonals.next().unwrap();
	let d3 = diagonals.next().unwrap();
	let d4 = diagonals.next().unwrap();

	let d5 = diagonals.next().unwrap();
	let d6 = diagonals.next().unwrap();
	let d7 = diagonals.next().unwrap();
	let d8 = diagonals.next().unwrap();

	assert!( diagonals.next().is_none() );

	fn check(d: Diagonal, cells: [Option<Player>; WIDTH + HEIGHT], length: usize) {
	    assert_eq!((d.cells, d.length), (cells, length) );
	}

	check(d1, [None, None, None, None, None, None, None], 2);
	check(d2, [blue, red, None, None, None, None, None], 3);
	check(d3, [None, blue, None, None, None, None, None], 3);
	check(d4, [red, None, None, None, None, None, None], 2);

	check(d5, [None, None, None, None, None, None, None], 2);
	check(d6, [red, red, None, None, None, None, None], 3);
	check(d7, [None, blue, None, None, None, None, None], 3);
	check(d8, [blue, red, None, None, None, None, None], 2);

}
<|endoftext|>


<commit_before>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(convert, collections, unboxed_closures)]

pub mod action;
pub mod parse;
pub mod schedule;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::{XBTVEd, EdBuffer};

#[no_mangle]
pub extern fn times2(num: isize) -> isize {
    num * 2
}
<commit_msg>working on calling code from C<commit_after>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(libc, convert, collections, unboxed_closures)]

extern crate libc;

use std::ffi::CString;
use std::mem;

pub mod action;
pub mod parse;
pub mod schedule;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::{XBTVEd, EdBuffer};

#[no_mangle]
pub extern fn create_app() -> *const XBTVEd {
    let app = Box::new(XBTVEd::new());
    unsafe {
        mem::transmute(app)
    }
}

#[no_mangle]
pub extern fn display_name(xbtved: *const XBTVEd) -> *const i8 {
    unsafe {
        match CString::new((*xbtved).current_buffer().get_name()) {
            Ok(x) => x.as_ptr(),
            Err(_) => CString::new("SCREWED UP!").unwrap().as_ptr()
        }
    }
}

#[no_mangle]
pub extern fn buffers_len(xbtved: *const XBTVEd) -> u32 {
    unsafe {
        let res = (*xbtved).buffers_len();
        println!("{}", res);
        res as u32
    }
}
<|endoftext|>


<commit_before>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;

#[cfg(test)]
extern crate rustc_version;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[test]
fn cli_test() {
    use std::process::Command;
    let cli_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .status()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd cli && npm install && npm run transpile")
                .status()
                .expect("failed to execute process")
    };
    assert!(cli_output.success());

    let cli_test_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .status()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/cli && npm install && npm run transpile && npm test")
                .status()
                .expect("failed to execute process")
    };
    assert!(cli_test_output.success());
}

#[test]
fn static_test() {
    use rustc_version::{version_meta, Channel};
    if version_meta().unwrap().channel != Channel::Nightly { return };
    use std::process::Command;
    let static_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .status()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/static && cargo test")
                .status()
                .expect("failed to execute process")
    };
    assert!(static_output.success());
}

#[test]
fn dynamic_test() {
    use std::process::Command;
    let dynamic_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .status()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd cli && npm install && cd ../test/dynamic && npm install && npm test")
                .status()
                .expect("failed to execute process")
    };
    assert!(dynamic_output.success());
}
<commit_msg>refactoring and added correct windows echo command<commit_after>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;

#[cfg(test)]
extern crate rustc_version;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[test]
fn cli_test() {
    use std::process::Command;
    if cfg!(target_os = "windows") {
        assert!(Command::new("cmd")
                        .args(&["/C", "echo Implement this later"])
                        .status()
                        .expect("failed to execute process")
                        .success());
        assert!(Command::new("cmd")
                        .args(&["/C", "echo Implement this later"])
                        .status()
                        .expect("failed to execute process")
                        .success());
    } else {
        assert!(Command::new("sh")
                        .arg("-c")
                        .arg("cd cli && npm install && npm run transpile")
                        .status()
                        .expect("failed to execute process")
                        .success());
        assert!(Command::new("sh")
                        .arg("-c")
                        .arg("cd test/cli && npm install && npm run transpile && npm test")
                        .status()
                        .expect("failed to execute process")
                        .success());
    };
}

#[test]
fn static_test() {
    use rustc_version::{version_meta, Channel};
    #[cfg(windows)]
    use std::env;

    if version_meta().unwrap().channel != Channel::Nightly { return };
    use std::process::Command;
    if cfg!(target_os = "windows") {
        assert!(Command::new("cmd")
                        .args(&["/C", "echo Implement this later"])
                        .status()
                        .expect("failed to execute process")
                        .success());
    } else {
        assert!(Command::new("sh")
                        .arg("-c")
                        .arg("cd test/static && cargo test")
                        .status()
                        .expect("failed to execute process")
                        .success());
    };
}

#[test]
fn dynamic_test() {
    use std::process::Command;
    #[cfg(windows)]
    use std::env;

    if cfg!(target_os = "windows") {
        assert!(Command::new("cmd")
                .args(&["/C", "echo Implement this later"])
                .status()
                .expect("failed to execute process")
                .success());
        assert!(Command::new("cmd")
                .args(&["/C", "echo Implement this later"])
                .status()
                .expect("failed to execute process")
                .success());
    } else {
        assert!(Command::new("sh")
                .arg("-c")
                .arg("cd cli && npm install && cd ../test/dynamic && npm install && npm test")
                .status()
                .expect("failed to execute process")
                .success());
    }
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;

use tokenizer::{Token, Tokenizer};
use types::point::Point;

mod tokenizer;
mod types;

pub struct Wkt {
    items: Vec<Point>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_point(&mut self, point: Point) {
        self.items.push(point);
    }

    fn from_reader(reader: &mut Reader) -> Result<Self, &'static str> {
        match reader.read_to_string() {
            Ok(string) => Wkt::from_str(string.as_slice()),
            Err(err) => Err(err.desc),
        }
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = tokenizer::tokenize(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokenizer) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut peek_tokens = tokens.peekable();
        match peek_tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                let uppercased = word.to_ascii_uppercase();
                let constructor = match uppercased.as_slice() {
                    "POINT" => Point::from_tokens,
                    _ => return Err("Invalid type encountered"),
                };
                match peek_tokens.next() {
                    Some(Token::ParenOpen) => (),
                    _ => return Err("Missing open parenthesis for type"),
                };
                match constructor(&mut peek_tokens) {
                    Ok(point) => wkt.add_point(point),
                    Err(s) => return Err(s),
                }
                match peek_tokens.next() {
                    Some(Token::ParenClose) => (),
                    _ => return Err("Missing closing parenthesis for type"),
                };
                Ok(wkt)
            },
            None => Ok(wkt),
            _ => Err("Invalid WKT format"),
        }
    }
}

#[test]
fn empty_string() {
    let wkt = Wkt::from_str("").ok().unwrap();
    assert_eq!(0, wkt.items.len());
}

#[test]
fn basic_point() {
    let mut wkt = Wkt::from_str("POINT (10 -20)").ok().unwrap();
    assert_eq!(1, wkt.items.len());
    let point = wkt.items.pop().unwrap();
    assert_eq!(10.0, point.coord.x);
    assert_eq!(-20.0, point.coord.y);
    assert_eq!(None, point.coord.z);
    assert_eq!(None, point.coord.m);
}

#[test]
fn invalid_points() {
    Wkt::from_str("POINT ()").err().unwrap();
    Wkt::from_str("POINT (10)").err().unwrap();
    Wkt::from_str("POINT 10").err().unwrap();
    Wkt::from_str("POINT (10 -20 40)").err().unwrap();
}
<commit_msg>Take advantage of variable shadowing<commit_after>use std::ascii::AsciiExt;

use tokenizer::{Token, Tokenizer};
use types::point::Point;

mod tokenizer;
mod types;

pub struct Wkt {
    items: Vec<Point>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_point(&mut self, point: Point) {
        self.items.push(point);
    }

    fn from_reader(reader: &mut Reader) -> Result<Self, &'static str> {
        match reader.read_to_string() {
            Ok(string) => Wkt::from_str(string.as_slice()),
            Err(err) => Err(err.desc),
        }
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = tokenizer::tokenize(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokenizer) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut tokens = tokens.peekable();
        match tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                let uppercased = word.to_ascii_uppercase();
                let constructor = match uppercased.as_slice() {
                    "POINT" => Point::from_tokens,
                    _ => return Err("Invalid type encountered"),
                };
                match tokens.next() {
                    Some(Token::ParenOpen) => (),
                    _ => return Err("Missing open parenthesis for type"),
                };
                match constructor(&mut tokens) {
                    Ok(point) => wkt.add_point(point),
                    Err(s) => return Err(s),
                }
                match tokens.next() {
                    Some(Token::ParenClose) => (),
                    _ => return Err("Missing closing parenthesis for type"),
                };
                Ok(wkt)
            },
            None => Ok(wkt),
            _ => Err("Invalid WKT format"),
        }
    }
}

#[test]
fn empty_string() {
    let wkt = Wkt::from_str("").ok().unwrap();
    assert_eq!(0, wkt.items.len());
}

#[test]
fn basic_point() {
    let mut wkt = Wkt::from_str("POINT (10 -20)").ok().unwrap();
    assert_eq!(1, wkt.items.len());
    let point = wkt.items.pop().unwrap();
    assert_eq!(10.0, point.coord.x);
    assert_eq!(-20.0, point.coord.y);
    assert_eq!(None, point.coord.z);
    assert_eq!(None, point.coord.m);
}

#[test]
fn invalid_points() {
    Wkt::from_str("POINT ()").err().unwrap();
    Wkt::from_str("POINT (10)").err().unwrap();
    Wkt::from_str("POINT 10").err().unwrap();
    Wkt::from_str("POINT (10 -20 40)").err().unwrap();
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::io::SeekFrom;
use std::mem;
use std::ptr;
use std::collections::HashMap;

extern crate libc;
extern crate encoding;

use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_16LE;

pub mod minidump_format;
use minidump_format as fmt;

#[allow(dead_code)]
pub struct Minidump {
    file : File,
    header : fmt::MDRawHeader,
    streams : HashMap<u32, fmt::MDRawDirectory>,
    swap : bool,
}

#[derive(Debug)]
pub enum Error {
    MissingHeader,
    HeaderMismatch,
    SwapNotImplemented,
    VersionMismatch,
    MissingDirectory,
    StreamReadFailure,
    StreamSizeMismatch,
    StreamNotFound,
    ModuleReadFailure,
    DataError,
    CodeViewReadFailure,
}

pub struct MinidumpThreadList;
pub struct MinidumpMemoryList;
pub struct MinidumpException;
pub struct MinidumpAssertion;
pub struct MinidumpSystemInfo;
pub struct MinidumpMiscInfo;
pub struct MinidumpBreakpadInfo;
pub struct MinidumpMemoryInfoList;

pub trait MinidumpStream {
    //TODO: associated_consts when that stabilizes.
    fn stream_type() -> u32;
    fn read(f : &File, expected_size : usize) -> Result<Self, Error>;
}

pub trait Module {
    fn base_address(&self) -> u64;
    fn size(&self) -> u64;
    fn code_file<'a>(&'a self) -> &'a String;
    //fn code_identifier(&self) -> Option<String>;
    //fn debug_file<'a>(&'a self) -> Option<&'a String>;
    //fn debug_identifier(&self) -> Option<String>;
    //fn version(&self) -> Option<String>;
}

pub enum CodeViewPDBRaw {
    PDB20(fmt::MDCVInfoPDB20),
    PDB70(fmt::MDCVInfoPDB70),
}

pub struct CodeViewPDB {
    pub raw : CodeViewPDBRaw,
    pub file : String,
}

pub enum CodeView {
    PDB(CodeViewPDB),
    Unknown { bytes: Vec<u8> },
}

pub struct MinidumpModule {
    pub raw : fmt::MDRawModule,
    name : String,
    pub codeview_info : Option<CodeView>,
    pub misc_info : Option<fmt::MDImageDebugMisc>,
}

pub struct MinidumpModuleList {
    pub modules : Vec<MinidumpModule>,
}

//======================================================
// Implementations

fn read_bytes(f : &File, count : usize) -> std::io::Result<Vec<u8>> {
    let mut buf = Vec::with_capacity(count);
    try!(f.take(count as u64).read_to_end(&mut buf));
    Ok(buf)
}

fn read<T : Copy>(f : &File) -> std::io::Result<T> {
    let size = mem::size_of::<T>();
    let mut buf = try!(read_bytes(f, size));
    let bytes = &mut buf[..];
    Ok(unsafe {
        let mut val : T = mem::uninitialized();
        ptr::copy(bytes.as_mut_ptr(), &mut val as *mut T as *mut u8, size);
        val
    })
}

fn read_string_utf16(mut f : &File, offset : u64) -> Result<String, Error> {
    try!(f.seek(SeekFrom::Start(offset)).or(Err(Error::DataError)));
    let size = try!(read::<u32>(f).or(Err(Error::DataError))) as usize;
    // TODO: swap
    if size % 2 != 0 {
        return Err(Error::DataError);
    }
    let buf = try!(read_bytes(f, size).or(Err(Error::DataError)));
    let bytes = &buf[..];
    UTF_16LE.decode(bytes, DecoderTrap::Strict).or(Err(Error::DataError))
}

fn read_codeview_pdb(mut f : &File, signature : u32, mut size : usize) -> Result<CodeView, Error> {
    let raw = match signature {
        fmt::MD_CVINFOPDB70_SIGNATURE => {
            size = size - mem::size_of::<fmt::MDCVInfoPDB70>() + 1;
            CodeViewPDBRaw::PDB70(try!(read::<fmt::MDCVInfoPDB70>(f).or(Err(Error::CodeViewReadFailure))))
        },
        fmt::MD_CVINFOPDB20_SIGNATURE => {
            size = size -mem::size_of::<fmt::MDCVInfoPDB20>() + 1;
            CodeViewPDBRaw::PDB20(try!(read::<fmt::MDCVInfoPDB20>(f).or(Err(Error::CodeViewReadFailure))))
        },
        _ => return Err(Error::CodeViewReadFailure),
    };
    // Both structs define a variable-length string with a placeholder
    // 1-byte array at the end, so seek back one byte and read the remaining
    // data as the string.
    try!(f.seek(SeekFrom::Current(-1)).or(Err(Error::CodeViewReadFailure)));
    let bytes = try!(read_bytes(f, size).or(Err(Error::CodeViewReadFailure)));
    // The string should have at least one trailing NUL.
    let file = String::from(String::from_utf8(bytes).unwrap().trim_right_matches('\0'));
    Ok(CodeView::PDB(CodeViewPDB { raw: raw, file: file}))
}

fn read_codeview(mut f : &File, location : fmt::MDLocationDescriptor) -> Result<CodeView, Error> {
    let size = location.data_size as usize;
    try!(f.seek(SeekFrom::Start(location.rva as u64)).or(Err(Error::CodeViewReadFailure)));
    // The CodeView data can contain a variable-length string at the end
    // and also can be one of a few different formats. Try to read the
    // signature first to figure out what format the data is.
    // TODO: swap
    let signature = try!(read::<u32>(f).or(Err(Error::CodeViewReadFailure)));
    // Seek back because the signature is part of the CV data.
    try!(f.seek(SeekFrom::Start(location.rva as u64)).or(Err(Error::CodeViewReadFailure)));
    match signature {
        fmt::MD_CVINFOPDB70_SIGNATURE | fmt::MD_CVINFOPDB20_SIGNATURE => {
            read_codeview_pdb(f, signature, size)
        },
        _ =>
            // Other formats aren't handled, but save the raw bytes.
            Ok(CodeView::Unknown { bytes: try!(read_bytes(f, size).or(Err(Error::CodeViewReadFailure))) })
    }
}

impl MinidumpModule {
    pub fn read(f : &File, raw : fmt::MDRawModule) -> Result<MinidumpModule, Error> {
        let name = try!(read_string_utf16(f, raw.module_name_rva as u64));
        let cv = if raw.cv_record.data_size > 0 {
            Some(try!(read_codeview(f, raw.cv_record).or(Err(Error::CodeViewReadFailure))))
        } else {
            None
        };
        Ok(MinidumpModule {
            raw: raw,
            name: name,
            codeview_info: cv,
            misc_info: None,
        })
    }
}

impl Module for MinidumpModule {
    fn base_address(&self) -> u64 { self.raw.base_of_image }
    fn size(&self) -> u64 { self.raw.size_of_image as u64 }
    fn code_file<'a>(&'a self) -> &'a String { &self.name }
/*
    fn code_identifier(&self) -> Option<String> {
        unimplemented!()
    }
    fn debug_file<'a>(&'a self) -> Option<&'a String> {
        match self.codeview_info {
            Some(CodeView::PDB(_)) => Some(self.codeview_info.file),
            _ => None,
        }
    }
    fn debug_identifier(&self) -> Option<String> {
        unimplemented!()
    }
    fn version(&self) -> Option<String> {
        unimplemented!()
    }
*/
}

impl MinidumpStream for MinidumpModuleList {
    fn stream_type() -> u32 { fmt::MD_MODULE_LIST_STREAM }
    fn read(f : &File, expected_size : usize) -> Result<MinidumpModuleList, Error> {
        if expected_size < mem::size_of::<u32>() {
            return Err(Error::StreamSizeMismatch);
        }
        // TODO: swap
        let count = try!(read::<u32>(&f).or(Err(Error::StreamReadFailure))) as usize;
        match expected_size - (mem::size_of::<u32>() + count * fmt::MD_MODULE_SIZE as usize) {
            0 => {},
            4 => {
                // 4 bytes of padding.
                try!(read::<u32>(&f).or(Err(Error::StreamReadFailure)));
            },
            _ => return Err(Error::StreamSizeMismatch)
        };
        // read count MDRawModule
        let mut raw_modules = Vec::with_capacity(count);
        for _ in 0..count {
            let raw = try!(read::<fmt::MDRawModule>(f).or(Err(Error::ModuleReadFailure)));
            // TODO: swap
            if raw.size_of_image == 0 || raw.size_of_image as u64 > (u64::max_value() - raw.base_of_image) {
                // Bad image size.
                //println!("image {}: bad image size: {}", i, raw.size_of_image);
                // TODO: just drop this module, keep the rest?
                return Err(Error::ModuleReadFailure);
            }
            raw_modules.push(raw);
        }
        // read auxiliary data for each module
        let mut modules = Vec::with_capacity(count);
        for raw in raw_modules.into_iter() {
            modules.push(try!(MinidumpModule::read(f, raw)));
        }
        // store modules by address (interval?)
        Ok(MinidumpModuleList { modules: modules })
    }
}

impl Minidump {
    pub fn read(f : File) -> Result<Minidump, Error> {
        let header = try!(read::<fmt::MDRawHeader>(&f).or(Err(Error::MissingHeader)));
        let swap = false;
        if header.signature != fmt::MD_HEADER_SIGNATURE {
            if header.signature.swap_bytes() != fmt::MD_HEADER_SIGNATURE {
                return Err(Error::HeaderMismatch);
            }
            return Err(Error::SwapNotImplemented);
            // TODO: implement swapping
            //swap = true;
        }
        if (header.version & 0x0000ffff) != fmt::MD_HEADER_VERSION {
            return Err(Error::VersionMismatch);
        }
        let mut streams = HashMap::with_capacity(header.stream_count as usize);
        if header.stream_count != 0 {
            for _ in 0..header.stream_count {
                let dir = try!(read::<fmt::MDRawDirectory>(&f).or(Err(Error::MissingDirectory)));
                if dir.stream_type != fmt::MD_UNUSED_STREAM {
                    streams.insert(dir.stream_type, dir);
                }
            }
        }
        Ok(Minidump {
            file: f,
            header: header,
            streams: streams,
            swap: swap
        })
    }

    pub fn get_stream<T: MinidumpStream>(&mut self) -> Result<T, Error> {
        match self.streams.get_mut(&T::stream_type()) {
            None => Err(Error::StreamNotFound),
            Some(dir) => {
                try!(self.file.seek(SeekFrom::Start(dir.location.rva as u64)).or(Err(Error::StreamReadFailure)));
                // TODO: cache result
                T::read(&self.file, dir.location.data_size as usize)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;
    use std::fs::File;
    use super::*;

    #[test]
    fn test_read_minidump() {
        let mut path = PathBuf::from(file!());
        path.pop();
        path.push("testdata/test.dmp");
        let f = File::open(&path).ok().expect(&format!("failed to open file: {:?}", path));
        let mut dump = Minidump::read(f).unwrap();
        assert_eq!(dump.streams.len(), 7);

        let module_list = dump.get_stream::<MinidumpModuleList>().unwrap();
        let modules = module_list.modules;
        assert_eq!(modules.len(), 13);
        assert_eq!(modules[0].code_file(), "c:\\test_app.exe");
        assert_eq!(modules[0].base_address(), 0x400000);
        assert_eq!(modules[0].size(), 0x2d000);
        assert_eq!(modules[12].code_file(), "C:\\WINDOWS\\system32\\psapi.dll");
        assert_eq!(modules[12].base_address(), 0x76bf0000);
        assert_eq!(modules[12].size(), 0xb000);
    }
}
<commit_msg>Elide some lifetimes, implement Module::debug_file<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::io::SeekFrom;
use std::mem;
use std::ptr;
use std::collections::HashMap;

extern crate libc;
extern crate encoding;

use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_16LE;

pub mod minidump_format;
use minidump_format as fmt;

#[allow(dead_code)]
pub struct Minidump {
    file : File,
    header : fmt::MDRawHeader,
    streams : HashMap<u32, fmt::MDRawDirectory>,
    swap : bool,
}

#[derive(Debug)]
pub enum Error {
    MissingHeader,
    HeaderMismatch,
    SwapNotImplemented,
    VersionMismatch,
    MissingDirectory,
    StreamReadFailure,
    StreamSizeMismatch,
    StreamNotFound,
    ModuleReadFailure,
    DataError,
    CodeViewReadFailure,
}

pub struct MinidumpThreadList;
pub struct MinidumpMemoryList;
pub struct MinidumpException;
pub struct MinidumpAssertion;
pub struct MinidumpSystemInfo;
pub struct MinidumpMiscInfo;
pub struct MinidumpBreakpadInfo;
pub struct MinidumpMemoryInfoList;

pub trait MinidumpStream {
    //TODO: associated_consts when that stabilizes.
    fn stream_type() -> u32;
    fn read(f : &File, expected_size : usize) -> Result<Self, Error>;
}

pub trait Module {
    fn base_address(&self) -> u64;
    fn size(&self) -> u64;
    fn code_file(&self) -> &String;
    //fn code_identifier(&self) -> Option<String>;
    fn debug_file(&self) -> Option<&String>;
    //fn debug_identifier(&self) -> Option<String>;
    //fn version(&self) -> Option<String>;
}

pub enum CodeViewPDBRaw {
    PDB20(fmt::MDCVInfoPDB20),
    PDB70(fmt::MDCVInfoPDB70),
}

pub struct CodeViewPDB {
    pub raw : CodeViewPDBRaw,
    pub file : String,
}

pub enum CodeView {
    PDB(CodeViewPDB),
    Unknown { bytes: Vec<u8> },
}

pub struct MinidumpModule {
    pub raw : fmt::MDRawModule,
    name : String,
    pub codeview_info : Option<CodeView>,
    pub misc_info : Option<fmt::MDImageDebugMisc>,
}

pub struct MinidumpModuleList {
    pub modules : Vec<MinidumpModule>,
}

//======================================================
// Implementations

fn read_bytes(f : &File, count : usize) -> std::io::Result<Vec<u8>> {
    let mut buf = Vec::with_capacity(count);
    try!(f.take(count as u64).read_to_end(&mut buf));
    Ok(buf)
}

fn read<T : Copy>(f : &File) -> std::io::Result<T> {
    let size = mem::size_of::<T>();
    let mut buf = try!(read_bytes(f, size));
    let bytes = &mut buf[..];
    Ok(unsafe {
        let mut val : T = mem::uninitialized();
        ptr::copy(bytes.as_mut_ptr(), &mut val as *mut T as *mut u8, size);
        val
    })
}

fn read_string_utf16(mut f : &File, offset : u64) -> Result<String, Error> {
    try!(f.seek(SeekFrom::Start(offset)).or(Err(Error::DataError)));
    let size = try!(read::<u32>(f).or(Err(Error::DataError))) as usize;
    // TODO: swap
    if size % 2 != 0 {
        return Err(Error::DataError);
    }
    let buf = try!(read_bytes(f, size).or(Err(Error::DataError)));
    let bytes = &buf[..];
    UTF_16LE.decode(bytes, DecoderTrap::Strict).or(Err(Error::DataError))
}

fn read_codeview_pdb(mut f : &File, signature : u32, mut size : usize) -> Result<CodeView, Error> {
    let raw = match signature {
        fmt::MD_CVINFOPDB70_SIGNATURE => {
            size = size - mem::size_of::<fmt::MDCVInfoPDB70>() + 1;
            CodeViewPDBRaw::PDB70(try!(read::<fmt::MDCVInfoPDB70>(f).or(Err(Error::CodeViewReadFailure))))
        },
        fmt::MD_CVINFOPDB20_SIGNATURE => {
            size = size -mem::size_of::<fmt::MDCVInfoPDB20>() + 1;
            CodeViewPDBRaw::PDB20(try!(read::<fmt::MDCVInfoPDB20>(f).or(Err(Error::CodeViewReadFailure))))
        },
        _ => return Err(Error::CodeViewReadFailure),
    };
    // Both structs define a variable-length string with a placeholder
    // 1-byte array at the end, so seek back one byte and read the remaining
    // data as the string.
    try!(f.seek(SeekFrom::Current(-1)).or(Err(Error::CodeViewReadFailure)));
    let bytes = try!(read_bytes(f, size).or(Err(Error::CodeViewReadFailure)));
    // The string should have at least one trailing NUL.
    let file = String::from(String::from_utf8(bytes).unwrap().trim_right_matches('\0'));
    Ok(CodeView::PDB(CodeViewPDB { raw: raw, file: file}))
}

fn read_codeview(mut f : &File, location : fmt::MDLocationDescriptor) -> Result<CodeView, Error> {
    let size = location.data_size as usize;
    try!(f.seek(SeekFrom::Start(location.rva as u64)).or(Err(Error::CodeViewReadFailure)));
    // The CodeView data can contain a variable-length string at the end
    // and also can be one of a few different formats. Try to read the
    // signature first to figure out what format the data is.
    // TODO: swap
    let signature = try!(read::<u32>(f).or(Err(Error::CodeViewReadFailure)));
    // Seek back because the signature is part of the CV data.
    try!(f.seek(SeekFrom::Start(location.rva as u64)).or(Err(Error::CodeViewReadFailure)));
    match signature {
        fmt::MD_CVINFOPDB70_SIGNATURE | fmt::MD_CVINFOPDB20_SIGNATURE => {
            read_codeview_pdb(f, signature, size)
        },
        _ =>
            // Other formats aren't handled, but save the raw bytes.
            Ok(CodeView::Unknown { bytes: try!(read_bytes(f, size).or(Err(Error::CodeViewReadFailure))) })
    }
}

impl MinidumpModule {
    pub fn read(f : &File, raw : fmt::MDRawModule) -> Result<MinidumpModule, Error> {
        let name = try!(read_string_utf16(f, raw.module_name_rva as u64));
        let cv = if raw.cv_record.data_size > 0 {
            Some(try!(read_codeview(f, raw.cv_record).or(Err(Error::CodeViewReadFailure))))
        } else {
            None
        };
        Ok(MinidumpModule {
            raw: raw,
            name: name,
            codeview_info: cv,
            misc_info: None,
        })
    }
}

impl Module for MinidumpModule {
    fn base_address(&self) -> u64 { self.raw.base_of_image }
    fn size(&self) -> u64 { self.raw.size_of_image as u64 }
    fn code_file(&self) -> &String { &self.name }
/*
    fn code_identifier(&self) -> Option<String> {
        unimplemented!()
    }
*/
    fn debug_file(&self) -> Option<&String> {
        match self.codeview_info {
            Some(CodeView::PDB(ref cv)) => Some(&cv.file),
            _ => None,
        }
    }
/*
    fn debug_identifier(&self) -> Option<String> {
        unimplemented!()
    }
    fn version(&self) -> Option<String> {
        unimplemented!()
    }
*/
}

impl MinidumpStream for MinidumpModuleList {
    fn stream_type() -> u32 { fmt::MD_MODULE_LIST_STREAM }
    fn read(f : &File, expected_size : usize) -> Result<MinidumpModuleList, Error> {
        if expected_size < mem::size_of::<u32>() {
            return Err(Error::StreamSizeMismatch);
        }
        // TODO: swap
        let count = try!(read::<u32>(&f).or(Err(Error::StreamReadFailure))) as usize;
        match expected_size - (mem::size_of::<u32>() + count * fmt::MD_MODULE_SIZE as usize) {
            0 => {},
            4 => {
                // 4 bytes of padding.
                try!(read::<u32>(&f).or(Err(Error::StreamReadFailure)));
            },
            _ => return Err(Error::StreamSizeMismatch)
        };
        // read count MDRawModule
        let mut raw_modules = Vec::with_capacity(count);
        for _ in 0..count {
            let raw = try!(read::<fmt::MDRawModule>(f).or(Err(Error::ModuleReadFailure)));
            // TODO: swap
            if raw.size_of_image == 0 || raw.size_of_image as u64 > (u64::max_value() - raw.base_of_image) {
                // Bad image size.
                //println!("image {}: bad image size: {}", i, raw.size_of_image);
                // TODO: just drop this module, keep the rest?
                return Err(Error::ModuleReadFailure);
            }
            raw_modules.push(raw);
        }
        // read auxiliary data for each module
        let mut modules = Vec::with_capacity(count);
        for raw in raw_modules.into_iter() {
            modules.push(try!(MinidumpModule::read(f, raw)));
        }
        // store modules by address (interval?)
        Ok(MinidumpModuleList { modules: modules })
    }
}

impl Minidump {
    pub fn read(f : File) -> Result<Minidump, Error> {
        let header = try!(read::<fmt::MDRawHeader>(&f).or(Err(Error::MissingHeader)));
        let swap = false;
        if header.signature != fmt::MD_HEADER_SIGNATURE {
            if header.signature.swap_bytes() != fmt::MD_HEADER_SIGNATURE {
                return Err(Error::HeaderMismatch);
            }
            return Err(Error::SwapNotImplemented);
            // TODO: implement swapping
            //swap = true;
        }
        if (header.version & 0x0000ffff) != fmt::MD_HEADER_VERSION {
            return Err(Error::VersionMismatch);
        }
        let mut streams = HashMap::with_capacity(header.stream_count as usize);
        if header.stream_count != 0 {
            for _ in 0..header.stream_count {
                let dir = try!(read::<fmt::MDRawDirectory>(&f).or(Err(Error::MissingDirectory)));
                if dir.stream_type != fmt::MD_UNUSED_STREAM {
                    streams.insert(dir.stream_type, dir);
                }
            }
        }
        Ok(Minidump {
            file: f,
            header: header,
            streams: streams,
            swap: swap
        })
    }

    pub fn get_stream<T: MinidumpStream>(&mut self) -> Result<T, Error> {
        match self.streams.get_mut(&T::stream_type()) {
            None => Err(Error::StreamNotFound),
            Some(dir) => {
                try!(self.file.seek(SeekFrom::Start(dir.location.rva as u64)).or(Err(Error::StreamReadFailure)));
                // TODO: cache result
                T::read(&self.file, dir.location.data_size as usize)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;
    use std::fs::File;
    use super::*;

    #[test]
    fn test_read_minidump() {
        let mut path = PathBuf::from(file!());
        path.pop();
        path.push("testdata/test.dmp");
        let f = File::open(&path).ok().expect(&format!("failed to open file: {:?}", path));
        let mut dump = Minidump::read(f).unwrap();
        assert_eq!(dump.streams.len(), 7);

        let module_list = dump.get_stream::<MinidumpModuleList>().unwrap();
        let modules = module_list.modules;
        assert_eq!(modules.len(), 13);
        assert_eq!(modules[0].code_file(), "c:\\test_app.exe");
        assert_eq!(modules[0].base_address(), 0x400000);
        assert_eq!(modules[0].size(), 0x2d000);
        assert_eq!(modules[0].debug_file().unwrap(), "c:\\test_app.pdb");
        assert_eq!(modules[12].code_file(), "C:\\WINDOWS\\system32\\psapi.dll");
        assert_eq!(modules[12].base_address(), 0x76bf0000);
        assert_eq!(modules[12].size(), 0xb000);
        assert_eq!(modules[12].debug_file().unwrap(), "psapi.pdb");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Composable first-order predicate functions.
//!
//! This library implements an interface to "predicates" - boolean-valued
//! functions of one argument. This allows combinatorial logic to be created and
//! assembled at runtime and then used one or more times for evaluating values.
//! This sort of object is really useful when creating filters and checks that
//! can be changed at runtime with user interaction - it allows a clean
//! separation of concerns where the configuration code can be used to build up
//! a predicate, and then that predicate can be given to the code that does the
//! actual filtering without the filtering code knowing anything about user
//! configuration. See the examples for how this can work.
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! predicates = "1.0.6"
//! ```
//!
//! A [prelude] is available to bring in all extension traits as well as providing
//! `prelude::predicate` which focuses on the 90% case of the API.
//! ```rust
//! use predicates::prelude::*;
//! ```
//!
//! ## Examples
//!
//! The simplest predicates are [`predicate::always`] and [`predicate::never`], which always
//! returns `true` and always returns `false`, respectively. The values are simply ignored when
//! evaluating against these predicates:
//! ```rust
//! use predicates::prelude::*;
//!
//! let always_true = predicate::always();
//! assert_eq!(true, always_true.eval(&5));
//! let always_false = predicate::never();
//! assert_eq!(false, always_false.eval(&5));
//! ```
//!
//! Pre-made predicates are available for types that implement the `PartialOrd` and
//! `PartialEq` traits. The following example uses `lt`, but `eq`, `ne`, `le`, `gt`,
//! `ge` are also available.
//! ```rust
//! use predicates::prelude::*;
//!
//! let less_than_ten = predicate::lt(10);
//! assert_eq!(true, less_than_ten.eval(&9));
//! assert_eq!(false, less_than_ten.eval(&11));
//! ```
//!
//! Any function over a reference to the desired `Item` that returns `bool`
//! can easily be made into a `Predicate` using the [`predicate::function`]
//! function.
//! ```rust
//! use predicates::prelude::*;
//!
//! let bound = 5;
//! let predicate_fn = predicate::function(|&x| x >= bound);
//! let between_5_and_10 = predicate_fn.and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&3));
//! ```
//!
//! The `Predicate` type is actually a trait, and that trait implements a
//! number of useful combinator functions. For example, evaluating for a value
//! between two other values can be accomplished as follows:
//! ```rust
//! use predicates::prelude::*;
//!
//! let between_5_and_10 = predicate::ge(5).and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&11));
//! assert_eq!(false, between_5_and_10.eval(&4));
//! ```
//!
//! The `Predicate` trait is pretty simple, the core of it is an
//! implementation of a `eval` function that takes a single argument and
//! returns a `bool`. Implementing a custom `Predicate` still allows all the
//! usual combinators of the `Predicate` trait to work!
//! ```rust
//! use std::fmt;
//!
//! use predicates::prelude::*;
//!
//! struct IsTheAnswer;
//! impl Predicate<i32> for IsTheAnswer {
//!     fn eval(&self, variable: &i32) -> bool {
//!         *variable == 42
//!     }
//! }
//! impl predicates::reflection::PredicateReflection for IsTheAnswer {}
//! impl fmt::Display for IsTheAnswer {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "var.is_the_answer()")
//!     }
//! }
//!
//! assert_eq!(true, IsTheAnswer.eval(&42));
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
//! assert_eq!(true, almost_the_answer.eval(&41));
//! ```
//!
//! ## Choosing a Predicate
//!
//! General predicates
//! - [`predicate::always`]
//! - [`predicate::never`]
//! - [`predicate::function`]
//! - [`predicate::in_iter`]: Specified value must be in the `Iterator`.
//!   - [`predicate::in_iter(...).sort`]: Optimization for repeatedly called predicates.
//!   - [`predicate::in_hash`]: Optimization for repeatedly called predicates.
//! - [`predicate::eq`]
//!   - [`predicate::float::is_close`]: Use this instead of `eq` for floating point values.
//! - [`predicate::ne`]
//! - [`predicate::ge`]
//! - [`predicate::gt`]
//! - [`predicate::le`]
//! - [`predicate::lt`]
//! - [`predicate::name`]: Improve readability of failure reporting by providing a meaningful name.
//!
//! Combinators
//! - [`pred_a.and(pred_b)`]: Both predicates must succeed.
//! - [`pred_a.or(pred_b)`]: One or both predicates must succeed.
//! - [`pred_a.not())`]: The predicate must fail.
//!
//! `String` predicates
//! - [`predicate::str::is_empty`]: Specified string must be empty
//! - [`str_pred = predicate::path::eq_file(...).utf8`]: Specified string must equal the contents
//!   of the given file.
//! - [`predicate::str::similar`]: Same as `eq` except report a diff.  See [`DifferencePredicate`]
//!   for more features.
//! - [`predicate::str::diff`]: Same as `ne`.  See [`DifferencePredicate`] for more features.
//! - [`predicate::str::starts_with`]: Specified string must start with the given needle.
//! - [`predicate::str::ends_with`]: Specified string must end with the given needle.
//! - [`predicate::str::contains`]: Specified string must contain the given needle.
//!   - [`predicate::str::contains(...).count`]: Required number of times the needle must show up.
//! - [`predicate::str::is_match`]: Specified string must match the given regex.
//!   - [`predicate::str::is_match(...).count`]: Required number of times the match must show up.
//! - [`str_pred.trim`]: Trim whitespace before passing it to `str_pred`.
//! - [`str_pred.normalize`]: Normalize the line endings before passing it to `str_pred`.
//! - [`bytes_pred = str_pred.from_utf8()`]: Reuse string predicates in other contexts, like the
//!   file system.
//!
//! File system predicates
//! - [`predicate::path::exists`]: Specified path must exist on disk.
//! - [`predicate::path::missing`]: Specified path must not exist on disk.
//! - [`predicate::path::is_dir`]: Specified path is a directory.
//! - [`predicate::path::is_file`]: Specified path is a file.
//! - [`predicate::path::is_symlink`]: Specified path is a symlink.
//! - [`path_pred = predicate::path::eq_file`]: Specified path's contents must equal the contents of the given
//!   file.
//! - [`path_pred = bytes_pred.from_file_path`]: Specified path's contents must equal the `bytes_pred`.
//!
//! [prelude]: prelude/index.html
//! [`DifferencePredicate`]: https://docs.rs/predicates/0.9.1/predicates/str/struct.DifferencePredicate.html
//! [`bytes_pred = str_pred.from_utf8()`]: prelude/trait.PredicateStrExt.html#method.from_utf8
//! [`path_pred = bytes_pred.from_file_path`]: prelude/trait.PredicateFileContentExt.html#method.from_file_path
//! [`path_pred = predicate::path::eq_file`]: prelude/predicate/path/fn.eq_file.html
//! [`pred_a.and(pred_b)`]: boolean/trait.PredicateBooleanExt.html#method.and
//! [`pred_a.not())`]: boolean/trait.PredicateBooleanExt.html#method.not
//! [`pred_a.or(pred_b)`]: boolean/trait.PredicateBooleanExt.html#method.or
//! [`predicate::always`]: constant/fn.always.html
//! [`predicate::eq`]: ord/fn.eq.html
//! [`predicate::float::is_close`]: prelude/predicate/float/fn.is_close.html
//! [`predicate::function`]: function/fn.function.html
//! [`predicate::ge`]: ord/fn.ge.html
//! [`predicate::gt`]: ord/fn.gt.html
//! [`predicate::in_hash`]: iter/fn.in_hash.html
//! [`predicate::in_iter(...).sort`]: iter/struct.InPredicate.html#method.sort
//! [`predicate::in_iter`]: iter/fn.in_iter.html
//! [`predicate::le`]: ord/fn.le.html
//! [`predicate::lt`]: ord/fn.lt.html
//! [`predicate::name`]: name/trait.PredicateNameExt.html#method.name
//! [`predicate::ne`]: ord/fn.ne.html
//! [`predicate::never`]: constant/fn.never.html
//! [`predicate::path::exists`]: prelude/predicate/path/fn.exists.html
//! [`predicate::path::is_dir`]: prelude/predicate/path/fn.is_dir.html
//! [`predicate::path::is_file`]: prelude/predicate/path/fn.is_file.html
//! [`predicate::path::is_symlink`]: prelude/predicate/path/fn.is_symlink.html
//! [`predicate::path::missing`]: prelude/predicate/path/fn.missing.html
//! [`predicate::str::contains(...).count`]: str/struct.ContainsPredicate.html#method.count
//! [`predicate::str::contains`]: prelude/predicate/str/fn.contains.html
//! [`predicate::str::diff`]: prelude/predicate/str/fn.diff.html
//! [`predicate::str::ends_with`]: prelude/predicate/str/fn.ends_with.html
//! [`predicate::str::is_empty`]: prelude/predicate/str/fn.is_empty.html
//! [`predicate::str::is_match(...).count`]: str/struct.RegexPredicate.html#method.count
//! [`predicate::str::is_match`]: prelude/predicate/str/fn.is_match.html
//! [`predicate::str::similar`]: prelude/predicate/str/fn.similar.html
//! [`predicate::str::starts_with`]: prelude/predicate/str/fn.starts_with.html
//! [`str_pred = predicate::path::eq_file(...).utf8`]: path/struct.BinaryFilePredicate.html#method.utf8
//! [`str_pred.normalize`]: prelude/trait.PredicateStrExt.html#method.normalize
//! [`str_pred.trim`]: prelude/trait.PredicateStrExt.html#method.trim

#![warn(missing_docs, missing_debug_implementations)]

pub mod prelude;

pub use predicates_core::*;
mod boxed;
pub use crate::boxed::*;

// core predicates
pub mod constant;
pub mod function;
pub mod iter;
pub mod name;
pub mod ord;

// combinators
pub mod boolean;

// specialized primitive `Predicate` types
pub mod float;
pub mod path;
pub mod str;

mod utils;
<commit_msg>docs: Run intraconv<commit_after>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Composable first-order predicate functions.
//!
//! This library implements an interface to "predicates" - boolean-valued
//! functions of one argument. This allows combinatorial logic to be created and
//! assembled at runtime and then used one or more times for evaluating values.
//! This sort of object is really useful when creating filters and checks that
//! can be changed at runtime with user interaction - it allows a clean
//! separation of concerns where the configuration code can be used to build up
//! a predicate, and then that predicate can be given to the code that does the
//! actual filtering without the filtering code knowing anything about user
//! configuration. See the examples for how this can work.
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! predicates = "1.0.6"
//! ```
//!
//! A [prelude] is available to bring in all extension traits as well as providing
//! `prelude::predicate` which focuses on the 90% case of the API.
//! ```rust
//! use predicates::prelude::*;
//! ```
//!
//! ## Examples
//!
//! The simplest predicates are [`predicate::always`] and [`predicate::never`], which always
//! returns `true` and always returns `false`, respectively. The values are simply ignored when
//! evaluating against these predicates:
//! ```rust
//! use predicates::prelude::*;
//!
//! let always_true = predicate::always();
//! assert_eq!(true, always_true.eval(&5));
//! let always_false = predicate::never();
//! assert_eq!(false, always_false.eval(&5));
//! ```
//!
//! Pre-made predicates are available for types that implement the `PartialOrd` and
//! `PartialEq` traits. The following example uses `lt`, but `eq`, `ne`, `le`, `gt`,
//! `ge` are also available.
//! ```rust
//! use predicates::prelude::*;
//!
//! let less_than_ten = predicate::lt(10);
//! assert_eq!(true, less_than_ten.eval(&9));
//! assert_eq!(false, less_than_ten.eval(&11));
//! ```
//!
//! Any function over a reference to the desired `Item` that returns `bool`
//! can easily be made into a `Predicate` using the [`predicate::function`]
//! function.
//! ```rust
//! use predicates::prelude::*;
//!
//! let bound = 5;
//! let predicate_fn = predicate::function(|&x| x >= bound);
//! let between_5_and_10 = predicate_fn.and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&3));
//! ```
//!
//! The `Predicate` type is actually a trait, and that trait implements a
//! number of useful combinator functions. For example, evaluating for a value
//! between two other values can be accomplished as follows:
//! ```rust
//! use predicates::prelude::*;
//!
//! let between_5_and_10 = predicate::ge(5).and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&11));
//! assert_eq!(false, between_5_and_10.eval(&4));
//! ```
//!
//! The `Predicate` trait is pretty simple, the core of it is an
//! implementation of a `eval` function that takes a single argument and
//! returns a `bool`. Implementing a custom `Predicate` still allows all the
//! usual combinators of the `Predicate` trait to work!
//! ```rust
//! use std::fmt;
//!
//! use predicates::prelude::*;
//!
//! struct IsTheAnswer;
//! impl Predicate<i32> for IsTheAnswer {
//!     fn eval(&self, variable: &i32) -> bool {
//!         *variable == 42
//!     }
//! }
//! impl predicates::reflection::PredicateReflection for IsTheAnswer {}
//! impl fmt::Display for IsTheAnswer {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "var.is_the_answer()")
//!     }
//! }
//!
//! assert_eq!(true, IsTheAnswer.eval(&42));
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
//! assert_eq!(true, almost_the_answer.eval(&41));
//! ```
//!
//! ## Choosing a Predicate
//!
//! General predicates
//! - [`predicate::always`]
//! - [`predicate::never`]
//! - [`predicate::function`]
//! - [`predicate::in_iter`]: Specified value must be in the `Iterator`.
//!   - [`predicate::in_iter(...).sort`]: Optimization for repeatedly called predicates.
//!   - [`predicate::in_hash`]: Optimization for repeatedly called predicates.
//! - [`predicate::eq`]
//!   - [`predicate::float::is_close`]: Use this instead of `eq` for floating point values.
//! - [`predicate::ne`]
//! - [`predicate::ge`]
//! - [`predicate::gt`]
//! - [`predicate::le`]
//! - [`predicate::lt`]
//! - [`predicate::name`]: Improve readability of failure reporting by providing a meaningful name.
//!
//! Combinators
//! - [`pred_a.and(pred_b)`]: Both predicates must succeed.
//! - [`pred_a.or(pred_b)`]: One or both predicates must succeed.
//! - [`pred_a.not())`]: The predicate must fail.
//!
//! `String` predicates
//! - [`predicate::str::is_empty`]: Specified string must be empty
//! - [`str_pred = predicate::path::eq_file(...).utf8`]: Specified string must equal the contents
//!   of the given file.
//! - [`predicate::str::similar`]: Same as `eq` except report a diff.  See [`DifferencePredicate`]
//!   for more features.
//! - [`predicate::str::diff`]: Same as `ne`.  See [`DifferencePredicate`] for more features.
//! - [`predicate::str::starts_with`]: Specified string must start with the given needle.
//! - [`predicate::str::ends_with`]: Specified string must end with the given needle.
//! - [`predicate::str::contains`]: Specified string must contain the given needle.
//!   - [`predicate::str::contains(...).count`]: Required number of times the needle must show up.
//! - [`predicate::str::is_match`]: Specified string must match the given regex.
//!   - [`predicate::str::is_match(...).count`]: Required number of times the match must show up.
//! - [`str_pred.trim`]: Trim whitespace before passing it to `str_pred`.
//! - [`str_pred.normalize`]: Normalize the line endings before passing it to `str_pred`.
//! - [`bytes_pred = str_pred.from_utf8()`]: Reuse string predicates in other contexts, like the
//!   file system.
//!
//! File system predicates
//! - [`predicate::path::exists`]: Specified path must exist on disk.
//! - [`predicate::path::missing`]: Specified path must not exist on disk.
//! - [`predicate::path::is_dir`]: Specified path is a directory.
//! - [`predicate::path::is_file`]: Specified path is a file.
//! - [`predicate::path::is_symlink`]: Specified path is a symlink.
//! - [`path_pred = predicate::path::eq_file`]: Specified path's contents must equal the contents of the given
//!   file.
//! - [`path_pred = bytes_pred.from_file_path`]: Specified path's contents must equal the `bytes_pred`.
//!
//! [`DifferencePredicate`]: crate::str::DifferencePredicate
//! [`bytes_pred = str_pred.from_utf8()`]: prelude::PredicateStrExt::from_utf8()
//! [`path_pred = bytes_pred.from_file_path`]: prelude::PredicateFileContentExt::from_file_path()
//! [`path_pred = predicate::path::eq_file`]: prelude::predicate::path::eq_file()
//! [`pred_a.and(pred_b)`]: boolean::PredicateBooleanExt::and()
//! [`pred_a.not())`]: boolean::PredicateBooleanExt::not()
//! [`pred_a.or(pred_b)`]: boolean::PredicateBooleanExt::or()
//! [`predicate::always`]: constant::always()
//! [`predicate::eq`]: ord::eq()
//! [`predicate::float::is_close`]: prelude::predicate::float::is_close()
//! [`predicate::function`]: function::function()
//! [`predicate::ge`]: ord::ge()
//! [`predicate::gt`]: ord::gt()
//! [`predicate::in_hash`]: iter::in_hash()
//! [`predicate::in_iter(...).sort`]: iter::InPredicate::sort()
//! [`predicate::in_iter`]: iter::in_iter()
//! [`predicate::le`]: ord::le()
//! [`predicate::lt`]: ord::lt()
//! [`predicate::name`]: name::PredicateNameExt::name()
//! [`predicate::ne`]: ord::ne()
//! [`predicate::never`]: constant::never()
//! [`predicate::path::exists`]: prelude::predicate::path::exists()
//! [`predicate::path::is_dir`]: prelude::predicate::path::is_dir()
//! [`predicate::path::is_file`]: prelude::predicate::path::is_file()
//! [`predicate::path::is_symlink`]: prelude::predicate::path::is_symlink()
//! [`predicate::path::missing`]: prelude::predicate::path::missing()
//! [`predicate::str::contains(...).count`]: str::ContainsPredicate::count()
//! [`predicate::str::contains`]: prelude::predicate::str::contains()
//! [`predicate::str::diff`]: prelude::predicate::str::diff()
//! [`predicate::str::ends_with`]: prelude::predicate::str::ends_with()
//! [`predicate::str::is_empty`]: prelude::predicate::str::is_empty()
//! [`predicate::str::is_match(...).count`]: str::RegexPredicate::count()
//! [`predicate::str::is_match`]: prelude::predicate::str::is_match()
//! [`predicate::str::similar`]: prelude::predicate::str::similar()
//! [`predicate::str::starts_with`]: prelude::predicate::str::starts_with()
//! [`str_pred = predicate::path::eq_file(...).utf8`]: path::BinaryFilePredicate::utf8()
//! [`str_pred.normalize`]: prelude::PredicateStrExt::normalize()
//! [`str_pred.trim`]: prelude::PredicateStrExt::trim()

#![warn(missing_docs, missing_debug_implementations)]

pub mod prelude;

pub use predicates_core::*;
mod boxed;
pub use crate::boxed::*;

// core predicates
pub mod constant;
pub mod function;
pub mod iter;
pub mod name;
pub mod ord;

// combinators
pub mod boolean;

// specialized primitive `Predicate` types
pub mod float;
pub mod path;
pub mod str;

mod utils;
<|endoftext|>