<commit_before>extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::DownloadError;
use lib::converter::Converter;

use std::fs::{remove_file};

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;
static CODE_FAILED: i8 = 3;
static CODE_SUCCESS: i8 = 2;

lazy_static! {
    pub static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] broken, enum not usable as of #10292
// enum QueryCodes {
//     Waiting = 0,
//     InProgress = 1,
//     Finished = 2,
//     Failed = 3,
// }

fn main() {

    let pool = lib::db_connect(lib::mysql_options(), SLEEP_MS);

    let converter = Converter::new(&CONFIG.general.ffmpeg_bin,&CONFIG.general.mp3_quality , pool.clone());
    let mut print_pause = true;
    loop {
        if let Some(result) = lib::request_entry(& pool) {
            print_pause = true;
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            lib::set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");
            lib::set_query_state(&pool.clone(),&qid, "started", false);

            let succes;
            {
                let mut left_files: Vec<String> = Vec::with_capacity(2);
                if result.playlist {
                    succes = match handle_playlist(result, &converter,&mut left_files) {
                        Ok(v) => v,
                        Err(e) => {println!("Playlist Error: {:?}", e); false }
                    };
                }else{
                    succes = match handle_download(result, None, &converter,&mut left_files) {
                        Ok(v) => v,
                        Err(e) => {println!("Download Error: {:?}", e); false }
                    };
                }

                if !left_files.is_empty() {
                    println!("cleaning up files");
                    for i in &left_files {
                        match remove_file(&i) {
                            Ok(_) => (println!("cleaning up {}",i)),
                            Err(e) => println!("unable to remove file '{}' {}",i,e),
                        }
                    }
                }
            }

            let code: i8 = if succes {
                CODE_SUCCESS//QueryCode
            } else {
                CODE_FAILED//QueryCode
            };
            lib::set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");

            let state = if code == 2 {
                "finished"
            } else {
                "failed"
            };
            lib::set_query_state(&pool.clone(),&qid, state, true);

        } else {
            if print_pause { println!("Pausing.."); print_pause = false; }
            std::thread::sleep_ms(SLEEP_MS);
        }
    }
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video separately and convert them together
///In case of a playlist download it depends on the target download folder & if it should be bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, the video but with the highest quality.
///Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, it's moved after a successful download, converted etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode'd name of the file is stored in the DB
fn handle_download<'a>(downl_db: DownloadDB, folder: Option<String>, converter: &Converter, file_db: &mut Vec<String>) -> Result<bool,DownloadError>{
    //update progress
    let is_zipped = match folder {
        Some(_) => true,
        None => false,
    };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, 0,false);

    let download = Downloader::new(&downl_db, &CONFIG.general);
    //get filename, check for DMCA
    let mut dmca = false; // "succ." dmca -> file already downloaded

    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib.. // k if( k == Err(DownloadError::DMCAError) )
            println!("DMCA error!");
            match download.lib_request_video() {
                Err(err) => { println!("Offliberty-call error {:?}", err); return Err(err); },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / restricted source etc.. abort
            println!("Unknown error: {:?}", e);
            return Err(e);
        },
    };

    let name_http_valid = lib::format_file_name(&name, &download, &downl_db.qid);

    let file_path = lib::format_file_path(&downl_db.qid, folder.clone(), false);
    file_db.push(file_path.clone());
    let save_path = &lib::format_save_path(folder.clone(),&name, &download, &downl_db.qid);

    println!("Filename: {}", name);

    let is_splitted_video = if dmca {
        false
    } else {
        lib::is_split_container(&downl_db.quality)
    };
    let convert_audio = CONFIG.extensions.mp3.contains(&downl_db.quality);

    let total_steps = if dmca {
        if download.is_audio() {
            3
        } else {
            2
        }
    } else if is_splitted_video {
        4
    } else if download.is_audio() {
        3
    } else {
        2
    };

    if !dmca {

        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, total_steps,false);

        //download first file, download audio raw source if specified or video
        try!(download.download_file(&file_path, convert_audio));

        if is_splitted_video {
            // download audio file & convert together
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 3, total_steps,false);

            let audio_path = lib::format_file_path(&downl_db.qid, folder.clone(), true);
            file_db.push(audio_path.clone());

            println!("Downloading audio.. {}", audio_path);
            try!(download.download_file(&audio_path, true));

            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 4, total_steps,false);

            match converter.merge_files(&downl_db.qid,&file_path, &audio_path,&save_path) {
                Err(e) => {println!("merge error: {:?}",e); return Err(e);},
                Ok(()) => {},
            }

            try!(remove_file(&audio_path));
            file_db.pop();

        }else{ // we're already done, only need to copy if it's not raw audio source
            if !download.is_audio() {
                try!(lib::move_file(&file_path, &save_path));
            }
        }
    }

    if download.is_audio(){ // if audio-> convert m4a to mp3, which converts directly to downl. dir
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, false);
        try!(converter.extract_audio(&file_path, &save_path,convert_audio));
        try!(remove_file(&file_path));
    }else{
        if is_splitted_video {
            try!(remove_file(&file_path));
        }else{
            try!(lib::move_file(&file_path, &save_path));
        }
    }
    file_db.pop();

    if !is_zipped { // add file to list, except it's for zip-compression later (=folder set)
        lib::add_file_entry(&downl_db.pool.clone(), &downl_db.qid,&name_http_valid, &name);
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, true);
    Ok(true)
}

///Handles a playlist request
///If zipping isn't requested the downloads will be split up,
///so for each video in the playlist an own query entry will be created
fn handle_playlist(mut downl_db: DownloadDB, converter: &Converter, file_db: &mut Vec<String>) -> Result<bool, DownloadError>{
    let mut max_steps = if downl_db.compress { 4 } else { 3 };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, max_steps,false);

    let pl_id: i64 = downl_db.qid;
    downl_db.update_folder(format!("{}/{}",&CONFIG.general.save_dir,pl_id));

    let download = Downloader::new(&downl_db, &CONFIG.general);

    let playlist_name;
    if downl_db.compress {
        playlist_name = lib::url_encode(try!(download.get_playlist_name()));
        try!(std::fs::create_dir(&downl_db.folder));
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, max_steps,false);

    let file_ids: Vec<String> = try!(download.get_playlist_ids());

    let mut current_url;
    for id in file_ids.iter() {
        downl_db.update_video(format!("https://wwww.youtube.com/watch?v={}",id), pl_id);
        println!("id: {}",id);
    }

    Ok(true)
}
<commit_msg>implemented handle_download in playlist iterator<commit_after>extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::DownloadError;
use lib::converter::Converter;

use std::fs::{remove_file};

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;
static CODE_FAILED: i8 = 3;
static CODE_SUCCESS: i8 = 2;

lazy_static! {
    pub static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] broken, enum not usable as of #10292
// enum QueryCodes {
//     Waiting = 0,
//     InProgress = 1,
//     Finished = 2,
//     Failed = 3,
// }

