<commit_before>use std::collections::BTreeSet;
use action::{POSSIBLE_DIRECTIONS,POSSIBLE_MOVE_TYPES,Coordinate,Move};

pub const NUM_COLS: usize = 5;
pub const NUM_ROWS: usize = 4;

// Hacks for the three states of the lower-left of the board in JunSeok vs YeonSeung game
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub enum BoardType {
    Left,
    LeftOrMiddle,
    Middle,
    RightOrMiddle,
    Right,
}

impl BoardType {
    fn is_final(&self) -> bool {
        match *self {
            BoardType::Left => true,
            BoardType::Middle => true,
            BoardType::Right => true,
            BoardType::LeftOrMiddle => false,
            BoardType::RightOrMiddle => false,
        }
    }

    // Can a board of type `current` become this type?
    fn applies_to(&self, current: Option<BoardType>) -> bool {
        match (current, *self) {
            // a none board type can change to anything.
            (None, _) => true,
            // LeftOrMiddle can change to itself, left, or middle.
            (Some(BoardType::LeftOrMiddle), BoardType::LeftOrMiddle) => true,
            (Some(BoardType::LeftOrMiddle), BoardType::Left) => true,
            (Some(BoardType::LeftOrMiddle), BoardType::Middle) => true,
            (Some(BoardType::LeftOrMiddle), _) => false,
            // RightOrMiddle can change to itself, right, or middle.
            (Some(BoardType::RightOrMiddle), BoardType::RightOrMiddle) => true,
            (Some(BoardType::RightOrMiddle), BoardType::Right) => true,
            (Some(BoardType::RightOrMiddle), BoardType::Middle) => true,
            (Some(BoardType::RightOrMiddle), _) => false,
            // Left, Middle, Right can change to themselves only.
            (Some(BoardType::Left), BoardType::Left) => true,
            (Some(BoardType::Left), _) => false,
            (Some(BoardType::Middle), BoardType::Middle) => true,
            (Some(BoardType::Middle), _) => false,
            (Some(BoardType::Right), BoardType::Right) => true,
            (Some(BoardType::Right), _) => false,
        }
    }

    fn induced_by(&self, c: Coordinate) -> bool {
        // Not in the lower left, so it's a free pass.
        if !c.induces_board_type() {
            return true;
        }

        match *self {
            BoardType::Left          => c != Coordinate{row: 2, col: 1} && c != Coordinate{row: 1, col: 1},
            BoardType::LeftOrMiddle  => c == Coordinate{row: 1, col: 0},
            BoardType::Middle        => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 1, col: 1},
            BoardType::RightOrMiddle => c == Coordinate{row: 3, col: 1},
            BoardType::Right         => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 2, col: 0},
        }
    }
}

const POSSIBLE_BOARD_TYPES: [BoardType; 5] = [
    BoardType::Left,
    BoardType::LeftOrMiddle,
    BoardType::Middle,
    BoardType::RightOrMiddle,
    BoardType::Right,
];

pub type BoardArray = [[bool; NUM_COLS]; NUM_ROWS];
pub struct Board {
    board: BoardArray,
    board_type: Option<BoardType>,
}

impl Board {
    pub fn new(array: BoardArray, board_type: Option<BoardType>) -> Board {
        Board{board: array, board_type: board_type}
    }

    pub fn make_move(&mut self, m: Move) {
        if let Some(bt) = m.new_board_type {
            if !bt.applies_to(self.board_type) {
                panic!("Board type is {:?}, not compatible with {:?}", self.board_type, bt);
            }
            self.board_type = m.new_board_type
        }
        self.set_squares(m, true)
    }

    pub fn undo_move(&mut self, m: Move) {
        self.board_type = m.old_board_type;
        self.set_squares(m, false)
    }

    fn set_squares(&mut self, m: Move, mode: bool) {
        self.board[m.coord.row][m.coord.col] = mode;
        for other_space in m.extensions().iter() {
            self.board[other_space.row][other_space.col] = mode;
        }
    }

    fn occupied(&self, c: Coordinate) -> bool {
        self.board[c.row][c.col]
    }

    // This assesses whether a coordinate can be placed on the board,
    // given the current type of the board.
    fn compatible(&self, c: Coordinate) -> bool {
        // Not in the lower left, so it's a free pass.
        if !c.induces_board_type() {
            return true;
        }

        match self.board_type {
            Some(BoardType::Left)          => c != Coordinate{row: 2, col: 1} && c != Coordinate{row: 1, col: 1},
            Some(BoardType::LeftOrMiddle)  => c != Coordinate{row: 1, col: 1},
            Some(BoardType::Middle)        => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 1, col: 1},
            Some(BoardType::RightOrMiddle) => c != Coordinate{row: 3, col: 0},
            Some(BoardType::Right)         => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 2, col: 0},
            None => true,
        }
    }

    fn frontier(&self) -> Vec<Coordinate> {
        let mut results = Vec::new();
        for row in 0..NUM_ROWS {
            for col in 0..NUM_COLS {
                let coord = Coordinate{row: row, col: col};
                if self.occupied(coord) || !self.compatible(coord) {
                    continue;
                }
                let have_neighbor = POSSIBLE_DIRECTIONS.iter().any(|dir| {
                    if let Some(dest) = coord.move_in(*dir, 1) { self.occupied(dest) } else { false }
                });
                if have_neighbor {
                    results.push(coord);
                }
            }
        }
        results
    }

    fn board_type_final(&self) -> bool {
        if let Some(x) = self.board_type { x.is_final() } else { false }
    }

    pub fn legal_moves(&self) -> Vec<Move> {
        let mut results = Vec::new();
        for frontier_space in self.frontier().iter() {
            for move_type in POSSIBLE_MOVE_TYPES.iter() {
                let mov = match Move::new(*frontier_space, *move_type, self.board_type) {
                    Some(x) => x,
                    None => continue,
                };
                let mut other_space_taken = false;
                let mut induces_board_type = frontier_space.induces_board_type();
                for other_space in mov.extensions().iter() {
                    if other_space.induces_board_type() {
                        induces_board_type = true;
                    }
                    if self.occupied(*other_space) || !self.compatible(*other_space) {
                        other_space_taken = true;
                        break;
                    }
                }
                if !other_space_taken {
                    if induces_board_type && !self.board_type_final() {
                        let mut ok_board_types = BTreeSet::new();
                        for board_type in POSSIBLE_BOARD_TYPES.iter() {
                            if !board_type.applies_to(self.board_type) {
                                continue;
                            }
                            if !board_type.induced_by(*frontier_space) {
                                continue;
                            }
                            if mov.extensions().iter().all(|coord| board_type.induced_by(*coord)) {
                                ok_board_types.insert(*board_type);
                            }
                        }

                        // Dominated board types...
                        if ok_board_types.contains(&BoardType::LeftOrMiddle) {
                            ok_board_types.remove(&BoardType::Left);
                            ok_board_types.remove(&BoardType::Middle);
                        }
                        if ok_board_types.contains(&BoardType::RightOrMiddle) {
                            ok_board_types.remove(&BoardType::Right);
                            ok_board_types.remove(&BoardType::Middle);
                        }

                        for board_type in ok_board_types.iter() {
                            results.push(mov.with_board_type(*board_type));
                        }

                    } else {
                        results.push(mov);
                    }
                }
            }
        }
        results
    }

    pub fn print(&self) {
        // Print header row
        print!("   ");
        for i in 0..NUM_COLS {
            print!("{: >5} ", i);
        }
        println!("");

        for (i, row) in self.board.iter().enumerate() {
            print!("{: >2} ", i);
            for col in row.iter() {
                print!("{: >5} ", col);
            }
            println!("");
        }
        println!("{:?}", self.board_type);
    }
}

<commit_msg>Board#legal_moves: Unindent<commit_after>use std::collections::BTreeSet;
use action::{POSSIBLE_DIRECTIONS,POSSIBLE_MOVE_TYPES,Coordinate,Move};

pub const NUM_COLS: usize = 5;
pub const NUM_ROWS: usize = 4;

// Hacks for the three states of the lower-left of the board in JunSeok vs YeonSeung game
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub enum BoardType {
    Left,
    LeftOrMiddle,
    Middle,
    RightOrMiddle,
    Right,
}

impl BoardType {
    fn is_final(&self) -> bool {
        match *self {
            BoardType::Left => true,
            BoardType::Middle => true,
            BoardType::Right => true,
            BoardType::LeftOrMiddle => false,
            BoardType::RightOrMiddle => false,
        }
    }

    // Can a board of type `current` become this type?
    fn applies_to(&self, current: Option<BoardType>) -> bool {
        match (current, *self) {
            // a none board type can change to anything.
            (None, _) => true,
            // LeftOrMiddle can change to itself, left, or middle.
            (Some(BoardType::LeftOrMiddle), BoardType::LeftOrMiddle) => true,
            (Some(BoardType::LeftOrMiddle), BoardType::Left) => true,
            (Some(BoardType::LeftOrMiddle), BoardType::Middle) => true,
            (Some(BoardType::LeftOrMiddle), _) => false,
            // RightOrMiddle can change to itself, right, or middle.
            (Some(BoardType::RightOrMiddle), BoardType::RightOrMiddle) => true,
            (Some(BoardType::RightOrMiddle), BoardType::Right) => true,
            (Some(BoardType::RightOrMiddle), BoardType::Middle) => true,
            (Some(BoardType::RightOrMiddle), _) => false,
            // Left, Middle, Right can change to themselves only.
            (Some(BoardType::Left), BoardType::Left) => true,
            (Some(BoardType::Left), _) => false,
            (Some(BoardType::Middle), BoardType::Middle) => true,
            (Some(BoardType::Middle), _) => false,
            (Some(BoardType::Right), BoardType::Right) => true,
            (Some(BoardType::Right), _) => false,
        }
    }

