<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(())
    }
}

#[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,
        }
    }
}

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

impl Field {
    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 current_state function for 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 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,
        }
    }
}

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

impl Field {
    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>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_warning_once(name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

pub unsafe fn any(data: *const raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn warning_once(name: &str) {
    unsafe { klee_warning_once(CString::new(name).unwrap().as_ptr()); }
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn i32(name: &str) -> i32 {
    let res : i32 = 0;
    symbol(&res, name);
    return res;
}

pub fn bool(name: &str) ->bool {
    let res : bool = false;
    symbol(&res, name);
    return res;
}

pub fn symbol<T>(data: &T, name: &str) {
    unsafe{ any(transmute(data as *const T), size_of::<T>(), name); }
}

pub fn assert_warn(condition: bool, msg: &str) {
    if condition {
        warning_once(msg);
    }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

#[link(name = "klee-libc")]
extern {
    fn klee_warning_once(name: *const raw::c_char);
}

pub unsafe fn any(data: *const raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn warning_once(name: &str) {
    unsafe { klee_warning_once(CString::new(name).unwrap().as_ptr()); }
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn i32(name: &str) -> i32 {
    let res : i32 = 0;
    symbol(&res, name);
    return res;
}

pub fn bool(name: &str) ->bool {
    let res : bool = false;
    symbol(&res, name);
    return res;
}

pub fn symbol<T>(data: &T, name: &str) {
    unsafe{ any(transmute(data as *const T), size_of::<T>(), name); }
}

pub fn assert_warn(condition: bool, msg: &str) {
    if condition {
        warning_once(msg);
    }
}
<|endoftext|>


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

use std::sync::atomic::AtomicPtr;
use std::sync::Arc;
use std::mem;
use std::ptr;
use std::ops::Deref;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::sync::atomic::Ordering;

/// An Atom wraps an AtomicPtr, it allows for safe mutation of an atomic
/// into common Rust Types.
pub struct Atom
 where P: IntoRawPtr + FromRawPtr {
    inner: AtomicPtr<()>,
    data: PhantomData

}

impl
 Debug for Atom
 where P: IntoRawPtr + FromRawPtr {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "atom({:?})", self.inner.load(Ordering::Relaxed))
    }
}

impl
 Atom
 where P: IntoRawPtr + FromRawPtr {
    /// Create a empty Atom
    pub fn empty() -> Atom
 {
        Atom {
            inner: AtomicPtr::new(ptr::null_mut()),
            data: PhantomData
        }
    }

    /// Create a new Atomic from Pointer P
    pub fn new(value: P) -> Atom
 {
        Atom {
            inner: AtomicPtr::new(unsafe { value.into_raw() }),
            data: PhantomData
        }
    }

    /// Swap a new value into the Atom, This will try multiple
    /// times until it succeeds. The old value will be returned.
    pub fn swap(&self, v: P) -> Option
 {
        let new = unsafe { v.into_raw() };
        let old = self.inner.swap(new, Ordering::AcqRel);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(old) })
        } else {
            None
        }
    }

    /// Take the value of the Atom replacing it with null pointer
    /// Returning the contents. If the contents was a `null` pointer the
    /// result will be `None`.
    pub fn take(&self) -> Option
 {
        let old = self.inner.swap(ptr::null_mut(), Ordering::Acquire);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(old) })
        } else {
            None
        }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `None` if the value was written,
    /// otherwise a `Some(v)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P) -> Option
 {
        let new = unsafe { v.into_raw() };
        let old = self.inner.compare_and_swap(ptr::null_mut(), new, Ordering::Release);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(new) })
        } else {
            None
        }
    }

    /// Take the current content, write it into P then do a CAS to extent this
    /// Atom with the previous contents. This can be used to create a LIFO
    ///
    /// Returns true if this set this migrated the Atom from null.
    pub fn replace_and_set_next(&self, mut value: P) -> bool
        where P: GetNextMut<NextPtr=Option
> {
        unsafe {
            let next = value.get_next() as *mut Option
;
            let raw = value.into_raw();
            // Iff next was set to Some(P) we want to
            // assert that it was droppeds
            drop(ptr::read(next));
            loop {
                let pcurrent = self.inner.load(Ordering::Relaxed);
                let current = if pcurrent.is_null() {
                    None
                } else {
                    Some(FromRawPtr::from_raw(pcurrent))
                };
                ptr::write(next, current);
                let last = self.inner.compare_and_swap(pcurrent, raw, Ordering::AcqRel);
                if last == pcurrent {
                    return last.is_null();
                }
            }
        }
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self) -> bool {
        self.inner.load(Ordering::Relaxed).is_null()
    }
}

impl
 Drop for Atom
 where P: IntoRawPtr + FromRawPtr  {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.inner.load(Ordering::Relaxed);
            if !ptr.is_null() {
                let _: P = FromRawPtr::from_raw(ptr);
            }
        }
    }
}

unsafe impl
 Send for Atom
 where P: IntoRawPtr + FromRawPtr {}
unsafe impl
 Sync for Atom
 where P: IntoRawPtr + FromRawPtr {}

/// Convert from into a raw pointer
pub trait IntoRawPtr {
    unsafe fn into_raw(self) -> *mut ();
}

/// Convert from a raw ptr into a pointer
pub trait FromRawPtr {
    unsafe fn from_raw(ptr: *mut ()) -> Self;
}

impl<T> IntoRawPtr for Box<T> {
    unsafe fn into_raw(self) -> *mut () {
        mem::transmute(self)
    }
}

impl<T> FromRawPtr for Box<T> {
    unsafe fn from_raw(ptr: *mut ()) -> Box<T> {
        mem::transmute(ptr)
    }
}

impl<T> IntoRawPtr for Arc<T> {
    unsafe fn into_raw(self) -> *mut () {
        mem::transmute(self)
    }
}

impl<T> FromRawPtr for Arc<T> {
    unsafe fn from_raw(ptr: *mut ()) -> Arc<T> {
        mem::transmute(ptr)
    }
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                       ptr: &T) -> &'a T {
    mem::transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                    ptr: &mut T) -> &'a mut T {
    mem::transmute(ptr)
}

/// This is a restricted version of the Atom. It allows for only
/// `set_if_none` to be called.
///
/// `swap` and `take` can be used only with a mutable reference. Meaning
/// that AtomSetOnce is not usable as a
#[derive(Debug)]
pub struct AtomSetOnce
 where P: IntoRawPtr + FromRawPtr {
    inner: Atom

}

impl
 AtomSetOnce

    where P: IntoRawPtr + FromRawPtr {

    /// Create a empty AtomSetOnce
    pub fn empty() -> AtomSetOnce
 {
        AtomSetOnce { inner: Atom::empty() }
    }

    /// Create a new AtomSetOnce from Pointer P
    pub fn new(value: P) -> AtomSetOnce
 {
        AtomSetOnce { inner: Atom::new(value) }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `OK(())` if the value was written,
    /// otherwise a `Err(P)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P) -> Option
 {
        self.inner.set_if_none(v)
    }

    /// Convert an AtomSetOnce into an Atom
    pub fn into_atom(self) -> Atom
 { self.inner }

    /// Allow access to the atom if exclusive access is granted
    pub fn atom(&mut self) -> &mut Atom
 { &mut self.inner }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self) -> bool { self.inner.is_none() }
}

impl<T, P> AtomSetOnce

    where P: IntoRawPtr + FromRawPtr + Deref<Target=T> {

    /// If the Atom is set, get the value
    pub fn get<'a>(&'a self) -> Option<&'a T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let v: P = FromRawPtr::from_raw(ptr);
                let out = copy_lifetime(self, &*v);
                mem::forget(v);
                Some(out)
            }
        }
    }
}

