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

use libc::{c_long, c_ulong, c_char};
use libc;

use std::mem;

pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type Ivar = libc::intptr_t;
pub type SEL = libc::intptr_t;
#[allow(non_camel_case_types)]
pub type id = libc::intptr_t;

#[cfg(target_word_size = "32")]
pub type NSInteger = libc::c_int;
#[cfg(target_word_size = "32")]
pub type NSUInteger = libc::c_uint;

#[cfg(target_word_size = "64")]
pub type NSInteger = libc::c_long;
#[cfg(target_word_size = "64")]
pub type NSUInteger = libc::c_ulong;

#[allow(non_upper_case_globals)]
pub const nil: id = 0;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *const libc::c_char) -> bool;
    pub fn class_addIvar(cls: Class,
                         name: *const libc::c_char,
                         size: libc::size_t,
                         alignment: u8,
                         types: *const libc::c_char)
                         -> bool;
    pub fn object_setInstanceVariable(obj: id, name: *const libc::c_char, value: *mut libc::c_void);
    pub fn object_getInstanceVariable(obj: id, name: *const libc::c_char, outValue: *mut *mut libc::c_void);
    pub fn objc_allocateClassPair(superclass: Class, name: *const libc::c_char, extraBytes: libc::size_t)
                                  -> Class;
    pub fn objc_getClass(name: *const libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver: id, theSelector: SEL, ...) -> id;
    pub fn objc_msgSend_stret(theReceiver: id, theSelector: SEL, ...);
    pub fn objc_registerClassPair(cls: Class);
    pub fn sel_registerName(name: *const libc::c_char) -> SEL;
}

/// Returns an Objective-C message send function that returns a type `T`.
pub unsafe fn msg_send<T>() -> extern fn(theReceiver: id, theSelector: SEL, ...) -> T {
    mem::transmute(objc_msgSend)
}

pub unsafe fn msg_send_stret<T>() -> extern fn(theReceiver: id, theSelector: SEL, ...) -> T {
    mem::transmute(objc_msgSend_stret)
}

/// A convenience method to convert the name of a class to the class object itself.
#[inline]
pub fn class(name: &str) -> id {
    unsafe {
        objc_getClass(name.to_c_str().as_ptr())
    }
}

/// A convenience method to convert the name of a selector to the selector object.
#[inline]
pub fn selector(name: &str) -> SEL {
    unsafe {
        sel_registerName(name.to_c_str().as_ptr())
    }
}

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

    #[test]
    pub fn test_nsapp() {
        unsafe {
            let _nsApp: id = msg_send()(class("NSApplication"), selector("sharedApplication"));
        }
    }

    #[test]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this: id, _: SEL) -> id {
            println!("doSomething");
            return this;
        }

        let ns_object = class("NSObject");
        let my_object = unsafe {
            objc_allocateClassPair(ns_object, "MyObject".to_c_str().as_ptr(), 0 as libc::size_t)
        };
        unsafe {
            let doSomething = selector("doSomething");
            let _ = class_addMethod(my_object, doSomething, MyObject_doSomething, "@@:".to_c_str().as_ptr());

            objc_registerClassPair(my_object);

            let mut obj: id = msg_send()(my_object, selector("alloc"));
            obj = msg_send()(obj, selector("init"));
            let _: () = msg_send()(obj, selector("doSomething"));
        }
    }
}
<commit_msg>Fix dangling pointer with `to_c_str().as_mut_ptr()`<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc::{c_long, c_ulong, c_char};
use libc;

use std::mem;

pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type Ivar = libc::intptr_t;
pub type SEL = libc::intptr_t;
#[allow(non_camel_case_types)]
pub type id = libc::intptr_t;

#[cfg(target_word_size = "32")]
pub type NSInteger = libc::c_int;
#[cfg(target_word_size = "32")]
pub type NSUInteger = libc::c_uint;

#[cfg(target_word_size = "64")]
pub type NSInteger = libc::c_long;
#[cfg(target_word_size = "64")]
pub type NSUInteger = libc::c_ulong;

#[allow(non_upper_case_globals)]
pub const nil: id = 0;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *const libc::c_char) -> bool;
    pub fn class_addIvar(cls: Class,
                         name: *const libc::c_char,
                         size: libc::size_t,
                         alignment: u8,
                         types: *const libc::c_char)
                         -> bool;
    pub fn object_setInstanceVariable(obj: id, name: *const libc::c_char, value: *mut libc::c_void);
    pub fn object_getInstanceVariable(obj: id, name: *const libc::c_char, outValue: *mut *mut libc::c_void);
    pub fn objc_allocateClassPair(superclass: Class, name: *const libc::c_char, extraBytes: libc::size_t)
                                  -> Class;
    pub fn objc_getClass(name: *const libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver: id, theSelector: SEL, ...) -> id;
    pub fn objc_msgSend_stret(theReceiver: id, theSelector: SEL, ...);
    pub fn objc_registerClassPair(cls: Class);
    pub fn sel_registerName(name: *const libc::c_char) -> SEL;
}

/// Returns an Objective-C message send function that returns a type `T`.
pub unsafe fn msg_send<T>() -> extern fn(theReceiver: id, theSelector: SEL, ...) -> T {
    mem::transmute(objc_msgSend)
}

pub unsafe fn msg_send_stret<T>() -> extern fn(theReceiver: id, theSelector: SEL, ...) -> T {
    mem::transmute(objc_msgSend_stret)
}

/// A convenience method to convert the name of a class to the class object itself.
#[inline]
pub fn class(name: &str) -> id {
    let name_c_str = name.to_c_str();
    unsafe {
        objc_getClass(name_c_str.as_ptr())
    }
}

/// A convenience method to convert the name of a selector to the selector object.
#[inline]
pub fn selector(name: &str) -> SEL {
    let name_c_str = name.to_c_str();
    unsafe {
        sel_registerName(name_c_str.as_ptr())
    }
}

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

    #[test]
    pub fn test_nsapp() {
        unsafe {
            let _nsApp: id = msg_send()(class("NSApplication"), selector("sharedApplication"));
        }
    }

    #[test]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this: id, _: SEL) -> id {
            println!("doSomething");
            return this;
        }

        let ns_object = class("NSObject");
        let name_c_str = "MyObject".to_c_str();
        let my_object = unsafe {
            objc_allocateClassPair(ns_object, name_c_str.as_ptr(), 0 as libc::size_t)
        };

        let doSomething = selector("doSomething");
        let types_c_str = "@@:".to_c_str();
        unsafe {
            let _ = class_addMethod(my_object, doSomething, MyObject_doSomething,
                                    types_c_str.as_ptr());

            objc_registerClassPair(my_object);

            let mut obj: id = msg_send()(my_object, selector("alloc"));
            obj = msg_send()(obj, selector("init"));
            let _: () = msg_send()(obj, selector("doSomething"));
        }
    }
}
<|endoftext|>


<commit_before>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<screen::Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    handle_input(screens, &input, &window, &mut self.context);
                    if screens.is_empty() {
                        // No screens - exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<screen::Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) {
    for action in last(screens).on_input(&input, &window, context) {
        match action {
            screen::InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            screen::InputResult::PopScreen => {
                screens.pop();
            }
            // TODO: Handle event correctly.
            // TODO: Use screen::InputResult.
            screen::InputResult::Exit => {}
        }
    }
}
<commit_msg>screen namespace<commit_after>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    //handle_input(screens, &input, &window, &mut self.context);
                    if screens.is_empty() {
                        // No screens - exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) {
    for action in last(screens).on_input(&input, &window, context) {
        match action {
            screen::InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            screen::InputResult::PopScreen => {
                screens.pop();
            }
            // TODO: Handle event correctly.
            // TODO: Use screen::InputResult.
            screen::InputResult::Exit => {}
        }
    }
}
<|endoftext|>


<commit_before>// This module provides the main structures and mechanics of the game

/// There are two players playing the match: Light and Dark
#[derive(Clone, Copy, PartialEq)]
pub enum Player {
    Light,
    Dark,
}