    fn induced_by(&self, c: Coordinate) -> bool {
        // Not in the lower left, so it's a free pass.
        if !c.induces_board_type() {
            return true;
        }

        match *self {
            BoardType::Left          => c != Coordinate{row: 2, col: 1} && c != Coordinate{row: 1, col: 1},
            BoardType::LeftOrMiddle  => c == Coordinate{row: 1, col: 0},
            BoardType::Middle        => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 1, col: 1},
            BoardType::RightOrMiddle => c == Coordinate{row: 3, col: 1},
            BoardType::Right         => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 2, col: 0},
        }
    }
}

const POSSIBLE_BOARD_TYPES: [BoardType; 5] = [
    BoardType::Left,
    BoardType::LeftOrMiddle,
    BoardType::Middle,
    BoardType::RightOrMiddle,
    BoardType::Right,
];

pub type BoardArray = [[bool; NUM_COLS]; NUM_ROWS];
pub struct Board {
    board: BoardArray,
    board_type: Option<BoardType>,
}

impl Board {
    pub fn new(array: BoardArray, board_type: Option<BoardType>) -> Board {
        Board{board: array, board_type: board_type}
    }

    pub fn make_move(&mut self, m: Move) {
        if let Some(bt) = m.new_board_type {
            if !bt.applies_to(self.board_type) {
                panic!("Board type is {:?}, not compatible with {:?}", self.board_type, bt);
            }
            self.board_type = m.new_board_type
        }
        self.set_squares(m, true)
    }

    pub fn undo_move(&mut self, m: Move) {
        self.board_type = m.old_board_type;
        self.set_squares(m, false)
    }

    fn set_squares(&mut self, m: Move, mode: bool) {
        self.board[m.coord.row][m.coord.col] = mode;
        for other_space in m.extensions().iter() {
            self.board[other_space.row][other_space.col] = mode;
        }
    }

    fn occupied(&self, c: Coordinate) -> bool {
        self.board[c.row][c.col]
    }

    // This assesses whether a coordinate can be placed on the board,
    // given the current type of the board.
    fn compatible(&self, c: Coordinate) -> bool {
        // Not in the lower left, so it's a free pass.
        if !c.induces_board_type() {
            return true;
        }

        match self.board_type {
            Some(BoardType::Left)          => c != Coordinate{row: 2, col: 1} && c != Coordinate{row: 1, col: 1},
            Some(BoardType::LeftOrMiddle)  => c != Coordinate{row: 1, col: 1},
            Some(BoardType::Middle)        => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 1, col: 1},
            Some(BoardType::RightOrMiddle) => c != Coordinate{row: 3, col: 0},
            Some(BoardType::Right)         => c != Coordinate{row: 3, col: 0} && c != Coordinate{row: 2, col: 0},
            None => true,
        }
    }

    fn frontier(&self) -> Vec<Coordinate> {
        let mut results = Vec::new();
        for row in 0..NUM_ROWS {
            for col in 0..NUM_COLS {
                let coord = Coordinate{row: row, col: col};
                if self.occupied(coord) || !self.compatible(coord) {
                    continue;
                }
                let have_neighbor = POSSIBLE_DIRECTIONS.iter().any(|dir| {
                    if let Some(dest) = coord.move_in(*dir, 1) { self.occupied(dest) } else { false }
                });
                if have_neighbor {
                    results.push(coord);
                }
            }
        }
        results
    }

    fn board_type_final(&self) -> bool {
        if let Some(x) = self.board_type { x.is_final() } else { false }
    }

    pub fn legal_moves(&self) -> Vec<Move> {
        let mut results = Vec::new();
        for frontier_space in self.frontier().iter() {
            for move_type in POSSIBLE_MOVE_TYPES.iter() {
                let mov = match Move::new(*frontier_space, *move_type, self.board_type) {
                    Some(x) => x,
                    None => continue,
                };
                let mut other_space_taken = false;
                let mut induces_board_type = frontier_space.induces_board_type();
                for other_space in mov.extensions().iter() {
                    if other_space.induces_board_type() {
                        induces_board_type = true;
                    }
                    if self.occupied(*other_space) || !self.compatible(*other_space) {
                        other_space_taken = true;
                        break;
                    }
                }
                if other_space_taken {
                    continue;
                }

                if !induces_board_type || self.board_type_final() {
                    results.push(mov);
                    continue;
                }

                let mut ok_board_types = BTreeSet::new();
                for board_type in POSSIBLE_BOARD_TYPES.iter() {
                    if !board_type.applies_to(self.board_type) {
                        continue;
                    }
                    if !board_type.induced_by(*frontier_space) {
                        continue;
                    }
                    if mov.extensions().iter().all(|coord| board_type.induced_by(*coord)) {
                        ok_board_types.insert(*board_type);
                    }
                }

                // Dominated board types...
                if ok_board_types.contains(&BoardType::LeftOrMiddle) {
                    ok_board_types.remove(&BoardType::Left);
                    ok_board_types.remove(&BoardType::Middle);
                }
                if ok_board_types.contains(&BoardType::RightOrMiddle) {
                    ok_board_types.remove(&BoardType::Right);
                    ok_board_types.remove(&BoardType::Middle);
                }

                for board_type in ok_board_types.iter() {
                    results.push(mov.with_board_type(*board_type));
                }
            }
        }
        results
    }

    pub fn print(&self) {
        // Print header row
        print!("   ");
        for i in 0..NUM_COLS {
            print!("{: >5} ", i);
        }
        println!("");

        for (i, row) in self.board.iter().enumerate() {
            print!("{: >2} ", i);
            for col in row.iter() {
                print!("{: >5} ", col);
            }
            println!("");
        }
        println!("{:?}", self.board_type);
    }
}

<|endoftext|>


<commit_before>use std;
use std::io;
use std::path::Path;
use std::fs::File;
use std::fs::metadata;
use std::io::prelude::*;
use rustc_serialize::Decodable;
use glob::Pattern;
use toml;
use clean;

pub const HAS_TABS: u8               = 1 << 0;
pub const TRAILING_SPACES: u8        = 1 << 1;
pub const HAS_ILLEGAL_CHARACTERS: u8 = 1 << 2;

fn check_content<'a>(input: &'a str, filename: &str) -> io::Result<u8> {
    debug!("check content of {}", filename);
    let mut result = 0;
    let mut i: u32 = 0;
    for line in input.lines_any() {
        i += 1;
        if line.ends_with(' ') {
            result |= TRAILING_SPACES;
        }
        if line.contains("\t") {
            result |= HAS_TABS;
        }
        if line.as_bytes().iter().any(|x| *x > 127) {
            println!("non ASCII line [{}]: {} [{}]", i, line, filename);
            result |= HAS_ILLEGAL_CHARACTERS;
        }
    }
    Ok(result)
}

pub fn is_dir(path: &Path) -> bool {
    if let Ok(result) = metadata(&path) {
        result.is_dir()
    } else {
        false
    }
}

fn report_offending_line(path: &Path) -> std::io::Result<()> {
    use std::io::BufReader;
    let mut i: u32 = 1;
    let f = try!(File::open(path));
    let file = BufReader::new(f);
    for line in file.lines() {
        match line.ok() {
            Some(_) => i = i + 1,
            None => println!("offending line {} in file [{}]", i, path.display()),
        }
    }
    Ok(())
}

pub fn check_path(path: &Path, clean: bool) -> io::Result<u8> {
    use std::io::ErrorKind;

    let mut f = try!(File::open(path));
    let mut buffer = String::new();
    let mut check = 0;
    if let Err(e) = f.read_to_string(&mut buffer) {
        match e.kind() {
            ErrorKind::InvalidData => {
                check = check | HAS_ILLEGAL_CHARACTERS;
                let _ = report_offending_line(path);
            },
            _ => return Err(e),
        }
    }
    // only check content if we could read the file
    if check == 0 { check = try!(check_content(&buffer, path.to_str().expect("not available"))); }
    if clean {
        let no_spaces = if (check & HAS_TABS) > 0 {
            println!("HAS_TABS:[{}] -> converting to spaces", path.display());
            clean::space_tabs_conversion(buffer, clean::TabStrategy::Untabify)
        } else { buffer };
        let res_string = if (check & TRAILING_SPACES) > 0 {
            println!("TRAILING_SPACES:[{}] -> removing", path.display());
            clean::remove_trailing_whitespaces(no_spaces)
        } else { no_spaces };
        let mut file = try!(File::create(path));
        try!(file.write_all(res_string.as_bytes()));
    }
    else /* report only */ { report(check, &path) }
    Ok(check)
}

fn report(check: u8, path: &Path) -> () {
    if (check & HAS_TABS) > 0 && (check & TRAILING_SPACES) > 0 {
        println!("HAS_TABS && TRAILING_SPACES:[{}]", path.display());
    } else if (check & HAS_TABS) > 0 {
        println!("HAS_TABS:[{}]", path.display());
    } else if (check & TRAILING_SPACES) > 0 {
        println!("TRAILING_SPACES:[{}]", path.display());
    }
}