fn main() {

    let pool = lib::db_connect(lib::mysql_options(), SLEEP_MS);

    let converter = Converter::new(&CONFIG.general.ffmpeg_bin,&CONFIG.general.mp3_quality , pool.clone());
    let mut print_pause = true;
    loop {
        if let Some(result) = lib::request_entry(& pool) {
            print_pause = true;
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            lib::set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");
            lib::set_query_state(&pool.clone(),&qid, "started", false);

            let succes;
            {
                let mut left_files: Vec<String> = Vec::with_capacity(2);
                if result.playlist {
                    succes = match handle_playlist(result, &converter,&mut left_files) {
                        Ok(v) => v,
                        Err(e) => {println!("Playlist Error: {:?}", e); false }
                    };
                }else{
                    succes = match handle_download(result, None, &converter,&mut left_files) {
                        Ok(v) => v,
                        Err(e) => {println!("Download Error: {:?}", e); false }
                    };
                }

                if !left_files.is_empty() {
                    println!("cleaning up files");
                    for i in &left_files {
                        match remove_file(&i) {
                            Ok(_) => (println!("cleaning up {}",i)),
                            Err(e) => println!("unable to remove file '{}' {}",i,e),
                        }
                    }
                }
            }

            let code: i8 = if succes {
                CODE_SUCCESS//QueryCode
            } else {
                CODE_FAILED//QueryCode
            };
            lib::set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");

            let state = if code == 2 {
                "finished"
            } else {
                "failed"
            };
            lib::set_query_state(&pool.clone(),&qid, state, true);

        } else {
            if print_pause { println!("Pausing.."); print_pause = false; }
            std::thread::sleep_ms(SLEEP_MS);
        }
    }
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video separately and convert them together
///In case of a playlist download it depends on the target download folder & if it should be bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, the video but with the highest quality.
///Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, it's moved after a successful download, converted etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode'd name of the file is stored in the DB
fn handle_download<'a>(downl_db: DownloadDB, folder: Option<String>, converter: &Converter, file_db: &mut Vec<String>) -> Result<bool,DownloadError>{
    //update progress
    let is_zipped = match folder {
        Some(_) => true,
        None => false,
    };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, 0,false);

    let download = Downloader::new(&downl_db, &CONFIG.general);
    //get filename, check for DMCA
    let mut dmca = false; // "succ." dmca -> file already downloaded

    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib.. // k if( k == Err(DownloadError::DMCAError) )
            println!("DMCA error!");
            match download.lib_request_video() {
                Err(err) => { println!("Offliberty-call error {:?}", err); return Err(err); },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / restricted source etc.. abort
            println!("Unknown error: {:?}", e);
            return Err(e);
        },
    };

    let name_http_valid = lib::format_file_name(&name, &download, &downl_db.qid);

    let file_path = lib::format_file_path(&downl_db.qid, folder.clone(), false);
    file_db.push(file_path.clone());
    let save_path = &lib::format_save_path(folder.clone(),&name, &download, &downl_db.qid);

    println!("Filename: {}", name);

    let is_splitted_video = if dmca {
        false
    } else {
        lib::is_split_container(&downl_db.quality)
    };
    let convert_audio = CONFIG.extensions.mp3.contains(&downl_db.quality);

    let total_steps = if dmca {
        if download.is_audio() {
            3
        } else {
            2
        }
    } else if is_splitted_video {
        4
    } else if download.is_audio() {
        3
    } else {
        2
    };

    if !dmca {

        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, total_steps,false);

        //download first file, download audio raw source if specified or video
        try!(download.download_file(&file_path, convert_audio));

        if is_splitted_video {
            // download audio file & convert together
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 3, total_steps,false);

            let audio_path = lib::format_file_path(&downl_db.qid, folder.clone(), true);
            file_db.push(audio_path.clone());

            println!("Downloading audio.. {}", audio_path);
            try!(download.download_file(&audio_path, true));

            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 4, total_steps,false);

            match converter.merge_files(&downl_db.qid,&file_path, &audio_path,&save_path) {
                Err(e) => {println!("merge error: {:?}",e); return Err(e);},
                Ok(()) => {},
            }

            try!(remove_file(&audio_path));
            file_db.pop();

        }else{ // we're already done, only need to copy if it's not raw audio source
            if !download.is_audio() {
                try!(lib::move_file(&file_path, &save_path));
            }
        }
    }

    if download.is_audio(){ // if audio-> convert m4a to mp3, which converts directly to downl. dir
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, false);
        try!(converter.extract_audio(&file_path, &save_path,convert_audio));
        try!(remove_file(&file_path));
    }else{
        if is_splitted_video {
            try!(remove_file(&file_path));
        }else{
            try!(lib::move_file(&file_path, &save_path));
        }
    }
    file_db.pop();

    if !is_zipped { // add file to list, except it's for zip-compression later (=folder set)
        lib::add_file_entry(&downl_db.pool.clone(), &downl_db.qid,&name_http_valid, &name);
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, true);
    Ok(true)
}

///Handles a playlist request
///If zipping isn't requested the downloads will be split up,
///so for each video in the playlist an own query entry will be created
fn handle_playlist(mut downl_db: DownloadDB, converter: &Converter, file_db: &mut Vec<String>) -> Result<bool, DownloadError>{
    let mut max_steps = if downl_db.compress { 4 } else { 3 };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, max_steps,false);

    let pl_id: i64 = downl_db.qid;
    //downl_db.update_folder(format!("{}/{}",&CONFIG.general.save_dir,pl_id));

    let download = Downloader::new(&downl_db, &CONFIG.general);

    let playlist_name;
    if downl_db.compress {
        playlist_name = lib::url_encode(try!(download.get_playlist_name()));
        try!(std::fs::create_dir(&downl_db.folder));
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, max_steps,false);

    let file_ids: Vec<String> = try!(download.get_playlist_ids());

    let mut current_url;
    let mut left_files: Vec<String> = Vec::with_capacity(file_ids.len*2);
    for id in file_ids.iter() {
        downl_db.update_video(format!("https://wwww.youtube.com/watch?v={}",id), pl_id);
        println!("id: {}",id);
        match handle_download(downl_db, Some(pl_id.to_string()), converter, &mut left_files) {
            Err(e) => println!("error downloading {}: {:?}",id,e),
            Ok(_) => {},
        }
    }

    if !left_files.is_empty() {
        println!("cleaning up files");
        for i in &left_files {
            match remove_file(&i) {
                Ok(_) => (println!("cleaning up {}",i)),
                Err(e) => println!("unable to remove file '{}' {}",i,e),
            }
        }
    }

    Ok(true)
}
<|endoftext|>


<commit_before>#![feature(globs)]

extern crate graphics;
extern crate piston;
extern crate rand;
extern crate native;

use piston::*;

mod snakeapp;
mod object;
mod settings;
mod text;
mod bar;
mod player;
mod snake;
mod action;
mod game_state;
mod character;
mod air_bottle;

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run GLFW on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    use snakeapp::SnakeApp;
    let mut game_window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Sea Snake Escape".to_string(),
            size: [512, 512],
            fullscreen: false,
            exit_on_esc: true,
            background_color: settings::WATER_COLOR,
        }
    );

    let mut asset_store = AssetStore::empty();

    let mut app = SnakeApp::new();
    app.run(&mut game_window, &mut asset_store);
}

<commit_msg>Rewrote using iterator design<commit_after>#![feature(globs)]

extern crate graphics;
extern crate piston;
extern crate rand;
extern crate native;

use piston::*;

mod snakeapp;
mod object;
mod settings;
mod text;
mod bar;
mod player;
mod snake;
mod action;
mod game_state;
mod character;
mod air_bottle;

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run GLFW on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    use snakeapp::SnakeApp;
    let mut game_window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Sea Snake Escape".to_string(),
            size: [512, 512],
            fullscreen: false,
            exit_on_esc: true,
            background_color: settings::WATER_COLOR,
        }
    );

    let mut asset_store = AssetStore::empty();

    let mut app = SnakeApp::new();
    app.load(&mut asset_store);

    // app.run(&mut game_window, &mut asset_store);
    let mut game_iterator = GameIterator::new(&mut game_window);
    loop { match game_iterator.next() { None => { break }, Some(e) => {
        match e {
            Render(args) => {
                app.render(0.0, &args.context, &mut Gl::new(args.gl_data, &mut asset_store));
            },
            Update(args) => {
                app.update(args.dt, &mut asset_store);
            },
            KeyPress(args) => {
                app.key_press(args.key, &mut asset_store);
            },
            KeyRelease(args) => {
                app.key_release(args.key, &mut asset_store);
            },
            _ => {},
        }
    } } }
}

<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

