<commit_before>#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]
#![feature(slicing_syntax)]

extern crate gfx;
extern crate wad;
extern crate math;

extern crate getopts;
#[phase(plugin, link)]
extern crate gl;
extern crate libc;
#[phase(plugin, link)]
extern crate log;
extern crate sdl2;
extern crate time;

use ctrl::GameController;
use ctrl::Gesture;
use gfx::ShaderLoader;
use level::Level;
use libc::c_void;
use math::{Mat4, Vec3};
use player::Player;
use sdl2::scancode::ScanCode;
use sdl2::video::GLAttr;
use sdl2::video::WindowPos;
use std::default::Default;
use wad::TextureDirectory;

pub mod camera;
pub mod ctrl;
pub mod player;
pub mod level;

const WINDOW_TITLE: &'static str = "Rusty Doom v0.0.7 - Toggle mouse with \
                                    backtick key (`))";
const OPENGL_DEPTH_SIZE: int = 24;
const SHADER_ROOT: &'static str = "src/shaders";

pub struct MainWindow {
    window: sdl2::video::Window,
    _context: sdl2::video::GLContext,
}
impl MainWindow {
    pub fn new(width: uint, height: uint) -> MainWindow {
        sdl2::video::gl_set_attribute(GLAttr::GLContextMajorVersion,
                                      gl::platform::GL_MAJOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLContextMinorVersion,
                                      gl::platform::GL_MINOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLDepthSize, OPENGL_DEPTH_SIZE);
        sdl2::video::gl_set_attribute(GLAttr::GLDoubleBuffer, 1);
        sdl2::video::gl_set_attribute(
            GLAttr::GLContextProfileMask,
            sdl2::video::ll::SDL_GLprofile::SDL_GL_CONTEXT_PROFILE_CORE as int);

        let window = sdl2::video::Window::new(
            WINDOW_TITLE, WindowPos::PosCentered, WindowPos::PosCentered,
            width as int, height as int,
            sdl2::video::OPENGL | sdl2::video::SHOWN).unwrap();

        let context = window.gl_create_context().unwrap();
        sdl2::clear_error();
        gl::load_with(|name| {
            match sdl2::video::gl_get_proc_address(name) {
                Some(glproc) => glproc as *const libc::c_void,
                None => {
                    warn!("missing GL function: {}", name);
                    std::ptr::null()
                }
            }
        });
        let mut vao_id = 0;
        check_gl_unsafe!(gl::GenVertexArrays(1, &mut vao_id));
        check_gl_unsafe!(gl::BindVertexArray(vao_id));
        MainWindow {
           window: window,
            _context: context,
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        let (w, h) = self.window.get_size();
        w as f32 / h as f32
    }

    pub fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }
}

pub struct GameConfig<'a> {
    wad: &'a str,
    metadata: &'a str,
    level_index: uint,
    fov: f32,
}

pub struct Game {
    window: MainWindow,
    player: Player,
    level: Level,
}
impl Game {
    pub fn new(window: MainWindow, config: GameConfig) -> Game {
        let mut wad = wad::Archive::open(&Path::new(config.wad),
                                         &Path::new(config.metadata)).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(gl::platform::GLSL_VERSION_STRING,
                                              Path::new(SHADER_ROOT));
        let level = Level::new(&shader_loader,
                               &mut wad, &textures, config.level_index);

        check_gl_unsafe!(gl::ClearColor(0.06, 0.07, 0.09, 0.0));
        check_gl_unsafe!(gl::Enable(gl::DEPTH_TEST));
        check_gl_unsafe!(gl::DepthFunc(gl::LESS));

        let start = *level.get_start_pos();
        let mut player = Player::new(config.fov, window.aspect_ratio(),
                                     Default::default());
        player.set_position(&Vec3::new(start.x, 0.3, start.y));

        Game {
            window: window,
            player: player,
            level: level
        }
    }

    pub fn run(&mut self) {
        let quit_gesture = Gesture::AnyOf(
            vec![Gesture::QuitTrigger,
                 Gesture::KeyTrigger(ScanCode::Escape)]);
        let grab_toggle_gesture = Gesture::KeyTrigger(ScanCode::Grave);

        let mut cum_time = 0.0;
        let mut cum_updates_time = 0.0;
        let mut num_frames = 0.0;
        let mut t0 = 0.0;
        let mut control = GameController::new();
        let mut mouse_grabbed = true;
        loop {
            check_gl_unsafe!(
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
            let t1 = time::precise_time_s();
            let mut delta = (t1 - t0) as f32;
            if delta < 1e-10 { delta = 1.0 / 60.0; }
            let delta = delta;
            t0 = t1;

            let updates_t0 = time::precise_time_s();

            control.update();
            if control.poll_gesture(&quit_gesture) {
                break;
            } else if control.poll_gesture(&grab_toggle_gesture) {
                mouse_grabbed = !mouse_grabbed;
                control.set_mouse_enabled(mouse_grabbed);
                control.set_cursor_grabbed(mouse_grabbed);
            }

            self.player.update(delta, &control);
            self.level.render(
                delta,
                &self.player.get_camera()
                .multiply_transform(&Mat4::new_identity()));

            let updates_t1 = time::precise_time_s();
            cum_updates_time += updates_t1 - updates_t0;

            cum_time += delta as f64;
            num_frames += 1.0 as f64;
            if cum_time > 2.0 {
                let fps = num_frames / cum_time;
                let cpums = 1000.0 * cum_updates_time / num_frames as f64;
                info!("Frame time: {:.2}ms ({:.2}ms cpu, FPS: {:.2})",
                      1000.0 / fps, cpums, fps);
                cum_time = 0.0;
                cum_updates_time = 0.0;
                num_frames = 0.0;
            }

            self.window.swap_buffers();
        }
    }
}

#[cfg(not(test))]
pub fn run() {
    use getopts::{optopt,optflag,getopts, usage};
    use std::os;

    let args: Vec<String> = os::args();
    let opts = [
        optopt("i", "iwad",
               "set initial wad file to use wad [default='doom1.wad']", "FILE"),
        optopt("m", "metadata",
               "path to toml toml metadata file [default='doom.toml']", "FILE"),
        optopt("l", "level",
               "the index of the level to render [default=0]", "N"),
        optopt("f", "fov",
               "horizontal field of view to please TotalHalibut [default=65]",
               "FLOAT"),
        optopt("r", "resolution",
               "the resolution at which to render the game [default=1280x720]",
               "WIDTHxHEIGHT"),
        optflag("d", "dump-levels", "list all levels and exit."),
        optflag("", "load-all", "loads all levels and exit; for debugging"),
        optflag("h", "help", "print this help message and exit"),
    ];

    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };

    let wad_filename = matches
        .opt_str("i")
        .unwrap_or("doom1.wad".to_string());
    let meta_filename = matches
        .opt_str("m")
        .unwrap_or("doom.toml".to_string());
    let (width, height) = matches
        .opt_str("r")
        .map(|r| {
            let v = r[].splitn(1, 'x').collect::<Vec<&str>>();
            if v.len() != 2 { None } else { Some(v) }
            .and_then(|v| from_str::<uint>(v[0]).map(|v0| (v0, v[1])))
            .and_then(|(v0, s)| from_str::<uint>(s).map(|v1| (v0, v1)))
            .expect("Invalid format for resolution, please use WIDTHxHEIGHT.")
        })
        .unwrap_or((1280, 720));
    let level_index = matches
        .opt_str("l")
        .map(|l| from_str::<uint>(l[])
            .expect("Invalid value for --level. Expected integer."))
        .unwrap_or(0);
    let fov = matches
        .opt_str("f")
        .map(|f| from_str::<f32>(f[])
             .expect("Invalid value for --fov. Expected float."))
        .unwrap_or(65.0);

    if matches.opt_present("h") {
        println!("{}", usage("A rust doom renderer.", &opts));
        return;
    }

    if matches.opt_present("d") {
        let wad = wad::Archive::open(
            &Path::new(wad_filename[]), &Path::new(meta_filename[])).unwrap();
        for i_level in range(0, wad.num_levels()) {
            println!("{:3} {:8}", i_level, wad.get_level_name(i_level));
        }
        return;
    }

    if matches.opt_present("load-all") {
        if !sdl2::init(sdl2::INIT_VIDEO) {
            panic!("main: sdl video init failed.");
        }
        let _win = MainWindow::new(width, height);
        let t0 = time::precise_time_s();
        let mut wad = wad::Archive::open(
            &Path::new(wad_filename[]), &Path::new(meta_filename[])).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        for level_index in range(0, wad.num_levels()) {
            let shader_loader = ShaderLoader::new(
                gl::platform::GLSL_VERSION_STRING, Path::new(SHADER_ROOT));
            Level::new(&shader_loader, &mut wad, &textures, level_index);
        }
        println!("Done, loaded all levels in {:.4}s. Shutting down...",
                 time::precise_time_s() - t0);
        sdl2::quit();
        return;
    }

    if !sdl2::init(sdl2::INIT_VIDEO) { panic!("main: sdl video init failed."); }

    let mut game = Game::new(
        MainWindow::new(width, height),
        GameConfig {
            wad: wad_filename[],
            metadata: meta_filename[],
            level_index: level_index,
            fov: fov,
        });
    game.run();

    info!("Shutting down.");
    drop(game);
    sdl2::quit();
}
<commit_msg>from_str(s) depreciated in favor of s.parse()<commit_after>#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]
#![feature(slicing_syntax)]

extern crate gfx;
extern crate wad;
extern crate math;

extern crate getopts;
#[phase(plugin, link)]
extern crate gl;
extern crate libc;
#[phase(plugin, link)]
extern crate log;
extern crate sdl2;
extern crate time;

use ctrl::GameController;
use ctrl::Gesture;
use gfx::ShaderLoader;
use level::Level;
use libc::c_void;
use math::{Mat4, Vec3};
use player::Player;
use sdl2::scancode::ScanCode;
use sdl2::video::GLAttr;
use sdl2::video::WindowPos;
use std::default::Default;
use wad::TextureDirectory;

pub mod camera;
pub mod ctrl;
pub mod player;
pub mod level;

const WINDOW_TITLE: &'static str = "Rusty Doom v0.0.7 - Toggle mouse with \
                                    backtick key (`))";
const OPENGL_DEPTH_SIZE: int = 24;
const SHADER_ROOT: &'static str = "src/shaders";