#[derive(Debug, RustcDecodable, PartialEq)]
pub struct EnforcerCfg {
    pub ignore: Vec<String>,
    pub globs: Vec<String>,
}

pub fn s(x: &str) -> String { x.to_string() }

pub fn default_cfg() -> EnforcerCfg {
    EnforcerCfg {
        ignore: vec![s(".git"), s(".bake"), s(".repo")],
        globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
    }
}

pub fn is_unwanted(comp: std::path::Component, to_ignore: &Vec<String>) -> bool {
    let path_elem = comp.as_os_str()
                        .to_str()
                        .expect(&format!("illegal path component {:?}", comp)[..]);
    to_ignore.iter()
        .any(|x| Pattern::new(x)
            .ok()
            .expect(&format!("{} seems not to be a valid pattern", x)[..])
            .matches(path_elem))
}

pub fn read_config<'a>(input: &'a str) -> io::Result<EnforcerCfg> {
    use std::io::{Error, ErrorKind};
    debug!("read_config");
    let mut parser = toml::Parser::new(input);
    fn default_err() -> Error {
        Error::new(ErrorKind::InvalidData, "could not parse the config")
    }

    parser.parse().map_or(Err(default_err()), |toml| {
        let mut decoder = toml::Decoder::new(toml::Value::Table(toml));
        EnforcerCfg::decode(&mut decoder)
            .ok()
            .map_or(Err(default_err()), |config|
                Ok(config))
    })
}

#[cfg(test)]
mod tests {
    use super::read_config;
    use super::is_unwanted;
    use super::s;
    use glob::Pattern;
    use super::EnforcerCfg;
    use std::ffi::OsStr;
    use std::path::Component::Normal;

    #[test]
    fn test_load_simple_config() {
        let c = include_str!("../samples/.enforcer");
        let cfg = read_config(c).unwrap();
        assert_eq!(cfg.ignore.len(), 2);
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert_eq!(expected.ignore, cfg.ignore);
        assert_eq!(expected, cfg);
    }
    #[test]
    fn test_load_broken_config() {
        let c = include_str!("../samples/.enforcer_broken");
        let cfg = read_config(c).unwrap();
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert!(expected.ignore != cfg.ignore);
    }
    #[test]
    fn test_glob() {
        assert!(Pattern::new("build_*").unwrap().matches("build_Debug"));
    }
    #[test]
    fn test_is_unwanted() {
        let cfg = EnforcerCfg { ignore: vec![s("build_*"), s(".git")], globs: vec![]};
        assert!(is_unwanted(Normal(OsStr::new("build_")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new("build_Debug")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new(".git")), &cfg.ignore));
        assert!(!is_unwanted(Normal(OsStr::new("bla")), &cfg.ignore));
    }
}

<commit_msg>stop when file cannot be read. otherwise we accidently wrote emtpy string to file<commit_after>use std;
use std::io;
use std::path::Path;
use std::fs::File;
use std::fs::metadata;
use std::io::prelude::*;
use rustc_serialize::Decodable;
use glob::Pattern;
use toml;
use clean;

pub const HAS_TABS: u8               = 1 << 0;
pub const TRAILING_SPACES: u8        = 1 << 1;
pub const HAS_ILLEGAL_CHARACTERS: u8 = 1 << 2;

fn check_content<'a>(input: &'a str, filename: &str) -> io::Result<u8> {
    debug!("check content of {}", filename);
    let mut result = 0;
    let mut i: u32 = 0;
    for line in input.lines_any() {
        i += 1;
        if line.ends_with(' ') {
            result |= TRAILING_SPACES;
        }
        if line.contains("\t") {
            result |= HAS_TABS;
        }
        if line.as_bytes().iter().any(|x| *x > 127) {
            println!("non ASCII line [{}]: {} [{}]", i, line, filename);
            result |= HAS_ILLEGAL_CHARACTERS;
        }
    }
    Ok(result)
}

pub fn is_dir(path: &Path) -> bool {
    if let Ok(result) = metadata(&path) {
        result.is_dir()
    } else {
        false
    }
}

fn report_offending_line(path: &Path) -> std::io::Result<()> {
    use std::io::BufReader;
    let mut i: u32 = 1;
    let f = try!(File::open(path));
    let file = BufReader::new(f);
    for line in file.lines() {
        match line.ok() {
            Some(_) => i = i + 1,
            None => println!("offending line {} in file [{}]", i, path.display()),
        }
    }
    Ok(())
}

pub fn check_path(path: &Path, clean: bool) -> io::Result<u8> {
    use std::io::ErrorKind;

    let mut f = try!(File::open(path));
    let mut buffer = String::new();
    let mut check = 0;
    if let Err(e) = f.read_to_string(&mut buffer) {
        match e.kind() {
            ErrorKind::InvalidData => {
                check = check | HAS_ILLEGAL_CHARACTERS;
                let _ = report_offending_line(path);
                return Ok(check)
            },
            _ => return Err(e),
        }
    }
    // only check content if we could read the file
    if check == 0 { check = try!(check_content(&buffer, path.to_str().expect("not available"))); }
    if clean {
        let no_spaces = if (check & HAS_TABS) > 0 {
            println!("HAS_TABS:[{}] -> converting to spaces", path.display());
            clean::space_tabs_conversion(buffer, clean::TabStrategy::Untabify)
        } else { buffer };
        let res_string = if (check & TRAILING_SPACES) > 0 {
            println!("TRAILING_SPACES:[{}] -> removing", path.display());
            clean::remove_trailing_whitespaces(no_spaces)
        } else { no_spaces };
        let mut file = try!(File::create(path));
        try!(file.write_all(res_string.as_bytes()));
    }
    else /* report only */ { report(check, &path) }
    Ok(check)
}

fn report(check: u8, path: &Path) -> () {
    if (check & HAS_TABS) > 0 && (check & TRAILING_SPACES) > 0 {
        println!("HAS_TABS && TRAILING_SPACES:[{}]", path.display());
    } else if (check & HAS_TABS) > 0 {
        println!("HAS_TABS:[{}]", path.display());
    } else if (check & TRAILING_SPACES) > 0 {
        println!("TRAILING_SPACES:[{}]", path.display());
    }
}

#[derive(Debug, RustcDecodable, PartialEq)]
pub struct EnforcerCfg {
    pub ignore: Vec<String>,
    pub globs: Vec<String>,
}

pub fn s(x: &str) -> String { x.to_string() }

pub fn default_cfg() -> EnforcerCfg {
    EnforcerCfg {
        ignore: vec![s(".git"), s(".bake"), s(".repo")],
        globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
    }
}

pub fn is_unwanted(comp: std::path::Component, to_ignore: &Vec<String>) -> bool {
    let path_elem = comp.as_os_str()
                        .to_str()
                        .expect(&format!("illegal path component {:?}", comp)[..]);
    to_ignore.iter()
        .any(|x| Pattern::new(x)
            .ok()
            .expect(&format!("{} seems not to be a valid pattern", x)[..])
            .matches(path_elem))
}

pub fn read_config<'a>(input: &'a str) -> io::Result<EnforcerCfg> {
    use std::io::{Error, ErrorKind};
    debug!("read_config");
    let mut parser = toml::Parser::new(input);
    fn default_err() -> Error {
        Error::new(ErrorKind::InvalidData, "could not parse the config")
    }

    parser.parse().map_or(Err(default_err()), |toml| {
        let mut decoder = toml::Decoder::new(toml::Value::Table(toml));
        EnforcerCfg::decode(&mut decoder)
            .ok()
            .map_or(Err(default_err()), |config|
                Ok(config))
    })
}

#[cfg(test)]
mod tests {
    use super::read_config;
    use super::is_unwanted;
    use super::s;
    use glob::Pattern;
    use super::EnforcerCfg;
    use std::ffi::OsStr;
    use std::path::Component::Normal;

    #[test]
    fn test_load_simple_config() {
        let c = include_str!("../samples/.enforcer");
        let cfg = read_config(c).unwrap();
        assert_eq!(cfg.ignore.len(), 2);
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert_eq!(expected.ignore, cfg.ignore);
        assert_eq!(expected, cfg);
    }
    #[test]
    fn test_load_broken_config() {
        let c = include_str!("../samples/.enforcer_broken");
        let cfg = read_config(c).unwrap();
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert!(expected.ignore != cfg.ignore);
    }
    #[test]
    fn test_glob() {
        assert!(Pattern::new("build_*").unwrap().matches("build_Debug"));
    }
    #[test]
    fn test_is_unwanted() {
        let cfg = EnforcerCfg { ignore: vec![s("build_*"), s(".git")], globs: vec![]};
        assert!(is_unwanted(Normal(OsStr::new("build_")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new("build_Debug")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new(".git")), &cfg.ignore));
        assert!(!is_unwanted(Normal(OsStr::new("bla")), &cfg.ignore));
    }
}

<|endoftext|>


<commit_before>use bson::Document;
use bson::Bson::{FloatingPoint, I64};
use bson::Bson::String as BsonString;
use mongodb::client::cursor::Cursor;
use mongodb::client::wire_protocol::flags::{OpInsertFlags, OpQueryFlags};
use mongodb::client::wire_protocol::operations::Message;
use std::io::Write;
use std::net::TcpStream;