impl<T> AtomSetOnce<Box<T>> {
    /// If the Atom is set, get the value
    pub fn get_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let mut v: Box<T> = FromRawPtr::from_raw(ptr);
                let out = copy_mut_lifetime(self, &mut *v);
                mem::forget(v);
                Some(out)
            }
        }
    }
}

impl<T> AtomSetOnce<T> where T: Clone+IntoRawPtr+FromRawPtr {
    /// Duplicate the inner pointer if it is set
    pub fn dup<'a>(&self) -> Option<T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let v: T = FromRawPtr::from_raw(ptr);
                let out = v.clone();
                mem::forget(v);
                Some(out)
            }
        }
    }
}

/// This is a utility Trait that fetches the next ptr from
/// an object.
pub trait GetNextMut {
    type NextPtr;
    fn get_next(&mut self) -> &mut Self::NextPtr;
}
<commit_msg>Do not assume memory layout of Rust structs<commit_after>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::sync::atomic::AtomicPtr;
use std::sync::Arc;
use std::mem;
use std::ptr;
use std::ops::Deref;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::sync::atomic::Ordering;

/// An Atom wraps an AtomicPtr, it allows for safe mutation of an atomic
/// into common Rust Types.
pub struct Atom
 where P: IntoRawPtr + FromRawPtr {
    inner: AtomicPtr<()>,
    data: PhantomData

}

impl
 Debug for Atom
 where P: IntoRawPtr + FromRawPtr {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "atom({:?})", self.inner.load(Ordering::Relaxed))
    }
}

impl
 Atom
 where P: IntoRawPtr + FromRawPtr {
    /// Create a empty Atom
    pub fn empty() -> Atom
 {
        Atom {
            inner: AtomicPtr::new(ptr::null_mut()),
            data: PhantomData
        }
    }

    /// Create a new Atomic from Pointer P
    pub fn new(value: P) -> Atom
 {
        Atom {
            inner: AtomicPtr::new(unsafe { value.into_raw() }),
            data: PhantomData
        }
    }

    /// Swap a new value into the Atom, This will try multiple
    /// times until it succeeds. The old value will be returned.
    pub fn swap(&self, v: P) -> Option
 {
        let new = unsafe { v.into_raw() };
        let old = self.inner.swap(new, Ordering::AcqRel);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(old) })
        } else {
            None
        }
    }

    /// Take the value of the Atom replacing it with null pointer
    /// Returning the contents. If the contents was a `null` pointer the
    /// result will be `None`.
    pub fn take(&self) -> Option
 {
        let old = self.inner.swap(ptr::null_mut(), Ordering::Acquire);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(old) })
        } else {
            None
        }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `None` if the value was written,
    /// otherwise a `Some(v)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P) -> Option
 {
        let new = unsafe { v.into_raw() };
        let old = self.inner.compare_and_swap(ptr::null_mut(), new, Ordering::Release);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(new) })
        } else {
            None
        }
    }

    /// Take the current content, write it into P then do a CAS to extent this
    /// Atom with the previous contents. This can be used to create a LIFO
    ///
    /// Returns true if this set this migrated the Atom from null.
    pub fn replace_and_set_next(&self, mut value: P) -> bool
        where P: GetNextMut<NextPtr=Option
> {
        unsafe {
            let next = value.get_next() as *mut Option
;
            let raw = value.into_raw();
            // Iff next was set to Some(P) we want to
            // assert that it was droppeds
            drop(ptr::read(next));
            loop {
                let pcurrent = self.inner.load(Ordering::Relaxed);
                let current = if pcurrent.is_null() {
                    None
                } else {
                    Some(FromRawPtr::from_raw(pcurrent))
                };
                ptr::write(next, current);
                let last = self.inner.compare_and_swap(pcurrent, raw, Ordering::AcqRel);
                if last == pcurrent {
                    return last.is_null();
                }
            }
        }
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self) -> bool {
        self.inner.load(Ordering::Relaxed).is_null()
    }
}

impl
 Drop for Atom
 where P: IntoRawPtr + FromRawPtr  {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.inner.load(Ordering::Relaxed);
            if !ptr.is_null() {
                let _: P = FromRawPtr::from_raw(ptr);
            }
        }
    }
}

unsafe impl
 Send for Atom
 where P: IntoRawPtr + FromRawPtr {}
unsafe impl
 Sync for Atom
 where P: IntoRawPtr + FromRawPtr {}

/// Convert from into a raw pointer
pub trait IntoRawPtr {
    unsafe fn into_raw(self) -> *mut ();
}

/// Convert from a raw ptr into a pointer
pub trait FromRawPtr {
    unsafe fn from_raw(ptr: *mut ()) -> Self;
}

impl<T> IntoRawPtr for Box<T> {
    #[inline]
    unsafe fn into_raw(self) -> *mut () {
        Box::into_raw(self) as *mut ()
    }
}

impl<T> FromRawPtr for Box<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Box<T> {
        Box::from_raw(ptr as *mut T)
    }
}

impl<T> IntoRawPtr for Arc<T> {
    #[inline]
    unsafe fn into_raw(self) -> *mut () {
        Arc::into_raw(self) as *mut _ as *mut ()
    }
}

impl<T> FromRawPtr for Arc<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Arc<T> {
        Arc::from_raw(ptr as *const () as *const T)
    }
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                       ptr: &T) -> &'a T {
    mem::transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                    ptr: &mut T) -> &'a mut T {
    mem::transmute(ptr)
}

/// This is a restricted version of the Atom. It allows for only
/// `set_if_none` to be called.
///
/// `swap` and `take` can be used only with a mutable reference. Meaning
/// that AtomSetOnce is not usable as a
#[derive(Debug)]
pub struct AtomSetOnce
 where P: IntoRawPtr + FromRawPtr {
    inner: Atom

}

impl
 AtomSetOnce

    where P: IntoRawPtr + FromRawPtr {

    /// Create an empty `AtomSetOnce`
    pub fn empty() -> AtomSetOnce
 {
        AtomSetOnce { inner: Atom::empty() }
    }

    /// Create a new `AtomSetOnce` from Pointer P
    pub fn new(value: P) -> AtomSetOnce
 {
        AtomSetOnce { inner: Atom::new(value) }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `OK(())` if the value was written,
    /// otherwise a `Err(P)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P) -> Option
 {
        self.inner.set_if_none(v)
    }

    /// Convert an `AtomSetOnce` into an `Atom`
    pub fn into_atom(self) -> Atom
 { self.inner }

    /// Allow access to the atom if exclusive access is granted
    pub fn atom(&mut self) -> &mut Atom
 { &mut self.inner }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self) -> bool { self.inner.is_none() }
}

impl<T, P> AtomSetOnce

    where P: IntoRawPtr + FromRawPtr + Deref<Target=T> {

    /// If the Atom is set, get the value
    pub fn get<'a>(&'a self) -> Option<&'a T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let v: P = FromRawPtr::from_raw(ptr);
                let out = copy_lifetime(self, &*v);
                mem::forget(v);
                Some(out)
            }
        }
    }
}

impl<T> AtomSetOnce<Box<T>> {
    /// If the Atom is set, get the value
    pub fn get_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let mut v: Box<T> = FromRawPtr::from_raw(ptr);
                let out = copy_mut_lifetime(self, &mut *v);
                mem::forget(v);
                Some(out)
            }
        }
    }
}