pub struct MainWindow {
    window: sdl2::video::Window,
    _context: sdl2::video::GLContext,
}
impl MainWindow {
    pub fn new(width: uint, height: uint) -> MainWindow {
        sdl2::video::gl_set_attribute(GLAttr::GLContextMajorVersion,
                                      gl::platform::GL_MAJOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLContextMinorVersion,
                                      gl::platform::GL_MINOR_VERSION);
        sdl2::video::gl_set_attribute(GLAttr::GLDepthSize, OPENGL_DEPTH_SIZE);
        sdl2::video::gl_set_attribute(GLAttr::GLDoubleBuffer, 1);
        sdl2::video::gl_set_attribute(
            GLAttr::GLContextProfileMask,
            sdl2::video::ll::SDL_GLprofile::SDL_GL_CONTEXT_PROFILE_CORE as int);

        let window = sdl2::video::Window::new(
            WINDOW_TITLE, WindowPos::PosCentered, WindowPos::PosCentered,
            width as int, height as int,
            sdl2::video::OPENGL | sdl2::video::SHOWN).unwrap();

        let context = window.gl_create_context().unwrap();
        sdl2::clear_error();
        gl::load_with(|name| {
            match sdl2::video::gl_get_proc_address(name) {
                Some(glproc) => glproc as *const libc::c_void,
                None => {
                    warn!("missing GL function: {}", name);
                    std::ptr::null()
                }
            }
        });
        let mut vao_id = 0;
        check_gl_unsafe!(gl::GenVertexArrays(1, &mut vao_id));
        check_gl_unsafe!(gl::BindVertexArray(vao_id));
        MainWindow {
           window: window,
            _context: context,
        }
    }

    pub fn aspect_ratio(&self) -> f32 {
        let (w, h) = self.window.get_size();
        w as f32 / h as f32
    }

    pub fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }
}

pub struct GameConfig<'a> {
    wad: &'a str,
    metadata: &'a str,
    level_index: uint,
    fov: f32,
}

pub struct Game {
    window: MainWindow,
    player: Player,
    level: Level,
}
impl Game {
    pub fn new(window: MainWindow, config: GameConfig) -> Game {
        let mut wad = wad::Archive::open(&Path::new(config.wad),
                                         &Path::new(config.metadata)).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        let shader_loader = ShaderLoader::new(gl::platform::GLSL_VERSION_STRING,
                                              Path::new(SHADER_ROOT));
        let level = Level::new(&shader_loader,
                               &mut wad, &textures, config.level_index);

        check_gl_unsafe!(gl::ClearColor(0.06, 0.07, 0.09, 0.0));
        check_gl_unsafe!(gl::Enable(gl::DEPTH_TEST));
        check_gl_unsafe!(gl::DepthFunc(gl::LESS));

        let start = *level.get_start_pos();
        let mut player = Player::new(config.fov, window.aspect_ratio(),
                                     Default::default());
        player.set_position(&Vec3::new(start.x, 0.3, start.y));

        Game {
            window: window,
            player: player,
            level: level
        }
    }

    pub fn run(&mut self) {
        let quit_gesture = Gesture::AnyOf(
            vec![Gesture::QuitTrigger,
                 Gesture::KeyTrigger(ScanCode::Escape)]);
        let grab_toggle_gesture = Gesture::KeyTrigger(ScanCode::Grave);

        let mut cum_time = 0.0;
        let mut cum_updates_time = 0.0;
        let mut num_frames = 0.0;
        let mut t0 = 0.0;
        let mut control = GameController::new();
        let mut mouse_grabbed = true;
        loop {
            check_gl_unsafe!(
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
            let t1 = time::precise_time_s();
            let mut delta = (t1 - t0) as f32;
            if delta < 1e-10 { delta = 1.0 / 60.0; }
            let delta = delta;
            t0 = t1;

            let updates_t0 = time::precise_time_s();

            control.update();
            if control.poll_gesture(&quit_gesture) {
                break;
            } else if control.poll_gesture(&grab_toggle_gesture) {
                mouse_grabbed = !mouse_grabbed;
                control.set_mouse_enabled(mouse_grabbed);
                control.set_cursor_grabbed(mouse_grabbed);
            }

            self.player.update(delta, &control);
            self.level.render(
                delta,
                &self.player.get_camera()
                .multiply_transform(&Mat4::new_identity()));

            let updates_t1 = time::precise_time_s();
            cum_updates_time += updates_t1 - updates_t0;

            cum_time += delta as f64;
            num_frames += 1.0 as f64;
            if cum_time > 2.0 {
                let fps = num_frames / cum_time;
                let cpums = 1000.0 * cum_updates_time / num_frames as f64;
                info!("Frame time: {:.2}ms ({:.2}ms cpu, FPS: {:.2})",
                      1000.0 / fps, cpums, fps);
                cum_time = 0.0;
                cum_updates_time = 0.0;
                num_frames = 0.0;
            }

            self.window.swap_buffers();
        }
    }
}

#[cfg(not(test))]
pub fn run() {
    use getopts::{optopt,optflag,getopts, usage};
    use std::os;

    let args: Vec<String> = os::args();
    let opts = [
        optopt("i", "iwad",
               "set initial wad file to use wad [default='doom1.wad']", "FILE"),
        optopt("m", "metadata",
               "path to toml toml metadata file [default='doom.toml']", "FILE"),
        optopt("l", "level",
               "the index of the level to render [default=0]", "N"),
        optopt("f", "fov",
               "horizontal field of view to please TotalHalibut [default=65]",
               "FLOAT"),
        optopt("r", "resolution",
               "the resolution at which to render the game [default=1280x720]",
               "WIDTHxHEIGHT"),
        optflag("d", "dump-levels", "list all levels and exit."),
        optflag("", "load-all", "loads all levels and exit; for debugging"),
        optflag("h", "help", "print this help message and exit"),
    ];

    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };

    let wad_filename = matches
        .opt_str("i")
        .unwrap_or("doom1.wad".to_string());
    let meta_filename = matches
        .opt_str("m")
        .unwrap_or("doom.toml".to_string());
    let (width, height) = matches
        .opt_str("r")
        .map(|r| {
            let v = r[].splitn(1, 'x').collect::<Vec<&str>>();
            if v.len() != 2 { None } else { Some(v) }
            .and_then(|v| v[0].parse().map(|v0| (v0, v[1])))
            .and_then(|(v0, s)| s.parse().map(|v1| (v0, v1)))
            .expect("Invalid format for resolution, please use WIDTHxHEIGHT.")
        })
        .unwrap_or((1280, 720));
    let level_index = matches
        .opt_str("l")
        .map(|l| l[].parse()
                    .expect("Invalid value for --level. Expected integer."))
        .unwrap_or(0);
    let fov = matches
        .opt_str("f")
        .map(|f| f[].parse()
                    .expect("Invalid value for --fov. Expected float."))
        .unwrap_or(65.0);

    if matches.opt_present("h") {
        println!("{}", usage("A rust doom renderer.", &opts));
        return;
    }

    if matches.opt_present("d") {
        let wad = wad::Archive::open(
            &Path::new(wad_filename[]), &Path::new(meta_filename[])).unwrap();
        for i_level in range(0, wad.num_levels()) {
            println!("{:3} {:8}", i_level, wad.get_level_name(i_level));
        }
        return;
    }

    if matches.opt_present("load-all") {
        if !sdl2::init(sdl2::INIT_VIDEO) {
            panic!("main: sdl video init failed.");
        }
        let _win = MainWindow::new(width, height);
        let t0 = time::precise_time_s();
        let mut wad = wad::Archive::open(
            &Path::new(wad_filename[]), &Path::new(meta_filename[])).unwrap();
        let textures = TextureDirectory::from_archive(&mut wad).unwrap();
        for level_index in range(0, wad.num_levels()) {
            let shader_loader = ShaderLoader::new(
                gl::platform::GLSL_VERSION_STRING, Path::new(SHADER_ROOT));
            Level::new(&shader_loader, &mut wad, &textures, level_index);
        }
        println!("Done, loaded all levels in {:.4}s. Shutting down...",
                 time::precise_time_s() - t0);
        sdl2::quit();
        return;
    }

    if !sdl2::init(sdl2::INIT_VIDEO) { panic!("main: sdl video init failed."); }

    let mut game = Game::new(
        MainWindow::new(width, height),
        GameConfig {
            wad: wad_filename[],
            metadata: meta_filename[],
            level_index: level_index,
            fov: fov,
        });
    game.run();

    info!("Shutting down.");
    drop(game);
    sdl2::quit();
}
<|endoftext|>


<commit_before><commit_msg>Simplify LoginAction::from_request a little.<commit_after><|endoftext|>


<commit_before><commit_msg>Implement sudoku<commit_after>// http://rosettacode.org/wiki/Sudoku

#![allow(unstable)]

use std::{fmt, iter};
use std::str::FromStr;
use std::num::Int;

const BOARD_WIDTH: usize = 9;
const BOARD_HEIGHT: usize = 9;
const GROUP_WIDTH: usize = 3;
const GROUP_HEIGHT: usize = 3;
const MAX_NUMBER: usize = 9;

type BITS = u16;
const MASK_ALL: BITS = 0x1ff;
const INVALID_CELL: usize = !0;

#[derive(Copy, Eq, PartialEq)]
struct Sudoku {
    map: [[BITS; BOARD_WIDTH]; BOARD_HEIGHT]
}

impl Sudoku {
    fn new() -> Sudoku {
        Sudoku { map: [[MASK_ALL; BOARD_WIDTH]; BOARD_HEIGHT] }
    }

    fn get(&self, x: usize, y: usize) -> usize {
        match self.map[y][x].count_ones() {
            0 => INVALID_CELL,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }

    fn set(&mut self, x: usize, y: usize, n: usize) {
        self.map[y][x] = 1 << (n - 1);
    }

}

impl FromStr for Sudoku {
    fn from_str(s: &str) -> Option<Sudoku> {
        let mut sudoku = Sudoku::new();

        for (y, line) in s.lines().filter(|l| !l.is_empty()).enumerate() {
            let line = line.trim_matches(CharExt::is_whitespace);
            for (x, c) in line.chars().enumerate() {
                if let Some(d) = c.to_digit(10) {
                    if d != 0 { sudoku.set(x, y, d); }
                } else {
                    return None
                }
            }
        }

        Some(sudoku)
    }
}

impl fmt::String for Sudoku {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let hbar = "+---+---+---+";