#[test]
fn cursor() {
    match TcpStream::connect("localhost:27017") {
        Ok(mut stream) => {
            let docs : Vec<_> = (0..10).map(|i| {
                let mut doc = Document::new();
                doc.insert("foo".to_owned(), I64(i));

                doc
            }).collect();

            let flags = OpInsertFlags::no_flags();
            let name = "test.test".to_owned();
            let res = Message::with_insert(1, flags, name, docs);

            let cm = match res {
                Ok(message) => message,
                Err(_) => panic!("Could not create insert message!")
            };

            match cm.write(&mut stream) {
                Ok(_) => (),
                Err(s) => panic!("{}", s)
            };

            let doc = Document::new();
            let flags = OpQueryFlags::no_flags();
            let name = "test.test".to_owned();
            let result = Cursor::query_with_batch_size(&mut stream, 3, 2, flags,
                                                       &name, 0, 0, doc, None);

            let mut cursor = match result {
                Ok(c) => c,
                Err(s) => panic!("{}", s)
            };

            let batch = cursor.next_batch();

            assert_eq!(batch.len(), 3 as usize);

            for i in 0..batch.len() {
                match batch[i].get("foo") {
                    Some(&I64(j)) => assert_eq!(i as i64, j),
                    e => panic!("Wrong value returned from Cursor#next_batch: {:?}", e)
                };
            }

            let bson = match cursor.next() {
                Some(b) => b,
                None => panic!("Nothing returned from Cursor#next")
            };

            match bson.get("foo") {
                Some(&I64(3)) => (),
                _ => panic!("Wrong value returned from Cursor#next")
            };

            let vec = cursor.next_n(20);

            assert_eq!(vec.len(), 6 as usize);

            for i in 0..vec.len() {
                match vec[i].get("foo") {
                    Some(&I64(j)) => assert_eq!(4 + i as i64 , j),
                    _ => panic!("Wrong value returned from Cursor#next_batch")
                };
            }
        },
        Err(_) => {
            panic!("Could not connect to server")
        }
    }
}
<commit_msg>minor cleanup for test<commit_after>use bson::Document;
use bson::Bson::{FloatingPoint, I64};
use bson::Bson::String as BsonString;
use mongodb::client::cursor::Cursor;
use mongodb::client::wire_protocol::flags::{OpInsertFlags, OpQueryFlags};
use mongodb::client::wire_protocol::operations::Message;
use std::io::Write;
use std::net::TcpStream;

#[test]
fn cursor_features() {
    match TcpStream::connect("localhost:27017") {
        Ok(mut stream) => {
            let docs : Vec<_> = (0..10).map(|i| {
                let mut doc = Document::new();
                doc.insert("foo".to_owned(), I64(i));

                doc
            }).collect();

            let flags = OpInsertFlags::no_flags();
            let name = "test.test".to_owned();
            let res = Message::with_insert(1, flags, name, docs);

            let cm = match res {
                Ok(message) => message,
                Err(_) => panic!("Could not create insert message!")
            };

            match cm.write(&mut stream) {
                Ok(_) => (),
                Err(s) => panic!("{}", s)
            };

            let doc = Document::new();
            let flags = OpQueryFlags::no_flags();
            let name = "test.test";
            let result = Cursor::query_with_batch_size(&mut stream, 3, 2, flags,
                                                       name, 0, 0, doc, None);

            let mut cursor = match result {
                Ok(c) => c,
                Err(s) => panic!("{}", s)
            };

            let batch = cursor.next_batch();

            assert_eq!(batch.len(), 3 as usize);

            for i in 0..batch.len() {
                match batch[i].get("foo") {
                    Some(&I64(j)) => assert_eq!(i as i64, j),
                    _ => panic!("Wrong value returned from Cursor#next_batch")
                };
            }

            let bson = match cursor.next() {
                Some(b) => b,
                None => panic!("Nothing returned from Cursor#next")
            };

            match bson.get("foo") {
                Some(&I64(3)) => (),
                _ => panic!("Wrong value returned from Cursor#next")
            };

            let vec = cursor.next_n(20);

            assert_eq!(vec.len(), 6 as usize);

            for i in 0..vec.len() {
                match vec[i].get("foo") {
                    Some(&I64(j)) => assert_eq!(4 + i as i64 , j),
                    _ => panic!("Wrong value returned from Cursor#next_batch")
                };
            }
        },
        Err(_) => {
            panic!("Could not connect to server")
        }
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate rand;

use image::{FilterType, GenericImage, Pixel};

use rand::distributions::{Normal, IndependentSample};
use std::fs::File;
use std::path::Path;

fn main() {
    println!("24 days of Rust - image (day 12)");
    let img = image::open(&Path::new("data/in.png")).ok().expect("Opening image failed");
    let filtered = img.fliph();
    let mut out = File::create(&Path::new("out.png")).unwrap();
    let _ = filtered.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let kernel = [-1.0f32, -1.0, -1.0,
                  -1.0, 8.0, -1.0,
                  -1.0, -1.0, -1.0];
    let filtered = img.filter3x3(&kernel);
    let mut out = File::create(&Path::new("out_blur.png")).unwrap();
    let _ = filtered.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let (width, height) = img.dimensions();
    let mut rng = rand::thread_rng();
    let normal = Normal::new(15.0, 15.0);
    let mut noisy = img.brighten(-25);
    for x in 0..(width) {
        for y in 0..(height) {
            let offset = normal.ind_sample(&mut rng) as u8;
            let px = img.get_pixel(x, y).map(|v| if v <= 255 - offset { v + offset } else { 255 });
            noisy.put_pixel(x, y, px);
        }
    }
    let mut out = File::create(&Path::new("out_noisy.png")).unwrap();
    let _ = noisy.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let thumbnail = img.resize(120, 120, FilterType::Lanczos3);
    let mut out = File::create(&Path::new("out_thumb.png")).unwrap();
    let _ = thumbnail.save(&mut out, image::PNG).ok().expect("Saving image failed");
}
<commit_msg>Removed explicit paths from day 12.<commit_after>extern crate image;
extern crate rand;

use image::{FilterType, GenericImage, Pixel};

use rand::distributions::{Normal, IndependentSample};
use std::fs::File;

fn main() {
    println!("24 days of Rust - image (day 12)");
    let img = image::open("data/in.png").ok().expect("Opening image failed");
    let filtered = img.fliph();
    let mut out = File::create("out.png").unwrap();
    let _ = filtered.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let kernel = [-1.0f32, -1.0, -1.0,
                  -1.0, 8.0, -1.0,
                  -1.0, -1.0, -1.0];
    let filtered = img.filter3x3(&kernel);
    let mut out = File::create("out_blur.png").unwrap();
    let _ = filtered.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let (width, height) = img.dimensions();
    let mut rng = rand::thread_rng();
    let normal = Normal::new(15.0, 15.0);
    let mut noisy = img.brighten(-25);
    for x in 0..(width) {
        for y in 0..(height) {
            let offset = normal.ind_sample(&mut rng) as u8;
            let px = img.get_pixel(x, y).map(|v| if v <= 255 - offset { v + offset } else { 255 });
            noisy.put_pixel(x, y, px);
        }
    }
    let mut out = File::create("out_noisy.png").unwrap();
    let _ = noisy.save(&mut out, image::PNG).ok().expect("Saving image failed");

    let thumbnail = img.resize(120, 120, FilterType::Lanczos3);
    let mut out = File::create("out_thumb.png").unwrap();
    let _ = thumbnail.save(&mut out, image::PNG).ok().expect("Saving image failed");
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::ops::{Add, Neg};
use num::bigint::BigInt;
use num::Integer;
use num::Zero;

use euclid::*;

use types::*;

// A "vector" in the world, possibly going up or down levels

// TODO: If memory use becomes a problem, it may be worth converting this to
// using a persistent data structure and sharing the coords deque as
// much as possible

#[derive(Clone)]
pub struct Delta {
    pub zdelta: i16, // How far DOWN the target is

    // TODO: maybe find a faster bigint
    pub coords: TypedVector2D<BigInt, UniverseSpace>,
}

impl Delta {
    // TODO: from
    // pub fn new(top: UVec) -> Delta {
    //     Delta {
    //         zdelta: 0,
    //         coords: TypedVector2D::new(BigInt::from(top.x), BigInt::from(top.y)),
    //     }
    // }

    pub fn zero() -> Delta {
        Delta {
            zdelta: 0,
            coords: TypedVector2D::new(BigInt::zero(), BigInt::zero())
        }
    }

    fn div_vec<T : Integer + From<u32>, U>(v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x.div_floor(&T::from(zoom_scale));
        v.y = v.y.div_floor(&T::from(zoom_scale));
        v
    }

    fn mult_vec<T : Integer + From<u32>, U>(v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x * (T::from(zoom_scale));
        v.y = v.y * (T::from(zoom_scale));
        v
    }

    pub fn shift_target_down(mut self) -> Delta {
        self.coords.x = self.coords.x * (BigInt::from(zoom_scale));
        self.coords.y = self.coords.y * (BigInt::from(zoom_scale));

        self.zdelta += 1;
        self
    }

    pub fn shift_target_down_ref(&self) -> Delta {
        self.clone().shift_target_down()
    }

    pub fn truncate_target_up(&mut self) -> () {
        self.coords.x = self.coords.x.div_floor(&BigInt::from(zoom_scale));
        self.coords.y = self.coords.y.div_floor(&BigInt::from(zoom_scale));

        self.zdelta -= 1;
    }

}

impl PartialEq for Delta {
    fn eq(&self, other: &Delta) -> bool {
        unimplemented!();
    }
}

impl Eq for Delta {}

impl<'a> Add<&'a Delta> for &'a Delta {
    type Output = Delta;

    fn add(self, other: &Delta) -> Delta {
        unimplemented!();
    }
}

// impl<'a, 'b> Add<&'b Delta> for &'a Delta {
//     type Output = Delta;

//     fn add(self, other: &'b Delta) -> Delta {
//         unimplemented!();
//     }
// }

impl Neg for Delta {
    type Output = Delta;

    fn neg(mut self) -> Delta {
        self.coords.iter_mut().map(|c| c.neg());
        self
    }
}
<commit_msg>Fill in more Delta<commit_after>use std::ops::{Add, Neg};
use num::bigint::BigInt;
use num::{Integer, Zero, ToPrimitive};

use euclid::*;

use types::*;

// A "vector" in the world, possibly going up or down levels

// TODO: If memory use becomes a problem, it may be worth converting this to
// using a persistent data structure and sharing the coords deque as
// much as possible

#[derive(Clone)]
pub struct Delta {
    pub zdelta: i16, // How far DOWN the target is

    // TODO: maybe find a faster bigint
    pub coords: TypedVector2D<BigInt, UniverseSpace>,
}

impl Delta {
    // TODO: from
    // pub fn new(top: UVec) -> Delta {
    //     Delta {
    //         zdelta: 0,
    //         coords: TypedVector2D::new(BigInt::from(top.x), BigInt::from(top.y)),
    //     }
    // }

    pub fn zero() -> Delta {
        Delta {
            zdelta: 0,
            coords: TypedVector2D::new(BigInt::zero(), BigInt::zero())
        }
    }

    fn div_vec<T : Integer + From<u32>, U>(v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x.div_floor(&T::from(zoom_scale));
        v.y = v.y.div_floor(&T::from(zoom_scale));
        v
    }

    fn mult_vec<T : Integer + From<u32>, U>(v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x * (T::from(zoom_scale));
        v.y = v.y * (T::from(zoom_scale));
        v
    }

    pub fn shift_target_down(mut self) -> Delta {
        self.coords.x = self.coords.x * (BigInt::from(zoom_scale));
        self.coords.y = self.coords.y * (BigInt::from(zoom_scale));

        self.zdelta += 1;
        self
    }

    pub fn shift_target_down_ref(&self) -> Delta {
        self.clone().shift_target_down()
    }

    pub fn truncate_target_up(&mut self) -> () {
        self.coords.x = self.coords.x.div_floor(&BigInt::from(zoom_scale));
        self.coords.y = self.coords.y.div_floor(&BigInt::from(zoom_scale));

        self.zdelta -= 1;
    }

    pub fn to_uvec(&self) -> UVec {
        UVec::new(self.coords.x.to_i32().unwrap(), self.coords.y.to_i32().unwrap())
    }

}

impl PartialEq for Delta {
    fn eq(&self, other: &Delta) -> bool {
        self.zdelta == other.zdelta && self.coords == other.coords
    }
}

impl Eq for Delta {}

impl<'a> Add<&'a Delta> for &'a Delta {
    type Output = Delta;

    fn add(self, other: &Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(self.coords.x + other.coords.x, self.coords.y + other.coords.y),
        }
    }
}