// TODO revisit these after 1.0.0beta
#![feature(env)]
#![feature(io)]
#![feature(path)]
#![feature(fs)]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
// use std::time::duration::Duration;
use quack::Set;
// use input::keyboard::Key;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            println!("Could not open rom {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            println!("You can provide a path to a chip8 binary to interpret it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => println!("Loaded rom size: {}", size),
        Err(e) => {
            println!("Error loading rom: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE);
            } else {
                (*window.borrow_mut()).window.set_title(TITLE);
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<commit_msg>Unwrap result of window.set_title() to silence warnings<commit_after>#![cfg_attr(test, allow(dead_code))]

// TODO revisit these after 1.0.0beta
#![feature(env)]
#![feature(io)]
#![feature(path)]
#![feature(fs)]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
// use std::time::duration::Duration;
use quack::Set;
// use input::keyboard::Key;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            println!("Could not open rom {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            println!("You can provide a path to a chip8 binary to interpret it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => println!("Loaded rom size: {}", size),
        Err(e) => {
            println!("Error loading rom: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE).unwrap();
            } else {
                (*window.borrow_mut()).window.set_title(TITLE).unwrap();
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;
use collections::PriorityQueue;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

#[deriving(Show,PartialEq,PartialOrd,Eq,Ord)]
enum Month { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }

fn string_to_month (s : &str) -> Option<Month> {
  match s {
    "Jan" => Some (Jan),
    "Feb" => Some (Feb),
    "Mar" => Some (Mar),
    "Apr" => Some (Apr),
    "May" => Some (May),
    "Jun" => Some (Jun),
    "Jul" => Some (Jul),
    "Aug" => Some (Aug),
    "Sep" => Some (Sep),
    "Oct" => Some (Oct),
    "Nov" => Some (Nov),
    "Dec" => Some (Dec),
    _     => None
  }
}

#[deriving(Show,PartialEq,Eq)]
struct TimedLine {
  l       : String,
  month   : Month,
  day     : u8,
  hour    : u8,
  minute  : u8,
  second  : u8,
  usecond : u32,
  target  : uint
}

impl TimedLine {
  fn new (l : &str, target : uint) -> TimedLine {
    let re = regex! (r"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) +(\d+) (\d+):(\d+):(\d+) (\d+):.*$");
    let caps = match re.captures (l) {
      None => fail! ("Could not analyze line: \"{}\"", l),
      Some (caps) => caps
    };
    let (month, day, hour, minute, second, usecond) =
      match (string_to_month (caps.at(1)), from_str::<u8>(caps.at(2)), from_str::<u8> (caps.at(3)), from_str::<u8> (caps.at(4)), from_str::<u8> (caps.at(5)), from_str::<u32> (caps.at(6))
      ) {
        (Some (month), Some (day), Some (hour), Some (minute), Some (second), Some (usecond)) => (month, day, hour, minute, second, usecond*100),
        _ => fail! ("Could not extract fields from line: \"{}\"", l)
      };

    TimedLine {
      l       : String::from_str (l),
      month   : month,
      day     : day,
      hour    : hour,
      minute  : minute,
      second  : second,
      usecond : usecond,
      target  : target
    }
  }
}

impl Ord for TimedLine {
  fn cmp(&self, other: &TimedLine) -> Ordering {
    let month_cmp = self.month.cmp (&other.month);
    if month_cmp == Equal {
      let day_cmp = self.day.cmp (&other.day);
      if day_cmp == Equal {
        let hour_cmp = self.hour.cmp (&other.hour);
        if hour_cmp == Equal {
          let minute_cmp = self.minute.cmp (&other.minute);
          if minute_cmp == Equal {
            let second_cmp = self.second.cmp (&other.second);
            if second_cmp == Equal {
              self.usecond.cmp (&other.usecond)
            }
            else { second_cmp }
          }
          else { minute_cmp }
        }
        else { hour_cmp }
      }
      else { day_cmp }
    }
    else { month_cmp }
  }
}

impl PartialOrd for TimedLine {
  fn partial_cmp(&self, other: &TimedLine) -> Option<Ordering> {
    Some (self.cmp (other))
  }
}

struct TimedLineQueue<'a> {
  q : PriorityQueue<TimedLine>,
  readers : &'a mut Vec<BrType>
}

impl<'a> TimedLineQueue<'a> {
  fn fill_que (&mut self, target : uint) {
    let reader = self.readers.get_mut (target);
    let mut lines = reader.lines ();
    let line_opt = lines.next ();
    match line_opt {
      Some (line) => {
        let line = line.unwrap();
        let line = line.as_slice();
        let line = line.trim_chars('\n');
        let timed_line = TimedLine::new (line, target);
        self.q.push (timed_line);
      }
      None => ()
    }
  }

  fn new (readers : & 'a mut Vec<BrType>) -> TimedLineQueue {
    let mut res = TimedLineQueue {
      q : PriorityQueue::new (),
      readers : readers
    };

    for (i, _) in res.readers.mut_iter().enumerate () {
      res.fill_que(i);
    }

    res
  }
}

impl<'a> Iterator<TimedLine> for TimedLineQueue<'a> {
  fn next (&mut self) -> Option<TimedLine> {
    let timed_line_opt = self.q.pop ();
    match timed_line_opt {
      None => (),
      Some (ref timed_line) => {
        self.fill_que(timed_line.target);
      }
    }

    timed_line_opt
  }
}

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  // let s = String::from_str ("Sep  2 14:25:02 8993: (main|info): --- NODE STARTED ---");
  // let tl = TimedLine::new (&s, 5u);
  // println!("TimedLine: {}", tl);

  // println!("Starting {}", args);

  let file_names = args.arg_file;
  let file_count = file_names.len ();
  let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (format!("{}.txt", i)));
  let files_out_it = paths_out_it.map (|path_out| {
    let res = File::create(&path_out);
    match res {
      Ok(_)  => (),
      Err(e) => fail!("Could not open output file: {}", e)
    };
    res
  }
  );
  let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out) );

  let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

  let mut tlq = TimedLineQueue::new (& mut buffered_readers_vec);
  for timed_line in tlq {
    let target = timed_line.target;
    {
      let writer = buffered_writers_vec.get_mut (target);
      let res = writer.write_line (format!("{}", timed_line.l).as_slice ());
      match res {
        Ok(_) => (),
        Err(e) => {
          let ref file_name = file_names[target];
          fail! ("Could not write to {}: {}", file_name, e);
        }
      };
    }

    for i in range (0, file_count).filter (|i| *i != target) {
      let writer = buffered_writers_vec.get_mut (i);
      let res = writer.write_line ("");
      match res {
        Ok(_) => (),
        Err(e) => {
          let ref file_name = file_names[i];
          fail! ("Could not write to {}: {}", file_name, e);
        }
      };
    }
  }
}
<commit_msg>Added ordering test<commit_after>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;
use collections::PriorityQueue;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

#[deriving(Show,PartialEq,PartialOrd,Eq,Ord)]
enum Month { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }

fn string_to_month (s : &str) -> Option<Month> {
  match s {
    "Jan" => Some (Jan),
    "Feb" => Some (Feb),
    "Mar" => Some (Mar),
    "Apr" => Some (Apr),
    "May" => Some (May),
    "Jun" => Some (Jun),
    "Jul" => Some (Jul),
    "Aug" => Some (Aug),
    "Sep" => Some (Sep),
    "Oct" => Some (Oct),
    "Nov" => Some (Nov),
    "Dec" => Some (Dec),
    _     => None
  }
}

#[deriving(Show,PartialEq,Eq)]
struct TimedLine {
  l       : String,
  month   : Month,
  day     : u8,
  hour    : u8,
  minute  : u8,
  second  : u8,
  usecond : u32,
  target  : uint
}

impl TimedLine {
  fn new (l : &str, target : uint) -> TimedLine {
    let re = regex! (r"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) +(\d+) (\d+):(\d+):(\d+) (\d+):.*$");
    let caps = match re.captures (l) {
      None => fail! ("Could not analyze line: \"{}\"", l),
      Some (caps) => caps
    };
    let (month, day, hour, minute, second, usecond) =
      match (string_to_month (caps.at(1)), from_str::<u8>(caps.at(2)), from_str::<u8> (caps.at(3)), from_str::<u8> (caps.at(4)), from_str::<u8> (caps.at(5)), from_str::<u32> (caps.at(6))
      ) {
        (Some (month), Some (day), Some (hour), Some (minute), Some (second), Some (usecond)) => (month, day, hour, minute, second, usecond*100),
        _ => fail! ("Could not extract fields from line: \"{}\"", l)
      };

    TimedLine {
      l       : String::from_str (l),
      month   : month,
      day     : day,
      hour    : hour,
      minute  : minute,
      second  : second,
      usecond : usecond,
      target  : target
    }
  }
}

impl Ord for TimedLine {
  fn cmp(&self, other: &TimedLine) -> Ordering {
    let month_cmp = self.month.cmp (&other.month);
    if month_cmp == Equal {
      let day_cmp = self.day.cmp (&other.day);
      if day_cmp == Equal {
        let hour_cmp = self.hour.cmp (&other.hour);
        if hour_cmp == Equal {
          let minute_cmp = self.minute.cmp (&other.minute);
          if minute_cmp == Equal {
            let second_cmp = self.second.cmp (&other.second);
            if second_cmp == Equal {
              self.usecond.cmp (&other.usecond)
            }
            else { second_cmp }
          }
          else { minute_cmp }
        }
        else { hour_cmp }
      }
      else { day_cmp }
    }
    else { month_cmp }
  }
}

impl PartialOrd for TimedLine {
  fn partial_cmp(&self, other: &TimedLine) -> Option<Ordering> {
    Some (self.cmp (other))
  }
}