impl Player {
    /// Get the player of the opposite kind to self
    fn opposite(&self) -> Player {
        match *self {
            Player::Light => {
                Player::Dark
                    }
            Player::Dark => {
                Player::Light
            }
        }
    }
}

/// A game can be in two status: either running (with a next player to play) or ended.
#[derive(Clone)]
pub enum Status {
    Running { next_player: Player },
    Ended,
}

/// Each cell in the board can either be empty or taken by one of the players.
#[derive(Clone, Copy)]
pub enum Cell {
    Empty,
    Taken { player: Player },
}

/// There are eight cardinal directions
const DIRECTIONS: usize = 8;

/// An array listing all the cardinal directions, represented by the coordinate delta to move in that direction
/// Example: if I am in cell (4, 5) and move NE, I go to cell (4, 5) + (1, -1) = (5, 4)
const DIRECTION: [(i8, i8); DIRECTIONS] = [
    ( 0, -1), //North
    ( 1, -1), //NE
    ( 1,  0), //East
    ( 1,  1), //SE
    ( 0,  1), //South
    (-1,  1), //SW
    (-1,  0), //West
    (-1, -1), //NW
    ];

/// The size of the board is a constant.
pub const BOARD_SIZE: usize = 8;

/// The board is given by a matrix of cells of size BOARD_SIZE and by which player has to move next.
#[derive(Clone)]
pub struct Game {
    board: [[Cell; BOARD_SIZE]; BOARD_SIZE],
    status: Status,
}

impl Game {
    /// Initializing a new game: starting positions on the board and Dark is the first to play
    pub fn new() -> Game {
        let mut board = [[Cell::Empty; BOARD_SIZE]; BOARD_SIZE];
        board[3][3] = Cell::Taken { player: Player::Light };
        board[4][4] = Cell::Taken { player: Player::Light };
        board[3][4] = Cell::Taken { player: Player::Dark };
        board[4][3] = Cell::Taken { player: Player::Dark };

        Game {
            board: board,
            status: Status::Running { next_player: Player::Dark },
        }
    }

    /// Return the game's board
    pub fn get_board(&self) -> [[Cell; BOARD_SIZE]; BOARD_SIZE] {
        self.board
    }

    /// Return the game's status
    pub fn get_status(&self) -> Status {
        self.status.clone()
    }

    /// Check that a given move is legal
    pub fn check_move (&self, (row, col): (usize, usize)) -> bool {

        // If the given coordinate falls out of the board or in a taken cell, the move cannot be legal
        if row >= BOARD_SIZE || col >= BOARD_SIZE {
            return false;
        } else if let Cell::Taken { player: _ } = self.board[row][col] {
            return false;
        }

        // If a move leads to eat in at least one direction, then it is legal
        for dir in DIRECTION.iter() {
            if self.check_move_along_direction((row, col), *dir) {
                return true;
            }
        }

        false
    }

    // Check whether a move leads to eat in a specified direction
    // Does NOT perform checks already performed by check_move!
    //#[inline]
    fn check_move_along_direction (&self, (row, col): (usize, usize), (delta_ns, delta_ew): (i8, i8)) -> bool {

        // Need at least two cells' space in the given direction
        let mut col_i8: i8 = col as i8 + 2*delta_ew;
        if ( col_i8 < 0 ) || ( col_i8 >= BOARD_SIZE as i8 ) {
                return false;
        }

        let mut row_i8: i8 = row as i8 + 2*delta_ns;
        if ( row_i8 < 0 ) || ( row_i8 >= BOARD_SIZE as i8 ) {
                return false;
        }

        if let Status::Running { next_player } = self.status {

            // Next cell has to be owned by the other player
            if let Cell::Taken { player } = self.board[ ( row as i8 + delta_ns ) as usize ][ ( col as i8 + delta_ew ) as usize] {
                if player == next_player {
                    return false;
                }

                while let Cell::Taken { player } = self.board[ row_i8 as usize ][ col_i8 as usize] {
                    if player == next_player {
                        return true;
                    }

                    col_i8 += delta_ew;
                    if ( col_i8 < 0 ) || ( col_i8 >= BOARD_SIZE as i8 ) {
                            return false;
                    }

                    row_i8 += delta_ns;
                    if ( row_i8 < 0 ) || ( row_i8 >= BOARD_SIZE as i8 ) {
                            return false;
                    }

                }
            }
        }

        false
    }

    // Eats all of the opponent's occupied cells from a specified cell (given by its coordinates) in a specified direction
    // until it finds a cell of the current player
    // WARNING: this function do NOT perform any check about whether or not the move is legal
    fn eat_along_direction (&mut self, (row, col): (usize, usize), (delta_ns, delta_ew): (i8, i8)) {

        if let Status::Running { next_player } = self.status {

            self.board[ ( row as i8 + delta_ns ) as usize ][ ( col as i8 + delta_ew ) as usize] = Cell::Taken { player: next_player };

            let (mut row_i8, mut col_i8): (i8, i8) = (row as i8 + 2*delta_ns, col as i8 + 2*delta_ew);

            while let Cell::Taken { player: player_in_cell } = self.board[ row_i8 as usize ][ col_i8 as usize] {
                if next_player == player_in_cell {
                    break;
                }

                self.board[ row_i8 as usize ][ col_i8 as usize ] = Cell::Taken { player: next_player };

                row_i8 += delta_ns;
                col_i8 += delta_ew;
            }
        }
    }

    // Current player perform a move, after verifying that it is legal
    pub fn make_move (&mut self, (row, col): (usize, usize)) -> &Game {

        if row >= BOARD_SIZE || col >= BOARD_SIZE {
            return self;
        } else if let Cell::Taken { player: _ } = self.board[row][col] {
            return self;
        }

        let mut legal: bool = false;

        for dir in DIRECTION.iter() {
            if self.check_move_along_direction((row, col), *dir) {
                self.eat_along_direction((row, col), *dir);
                if !legal {
                    legal = true;
                }
            }
        }

        // If a move is legal, the next player to play has to be determined
        // If the opposite player can make any move at all, it gets the turn
        // If not, if the previous player can make any move at all, it gets the turn
        // If not (that is, if no player can make any move at all) the game is ended
        if legal {
            if let Status::Running { next_player } = self.status {
                self.board[row][col] = Cell::Taken { player: next_player };

                self.status = Status::Running { next_player: next_player.opposite() };
                if self.can_move() {
                    return self;
                }

                self.status = Status::Running { next_player: next_player };
                if self.can_move() {
                    return self;
                }

                self.status = Status::Ended;
                return self;
            }
        }

        self
    }

    // Return whether or not next_player can make any move at all
    fn can_move(&self) -> bool {

        for (row_n, row) in self.board.iter().enumerate() {
            for (col_n, _cell) in row.iter().enumerate() {
               if self.check_move((row_n, col_n)) {
                    return true;
                }
            }
        }
        false

    }

    // Return the current score of the match
    pub fn get_score(&self) -> (u8, u8) {
        let (mut score_light, mut score_dark): (u8, u8) = (0, 0);

        for row in self.board.iter() {
            for cell in row.iter() {
                match *cell {
                    Cell::Taken { player: Player::Light } => score_light += 1,
                    Cell::Taken { player: Player::Dark } => score_dark += 1,
                    _ => {},
                }
            }
        }

        (score_light, score_dark)
    }

    // Return the difference in score between Light and Dark, in a time-efficient way
    pub fn get_score_diff(&self) -> i16 {
        let mut score: i16 = 0;

        for row in self.board.iter() {
            for cell in row.iter() {
                match *cell {
                    Cell::Taken { player: Player::Light } => score += 1,
                    Cell::Taken { player: Player::Dark } => score -= 1,
                    _ => {},
                }
            }
        }

        score
    }

    pub fn get_turn(&self) -> u8 {
        let mut turn: u8 = 0;

        for row in self.board.iter() {
            for cell in row.iter() {
                if let Cell::Taken { player: _ } =  *cell {
                    turn += 1;
                }
            }
        }
        turn
    }