impl Neg for Delta {
    type Output = Delta;

    fn neg(mut self) -> Delta {
        self.coords.x = -self.coords.x;
        self.coords.y = -self.coords.y;
        self
    }
}
<|endoftext|>


<commit_before>//! Error types and conversion functions.

use std;
use std::error::Error;
use std::fmt;

use gfx;
use glutin;
use winit;

use app_dirs2::AppDirsError;
use gilrs;
use image;
use rodio::decoder::DecoderError;
use toml;
use zip;

/// An enum containing all kinds of game framework errors.
#[derive(Debug)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `EventsLoopProxy` attempts to
    /// wake up an `EventsLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to parse a resource
    ResourceLoadError(String),
    /// Unable to find a resource; the Vec is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(String),
    /// Something went wrong trying to create a window
    WindowError(glutin::CreationError),
    /// Something went wrong trying to read from a file
    IOError(std::io::Error),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    // TODO: Document this better
    /// Something went wrong with Gilrs
    GilrsError(gilrs::Error),
    /// Something else happened; this is generally a bug.
    UnknownError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn description(&self) -> &str {
        match *self {
            GameError::FilesystemError(_) => "Filesystem error",
            GameError::ConfigError(_) => "Config file error",
            GameError::EventLoopError(_) => "Event loop error",
            GameError::ResourceLoadError(_) => "Resource load error",
            GameError::ResourceNotFound(_, _) => "Resource not found",
            GameError::RenderError(_) => "Render error",
            GameError::AudioError(_) => "Audio error",
            GameError::WindowError(_) => "Window error",
            GameError::IOError(_) => "IO error",
            GameError::FontError(_) => "Font error",
            GameError::VideoError(_) => "Video error",
            GameError::ShaderProgramError(_) => "Shader program error",
            GameError::GilrsError(_) => "Gilrs error",
            GameError::UnknownError(_) => "Unknown error",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            GameError::WindowError(ref e) => Some(e),
            GameError::IOError(ref e) => Some(e),
            GameError::ShaderProgramError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<String> for GameError {
    fn from(s: String) -> GameError {
        GameError::UnknownError(s)
    }
}

impl From<AppDirsError> for GameError {
    fn from(e: AppDirsError) -> GameError {
        let errmessage = format!("{}", e);
        GameError::FilesystemError(errmessage)
    }
}
impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(e)
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.description());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.description());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.description());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.description());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.description());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

// TODO: improve winit/glutin error handling.

impl From<winit::EventsLoopClosed> for GameError {
    fn from(_: glutin::EventsLoopClosed) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowError(s)
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    // TODO: Better error type?
    fn from(s: gilrs::Error) -> GameError {
        GameError::GilrsError(s)
    }
}
<commit_msg>More descriptive errors<commit_after>//! Error types and conversion functions.

use std;
use std::error::Error;
use std::fmt;

use gfx;
use glutin;
use winit;

use app_dirs2::AppDirsError;
use gilrs;
use image;
use rodio::decoder::DecoderError;
use toml;
use zip;

/// An enum containing all kinds of game framework errors.
#[derive(Debug)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `EventsLoopProxy` attempts to
    /// wake up an `EventsLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to parse a resource
    ResourceLoadError(String),
    /// Unable to find a resource; the Vec is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(String),
    /// Something went wrong trying to create a window
    WindowError(glutin::CreationError),
    /// Something went wrong trying to read from a file
    IOError(std::io::Error),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    /// Something went wrong with Gilrs
    GilrsError(String),
    /// Something else happened; this is generally a bug.
    UnknownError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn description(&self) -> &str {
        match *self {
            GameError::FilesystemError(_) => "Filesystem error",
            GameError::ConfigError(_) => "Config file error",
            GameError::EventLoopError(_) => "Event loop error",
            GameError::ResourceLoadError(_) => "Resource load error",
            GameError::ResourceNotFound(_, _) => "Resource not found",
            GameError::RenderError(_) => "Render error",
            GameError::AudioError(_) => "Audio error",
            GameError::WindowError(_) => "Window error",
            GameError::IOError(_) => "IO error",
            GameError::FontError(_) => "Font error",
            GameError::VideoError(_) => "Video error",
            GameError::ShaderProgramError(_) => "Shader program error",
            GameError::GilrsError(_) => "Gamepad error",
            GameError::UnknownError(_) => "Unknown error",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            GameError::WindowError(ref e) => Some(e),
            GameError::IOError(ref e) => Some(e),
            GameError::ShaderProgramError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<String> for GameError {
    fn from(s: String) -> GameError {
        GameError::UnknownError(s)
    }
}

impl From<AppDirsError> for GameError {
    fn from(e: AppDirsError) -> GameError {
        let errmessage = format!("{}", e);
        GameError::FilesystemError(errmessage)
    }
}
impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(e)
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.description());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.description());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.description());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.description());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.description());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

// TODO: improve winit/glutin error handling.

impl From<winit::EventsLoopClosed> for GameError {
    fn from(_: glutin::EventsLoopClosed) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowError(s)
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    // TODO: Better error type?
    fn from(s: gilrs::Error) -> GameError {
        let errstr = format!("Gamepad error: {}", s);
        GameError::GilrsError(errstr)
    }
}
<|endoftext|>


<commit_before>use ffi::*;
use std::result;
use util::*;
use std::fmt::{self,Debug,Formatter};

unsafe impl Send for GError {}
unsafe impl Send for Error {}

pub struct Error{
    error: *mut GError
}

impl Debug for Error{
    fn fmt(&self, fmt: &mut Formatter) -> result::Result<(), fmt::Error>{
        fmt.write_str(format!("gst::Error: domain: {}, code: {}, message: {}",self.domain(),self.code(),self.message()).as_ref())
    }
}