struct TimedLineQueue<'a> {
  q : PriorityQueue<TimedLine>,
  readers : &'a mut Vec<BrType>
}

impl<'a> TimedLineQueue<'a> {
  fn fill_que (&mut self, target : uint) {
    let reader = self.readers.get_mut (target);
    let mut lines = reader.lines ();
    let line_opt = lines.next ();
    match line_opt {
      Some (line) => {
        let line = line.unwrap();
        let line = line.as_slice();
        let line = line.trim_chars('\n');
        let timed_line = TimedLine::new (line, target);
        self.q.push (timed_line);
      }
      None => ()
    }
  }

  fn new (readers : & 'a mut Vec<BrType>) -> TimedLineQueue {
    let mut res = TimedLineQueue {
      q : PriorityQueue::new (),
      readers : readers
    };

    for (i, _) in res.readers.mut_iter().enumerate () {
      res.fill_que(i);
    }

    res
  }
}

impl<'a> Iterator<TimedLine> for TimedLineQueue<'a> {
  fn next (&mut self) -> Option<TimedLine> {
    let timed_line_opt = self.q.pop ();
    match timed_line_opt {
      None => (),
      Some (ref timed_line) => {
        self.fill_que(timed_line.target);
      }
    }

    timed_line_opt
  }
}

#[test]
fn test_timed_line_ordering () {
  let s1 = String::from_str ("Sep  2 14:25:02 8993: (main|info): --- NODE STARTED ---");
  let s2 = String::from_str ("Sep  2 14:25:02 9488: (main|info): --- NODE STARTED ---");

  let tl_1 = TimedLine::new (s1.as_slice(), 5u);
  let tl_2 = TimedLine::new (s2.as_slice(), 5u);

  assert! (tl_1.cmp (&tl_2) == Less);
  assert! (tl_2.cmp (&tl_1) == Greater);
  assert! (tl_1.cmp (&tl_1) == Equal);
  assert! (tl_2.cmp (&tl_2) == Equal);
}

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  let file_names = args.arg_file;
  let file_count = file_names.len ();
  let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (format!("{}.txt", i)));
  let files_out_it = paths_out_it.map (|path_out| {
    let res = File::create(&path_out);
    match res {
      Ok(_)  => (),
      Err(e) => fail!("Could not open output file: {}", e)
    };
    res
  }
  );
  let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out) );

  let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

  let mut tlq = TimedLineQueue::new (& mut buffered_readers_vec);
  for timed_line in tlq {
    let target = timed_line.target;
    {
      let writer = buffered_writers_vec.get_mut (target);
      let res = writer.write_line (format!("{}", timed_line.l).as_slice ());
      match res {
        Ok(_) => (),
        Err(e) => {
          let ref file_name = file_names[target];
          fail! ("Could not write to {}: {}", file_name, e);
        }
      };
    }

    for i in range (0, file_count).filter (|i| *i != target) {
      let writer = buffered_writers_vec.get_mut (i);
      let res = writer.write_line ("");
      match res {
        Ok(_) => (),
        Err(e) => {
          let ref file_name = file_names[i];
          fail! ("Could not write to {}: {}", file_name, e);
        }
      };
    }
  }
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate glob;
extern crate xml;

#[macro_use]
extern crate serde_derive;

use glob::glob;

use std::convert::From;
use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::BufReader;

use xml::reader::{EventReader, XmlEvent};
use xml::name::{Name, OwnedName};

#[derive(Debug)]
struct UrlReport {
    page_urls: Vec<String>,
    image_urls: Vec<String>,
    files: Vec<String>,
    prefixes: HashSet<String>,
}

#[derive(Debug, Serialize)]
enum UrlType {
    Page,
    Image,
}

#[derive(Debug, Serialize)]
struct IndexableEntry {
    url: String,
    url_type: UrlType,
}

fn process(glob_pattern: &str, report: &mut UrlReport) {
    for entry in glob(glob_pattern).expect("Failed to read glob pattern for XML files.") {
        match entry {
            Ok(path) => {
                report.files.push(String::from(path.to_str().unwrap()));
                let file = File::open(path).unwrap();
                let file = BufReader::new(file);

                let parser = EventReader::new(file);
                let mut current_name: OwnedName = Name {
                    local_name: "sitemapindex",
                    namespace: Some("http://www.sitemaps.org/schemas/sitemap/0.9"),
                    prefix: None,
                }.to_owned();

                for e in parser {
                    match e {
                        Ok(XmlEvent::StartElement { name, .. }) => {
                            current_name = name;
                        }
                        Ok(XmlEvent::Characters(cs)) => {
                            // TODO Understand why clone() is needed here, what's causing a move
                            match current_name.prefix.clone() {
                                Some(pre) => {
                                    report.prefixes.insert(pre.clone());
                                    match pre.as_ref() {
                                        "image" => {
                                            match current_name.local_name.as_ref() {
                                                "loc" => {
                                                    report.image_urls.push(cs);
                                                }
                                                _ => {}
                                            }
                                        }
                                        _ => {}
                                    }
                                }
                                None => {
                                    match current_name.local_name.as_ref() {
                                        "loc" => {
                                            report.page_urls.push(cs);
                                        }
                                        _ => {}
                                    }
                                }
                            }
                        }
                        Err(e) => {
                            println!("Error: {:?}", e);
                            break;
                        }
                        _ => {}
                    }
                }
            }
            Err(e) => println!("Error: {:?}", e),
        }
    }
}

fn main() {
    let args = env::args();
    if args.len() < 2 || args.len() > 3 {
        println!(
            "
    USAGE: xmler <glob-pattern> [output-csv-file]

    You must supply a glob pattern representing the file patterns for xmler to search.

       Example: ./xmler 'abc/**/*.xml'

    If you then specify a file name, all URLs found will be written to it in CSV format.
    "
        );
        ::std::process::exit(1);
    }
    let glob_pattern = env::args().nth(1).unwrap();
    let report = &mut UrlReport {
        page_urls: Vec::new(),
        image_urls: Vec::new(),
        files: Vec::new(),
        prefixes: HashSet::new(),
    };
    println!("Processing all files that match your glob pattern...");
    process(&glob_pattern, report);
    println!(
        "
    Report:

        * {} Page URLs
        * {} Image URLs",
        report.page_urls.len(),
        report.image_urls.len()
    );
    let page_urls_set: HashSet<String> = report.page_urls.clone().into_iter().collect();
    let image_urls_set: HashSet<String> = report.image_urls.clone().into_iter().collect();
    println!(
        "
        * {} Unique Page URLs
        * {} Unique Image URLs",
        page_urls_set.len(),
        image_urls_set.len()
    );
    println!(
        "
        * {} files were consulted",
        report.files.len()
    );
    println!(
        "
        * XML prefixes encountered: {:?}",
        report.prefixes
    );

    // Persist report to CSV if output file-name specified
    match env::args().nth(2) {
        Some(file_path) => {
            println!("Writing output to CSV {}", file_path);
            match csv::Writer::from_path(file_path) {
                Ok(mut writer) => {
                    for url in page_urls_set {
                        match writer.serialize(IndexableEntry {
                            url: url,
                            url_type: UrlType::Page,
                        }) {
                            Ok(_) => {}
                            Err(e) => println!("Error: {:?}", e),
                        }
                    }
                    for url in image_urls_set {
                        match writer.serialize(IndexableEntry {
                            url: url,
                            url_type: UrlType::Image,
                        }) {
                            Ok(_) => {}
                            Err(e) => println!("Error: {:?}", e),
                        }
                    }
                    match writer.flush() {
                        Ok(_) => {}
                        Err(e) => println!("Error: {:?}", e),
                    }
                }
                Err(e) => println!("Error: {:?}", e),
            }
        }
        None => {}
    }
}
<commit_msg>Only track loc's inside urlset's<commit_after>extern crate csv;
extern crate glob;
extern crate xml;

#[macro_use]
extern crate serde_derive;

use glob::glob;

use std::convert::From;
use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::BufReader;

use xml::reader::{EventReader, XmlEvent};
use xml::name::{Name, OwnedName};

#[derive(Debug)]
struct UrlReport {
    page_urls: Vec<String>,
    image_urls: Vec<String>,
    files: Vec<String>,
    prefixes: HashSet<String>,
}

#[derive(Debug, Serialize)]
enum UrlType {
    Page,
    Image,
}

#[derive(Debug, Serialize)]
struct IndexableEntry {
    url: String,
    url_type: UrlType,
}