        for y in (0 .. BOARD_HEIGHT) {
            if y % GROUP_HEIGHT == 0 {
                try!(writeln!(f, "{}", hbar));
            }

            for x in (0 .. BOARD_WIDTH) {
                if x % GROUP_WIDTH == 0 {
                    try!(write!(f, "|"));
                }

                match self.get(x, y) {
                    INVALID_CELL => try!(write!(f, "!")),
                    0 => try!(write!(f, " ")),
                    d => try!(write!(f, "{}", d))
                }
            }
            try!(writeln!(f, "|"));
        }
        try!(writeln!(f, "{}", hbar));

        Ok(())
    }
}

fn solve_sudoku(mut puzzle: Sudoku) -> Vec<Sudoku> {
    let idx_in_grp = [(0, 0), (0, 1), (0, 2),
                      (1, 0), (1, 1), (1, 2),
                      (2, 0), (2, 1), (2, 2)];

    loop {
        let bkup = puzzle;

        // If the number at cell (x, y) is uniquely determined, that number must
        // not be appeared at the cells in the same row/column/group.
        for y in (0 .. BOARD_HEIGHT) {
            for x in (0 .. BOARD_WIDTH) {
                if puzzle.map[y][x].count_ones() != 1 { continue }

                let (x0, y0) = ((x / GROUP_WIDTH) * GROUP_WIDTH,
                                (y / GROUP_HEIGHT) * GROUP_HEIGHT);

                let row = (0 .. BOARD_WIDTH).map(|x| (x, y));
                let col = (0 .. BOARD_HEIGHT).map(|y| (x, y));
                let grp = idx_in_grp.iter().map(|&(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp)
                    .filter(|&pos: &(usize, usize)| pos != (x, y));

                let mask = !puzzle.map[y][x] & MASK_ALL;
                for (x, y) in it {
                    puzzle.map[y][x] &= mask;
                }
            }
        }

        // If `n` appears only once at the cell in the row/column/group, the
        // number of the cell must be `n`.
        for n in (0 .. MAX_NUMBER) {
            let bit = 1 << n;

            // Check each rows
            for y in (0 .. BOARD_HEIGHT) {
                let next = {
                    let mut it = (0 .. BOARD_WIDTH)
                        .filter(|&x| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[y][next.unwrap()] = bit;
            }

            // Check each columns
            for x in (0 .. BOARD_WIDTH) {
                let next = {
                    let mut it = (0 .. BOARD_HEIGHT)
                        .filter(|&y| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_none() || it.next().is_some() { continue }
                    next
                };
                puzzle.map[next.unwrap()][x] = bit;
            }

            // Check each groups
            for y0 in iter::range_step(0, BOARD_HEIGHT, GROUP_WIDTH) {
                for x0 in iter::range_step(0, BOARD_WIDTH, GROUP_HEIGHT) {
                    let next = {
                        let mut it = idx_in_grp
                            .iter()
                            .map(|&(dx, dy)| (x0 + dx, y0 + dy))
                            .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                        let next = it.next();
                        if next.is_none() || it.next().is_some() { continue }
                        next
                    };
                    let (x, y) = next.unwrap();
                    puzzle.map[y][x] = bit;
                }
            }
        }

        // Loop until no cells can be filled.
        if puzzle == bkup { break }
    }

    let it = (0 .. BOARD_HEIGHT * BOARD_WIDTH)
        .map(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .map(|(x, y)| (x, y, puzzle.map[y][x].count_ones() as BITS))
        .collect::<Vec<_>>();

    // If some cells have no possible number, there is no answer.
    if it.iter().any(|&(_x, _y, cnt)| cnt == 0) { return vec![]; }

    // If all cells have exact one possible number, this is a answer.
    if it.iter().all(|&(_x, _y, cnt)| cnt == 1) { return vec![puzzle]; }

    // Find the first undetermined cell.
    let (x, y, _cnt) = *it.iter()
        .filter(|& &(_x, _y, cnt)| cnt > 1)
        .min_by(|& &(_x, _y, cnt)| cnt)
        .unwrap();

    let mut answers = vec![];
    for n in (0 .. MAX_NUMBER) {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { continue }

        // Assuming the number at (x, y) is `n`, try to solve the problem again.
        // If some answers are found, append them to the `answers`.
        let mut p2 = puzzle;
        p2.map[y][x] = bit;
        answers.extend(solve_sudoku(p2).into_iter());
    }
    answers
}

const INPUT: &'static str = "
    850002400
    720000009
    004000000
    000107002
    305000900
    040000000
    000080070
    017000000
    000036040
";

fn main() {
    let puzzle = INPUT.parse::<Sudoku>().unwrap();

    println!("{}", puzzle);

    for answer in solve_sudoku(puzzle).iter() {
        println!("{}", answer);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add dom utility module<commit_after>use std::rc::Rc;
use html5ever::tendril::StrTendril;
use html5ever::rcdom::NodeData::{Element, Text};
use html5ever::rcdom::{Handle, Node};
use html5ever::Attribute;
use std::str::FromStr;

pub fn get_tag_name(handle: Handle) -> Option<String> {
    match handle.data {
        Element { ref name,  .. } => Some(name.local.as_ref().to_lowercase().to_string()),
        _ => None,
    }
}

pub fn get_attr<'a>(name: &str, handle: Handle) -> Option<String> {
    match handle.data {
        Element { name: _, ref attrs, .. } => attr(name, &attrs.borrow()),
        _                                  => None,
    }
}

pub fn attr(attr_name: &str, attrs: &Vec<Attribute>) -> Option<String> {
    for attr in attrs.iter() {
        if attr.name.local.as_ref() == attr_name {
            return Some(attr.value.to_string())
        }
    }
    None
}

pub fn set_attr(attr_name: &str, value: &str, handle: Handle) {
    match handle.data {
        Element { name: _, ref attrs, .. } => {
            let attrs = &mut attrs.borrow_mut();
            if let Some(index) = attrs.iter().position(|attr| {
                let name = attr.name.local.as_ref();
                name == attr_name
            }) {
                match StrTendril::from_str(value) {
                    Ok(value) => attrs[index] = Attribute {
                        name:  attrs[index].name.clone(),
                        value: value,
                    },
                    Err(_) => (),
                }
            }
        }
        _ => (),
    }
}

pub fn clean_attr(attr_name: &str, attrs: &mut Vec<Attribute>) {
    if let Some(index) = attrs.iter().position(|attr| {
        let name = attr.name.local.as_ref();
        name == attr_name
    }) {
        attrs.remove(index);
    }
}

pub fn is_empty(handle: Handle) -> bool {
    for child in handle.children.borrow().iter() {
        let c = child.clone();
        match c.data {
            Text { ref contents } => {
                if contents.borrow().trim().len() > 0 {
                    return false
                }
            },
            Element { ref name, .. } => {
                let tag_name = name.local.as_ref();
                match tag_name.to_lowercase().as_ref() {
                    "li" | "dt" | "dd" | "p" | "div" => {
                        if !is_empty(child.clone()) {
                            return false
                        }
                    },
                    _ => return false,
                }
            },
            _ => ()
        }
    }
    match get_tag_name(handle.clone()).unwrap_or("".to_string()).as_ref() {
        "li" | "dt" | "dd" | "p" | "div" | "canvas" => true,
        _ => false,
    }
}

pub fn has_link(handle: Handle) -> bool {
    if "a" == &get_tag_name(handle.clone()).unwrap_or("".to_string()) {
        return true
    }
    for child in handle.children.borrow().iter() {
        if has_link(child.clone()) {
            return true
        }
    }
    return false
}

pub fn extract_text(handle: Handle, text: &mut String, deep: bool) {
    for child in handle.children.borrow().iter() {
        let c = child.clone();
        match c.data {
            Text { ref contents } => {
                text.push_str(contents.borrow().trim());
            },
            Element { .. } => {
                if deep {
                    extract_text(child.clone(), text, deep);
                }
            },
            _ => ()
        }
    }
}

pub fn text_len(handle: Handle) -> usize {
    let mut len = 0;
    for child in handle.children.borrow().iter() {
        let c = child.clone();
        match c.data {
            Text { ref contents } => {
                len += contents.borrow().trim().chars().count();
            },
            Element { .. } => {
                len += text_len(child.clone());
            },
            _ => ()
        }
    }
    len
}

pub fn find_node(handle: Handle, tag_name: &str, nodes: &mut Vec<Rc<Node>>) {
    for child in handle.children.borrow().iter() {
        let c = child.clone();
        match c.data {
            Element { ref name, .. } => {
                let t = name.local.as_ref();
                if t.to_lowercase() == tag_name {
                    nodes.push(child.clone());
                };
                find_node(child.clone(), tag_name, nodes)
            },
            _ => ()
        }
    }
}

pub fn has_nodes(handle: Handle, tag_names: &Vec<&'static str>) -> bool {
    for child in handle.children.borrow().iter() {
        let tag_name: &str = &get_tag_name(child.clone()).unwrap_or("".to_string());
        if tag_names.iter().any(|&n| n == tag_name) {
            return true
        }
        if match child.clone().data {
            Element { .. } => {
                has_nodes(child.clone(), tag_names)
            },
            _ => false,
        } {
            return true
        }
    }
    return false
}
<|endoftext|>


<commit_before><commit_msg>add methods to calculate center of screen<commit_after><|endoftext|>


<commit_before><commit_msg>Implment loose_dbpage<commit_after><|endoftext|>


<commit_before>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

extern crate regex;

use std::collections::HashMap;
use template::Template;
use lexer::Token;
use lexer::Element;
use tags::{IfBlock, ForBlock, RawBlock, CommentBlock};
use std::string::ToString;
use std::default::Default;
pub use value::Value;
pub use context::Context;
pub use template::Template;

mod template;
mod output;
mod text;
pub mod lexer;
mod parser;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode{
    Strict,
    Warn,
    Lax
}

impl Default for ErrorMode {
   fn default() -> ErrorMode { ErrorMode::Warn }
}

/// A trait for creating custom tags.
pub trait Tag {
    fn initialize(&self, tag_name: &str, arguments: &[Token], options : &LiquidOptions) -> Box<Renderable>;
}

/// The trait to use when implementing custom block-size tags ({% if something %})
pub trait Block {
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Result<Box<Renderable +'a>, String>;
}

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Option<String>;
}

#[derive(Default)]
pub struct LiquidOptions<'a> {
    pub blocks : HashMap<String, Box<Block + 'a>>,
    pub tags : HashMap<String, Box<Tag + 'a>>,
    pub error_mode : ErrorMode
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use std::default::Default;
/// use liquid::Renderable;
/// use liquid::LiquidOptions;
/// use liquid::Context;
/// let mut options : LiquidOptions = Default::default();
/// let template = liquid::parse("Liquid!", &mut options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), "Liquid!".to_string());
/// ```
///
pub fn parse<'a, 'b> (text: &str, options: &'b mut LiquidOptions<'a>) -> Result<Template<'b>, String>{
    let tokens = lexer::tokenize(&text);
    options.blocks.insert("raw".to_string(), Box::new(RawBlock) as Box<Block>);
    options.blocks.insert("if".to_string(), Box::new(IfBlock) as Box<Block>);
    options.blocks.insert("for".to_string(), Box::new(ForBlock) as Box<Block>);
    options.blocks.insert("comment".to_string(), Box::new(CommentBlock) as Box<Block>);
    match parser::parse(&tokens, options) {
        Ok(renderables) => Ok(Template::new(renderables)),
        Err(e) => Err(e)
    }
}

<commit_msg>fix duplicate import error<commit_after>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

extern crate regex;

use std::collections::HashMap;
use lexer::Token;
use lexer::Element;
use tags::{IfBlock, ForBlock, RawBlock, CommentBlock};
use std::string::ToString;
use std::default::Default;
pub use value::Value;
pub use context::Context;
pub use template::Template;

mod template;
mod output;
mod text;
pub mod lexer;
mod parser;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode{
    Strict,
    Warn,
    Lax
}

impl Default for ErrorMode {
   fn default() -> ErrorMode { ErrorMode::Warn }
}

/// A trait for creating custom tags.
pub trait Tag {
    fn initialize(&self, tag_name: &str, arguments: &[Token], options : &LiquidOptions) -> Box<Renderable>;
}

/// The trait to use when implementing custom block-size tags ({% if something %})
pub trait Block {
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Result<Box<Renderable +'a>, String>;
}

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Option<String>;
}

#[derive(Default)]
pub struct LiquidOptions<'a> {
    pub blocks : HashMap<String, Box<Block + 'a>>,
    pub tags : HashMap<String, Box<Tag + 'a>>,
    pub error_mode : ErrorMode
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use std::default::Default;
/// use liquid::Renderable;
/// use liquid::LiquidOptions;
/// use liquid::Context;
/// let mut options : LiquidOptions = Default::default();
/// let template = liquid::parse("Liquid!", &mut options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), "Liquid!".to_string());
/// ```
///
pub fn parse<'a, 'b> (text: &str, options: &'b mut LiquidOptions<'a>) -> Result<Template<'b>, String>{
    let tokens = lexer::tokenize(&text);
    options.blocks.insert("raw".to_string(), Box::new(RawBlock) as Box<Block>);
    options.blocks.insert("if".to_string(), Box::new(IfBlock) as Box<Block>);
    options.blocks.insert("for".to_string(), Box::new(ForBlock) as Box<Block>);
    options.blocks.insert("comment".to_string(), Box::new(CommentBlock) as Box<Block>);
    match parser::parse(&tokens, options) {
        Ok(renderables) => Ok(Template::new(renderables)),
        Err(e) => Err(e)
    }
}

<|endoftext|>


<commit_before><commit_msg>Added vim comment to src/xcb.rs<commit_after><|endoftext|>


<commit_before><commit_msg>test(parser): initial commit<commit_after><|endoftext|>


<commit_before><commit_msg>Add tests/simple.rs<commit_after>use snowchains::app::{App, Opt};
use snowchains::path::AbsPathBuf;
use snowchains::service::{Credentials, ServiceName};
use snowchains::terminal::{AnsiColorChoice, TermImpl};

use tempdir::TempDir;

use std::path::PathBuf;

#[test]
fn it_works() {
    let _ = env_logger::try_init();

    let tempdir = TempDir::new("simple_it_works").unwrap();

    let src_dir = tempdir.path().join("rs").join("src").join("bin");
    let src_path = src_dir.join("a.rs");
    let suite_dir = tempdir.path().join("tests").join("other").join("practice");
    let suite_path = suite_dir.join("a.yaml");
    static CODE: &str = r#"use std::io::{self, Read};

fn main() {
    let mut input = "".to_owned();
    io::stdin().read_to_string(&mut input).unwrap();
    let mut input = input.split(char::is_whitespace);
    let a = input.next().unwrap().parse::<u32>().unwrap();
    let b = input.next().unwrap().parse::<u32>().unwrap();
    let c = input.next().unwrap().parse::<u32>().unwrap();
    let s = input.next().unwrap();
    println!("{} {}", a + b + c, s);
}
"#;
    static WRONG_CODE: &str = "fn main {}";
    static SUITE: &str = r#"---
type: simple
match: exact
cases:
  - name: Sample 1
    in: |
      1
      2 3
      test
    out: |
      6 test
  - name: Sample 2
    in: |
      72
      128 256
      myonmyon
    out: |
      456 myonmyon
"#;

    std::fs::create_dir_all(&src_dir).unwrap();
    std::fs::create_dir_all(&suite_dir).unwrap();
    std::fs::write(&suite_path, SUITE).unwrap();

    let mut app = App {
        working_dir: AbsPathBuf::try_new(tempdir.path().to_owned()).unwrap(),
        cookies_on_init: "$service".to_owned(),
        dropbox_auth_on_init: "dropbox.json".to_owned(),
        enable_dropbox_on_init: false,
        credentials: Credentials::default(),
        term: TermImpl::null(),
    };
    app.run(Opt::Init {
        color_choice: AnsiColorChoice::Never,
        directory: PathBuf::from("."),
    })
    .unwrap();

    let mut test = |code: &str| -> snowchains::Result<()> {
        std::fs::write(&src_path, code)?;
        app.run(Opt::Judge {
            force_compile: false,
            service: Some(ServiceName::Other),
            contest: Some("practice".to_owned()),
            language: Some("rust".to_owned()),
            jobs: None,
            color_choice: AnsiColorChoice::Never,
            problem: "a".to_owned(),
        })
    };
    test(CODE).unwrap();
    test(WRONG_CODE).unwrap_err();
}
<|endoftext|>


<commit_before><commit_msg>Implement UnixDatagram::new()<commit_after><|endoftext|>


<commit_before><commit_msg>chg option.as_ref()<commit_after><|endoftext|>


<commit_before><commit_msg>test(parse_query): rustfmt<commit_after><|endoftext|>


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

//! The Rust prelude. Imported into every module by default.

// Reexported core operators
pub use either::{Either, Left, Right};
pub use kinds::{Const, Copy, Owned, Sized};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
pub use ops::{Shl, Shr, Index};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

// Reexported functions
pub use io::{print, println};

// Reexported types and traits
pub use clone::{Clone, DeepClone};
pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
pub use char::Char;
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
pub use old_iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
pub use old_iter::{ExtendedMutableIter};
pub use iter::Times;
pub use num::{Num, NumCast};
pub use num::{Orderable, Signed, Unsigned, Round};
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
pub use num::{Integer, Fractional, Real, RealExt};
pub use num::{Bitwise, BitCount, Bounded};
pub use num::{Primitive, Int, Float};
pub use path::GenericPath;
pub use path::Path;
pub use path::PosixPath;
pub use path::WindowsPath;
pub use ptr::Ptr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
pub use str::{StrSlice, OwnedStr, StrUtil};
pub use from_str::{FromStr};
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume};
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5};
pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9};
pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12};
pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5};
pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};