impl Drop for Error{
    fn drop(&mut self){
        unsafe{
            if self.error != ptr::null_mut(){
                g_error_free(self.error);
            }
        }
    }
}

impl Error{
    pub fn new(domain: u32, code: i32, message: &str) -> Error{
        let cmessage = CString::new(message).unwrap();
        unsafe{
            Error{error: g_error_new(domain, code, cmessage.as_ptr())}
        }
    }

    pub unsafe fn new_from_g_error(err: *mut GError) -> Error{
        Error{ error: err }
    }

    pub fn message(&self) -> String{
        unsafe{
            if self.error != ptr::null_mut(){
                from_c_str!(mem::transmute((*self.error).message)).to_string()
            }else{
                "".to_string()
            }
        }
    }

    pub fn code(&self) -> i32{
        unsafe{
            if self.error !=ptr::null_mut(){
                (*self.error).code
            }else{
                0
            }
        }
    }

    pub fn domain(&self) -> u32{
        unsafe{
            if self.error != ptr::null_mut(){
                (*self.error).domain
            }else{
                0
            }
        }
    }
}

pub type Result<T> = result::Result<T,Error>;
<commit_msg>error: implement std::error::Error<commit_after>use ffi::*;
use std::result;
use util::*;
use std::fmt::{self,Debug,Formatter,Display};
use std::error;

unsafe impl Send for GError {}
unsafe impl Send for Error {}

pub struct Error{
    error: *mut GError
}

impl Debug for Error{
    fn fmt(&self, fmt: &mut Formatter) -> result::Result<(), fmt::Error>{
        fmt.write_str(format!("gst::Error: domain: {}, code: {}, message: {}",self.domain(),self.code(),self.message()).as_ref())
    }
}

impl Drop for Error{
    fn drop(&mut self){
        unsafe{
            if self.error != ptr::null_mut(){
                g_error_free(self.error);
            }
        }
    }
}

impl Error{
    pub fn new(domain: u32, code: i32, message: &str) -> Error{
        let cmessage = CString::new(message).unwrap();
        unsafe{
            Error{error: g_error_new(domain, code, cmessage.as_ptr())}
        }
    }

    pub unsafe fn new_from_g_error(err: *mut GError) -> Error{
        Error{ error: err }
    }

    pub fn message(&self) -> String{
        unsafe{
            if self.error != ptr::null_mut(){
                from_c_str!(mem::transmute((*self.error).message)).to_string()
            }else{
                "".to_string()
            }
        }
    }

    pub fn code(&self) -> i32{
        unsafe{
            if self.error !=ptr::null_mut(){
                (*self.error).code
            }else{
                0
            }
        }
    }

    pub fn domain(&self) -> u32{
        unsafe{
            if self.error != ptr::null_mut(){
                (*self.error).domain
            }else{
                0
            }
        }
    }
}

impl Display for Error{
    fn fmt(&self, fmt: &mut Formatter) -> result::Result<(), fmt::Error>{
        fmt.write_str(format!("gst::Error: domain: {}, code: {}, message: {}",self.domain(),self.code(),self.message()).as_ref())
    }
}

impl error::Error for Error{
    fn description(&self) -> &str{
        if self.error != ptr::null_mut(){
            unsafe{ from_c_str!(mem::transmute((*self.error).message)) }
        }else{
            ""
        }
    }
}

pub type Result<T> = result::Result<T,Error>;
<|endoftext|>


<commit_before>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use winit;
use gilrs;

/// A key code.
pub use winit::VirtualKeyCode as KeyCode;

/// A struct that holds the state of keyboard modifier buttons such as ctrl or shift.
pub use winit::ModifiersState as KeyMods;
/// A mouse button.
pub use winit::MouseButton;

/// An analog axis of some device (controller, joystick...).
pub use gilrs::Axis;
/// A button of some device (controller, joystick...).
pub use gilrs::Button;

/// `winit` events; nested in a module for re-export neatness.
pub mod winit_event {
    pub use super::winit::{DeviceEvent, ElementState, Event, KeyboardInput, MouseScrollDelta,
                           TouchPhase, WindowEvent};
}

use self::winit_event::*;
/// `winit` event loop.
pub use winit::EventsLoop;

use GameResult;
use context::Context;

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32, _xrel: f32, _yrel: f32) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32) {}

    /// A keyboard button was pressed.
    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
    ) {
        if keycode == KeyCode::Escape {
            ctx.quit();
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: KeyCode, _keymods: KeyMods) {}

    /// A unicode character was received, usually from keyboard input.
    /// This is the intended way of facilitating text input.
    fn text_input_event(&mut self, _ctx: &mut Context, _character: char) {}

    /// A controller button was pressed; instance_id identifies which controller.
    fn controller_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: Button,
        _id: usize,
    ) {
    }

    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _id: usize) {}

    /// A controller axis moved.
    fn controller_axis_event(
        &mut self,
        _ctx: &mut Context,
        _axis: Axis,
        _value: f32,
        _id: usize,
    ) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        debug!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, events_loop: &mut EventsLoop, state: &mut S) -> GameResult