    pub fn get_cell(&self, (row, col): (usize, usize)) -> Cell {
        self.board[row][col]
    }

}
<commit_msg>Tracking score: performance improvement<commit_after>// This module provides the main structures and mechanics of the game

/// There are two players playing the match: Light and Dark
#[derive(Clone, Copy, PartialEq)]
pub enum Player {
    Light,
    Dark,
}

impl Player {
    /// Get the player of the opposite kind to self
    fn opposite(&self) -> Player {
        match *self {
            Player::Light => {
                Player::Dark
                    }
            Player::Dark => {
                Player::Light
            }
        }
    }
}

/// A game can be in two status: either running (with a next player to play) or ended.
#[derive(Clone)]
pub enum Status {
    Running { next_player: Player },
    Ended,
}

/// Each cell in the board can either be empty or taken by one of the players.
#[derive(Clone, Copy)]
pub enum Cell {
    Empty,
    Taken { player: Player },
}

/// There are eight cardinal directions
const DIRECTIONS: usize = 8;

/// An array listing all the cardinal directions, represented by the coordinate delta to move in that direction
/// Example: if I am in cell (4, 5) and move NE, I go to cell (4, 5) + (1, -1) = (5, 4)
const DIRECTION: [(i8, i8); DIRECTIONS] = [
    ( 0, -1), //North
    ( 1, -1), //NE
    ( 1,  0), //East
    ( 1,  1), //SE
    ( 0,  1), //South
    (-1,  1), //SW
    (-1,  0), //West
    (-1, -1), //NW
    ];

/// The size of the board is a constant.
pub const BOARD_SIZE: usize = 8;

/// The board is given by a matrix of cells of size BOARD_SIZE and by which player has to move next.
#[derive(Clone)]
pub struct Game {
    board: [[Cell; BOARD_SIZE]; BOARD_SIZE],
    status: Status,
    score_light: u8,
    score_dark: u8,
}

impl Game {
    /// Initializing a new game: starting positions on the board and Dark is the first to play
    pub fn new() -> Game {
        let mut board = [[Cell::Empty; BOARD_SIZE]; BOARD_SIZE];
        board[3][3] = Cell::Taken { player: Player::Light };
        board[4][4] = Cell::Taken { player: Player::Light };
        board[3][4] = Cell::Taken { player: Player::Dark };
        board[4][3] = Cell::Taken { player: Player::Dark };

        Game {
            board: board,
            status: Status::Running { next_player: Player::Dark },
            score_light: 2,
            score_dark: 2,
        }
    }

    /// Return the game's board
    pub fn get_board(&self) -> [[Cell; BOARD_SIZE]; BOARD_SIZE] {
        self.board
    }

    /// Return the game's status
    pub fn get_status(&self) -> Status {
        self.status.clone()
    }

    /// Check that a given move is legal
    pub fn check_move (&self, (row, col): (usize, usize)) -> bool {

        // If the given coordinate falls out of the board or in a taken cell, the move cannot be legal
        if row >= BOARD_SIZE || col >= BOARD_SIZE {
            return false;
        } else if let Cell::Taken { player: _ } = self.board[row][col] {
            return false;
        }

        // If a move leads to eat in at least one direction, then it is legal
        for dir in &DIRECTION {
            if self.check_move_along_direction((row, col), *dir) {
                return true;
            }
        }

        false
    }

    // Check whether a move leads to eat in a specified direction
    // Does NOT perform checks already performed by check_move!
    //#[inline]
    fn check_move_along_direction (&self, (row, col): (usize, usize), (delta_ns, delta_ew): (i8, i8)) -> bool {

        // Need at least two cells' space in the given direction
        let mut col_i8: i8 = col as i8 + 2*delta_ew;
        if ( col_i8 < 0 ) || ( col_i8 >= BOARD_SIZE as i8 ) {
                return false;
        }

        let mut row_i8: i8 = row as i8 + 2*delta_ns;
        if ( row_i8 < 0 ) || ( row_i8 >= BOARD_SIZE as i8 ) {
                return false;
        }

        if let Status::Running { next_player } = self.status {

            // Next cell has to be owned by the other player
            if let Cell::Taken { player } = self.board[ ( row as i8 + delta_ns ) as usize ][ ( col as i8 + delta_ew ) as usize] {
                if player == next_player {
                    return false;
                }

                while let Cell::Taken { player } = self.board[ row_i8 as usize ][ col_i8 as usize] {
                    if player == next_player {
                        return true;
                    }

                    col_i8 += delta_ew;
                    if ( col_i8 < 0 ) || ( col_i8 >= BOARD_SIZE as i8 ) {
                            return false;
                    }

                    row_i8 += delta_ns;
                    if ( row_i8 < 0 ) || ( row_i8 >= BOARD_SIZE as i8 ) {
                            return false;
                    }

                }
            }
        }

        false
    }

    // Eats all of the opponent's occupied cells from a specified cell (given by its coordinates) in a specified direction
    // until it finds a cell of the current player
    // WARNING: this function do NOT perform any check about whether or not the move is legal
    fn eat_along_direction (&mut self, (row, col): (usize, usize), (delta_ns, delta_ew): (i8, i8)) {

        if let Status::Running { next_player } = self.status {

            self.board[ ( row as i8 + delta_ns ) as usize ][ ( col as i8 + delta_ew ) as usize] = Cell::Taken { player: next_player };

            let (mut row_i8, mut col_i8): (i8, i8) = (row as i8 + 2*delta_ns, col as i8 + 2*delta_ew);

            let mut eating: u8 = 1;

            while let Cell::Taken { player: player_in_cell } = self.board[ row_i8 as usize ][ col_i8 as usize] {
                if next_player == player_in_cell {
                    break;
                }

                self.board[ row_i8 as usize ][ col_i8 as usize ] = Cell::Taken { player: next_player };

                eating += 1;
                row_i8 += delta_ns;
                col_i8 += delta_ew;
            }

            match next_player {
                Player::Light => {
                    self.score_light += eating;
                    self.score_dark -= eating;
                }
                Player::Dark => {
                    self.score_light -= eating;
                    self.score_dark += eating;
                }
            }
        }
    }

    // Current player perform a move, after verifying that it is legal
    pub fn make_move (&mut self, (row, col): (usize, usize)) -> &Game {

        if row >= BOARD_SIZE || col >= BOARD_SIZE {
            return self;
        } else if let Cell::Taken { player: _ } = self.board[row][col] {
            return self;
        }

        let mut legal: bool = false;

        for dir in &DIRECTION {
            if self.check_move_along_direction((row, col), *dir) {
                self.eat_along_direction((row, col), *dir);
                if !legal {
                    legal = true;
                }
            }
        }

        // If a move is legal, the next player to play has to be determined
        // If the opposite player can make any move at all, it gets the turn
        // If not, if the previous player can make any move at all, it gets the turn
        // If not (that is, if no player can make any move at all) the game is ended
        if legal {
            if let Status::Running { next_player } = self.status {
                self.board[row][col] = Cell::Taken { player: next_player };

                match next_player {
                    Player::Light => self.score_light += 1,
                    Player::Dark => self.score_dark += 1,
                }

                self.status = Status::Running { next_player: next_player.opposite() };
                if self.can_move() {
                    return self;
                }

                self.status = Status::Running { next_player: next_player };
                if self.can_move() {
                    return self;
                }

                self.status = Status::Ended;
                return self;
            }
        }

        self
    }

    // Return whether or not next_player can make any move at all
    fn can_move(&self) -> bool {

        for (row_n, row) in self.board.iter().enumerate() {
            for (col_n, _cell) in row.iter().enumerate() {
               if self.check_move((row_n, col_n)) {
                    return true;
                }
            }
        }
        false
    }

    // Return the current score of the match
    pub fn get_score(&self) -> (u8, u8) {
        (self.score_light, self.score_dark)
    }

    // Return the difference in score between Light and Dark
    pub fn get_score_diff(&self) -> i16 {
        self.score_light as i16 - self.score_dark as i16
    }

    // Return how many cells are taken on the board
    pub fn get_turn(&self) -> u8 {
        self.score_light + self.score_dark
    }