// Reexported runtime types
pub use comm::{stream, Port, Chan, GenericChan, GenericSmartChan, GenericPort, Peekable};
pub use task::spawn;

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

/*!

Many programming languages have a 'prelude': a particular subset of the
libraries that come with the language. Every program imports the prelude by
default.

For example, it would be annoying to add `use io::println;` to every single
program, and the vast majority of Rust programs will wish to print to standard
output. Therefore, it makes sense to import it into every program.

Rust's prelude has three main parts:

1. io::print and io::println.
2. Core operators, such as `Add`, `Mul`, and `Not`.
3. Various types and traits, such as `Clone`, `Eq`, and `comm::Chan`.

*/

// Reexported core operators
pub use either::{Either, Left, Right};
pub use kinds::{Const, Copy, Owned, Sized};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
pub use ops::{Shl, Shr, Index};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

// Reexported functions
pub use io::{print, println};

// Reexported types and traits
pub use clone::{Clone, DeepClone};
pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
pub use char::Char;
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
pub use old_iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
pub use old_iter::{ExtendedMutableIter};
pub use iter::Times;
pub use num::{Num, NumCast};
pub use num::{Orderable, Signed, Unsigned, Round};
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
pub use num::{Integer, Fractional, Real, RealExt};
pub use num::{Bitwise, BitCount, Bounded};
pub use num::{Primitive, Int, Float};
pub use path::GenericPath;
pub use path::Path;
pub use path::PosixPath;
pub use path::WindowsPath;
pub use ptr::Ptr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
pub use str::{StrSlice, OwnedStr, StrUtil};
pub use from_str::{FromStr};
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume};
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5};
pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9};
pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12};
pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5};
pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};

// Reexported runtime types
pub use comm::{stream, Port, Chan, GenericChan, GenericSmartChan, GenericPort, Peekable};
pub use task::spawn;

<|endoftext|>


<commit_before><commit_msg>Initial unit test for calculating sha1 hash<commit_after><|endoftext|>


<commit_before><commit_msg>Change return type of `version` to `&'static str`<commit_after><|endoftext|>


<commit_before><commit_msg>run_command API update<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor imag-mv to fit new store iterator interface<commit_after><|endoftext|>


<commit_before><commit_msg>tupleicious<commit_after>fn main() {
	let (x, y, z) = triplets(4); //ISO-9931: random number
	println!("x: {x}, y: {y}, z: {z}",
		 x = x,
		 y = y,
		 z = z);
}

fn triplets(x: int) -> (int, int, int) {
	(x, x+1, x+2)
}
<|endoftext|>


<commit_before><commit_msg>Update TcpStream parameters<commit_after><|endoftext|>


<commit_before><commit_msg>Run bindgen to get fuse low-level C API<commit_after>/* automatically generated by rust-bindgen */