fn process(glob_pattern: &str, report: &mut UrlReport) {
    for entry in glob(glob_pattern).expect("Failed to read glob pattern for XML files.") {
        match entry {
            Ok(path) => {
                report.files.push(String::from(path.to_str().unwrap()));
                let file = File::open(path).unwrap();
                let file = BufReader::new(file);

                let parser = EventReader::new(file);
                let mut current_name: OwnedName = Name {
                    local_name: "sitemapindex",
                    namespace: Some("http://www.sitemaps.org/schemas/sitemap/0.9"),
                    prefix: None,
                }.to_owned();
                let mut in_url_set = false;

                for e in parser {
                    match e {
                        Ok(XmlEvent::StartElement { name, .. }) => {
                            if current_name.local_name == "urlset" {
                                in_url_set = true;
                            }
                            current_name = name;
                        }
                        Ok(XmlEvent::Characters(cs)) => {
                            if in_url_set {
                                // TODO Understand why clone() is needed here, what's causing a move
                                match current_name.prefix.clone() {
                                    Some(pre) => {
                                        report.prefixes.insert(pre.clone());
                                        match pre.as_ref() {
                                            "image" => {
                                                match current_name.local_name.as_ref() {
                                                    "loc" => {
                                                        report.image_urls.push(cs);
                                                    }
                                                    _ => {}
                                                }
                                            }
                                            _ => {}
                                        }
                                    }
                                    None => {
                                        match current_name.local_name.as_ref() {
                                            "loc" => {
                                                report.page_urls.push(cs);
                                            }
                                            _ => {}
                                        }
                                    }
                                }
                            }
                        }
                        Err(e) => {
                            println!("Error: {:?}", e);
                            break;
                        }
                        _ => {}
                    }
                }
            }
            Err(e) => println!("Error: {:?}", e),
        }
    }
}

fn main() {
    let args = env::args();
    if args.len() < 2 || args.len() > 3 {
        println!(
            "
    USAGE: xmler <glob-pattern> [output-csv-file]

    You must supply a glob pattern representing the file patterns for xmler to search.

       Example: ./xmler 'abc/**/*.xml'

    If you then specify a file name, all URLs found will be written to it in CSV format.
    "
        );
        ::std::process::exit(1);
    }
    let glob_pattern = env::args().nth(1).unwrap();
    let report = &mut UrlReport {
        page_urls: Vec::new(),
        image_urls: Vec::new(),
        files: Vec::new(),
        prefixes: HashSet::new(),
    };
    println!("Processing all files that match your glob pattern...");
    process(&glob_pattern, report);
    println!(
        "
    Report:

        * {} Page URLs
        * {} Image URLs",
        report.page_urls.len(),
        report.image_urls.len()
    );
    let page_urls_set: HashSet<String> = report.page_urls.clone().into_iter().collect();
    let image_urls_set: HashSet<String> = report.image_urls.clone().into_iter().collect();
    println!(
        "
        * {} Unique Page URLs
        * {} Unique Image URLs",
        page_urls_set.len(),
        image_urls_set.len()
    );
    println!(
        "
        * {} files were consulted",
        report.files.len()
    );
    println!(
        "
        * XML prefixes encountered: {:?}",
        report.prefixes
    );

    // Persist report to CSV if output file-name specified
    match env::args().nth(2) {
        Some(file_path) => {
            println!("Writing output to CSV {}", file_path);
            match csv::Writer::from_path(file_path) {
                Ok(mut writer) => {
                    for url in page_urls_set {
                        match writer.serialize(IndexableEntry {
                            url: url,
                            url_type: UrlType::Page,
                        }) {
                            Ok(_) => {}
                            Err(e) => println!("Error: {:?}", e),
                        }
                    }
                    for url in image_urls_set {
                        match writer.serialize(IndexableEntry {
                            url: url,
                            url_type: UrlType::Image,
                        }) {
                            Ok(_) => {}
                            Err(e) => println!("Error: {:?}", e),
                        }
                    }
                    match writer.flush() {
                        Ok(_) => {}
                        Err(e) => println!("Error: {:?}", e),
                    }
                }
                Err(e) => println!("Error: {:?}", e),
            }
        }
        None => {}
    }
}
<|endoftext|>


<commit_before>extern crate bencode;

use std::env;
use std::collections::HashMap;
use bencode::{deserialize_file, Bencode};

#[derive(Debug)]
struct Metadata {
    announce: String,
}

trait ToMetadata {
    fn to_metadata (&self) -> Option<Metadata>;
    fn get_int(&self, key: &str) -> Option<i64>;
    fn get_string(&self, key: &str) -> Option<String>;
}

impl ToMetadata for HashMap<String, Bencode> {
    fn to_metadata (&self) -> Option<Metadata> {
        let announce = self.get_string("announce").unwrap();
        Some(Metadata {
            announce: announce,
        })
    }

    fn get_int (&self, key: &str) -> Option <i64> {
        match self.get(key) {
            Some(&Bencode::Int(a)) => Some(a),
            _ => None
        }
    }

    fn get_string (&self, key: &str) -> Option <String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a.clone()),
            _ => None
        }
    }

}

fn main () {
    let path = env::args().nth(1).unwrap();
    let content = deserialize_file(path).unwrap();
    let metadata = match *content.first().unwrap() {
        Bencode::Dict(ref x) => {
             x.to_metadata()
        },
        _ => panic!("something")
    };

    println!("{:?}", metadata.unwrap());
}
<commit_msg>renaming ToMetadata trait to MetadataDict, adding HashMap convenience operations<commit_after>extern crate bencode;

use std::env;
use std::collections::HashMap;
use bencode::{deserialize_file, Bencode};

#[derive(Debug)]
struct Metadata {
    announce: String,
}

trait MetadataDict {
    fn to_metadata (&self) -> Option<Metadata>;
    fn get_int(&self, key: &str) -> Option<i64>;
    fn get_string(&self, key: &str) -> Option<&String>;
    fn get_dict(&self, key: &str) -> Option<&HashMap<String, Bencode>>;
    fn get_list(&self, key: &str) -> Option<&Vec<Bencode>>;
}

impl MetadataDict for HashMap<String, Bencode> {
    /// Extracts information from this HashMap into a Metadata instance, if valid. Currently if it
    /// is invalid, it will just throw a runtime exception
    fn to_metadata (&self) -> Option<Metadata> {
        let announce = self.get_string("announce").unwrap();
        Some(Metadata {
            announce: announce.clone(),
        })
    }

    fn get_int (&self, key: &str) -> Option <i64> {
        match self.get(key) {
            Some(&Bencode::Int(a)) => Some(a),
            _ => None
        }
    }