    // Return a cell given its coordinates
    pub fn get_cell(&self, (row, col): (usize, usize)) -> Cell {
        self.board[row][col]
    }

}
<|endoftext|>


<commit_before>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct ImplGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct TyGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `TyGenerics::as_turbofish`.
#[derive(Debug)]
pub struct Turbofish<'a>(&'a Generics);

#[cfg(feature = "printing")]
impl Generics {
    /// Split a type's generics into the pieces required for impl'ing a trait
    /// for that type.
    ///
    /// ```
    /// # extern crate syn;
    /// # #[macro_use]
    /// # extern crate quote;
    /// # fn main() {
    /// # let generics: syn::Generics = Default::default();
    /// # let name = syn::Ident::new("MyType");
    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    /// quote! {
    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
    ///         // ...
    ///     }
    /// }
    /// # ;
    /// # }
    /// ```
    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
    }
}

#[cfg(feature = "printing")]
impl<'a> TyGenerics<'a> {
    /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
    pub fn as_turbofish(&self) -> Turbofish {
        Turbofish(self.0)
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Lifetime {
    pub ident: Ident,
}

impl Lifetime {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        let id = Ident::new(t);
        if !id.as_ref().starts_with('\'') {
            panic!("lifetime name must start with apostrophe as in \"'a\", \
                   got {:?}",
                   id.as_ref());
        }
        Lifetime { ident: id }
    }
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct LifetimeDef {
    pub attrs: Vec<Attribute>,
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

impl LifetimeDef {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        LifetimeDef {
            attrs: Vec::new(),
            lifetime: Lifetime::new(t),
            bounds: Vec::new(),
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TyParam {
    pub attrs: Vec<Attribute>,
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

impl WhereClause {
    pub fn none() -> Self {
        WhereClause { predicates: Vec::new() }
    }
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
    /// An equality predicate (unsupported)
    EqPredicate(WhereEqPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

/// An equality predicate (unsupported).
///
/// E.g. `T=int`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereEqPredicate {
    pub lhs_ty: Ty,
    pub rhs_ty: Ty,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::outer_attr;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, map!(
        alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                cond!(!lifetimes.is_empty() || !ty_params.is_empty(), option!(punct!(","))) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ),
        |(lifetimes, ty_params)| Generics {
            lifetimes: lifetimes,
            ty_params: ty_params,
            where_clause: Default::default(),
        }
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        alt!(
            map!(ident, |id| Lifetime {
                ident: format!("'{}", id).into(),
            })
            |
            map!(keyword!("static"), |_| Lifetime {
                ident: "'static".into(),
            })
        )
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        attrs: many0!(outer_attr) >>
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            attrs: attrs,
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: terminated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        attrs: many0!(outer_attr) >>
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            attrs: attrs,
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            bounds: opt_vec!(preceded!(
                punct!(":"),
                separated_list!(punct!("+"), lifetime)
            )) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for ImplGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.0.lifetimes, ",");
                // Leave off the type parameter defaults
                for (i, ty_param) in self.0
                        .ty_params
                        .iter()
                        .enumerate() {
                    if i > 0 || has_lifetimes {
                        tokens.append(",");
                    }
                    tokens.append_all(ty_param.attrs.outer());
                    ty_param.ident.to_tokens(tokens);
                    if !ty_param.bounds.is_empty() {
                        tokens.append(":");
                        tokens.append_separated(&ty_param.bounds, "+");
                    }
                }
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for TyGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                // Leave off the lifetime bounds and attributes
                let lifetimes = self.0
                    .lifetimes
                    .iter()
                    .map(|ld| &ld.lifetime);
                tokens.append_separated(lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                // Leave off the type parameter bounds, defaults, and attributes
                let ty_params = self.0
                    .ty_params
                    .iter()
                    .map(|tp| &tp.ident);
                tokens.append_separated(ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for Turbofish<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("::");
                TyGenerics(self.0).to_tokens(tokens);
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::EqPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereEqPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lhs_ty.to_tokens(tokens);
            tokens.append("=");
            self.rhs_ty.to_tokens(tokens);
        }
    }
}
<commit_msg>Added From<Ident> for TyParam<commit_after>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct ImplGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct TyGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `TyGenerics::as_turbofish`.
#[derive(Debug)]
pub struct Turbofish<'a>(&'a Generics);

#[cfg(feature = "printing")]
impl Generics {
    /// Split a type's generics into the pieces required for impl'ing a trait
    /// for that type.
    ///
    /// ```
    /// # extern crate syn;
    /// # #[macro_use]
    /// # extern crate quote;
    /// # fn main() {
    /// # let generics: syn::Generics = Default::default();
    /// # let name = syn::Ident::new("MyType");
    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    /// quote! {
    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
    ///         // ...
    ///     }
    /// }
    /// # ;
    /// # }
    /// ```
    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
    }
}

#[cfg(feature = "printing")]
impl<'a> TyGenerics<'a> {
    /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
    pub fn as_turbofish(&self) -> Turbofish {
        Turbofish(self.0)
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Lifetime {
    pub ident: Ident,
}

impl Lifetime {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        let id = Ident::new(t);
        if !id.as_ref().starts_with('\'') {
            panic!("lifetime name must start with apostrophe as in \"'a\", \
                   got {:?}",
                   id.as_ref());
        }
        Lifetime { ident: id }
    }
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct LifetimeDef {
    pub attrs: Vec<Attribute>,
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

impl LifetimeDef {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        LifetimeDef {
            attrs: Vec::new(),
            lifetime: Lifetime::new(t),
            bounds: Vec::new(),
        }
    }
}

/// A generic type parameter, e.g. `T: Into<String>`.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TyParam {
    pub attrs: Vec<Attribute>,
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

impl From<Ident> for TyParam {
    fn from(ident: Ident) -> Self {
        TyParam {
            attrs: vec![],
            ident: ident,
            bounds: vec![],
            default: None,
        }
    }
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

impl WhereClause {
    pub fn none() -> Self {
        WhereClause { predicates: Vec::new() }
    }
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
    /// An equality predicate (unsupported)
    EqPredicate(WhereEqPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

/// An equality predicate (unsupported).
///
/// E.g. `T=int`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct WhereEqPredicate {
    pub lhs_ty: Ty,
    pub rhs_ty: Ty,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::outer_attr;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, map!(
        alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                cond!(!lifetimes.is_empty() || !ty_params.is_empty(), option!(punct!(","))) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ),
        |(lifetimes, ty_params)| Generics {
            lifetimes: lifetimes,
            ty_params: ty_params,
            where_clause: Default::default(),
        }
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        alt!(
            map!(ident, |id| Lifetime {
                ident: format!("'{}", id).into(),
            })
            |
            map!(keyword!("static"), |_| Lifetime {
                ident: "'static".into(),
            })
        )
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        attrs: many0!(outer_attr) >>
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            attrs: attrs,
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: terminated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        attrs: many0!(outer_attr) >>
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            attrs: attrs,
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            bounds: opt_vec!(preceded!(
                punct!(":"),
                separated_list!(punct!("+"), lifetime)
            )) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for ImplGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.0.lifetimes, ",");
                // Leave off the type parameter defaults
                for (i, ty_param) in self.0
                        .ty_params
                        .iter()
                        .enumerate() {
                    if i > 0 || has_lifetimes {
                        tokens.append(",");
                    }
                    tokens.append_all(ty_param.attrs.outer());
                    ty_param.ident.to_tokens(tokens);
                    if !ty_param.bounds.is_empty() {
                        tokens.append(":");
                        tokens.append_separated(&ty_param.bounds, "+");
                    }
                }
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for TyGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                // Leave off the lifetime bounds and attributes
                let lifetimes = self.0
                    .lifetimes
                    .iter()
                    .map(|ld| &ld.lifetime);
                tokens.append_separated(lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                // Leave off the type parameter bounds, defaults, and attributes
                let ty_params = self.0
                    .ty_params
                    .iter()
                    .map(|tp| &tp.ident);
                tokens.append_separated(ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for Turbofish<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("::");
                TyGenerics(self.0).to_tokens(tokens);
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::EqPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereEqPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lhs_ty.to_tokens(tokens);
            tokens.append("=");
            self.rhs_ty.to_tokens(tokens);
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::authenticatorservice::AuthenticatorService;
use crate::statecallback::StateCallback;
use crate::{RegisterResult, SignResult};
use libc::size_t;
use rand::{thread_rng, Rng};
use std::collections::HashMap;
use std::sync::mpsc::channel;
use std::{ptr, slice};

type U2FAppIds = Vec<crate::AppId>;
type U2FKeyHandles = Vec<crate::KeyHandle>;
type U2FCallback = extern "C" fn(u64, *mut U2FResult);

pub enum U2FResult {
    Success(HashMap<u8, Vec<u8>>),
    Error(crate::Error),
}

const RESBUF_ID_REGISTRATION: u8 = 0;
const RESBUF_ID_KEYHANDLE: u8 = 1;
const RESBUF_ID_SIGNATURE: u8 = 2;
const RESBUF_ID_APPID: u8 = 3;
const RESBUF_ID_VENDOR_NAME: u8 = 4;
const RESBUF_ID_DEVICE_NAME: u8 = 5;
const RESBUF_ID_FIRMWARE_MAJOR: u8 = 6;
const RESBUF_ID_FIRMWARE_MINOR: u8 = 7;
const RESBUF_ID_FIRMWARE_BUILD: u8 = 8;

// Generates a new 64-bit transaction id with collision probability 2^-32.
fn new_tid() -> u64 {
    thread_rng().gen::<u64>()
}

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub extern "C" fn rust_u2f_mgr_new() -> *mut AuthenticatorService {
    if let Ok(mut mgr) = AuthenticatorService::new() {
        mgr.add_detected_transports();
        Box::into_raw(Box::new(mgr))
    } else {
        ptr::null_mut()
    }
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_free(mgr: *mut AuthenticatorService) {
    if !mgr.is_null() {
        Box::from_raw(mgr);
    }
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_new() -> *mut U2FAppIds {
    Box::into_raw(Box::new(vec![]))
}

/// # Safety
///
/// This method must be used on an actual U2FAppIds handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_add(
    ids: *mut U2FAppIds,
    id_ptr: *const u8,
    id_len: usize,
) {
    (*ids).push(from_raw(id_ptr, id_len));
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_free(ids: *mut U2FAppIds) {
    if !ids.is_null() {
        Box::from_raw(ids);
    }
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_new() -> *mut U2FKeyHandles {
    Box::into_raw(Box::new(vec![]))
}

/// # Safety
///
/// This method must be used on an actual U2FKeyHandles handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_add(
    khs: *mut U2FKeyHandles,
    key_handle_ptr: *const u8,
    key_handle_len: usize,
    transports: u8,
) {
    (*khs).push(crate::KeyHandle {
        credential: from_raw(key_handle_ptr, key_handle_len),
        transports: crate::AuthenticatorTransports::from_bits_truncate(transports),
    });
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_free(khs: *mut U2FKeyHandles) {
    if !khs.is_null() {
        Box::from_raw(khs);
    }
}

/// # Safety
///
/// This method must be used on an actual U2FResult handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_result_error(res: *const U2FResult) -> u8 {
    if res.is_null() {
        return crate::Error::Unknown as u8;
    }

    if let U2FResult::Error(ref err) = *res {
        return *err as u8;
    }

    0 /* No error, the request succeeded. */
}

/// # Safety
///
/// This method must be used before rust_u2f_resbuf_copy
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_resbuf_length(
    res: *const U2FResult,
    bid: u8,
    len: *mut size_t,
) -> bool {
    if res.is_null() {
        return false;
    }

    if let U2FResult::Success(ref bufs) = *res {
        if let Some(buf) = bufs.get(&bid) {
            *len = buf.len();
            return true;
        }
    }

    false
}

/// # Safety
///
/// This method does not ensure anything about dst before copying, so
/// ensure it is long enough (using rust_u2f_resbuf_length)
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_resbuf_copy(
    res: *const U2FResult,
    bid: u8,
    dst: *mut u8,
) -> bool {
    if res.is_null() {
        return false;
    }

    if let U2FResult::Success(ref bufs) = *res {
        if let Some(buf) = bufs.get(&bid) {
            ptr::copy_nonoverlapping(buf.as_ptr(), dst, buf.len());
            return true;
        }
    }

    false
}

/// # Safety
///
/// This method should not be called on U2FResult handles after they've been
/// freed or a double-free will occur
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_res_free(res: *mut U2FResult) {
    if !res.is_null() {
        Box::from_raw(res);
    }
}

/// # Safety
///
/// This method should not be called on AuthenticatorService handles after
/// they've been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_register(
    mgr: *mut AuthenticatorService,
    flags: u64,
    timeout: u64,
    callback: U2FCallback,
    challenge_ptr: *const u8,
    challenge_len: usize,
    application_ptr: *const u8,
    application_len: usize,
    khs: *const U2FKeyHandles,
) -> u64 {
    if mgr.is_null() {
        return 0;
    }

    // Check buffers.
    if challenge_ptr.is_null() || application_ptr.is_null() {
        return 0;
    }

    let flags = crate::RegisterFlags::from_bits_truncate(flags);
    let challenge = from_raw(challenge_ptr, challenge_len);
    let application = from_raw(application_ptr, application_len);
    let key_handles = (*khs).clone();

    let (tx, _rx) = channel::<crate::StatusUpdate>();
    let tid = new_tid();

    let state_callback =
        StateCallback::<Result<RegisterResult, crate::Error>>::new(Box::new(move |rv| {
            let result = match rv {
                Ok((registration, dev_info)) => {
                    let mut bufs = HashMap::new();
                    bufs.insert(RESBUF_ID_REGISTRATION, registration);
                    bufs.insert(RESBUF_ID_VENDOR_NAME, dev_info.vendor_name);
                    bufs.insert(RESBUF_ID_DEVICE_NAME, dev_info.device_name);
                    bufs.insert(RESBUF_ID_FIRMWARE_MAJOR, vec![dev_info.version_major]);
                    bufs.insert(RESBUF_ID_FIRMWARE_MINOR, vec![dev_info.version_minor]);
                    bufs.insert(RESBUF_ID_FIRMWARE_BUILD, vec![dev_info.version_build]);
                    U2FResult::Success(bufs)
                }
                Err(e) => U2FResult::Error(e),
            };

            callback(tid, Box::into_raw(Box::new(result)));
        }));

    let res = (*mgr).register(
        flags,
        timeout,
        challenge,
        application,
        key_handles,
        tx,
        state_callback,
    );

    if res.is_ok() {
        tid
    } else {
        0
    }
}

/// # Safety
///
/// This method should not be called on AuthenticatorService handles after
/// they've been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_sign(
    mgr: *mut AuthenticatorService,
    flags: u64,
    timeout: u64,
    callback: U2FCallback,
    challenge_ptr: *const u8,
    challenge_len: usize,
    app_ids: *const U2FAppIds,
    khs: *const U2FKeyHandles,
) -> u64 {
    if mgr.is_null() || khs.is_null() {
        return 0;
    }

    // Check buffers.
    if challenge_ptr.is_null() {
        return 0;
    }

    // Need at least one app_id.
    if (*app_ids).is_empty() {
        return 0;
    }

    let flags = crate::SignFlags::from_bits_truncate(flags);
    let challenge = from_raw(challenge_ptr, challenge_len);
    let app_ids = (*app_ids).clone();
    let key_handles = (*khs).clone();

    let (tx, _rx) = channel::<crate::StatusUpdate>();

    let tid = new_tid();
    let state_callback =
        StateCallback::<Result<SignResult, crate::Error>>::new(Box::new(move |rv| {
            let result = match rv {
                Ok((app_id, key_handle, signature, dev_info)) => {
                    let mut bufs = HashMap::new();
                    bufs.insert(RESBUF_ID_KEYHANDLE, key_handle);
                    bufs.insert(RESBUF_ID_SIGNATURE, signature);
                    bufs.insert(RESBUF_ID_APPID, app_id);
                    bufs.insert(RESBUF_ID_VENDOR_NAME, dev_info.vendor_name);
                    bufs.insert(RESBUF_ID_DEVICE_NAME, dev_info.device_name);
                    bufs.insert(RESBUF_ID_FIRMWARE_MAJOR, vec![dev_info.version_major]);
                    bufs.insert(RESBUF_ID_FIRMWARE_MINOR, vec![dev_info.version_minor]);
                    bufs.insert(RESBUF_ID_FIRMWARE_BUILD, vec![dev_info.version_build]);
                    U2FResult::Success(bufs)
                }
                Err(e) => U2FResult::Error(e),
            };

            callback(tid, Box::into_raw(Box::new(result)));
        }));

    let res = (*mgr).sign(
        flags,
        timeout,
        challenge,
        app_ids,
        key_handles,
        tx,
        state_callback,
    );

    if res.is_ok() {
        tid
    } else {
        0
    }
}

/// # Safety
///
/// This method should not be called AuthenticatorService handles after they've
/// been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_cancel(mgr: *mut AuthenticatorService) {
    if !mgr.is_null() {
        // Ignore return value.
        let _ = (*mgr).cancel();
    }
}
<commit_msg>Absorb status updates at the C API, rather than letting the channel error<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::authenticatorservice::AuthenticatorService;
use crate::statecallback::StateCallback;
use crate::{RegisterResult, SignResult};
use libc::size_t;
use rand::{thread_rng, Rng};
use std::collections::HashMap;
use std::sync::mpsc::channel;
use std::thread;
use std::{ptr, slice};

type U2FAppIds = Vec<crate::AppId>;
type U2FKeyHandles = Vec<crate::KeyHandle>;
type U2FCallback = extern "C" fn(u64, *mut U2FResult);

pub enum U2FResult {
    Success(HashMap<u8, Vec<u8>>),
    Error(crate::Error),
}

const RESBUF_ID_REGISTRATION: u8 = 0;
const RESBUF_ID_KEYHANDLE: u8 = 1;
const RESBUF_ID_SIGNATURE: u8 = 2;
const RESBUF_ID_APPID: u8 = 3;
const RESBUF_ID_VENDOR_NAME: u8 = 4;
const RESBUF_ID_DEVICE_NAME: u8 = 5;
const RESBUF_ID_FIRMWARE_MAJOR: u8 = 6;
const RESBUF_ID_FIRMWARE_MINOR: u8 = 7;
const RESBUF_ID_FIRMWARE_BUILD: u8 = 8;

// Generates a new 64-bit transaction id with collision probability 2^-32.
fn new_tid() -> u64 {
    thread_rng().gen::<u64>()
}

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub extern "C" fn rust_u2f_mgr_new() -> *mut AuthenticatorService {
    if let Ok(mut mgr) = AuthenticatorService::new() {
        mgr.add_detected_transports();
        Box::into_raw(Box::new(mgr))
    } else {
        ptr::null_mut()
    }
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_free(mgr: *mut AuthenticatorService) {
    if !mgr.is_null() {
        Box::from_raw(mgr);
    }
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_new() -> *mut U2FAppIds {
    Box::into_raw(Box::new(vec![]))
}

/// # Safety
///
/// This method must be used on an actual U2FAppIds handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_add(
    ids: *mut U2FAppIds,
    id_ptr: *const u8,
    id_len: usize,
) {
    (*ids).push(from_raw(id_ptr, id_len));
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_app_ids_free(ids: *mut U2FAppIds) {
    if !ids.is_null() {
        Box::from_raw(ids);
    }
}

/// # Safety
///
/// The handle returned by this method must be freed by the caller.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_new() -> *mut U2FKeyHandles {
    Box::into_raw(Box::new(vec![]))
}

/// # Safety
///
/// This method must be used on an actual U2FKeyHandles handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_add(
    khs: *mut U2FKeyHandles,
    key_handle_ptr: *const u8,
    key_handle_len: usize,
    transports: u8,
) {
    (*khs).push(crate::KeyHandle {
        credential: from_raw(key_handle_ptr, key_handle_len),
        transports: crate::AuthenticatorTransports::from_bits_truncate(transports),
    });
}

/// # Safety
///
/// This method must not be called on a handle twice, and the handle is unusable
/// after.
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_khs_free(khs: *mut U2FKeyHandles) {
    if !khs.is_null() {
        Box::from_raw(khs);
    }
}

/// # Safety
///
/// This method must be used on an actual U2FResult handle
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_result_error(res: *const U2FResult) -> u8 {
    if res.is_null() {
        return crate::Error::Unknown as u8;
    }

    if let U2FResult::Error(ref err) = *res {
        return *err as u8;
    }

    0 /* No error, the request succeeded. */
}

/// # Safety
///
/// This method must be used before rust_u2f_resbuf_copy
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_resbuf_length(
    res: *const U2FResult,
    bid: u8,
    len: *mut size_t,
) -> bool {
    if res.is_null() {
        return false;
    }

    if let U2FResult::Success(ref bufs) = *res {
        if let Some(buf) = bufs.get(&bid) {
            *len = buf.len();
            return true;
        }
    }

    false
}

/// # Safety
///
/// This method does not ensure anything about dst before copying, so
/// ensure it is long enough (using rust_u2f_resbuf_length)
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_resbuf_copy(
    res: *const U2FResult,
    bid: u8,
    dst: *mut u8,
) -> bool {
    if res.is_null() {
        return false;
    }

    if let U2FResult::Success(ref bufs) = *res {
        if let Some(buf) = bufs.get(&bid) {
            ptr::copy_nonoverlapping(buf.as_ptr(), dst, buf.len());
            return true;
        }
    }

    false
}

/// # Safety
///
/// This method should not be called on U2FResult handles after they've been
/// freed or a double-free will occur
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_res_free(res: *mut U2FResult) {
    if !res.is_null() {
        Box::from_raw(res);
    }
}

/// # Safety
///
/// This method should not be called on AuthenticatorService handles after
/// they've been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_register(
    mgr: *mut AuthenticatorService,
    flags: u64,
    timeout: u64,
    callback: U2FCallback,
    challenge_ptr: *const u8,
    challenge_len: usize,
    application_ptr: *const u8,
    application_len: usize,
    khs: *const U2FKeyHandles,
) -> u64 {
    if mgr.is_null() {
        return 0;
    }

    // Check buffers.
    if challenge_ptr.is_null() || application_ptr.is_null() {
        return 0;
    }

    let flags = crate::RegisterFlags::from_bits_truncate(flags);
    let challenge = from_raw(challenge_ptr, challenge_len);
    let application = from_raw(application_ptr, application_len);
    let key_handles = (*khs).clone();

    let (status_tx, status_rx) = channel::<crate::StatusUpdate>();
    thread::spawn(move || loop {
        // Issue https://github.com/mozilla/authenticator-rs/issues/132 will
        // plumb the status channel through to the actual C API signatures
        match status_rx.recv() {
            Ok(_) => {}
            Err(_recv_error) => return,
        }
    });

    let tid = new_tid();

    let state_callback =
        StateCallback::<Result<RegisterResult, crate::Error>>::new(Box::new(move |rv| {
            let result = match rv {
                Ok((registration, dev_info)) => {
                    let mut bufs = HashMap::new();
                    bufs.insert(RESBUF_ID_REGISTRATION, registration);
                    bufs.insert(RESBUF_ID_VENDOR_NAME, dev_info.vendor_name);
                    bufs.insert(RESBUF_ID_DEVICE_NAME, dev_info.device_name);
                    bufs.insert(RESBUF_ID_FIRMWARE_MAJOR, vec![dev_info.version_major]);
                    bufs.insert(RESBUF_ID_FIRMWARE_MINOR, vec![dev_info.version_minor]);
                    bufs.insert(RESBUF_ID_FIRMWARE_BUILD, vec![dev_info.version_build]);
                    U2FResult::Success(bufs)
                }
                Err(e) => U2FResult::Error(e),
            };

            callback(tid, Box::into_raw(Box::new(result)));
        }));

    let res = (*mgr).register(
        flags,
        timeout,
        challenge,
        application,
        key_handles,
        status_tx,
        state_callback,
    );

    if res.is_ok() {
        tid
    } else {
        0
    }
}

/// # Safety
///
/// This method should not be called on AuthenticatorService handles after
/// they've been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_sign(
    mgr: *mut AuthenticatorService,
    flags: u64,
    timeout: u64,
    callback: U2FCallback,
    challenge_ptr: *const u8,
    challenge_len: usize,
    app_ids: *const U2FAppIds,
    khs: *const U2FKeyHandles,
) -> u64 {
    if mgr.is_null() || khs.is_null() {
        return 0;
    }

    // Check buffers.
    if challenge_ptr.is_null() {
        return 0;
    }

    // Need at least one app_id.
    if (*app_ids).is_empty() {
        return 0;
    }

    let flags = crate::SignFlags::from_bits_truncate(flags);
    let challenge = from_raw(challenge_ptr, challenge_len);
    let app_ids = (*app_ids).clone();
    let key_handles = (*khs).clone();

    let (status_tx, status_rx) = channel::<crate::StatusUpdate>();
    thread::spawn(move || loop {
        // Issue https://github.com/mozilla/authenticator-rs/issues/132 will
        // plumb the status channel through to the actual C API signatures
        match status_rx.recv() {
            Ok(_) => {}
            Err(_recv_error) => return,
        }
    });

    let tid = new_tid();
    let state_callback =
        StateCallback::<Result<SignResult, crate::Error>>::new(Box::new(move |rv| {
            let result = match rv {
                Ok((app_id, key_handle, signature, dev_info)) => {
                    let mut bufs = HashMap::new();
                    bufs.insert(RESBUF_ID_KEYHANDLE, key_handle);
                    bufs.insert(RESBUF_ID_SIGNATURE, signature);
                    bufs.insert(RESBUF_ID_APPID, app_id);
                    bufs.insert(RESBUF_ID_VENDOR_NAME, dev_info.vendor_name);
                    bufs.insert(RESBUF_ID_DEVICE_NAME, dev_info.device_name);
                    bufs.insert(RESBUF_ID_FIRMWARE_MAJOR, vec![dev_info.version_major]);
                    bufs.insert(RESBUF_ID_FIRMWARE_MINOR, vec![dev_info.version_minor]);
                    bufs.insert(RESBUF_ID_FIRMWARE_BUILD, vec![dev_info.version_build]);
                    U2FResult::Success(bufs)
                }
                Err(e) => U2FResult::Error(e),
            };

            callback(tid, Box::into_raw(Box::new(result)));
        }));

    let res = (*mgr).sign(
        flags,
        timeout,
        challenge,
        app_ids,
        key_handles,
        status_tx,
        state_callback,
    );

    if res.is_ok() {
        tid
    } else {
        0
    }
}

/// # Safety
///
/// This method should not be called AuthenticatorService handles after they've
/// been freed
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_cancel(mgr: *mut AuthenticatorService) {
    if !mgr.is_null() {
        // Ignore return value.
        let _ = (*mgr).cancel();
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::f64::NAN;
use std::ops::{Add, Sub, Div, Mul};

// ===== GVector =====

#[derive(Debug, Copy, Clone)]
pub struct GVector {
    pub x: f64,
    pub y: f64,
    pub z: f64
}

impl GVector {
    pub fn has_nans(&self) -> bool {
        return (self.x == NAN) || (self.y == NAN) || (self.z == NAN);
    }

    pub fn dot(gv1: GVector, gv2: GVector) -> f64 {
        return gv1.x * gv2.x + gv1.y * gv2.y + gv1.z * gv2.z;
    }

    pub fn cross_dos(gv1: GVector, gv2: GVector) -> GVector {
        GVector {
            x: (gv1.y * gv2.z) - (gv1.z * gv2.y),
            y: (gv1.z * gv2.x) - (gv1.x * gv2.z),
            z: (gv1.x * gv2.y) - (gv1.y * gv2.x)
        }
    }

    pub fn length_sqr(&self)  -> f64{
        return self.x * self.x + self.y * self.y + self.z * self.z;
    }

    pub fn length(&self) -> f64 {
        return self.length_sqr().sqrt();
    }

    pub fn normalize(&mut self) -> GVector {
        let len = self.length();
        self.x = self.x / len;
        self.y = self.y / len;
        self.z = self.z / len;
        return self.clone();
    }

    // TODO: CoordinateSystem
    pub fn coordinate_system(gv1: &mut GVector,
                             gv2: &mut GVector,
                             gv3: &mut GVector) {
        return;
    }

}

// ----- operation overload for (GVector, GVector)
// TODO: IF SOMEONE KNOW HOW TO USE MACRO LIKE add_impl!
// TO REPLACE THESE STUPID CODE
// FELL FREE TO TEACH ME!!

impl Add<GVector> for GVector {

    type Output = GVector;
    fn add(self, other: GVector) -> GVector {
        GVector {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}
impl Sub<GVector> for GVector {

    type Output = GVector;
    fn sub(self, other: GVector) -> GVector {
        GVector {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<GVector> for GVector {

    type Output = GVector;
    fn mul(self, other: GVector) -> GVector {
        GVector {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }

}

impl Div<GVector> for GVector {

    type Output = GVector;
    fn div(self, other: GVector) -> GVector {
        GVector {
            x: self.x / other.x,
            y: self.y / other.y,
            z: self.z / other.z
        }
    }
}

// ----- operation overload for (GVector, scala)

impl Add<f64> for GVector {

    type Output = GVector;
    fn add(self, v: f64) -> GVector {
        GVector {
            x: self.x + v,
            y: self.y + v,
            z: self.z + v
        }
    }
}
impl Sub<f64> for GVector {

    type Output = GVector;
    fn sub(self, v: f64) -> GVector {
        GVector {
            x: self.x - v,
            y: self.y - v,
            z: self.z - v
        }
    }
}

impl Mul<f64> for GVector {

    type Output = GVector;
    fn mul(self, v: f64) -> GVector {
        GVector {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v
        }
    }

}

impl Div<f64> for GVector {

    type Output = GVector;
    fn div(self, v: f64) -> GVector {
        GVector {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v
        }
    }
}

// ===== GPoint

pub struct GPoint {
    pub x: f64,
    pub y: f64,
    pub z: f64
}

// ----- operation overload for (GPoint, GPoint)

impl Add<GPoint> for GPoint {

    type Output = GPoint;
    fn add(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}
impl Sub<GPoint> for GPoint {

    type Output = GPoint;
    fn sub(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<GPoint> for GPoint {

    type Output = GPoint;
    fn mul(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }

}

impl Div<GPoint> for GPoint {

    type Output = GPoint;
    fn div(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x / other.x,
            y: self.y / other.y,
            z: self.z / other.z
        }
    }
}

// ----- operation overload for (GPoint, scala)

impl Add<f64> for GPoint {

    type Output = GPoint;
    fn add(self, v: f64) -> GPoint {
        GPoint {
            x: self.x + v,
            y: self.y + v,
            z: self.z + v
        }
    }
}
impl Sub<f64> for GPoint {

    type Output = GPoint;
    fn sub(self, v: f64) -> GPoint {
        GPoint {
            x: self.x - v,
            y: self.y - v,
            z: self.z - v
        }
    }
}

impl Mul<f64> for GPoint {

    type Output = GPoint;
    fn mul(self, v: f64) -> GPoint {
        GPoint {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v
        }
    }

}

impl Div<f64> for GPoint {

    type Output = GPoint;
    fn div(self, v: f64) -> GPoint {
        GPoint {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v
        }
    }
}
<commit_msg>dev-2017.01.08.02<commit_after>use std::f64;
use std::f64::NAN;
use std::ops::{Add, Sub, Div, Mul};

// ===== GVector =====

#[derive(Debug, Copy, Clone)]
pub struct GVector {
    pub x: f64,
    pub y: f64,
    pub z: f64
}

impl GVector {
    #[inline]
    pub fn has_nans(&self) -> bool {
        return (self.x == NAN) || (self.y == NAN) || (self.z == NAN);
    }

    #[inline]
    pub fn dot(gv1: GVector, gv2: GVector) -> f64 {
        return gv1.x * gv2.x + gv1.y * gv2.y + gv1.z * gv2.z;
    }

    #[inline]
    pub fn cross_dos(gv1: GVector, gv2: GVector) -> GVector {
        GVector {
            x: (gv1.y * gv2.z) - (gv1.z * gv2.y),
            y: (gv1.z * gv2.x) - (gv1.x * gv2.z),
            z: (gv1.x * gv2.y) - (gv1.y * gv2.x)
        }
    }

    #[inline]
    pub fn length_sqr(&self)  -> f64{
        return self.x * self.x + self.y * self.y + self.z * self.z;
    }

    #[inline]
    pub fn length(&self) -> f64 {
        return self.length_sqr().sqrt();
    }

    #[inline]
    pub fn normalize(&mut self) -> GVector {
        let len = self.length();
        self.x = self.x / len;
        self.y = self.y / len;
        self.z = self.z / len;
        return self.clone();
    }

    // TODO: CoordinateSystem
    #[inline]
    pub fn coordinate_system(gv1: &mut GVector,
                             gv2: &mut GVector,
                             gv3: &mut GVector) {
        return;
    }

}

// ----- operation overload for (GVector, GVector)
// TODO: IF SOMEONE KNOW HOW TO USE MACRO LIKE add_impl!
// TO REPLACE THESE STUPID CODE
// FELL FREE TO TEACH ME!!

impl Add<GVector> for GVector {

    type Output = GVector;
    #[inline]
    fn add(self, other: GVector) -> GVector {
        GVector {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}
impl Sub<GVector> for GVector {

    type Output = GVector;
    #[inline]
    fn sub(self, other: GVector) -> GVector {
        GVector {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<GVector> for GVector {

    type Output = GVector;
    #[inline]
    fn mul(self, other: GVector) -> GVector {
        GVector {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }

}

impl Div<GVector> for GVector {

    type Output = GVector;
    #[inline]
    fn div(self, other: GVector) -> GVector {
        GVector {
            x: self.x / other.x,
            y: self.y / other.y,
            z: self.z / other.z
        }
    }
}

// ----- operation overload for (GVector, scala)

impl Add<f64> for GVector {

    type Output = GVector;
    #[inline]
    fn add(self, v: f64) -> GVector {
        GVector {
            x: self.x + v,
            y: self.y + v,
            z: self.z + v
        }
    }
}
impl Sub<f64> for GVector {

    type Output = GVector;
    fn sub(self, v: f64) -> GVector {
        GVector {
            x: self.x - v,
            y: self.y - v,
            z: self.z - v
        }
    }
}

impl Mul<f64> for GVector {

    type Output = GVector;
    fn mul(self, v: f64) -> GVector {
        GVector {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v
        }
    }

}

impl Div<f64> for GVector {

    type Output = GVector;
    fn div(self, v: f64) -> GVector {
        GVector {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v
        }
    }
}

// ===== GPoint
#[derive(Debug, Copy, Clone)]
pub struct GPoint {
    pub x: f64,
    pub y: f64,
    pub z: f64
}

impl GPoint {

    #[inline]
    pub fn length_sqr(&self) -> f64{
        return self.x + self.x + self.y * self.y + self.z * self.z;
    }

    #[inline]
    pub fn length(&self) -> f64 {
        return self.length_sqr().sqrt();
    }

    #[inline]
    pub fn distance(gp1: GPoint, gp2: GPoint) -> f64 {
        return (gp1 - gp2).length();
    }

    #[inline]
    pub fn distance_sqr(gp1: GPoint, gp2: GPoint) -> f64 {
        return (gp1 - gp2).length_sqr();
    }
}

// ----- operation overload for (GPoint, GPoint)

impl Add<GPoint> for GPoint {

    type Output = GPoint;
    #[inline]
    fn add(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}
impl Sub<GPoint> for GPoint {

    type Output = GPoint;
    #[inline]
    fn sub(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<GPoint> for GPoint {

    type Output = GPoint;
    #[inline]
    fn mul(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }

}

impl Div<GPoint> for GPoint {

    type Output = GPoint;
    #[inline]
    fn div(self, other: GPoint) -> GPoint {
        GPoint {
            x: self.x / other.x,
            y: self.y / other.y,
            z: self.z / other.z
        }
    }
}

// ----- operation overload for (GPoint, scala)

impl Add<f64> for GPoint {

    type Output = GPoint;
    #[inline]
    fn add(self, v: f64) -> GPoint {
        GPoint {
            x: self.x + v,
            y: self.y + v,
            z: self.z + v
        }
    }
}
impl Sub<f64> for GPoint {

    type Output = GPoint;
    #[inline]
    fn sub(self, v: f64) -> GPoint {
        GPoint {
            x: self.x - v,
            y: self.y - v,
            z: self.z - v
        }
    }
}

impl Mul<f64> for GPoint {

    type Output = GPoint;
    #[inline]
    fn mul(self, v: f64) -> GPoint {
        GPoint {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v
        }
    }

}

impl Div<f64> for GPoint {

    type Output = GPoint;
    #[inline]
    fn div(self, v: f64) -> GPoint {
        GPoint {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v
        }
    }
}
<|endoftext|>


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

use base::CGFloat;

pub const CG_ZERO_POINT: CGPoint = CGPoint {
    x: 0.0,
    y: 0.0,
};

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGSize {
    pub width: CGFloat,
    pub height: CGFloat,
}

impl CGSize {
    #[inline]
    pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
        CGSize {
            width: width,
            height: height,
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGPoint {
    pub x: CGFloat,
    pub y: CGFloat,
}

impl CGPoint {
    #[inline]
    pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
        CGPoint {
            x: x,
            y: y,
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGRect {
    pub origin: CGPoint,
    pub size: CGSize
}

impl CGRect {
    #[inline]
    pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect {
        CGRect {
            origin: *origin,
            size: *size,
        }
    }

    #[inline]
    pub fn inset(&self, size: &CGSize) -> CGRect {
        unsafe {
            ffi::CGRectInset(*self, size.width, size.height)
        }
    }
}

mod ffi {
    use base::CGFloat;
    use geometry::CGRect;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
    }
}

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

use base::CGFloat;
use core_foundation::base::TCFType;
use core_foundation::dictionary::CFDictionary;

pub const CG_ZERO_POINT: CGPoint = CGPoint {
    x: 0.0,
    y: 0.0,
};

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGSize {
    pub width: CGFloat,
    pub height: CGFloat,
}

impl CGSize {
    #[inline]
    pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
        CGSize {
            width: width,
            height: height,
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGPoint {
    pub x: CGFloat,
    pub y: CGFloat,
}

impl CGPoint {
    #[inline]
    pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
        CGPoint {
            x: x,
            y: y,
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CGRect {
    pub origin: CGPoint,
    pub size: CGSize
}

impl CGRect {
    #[inline]
    pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect {
        CGRect {
            origin: *origin,
            size: *size,
        }
    }

    #[inline]
    pub fn inset(&self, size: &CGSize) -> CGRect {
        unsafe {
            ffi::CGRectInset(*self, size.width, size.height)
        }
    }

    #[inline]
    pub fn from_dict_representation(dict: &CFDictionary) -> Option<CGRect> {
        let mut rect = CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(0., 0.));
        let result = unsafe {
            ffi::CGRectMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut rect)
        };
        if result == 0 {
            None
        } else {
            Some(rect)
        }
    }
}

mod ffi {
    use base::{CGFloat, boolean_t};
    use geometry::CGRect;
    use core_foundation::dictionary::CFDictionaryRef;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
        pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef,
                                                      rect: *mut CGRect) -> boolean_t;
    }
}

<|endoftext|>