use std::libc::*;
pub struct Struct_fuse_opt {
    pub templ: *c_schar,
    pub offset: c_ulong,
    pub value: c_int,
}
pub struct Struct_fuse_args {
    pub argc: c_int,
    pub argv: *mut *mut c_schar,
    pub allocated: c_int,
}
pub type fuse_opt_proc_t = *u8;
pub struct Struct_fuse_file_info {
    pub flags: c_int,
    pub fh_old: c_ulong,
    pub writepage: c_int,
    pub direct_io: c_uint,
    pub keep_cache: c_uint,
    pub flush: c_uint,
    pub nonseekable: c_uint,
    pub flock_release: c_uint,
    pub padding: c_uint,
    pub fh: uint64_t,
    pub lock_owner: uint64_t,
}
pub struct Struct_fuse_conn_info {
    pub proto_major: c_uint,
    pub proto_minor: c_uint,
    pub async_read: c_uint,
    pub max_write: c_uint,
    pub max_readahead: c_uint,
    pub capable: c_uint,
    pub want: c_uint,
    pub max_background: c_uint,
    pub congestion_threshold: c_uint,
    pub reserved: [c_uint, ..23u],
}
pub type Struct_fuse_session = c_void;
pub type Struct_fuse_chan = c_void;
pub type Struct_fuse_pollhandle = c_void;
pub type Enum_fuse_buf_flags = c_uint;
pub static FUSE_BUF_IS_FD: c_uint = 2;
pub static FUSE_BUF_FD_SEEK: c_uint = 4;
pub static FUSE_BUF_FD_RETRY: c_uint = 8;
pub type Enum_fuse_buf_copy_flags = c_uint;
pub static FUSE_BUF_NO_SPLICE: c_uint = 2;
pub static FUSE_BUF_FORCE_SPLICE: c_uint = 4;
pub static FUSE_BUF_SPLICE_MOVE: c_uint = 8;
pub static FUSE_BUF_SPLICE_NONBLOCK: c_uint = 16;
pub struct Struct_fuse_buf {
    pub size: size_t,
    pub flags: Enum_fuse_buf_flags,
    pub mem: *mut c_void,
    pub fd: c_int,
    pub pos: off_t,
}
pub struct Struct_fuse_bufvec {
    pub count: size_t,
    pub idx: size_t,
    pub off: size_t,
    pub buf: [Struct_fuse_buf, ..1u],
}
pub type fuse_ino_t = c_ulong;
pub type Struct_fuse_req = c_void;
pub type fuse_req_t = *mut Struct_fuse_req;
pub struct Struct_fuse_entry_param {
    pub ino: fuse_ino_t,
    pub generation: c_ulong,
    pub attr: Struct_stat,
    pub attr_timeout: c_double,
    pub entry_timeout: c_double,
}
pub struct Struct_fuse_ctx {
    pub uid: uid_t,
    pub gid: gid_t,
    pub pid: pid_t,
    pub umask: mode_t,
}
pub struct Struct_fuse_forget_data {
    pub ino: uint64_t,
    pub nlookup: uint64_t,
}
pub struct Struct_fuse_lowlevel_ops {
    pub init: *u8,
    pub destroy: *u8,
    pub lookup: *u8,
    pub forget: *u8,
    pub getattr: *u8,
    pub setattr: *u8,
    pub readlink: *u8,
    pub mknod: *u8,
    pub mkdir: *u8,
    pub unlink: *u8,
    pub rmdir: *u8,
    pub symlink: *u8,
    pub rename: *u8,
    pub link: *u8,
    pub open: *u8,
    pub read: *u8,
    pub write: *u8,
    pub flush: *u8,
    pub release: *u8,
    pub fsync: *u8,
    pub opendir: *u8,
    pub readdir: *u8,
    pub releasedir: *u8,
    pub fsyncdir: *u8,
    pub statfs: *u8,
    pub setxattr: *u8,
    pub getxattr: *u8,
    pub listxattr: *u8,
    pub removexattr: *u8,
    pub access: *u8,
    pub create: *u8,
    pub getlk: *u8,
    pub setlk: *u8,
    pub bmap: *u8,
    pub ioctl: *u8,
    pub poll: *u8,
    pub write_buf: *u8,
    pub retrieve_reply: *u8,
    pub forget_multi: *u8,
    pub flock: *u8,
    pub fallocate: *u8,
}
pub type fuse_interrupt_func_t = *u8;
pub struct Struct_fuse_session_ops {
    pub process: *u8,
    pub exit: *u8,
    pub exited: *u8,
    pub destroy: *u8,
}
pub struct Struct_fuse_chan_ops {
    pub receive: *u8,
    pub send: *u8,
    pub destroy: *u8,
}
#[link_args = "-lfuse"]
extern "C" {
    pub fn fuse_opt_parse(args: *mut Struct_fuse_args, data: *mut c_void,
                          opts: *Struct_fuse_opt, proc: fuse_opt_proc_t) ->
     c_int;
    pub fn fuse_opt_add_opt(opts: *mut *mut c_schar, opt: *c_schar) -> c_int;
    pub fn fuse_opt_add_opt_escaped(opts: *mut *mut c_schar, opt: *c_schar) ->
     c_int;
    pub fn fuse_opt_add_arg(args: *mut Struct_fuse_args, arg: *c_schar) ->
     c_int;
    pub fn fuse_opt_insert_arg(args: *mut Struct_fuse_args, pos: c_int,
                               arg: *c_schar) -> c_int;
    pub fn fuse_opt_free_args(args: *mut Struct_fuse_args);
    pub fn fuse_opt_match(opts: *Struct_fuse_opt, opt: *c_schar) -> c_int;
    pub fn fuse_mount(mountpoint: *c_schar, args: *mut Struct_fuse_args) ->
     *mut Struct_fuse_chan;
    pub fn fuse_unmount(mountpoint: *c_schar, ch: *mut Struct_fuse_chan);
    pub fn fuse_parse_cmdline(args: *mut Struct_fuse_args,
                              mountpoint: *mut *mut c_schar,
                              multithreaded: *mut c_int,
                              foreground: *mut c_int) -> c_int;
    pub fn fuse_daemonize(foreground: c_int) -> c_int;
    pub fn fuse_version() -> c_int;
    pub fn fuse_pollhandle_destroy(ph: *mut Struct_fuse_pollhandle);
    pub fn fuse_buf_size(bufv: *Struct_fuse_bufvec) -> size_t;
    pub fn fuse_buf_copy(dst: *mut Struct_fuse_bufvec,
                         src: *mut Struct_fuse_bufvec,
                         flags: Enum_fuse_buf_copy_flags) -> ssize_t;
    pub fn fuse_set_signal_handlers(se: *mut Struct_fuse_session) -> c_int;
    pub fn fuse_remove_signal_handlers(se: *mut Struct_fuse_session);
    pub fn fuse_reply_err(req: fuse_req_t, err: c_int) -> c_int;
    pub fn fuse_reply_none(req: fuse_req_t);
    pub fn fuse_reply_entry(req: fuse_req_t, e: *Struct_fuse_entry_param) ->
     c_int;
    pub fn fuse_reply_create(req: fuse_req_t, e: *Struct_fuse_entry_param,
                             fi: *Struct_fuse_file_info) -> c_int;
    pub fn fuse_reply_attr(req: fuse_req_t, attr: *Struct_stat,
                           attr_timeout: c_double) -> c_int;
    pub fn fuse_reply_readlink(req: fuse_req_t, link: *c_schar) -> c_int;
    pub fn fuse_reply_open(req: fuse_req_t, fi: *Struct_fuse_file_info) ->
     c_int;
    pub fn fuse_reply_write(req: fuse_req_t, count: size_t) -> c_int;
    pub fn fuse_reply_buf(req: fuse_req_t, buf: *c_schar, size: size_t) ->
     c_int;
    pub fn fuse_reply_data(req: fuse_req_t, bufv: *mut Struct_fuse_bufvec,
                           flags: Enum_fuse_buf_copy_flags) -> c_int;
    pub fn fuse_reply_iov(req: fuse_req_t, iov: *Struct_iovec, count: c_int)
     -> c_int;
    pub fn fuse_reply_statfs(req: fuse_req_t, stbuf: *Struct_statvfs) ->
     c_int;
    pub fn fuse_reply_xattr(req: fuse_req_t, count: size_t) -> c_int;
    pub fn fuse_reply_lock(req: fuse_req_t, lock: *Struct_flock) -> c_int;
    pub fn fuse_reply_bmap(req: fuse_req_t, idx: uint64_t) -> c_int;
    pub fn fuse_add_direntry(req: fuse_req_t, buf: *mut c_schar,
                             bufsize: size_t, name: *c_schar,
                             stbuf: *Struct_stat, off: off_t) -> size_t;
    pub fn fuse_reply_ioctl_retry(req: fuse_req_t, in_iov: *Struct_iovec,
                                  in_count: size_t, out_iov: *Struct_iovec,
                                  out_count: size_t) -> c_int;
    pub fn fuse_reply_ioctl(req: fuse_req_t, result: c_int, buf: *c_void,
                            size: size_t) -> c_int;
    pub fn fuse_reply_ioctl_iov(req: fuse_req_t, result: c_int,
                                iov: *Struct_iovec, count: c_int) -> c_int;
    pub fn fuse_reply_poll(req: fuse_req_t, revents: c_uint) -> c_int;
    pub fn fuse_lowlevel_notify_poll(ph: *mut Struct_fuse_pollhandle) ->
     c_int;
    pub fn fuse_lowlevel_notify_inval_inode(ch: *mut Struct_fuse_chan,
                                            ino: fuse_ino_t, off: off_t,
                                            len: off_t) -> c_int;
    pub fn fuse_lowlevel_notify_inval_entry(ch: *mut Struct_fuse_chan,
                                            parent: fuse_ino_t,
                                            name: *c_schar, namelen: size_t)
     -> c_int;
    pub fn fuse_lowlevel_notify_delete(ch: *mut Struct_fuse_chan,
                                       parent: fuse_ino_t, child: fuse_ino_t,
                                       name: *c_schar, namelen: size_t) ->
     c_int;
    pub fn fuse_lowlevel_notify_store(ch: *mut Struct_fuse_chan,
                                      ino: fuse_ino_t, offset: off_t,
                                      bufv: *mut Struct_fuse_bufvec,
                                      flags: Enum_fuse_buf_copy_flags) ->
     c_int;
    pub fn fuse_lowlevel_notify_retrieve(ch: *mut Struct_fuse_chan,
                                         ino: fuse_ino_t, size: size_t,
                                         offset: off_t, cookie: *mut c_void)
     -> c_int;
    pub fn fuse_req_userdata(req: fuse_req_t) -> *mut c_void;
    pub fn fuse_req_ctx(req: fuse_req_t) -> *Struct_fuse_ctx;
    pub fn fuse_req_getgroups(req: fuse_req_t, size: c_int, list: *mut gid_t)
     -> c_int;
    pub fn fuse_req_interrupt_func(req: fuse_req_t,
                                   func: fuse_interrupt_func_t,
                                   data: *mut c_void);
    pub fn fuse_req_interrupted(req: fuse_req_t) -> c_int;
    pub fn fuse_lowlevel_is_lib_option(opt: *c_schar) -> c_int;
    pub fn fuse_lowlevel_new(args: *mut Struct_fuse_args,
                             op: *Struct_fuse_lowlevel_ops, op_size: size_t,
                             userdata: *mut c_void) ->
     *mut Struct_fuse_session;
    pub fn fuse_session_new(op: *mut Struct_fuse_session_ops,
                            data: *mut c_void) -> *mut Struct_fuse_session;
    pub fn fuse_session_add_chan(se: *mut Struct_fuse_session,
                                 ch: *mut Struct_fuse_chan);
    pub fn fuse_session_remove_chan(ch: *mut Struct_fuse_chan);
    pub fn fuse_session_next_chan(se: *mut Struct_fuse_session,
                                  ch: *mut Struct_fuse_chan) ->
     *mut Struct_fuse_chan;
    pub fn fuse_session_process(se: *mut Struct_fuse_session, buf: *c_schar,
                                len: size_t, ch: *mut Struct_fuse_chan);
    pub fn fuse_session_process_buf(se: *mut Struct_fuse_session,
                                    buf: *Struct_fuse_buf,
                                    ch: *mut Struct_fuse_chan);
    pub fn fuse_session_receive_buf(se: *mut Struct_fuse_session,
                                    buf: *mut Struct_fuse_buf,
                                    chp: *mut *mut Struct_fuse_chan) -> c_int;
    pub fn fuse_session_destroy(se: *mut Struct_fuse_session);
    pub fn fuse_session_exit(se: *mut Struct_fuse_session);
    pub fn fuse_session_reset(se: *mut Struct_fuse_session);
    pub fn fuse_session_exited(se: *mut Struct_fuse_session) -> c_int;
    pub fn fuse_session_data(se: *mut Struct_fuse_session) -> *mut c_void;
    pub fn fuse_session_loop(se: *mut Struct_fuse_session) -> c_int;
    pub fn fuse_session_loop_mt(se: *mut Struct_fuse_session) -> c_int;
    pub fn fuse_chan_new(op: *mut Struct_fuse_chan_ops, fd: c_int,
                         bufsize: size_t, data: *mut c_void) ->
     *mut Struct_fuse_chan;
    pub fn fuse_chan_fd(ch: *mut Struct_fuse_chan) -> c_int;
    pub fn fuse_chan_bufsize(ch: *mut Struct_fuse_chan) -> size_t;
    pub fn fuse_chan_data(ch: *mut Struct_fuse_chan) -> *mut c_void;
    pub fn fuse_chan_session(ch: *mut Struct_fuse_chan) ->
     *mut Struct_fuse_session;
    pub fn fuse_chan_recv(ch: *mut *mut Struct_fuse_chan, buf: *mut c_schar,
                          size: size_t) -> c_int;
    pub fn fuse_chan_send(ch: *mut Struct_fuse_chan, iov: *Struct_iovec,
                          count: size_t) -> c_int;
    pub fn fuse_chan_destroy(ch: *mut Struct_fuse_chan);
}
<|endoftext|>