    fn get_string (&self, key: &str) -> Option <&String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_dict (&self, key: &str) -> Option <&HashMap<String, Bencode>> {
        match self.get(key) {
            Some(&Bencode::Dict(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_list (&self, key: &str) -> Option <&Vec<Bencode>> {
        match self.get(key) {
            Some(&Bencode::List(ref a)) => Some(a),
            _ => None
        }
    }
}

fn main () {
    let path = env::args().nth(1).unwrap_or_else(||panic!("no path to torrent provided"));
    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));
    let metadata = match content.first() {
        Some(&Bencode::Dict(ref x)) => x.to_metadata(),
        _ => panic!("no valid information in torrent file")
    };

    println!("{:?}", metadata.unwrap());
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate requests;
extern crate json;

mod crates;

use clap::{App, SubCommand, Arg, AppSettings, ArgMatches};

const CARGO: &'static str = "cargo";

#[derive(Debug, PartialEq)]
enum Flag {
    Repository,
    Documentation,
    Downloads,
    Homepage,
    Default,
}

#[derive(Debug)]
struct Report {
    flags: Vec<Flag>,
    verbose: bool,
    json: bool,
}

impl Report {
    pub fn new(info: &ArgMatches) -> Self {

        let mut flags: Vec<Flag> = vec![];
        if info.is_present("repository") {
            flags.push(Flag::Repository);
        }
        if info.is_present("documentation") {
            flags.push(Flag::Documentation);
        }
        if info.is_present("downloads") {
            flags.push(Flag::Downloads);
        }
        if info.is_present("homepage") {
            flags.push(Flag::Homepage);
        }

        if flags.is_empty() {
            flags.push(Flag::Default);
        }

        Report {
            flags: flags,
            verbose: info.is_present("verbose"),
            json: info.is_present("json"),
        }
    }

    pub fn report(&self, name: &str) {
        if let Ok(response) = query(name) {
            if self.json {
                self.report_json(&response);
            } else {
                if let Some(krate) = get_crate(&response) {
                    self.report_crate(&krate);
                }
            }
        }
    }

    pub fn report_json(&self, response: &requests::Response) {
        if self.verbose {
            if let Ok(json) = response.json() {
                println!("{}", json::stringify(json));
            }
        } else {
            if let Some(json) = response.text() {
                println!("{}", json);
            }
        }
    }

    pub fn report_crate(&self, krate: &crates::Crate) {
        for flag in &self.flags {
            match *flag {
                Flag::Repository => krate.print_repository(self.verbose),
                Flag::Documentation => krate.print_documentation(self.verbose),
                Flag::Downloads => krate.print_downloads(self.verbose),
                Flag::Homepage => krate.print_homepage(self.verbose),
                Flag::Default => reportv(krate, self.verbose),
            }
        }
    }
}

fn reportv(krate: &crates::Crate, verbose: bool) {
    if verbose {
        println!("{:#}", krate);
    } else {
        println!("{}", krate);
    }
}

fn query(krate: &str) -> requests::RequestsResult {
    requests::get(&format!("http://crates.io/api/v1/crates/{}", krate))
}

fn get_crate(response: &requests::Response) -> Option<crates::Crate> {
    response.json().ok().map(|k| crates::Crate::new(k["crate"].clone()))
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
        .bin_name(CARGO)
        .author(crate_authors!())
        .version(crate_version!())
        .about("Query crates.io registry for crates details")
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("info")
            .setting(AppSettings::ArgRequiredElseHelp)
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("documentation")
                .short("d")
                .long("documentation")
                .help("Report documentation URL"))
            .arg(Arg::with_name("downloads")
                .short("D")
                .long("downloads")
                .help("Report number of crate downloads"))
            .arg(Arg::with_name("homepage")
                .short("H")
                .long("homepage")
                .help("Report home page URL"))
            .arg(Arg::with_name("repository")
                .short("r")
                .long("repository")
                .help("Report crate repository URL"))
            .arg(Arg::with_name("json")
                .short("j")
                .long("json")
                .help("Report raw JSON data from crates.io")
                .conflicts_with_all(&["documentation", "downloads", "homepage", "repository"]))
            .arg(Arg::with_name("verbose")
                .short("v")
                .long("verbose")
                .help("Report more details"))
            .arg_from_usage("<crate>... 'crate to query'"))
        .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        if let Some(crates) = info.values_of("crate") {
            let rep = Report::new(info);
            for krate in crates {
                // debug(&krate);
                rep.report(krate);
            }
        }
    }
}
<commit_msg>Pretty JSON when verbose mode on<commit_after>#[macro_use]
extern crate clap;
extern crate requests;
extern crate json;

mod crates;

use clap::{App, SubCommand, Arg, AppSettings, ArgMatches};

const CARGO: &'static str = "cargo";

#[derive(Debug, PartialEq)]
enum Flag {
    Repository,
    Documentation,
    Downloads,
    Homepage,
    Default,
}

#[derive(Debug)]
struct Report {
    flags: Vec<Flag>,
    verbose: bool,
    json: bool,
}

impl Report {
    pub fn new(info: &ArgMatches) -> Self {

        let mut flags: Vec<Flag> = vec![];
        if info.is_present("repository") {
            flags.push(Flag::Repository);
        }
        if info.is_present("documentation") {
            flags.push(Flag::Documentation);
        }
        if info.is_present("downloads") {
            flags.push(Flag::Downloads);
        }
        if info.is_present("homepage") {
            flags.push(Flag::Homepage);
        }

        if flags.is_empty() {
            flags.push(Flag::Default);
        }

        Report {
            flags: flags,
            verbose: info.is_present("verbose"),
            json: info.is_present("json"),
        }
    }

    pub fn report(&self, name: &str) {
        if let Ok(response) = query(name) {
            if self.json {
                self.report_json(&response);
            } else {
                if let Some(krate) = get_crate(&response) {
                    self.report_crate(&krate);
                }
            }
        }
    }

    pub fn report_json(&self, response: &requests::Response) {
        if self.verbose {
            if let Ok(json) = response.json() {
                println!("{}", json.pretty(4));
            }
        } else {
            if let Some(json) = response.text() {
                println!("{}", json);
            }
        }
    }

    pub fn report_crate(&self, krate: &crates::Crate) {
        for flag in &self.flags {
            match *flag {
                Flag::Repository => krate.print_repository(self.verbose),
                Flag::Documentation => krate.print_documentation(self.verbose),
                Flag::Downloads => krate.print_downloads(self.verbose),
                Flag::Homepage => krate.print_homepage(self.verbose),
                Flag::Default => reportv(krate, self.verbose),
            }
        }
    }
}

fn reportv(krate: &crates::Crate, verbose: bool) {
    if verbose {
        println!("{:#}", krate);
    } else {
        println!("{}", krate);
    }
}

fn query(krate: &str) -> requests::RequestsResult {
    requests::get(&format!("http://crates.io/api/v1/crates/{}", krate))
}