where
    S: EventHandler,
{
    use keyboard;
    use mouse;

    while ctx.continuing {
        ctx.timer_context.tick();
        events_loop.poll_events(|event| {
            ctx.process_event(&event);
            match event {
                Event::WindowEvent { event, .. } => match event {
                    WindowEvent::Resized(width, height) => {
                        state.resize_event(ctx, width, height);
                    }
                    WindowEvent::CloseRequested => {
                        if !state.quit_event(ctx) {
                            ctx.quit();
                        }
                    }
                    WindowEvent::Focused(gained) => {
                        state.focus_event(ctx, gained);
                    }
                    WindowEvent::ReceivedCharacter(ch) => {
                        state.text_input_event(ctx, ch);
                    }
                    WindowEvent::KeyboardInput {
                        input:
                            KeyboardInput {
                                state: element_state,
                                virtual_keycode: Some(keycode),
                                modifiers,
                                ..
                            },
                        ..
                    } => match element_state {
                        ElementState::Pressed => {
                            let repeat = keyboard::is_repeated(ctx, keycode);
                            state.key_down_event(ctx, keycode, modifiers, repeat);
                        }
                        ElementState::Released => {
                            state.key_up_event(ctx, keycode, modifiers);
                        }
                    },
                    WindowEvent::MouseWheel { delta, .. } => {
                        let (x, y) = match delta {
                            MouseScrollDelta::LineDelta(x, y) => (x, y),
                            MouseScrollDelta::PixelDelta(x, y) => (x, y),
                        };
                        state.mouse_wheel_event(ctx, x, y);
                    }
                    WindowEvent::MouseInput {
                        state: element_state,
                        button,
                        ..
                    } => {
                        let position = mouse::get_position(ctx);
                        match element_state {
                            ElementState::Pressed => {
                                state.mouse_button_down_event(ctx, button, position.x, position.y)
                            }
                            ElementState::Released => {
                                state.mouse_button_up_event(ctx, button, position.x, position.y)
                            }
                        }
                    }
                    WindowEvent::CursorMoved { .. } => {
                        let position = mouse::get_position(ctx);
                        let delta = mouse::get_delta(ctx);
                        state.mouse_motion_event(ctx, position.x, position.y, delta.x, delta.y);
                    }
                    _ => (),
                },
                Event::DeviceEvent { event, .. } => match event {
                    _ => (),
                },
                Event::Awakened => unimplemented!(),
                Event::Suspended(_) => unimplemented!(),
            }
        });
        while let Some(gilrs::Event{id, event,..}) = ctx.gamepad_context.gilrs.next_event() {
            match event {
                gilrs::EventType::ButtonPressed(button, _) => {
                    state.controller_button_down_event(ctx, button, id);
                }
                gilrs::EventType::ButtonReleased(button, _) => {
                    state.controller_button_up_event(ctx, button, id);
                }
                gilrs::EventType::AxisChanged(axis, value, _) => {
                    state.controller_axis_event(ctx, axis, value, id);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<commit_msg>Update documenation<commit_after>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use gilrs;
use winit;

/// A key code.
pub use winit::VirtualKeyCode as KeyCode;

/// A struct that holds the state of keyboard modifier buttons such as ctrl or shift.
pub use winit::ModifiersState as KeyMods;
/// A mouse button.
pub use winit::MouseButton;

/// An analog axis of some device (controller, joystick...).
pub use gilrs::Axis;
/// A button of some device (controller, joystick...).
pub use gilrs::Button;

/// `winit` events; nested in a module for re-export neatness.
pub mod winit_event {
    pub use super::winit::{DeviceEvent, ElementState, Event, KeyboardInput, MouseScrollDelta,
                           TouchPhase, WindowEvent};
}

use self::winit_event::*;
/// `winit` event loop.
pub use winit::EventsLoop;

use context::Context;
use GameResult;

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32, _xrel: f32, _yrel: f32) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32) {}

    /// A keyboard button was pressed.
    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
    ) {
        if keycode == KeyCode::Escape {
            ctx.quit();
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: KeyCode, _keymods: KeyMods) {}

    /// A unicode character was received, usually from keyboard input.
    /// This is the intended way of facilitating text input.
    fn text_input_event(&mut self, _ctx: &mut Context, _character: char) {}

    /// A controller button was pressed; id identifies which controller.
    fn controller_button_down_event(&mut self, _ctx: &mut Context, _btn: Button, _id: usize) {}

    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _id: usize) {}

    /// A controller axis moved.
    fn controller_axis_event(&mut self, _ctx: &mut Context, _axis: Axis, _value: f32, _id: usize) {}

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        debug!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, events_loop: &mut EventsLoop, state: &mut S) -> GameResult
where
    S: EventHandler,
{
    use keyboard;
    use mouse;

    while ctx.continuing {
        ctx.timer_context.tick();
        events_loop.poll_events(|event| {
            ctx.process_event(&event);
            match event {
                Event::WindowEvent { event, .. } => match event {
                    WindowEvent::Resized(width, height) => {
                        state.resize_event(ctx, width, height);
                    }
                    WindowEvent::CloseRequested => {
                        if !state.quit_event(ctx) {
                            ctx.quit();
                        }
                    }
                    WindowEvent::Focused(gained) => {
                        state.focus_event(ctx, gained);
                    }
                    WindowEvent::ReceivedCharacter(ch) => {
                        state.text_input_event(ctx, ch);
                    }
                    WindowEvent::KeyboardInput {
                        input:
                            KeyboardInput {
                                state: element_state,
                                virtual_keycode: Some(keycode),
                                modifiers,
                                ..
                            },
                        ..
                    } => match element_state {
                        ElementState::Pressed => {
                            let repeat = keyboard::is_repeated(ctx, keycode);
                            state.key_down_event(ctx, keycode, modifiers, repeat);
                        }
                        ElementState::Released => {
                            state.key_up_event(ctx, keycode, modifiers);
                        }
                    },
                    WindowEvent::MouseWheel { delta, .. } => {
                        let (x, y) = match delta {
                            MouseScrollDelta::LineDelta(x, y) => (x, y),
                            MouseScrollDelta::PixelDelta(x, y) => (x, y),
                        };
                        state.mouse_wheel_event(ctx, x, y);
                    }
                    WindowEvent::MouseInput {
                        state: element_state,
                        button,
                        ..
                    } => {
                        let position = mouse::get_position(ctx);
                        match element_state {
                            ElementState::Pressed => {
                                state.mouse_button_down_event(ctx, button, position.x, position.y)
                            }
                            ElementState::Released => {
                                state.mouse_button_up_event(ctx, button, position.x, position.y)
                            }
                        }
                    }
                    WindowEvent::CursorMoved { .. } => {
                        let position = mouse::get_position(ctx);
                        let delta = mouse::get_delta(ctx);
                        state.mouse_motion_event(ctx, position.x, position.y, delta.x, delta.y);
                    }
                    _ => (),
                },
                Event::DeviceEvent { event, .. } => match event {
                    _ => (),
                },
                Event::Awakened => unimplemented!(),
                Event::Suspended(_) => unimplemented!(),
            }
        });
        while let Some(gilrs::Event { id, event, .. }) = ctx.gamepad_context.gilrs.next_event() {
            match event {
                gilrs::EventType::ButtonPressed(button, _) => {
                    state.controller_button_down_event(ctx, button, id);
                }
                gilrs::EventType::ButtonReleased(button, _) => {
                    state.controller_button_up_event(ctx, button, id);
                }
                gilrs::EventType::AxisChanged(axis, value, _) => {
                    state.controller_axis_event(ctx, axis, value, id);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Interfaces to VST events.
// TODO: Update and explain both host and plugin events

use std::{mem, slice};

use api;

/// A VST event.
#[derive(Copy, Clone)]
pub enum Event<'a> {
    /// A midi event.
    ///
    /// These are sent to the plugin before `Plugin::processing()` or `Plugin::processing_f64()` is
    /// called.
    Midi(MidiEvent),

    /// A system exclusive event.
    ///
    /// This is just a block of data and it is up to the plugin to interpret this. Generally used
    /// by midi controllers.
    SysEx(SysExEvent<'a>),

    /// A deprecated event.
    ///
    /// Passes the raw midi event structure along with this so that implementors can handle
    /// optionally handle this event.
    Deprecated(api::Event),
}

/// A midi event.
///
/// These are sent to the plugin before `Plugin::processing()` or `Plugin::processing_f64()` is
/// called.
#[derive(Copy, Clone)]
pub struct MidiEvent {
    /// The raw midi data associated with this event.
    pub data: [u8; 3],

    /// Number of samples into the current processing block that this event occurs on.
    ///
    /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
    /// `samples[123]`.
    // TODO: Don't repeat this value in all event types
    pub delta_frames: i32,

    /// This midi event was created live as opposed to being played back in the sequencer.
    ///
    /// This can give the plugin priority over this event if it introduces a lot of latency.
    pub live: bool,

    /// The length of the midi note associated with this event, if available.
    pub note_length: Option<i32>,

    /// Offset in samples into note from note start, if available.
    pub note_offset: Option<i32>,

    /// Detuning between -63 and +64 cents.
    pub detune: i8,

    /// Note off velocity between 0 and 127.
    pub note_off_velocity: u8,
}

/// A system exclusive event.
///
/// This is just a block of data and it is up to the plugin to interpret this. Generally used
/// by midi controllers.
#[derive(Copy, Clone)]
pub struct SysExEvent<'a> {
    /// The SysEx payload.
    pub payload: &'a [u8],

    /// Number of samples into the current processing block that this event occurs on.
    ///
    /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
    /// `samples[123]`.
    pub delta_frames: i32,
}

impl<'a> From<api::Event> for Event<'a> {
    fn from(event: api::Event) -> Event<'a> {
        use api::EventType::*;

        match event.event_type {
            Midi => {
                let event: api::MidiEvent = unsafe { mem::transmute(event) };

                let length = if event.note_length > 0 {
                    Some(event.note_length)
                } else {
                    None
                };
                let offset = if event.note_offset > 0 {
                    Some(event.note_offset)
                } else {
                    None
                };
                let flags = api::MidiEventFlags::from_bits(event.flags).unwrap();

                Event::Midi(MidiEvent {
                    data: event.midi_data,
                    delta_frames: event.delta_frames,
                    live: flags.intersects(api::MidiEventFlags::REALTIME_EVENT),
                    note_length: length,
                    note_offset: offset,
                    detune: event.detune,
                    note_off_velocity: event.note_off_velocity,
                })
            }

            SysEx => Event::SysEx(SysExEvent {
                payload: unsafe {
                    // We can safely transmute the event pointer to a `SysExEvent` pointer as
                    // event_type refers to a `SysEx` type.
                    #[allow(clippy::cast_ptr_alignment)]
                    let event: &api::SysExEvent =
                        &*(&event as *const api::Event as *const api::SysExEvent);
                    slice::from_raw_parts(event.system_data, event.data_size as usize)
                },

                delta_frames: event.delta_frames,
            }),

            _ => Event::Deprecated(event),
        }
    }
}
<commit_msg>Replace transmute with just pointer cast<commit_after>//! Interfaces to VST events.
// TODO: Update and explain both host and plugin events

use std::{mem, slice};

use api;

/// A VST event.
#[derive(Copy, Clone)]
pub enum Event<'a> {
    /// A midi event.
    ///
    /// These are sent to the plugin before `Plugin::processing()` or `Plugin::processing_f64()` is
    /// called.
    Midi(MidiEvent),

    /// A system exclusive event.
    ///
    /// This is just a block of data and it is up to the plugin to interpret this. Generally used
    /// by midi controllers.
    SysEx(SysExEvent<'a>),

    /// A deprecated event.
    ///
    /// Passes the raw midi event structure along with this so that implementors can handle
    /// optionally handle this event.
    Deprecated(api::Event),
}

/// A midi event.
///
/// These are sent to the plugin before `Plugin::processing()` or `Plugin::processing_f64()` is
/// called.
#[derive(Copy, Clone)]
pub struct MidiEvent {
    /// The raw midi data associated with this event.
    pub data: [u8; 3],

    /// Number of samples into the current processing block that this event occurs on.
    ///
    /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
    /// `samples[123]`.
    // TODO: Don't repeat this value in all event types
    pub delta_frames: i32,

    /// This midi event was created live as opposed to being played back in the sequencer.
    ///
    /// This can give the plugin priority over this event if it introduces a lot of latency.
    pub live: bool,

    /// The length of the midi note associated with this event, if available.
    pub note_length: Option<i32>,

    /// Offset in samples into note from note start, if available.
    pub note_offset: Option<i32>,

    /// Detuning between -63 and +64 cents.
    pub detune: i8,

    /// Note off velocity between 0 and 127.
    pub note_off_velocity: u8,
}

/// A system exclusive event.
///
/// This is just a block of data and it is up to the plugin to interpret this. Generally used
/// by midi controllers.
#[derive(Copy, Clone)]
pub struct SysExEvent<'a> {
    /// The SysEx payload.
    pub payload: &'a [u8],

    /// Number of samples into the current processing block that this event occurs on.
    ///
    /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
    /// `samples[123]`.
    pub delta_frames: i32,
}

impl<'a> From<api::Event> for Event<'a> {
    fn from(event: api::Event) -> Event<'a> {
        use api::EventType::*;

        match event.event_type {
            Midi => {
                let event: api::MidiEvent = unsafe { mem::transmute(event) };

                let length = if event.note_length > 0 {
                    Some(event.note_length)
                } else {
                    None
                };
                let offset = if event.note_offset > 0 {
                    Some(event.note_offset)
                } else {
                    None
                };
                let flags = api::MidiEventFlags::from_bits(event.flags).unwrap();

                Event::Midi(MidiEvent {
                    data: event.midi_data,
                    delta_frames: event.delta_frames,
                    live: flags.intersects(api::MidiEventFlags::REALTIME_EVENT),
                    note_length: length,
                    note_offset: offset,
                    detune: event.detune,
                    note_off_velocity: event.note_off_velocity,
                })
            }

            SysEx => Event::SysEx(SysExEvent {
                payload: unsafe {
                    // We can safely cast the event pointer to a `SysExEvent` pointer as
                    // event_type refers to a `SysEx` type.
                    #[allow(clippy::cast_ptr_alignment)]
                    let event: &api::SysExEvent =
                        &*(&event as *const api::Event as *const api::SysExEvent);
                    slice::from_raw_parts(event.system_data, event.data_size as usize)
                },

                delta_frames: event.delta_frames,
            }),

            _ => Event::Deprecated(event),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use gdk_ffi as ffi;

use EventType;
use Window;

glib_wrapper! {
    /// A generic GDK event.
    pub struct Event(Boxed<ffi::GdkEvent>);

    match fn {
        copy => |ptr| ffi::gdk_event_copy(ptr),
        free => |ptr| ffi::gdk_event_free(ptr),
    }
}

impl Event {
    /// Returns the event type.
    pub fn get_event_type(&self) -> EventType {
        self.as_ref().type_
    }

    /// Returns the associated `Window` if applicable.
    pub fn get_window(&self) -> Option<Window> {
        unsafe { from_glib_none(self.as_ref().window) }
    }

    /// Returns whether the event was sent explicitly.
    pub fn get_send_event(&self) -> bool {
        from_glib(self.as_ref().send_event as i32)
    }

    /// Tries to downcast to a specific event type.
    pub fn downcast<T: FromEvent>(self) -> Result<T, Self> {
        T::from(self)
    }
}

/// A helper trait implemented by all event subtypes.
pub trait FromEvent: Sized {
    fn from(ev: Event) -> Result<Self, Event>;
}

macro_rules! event_wrapper {
    ($name:ident, $ffi_name:ident) => {
        impl<'a> ToGlibPtr<'a, *const ::gdk_ffi::$ffi_name> for $name {
            type Storage = &'a Self;

            #[inline]
            fn to_glib_none(&'a self) -> Stash<'a, *const ::gdk_ffi::$ffi_name, Self> {
                let ptr = ToGlibPtr::<*const ::gdk_ffi::GdkEvent>::to_glib_none(&self.0).0;
                Stash(ptr as *const ::gdk_ffi::$ffi_name, self)
            }
        }

        impl<'a> ToGlibPtrMut<'a, *mut ::gdk_ffi::$ffi_name> for $name {
            type Storage = &'a mut Self;

            #[inline]
            fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ::gdk_ffi::$ffi_name, Self> {
                let ptr = ToGlibPtrMut::<*mut ::gdk_ffi::GdkEvent>::to_glib_none_mut(&mut self.0).0;
                StashMut(ptr as *mut ::gdk_ffi::$ffi_name, self)
            }
        }

        impl FromGlibPtr<*mut ::gdk_ffi::$ffi_name> for $name {
            #[inline]
            unsafe fn from_glib_none(ptr: *mut ::gdk_ffi::$ffi_name) -> Self {
                $name(from_glib_none(ptr as *mut ::gdk_ffi::GdkEvent))
            }

            #[inline]
            unsafe fn from_glib_full(ptr: *mut ::gdk_ffi::$ffi_name) -> Self {
                $name(from_glib_full(ptr as *mut ::gdk_ffi::GdkEvent))
            }
        }

        impl AsRef<::gdk_ffi::$ffi_name> for $name {
            #[inline]
            fn as_ref(&self) -> &::gdk_ffi::$ffi_name {
                unsafe {
                    let ptr: *const ::gdk_ffi::$ffi_name = self.to_glib_none().0;
                    &*ptr
                }
            }
        }

        impl AsMut<::gdk_ffi::$ffi_name> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut ::gdk_ffi::$ffi_name {
                unsafe {
                    let ptr: *mut ::gdk_ffi::$ffi_name = self.to_glib_none_mut().0;
                    &mut *ptr
                }
            }
        }
    }
}

event_wrapper!(Event, GdkEventAny);

macro_rules! event_subtype {
    ($name:ident, $($ty:ident)|+) => {
        impl ::event::FromEvent for $name {
            fn from(ev: ::event::Event) -> Result<Self, ::event::Event> {
                skip_assert_initialized!();
                use EventType::*;
                match ev.as_ref().type_ {
                    $($ty)|+ => Ok($name(ev)),
                    _ => Err(ev),
                }
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = ::event::Event;

            fn deref(&self) -> &::event::Event {
                &self.0
            }
        }

        impl ::std::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut ::event::Event {
                &mut self.0
            }
        }
    }
}
<commit_msg>Add `Event::is` to go with `downcast`<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use gdk_ffi as ffi;

use EventType;
use Window;

glib_wrapper! {
    /// A generic GDK event.
    pub struct Event(Boxed<ffi::GdkEvent>);

    match fn {
        copy => |ptr| ffi::gdk_event_copy(ptr),
        free => |ptr| ffi::gdk_event_free(ptr),
    }
}

impl Event {
    /// Returns the event type.
    pub fn get_event_type(&self) -> EventType {
        self.as_ref().type_
    }

    /// Returns the associated `Window` if applicable.
    pub fn get_window(&self) -> Option<Window> {
        unsafe { from_glib_none(self.as_ref().window) }
    }

    /// Returns whether the event was sent explicitly.
    pub fn get_send_event(&self) -> bool {
        from_glib(self.as_ref().send_event as i32)
    }

    /// Returns `true` if the event type matches `T`.
    pub fn is<T: FromEvent>(&self) -> bool {
        T::is(self)
    }

    /// Tries to downcast to a specific event type.
    pub fn downcast<T: FromEvent>(self) -> Result<T, Self> {
        T::from(self)
    }
}

/// A helper trait implemented by all event subtypes.
pub trait FromEvent: Sized {
    fn is(ev: &Event) -> bool;
    fn from(ev: Event) -> Result<Self, Event>;
}

macro_rules! event_wrapper {
    ($name:ident, $ffi_name:ident) => {
        impl<'a> ToGlibPtr<'a, *const ::gdk_ffi::$ffi_name> for $name {
            type Storage = &'a Self;

            #[inline]
            fn to_glib_none(&'a self) -> Stash<'a, *const ::gdk_ffi::$ffi_name, Self> {
                let ptr = ToGlibPtr::<*const ::gdk_ffi::GdkEvent>::to_glib_none(&self.0).0;
                Stash(ptr as *const ::gdk_ffi::$ffi_name, self)
            }
        }

        impl<'a> ToGlibPtrMut<'a, *mut ::gdk_ffi::$ffi_name> for $name {
            type Storage = &'a mut Self;

            #[inline]
            fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ::gdk_ffi::$ffi_name, Self> {
                let ptr = ToGlibPtrMut::<*mut ::gdk_ffi::GdkEvent>::to_glib_none_mut(&mut self.0).0;
                StashMut(ptr as *mut ::gdk_ffi::$ffi_name, self)
            }
        }

        impl FromGlibPtr<*mut ::gdk_ffi::$ffi_name> for $name {
            #[inline]
            unsafe fn from_glib_none(ptr: *mut ::gdk_ffi::$ffi_name) -> Self {
                $name(from_glib_none(ptr as *mut ::gdk_ffi::GdkEvent))
            }

            #[inline]
            unsafe fn from_glib_full(ptr: *mut ::gdk_ffi::$ffi_name) -> Self {
                $name(from_glib_full(ptr as *mut ::gdk_ffi::GdkEvent))
            }
        }

        impl AsRef<::gdk_ffi::$ffi_name> for $name {
            #[inline]
            fn as_ref(&self) -> &::gdk_ffi::$ffi_name {
                unsafe {
                    let ptr: *const ::gdk_ffi::$ffi_name = self.to_glib_none().0;
                    &*ptr
                }
            }
        }

        impl AsMut<::gdk_ffi::$ffi_name> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut ::gdk_ffi::$ffi_name {
                unsafe {
                    let ptr: *mut ::gdk_ffi::$ffi_name = self.to_glib_none_mut().0;
                    &mut *ptr
                }
            }
        }
    }
}

event_wrapper!(Event, GdkEventAny);

macro_rules! event_subtype {
    ($name:ident, $($ty:ident)|+) => {
        impl ::event::FromEvent for $name {
            #[inline]
            fn is(ev: &::event::Event) -> bool {
                skip_assert_initialized!();
                use EventType::*;
                match ev.as_ref().type_ {
                    $($ty)|+ => true,
                    _ => false,
                }
            }

            #[inline]
            fn from(ev: ::event::Event) -> Result<Self, ::event::Event> {
                skip_assert_initialized!();
                if Self::is(&ev) {
                    Ok($name(ev))
                }
                else {
                    Err(ev)
                }
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = ::event::Event;

            fn deref(&self) -> &::event::Event {
                &self.0
            }
        }

        impl ::std::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut ::event::Event {
                &mut self.0
            }
        }
    }
}
<|endoftext|>