<commit_before><commit_msg>Add some really simple testing around undo/redo<commit_after>#[macro_use]
extern crate lazy_static;
extern crate typenum;

extern crate rex;

mod util;

use std::path::Path;

use rex::frontend::{KeyPress};

use util::mock_filesystem::{DefMockFilesystem};

#[test]
fn test_undo_insert() {
    let v : Vec<u8> = (0..0xff).into_iter().collect();
    let result = v.clone();

    let (mut edit, mut frontend) = util::simple_init_with_vec(v);

    frontend.run_str(&mut edit, "AA");
    assert_eq!(edit.get_position(), 1);

    frontend.run_keys(&mut edit, vec![KeyPress::Shortcut('z'), KeyPress::Shortcut('z')]);
    assert_eq!(edit.get_position(), 0);

    edit.save(Path::new("test_copy_paste"));
    util::assert_iter_eq(result.iter(), DefMockFilesystem::get_inner("test_copy_paste").iter());
}

#[test]
fn test_undo_delete() {
    let v : Vec<u8> = (0..0xff).into_iter().collect();
    let result = v.clone();

    let (mut edit, mut frontend) = util::simple_init_with_vec(v);

    frontend.run_keys(&mut edit, vec![KeyPress::Delete]);

    frontend.run_keys(&mut edit, vec![KeyPress::Shortcut('z')]);
    assert_eq!(edit.get_position(), 0);

    edit.save(Path::new("test_copy_paste"));
    util::assert_iter_eq(result.iter(), DefMockFilesystem::get_inner("test_copy_paste").iter());
}
<|endoftext|>


<commit_before><commit_msg>src/rpc/mod.rs: address connector methods<commit_after><|endoftext|>


<commit_before><commit_msg>Removed dead code<commit_after><|endoftext|>


<commit_before><commit_msg>Create lib.rs<commit_after>#![feature(question_mark)]
#[test]
fn it_works() {
}

#[macro_use]
extern crate nom;
extern crate memmap;

pub mod id;
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

extern crate zip;
extern crate quick_xml;
extern crate encoding;
extern crate byteorder;
#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate log;

mod errors;
pub mod vba;

use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::collections::HashMap;
use std::slice::Chunks;

pub use errors::*;
use vba::VbaProject;

use zip::read::{ZipFile, ZipArchive};
use zip::result::ZipError;
use quick_xml::{XmlReader, Event, AsStr};

macro_rules! unexp {
    ($pat: expr) => {
        {
            return Err($pat.into());
        }
    };
    ($pat: expr, $($args: expr)* ) => {
        {
            return Err(format!($pat, $($args)*).into());
        }
    };
}

#[derive(Debug, Clone)]
pub enum DataType {
    Int(i64),
    Float(f64),
    String(String),
    Empty,
}

enum FileType {
    /// Compound File Binary Format [MS-CFB]
    CFB(File),
    Zip(ZipArchive<File>),
}

pub struct Excel {
    zip: FileType,
    strings: Vec<String>,
    /// Map of sheet names/sheet path within zip archive
    sheets: HashMap<String, String>,
}

#[derive(Debug, Default)]
pub struct Range {
    position: (u32, u32),
    size: (usize, usize),
    inner: Vec<DataType>,
}

/// An iterator to read `Range` struct row by row
pub struct Rows<'a> {
    inner: Chunks<'a, DataType>,
}

impl Excel {

    /// Opens a new workbook
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Excel> {
        let f = try!(File::open(&path));
        let zip = match path.as_ref().extension().and_then(|s| s.to_str()) {
            Some("xls") | Some("xla") => FileType::CFB(f),
            Some("xlsx") | Some("xlsb") | Some("xlsm") |
                Some("xlam") => FileType::Zip(try!(ZipArchive::new(f))),
            Some(e) => return Err(format!("unrecognized extension: {:?}", e).into()),
            None => return Err("expecting a file with an extension".into()),
        };
        Ok(Excel { zip: zip, strings: vec![], sheets: HashMap::new() })
    }

    /// Does the workbook contain a vba project
    pub fn has_vba(&mut self) -> bool {
        match self.zip {
            FileType::CFB(_) => true,
            FileType::Zip(ref mut z) => z.by_name("xl/vbaProject.bin").is_ok()
        }
    }

    /// Gets vba project
    pub fn vba_project(&mut self) -> Result<VbaProject> {
        match self.zip {
            FileType::CFB(ref mut f) => {
                let len = try!(f.metadata()).len() as usize;
                VbaProject::new(f, len)
            },
            FileType::Zip(ref mut z) => {
                let f = try!(z.by_name("xl/vbaProject.bin"));
                let len = f.size() as usize;
                VbaProject::new(f, len)
            }
        }
    }

    /// Get all data from `Worksheet`
    pub fn worksheet_range(&mut self, name: &str) -> Result<Range> {
        try!(self.read_shared_strings());
        try!(self.read_sheets_names());
        let strings = &self.strings;
        let z = match self.zip {
            FileType::CFB(_) => return Err("worksheet_range not implemented for CFB files".into()),
            FileType::Zip(ref mut z) => z
        };
        let ws = match self.sheets.get(name) {
            Some(p) => try!(z.by_name(p)),
            None => unexp!("Sheet '{}' does not exist", name),
        };
        Range::from_worksheet(ws, strings)
    }