fn get_crate(response: &requests::Response) -> Option<crates::Crate> {
    response.json().ok().map(|k| crates::Crate::new(k["crate"].clone()))
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
        .bin_name(CARGO)
        .author(crate_authors!())
        .version(crate_version!())
        .about("Query crates.io registry for crates details")
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("info")
            .setting(AppSettings::ArgRequiredElseHelp)
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("documentation")
                .short("d")
                .long("documentation")
                .help("Report documentation URL"))
            .arg(Arg::with_name("downloads")
                .short("D")
                .long("downloads")
                .help("Report number of crate downloads"))
            .arg(Arg::with_name("homepage")
                .short("H")
                .long("homepage")
                .help("Report home page URL"))
            .arg(Arg::with_name("repository")
                .short("r")
                .long("repository")
                .help("Report crate repository URL"))
            .arg(Arg::with_name("json")
                .short("j")
                .long("json")
                .help("Report raw JSON data from crates.io")
                .conflicts_with_all(&["documentation", "downloads", "homepage", "repository"]))
            .arg(Arg::with_name("verbose")
                .short("v")
                .long("verbose")
                .help("Report more details"))
            .arg_from_usage("<crate>... 'crate to query'"))
        .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        if let Some(crates) = info.values_of("crate") {
            let rep = Report::new(info);
            for krate in crates {
                // debug(&krate);
                rep.report(krate);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Simpe tools for dealing with masks, and abstracts the requirement of
//! image.

extern crate image;

use std::error::Error;
use std::path::Path;

use self::image::{DynamicImage, GenericImage, Pixel};
use rand::{thread_rng, ThreadRng, Rng};

pub struct Mask {
    image: Box<DynamicImage>,
    /// Pixels per unit
    ppu: f64,
    rng: ThreadRng,
}

impl Mask {
    pub fn new(path: &Path, ppu: f64) -> Result<Self, Box<Error>> {
        let img = image::open(path)?;
        Ok(Self {
               image: Box::new(img),
               ppu: ppu,
               rng: thread_rng(),
           })
    }

    pub fn keep(&mut self, x: f64, y: f64) -> bool {
        let i = (x * self.ppu).floor() as u32 % self.image.width();
        let j = (y * self.ppu).floor() as u32 % self.image.height();
        let alpha = self.image.get_pixel(i, j).channels()[3];
        let prob = alpha as f64 / 255.0;
        let shoot: f64 = self.rng.next_f64();
        shoot < prob
    }
}<commit_msg>Closes #35 fix the images for ease of use.<commit_after>//! Simpe tools for dealing with masks, and abstracts the requirement of
//! image.

extern crate image;

use std::error::Error;
use std::path::Path;

use self::image::{DynamicImage, GenericImage, Pixel};
use rand::{thread_rng, ThreadRng, Rng};

pub struct Mask {
    image: Box<DynamicImage>,
    /// Pixels per unit
    ppu: f64,
    rng: ThreadRng,
}

impl Mask {
    pub fn new(path: &Path, ppu: f64) -> Result<Self, Box<Error>> {
        let img = image::open(path)?;
        Ok(Self {
               image: Box::new(img),
               ppu: ppu,
               rng: thread_rng(),
           })
    }

    pub fn keep(&mut self, x: f64, y: f64) -> bool {
        let i = (x * self.ppu).floor() as u32 % self.image.width();
        let j = (y * self.ppu).floor() as u32 % self.image.height();
        let j = self.image.height() - j - 1;
        let alpha = self.image.get_pixel(i, j).channels()[3];
        let prob = alpha as f64 / 255.0;
        let shoot: f64 = self.rng.next_f64();
        shoot < prob
    }
}
<|endoftext|>


<commit_before>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// pair := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
////// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(pair_0_1.fst_ref(), Ok(&zero()));
///	assert_eq!(pair_0_1.snd_ref(), Ok(&one()));
/// ```
pub fn pair() -> Term { abs(abs(abs(Var(1).app(Var(3)).app(Var(2))))) }

/// Applied to a Church-encoded pair (a, b) it yields a.
///
/// first := λp.p true = λ 1 true
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(first().app(pair_0_1)), zero());
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair (a, b) it yields b.
///
/// second := λp.p false = λ 1 false
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(second().app(pair_0_1)), one());
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
	/// Checks whether self is a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert!(pair01.is_pair());
	/// ```
	pub fn is_pair(&self) -> bool {
		self.fst_ref().is_ok() && self.snd_ref().is_ok()
	}

	/// Splits a Church-encoded pair into a pair of terms, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair(), Ok((zero(), one())));
	/// ```
	pub fn unpair(self) -> Result<(Term, Term), Error> {
		if let Abs(_) = self {
			if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
				Ok((try!(wrapped_a.rhs()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp() {
				Ok((try!(wrapped_a.rhs()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Splits a Church-encoded pair into a pair of references to its underlying terms.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
	/// ```
	pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
		if let Abs(_) = *self {
			if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
				Ok((try!(wrapped_a.rhs_ref()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp_ref() {
				Ok((try!(wrapped_a.rhs_ref()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
	/// ```
	pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
		if let Abs(_) = *self {
			if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
				Ok((try!(wrapped_a.rhs_ref_mut()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
				Ok((try!(wrapped_a.rhs_ref_mut()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Returns the first term from a Church-encoded pair, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst(), Ok(zero()));
	/// ```
	pub fn fst(self) -> Result<Term, Error> {
		Ok(try!(self.unpair()).0)
	}

	/// Returns a reference to the first term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
	/// ```
	pub fn fst_ref(&self) -> Result<&Term, Error> {
		Ok(try!(self.unpair_ref()).0)
	}

	/// Returns a mutable reference to the first term of a Church-encoded pair.
	/// Returns a reference to the first term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
	/// ```
	pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
		Ok(try!(self.unpair_ref_mut()).0)
	}

	/// Returns the second term from a Church-encoded pair, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd(), Ok(one()));
	/// ```
	pub fn snd(self) -> Result<Term, Error> {
		Ok(try!(self.unpair()).1)
	}

	/// Returns a reference to the second term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd_ref(), Ok(&one()));
	/// ```
	pub fn snd_ref(&self) -> Result<&Term, Error> {
		Ok(try!(self.unpair_ref()).1)
	}

	/// Returns a mutable reference to the second term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
	/// ```
	pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
		Ok(try!(self.unpair_ref_mut()).1)
	}
}

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

	#[test]
	fn pair_operations() {
		let pair_four_three = normalize(pair().app(to_cnum(4)).app(to_cnum(3)));

		assert!(pair_four_three.is_pair());

		assert_eq!(pair_four_three.fst_ref(), Ok(&to_cnum(4)));
		assert_eq!(pair_four_three.snd_ref(), Ok(&to_cnum(3)));

		let unpaired = pair_four_three.unpair();
		assert_eq!(unpaired, Ok((to_cnum(4), to_cnum(3))));
	}
}
<commit_msg>Fix a pair test<commit_after>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// pair := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
/// let pair01 = pair().app(zero()).app(one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
///	assert_eq!(pair01.snd_ref(), Ok(&one()));
/// ```
pub fn pair() -> Term { abs(abs(abs(Var(1).app(Var(3)).app(Var(2))))) }

/// Applied to a Church-encoded pair (a, b) it yields a.
///
/// first := λp.p true = λ 1 true
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(first().app(pair_0_1)), zero());
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair (a, b) it yields b.
///
/// second := λp.p false = λ 1 false
///
/// # Example
/// ```
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::normalize;
///
/// let pair_0_1 = pair().app(zero()).app(one());
///
/// assert_eq!(normalize(second().app(pair_0_1)), one());
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
	/// Checks whether self is a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert!(pair01.is_pair());
	/// ```
	pub fn is_pair(&self) -> bool {
		self.fst_ref().is_ok() && self.snd_ref().is_ok()
	}

	/// Splits a Church-encoded pair into a pair of terms, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair(), Ok((zero(), one())));
	/// ```
	pub fn unpair(self) -> Result<(Term, Term), Error> {
		if let Abs(_) = self {
			if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
				Ok((try!(wrapped_a.rhs()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp() {
				Ok((try!(wrapped_a.rhs()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Splits a Church-encoded pair into a pair of references to its underlying terms.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
	/// ```
	pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
		if let Abs(_) = *self {
			if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
				Ok((try!(wrapped_a.rhs_ref()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp_ref() {
				Ok((try!(wrapped_a.rhs_ref()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
	/// ```
	pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
		if let Abs(_) = *self {
			if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
				Ok((try!(wrapped_a.rhs_ref_mut()), b))
			} else {
				Err(NotAPair)
			}
		} else {
			if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
				Ok((try!(wrapped_a.rhs_ref_mut()), b))
			} else {
				Err(NotAPair)
			}
		}
	}

	/// Returns the first term from a Church-encoded pair, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst(), Ok(zero()));
	/// ```
	pub fn fst(self) -> Result<Term, Error> {
		Ok(try!(self.unpair()).0)
	}

	/// Returns a reference to the first term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
	/// ```
	pub fn fst_ref(&self) -> Result<&Term, Error> {
		Ok(try!(self.unpair_ref()).0)
	}

	/// Returns a mutable reference to the first term of a Church-encoded pair.
	/// Returns a reference to the first term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
	/// ```
	pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
		Ok(try!(self.unpair_ref_mut()).0)
	}

	/// Returns the second term from a Church-encoded pair, consuming self.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd(), Ok(one()));
	/// ```
	pub fn snd(self) -> Result<Term, Error> {
		Ok(try!(self.unpair()).1)
	}

	/// Returns a reference to the second term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd_ref(), Ok(&one()));
	/// ```
	pub fn snd_ref(&self) -> Result<&Term, Error> {
		Ok(try!(self.unpair_ref()).1)
	}

	/// Returns a mutable reference to the second term of a Church-encoded pair.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::pair::pair;
	/// use lambda_calculus::arithmetic::{zero, one};
	///
	/// let mut pair01 = pair().app(zero()).app(one());
	///
	/// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
	/// ```
	pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
		Ok(try!(self.unpair_ref_mut()).1)
	}
}

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

	#[test]
	fn pair_operations() {
		let pair_four_three = normalize(pair().app(to_cnum(4)).app(to_cnum(3)));

		assert!(pair_four_three.is_pair());

		assert_eq!(pair_four_three.fst_ref(), Ok(&to_cnum(4)));
		assert_eq!(pair_four_three.snd_ref(), Ok(&to_cnum(3)));

		let unpaired = pair_four_three.unpair();
		assert_eq!(unpaired, Ok((to_cnum(4), to_cnum(3))));
	}
}
<|endoftext|>


<commit_before>use libc::{self, c_void, c_char, c_int, c_uint, c_double};
use std::ffi::CString;
use std::ptr;
use heartbeats_sys::heartbeat::Heartbeat;

pub type POETApplyFn = unsafe extern fn(states: *mut c_void,
                                        num_states: c_uint,
                                        id: c_uint,
                                        last_id: c_uint);

pub type POETCurrentStateFn = unsafe extern fn(states: *const c_void,
                                               num_states: c_uint,
                                               curr_state_id: *mut c_uint) -> i32;

#[link(name = "poet")]
extern {
    /*
     * Core functions - poet.h
     */

    fn poet_init(heart: *mut c_void,
                 perf_goal: c_double,
                 num_system_states: c_uint,
                 control_states: *mut c_void,
                 apply_states: *mut c_void,
                 apply_func: POETApplyFn,
                 curr_state_func: POETCurrentStateFn,
                 buffer_depth: c_uint,
                 log_filename: *const c_char) -> *mut c_void;

    fn poet_apply_control(state: *mut c_void);

    fn poet_destroy(state: *mut c_void);

    /*
     * Configuration/utility functions - poet_config.h
     */

    fn apply_cpu_config(states: *mut c_void,
                        num_states: c_uint,
                        id: c_uint,
                        last_id: c_uint);

    fn get_control_states(path: *const c_char,
                          states: *mut *mut c_void,
                          num_states: *mut c_uint) -> c_int;

    fn get_cpu_states(path: *const c_char,
                      states: *mut *mut c_void,
                      num_states: *mut c_uint) -> c_int;

    fn get_current_cpu_state(states: *const c_void,
                             num_states: c_uint,
                             curr_state_id: *mut c_uint) -> c_int;

}

pub struct POETStates {
    pub control_states: *mut c_void,
    pub cpu_states: *mut c_void,
    pub num_states: u32,
}

impl POETStates  {
    pub fn new() -> Result<POETStates, String> {
        let mut control_states = ptr::null_mut();
        let mut cpu_states = ptr::null_mut();
        let mut num_ctl_states : u32 = 0;
        let mut num_cpu_states : u32 = 0;
        let res = unsafe {
            get_control_states(ptr::null(),
                               &mut control_states,
                               &mut num_ctl_states)
        };
        if res != 0 {
            return Err("Failed to load control states".to_string());
        }
        let res = unsafe {
            get_cpu_states(ptr::null(),
                           &mut cpu_states,
                           &mut num_cpu_states)
        };
        if res != 0 {
            unsafe {
                libc::free(control_states);
            }
            return Err("Failed to load cpu states".to_string());
        }
        if num_ctl_states != num_cpu_states {
            unsafe {
                libc::free(control_states);
                libc::free(cpu_states);
            }
            return Err("Number of control and cpu states don't match".to_string());
        }
        return Ok(POETStates {
                    control_states: control_states,
                    cpu_states: cpu_states,
                    num_states: num_ctl_states,
                });
    }
}

impl Drop for POETStates {
    fn drop(&mut self) {
        unsafe {
            libc::free(self.control_states);
            libc::free(self.cpu_states);
        }
        println!("Cleaned up POET states");
    }
}

pub struct POET {
    pub poet: *mut c_void,
}

impl POET {
    pub fn new(hb: &mut Heartbeat,
               perf_goal: f64,
               poet_states: &mut POETStates,
               apply_func: Option<POETApplyFn>,
               curr_state_func: Option<POETCurrentStateFn>,
               buffer_depth: u32,
               log_filename: &str) -> Result<POET, String> {
        let apply_func = match apply_func {
            Some(p) => p,
            None => apply_cpu_config,
        };
        let curr_state_func = match curr_state_func {
            Some(p) => p,
            None => get_current_cpu_state,
        };
        let poet = unsafe {
            poet_init(hb.hb, perf_goal,
                      poet_states.num_states, poet_states.control_states, poet_states.cpu_states,
                      apply_func, curr_state_func,
                      buffer_depth,
                      CString::new(log_filename).unwrap().as_ptr())
        };
        if poet.is_null() {
            return Err("Failed to instantiate POET object".to_string());
        }
        Ok(POET { poet: poet, })
    }

    pub fn apply_control(&mut self) {
        unsafe {
            poet_apply_control(self.poet);
        }
    }
}

impl Drop for POET {
    fn drop(&mut self) {
        unsafe {
            poet_destroy(self.poet);
        }
        println!("Cleaned up POET");
    }
}

<commit_msg>Give control of control and cpu states to user<commit_after>use libc::{self, c_void, c_char, c_int, c_uint, c_double};
use std::ffi::CString;
use std::ptr;
use heartbeats_sys::heartbeat::Heartbeat;

pub type POETApplyFn = unsafe extern fn(states: *mut c_void,
                                        num_states: c_uint,
                                        id: c_uint,
                                        last_id: c_uint);

pub type POETCurrentStateFn = unsafe extern fn(states: *const c_void,
                                               num_states: c_uint,
                                               curr_state_id: *mut c_uint) -> i32;

#[link(name = "poet")]
extern {
    /*
     * Core functions - poet.h
     */

    fn poet_init(heart: *mut c_void,
                 perf_goal: c_double,
                 num_system_states: c_uint,
                 control_states: *mut POETControlState,
                 apply_states: *mut POETCpuState,
                 apply_func: POETApplyFn,
                 curr_state_func: POETCurrentStateFn,
                 buffer_depth: c_uint,
                 log_filename: *const c_char) -> *mut c_void;

    fn poet_apply_control(state: *mut c_void);

    fn poet_destroy(state: *mut c_void);

    /*
     * Configuration/utility functions - poet_config.h
     */

    fn apply_cpu_config(states: *mut c_void,
                        num_states: c_uint,
                        id: c_uint,
                        last_id: c_uint);

    pub fn get_control_states(path: *const c_char,
                              states: *mut *mut POETControlState,
                              num_states: *mut c_uint) -> c_int;

    pub fn get_cpu_states(path: *const c_char,
                          states: *mut *mut POETCpuState,
                          num_states: *mut c_uint) -> c_int;

    fn get_current_cpu_state(states: *const c_void,
                             num_states: c_uint,
                             curr_state_id: *mut c_uint) -> c_int;

}

#[repr(C)]
pub struct POETControlState {
    pub id: c_uint,
    pub speedup: c_double,
    pub cost: c_double,
}

impl POETControlState {
    pub fn new() -> Result<(*mut POETControlState, u32), String> {
        let mut control_states = ptr::null_mut();
        let mut num_ctl_states : u32 = 0;
        let res = unsafe {
            get_control_states(ptr::null(),
                               &mut control_states,
                               &mut num_ctl_states)
        };
        if res != 0 {
            return Err("Failed to load control states".to_string());
        }
        Ok((control_states, num_ctl_states))
    }
}

#[repr(C)]
pub struct POETCpuState {
    id: c_uint,
    freq: c_uint,
    cores: c_uint,
}

impl POETCpuState {
    pub fn new() -> Result<(*mut POETCpuState, u32), String> {
        let mut cpu_states = ptr::null_mut();
        let mut num_cpu_states : u32 = 0;
        let res = unsafe {
            get_cpu_states(ptr::null(),
                           &mut cpu_states,
                           &mut num_cpu_states)
        };
        if res != 0 {
            return Err("Failed to load cpu states".to_string());
        }
        Ok((cpu_states, num_cpu_states))
    }
}

pub struct POET {
    pub poet: *mut c_void,
}

impl POET {
    pub fn new(hb: &mut Heartbeat,
               perf_goal: f64,
               control_states: *mut POETControlState,
               cpu_states: *mut POETCpuState,
               num_states: u32,
               apply_func: Option<POETApplyFn>,
               curr_state_func: Option<POETCurrentStateFn>,
               buffer_depth: u32,
               log_filename: &str) -> Result<POET, String> {
        let apply_func = match apply_func {
            Some(p) => p,
            None => apply_cpu_config,
        };
        let curr_state_func = match curr_state_func {
            Some(p) => p,
            None => get_current_cpu_state,
        };
        let poet = unsafe {
            poet_init(hb.hb, perf_goal,
                      num_states, control_states, cpu_states,
                      apply_func, curr_state_func,
                      buffer_depth,
                      CString::new(log_filename).unwrap().as_ptr())
        };
        if poet.is_null() {
            return Err("Failed to instantiate POET object".to_string());
        }
        Ok(POET { poet: poet, })
    }

    pub fn apply_control(&mut self) {
        unsafe {
            poet_apply_control(self.poet);
        }
    }
}

impl Drop for POET {
    fn drop(&mut self) {
        unsafe {
            poet_destroy(self.poet);
        }
        println!("Cleaned up POET");
    }
}

#[test]
fn test_basic() {
    let mut hb = Heartbeat::new(None, 20, 20, "heartbeat.log", None).unwrap();
    let (control_states, num_ctl_states): (*mut POETControlState, u32) = POETControlState::new().ok().expect("Failed to load control states");
    let (cpu_states, num_cpu_states): (*mut POETCpuState, u32) = POETCpuState::new().ok().expect("Failed to load cpu states");
    if num_ctl_states != num_cpu_states {
        panic!("Number of control and cpu states don't match");
    }
    let mut poet = POET::new(&mut hb, 100.0,
                             control_states, cpu_states, num_ctl_states,
                             None, None,
                             20u32, "poet.log").ok().expect("Failed to initialize POET");
    hb.heartbeat(0, 1, 0.0, None);
    poet.apply_control();
    unsafe {
        libc::free(control_states as *mut c_void);
        libc::free(cpu_states as *mut c_void);
    }
}
<|endoftext|>