impl<T> AtomSetOnce<T> where T: Clone+IntoRawPtr+FromRawPtr {
    /// Duplicate the inner pointer if it is set
    pub fn dup<'a>(&self) -> Option<T> {
        let ptr = self.inner.inner.load(Ordering::Acquire);
        if ptr.is_null() {
            None
        } else {
            unsafe {
                // This is safe since ptr cannot be changed once it is set
                // which means that this is now a Arc or a Box.
                let v: T = FromRawPtr::from_raw(ptr);
                let out = v.clone();
                mem::forget(v);
                Some(out)
            }
        }
    }
}

/// This is a utility Trait that fetches the next ptr from
/// an object.
pub trait GetNextMut {
    type NextPtr;
    fn get_next(&mut self) -> &mut Self::NextPtr;
}
<|endoftext|>


<commit_before>//! Crate ruma_client_api contains serializable types for the requests and responses for each
//! endpoint in the [Matrix](https://matrix.org/) client API specification. These types can be
//! shared by client and server code.

#![deny(missing_debug_implementations, missing_docs)]
#![feature(proc_macro, try_from)]

extern crate futures;
extern crate http;
extern crate hyper;
extern crate ruma_api;
extern crate ruma_api_macros;
extern crate ruma_events;
extern crate ruma_identifiers;
extern crate ruma_signatures;
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
extern crate serde_urlencoded;
extern crate url;

/// Endpoints for the r0.x.x versions of the client API specification.
pub mod r0 {
    pub mod account;
    pub mod alias;
    pub mod config;
    pub mod contact;
    pub mod context;
    pub mod directory;
    pub mod filter;
    pub mod media;
    pub mod membership;
    pub mod presence;
    pub mod profile;
    pub mod push;
    pub mod receipt;
    pub mod redact;
    pub mod room;
    pub mod search;
    pub mod send;
    pub mod server;
    pub mod session;
    pub mod sync;
    pub mod tag;
    pub mod typing;
    pub mod voip;
}

pub mod unversioned;
<commit_msg>Fix Rust's hint about proc_macro<commit_after>//! Crate ruma_client_api contains serializable types for the requests and responses for each
//! endpoint in the [Matrix](https://matrix.org/) client API specification. These types can be
//! shared by client and server code.

#![deny(missing_debug_implementations, missing_docs)]
#![feature(try_from)]

extern crate futures;
extern crate http;
extern crate hyper;
extern crate ruma_api;
extern crate ruma_api_macros;
extern crate ruma_events;
extern crate ruma_identifiers;
extern crate ruma_signatures;
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
extern crate serde_urlencoded;
extern crate url;

/// Endpoints for the r0.x.x versions of the client API specification.
pub mod r0 {
    pub mod account;
    pub mod alias;
    pub mod config;
    pub mod contact;
    pub mod context;
    pub mod directory;
    pub mod filter;
    pub mod media;
    pub mod membership;
    pub mod presence;
    pub mod profile;
    pub mod push;
    pub mod receipt;
    pub mod redact;
    pub mod room;
    pub mod search;
    pub mod send;
    pub mod server;
    pub mod session;
    pub mod sync;
    pub mod tag;
    pub mod typing;
    pub mod voip;
}

pub mod unversioned;
<|endoftext|>


<commit_before>extern crate libc;
use libc::{
    c_char,
    c_void,
    c_int,
    uint32_t,
};

#[macro_use]
extern crate bitflags;

extern crate libfreenect_sys;
use libfreenect_sys::{
    freenect_context,
    freenect_init,
    freenect_shutdown,
    freenect_loglevel,
    freenect_set_log_level,
    freenect_process_events,
    freenect_num_devices,
    freenect_device_flags,
    freenect_device_attributes,
    freenect_list_device_attributes,
    freenect_free_device_attributes,
    freenect_supported_subdevices,
    freenect_select_subdevices,
    freenect_enabled_subdevices,
    freenect_device,
    freenect_open_device,
    freenect_open_device_by_camera_serial,
    freenect_close_device,
    freenect_set_depth_callback,
    freenect_set_video_callback,
    freenect_set_depth_chunk_callback,
    freenect_set_video_chunk_callback,
    freenect_get_user,
    freenect_set_user,
};

use std::ptr;
use std::ffi;
use std::sync::Arc;

enum FreenectError {
    LibraryReturnCode(i32),
    NullPtr,
}

pub type FreenectResult<T> = Result<T, FreenectError>;

pub enum LogLevel {
	Fatal,         // Log for crashing/non-recoverable errors
	Error,         // Log for major errors
	Warning,       // Log for warning messages
	Notice,        // Log for important messages
	Info,          // Log for normal messages
	Debug,         // Log for useful development messages
	Spew,          // Log for slightly less useful messages
	Flood,         // Log EVERYTHING. May slow performance.
}

impl LogLevel {
    fn to_lowlevel(self) -> freenect_loglevel {
        match self {
            LogLevel::Fatal => freenect_loglevel::FREENECT_LOG_FATAL,
            _ => freenect_loglevel::FREENECT_LOG_FATAL,
        }
    }

    fn from_lowlevel(lvl: freenect_loglevel) -> LogLevel {
        match lvl {
            freenect_loglevel::FREENECT_LOG_FATAL => LogLevel::Fatal,
            _ => LogLevel::Fatal
        }
    }
}

bitflags! {
    flags DeviceFlags: u32 {
        const DEVICE_MOTOR  = freenect_device_flags::FREENECT_DEVICE_MOTOR  as u32,
        const DEVICE_CAMERA = freenect_device_flags::FREENECT_DEVICE_CAMERA as u32,
        const DEVICE_AUDIO  = freenect_device_flags::FREENECT_DEVICE_AUDIO  as u32,
    }
}

pub struct DeviceAttributes {
    camera_serial: String,
}

struct InnerContext {
    ctx: *mut freenect_context,
}