    /// Loop through all archive files and opens 'xl/worksheets' files
    /// Store sheet name and path into self.sheets
    fn read_sheets_names(&mut self) -> Result<()> {
        if self.sheets.is_empty() {
            let sheets = {
                let mut sheets = HashMap::new();
                let z = match self.zip {
                    FileType::CFB(_) => return Err("read_sheet_names not implemented for CFB files".into()),
                    FileType::Zip(ref mut z) => z
                };
                for i in 0..z.len() {
                    let f = try!(z.by_index(i));
                    let name = f.name().to_string();
                    if name.starts_with("xl/worksheets/") {
                        let xml = XmlReader::from_reader(BufReader::new(f))
                            .with_check(false)
                            .trim_text(false);
                        'xml_loop: for res_event in xml {
                            if let Ok(Event::Start(ref e)) = res_event {
                                if e.name() == b"sheetPr" {
                                    for a in e.attributes() {
                                        if let Ok((b"codeName", v)) = a {
                                            sheets.insert(try!(v.as_str()).to_string(), name);
                                            break 'xml_loop;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                sheets
            };
            self.sheets = sheets;
        }
        Ok(())
    }

    /// Read shared string list
    fn read_shared_strings(&mut self) -> Result<()> {
        if self.strings.is_empty() {
            let z = match self.zip {
                FileType::CFB(_) => return Err("read_shared_strings not implemented for CFB files".into()),
                FileType::Zip(ref mut z) => z
            };
            match z.by_name("xl/sharedStrings.xml") {
                Ok(f) => {
                    let mut xml = XmlReader::from_reader(BufReader::new(f))
                        .with_check(false)
                        .trim_text(false);

                    let mut strings = Vec::new();
                    while let Some(res_event) = xml.next() {
                        match res_event {
                            Ok(Event::Start(ref e)) if e.name() == b"t" => {
                                strings.push(try!(xml.read_text(b"t")));
                            }
                            Err(e) => return Err(e.into()),
                            _ => (),
                        }
                    }
                    self.strings = strings;
                },
                Err(ZipError::FileNotFound) => (),
                Err(e) => return Err(e.into()),
            }
        }

        Ok(())
    }

}

impl Range {

    /// open a xml `ZipFile` reader and read content of *sheetData* and *dimension* node
    fn from_worksheet(xml: ZipFile, strings: &[String]) -> Result<Range> {
        let mut xml = XmlReader::from_reader(BufReader::new(xml))
            .with_check(false)
            .trim_text(false);
        let mut data = Range::default();
        while let Some(res_event) = xml.next() {
            match res_event {
                Err(e) => return Err(e.into()),
                Ok(Event::Start(ref e)) => {
                    match e.name() {
                        b"dimension" => match e.attributes().filter_map(|a| a.ok())
                                .find(|&(key, _)| key == b"ref") {
                            Some((_, dim)) => {
                                let (position, size) = try!(get_dimension(try!(dim.as_str())));
                                data.position = position;
                                data.size = (size.0 as usize, size.1 as usize);
                                data.inner.reserve_exact(data.size.0 * data.size.1);
                            },
                            None => unexp!("Expecting dimension, got {:?}", e),
                        },
                        b"sheetData" => {
                            let _ = try!(data.read_sheet_data(&mut xml, strings));
                        }
                        _ => (),
                    }
                },
                _ => (),
            }
        }
        data.inner.shrink_to_fit();
        Ok(data)
    }

    /// get worksheet position (row, column)
    pub fn get_position(&self) -> (u32, u32) {
        self.position
    }

    /// get size
    pub fn get_size(&self) -> (usize, usize) {
        self.size
    }

    /// get cell value
    pub fn get_value(&self, i: usize, j: usize) -> &DataType {
        let idx = i * self.size.0 + j;
        &self.inner[idx]
    }

    /// get an iterator over inner rows
    pub fn rows(&self) -> Rows {
        let width = self.size.0;
        Rows { inner: self.inner.chunks(width) }
    }

    /// read sheetData node
    fn read_sheet_data(&mut self, xml: &mut XmlReader<BufReader<ZipFile>>, strings: &[String])
        -> Result<()>
    {
        while let Some(res_event) = xml.next() {
            match res_event {
                Err(e) => return Err(e.into()),
                Ok(Event::Start(ref c_element)) => {
                    if c_element.name() == b"c" {
                        loop {
                            match xml.next() {
                                Some(Err(e)) => return Err(e.into()),
                                Some(Ok(Event::Start(ref e))) => {
                                    if e.name() == b"v" {
                                        let v = try!(xml.read_text(b"v"));
                                        let value = match c_element.attributes()
                                            .filter_map(|a| a.ok())
                                            .find(|&(k, _)| k == b"t") {
                                                Some((_, b"s")) => {
                                                    let idx: usize = try!(v.parse());
                                                    DataType::String(strings[idx].clone())
                                                },
                                                // TODO: check in styles to know which type is
                                                // supposed to be used
                                                _ => match v.parse() {
                                                    Ok(i) => DataType::Int(i),
                                                    Err(_) => try!(v.parse()
                                                                   .map(DataType::Float)),
                                                },
                                            };
                                        self.inner.push(value);
                                        break;
                                    } else {
                                        unexp!("not v node");
                                    }
                                },
                                Some(Ok(Event::End(ref e))) => {
                                    if e.name() == b"c" {
                                        self.inner.push(DataType::Empty);
                                        break;
                                    }
                                }
                                None => unexp!("End of xml"),
                                _ => (),
                            }
                        }
                    }
                },
                Ok(Event::End(ref e)) if e.name() == b"sheetData" => return Ok(()),
                _ => (),
            }
        }
        unexp!("Could not find </sheetData>")
    }

}

impl<'a> Iterator for Rows<'a> {
    type Item = &'a [DataType];
    fn next(&mut self) -> Option<&'a [DataType]> {
        self.inner.next()
    }
}

/// converts a text representation (e.g. "A6:G67") of a dimension into integers
/// - top left (row, column),
/// - size (width, height)
fn get_dimension(dimension: &str) -> Result<((u32, u32), (u32, u32))> {
    match dimension.chars().position(|c| c == ':') {
        None => {
            get_row_column(dimension).map(|position| (position, (1, 1)))
        },
        Some(p) => {
            let top_left = try!(get_row_column(&dimension[..p]));
            let bottom_right = try!(get_row_column(&dimension[p + 1..]));
            Ok((top_left, (bottom_right.0 - top_left.0 + 1, bottom_right.1 - top_left.1 + 1)))
        }
    }
}

/// converts a text range name into its position (row, column)
fn get_row_column(range: &str) -> Result<(u32, u32)> {
    let mut col = 0;
    let mut pow = 1;
    let mut rowpos = range.len();
    let mut readrow = true;
    for c in range.chars().rev() {
        match c {
            '0'...'9' => {
                if readrow {
                    rowpos -= 1;
                } else {
                    unexp!("Numeric character are only allowed at the end of the range: {}", c);
                }
            }
            c @ 'A'...'Z' => {
                readrow = false;
                col += ((c as u8 - b'A') as u32 + 1) * pow;
                pow *= 26;
            },
            c @ 'a'...'z' => {
                readrow = false;
                col += ((c as u8 - b'a') as u32 + 1) * pow;
                pow *= 26;
            },
            _ => unexp!("Expecting alphanumeric character, got {:?}", c),
        }
    }
    let row = try!(range[rowpos..].parse());
    Ok((row, col))
}

#[cfg(test)]
mod tests {

    extern crate env_logger;

    use super::Excel;
    use std::fs::File;
    use super::vba::VbaProject;

    #[test]
    fn test_range_sample() {
        let mut xl = Excel::open("/home/jtuffe/download/DailyValo_FX_Rates_Credit_05 25 16.xlsm")
            .expect("cannot open excel file");
        println!("{:?}", xl.sheets);
        let data = xl.worksheet_range("Sheet1");
        assert!(data.is_ok());
        for (i, r) in data.unwrap().rows().enumerate() {
            println!("Row {}: {:?}", i, r);
        }
    }

    #[test]
    fn test_vba() {

        env_logger::init().unwrap();

//         let path = "/home/jtuffe/download/test_vba.xlsm";
        let path = "/home/jtuffe/download/Extractions Simples.xlsb";
        let path = "/home/jtuffe/download/test_xl/ReportRDM_CVA VF_v3.xlsm";
        let path = "/home/jtuffe/download/KelvinsAutoEmailer.xls";
        let f = File::open(path).unwrap();
        let len = f.metadata().unwrap().len() as usize;
        let vba_project = VbaProject::new(f, len).unwrap();
        let vba = vba_project.read_vba();
        let (references, modules) = vba.unwrap();
        println!("references: {:#?}", references);
        for module in &modules {
            let data = vba_project.read_module(module).unwrap();
            println!("module {}:\r\n{}", module.name, data);
        }

    }
}
<commit_msg>add relationship search to find sheet name/path<commit_after>#![feature(conservative_impl_trait)]

extern crate zip;
extern crate quick_xml;
extern crate encoding;
extern crate byteorder;
#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate log;

mod errors;
pub mod vba;

use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::collections::HashMap;
use std::slice::Chunks;

pub use errors::*;
use vba::VbaProject;

use zip::read::{ZipFile, ZipArchive};
use zip::result::ZipError;
use quick_xml::{XmlReader, Event, AsStr};

macro_rules! unexp {
    ($pat: expr) => {
        {
            return Err($pat.into());
        }
    };
    ($pat: expr, $($args: expr)* ) => {
        {
            return Err(format!($pat, $($args)*).into());
        }
    };
}

#[derive(Debug, Clone, PartialEq)]
pub enum DataType {
    Int(i64),
    Float(f64),
    String(String),
    Empty,
}

enum FileType {
    /// Compound File Binary Format [MS-CFB]
    CFB(File),
    Zip(ZipArchive<File>),
}

pub struct Excel {
    zip: FileType,
    strings: Vec<String>,
    relationships: HashMap<Vec<u8>, String>,
    /// Map of sheet names/sheet path within zip archive
    sheets: HashMap<String, String>,
}

#[derive(Debug, Default)]
pub struct Range {
    position: (u32, u32),
    size: (usize, usize),
    inner: Vec<DataType>,
}

/// An iterator to read `Range` struct row by row
pub struct Rows<'a> {
    inner: Chunks<'a, DataType>,
}

impl Excel {

    /// Opens a new workbook
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Excel> {
        let f = try!(File::open(&path));
        let zip = match path.as_ref().extension().and_then(|s| s.to_str()) {
            Some("xls") | Some("xla") => FileType::CFB(f),
            Some("xlsx") | Some("xlsb") | Some("xlsm") |
                Some("xlam") => FileType::Zip(try!(ZipArchive::new(f))),
            Some(e) => return Err(format!("unrecognized extension: {:?}", e).into()),
            None => return Err("expecting a file with an extension".into()),
        };
        Ok(Excel {
            zip: zip,
            strings: vec![],
            relationships: HashMap::new(),
            sheets: HashMap::new(),
        })
    }

    /// Does the workbook contain a vba project
    pub fn has_vba(&mut self) -> bool {
        match self.zip {
            FileType::CFB(_) => true,
            FileType::Zip(ref mut z) => z.by_name("xl/vbaProject.bin").is_ok()
        }
    }

    /// Gets vba project
    pub fn vba_project(&mut self) -> Result<VbaProject> {
        match self.zip {
            FileType::CFB(ref mut f) => {
                let len = try!(f.metadata()).len() as usize;
                VbaProject::new(f, len)
            },
            FileType::Zip(ref mut z) => {
                let f = try!(z.by_name("xl/vbaProject.bin"));
                let len = f.size() as usize;
                VbaProject::new(f, len)
            }
        }
    }

    /// Get all data from `Worksheet`
    pub fn worksheet_range(&mut self, name: &str) -> Result<Range> {
        try!(self.read_shared_strings());
        try!(self.read_relationships());
        try!(self.read_sheets_names());
        let strings = &self.strings;
        let z = match self.zip {
            FileType::CFB(_) => return Err("worksheet_range not implemented for CFB files".into()),
            FileType::Zip(ref mut z) => z
        };
        let ws = match self.sheets.get(name) {
            Some(p) => {
                println!("get sheet {} at path {}", name, p);
                try!(z.by_name(p))
            },
            None => unexp!("Sheet '{}' does not exist", name),
        };
        Range::from_worksheet(ws, strings)
    }

    /// Read sheets from workbook.xml and get their corresponding path from relationships
    fn read_sheets_names(&mut self) -> Result<()> {
        if self.sheets.is_empty() {
            let z = match self.zip {
                FileType::CFB(_) => return Err("read_sheet_names not implemented for CFB files".into()),
                FileType::Zip(ref mut z) => z
            };

            match z.by_name("xl/workbook.xml") {
                Ok(f) => {
                    let mut xml = XmlReader::from_reader(BufReader::new(f))
                        .with_check(false)
                        .trim_text(false);

                    while let Some(res_event) = xml.next() {
                        match res_event {
                            Ok(Event::Start(ref e)) if e.name() == b"sheet" => {
                                let mut name = String::new();
                                let mut path = String::new();
                                for a in e.attributes() {
                                    match try!(a) {
                                        (b"name", v) => name = try!(v.as_str()).to_string(),
                                        (b"r:id", v) => path = format!("xl/{}", self.relationships[v]),
                                        _ => (),
                                    }
                                }
                                self.sheets.insert(name, path);
                            }
                            Err(e) => return Err(e.into()),
                            _ => (),
                        }
                    }
                },
                Err(ZipError::FileNotFound) => (),
                Err(e) => return Err(e.into()),
            }
        }
        Ok(())
    }

    /// Read shared string list
    fn read_shared_strings(&mut self) -> Result<()> {
        if self.strings.is_empty() {
            let z = match self.zip {
                FileType::CFB(_) => return Err("read_shared_strings not implemented for CFB files".into()),
                FileType::Zip(ref mut z) => z
            };
            match z.by_name("xl/sharedStrings.xml") {
                Ok(f) => {
                    let mut xml = XmlReader::from_reader(BufReader::new(f))
                        .with_check(false)
                        .trim_text(false);

                    let mut strings = Vec::new();
                    while let Some(res_event) = xml.next() {
                        match res_event {
                            Ok(Event::Start(ref e)) if e.name() == b"t" => {
                                strings.push(try!(xml.read_text(b"t")));
                            }
                            Err(e) => return Err(e.into()),
                            _ => (),
                        }
                    }
                    self.strings = strings;
                },
                Err(ZipError::FileNotFound) => (),
                Err(e) => return Err(e.into()),
            }
        }

        Ok(())
    }

    /// Read workbook relationships
    fn read_relationships(&mut self) -> Result<()> {
        if self.relationships.is_empty() {
            let z = match self.zip {
                FileType::CFB(_) => return Err("read_shared_strings not implemented for CFB files".into()),
                FileType::Zip(ref mut z) => z
            };
            match z.by_name("xl/_rels/workbook.xml.rels") {
                Ok(f) => {
                    let mut xml = XmlReader::from_reader(BufReader::new(f))
                        .with_check(false)
                        .trim_text(false);

                    while let Some(res_event) = xml.next() {
                        match res_event {
                            Ok(Event::Start(ref e)) if e.name() == b"Relationship" => {
                                let mut id = Vec::new();
                                let mut target = String::new();
                                for a in e.attributes() {
                                    match try!(a) {
                                        (b"Id", v) => id.extend_from_slice(v),
                                        (b"Target", v) => target = try!(v.as_str()).to_string(),
                                        _ => (),
                                    }
                                }
                                self.relationships.insert(id, target);
                            }
                            Err(e) => return Err(e.into()),
                            _ => (),
                        }
                    }
                },
                Err(ZipError::FileNotFound) => (),
                Err(e) => return Err(e.into()),
            }
        }

        Ok(())
    }

}

impl Range {

    /// open a xml `ZipFile` reader and read content of *sheetData* and *dimension* node
    fn from_worksheet(xml: ZipFile, strings: &[String]) -> Result<Range> {
        let mut xml = XmlReader::from_reader(BufReader::new(xml))
            .with_check(false)
            .trim_text(false);
        let mut data = Range::default();
        while let Some(res_event) = xml.next() {
            match res_event {
                Err(e) => return Err(e.into()),
                Ok(Event::Start(ref e)) => {
                    match e.name() {
                        b"dimension" => match e.attributes().filter_map(|a| a.ok())
                                .find(|&(key, _)| key == b"ref") {
                            Some((_, dim)) => {
                                let (position, size) = try!(get_dimension(try!(dim.as_str())));
                                data.position = position;
                                data.size = (size.0 as usize, size.1 as usize);
                                data.inner.reserve_exact(data.size.0 * data.size.1);
                            },
                            None => unexp!("Expecting dimension, got {:?}", e),
                        },
                        b"sheetData" => {
                            let _ = try!(data.read_sheet_data(&mut xml, strings));
                        }
                        _ => (),
                    }
                },
                _ => (),
            }
        }
        data.inner.shrink_to_fit();
        Ok(data)
    }

    /// get worksheet position (row, column)
    pub fn get_position(&self) -> (u32, u32) {
        self.position
    }

    /// get size
    pub fn get_size(&self) -> (usize, usize) {
        self.size
    }

    /// get cell value
    pub fn get_value(&self, i: usize, j: usize) -> &DataType {
        let idx = i * self.size.0 + j;
        &self.inner[idx]
    }

    /// get an iterator over inner rows
    pub fn rows(&self) -> Rows {
        let width = self.size.0;
        Rows { inner: self.inner.chunks(width) }
    }

    /// read sheetData node
    fn read_sheet_data(&mut self, xml: &mut XmlReader<BufReader<ZipFile>>, strings: &[String])
        -> Result<()>
    {
        while let Some(res_event) = xml.next() {
            match res_event {
                Err(e) => return Err(e.into()),
                Ok(Event::Start(ref c_element)) => {
                    if c_element.name() == b"c" {
                        loop {
                            match xml.next() {
                                Some(Err(e)) => return Err(e.into()),
                                Some(Ok(Event::Start(ref e))) => {
                                    if e.name() == b"v" {
                                        let v = try!(xml.read_text(b"v"));
                                        let value = match c_element.attributes()
                                            .filter_map(|a| a.ok())
                                            .find(|&(k, _)| k == b"t") {
                                                Some((_, b"s")) => {
                                                    let idx: usize = try!(v.parse());
                                                    DataType::String(strings[idx].clone())
                                                },
                                                // TODO: check in styles to know which type is
                                                // supposed to be used
                                                _ => match v.parse() {
                                                    Ok(i) => DataType::Int(i),
                                                    Err(_) => try!(v.parse()
                                                                   .map(DataType::Float)),
                                                },
                                            };
                                        self.inner.push(value);
                                        break;
                                    } else {
                                        unexp!("not v node");
                                    }
                                },
                                Some(Ok(Event::End(ref e))) => {
                                    if e.name() == b"c" {
                                        self.inner.push(DataType::Empty);
                                        break;
                                    }
                                }
                                None => unexp!("End of xml"),
                                _ => (),
                            }
                        }
                    }
                },
                Ok(Event::End(ref e)) if e.name() == b"sheetData" => return Ok(()),
                _ => (),
            }
        }
        unexp!("Could not find </sheetData>")
    }

}

impl<'a> Iterator for Rows<'a> {
    type Item = &'a [DataType];
    fn next(&mut self) -> Option<&'a [DataType]> {
        self.inner.next()
    }
}

/// converts a text representation (e.g. "A6:G67") of a dimension into integers
/// - top left (row, column),
/// - size (width, height)
fn get_dimension(dimension: &str) -> Result<((u32, u32), (u32, u32))> {
    match dimension.chars().position(|c| c == ':') {
        None => {
            get_row_column(dimension).map(|position| (position, (1, 1)))
        },
        Some(p) => {
            let top_left = try!(get_row_column(&dimension[..p]));
            let bottom_right = try!(get_row_column(&dimension[p + 1..]));
            Ok((top_left, (bottom_right.0 - top_left.0 + 1, bottom_right.1 - top_left.1 + 1)))
        }
    }
}

/// converts a text range name into its position (row, column)
fn get_row_column(range: &str) -> Result<(u32, u32)> {
    let mut col = 0;
    let mut pow = 1;
    let mut rowpos = range.len();
    let mut readrow = true;
    for c in range.chars().rev() {
        match c {
            '0'...'9' => {
                if readrow {
                    rowpos -= 1;
                } else {
                    unexp!("Numeric character are only allowed at the end of the range: {}", c);
                }
            }
            c @ 'A'...'Z' => {
                readrow = false;
                col += ((c as u8 - b'A') as u32 + 1) * pow;
                pow *= 26;
            },
            c @ 'a'...'z' => {
                readrow = false;
                col += ((c as u8 - b'a') as u32 + 1) * pow;
                pow *= 26;
            },
            _ => unexp!("Expecting alphanumeric character, got {:?}", c),
        }
    }
    let row = try!(range[rowpos..].parse());
    Ok((row, col))
}

<|endoftext|>


<commit_before>#![allow(raw_pointer_derive)]
#![feature(std_misc, collections, rand, path, core, libc)]

extern crate libc;
extern crate rand;

pub use sdl::*;

pub mod audio;
pub mod cd;
pub mod event;
pub mod joy;
pub mod mouse;
pub mod video;
pub mod gl;
pub mod wm;

pub mod sdl;
<commit_msg>Revert feature 'collections'<commit_after>#![allow(raw_pointer_derive)]
#![feature(std_misc, rand, path, core, libc)]

extern crate libc;
extern crate rand;

pub use sdl::*;

pub mod audio;
pub mod cd;
pub mod event;
pub mod joy;
pub mod mouse;
pub mod video;
pub mod gl;
pub mod wm;

pub mod sdl;
<|endoftext|>


<commit_before><commit_msg>pub mod vec<commit_after><|endoftext|>


<commit_before><commit_msg>fix: update to rust nightly<commit_after><|endoftext|>