impl InnerContext {
    fn new() -> FreenectResult<InnerContext> {
        let mut ctx = InnerContext{ctx: ptr::null_mut()};

        match unsafe { freenect_init(&mut ctx.ctx, ptr::null_mut()) } {
            0 => {
                if ctx.ctx != ptr::null_mut() {
                    Ok(ctx)
                } else {
                    Err(FreenectError::NullPtr)
                }
            },
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }
}

impl Drop for InnerContext {
    fn drop(&mut self) {
        let ret = unsafe { freenect_shutdown(self.ctx) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub struct Context {
    ctx: Arc<InnerContext>,
}

impl Context {
    pub fn new() -> FreenectResult<Context> {
        let inner_ctx = try!(InnerContext::new());

        Ok(Context{ctx: Arc::new(inner_ctx)})
    }

    pub fn set_log_level(&mut self, level: LogLevel) {
        unsafe { freenect_set_log_level(self.ctx.ctx, level.to_lowlevel()); }
    }

    // pub fn set_log_callback(&mut self) {
    //
    // }
    //
    // // Convert C callback parameters to rustified versions, then call user callback
    // fn callback_trampoline(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char) {
    //     let level = LogLevel::from_lowlevel(level);
    //     let msg = unsafe { ffi::CStr::from_ptr(msg) };
    // }

    pub fn process_events(&mut self) -> FreenectResult<()> {
        match unsafe { freenect_process_events(self.ctx.ctx) } {
            0 => Ok(()),
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }

    pub fn num_devices(&mut self) -> FreenectResult<u32> {
        let ret = unsafe { freenect_num_devices(self.ctx.ctx) };
        if ret < 0 {
            Err(FreenectError::LibraryReturnCode(ret))
        } else {
            Ok(ret as u32)
        }
    }

    pub fn list_device_attributes(&mut self) -> FreenectResult<Vec<DeviceAttributes>> {
        let mut lowlevel_list: *mut freenect_device_attributes = ptr::null_mut();

        let ret = unsafe { freenect_list_device_attributes(self.ctx.ctx, &mut lowlevel_list) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret));
        }

        let mut device_list: Vec<DeviceAttributes> = Vec::new();

        let mut curr_item = lowlevel_list;
        while curr_item != ptr::null_mut() {
            let serial_cstr = unsafe { ffi::CStr::from_ptr((*curr_item).camera_serial) };
            let serial = String::from_utf8_lossy(serial_cstr.to_bytes()).to_string();

            device_list.push(DeviceAttributes{camera_serial: serial});
            unsafe { curr_item = (*curr_item).next };
        }

        unsafe { freenect_free_device_attributes(self.ctx.ctx, lowlevel_list) };

        Ok(device_list)
    }

    fn select_subdevices(&mut self, subdevs: DeviceFlags) {
        unsafe { freenect_select_subdevices(self.ctx.ctx, subdevs.bits) };
    }

    fn enabled_subdevices(&mut self) -> DeviceFlags {
        let ret = unsafe { freenect_enabled_subdevices(self.ctx.ctx) };

        return DeviceFlags::from_bits(ret as u32).unwrap();
    }

    pub fn open_device(&mut self, index: u32, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device(self.ctx.ctx, &mut dev, index as i32) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }

    pub fn open_device_by_camera_serial(&mut self, serial: &str, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        let serial_cstring = ffi::CString::new(serial).unwrap();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device_by_camera_serial(self.ctx.ctx, &mut dev, serial_cstring.as_ptr()) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }
}

// Exists so it can be boxed (therefore fixing its memory address) and have its address handed as a
// C callback user pointer
struct ClosureHolder {
    depth_cb: Option<Box<FnMut()>>,
    video_cb: Option<Box<FnMut()>>,
    depth_chunk_cb: Option<Box<FnMut()>>,
    video_chunk_cb: Option<Box<FnMut()>>,
}

pub struct MotorSubdevice {
    dev: *mut freenect_device,
}

pub struct CameraSubdevice {
    dev: *mut freenect_device,
}

pub struct AudioSubdevice {
    dev: *mut freenect_device,
}

pub struct Device {
    ctx: Arc<InnerContext>, // Handle to prevent underlying context being free'd before device
    dev: *mut freenect_device,
    ch: Box<ClosureHolder>,
    pub motor:  Option<MotorSubdevice>,
    pub camera: Option<CameraSubdevice>,
    pub audio:  Option<AudioSubdevice>,
}

impl Device {
    fn from_raw_device(ctx: Arc<InnerContext>, dev: *mut freenect_device, subdevs: DeviceFlags) -> Device {
        let mut dev = Device {
            ctx: ctx,
            dev: dev,
            ch: Box::new(ClosureHolder {
                depth_cb: None,
                video_cb: None,
                depth_chunk_cb: None,
                video_chunk_cb: None,
            }),
            motor:  if subdevs.contains(DEVICE_MOTOR)  { Some(MotorSubdevice{dev: dev})  } else { None },
            camera: if subdevs.contains(DEVICE_CAMERA) {
                        Some(CameraSubdevice{
                            dev: dev,
                            })
                    } else {
                        None
                    },
            audio:  if subdevs.contains(DEVICE_AUDIO)  { Some(AudioSubdevice{dev: dev})  } else { None },
        };

        // Register all callbacks. We'll let Rust code decide if a user callback should be called.
        unsafe {
            freenect_set_user(dev.dev, std::mem::transmute(&mut *dev.ch));

            freenect_set_depth_callback(dev.dev, Device::depth_cb_trampoline);
            freenect_set_video_callback(dev.dev, Device::video_cb_trampoline);
            freenect_set_depth_chunk_callback(dev.dev, Device::depth_chunk_cb_trampoline);
            freenect_set_video_chunk_callback(dev.dev, Device::video_chunk_cb_trampoline);
        }

        return dev;
    }

    extern "C" fn depth_cb_trampoline(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t) {
        unsafe {
            let ch = freenect_get_user(dev) as *mut ClosureHolder;

            match (*ch).depth_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn video_cb_trampoline(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t) {
        unsafe {
            let ch = freenect_get_user(dev) as *mut ClosureHolder;

            match (*ch).video_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn video_chunk_cb_trampoline(buffer: *mut c_void, pkt_data: *mut c_void, pkt_num: c_int, datalen: c_int, user_data: *mut c_void) {
        unsafe {
            let ch = user_data as *mut ClosureHolder;

            match (*ch).video_chunk_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn depth_chunk_cb_trampoline(buffer: *mut c_void, pkt_data: *mut c_void, pkt_num: c_int, datalen: c_int, user_data: *mut c_void) {
        unsafe {
            let ch = user_data as *mut ClosureHolder;

            match (*ch).depth_chunk_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }
}

impl Drop for Device {
    fn drop(&mut self) {
        let ret = unsafe { freenect_close_device(self.dev) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub fn supported_subdevices() -> DeviceFlags {
    let bits = unsafe { freenect_supported_subdevices() as u32 };
    return DeviceFlags::from_bits(bits).unwrap();
}
<commit_msg>Switch from Arc -> Rc for main context object<commit_after>use std::ffi;
use std::ptr;
use std::rc::Rc;

extern crate libc;
use libc::{
    c_char,
    c_void,
    c_int,
    uint32_t,
};

#[macro_use]
extern crate bitflags;

extern crate libfreenect_sys;
use libfreenect_sys::{
    freenect_context,
    freenect_init,
    freenect_shutdown,
    freenect_loglevel,
    freenect_set_log_level,
    freenect_process_events,
    freenect_num_devices,
    freenect_device_flags,
    freenect_device_attributes,
    freenect_list_device_attributes,
    freenect_free_device_attributes,
    freenect_supported_subdevices,
    freenect_select_subdevices,
    freenect_enabled_subdevices,
    freenect_device,
    freenect_open_device,
    freenect_open_device_by_camera_serial,
    freenect_close_device,
    freenect_set_depth_callback,
    freenect_set_video_callback,
    freenect_set_depth_chunk_callback,
    freenect_set_video_chunk_callback,
    freenect_get_user,
    freenect_set_user,
    freenect_start_depth,
    freenect_start_video,
    freenect_stop_depth,
    freenect_stop_video,
};

enum FreenectError {
    LibraryReturnCode(i32),
    NullPtr,
}

// Error type for the library
pub type FreenectResult<T> = Result<T, FreenectError>;

pub enum LogLevel {
	Fatal,         // Log for crashing/non-recoverable errors
	Error,         // Log for major errors
	Warning,       // Log for warning messages
	Notice,        // Log for important messages
	Info,          // Log for normal messages
	Debug,         // Log for useful development messages
	Spew,          // Log for slightly less useful messages
	Flood,         // Log EVERYTHING. May slow performance.
}

// FIXME: TBD remaining log levels
impl LogLevel {
    fn to_lowlevel(self) -> freenect_loglevel {
        match self {
            LogLevel::Fatal => freenect_loglevel::FREENECT_LOG_FATAL,
            _ => freenect_loglevel::FREENECT_LOG_FATAL,
        }
    }

    fn from_lowlevel(lvl: freenect_loglevel) -> LogLevel {
        match lvl {
            freenect_loglevel::FREENECT_LOG_FATAL => LogLevel::Fatal,
            _ => LogLevel::Fatal
        }
    }
}

bitflags! {
    flags DeviceFlags: u32 {
        const DEVICE_MOTOR  = freenect_device_flags::FREENECT_DEVICE_MOTOR  as u32,
        const DEVICE_CAMERA = freenect_device_flags::FREENECT_DEVICE_CAMERA as u32,
        const DEVICE_AUDIO  = freenect_device_flags::FREENECT_DEVICE_AUDIO  as u32,
    }
}

pub struct DeviceAttributes {
    pub camera_serial: String,
}

struct InnerContext {
    ctx: *mut freenect_context,
}

impl InnerContext {
    fn new() -> FreenectResult<InnerContext> {
        let mut ctx = InnerContext{ctx: ptr::null_mut()};

        match unsafe { freenect_init(&mut ctx.ctx, ptr::null_mut()) } {
            0 => {
                if ctx.ctx != ptr::null_mut() {
                    Ok(ctx)
                } else {
                    Err(FreenectError::NullPtr)
                }
            },
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }
}

impl Drop for InnerContext {
    fn drop(&mut self) {
        let ret = unsafe { freenect_shutdown(self.ctx) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub struct Context {
    ctx: Rc<InnerContext>,
}

impl Context {
    pub fn new() -> FreenectResult<Context> {
        let inner_ctx = try!(InnerContext::new());

        Ok(Context{ctx: Rc::new(inner_ctx)})
    }

    pub fn set_log_level(&mut self, level: LogLevel) {
        unsafe { freenect_set_log_level(self.ctx.ctx, level.to_lowlevel()); }
    }

    // pub fn set_log_callback(&mut self) {
    //
    // }
    //
    // // Convert C callback parameters to rustified versions, then call user callback
    // fn callback_trampoline(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char) {
    //     let level = LogLevel::from_lowlevel(level);
    //     let msg = unsafe { ffi::CStr::from_ptr(msg) };
    // }

    pub fn process_events(&mut self) -> FreenectResult<()> {
        match unsafe { freenect_process_events(self.ctx.ctx) } {
            0 => Ok(()),
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }

    pub fn num_devices(&mut self) -> FreenectResult<u32> {
        let ret = unsafe { freenect_num_devices(self.ctx.ctx) };
        if ret < 0 {
            Err(FreenectError::LibraryReturnCode(ret))
        } else {
            Ok(ret as u32)
        }
    }

    pub fn list_device_attributes(&mut self) -> FreenectResult<Vec<DeviceAttributes>> {
        let mut lowlevel_list: *mut freenect_device_attributes = ptr::null_mut();

        let ret = unsafe { freenect_list_device_attributes(self.ctx.ctx, &mut lowlevel_list) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret));
        }

        let mut device_list: Vec<DeviceAttributes> = Vec::new();

        let mut curr_item = lowlevel_list;
        while curr_item != ptr::null_mut() {
            let serial_cstr = unsafe { ffi::CStr::from_ptr((*curr_item).camera_serial) };
            let serial = String::from_utf8_lossy(serial_cstr.to_bytes()).to_string();

            device_list.push(DeviceAttributes{camera_serial: serial});
            unsafe { curr_item = (*curr_item).next };
        }

        unsafe { freenect_free_device_attributes(self.ctx.ctx, lowlevel_list) };

        Ok(device_list)
    }

    fn select_subdevices(&mut self, subdevs: DeviceFlags) {
        unsafe { freenect_select_subdevices(self.ctx.ctx, subdevs.bits) };
    }

    fn enabled_subdevices(&mut self) -> DeviceFlags {
        let ret = unsafe { freenect_enabled_subdevices(self.ctx.ctx) };

        return DeviceFlags::from_bits(ret as u32).unwrap();
    }

    pub fn open_device(&mut self, index: u32, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device(self.ctx.ctx, &mut dev, index as i32) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }

    pub fn open_device_by_camera_serial(&mut self, serial: &str, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        let serial_cstring = ffi::CString::new(serial).unwrap();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device_by_camera_serial(self.ctx.ctx, &mut dev, serial_cstring.as_ptr()) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }
}

// Exists so it can be boxed (therefore fixing its memory address) and have its address handed as a
// C callback userdata  void pointer
struct ClosureHolder {
    depth_cb: Option<Box<FnMut()>>,
    video_cb: Option<Box<FnMut()>>,
    depth_chunk_cb: Option<Box<FnMut()>>,
    video_chunk_cb: Option<Box<FnMut()>>,
}

pub struct MotorSubdevice {
    dev: *mut freenect_device,
}

pub struct CameraSubdevice {
    dev: *mut freenect_device,
}

pub struct AudioSubdevice {
    dev: *mut freenect_device,
}

pub struct Device {
    ctx: Rc<InnerContext>, // Handle to prevent underlying context being free'd before device
    dev: *mut freenect_device,
    ch: Box<ClosureHolder>,
    pub motor:  Option<MotorSubdevice>,
    pub camera: Option<CameraSubdevice>,
    pub audio:  Option<AudioSubdevice>,
}

impl Device {
    fn from_raw_device(ctx: Rc<InnerContext>, dev: *mut freenect_device, subdevs: DeviceFlags) -> Device {
        let mut dev = Device {
            ctx: ctx,
            dev: dev,
            ch: Box::new(ClosureHolder {
                depth_cb: None,
                video_cb: None,
                depth_chunk_cb: None,
                video_chunk_cb: None,
            }),
            motor:  if subdevs.contains(DEVICE_MOTOR)  { Some(MotorSubdevice{dev: dev})  } else { None },
            camera: if subdevs.contains(DEVICE_CAMERA) {
                        Some(CameraSubdevice{
                            dev: dev,
                            })
                    } else {
                        None
                    },
            audio:  if subdevs.contains(DEVICE_AUDIO)  { Some(AudioSubdevice{dev: dev})  } else { None },
        };

        // Register all callbacks. We'll let Rust code decide if a user callback should be called.
        unsafe {
            freenect_set_user(dev.dev, std::mem::transmute(&mut *dev.ch));

            freenect_set_depth_callback(dev.dev, Device::depth_cb_trampoline);
            freenect_set_video_callback(dev.dev, Device::video_cb_trampoline);
            freenect_set_depth_chunk_callback(dev.dev, Device::depth_chunk_cb_trampoline);
            freenect_set_video_chunk_callback(dev.dev, Device::video_chunk_cb_trampoline);
        }

        return dev;
    }

    extern "C" fn depth_cb_trampoline(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t) {
        unsafe {
            let ch = freenect_get_user(dev) as *mut ClosureHolder;

            match (*ch).depth_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn video_cb_trampoline(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t) {
        unsafe {
            let ch = freenect_get_user(dev) as *mut ClosureHolder;

            match (*ch).video_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn video_chunk_cb_trampoline(buffer: *mut c_void, pkt_data: *mut c_void, pkt_num: c_int, datalen: c_int, user_data: *mut c_void) {
        unsafe {
            let ch = user_data as *mut ClosureHolder;

            match (*ch).video_chunk_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    extern "C" fn depth_chunk_cb_trampoline(buffer: *mut c_void, pkt_data: *mut c_void, pkt_num: c_int, datalen: c_int, user_data: *mut c_void) {
        unsafe {
            let ch = user_data as *mut ClosureHolder;

            match (*ch).depth_chunk_cb {
                Some(ref mut cb) => cb(),
                None => return,
            };
        }
    }

    fn set_depth_callback(&mut self, cb: Option<Box<FnMut()>>) {
        self.ch.depth_cb = cb;
    }

    fn set_video_callback(&mut self, cb: Option<Box<FnMut()>>) {
        self.ch.video_cb = cb;
    }

    fn set_depth_chunk_callback(&mut self, cb: Option<Box<FnMut()>>) {
        self.ch.depth_chunk_cb = cb;
    }

    fn set_video_chunk_callback(&mut self, cb: Option<Box<FnMut()>>) {
        self.ch.video_chunk_cb = cb;
    }

    pub fn start_depth(&mut self) -> FreenectResult<()> {
        let ret = unsafe { freenect_start_depth(self.dev)};

        if ret == 0 {
            Ok(())
        } else {
            Err(FreenectError::LibraryReturnCode(ret))
        }
    }

    pub fn start_video(&mut self) -> FreenectResult<()> {
        let ret = unsafe { freenect_start_video(self.dev)};

        if ret == 0 {
            Ok(())
        } else {
            Err(FreenectError::LibraryReturnCode(ret))
        }
    }

    pub fn stop_depth(&mut self) -> FreenectResult<()> {
        let ret = unsafe { freenect_stop_depth(self.dev)};

        if ret == 0 {
            Ok(())
        } else {
            Err(FreenectError::LibraryReturnCode(ret))
        }
    }

    pub fn stop_video(&mut self) -> FreenectResult<()> {
        let ret = unsafe { freenect_stop_video(self.dev)};

        if ret == 0 {
            Ok(())
        } else {
            Err(FreenectError::LibraryReturnCode(ret))
        }
    }
}

impl Drop for Device {
    fn drop(&mut self) {
        let ret = unsafe { freenect_close_device(self.dev) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub fn supported_subdevices() -> DeviceFlags {
    let bits = unsafe { freenect_supported_subdevices() as u32 };
    return DeviceFlags::from_bits(bits).unwrap();
}
<|endoftext|>


<commit_before>//!
//! # Desync
//!
//!
//! This is a library for Rust that provides a model of concurrency based around the idea of
//! scheduling operations on data. This is in contrast to the traditional model where operations
//! are scheduled on threads with ownership of the data being passed between them.
//!
//! This approach has several advantages over the traditional method:
//!
//!  * It's simpler: almost the  entire set of thread methods and synchronisation primitives can
//!    be replaced with the two fundamental scheduling functions, `sync()` and `desync()`.
//!  * It's easier to reason about: scheduled operations are always performed in the order they're
//!    queued so race conditions and similar issues due to out-of-order execution are both much rarer
//!    and easier to debug.
//!  * It makes it easier to write highly concurrent code: desync makes moving between performing
//!    operations synchronously and asynchronously trivial, with no need to deal with adding code to
//!    start threads or communicate between them.
//!
//! In addition to the two fundamental methods, desync provides methods for generating futures and
//! processing streams.
//!
//! # Quick start
//!
//! There is a single new synchronisation object: `Desync`. You create one like this:
//!
//! ```
//! use desync::Desync;
//! let number = Desync::new(0);
//! ```
//!
//! It supports two main operations. `desync` will schedule a new job for the object that will run
//! in a background thread. It's useful for deferring long-running operations and moving updates
//! so they can run in parallel.
//!
//! ```
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! let number = Desync::new(0);
//! number.desync(|val| {
//!     // Long update here
//!     thread::sleep(Duration::from_millis(100));
//!     *val = 42;
//! });
//!
//! // We can carry on what we're doing with the update now running in the background
//! ```
//!
//! The other operation is `sync`, which schedules a job to run synchronously on the data structure.
//! This is useful for retrieving values from a `Desync`.
//!
//! ```
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! # let number = Desync::new(0);
//! # number.desync(|val| {
//! #     // Long update here
//! #     thread::sleep(Duration::from_millis(100));
//! #     *val = 42;
//! # });
//! let new_number = number.sync(|val| *val);           // = 42
//! # assert!(new_number == 42);
//! ```
//!
//! `Desync` objects always run operations in the order that is provided, so all operations are
//! serialized from the point of view of the data that they contain. When combined with the ability
//! to perform operations asynchronously, this provides a useful way to immediately parallelize
//! long-running operations.
//!
//! The `future()` action returns a boxed Future that can be used with other libraries that use them. It's
//! conceptually the same as `sync`, except that it doesn't wait for the operation to complete:
//!
//! ```
//! # extern crate futures;
//! # extern crate desync;
//! # fn main() {
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! # use futures::executor;
//! # use futures::future;
//! # let number = Desync::new(0);
//! # number.desync(|val| {
//! #     // Long update here
//! #     thread::sleep(Duration::from_millis(100));
//! #     *val = 42;
//! # });
//! let future_number = number.future(|val| future::ready(*val));
//! assert!(executor::block_on(async { future_number.await.unwrap() }) == 42 );
//! # }
//!
//! Note that this is the equivalent of just `number.sync(|val| *val)`, so this is mainly useful for
//! interacting with other code that's already using futures. The `after()` function is also provided
//! for using the results of futures to update the contents of `Desync` data: these all preserve the
//! strict order-of-operations semantics, so operations scheduled after an `after` won't start until
//! that operation has completed.
//!
//! # Pipes and streams
//!
//! As well as support for futures, Desync provides supports for streams. The `pipe_in()` and `pipe()`
//! functions provide a way to process stream data in a desync object as it arrives. `pipe_in()` just
//! processes stream data as it arrives, and `pipe()` provides an output stream of data.
//!
//! `pipe()` is quite useful as a way to provide asynchronous access to synchronous code: it can be used
//! to create a channel to send requests to an asynchronous target and retrieve results back via its
//! output. (Unlike this 'traditional' method, the actual scheduling and channel maintenance does not
//! need to be explicitly implemented)
//!
//! ```
//!

#![warn(bare_trait_objects)]

#[macro_use]
extern crate lazy_static;
extern crate futures;

#[cfg(not(target_arch = "wasm32"))]
extern crate num_cpus;

pub mod scheduler;
pub mod desync;
pub mod pipe;

mod job;
mod future_job;
mod unsafe_job;
mod scheduler_thread;

pub use self::desync::*;
pub use self::pipe::*;
<commit_msg>Fix misplaced quote<commit_after>//!
//! # Desync
//!
//!
//! This is a library for Rust that provides a model of concurrency based around the idea of
//! scheduling operations on data. This is in contrast to the traditional model where operations
//! are scheduled on threads with ownership of the data being passed between them.
//!
//! This approach has several advantages over the traditional method:
//!
//!  * It's simpler: almost the  entire set of thread methods and synchronisation primitives can
//!    be replaced with the two fundamental scheduling functions, `sync()` and `desync()`.
//!  * It's easier to reason about: scheduled operations are always performed in the order they're
//!    queued so race conditions and similar issues due to out-of-order execution are both much rarer
//!    and easier to debug.
//!  * It makes it easier to write highly concurrent code: desync makes moving between performing
//!    operations synchronously and asynchronously trivial, with no need to deal with adding code to
//!    start threads or communicate between them.
//!
//! In addition to the two fundamental methods, desync provides methods for generating futures and
//! processing streams.
//!
//! # Quick start
//!
//! There is a single new synchronisation object: `Desync`. You create one like this:
//!
//! ```
//! use desync::Desync;
//! let number = Desync::new(0);
//! ```
//!
//! It supports two main operations. `desync` will schedule a new job for the object that will run
//! in a background thread. It's useful for deferring long-running operations and moving updates
//! so they can run in parallel.
//!
//! ```
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! let number = Desync::new(0);
//! number.desync(|val| {
//!     // Long update here
//!     thread::sleep(Duration::from_millis(100));
//!     *val = 42;
//! });
//!
//! // We can carry on what we're doing with the update now running in the background
//! ```
//!
//! The other operation is `sync`, which schedules a job to run synchronously on the data structure.
//! This is useful for retrieving values from a `Desync`.
//!
//! ```
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! # let number = Desync::new(0);
//! # number.desync(|val| {
//! #     // Long update here
//! #     thread::sleep(Duration::from_millis(100));
//! #     *val = 42;
//! # });
//! let new_number = number.sync(|val| *val);           // = 42
//! # assert!(new_number == 42);
//! ```
//!
//! `Desync` objects always run operations in the order that is provided, so all operations are
//! serialized from the point of view of the data that they contain. When combined with the ability
//! to perform operations asynchronously, this provides a useful way to immediately parallelize
//! long-running operations.
//!
//! The `future()` action returns a boxed Future that can be used with other libraries that use them. It's
//! conceptually the same as `sync`, except that it doesn't wait for the operation to complete:
//!
//! ```
//! # extern crate futures;
//! # extern crate desync;
//! # fn main() {
//! # use desync::Desync;
//! # use std::thread;
//! # use std::time::*;
//! # use futures::executor;
//! # use futures::future;
//! # let number = Desync::new(0);
//! # number.desync(|val| {
//! #     // Long update here
//! #     thread::sleep(Duration::from_millis(100));
//! #     *val = 42;
//! # });
//! let future_number = number.future(|val| future::ready(*val));
//! assert!(executor::block_on(async { future_number.await.unwrap() }) == 42 );
//! # }
//! ```
//!
//! Note that this is the equivalent of just `number.sync(|val| *val)`, so this is mainly useful for
//! interacting with other code that's already using futures. The `after()` function is also provided
//! for using the results of futures to update the contents of `Desync` data: these all preserve the
//! strict order-of-operations semantics, so operations scheduled after an `after` won't start until
//! that operation has completed.
//!
//! # Pipes and streams
//!
//! As well as support for futures, Desync provides supports for streams. The `pipe_in()` and `pipe()`
//! functions provide a way to process stream data in a desync object as it arrives. `pipe_in()` just
//! processes stream data as it arrives, and `pipe()` provides an output stream of data.
//!
//! `pipe()` is quite useful as a way to provide asynchronous access to synchronous code: it can be used
//! to create a channel to send requests to an asynchronous target and retrieve results back via its
//! output. (Unlike this 'traditional' method, the actual scheduling and channel maintenance does not
//! need to be explicitly implemented)
//!

#![warn(bare_trait_objects)]

#[macro_use]
extern crate lazy_static;
extern crate futures;

#[cfg(not(target_arch = "wasm32"))]
extern crate num_cpus;

pub mod scheduler;
pub mod desync;
pub mod pipe;

mod job;
mod future_job;
mod unsafe_job;
mod scheduler_thread;

pub use self::desync::*;
pub use self::pipe::*;
<|endoftext|>


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

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod hex;
pub mod sign;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<commit_msg>add top-level doc ref for server<commit_after>// Copyright 2017 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
//! This documentation is for working with Roughtime protocol details. Docs for the
//! **server** [are here](../server/index.html).
//!

extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod hex;
pub mod sign;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<|endoftext|>


<commit_before>extern crate libc;
extern crate pocketsphinx_sys as bindings;

use std::ptr;
use std::ffi::{CStr, CString};
use libc::c_char;

pub use search::*;
pub use nbest::*;
pub use jsgf::*;
pub use error::*;

mod search;
mod nbest;
mod jsgf;
mod error;

pub struct CmdLn {
    raw: *mut bindings::cmd_ln_t,
}

impl CmdLn {
    pub fn init(strict: bool, args: &[&str]) -> Result<Self> {
        // Sphinx assumes that `args` are valid as long as returned
        // `cmd_ln_t` is alive, so copy them.
        let c_args: Vec<_> = args.iter().map(|s| CString::new(*s).unwrap()).collect();
        let args_ptrs: Vec<_> = c_args.iter().map(|s| s.as_ptr()).collect();
        let raw = unsafe {
            bindings::cmd_ln_parse_r(ptr::null_mut(),
                                     bindings::ps_args(),
                                     args_ptrs.len() as i32,
                                     args_ptrs.as_ptr(),
                                     strict as i32)
        };
        if raw.is_null() {
            return Err(Error);
        }
        Ok(CmdLn{raw: raw})
    }

    pub unsafe fn get_str(&self, name: &str) -> &str {
        let c_str = bindings::cmd_ln_str_r(self.raw, CString::new(name).unwrap().as_ptr());
        CStr::from_ptr(c_str).to_str().unwrap()
    }

    pub unsafe fn get_int(&self, name: &str) -> i64 {
        bindings::cmd_ln_int_r(self.raw, CString::new(name).unwrap().as_ptr())
    }

    pub unsafe fn get_float(&self, name: &str) -> f64 {
        bindings::cmd_ln_float_r(self.raw, CString::new(name).unwrap().as_ptr())
    }

    pub fn exists(&self, name: &str) -> bool {
        let res = unsafe { bindings::cmd_ln_exists_r(self.raw, CString::new(name).unwrap().as_ptr()) };
        res != 0
    }

    pub unsafe fn get_boolean(&self, name: &str) -> bool {
        self.get_int(name) != 0
    }

    pub unsafe fn get_int32(&self, name: &str) -> i32 {
        self.get_int(name) as i32
    }

    pub unsafe fn get_float32(&self, name: &str) -> f32 {
        self.get_float(name) as f32
    }

    pub unsafe fn get_float64(&self, name: &str) -> f64 {
        self.get_float(name) as f64
    }
}

impl Drop for CmdLn {
    fn drop(&mut self) {
        if !self.raw.is_null() {
            let ref_count = unsafe { bindings::cmd_ln_free_r(self.raw) };
            assert!(ref_count == 0);
        }
    }
}

pub struct PsDecoder {
    raw: *mut bindings::ps_decoder_t,
    #[allow(dead_code)]
    config: CmdLn,
}

impl PsDecoder {
    pub fn init(config: CmdLn) -> Self {
        let raw = unsafe { bindings::ps_init(config.raw) };
        assert!(!raw.is_null());
        PsDecoder{raw: raw, config: config}
    }

    pub fn start_utt(&self, utt_id: Option<&str>) -> Result<()>  {
        let (_id_cstr, id_ptr) = utt_id.map_or_else(
            ||  { (CString::new("").unwrap(), ptr::null()) },
            |s| {
                let cstr = CString::new(s).unwrap();
                let cptr = cstr.as_ptr();
                (cstr, cptr)
            }
        );
        let code = unsafe { bindings::ps_start_utt(self.raw, id_ptr) };
        if code == 0 { Ok(()) } else { Err(Error) }
    }

    pub fn process_raw(&self,
                       data: &[i16],
                       no_search: bool,
                       full_utt: bool) -> Result<i32> {
        let frames = unsafe {
            bindings::ps_process_raw(self.raw, data.as_ptr(), data.len(),
                                     no_search as i32, full_utt as i32)
        };
        if frames < 0 { return Err(Error); }
        Ok(frames)
    }

    pub fn end_utt(&self) -> Result<()> {
        let code = unsafe { bindings::ps_end_utt(self.raw) };
        if code < 0 { return Err(Error); }
        Ok(())
    }

    pub fn get_hyp(&self) -> Option<(String, Option<String>, i32)> {
        let mut score: i32 = 0;
        let mut c_utt_id: *const c_char = ptr::null();
        let c_hyp = unsafe { bindings::ps_get_hyp(self.raw, &mut score, &mut c_utt_id) };
        if c_hyp.is_null() { return None; }

        let hyp = unsafe { CStr::from_ptr(c_hyp) }.to_string_lossy().into_owned();
        let utt_id = if c_utt_id.is_null() {
            None
        } else {
            Some(unsafe { CStr::from_ptr(c_utt_id) }.to_string_lossy().into_owned())
        };
        Some((hyp, utt_id, score))
    }

    pub fn get_in_speech(&self) -> bool {
        let res = unsafe { bindings::ps_get_in_speech(self.raw) };
        res == 1
    }

    pub fn get_prob(&self) -> i32 {
        unsafe { bindings::ps_get_prob(self.raw) }
    }

    pub fn get_n_frames(&self) -> i32 {
        unsafe { bindings::ps_get_n_frames(self.raw) }
    }

    pub fn nbest(&self, start_frame: i32, end_frame: i32,
                 ctx1: Option<&str>, ctx2: Option<&str>) -> NBestIter {
        let c_ctx1 = ctx1.map(|s| CString::new(s).unwrap());
        let c_ctx2 = ctx2.map(|s| CString::new(s).unwrap());
        let raw_nbest = unsafe {
            bindings::ps_nbest(self.raw, start_frame, end_frame,
                               c_ctx1.map_or(ptr::null(), |c| c.as_ptr()),
                               c_ctx2.map_or(ptr::null(), |c| c.as_ptr()))
        };
        NBestIter::new(raw_nbest)
    }

    pub fn nbest_simple(&self) -> NBestIter {
        self.nbest(0, -1, None, None)
    }

    pub fn seg_iter(&self) -> SegIter {
        let mut best_score: i32 = 0;
        SegIter::new(unsafe { bindings::ps_seg_iter(self.raw, &mut best_score) })
    }

    pub fn searches(&self) -> Searches {
        Searches::new(self.raw)
    }
}

impl Drop for PsDecoder {
    fn drop(&mut self) {
        let ref_count = unsafe { bindings::ps_free(self.raw) };
        assert!(ref_count == 0);
    }
}
<commit_msg>memory leak fix: remove unneeded config field, ignore refcount in drop<commit_after>extern crate libc;
extern crate pocketsphinx_sys as bindings;

use std::ptr;
use std::ffi::{CStr, CString};
use libc::c_char;

pub use search::*;
pub use nbest::*;
pub use jsgf::*;
pub use error::*;

mod search;
mod nbest;
mod jsgf;
mod error;

pub struct CmdLn {
    raw: *mut bindings::cmd_ln_t,
}

impl CmdLn {
    pub fn init(strict: bool, args: &[&str]) -> Result<Self> {
        // Sphinx assumes that `args` are valid as long as returned
        // `cmd_ln_t` is alive, so copy them.
        let c_args: Vec<_> = args.iter().map(|s| CString::new(*s).unwrap()).collect();
        let args_ptrs: Vec<_> = c_args.iter().map(|s| s.as_ptr()).collect();
        let raw = unsafe {
            bindings::cmd_ln_parse_r(ptr::null_mut(),
                                     bindings::ps_args(),
                                     args_ptrs.len() as i32,
                                     args_ptrs.as_ptr(),
                                     strict as i32)
        };
        if raw.is_null() {
            return Err(Error);
        }
        Ok(CmdLn{raw: raw})
    }

    pub unsafe fn get_str(&self, name: &str) -> &str {
        let c_str = bindings::cmd_ln_str_r(self.raw, CString::new(name).unwrap().as_ptr());
        CStr::from_ptr(c_str).to_str().unwrap()
    }

    pub unsafe fn get_int(&self, name: &str) -> i64 {
        bindings::cmd_ln_int_r(self.raw, CString::new(name).unwrap().as_ptr())
    }

    pub unsafe fn get_float(&self, name: &str) -> f64 {
        bindings::cmd_ln_float_r(self.raw, CString::new(name).unwrap().as_ptr())
    }

    pub fn exists(&self, name: &str) -> bool {
        let res = unsafe { bindings::cmd_ln_exists_r(self.raw, CString::new(name).unwrap().as_ptr()) };
        res != 0
    }

    pub unsafe fn get_boolean(&self, name: &str) -> bool {
        self.get_int(name) != 0
    }

    pub unsafe fn get_int32(&self, name: &str) -> i32 {
        self.get_int(name) as i32
    }

    pub unsafe fn get_float32(&self, name: &str) -> f32 {
        self.get_float(name) as f32
    }

    pub unsafe fn get_float64(&self, name: &str) -> f64 {
        self.get_float(name) as f64
    }
}

impl Drop for CmdLn {
    fn drop(&mut self) {
        if !self.raw.is_null() {
            unsafe { bindings::cmd_ln_free_r(self.raw) };
        }
    }
}

pub struct PsDecoder {
    raw: *mut bindings::ps_decoder_t,
}

impl PsDecoder {
    pub fn init(config: CmdLn) -> Self {
        let raw = unsafe { bindings::ps_init(config.raw) };
        assert!(!raw.is_null());
        PsDecoder{raw: raw}
    }

    pub fn start_utt(&self, utt_id: Option<&str>) -> Result<()>  {
        let (_id_cstr, id_ptr) = utt_id.map_or_else(
            ||  { (CString::new("").unwrap(), ptr::null()) },
            |s| {
                let cstr = CString::new(s).unwrap();
                let cptr = cstr.as_ptr();
                (cstr, cptr)
            }
        );
        let code = unsafe { bindings::ps_start_utt(self.raw, id_ptr) };
        if code == 0 { Ok(()) } else { Err(Error) }
    }

    pub fn process_raw(&self,
                       data: &[i16],
                       no_search: bool,
                       full_utt: bool) -> Result<i32> {
        let frames = unsafe {
            bindings::ps_process_raw(self.raw, data.as_ptr(), data.len(),
                                     no_search as i32, full_utt as i32)
        };
        if frames < 0 { return Err(Error); }
        Ok(frames)
    }

    pub fn end_utt(&self) -> Result<()> {
        let code = unsafe { bindings::ps_end_utt(self.raw) };
        if code < 0 { return Err(Error); }
        Ok(())
    }

    pub fn get_hyp(&self) -> Option<(String, Option<String>, i32)> {
        let mut score: i32 = 0;
        let mut c_utt_id: *const c_char = ptr::null();
        let c_hyp = unsafe { bindings::ps_get_hyp(self.raw, &mut score, &mut c_utt_id) };
        if c_hyp.is_null() { return None; }

        let hyp = unsafe { CStr::from_ptr(c_hyp) }.to_string_lossy().into_owned();
        let utt_id = if c_utt_id.is_null() {
            None
        } else {
            Some(unsafe { CStr::from_ptr(c_utt_id) }.to_string_lossy().into_owned())
        };
        Some((hyp, utt_id, score))
    }

    pub fn get_in_speech(&self) -> bool {
        let res = unsafe { bindings::ps_get_in_speech(self.raw) };
        res == 1
    }

    pub fn get_prob(&self) -> i32 {
        unsafe { bindings::ps_get_prob(self.raw) }
    }

    pub fn get_n_frames(&self) -> i32 {
        unsafe { bindings::ps_get_n_frames(self.raw) }
    }

    pub fn nbest(&self, start_frame: i32, end_frame: i32,
                 ctx1: Option<&str>, ctx2: Option<&str>) -> NBestIter {
        let c_ctx1 = ctx1.map(|s| CString::new(s).unwrap());
        let c_ctx2 = ctx2.map(|s| CString::new(s).unwrap());
        let raw_nbest = unsafe {
            bindings::ps_nbest(self.raw, start_frame, end_frame,
                               c_ctx1.map_or(ptr::null(), |c| c.as_ptr()),
                               c_ctx2.map_or(ptr::null(), |c| c.as_ptr()))
        };
        NBestIter::new(raw_nbest)
    }

    pub fn nbest_simple(&self) -> NBestIter {
        self.nbest(0, -1, None, None)
    }

    pub fn seg_iter(&self) -> SegIter {
        let mut best_score: i32 = 0;
        SegIter::new(unsafe { bindings::ps_seg_iter(self.raw, &mut best_score) })
    }

    pub fn searches(&self) -> Searches {
        Searches::new(self.raw)
    }
}

impl Drop for PsDecoder {
    fn drop(&mut self) {
        let ref_count = unsafe { bindings::ps_free(self.raw) };
        assert!(ref_count == 0);
    }
}
<|endoftext|>