<commit_before>extern crate colored;
extern crate json;
extern crate structopt;
extern crate syntax;

mod builder;
mod dot_printer;
mod printer;
mod tree;

use std::process;
use std::{io, path};

use syntax::ast::NodeId;
use syntax::parse::{self, ParseSess};
use syntax::source_map;
use syntax::visit::Visitor;

use structopt::StructOpt;

use colored::*;

use builder::Builder;
use builder::Config as BuilderConfig;

use printer::Config as PrinterConfig;
use printer::Printer;

use dot_printer::Config as DotPrinterConfig;
use dot_printer::DotPrinter;

pub enum Error {
    CargoExecutionFailed(io::Error),
    InvalidManifestJson(json::JsonError),
    NoLibraryTargetFound,
    NoMatchingBinaryTargetFound,
    NoTargetProvided,
    Syntax(String),
}

fn get_manifest() -> Result<json::JsonValue, Error> {
    let output = process::Command::new("cargo").arg("read-manifest").output();
    let stdout = try!(output.map_err(Error::CargoExecutionFailed)).stdout;
    let json_string = String::from_utf8(stdout).expect("Failed reading cargo output");
    json::parse(&json_string).map_err(Error::InvalidManifestJson)
}

fn get_target_config<'a>(
    target_cfgs: &'a [json::JsonValue],
    args: &Arguments,
) -> Result<&'a json::JsonValue, Error> {
    fn is_lib(cfg: &json::JsonValue) -> bool {
        let is_lib = cfg["kind"].contains("lib");
        let is_rlib = cfg["kind"].contains("rlib");
        let is_staticlib = cfg["kind"].contains("staticlib");
        is_lib || is_rlib || is_staticlib
    }
    if args.lib {
        target_cfgs
            .into_iter()
            .find(|cfg| is_lib(cfg))
            .ok_or(Error::NoLibraryTargetFound)
    } else if let Some(ref name) = args.bin {
        target_cfgs
            .into_iter()
            .find(|cfg| cfg["kind"].contains("bin") && cfg["name"] == name.as_ref())
            .ok_or(Error::NoMatchingBinaryTargetFound)
    } else if target_cfgs.len() == 1 {
        Ok(&target_cfgs[0])
    } else {
        target_cfgs
            .into_iter()
            .find(|cfg| is_lib(cfg))
            .ok_or(Error::NoTargetProvided)
    }
}

fn get_build_scripts(target_cfgs: &[json::JsonValue]) -> Vec<path::PathBuf> {
    target_cfgs
        .into_iter()
        .filter_map(|cfg| {
            if cfg["kind"].contains("custom-build") {
                cfg["src_path"]
                    .as_str()
                    .map(|s| path::Path::new("./").join(s))
            } else {
                None
            }
        }).collect()
}

fn run(args: &Arguments) -> Result<(), Error> {
    let json = try!(get_manifest());
    let target_cfgs: Vec<_> = json["targets"].members().cloned().collect();
    let build_scripts = get_build_scripts(&target_cfgs);
    let target_config = try!(get_target_config(&target_cfgs, args));
    let target_name = target_config["name"]
        .as_str()
        .expect("Expected `name` property.");
    let src_path = target_config["src_path"]
        .as_str()
        .expect("Expected `src_path` property.");
    let parse_session = ParseSess::new(source_map::FilePathMapping::empty());

    syntax::with_globals(|| {
        let krate = try!(
            match parse::parse_crate_from_file(src_path.as_ref(), &parse_session) {
                Ok(_) if parse_session.span_diagnostic.has_errors() => Err(None),
                Ok(krate) => Ok(krate),
                Err(e) => Err(Some(e)),
            }.map_err(|e| Error::Syntax(format!("{:?}", e)))
        );

        let builder_config = BuilderConfig {
            include_orphans: args.orphans,
            ignored_files: build_scripts,
        };
        let mut builder = Builder::new(
            builder_config,
            target_name.to_string(),
            parse_session.source_map(),
        );
        builder.visit_mod(&krate.module, krate.span, &krate.attrs[..], NodeId::from(0_usize));

        match args.command {
            Command::Graph {
                conditional,
                external,
                types,
            } => {
                let printer_config = DotPrinterConfig {
                    colored: !args.plain,
                    show_conditional: conditional,
                    show_external: external,
                    show_types: types,
                };
                println!("digraph something {{");
                let tree = builder.tree();
                let printer = DotPrinter::new(printer_config, tree);
                tree.accept(&mut vec![], &mut vec![], &printer);
                println!("}}");
            }
            Command::Tree => {
                let printer_config = PrinterConfig {
                    colored: !args.plain,
                };
                let printer = Printer::new(printer_config);
                println!();
                let tree = builder.tree();
                tree.accept(&mut vec![], &mut vec![], &printer);
                println!();
            }
        }

        Ok(())
    })
}

#[derive(StructOpt)]
#[structopt(
    name = "cargo-modules",
    about = "Print a crate's module tree or graph.",
    author = "",
    after_help = "If neither `--bin` nor `--example` are given,\n\
                  then if the project only has one bin target it will be run.\n\
                  Otherwise `--bin` specifies the bin target to run.\n\
                  At most one `--bin` can be provided.\n\
                  \n(On 'Windows' systems coloring is disabled. Sorry.)\n"
)]
struct Arguments {
    /// Include orphaned modules (i.e. unused files in /src).
    #[structopt(short = "o", long = "orphans")]
    orphans: bool,

    /// List modules of this package's library (overrides '--bin')
    #[structopt(short = "l", long = "lib")]
    lib: bool,

    /// Plain uncolored output.
    #[structopt(short = "p", long = "plain")]
    plain: bool,

    /// List modules of the specified binary
    #[structopt(short = "b", long = "bin")]
    bin: Option<String>,

    /// Sets an explicit crate path (ignored)
    #[structopt(name = "CRATE_DIR")]
    _dir: Option<String>,

    #[structopt(subcommand)]
    command: Command,
}

#[derive(StructOpt)]
enum Command {
    #[structopt(
        name = "tree",
        about = "Print a crate's module tree.",
        author = ""
    )]
    Tree,
    #[structopt(
        name = "graph",
        about = "Print a crate's module graph.",
        author = "",
        after_help = "If you have xdot installed on your system, you can run this using:\n\
                      `cargo modules graph | xdot -`"
    )]
    Graph {
        /// Show external types.
        #[structopt(short = "e", long = "external")]
        external: bool,
        /// Show conditional modules.
        #[structopt(short = "c", long = "conditional")]
        conditional: bool,
        /// Plain uncolored output.
        #[structopt(short = "t", long = "types")]
        types: bool,
    },
}

fn main() {
    let arguments = Arguments::from_args();

    if let Err(error) = run(&arguments) {
        let error_string = match error {
            Error::CargoExecutionFailed(error) => {
                format!("Error: Failed to run `cargo` command.\n{:?}", error)
            }
            Error::InvalidManifestJson(error) => {
                format!("Error: Failed to parse JSON response.\n{:?}", error)
            }
            Error::NoLibraryTargetFound => "Error: No library target found.".to_string(),
            Error::NoMatchingBinaryTargetFound => {
                "Error: No matching binary target found.".to_string()
            }
            Error::NoTargetProvided => "Error: Please specify a target to process.".to_string(),
            Error::Syntax(error) => format!("Error: Failed to parse: {}", error),
        };
        println!("{}", error_string.red());
    }
}
<commit_msg>Call iter directly (clipply)<commit_after>extern crate colored;
extern crate json;
extern crate structopt;
extern crate syntax;

mod builder;
mod dot_printer;
mod printer;
mod tree;

use std::process;
use std::{io, path};

use syntax::ast::NodeId;
use syntax::parse::{self, ParseSess};
use syntax::source_map;
use syntax::visit::Visitor;

use structopt::StructOpt;

use colored::*;

use builder::Builder;
use builder::Config as BuilderConfig;

use printer::Config as PrinterConfig;
use printer::Printer;

use dot_printer::Config as DotPrinterConfig;
use dot_printer::DotPrinter;

pub enum Error {
    CargoExecutionFailed(io::Error),
    InvalidManifestJson(json::JsonError),
    NoLibraryTargetFound,
    NoMatchingBinaryTargetFound,
    NoTargetProvided,
    Syntax(String),
}

fn get_manifest() -> Result<json::JsonValue, Error> {
    let output = process::Command::new("cargo").arg("read-manifest").output();
    let stdout = try!(output.map_err(Error::CargoExecutionFailed)).stdout;
    let json_string = String::from_utf8(stdout).expect("Failed reading cargo output");
    json::parse(&json_string).map_err(Error::InvalidManifestJson)
}

fn get_target_config<'a>(
    target_cfgs: &'a [json::JsonValue],
    args: &Arguments,
) -> Result<&'a json::JsonValue, Error> {
    fn is_lib(cfg: &json::JsonValue) -> bool {
        let is_lib = cfg["kind"].contains("lib");
        let is_rlib = cfg["kind"].contains("rlib");
        let is_staticlib = cfg["kind"].contains("staticlib");
        is_lib || is_rlib || is_staticlib
    }
    if args.lib {
        target_cfgs
            .iter()
            .find(|cfg| is_lib(cfg))
            .ok_or(Error::NoLibraryTargetFound)
    } else if let Some(ref name) = args.bin {
        target_cfgs
            .iter()
            .find(|cfg| cfg["kind"].contains("bin") && cfg["name"] == name.as_ref())
            .ok_or(Error::NoMatchingBinaryTargetFound)
    } else if target_cfgs.len() == 1 {
        Ok(&target_cfgs[0])
    } else {
        target_cfgs
            .iter()
            .find(|cfg| is_lib(cfg))
            .ok_or(Error::NoTargetProvided)
    }
}

fn get_build_scripts(target_cfgs: &[json::JsonValue]) -> Vec<path::PathBuf> {
    target_cfgs
        .iter()
        .filter_map(|cfg| {
            if cfg["kind"].contains("custom-build") {
                cfg["src_path"]
                    .as_str()
                    .map(|s| path::Path::new("./").join(s))
            } else {
                None
            }
        }).collect()
}

fn run(args: &Arguments) -> Result<(), Error> {
    let json = try!(get_manifest());
    let target_cfgs: Vec<_> = json["targets"].members().cloned().collect();
    let build_scripts = get_build_scripts(&target_cfgs);
    let target_config = try!(get_target_config(&target_cfgs, args));
    let target_name = target_config["name"]
        .as_str()
        .expect("Expected `name` property.");
    let src_path = target_config["src_path"]
        .as_str()
        .expect("Expected `src_path` property.");
    let parse_session = ParseSess::new(source_map::FilePathMapping::empty());

    syntax::with_globals(|| {
        let krate = try!(
            match parse::parse_crate_from_file(src_path.as_ref(), &parse_session) {
                Ok(_) if parse_session.span_diagnostic.has_errors() => Err(None),
                Ok(krate) => Ok(krate),
                Err(e) => Err(Some(e)),
            }.map_err(|e| Error::Syntax(format!("{:?}", e)))
        );

        let builder_config = BuilderConfig {
            include_orphans: args.orphans,
            ignored_files: build_scripts,
        };
        let mut builder = Builder::new(
            builder_config,
            target_name.to_string(),
            parse_session.source_map(),
        );
        builder.visit_mod(&krate.module, krate.span, &krate.attrs[..], NodeId::from(0_usize));

        match args.command {
            Command::Graph {
                conditional,
                external,
                types,
            } => {
                let printer_config = DotPrinterConfig {
                    colored: !args.plain,
                    show_conditional: conditional,
                    show_external: external,
                    show_types: types,
                };
                println!("digraph something {{");
                let tree = builder.tree();
                let printer = DotPrinter::new(printer_config, tree);
                tree.accept(&mut vec![], &mut vec![], &printer);
                println!("}}");
            }
            Command::Tree => {
                let printer_config = PrinterConfig {
                    colored: !args.plain,
                };
                let printer = Printer::new(printer_config);
                println!();
                let tree = builder.tree();
                tree.accept(&mut vec![], &mut vec![], &printer);
                println!();
            }
        }

        Ok(())
    })
}

#[derive(StructOpt)]
#[structopt(
    name = "cargo-modules",
    about = "Print a crate's module tree or graph.",
    author = "",
    after_help = "If neither `--bin` nor `--example` are given,\n\
                  then if the project only has one bin target it will be run.\n\
                  Otherwise `--bin` specifies the bin target to run.\n\
                  At most one `--bin` can be provided.\n\
                  \n(On 'Windows' systems coloring is disabled. Sorry.)\n"
)]
struct Arguments {
    /// Include orphaned modules (i.e. unused files in /src).
    #[structopt(short = "o", long = "orphans")]
    orphans: bool,

    /// List modules of this package's library (overrides '--bin')
    #[structopt(short = "l", long = "lib")]
    lib: bool,

    /// Plain uncolored output.
    #[structopt(short = "p", long = "plain")]
    plain: bool,

    /// List modules of the specified binary
    #[structopt(short = "b", long = "bin")]
    bin: Option<String>,

    /// Sets an explicit crate path (ignored)
    #[structopt(name = "CRATE_DIR")]
    _dir: Option<String>,

    #[structopt(subcommand)]
    command: Command,
}

#[derive(StructOpt)]
enum Command {
    #[structopt(
        name = "tree",
        about = "Print a crate's module tree.",
        author = ""
    )]
    Tree,
    #[structopt(
        name = "graph",
        about = "Print a crate's module graph.",
        author = "",
        after_help = "If you have xdot installed on your system, you can run this using:\n\
                      `cargo modules graph | xdot -`"
    )]
    Graph {
        /// Show external types.
        #[structopt(short = "e", long = "external")]
        external: bool,
        /// Show conditional modules.
        #[structopt(short = "c", long = "conditional")]
        conditional: bool,
        /// Plain uncolored output.
        #[structopt(short = "t", long = "types")]
        types: bool,
    },
}

fn main() {
    let arguments = Arguments::from_args();

    if let Err(error) = run(&arguments) {
        let error_string = match error {
            Error::CargoExecutionFailed(error) => {
                format!("Error: Failed to run `cargo` command.\n{:?}", error)
            }
            Error::InvalidManifestJson(error) => {
                format!("Error: Failed to parse JSON response.\n{:?}", error)
            }
            Error::NoLibraryTargetFound => "Error: No library target found.".to_string(),
            Error::NoMatchingBinaryTargetFound => {
                "Error: No matching binary target found.".to_string()
            }
            Error::NoTargetProvided => "Error: Please specify a target to process.".to_string(),
            Error::Syntax(error) => format!("Error: Failed to parse: {}", error),
        };
        println!("{}", error_string.red());
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
#[macro_use]
extern crate clap;

use clap::{Arg, App};

fn main() {
    App::new("Helium")
        .version(crate_version!())
        .author(crate_authors!())
        .about("The awesomest of editors.")
        .arg(Arg::with_name("file")
            .help("Input file")
            .index(1))
        .get_matches();

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let window = sdl_context.video()
        .unwrap()
        .window("Helium", 800, 600)
        .resizable()
        .allow_highdpi()
        .build()
        .unwrap();
    let mut renderer = window.renderer()
        .accelerated()
        .present_vsync()
        .build()
        .unwrap();
    let font = ttf_context.load_font(std::path::Path::new("DejaVuSansMono.ttf"), 16).unwrap();
    let hello =
        font.render("Hello world!").blended(sdl2::pixels::Color::RGB(150, 150, 150)).unwrap();
    let rect = sdl2::rect::Rect::new(0, 0, hello.width(), hello.height());
    let mut hello_texture = renderer.create_texture_from_surface(&hello).unwrap();
    renderer.set_draw_color(sdl2::pixels::Color::RGB(30, 35, 40));

    for event in sdl_context.event_pump().unwrap().wait_iter() {
        match event {
            sdl2::event::Event::Quit { .. } => return,
            sdl2::event::Event::Window { .. } => {
                renderer.clear();
                renderer.copy(&mut hello_texture, None, Some(rect)).unwrap();
                renderer.present();
            }
            _ => {}
        }
    }
}
<commit_msg>Larger font size<commit_after>extern crate sdl2;
#[macro_use]
extern crate clap;

use clap::{Arg, App};

fn main() {
    App::new("Helium")
        .version(crate_version!())
        .author(crate_authors!())
        .about("The awesomest of editors.")
        .arg(Arg::with_name("file")
            .help("Input file")
            .index(1))
        .get_matches();

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let window = sdl_context.video()
        .unwrap()
        .window("Helium", 800, 600)
        .resizable()
        .allow_highdpi()
        .build()
        .unwrap();
    let mut renderer = window.renderer()
        .accelerated()
        .present_vsync()
        .build()
        .unwrap();
    let font = ttf_context.load_font(std::path::Path::new("DejaVuSansMono.ttf"), 24).unwrap();
    let hello =
        font.render("Hello world!").blended(sdl2::pixels::Color::RGB(150, 150, 150)).unwrap();
    let rect = sdl2::rect::Rect::new(0, 0, hello.width(), hello.height());
    let mut hello_texture = renderer.create_texture_from_surface(&hello).unwrap();
    renderer.set_draw_color(sdl2::pixels::Color::RGB(30, 35, 40));

    for event in sdl_context.event_pump().unwrap().wait_iter() {
        match event {
            sdl2::event::Event::Quit { .. } => return,
            sdl2::event::Event::Window { .. } => {
                renderer.clear();
                renderer.copy(&mut hello_texture, None, Some(rect)).unwrap();
                renderer.present();
            }
            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>extern crate termion;
extern crate serde_json;

mod core;

use termion::{color, style};
use std::io;
use core::Core;
use std::{thread, time};

fn main() {
    let mut core = Core::new("../xi-editor/rust/target/debug/xi-core");
    core.open("foo.txt");
    core.char('h');
    core.char('e');
    core.char('l');
    core.char('l');
    core.char('o');
    core.char(' ');
    core.char('w');
    core.char('o');
    core.char('r');
    core.char('l');
    core.char('d');
    core.char('!');
    core.insert_newline();
    thread::sleep(time::Duration::from_millis(1000));
}
<commit_msg>add some sleep to show when the error occurs<commit_after>extern crate termion;
extern crate serde_json;

mod core;

use termion::{color, style};
use std::io;
use core::Core;
use std::{thread, time};

fn main() {
    let mut core = Core::new("../xi-editor/rust/target/debug/xi-core");
    thread::sleep(time::Duration::from_millis(1000));
    core.open("foo.txt");
    thread::sleep(time::Duration::from_millis(1000));
    core.char('h');
    core.char('e');
    core.char('l');
    core.char('l');
    core.char('o');
    core.char(' ');
    core.char('w');
    core.char('o');
    core.char('r');
    core.char('l');
    core.char('d');
    core.char('!');
    core.insert_newline();
    thread::sleep(time::Duration::from_millis(1000));
}
<|endoftext|>


<commit_before>#![crate_name="magog"]
#![feature(unboxed_closures, plugin)]
#![feature(core, collections, path_ext, exit_status)]
#![feature(custom_derive)]
#![plugin(rand_macros)]

#[no_link] extern crate rand_macros;
extern crate rand;
extern crate rustc_serialize;
extern crate num;
extern crate getopts;
extern crate image;
extern crate time;
extern crate toml;
#[macro_use]
extern crate calx;

use std::env;
use std::path::{PathBuf};
use std::fs::{self, File};
use std::io::prelude::*;
use std::default::Default;
use calx::backend::{Canvas, CanvasBuilder, Event};
use gamestate::GameState;
use titlestate::TitleState;

pub static SCREEN_W: u32 = 640;
pub static SCREEN_H: u32 = 360;

pub mod drawable;
pub mod tilecache;
pub mod viewutil;
pub mod worldview;
mod config;
mod gamestate;
mod titlestate;
mod sprite;
mod msg_queue;
mod console;
mod world;

pub trait State {
    fn process(&mut self, event: Event) -> Option<Transition>;
}

pub enum Transition {
    Game,
    Title,
    Exit,
}

pub fn version() -> String {
    let next_release = "0.1.0";
    let git_hash = include_str!("git_hash.inc");
    // Set is_release to true for one commit to make a release.
    let is_release = false;

    if is_release {
        format!("{}", next_release)
    } else {
        format!("{}-alpha+g{}", next_release, git_hash)
    }
}

/// Get the application data file path and ensure the path exists.
pub fn app_data_path() -> PathBuf {
    let ret = calx::app_data_path("magog");
    if !ret.exists() {
        // Create the config dir
        // TODO: Handle error
        fs::create_dir_all(&ret).unwrap();
    }
    ret
}

pub fn compiler_version() -> String {
    include_str!("../rustc_version.txt").trim().to_string()
}

pub fn screenshot(ctx: &mut Canvas) {
    use time;
    use std::path::{Path};
    use std::fs::{self, File, PathExt};
    use std::thread;
    use image;

    let shot = ctx.screenshot();

    // XXX: If the game is terminated right after taking a screenshot, the
    // screenshotting thread will be stopped and an incomplete image file will
    // result. Not sure if there's a better solution for this than some kind
    // of global worker thread pool where the screenshot thread should be
    // added.
    thread::spawn(move || {
        let timestamp = time::precise_time_s() as u64;
        // Create screenshot filenames by concatenating the current timestamp in
        // seconds with a running number from 00 to 99. 100 shots per second
        // should be good enough.

        // Default if we fail to generate any of the 100 candidates for this
        // second, just overwrite with the "xx" prefix then.
        let mut filename = format!("magog-{}{}.png", timestamp, "xx");

        // Run through candidates for this second.
        for i in 0..100 {
            let test_filename = format!("magog-{}{:02}.png", timestamp, i);
            if !Path::new(&test_filename).exists() {
                // Thread-safe claiming: create_dir will fail if the dir
                // already exists (it'll exist if another thread is gunning
                // for the same filename and managed to get past us here).
                // At least assuming that create_dir is atomic...
                let squat_dir = format!(".tmp-{}{:02}", timestamp, i);
                if std::fs::create_dir(&squat_dir).is_ok() {
                    File::create(&test_filename).unwrap();
                    filename = test_filename;
                    fs::remove_dir(&squat_dir).unwrap();
                    break;
                } else {
                    continue;
                }
            }
        }

        let _ = image::save_buffer(&Path::new(&filename), &shot, shot.width(), shot.height(), image::ColorType::RGB(8));
    });
}

pub fn main() {
    // TODO: Use persistent config object.
    let mut config: config::Config = Default::default();

    // Init the config file
    let cfg_path = config.file_path();
    if cfg_path.exists() {
        config.load(cfg_path).unwrap();
    } else {
        // Write the default config.
        let mut file = File::create(cfg_path).unwrap();
        file.write_all(config.default_file().as_bytes()).unwrap()
    }

    // Read command line arguments, *after* reading the config file. Command
    // line overrules file.
    match config.parse_args(env::args()) {
        Err(e) => {
            println!("{}", e);
            env::set_exit_status(1);
            return;
        }
        Ok(Some(msg)) => {
            println!("{}", msg);
            return;
        }
        _ => {}
    };

    let mut canvas = CanvasBuilder::new()
        .set_size(SCREEN_W, SCREEN_H)
        .set_magnify(config.magnify_mode)
        .set_title("Magog")
        .set_frame_interval(0.030f64);
    tilecache::init(&mut canvas);
    let mut state: Box<State> = Box::new(TitleState::new());

    for evt in canvas.run() {
        match state.process(evt) {
            Some(Transition::Title) => { state = Box::new(TitleState::new()); }
            Some(Transition::Game) => {
                state = Box::new(GameState::new(config)); }
            Some(Transition::Exit) => { break; }
            _ => ()
        }
    }
}
<commit_msg>Don't multithread saving screenshots<commit_after>#![crate_name="magog"]
#![feature(unboxed_closures, plugin)]
#![feature(core, collections, path_ext, exit_status)]
#![feature(custom_derive)]
#![plugin(rand_macros)]

#[no_link] extern crate rand_macros;
extern crate rand;
extern crate rustc_serialize;
extern crate num;
extern crate getopts;
extern crate image;
extern crate time;
extern crate toml;
#[macro_use]
extern crate calx;

use std::env;
use std::path::{PathBuf};
use std::fs::{self, File};
use std::io::prelude::*;
use std::default::Default;
use calx::backend::{Canvas, CanvasBuilder, Event};
use gamestate::GameState;
use titlestate::TitleState;

pub static SCREEN_W: u32 = 640;
pub static SCREEN_H: u32 = 360;

pub mod drawable;
pub mod tilecache;
pub mod viewutil;
pub mod worldview;
mod config;
mod gamestate;
mod titlestate;
mod sprite;
mod msg_queue;
mod console;
mod world;

pub trait State {
    fn process(&mut self, event: Event) -> Option<Transition>;
}

pub enum Transition {
    Game,
    Title,
    Exit,
}

pub fn version() -> String {
    let next_release = "0.1.0";
    let git_hash = include_str!("git_hash.inc");
    // Set is_release to true for one commit to make a release.
    let is_release = false;

    if is_release {
        format!("{}", next_release)
    } else {
        format!("{}-alpha+g{}", next_release, git_hash)
    }
}

/// Get the application data file path and ensure the path exists.
pub fn app_data_path() -> PathBuf {
    let ret = calx::app_data_path("magog");
    if !ret.exists() {
        // Create the config dir
        // TODO: Handle error
        fs::create_dir_all(&ret).unwrap();
    }
    ret
}

pub fn compiler_version() -> String {
    include_str!("../rustc_version.txt").trim().to_string()
}

pub fn screenshot(ctx: &mut Canvas) {
    use time;
    use std::path::{Path};
    use std::fs::{self, File, PathExt};
    use image;

    let shot = ctx.screenshot();

    let timestamp = time::precise_time_s() as u64;
    // Create screenshot filenames by concatenating the current timestamp in
    // seconds with a running number from 00 to 99. 100 shots per second
    // should be good enough.

    // Default if we fail to generate any of the 100 candidates for this
    // second, just overwrite with the "xx" prefix then.
    let mut filename = format!("magog-{}{}.png", timestamp, "xx");

    // Run through candidates for this second.
    for i in 0..100 {
        let test_filename = format!("magog-{}{:02}.png", timestamp, i);
        if !Path::new(&test_filename).exists() {
            // Thread-safe claiming: create_dir will fail if the dir
            // already exists (it'll exist if another thread is gunning
            // for the same filename and managed to get past us here).
            // At least assuming that create_dir is atomic...
            let squat_dir = format!(".tmp-{}{:02}", timestamp, i);
            if std::fs::create_dir(&squat_dir).is_ok() {
                File::create(&test_filename).unwrap();
                filename = test_filename;
                fs::remove_dir(&squat_dir).unwrap();
                break;
            } else {
                continue;
            }
        }
    }

    let _ = image::save_buffer(&Path::new(&filename), &shot, shot.width(), shot.height(), image::ColorType::RGB(8));
}

pub fn main() {
    // TODO: Use persistent config object.
    let mut config: config::Config = Default::default();

    // Init the config file
    let cfg_path = config.file_path();
    if cfg_path.exists() {
        config.load(cfg_path).unwrap();
    } else {
        // Write the default config.
        let mut file = File::create(cfg_path).unwrap();
        file.write_all(config.default_file().as_bytes()).unwrap()
    }

    // Read command line arguments, *after* reading the config file. Command
    // line overrules file.
    match config.parse_args(env::args()) {
        Err(e) => {
            println!("{}", e);
            env::set_exit_status(1);
            return;
        }
        Ok(Some(msg)) => {
            println!("{}", msg);
            return;
        }
        _ => {}
    };

    let mut canvas = CanvasBuilder::new()
        .set_size(SCREEN_W, SCREEN_H)
        .set_magnify(config.magnify_mode)
        .set_title("Magog")
        .set_frame_interval(0.030f64);
    tilecache::init(&mut canvas);
    let mut state: Box<State> = Box::new(TitleState::new());

    for evt in canvas.run() {
        match state.process(evt) {
            Some(Transition::Title) => { state = Box::new(TitleState::new()); }
            Some(Transition::Game) => {
                state = Box::new(GameState::new(config)); }
            Some(Transition::Exit) => { break; }
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl > class_decl
        / method_decl > method_decl

    class_decl
        = kw_class constant class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block

    block
        = lbracket ((stmt / expr) terminator?)* rbracket

    stmt
        = if_stmt > if_stmt
        / while_stmt > while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    call_with_receiver
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    call_no_receiver
        = identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr
          / call_with_receiver > call_with_receiver
          / receiver_expr

    receiver_expr
        = literal
        / call_no_receiver > call_no_receiver
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*)

    param_list
        = (identifier ("," spacing identifier)*)

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_no_receiver(method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(None, method, args))
    }

    fn call_with_receiver(receiver: Option<PExpr>, method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<(PExpr, Vec<PExpr>)>, body: Vec<(PExpr, Option<()>)>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn if_stmt(condition: PExpr, block: Vec<(PExpr, Option<()>)>, else_block: Option<Vec<(PExpr, Option<()>)>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<(PExpr, Option<()>)>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>),
        IfStatement(PExpr, Vec<(PExpr, Option<()>)>, Option<Vec<(PExpr, Option<()>)>>),
        MethodDecl(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>),
        WhileStatement(PExpr, Vec<(PExpr, Option<()>)>),
        Call(Option<PExpr>, PExpr, Option<(PExpr, Vec<PExpr>)>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", awesome::parse_program(contents.stream()).unwrap_data());
}
<commit_msg>Improved the way ClassDecl is presented and fixed MethodDecl parsing.<commit_after>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl > class_decl
        / method_decl

    class_decl
        = kw_class constant class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block > method_decl

    block
        = lbracket ((stmt / expr) terminator?)* rbracket

    stmt
        = if_stmt > if_stmt
        / while_stmt > while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    call_with_receiver
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    call_no_receiver
        = identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr
          / call_with_receiver > call_with_receiver
          / receiver_expr

    receiver_expr
        = call_no_receiver > call_no_receiver
        / literal
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*)

    param_list
        = (identifier ("," spacing identifier)*)

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_no_receiver(method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(None, method, args))
    }

    fn call_with_receiver(receiver: Option<PExpr>, method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<PExpr>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<(PExpr, Vec<PExpr>)>, body: Vec<(PExpr, Option<()>)>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn if_stmt(condition: PExpr, block: Vec<(PExpr, Option<()>)>, else_block: Option<Vec<(PExpr, Option<()>)>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<(PExpr, Option<()>)>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<PExpr>),
        IfStatement(PExpr, Vec<(PExpr, Option<()>)>, Option<Vec<(PExpr, Option<()>)>>),
        MethodDecl(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>),
        WhileStatement(PExpr, Vec<(PExpr, Option<()>)>),
        Call(Option<PExpr>, PExpr, Option<(PExpr, Vec<PExpr>)>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", awesome::parse_program(contents.stream()).unwrap_data());
}
<|endoftext|>


<commit_before>use std::fs;
use std::env;
use std::fs::File;
use std::io::Read;
use std::hash::Hasher;
use std::path::PathBuf;
use std::collections::HashMap;
use std::os::unix::fs::MetadataExt;
use std::collections::hash_map::DefaultHasher;

#[macro_use]
extern crate log;
extern crate env_logger;

struct FileEntry {
    inode: u64,
    dev:  u64,
    path : String,
}

fn collect_files(dir: &String, h: &mut HashMap<u64, Vec<FileEntry>>) {

    let entries = match fs::read_dir(dir) {
        Ok(x) => x,
        _ => {
            warn!("{}: invalid directory", dir);
            return
        },
    };

    for path in  entries.filter( |x| x.is_ok() ).map( |x| x.unwrap().path() )
                .collect::<Vec<PathBuf>>() {
        if let (Some(path_str), Ok(metadata)) =
                (path.to_str(), path.symlink_metadata()) {
            let ft = metadata.file_type();
            if ft.is_symlink() {
                continue;
            } else if ft.is_file() {
                match metadata.len() {
                    0 => continue, //Ignore empty files.
                    i => h.entry(i).or_insert_with(Vec::new)
                          .push(
                           FileEntry{
                               inode : metadata.ino(),
                               dev   : metadata.dev(),
                               path  : String::from(path_str),
                           }),
                };
            } else if ft.is_dir() {
                collect_files(&(String::from(path_str)), h);
            }
        } else {
            warn!("Failed to retrieve metadata for {}", path.to_str().unwrap());
        }
    }
}

fn find_duplicates(duplicates: &mut HashMap<u64, Vec<FileEntry>>,
                   vec: &Vec<FileEntry>, thorough: bool ) {
    for file_entry in vec {
        if let Ok(mut file) = File::open(&file_entry.path) {
            let mut hash: u64 = 0;
            let mut hasher = DefaultHasher::new();
            if thorough {
                let mut contents: Vec<u8> = Vec::new();
                if let Ok(_) = file.read_to_end(&mut contents) {
                    hasher.write(&contents[..]);
                    hash = hasher.finish();
                } else {
                    warn!("Failed to read {}", file_entry.path);
                }
            } else {
                let mut buf: [u8; 1024] = [0; 1024];
                if let Ok(nbytes) = file.read(&mut buf) {
                    hasher.write(&buf[..nbytes as usize]);
                    hash = hasher.finish();
                } else {
                    warn!("Failed to read {} chunk", file_entry.path);
                }
            }
            if hash != 0 {
                duplicates.entry(hash).or_insert_with(Vec::new)
                    .push(
                        FileEntry{
                            inode : file_entry.inode,
                            dev   : file_entry.dev,
                            path  : file_entry.path.to_string(),
                        });
            }
        } else {
            warn!("Failed to open file {}", file_entry.path);
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args: Vec<String> = env::args().collect();

    // Print out usage if no directories are given.
    if args.len() == 1 || ( args.len() == 2 && args[1] == "-t" ) {
        println!("Usage: {} [-t] <dir1> [dir2 [dir3 ...]]", args[0]);
        ::std::process::exit(0);
    }

    let mut hmap: HashMap<u64, Vec<FileEntry> > = HashMap::new();

    let mut thorough = false;
    for dir in &args[1..] {
        if dir == "-t" {
            thorough = true;
            continue;
        }
        collect_files(dir, &mut hmap);
    }

    // Get rid of all the single entries.
    hmap.retain(|_, v| v.len() >= 2);

    let mut cluster = 1;

    for (key, val) in hmap.iter() {
        let mut duplicates: HashMap<u64, Vec<FileEntry> > = HashMap::new();
        find_duplicates(&mut duplicates, &val, thorough);

        for (hash, vec) in duplicates {
            if vec.len() >= 2 {
                println!("{} files in cluster {} (size: {}, digest: {})",
                         vec.len(), cluster, key, hash);
                // for_each becomes stable v1.22.0 onwards. Should uncomment then.
                //vec.iter().for_each(|f| println!("{}", f.path));
                for file_entry in vec {
                    println!("{}", file_entry.path);
                }
                cluster += 1;
            }
        }
    }
}
<commit_msg>Remove unnecessary struct<commit_after>use std::fs;
use std::env;
use std::fs::File;
use std::io::Read;
use std::hash::Hasher;
use std::path::PathBuf;
use std::collections::HashMap;
use std::os::unix::fs::MetadataExt;
use std::collections::hash_map::DefaultHasher;

#[macro_use]
extern crate log;
extern crate env_logger;

fn collect_files(dir: &String, h: &mut HashMap<u64, Vec<String>>) {

    let entries = match fs::read_dir(dir) {
        Ok(x) => x,
        _ => {
            warn!("{}: invalid directory", dir);
            return
        },
    };

    for path in  entries.filter( |x| x.is_ok() ).map( |x| x.unwrap().path() )
                .collect::<Vec<PathBuf>>() {
        if let (Some(path_str), Ok(metadata)) =
                (path.to_str(), path.symlink_metadata()) {
            let ft = metadata.file_type();
            if ft.is_symlink() {
                continue;
            } else if ft.is_file() {
                match metadata.len() {
                    0 => continue, //Ignore empty files.
                    i => h.entry(i).or_insert_with(Vec::new)
                          .push(String::from(path_str)),
                };
            } else if ft.is_dir() {
                collect_files(&(String::from(path_str)), h);
            }
        } else {
            warn!("Failed to retrieve metadata for {}", path.to_str().unwrap());
        }
    }
}

fn find_duplicates(duplicates: &mut HashMap<u64, Vec<String>>,
                   vec: &Vec<String>, thorough: bool ) {
    for file_entry in vec {
        if let Ok(mut file) = File::open(file_entry) {
            let mut hash: u64 = 0;
            let mut hasher = DefaultHasher::new();
            if thorough {
                let mut contents: Vec<u8> = Vec::new();
                if let Ok(_) = file.read_to_end(&mut contents) {
                    hasher.write(&contents[..]);
                    hash = hasher.finish();
                } else {
                    warn!("Failed to read {}", file_entry);
                }
            } else {
                let mut buf: [u8; 1024] = [0; 1024];
                if let Ok(nbytes) = file.read(&mut buf) {
                    hasher.write(&buf[..nbytes as usize]);
                    hash = hasher.finish();
                } else {
                    warn!("Failed to read {} chunk", file_entry);
                }
            }
            if hash != 0 {
                duplicates.entry(hash).or_insert_with(Vec::new)
                    .push(file_entry.to_string());
            }
        } else {
            warn!("Failed to open file {}", file_entry);
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args: Vec<String> = env::args().collect();

    // Print out usage if no directories are given.
    if args.len() == 1 || ( args.len() == 2 && args[1] == "-t" ) {
        println!("Usage: {} [-t] <dir1> [dir2 [dir3 ...]]", args[0]);
        ::std::process::exit(0);
    }

    let mut hmap: HashMap<u64, Vec<String> > = HashMap::new();

    let mut thorough = false;
    for dir in &args[1..] {
        if dir == "-t" {
            thorough = true;
            continue;
        }
        collect_files(dir, &mut hmap);
    }

    // Get rid of all the single entries.
    hmap.retain(|_, v| v.len() >= 2);

    let mut cluster = 1;

    for (key, val) in hmap.iter() {
        let mut duplicates: HashMap<u64, Vec<String> > = HashMap::new();
        find_duplicates(&mut duplicates, &val, thorough);

        for (hash, vec) in duplicates {
            if vec.len() >= 2 {
                println!("{} files in cluster {} (size: {}, digest: {})",
                         vec.len(), cluster, key, hash);
                // for_each becomes stable v1.22.0 onwards. Should uncomment then.
                //vec.iter().for_each(|f| println!("{}", f.path));
                for file_entry in vec {
                    println!("{}", file_entry);
                }
                cluster += 1;
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate glob;
#[macro_use] extern crate uuid;
#[macro_use] extern crate regex;
extern crate config;

use cli::CliConfig;
use configuration::Configuration;
use runtime::{ImagLogger, Runtime};
use clap::App;
use module::Module;
use module::ModuleError;
use module::CommandEnv;
use module::bm::BMModule;
use storage::backend::StorageBackend;

mod cli;
mod configuration;
mod runtime;
mod module;
mod storage;
mod ui;

fn main() {
    let yaml = load_yaml!("../etc/cli.yml");
    let app = App::from_yaml(yaml);
    let config = CliConfig::new(app);
    let configuration = Configuration::new(&config);

    let logger = ImagLogger::init(&configuration, &config);
    debug!("Logger created!");

    debug!("CliConfig    : {:?}", &config);
    debug!("Configuration: {:?}", &configuration);

    let rt = Runtime::new(configuration, config);

    debug!("Runtime      : {:?}", &rt);

    if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") {
        let module : BMModule = Module::new(&rt);
        let commands          = module.get_commands(&rt);
        if let Some(command)  = matches.subcommand_name() {
            debug!("Subcommand: {}", command);

            let backend = StorageBackend::new(rt.get_rtp());

            let cmdenv = CommandEnv {
                rt: &rt,
                bk: &backend,
                matches: matches,
            };

            let result = match commands.get(command) {
                Some(f) => f(cmdenv),
                None    => Err(ModuleError::new("No subcommand found")),
            };

            debug!("Result of command: {:?}", result);
        } else {
            debug!("No subcommand");
        }

        module.shutdown(&rt);
    } else {
        // Err(ModuleError::mk("No commandline call"))
        info!("No commandline call...")
    }

    info!("Hello, world!");
}
<commit_msg>We need to unwrap here (and it is save)<commit_after>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate glob;
#[macro_use] extern crate uuid;
#[macro_use] extern crate regex;
extern crate config;

use cli::CliConfig;
use configuration::Configuration;
use runtime::{ImagLogger, Runtime};
use clap::App;
use module::Module;
use module::ModuleError;
use module::CommandEnv;
use module::bm::BMModule;
use storage::backend::StorageBackend;

mod cli;
mod configuration;
mod runtime;
mod module;
mod storage;
mod ui;

fn main() {
    let yaml = load_yaml!("../etc/cli.yml");
    let app = App::from_yaml(yaml);
    let config = CliConfig::new(app);
    let configuration = Configuration::new(&config);

    let logger = ImagLogger::init(&configuration, &config);
    debug!("Logger created!");

    debug!("CliConfig    : {:?}", &config);
    debug!("Configuration: {:?}", &configuration);

    let rt = Runtime::new(configuration, config);

    debug!("Runtime      : {:?}", &rt);

    if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") {
        let module : BMModule = Module::new(&rt);
        let commands          = module.get_commands(&rt);
        if let Some(command)  = matches.subcommand_name() {
            debug!("Subcommand: {}", command);

            let backend = StorageBackend::new(rt.get_rtp());

            let cmdenv = CommandEnv {
                rt: &rt,
                bk: &backend,
                matches: matches.subcommand_matches(command).unwrap(),
            };

            let result = match commands.get(command) {
                Some(f) => f(cmdenv),
                None    => Err(ModuleError::new("No subcommand found")),
            };

            debug!("Result of command: {:?}", result);
        } else {
            debug!("No subcommand");
        }

        module.shutdown(&rt);
    } else {
        // Err(ModuleError::mk("No commandline call"))
        info!("No commandline call...")
    }

    info!("Hello, world!");
}
<|endoftext|>


<commit_before>extern crate ldap;

fn main()
{
    let mut ldap = ldap::LDAP::new();

    if !ldap.initialize("ldap://localhost:3890")
    {
        panic!("Init panicked!");
    }

    ldap.set_option();

    if !ldap.simple_bind("cn=admin,dc=ad,dc=ggnet", "DidRPwfLDAP!")
    {
        panic!("Bind panicked!");
    }

    ldap.destroy();
}
<commit_msg>Added new tests to reflect changes.<commit_after>extern crate ldap;

fn main()
{
    let mut ldap = ldap::LDAP::new();

    if !ldap.initialize("ldap://localhost:3890")
    {
        panic!("Init panicked!");
    }

    ldap.set_option();

    if !ldap.simple_bind("cn=admin,dc=ad,dc=ggnet", "DidRPwfLDAP!")
    {
        panic!("Bind panicked!");
    }

    let mut search_result = ldap.search("ou=Benutzer,dc=ad,dc=ggnet", 2, "(objectClass=*)", "*", 0).unwrap();
    println!("{}", search_result.first_entry(&mut ldap).unwrap().get_dn(&mut ldap));

    ldap.unbind();

}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(Debug)]
enum Expr {
    Numeral(i64),
    Plus(Box<Expr>, Box<Expr>),
    Minus(Box<Expr>, Box<Expr>),
    Times(Box<Expr>, Box<Expr>),
    Divide(Box<Expr>, Box<Expr>),
    Negate(Box<Expr>),
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Expr::Numeral(i) => write!(f, "{}", i),
            &Expr::Plus(ref i, ref j) => write!(f, "{} + {}", i, j),
            &Expr::Minus(ref i, ref j) => write!(f, "{} - {}", i, j),
            &Expr::Times(ref i, ref j) => write!(f, "{} * {}", i, j),
            &Expr::Divide(ref i, ref j) => write!(f, "{} / {}", i, j),
            &Expr::Negate(ref i) => write!(f, "-{}", i),
        }
    }
}

fn main() {
    let n1: Expr = Expr::Numeral(5);
    let p: Expr = Expr::Plus(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let m: Expr = Expr::Minus(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let t: Expr = Expr::Times(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let d: Expr = Expr::Divide(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let n: Expr = Expr::Negate(Box::new(Expr::Numeral(5)));
    println!("{}", n1);
    println!("{}", p);
    println!("{}", m);
    println!("{}", t);
    println!("{}", d);
    println!("{}", n);
}
<commit_msg>implement eval() for Expr<commit_after>use std::fmt;

#[derive(Debug)]
enum Expr {
    Numeral(i64),
    Plus(Box<Expr>, Box<Expr>),
    Minus(Box<Expr>, Box<Expr>),
    Times(Box<Expr>, Box<Expr>),
    Divide(Box<Expr>, Box<Expr>),
    Negate(Box<Expr>),
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Expr::Numeral(i) => write!(f, "{}", i),
            &Expr::Plus(ref i, ref j) => write!(f, "{} + {}", i, j),
            &Expr::Minus(ref i, ref j) => write!(f, "{} - {}", i, j),
            &Expr::Times(ref i, ref j) => write!(f, "{} * {}", i, j),
            &Expr::Divide(ref i, ref j) => write!(f, "{} / {}", i, j),
            &Expr::Negate(ref i) => write!(f, "-{}", i),
        }
    }
}

fn eval(expr: Expr) -> i64 {
    match expr {
        Expr::Numeral(i) => i,
        Expr::Plus(i, j) => eval(*i) + eval(*j),
        Expr::Minus(i, j) => eval(*i) - eval(*j),
        Expr::Times(i, j) => eval(*i) * eval(*j),
        Expr::Divide(i, j) => eval(*i) / eval(*j),
        Expr::Negate(i) => eval(*i) * -1,
    }
}

fn main() {
    let n1: Expr = Expr::Numeral(5);
    let p: Expr = Expr::Plus(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let m: Expr = Expr::Minus(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let t: Expr = Expr::Times(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let d: Expr = Expr::Divide(Box::new(Expr::Numeral(5)), Box::new(Expr::Numeral(7)));
    let n: Expr = Expr::Negate(Box::new(Expr::Numeral(5)));
    println!("{}", n1);
    println!("{}", p);
    println!("{}", m);
    println!("{}", t);
    println!("{}", d);
    println!("{}", n);

    println!("{}", eval(p));
}
<|endoftext|>


<commit_before>const NUM_DIRECTIONS: usize = 4;
const NUM_ROOMS: usize = 2;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway,
  AudienceChamber,
}

#[derive(Debug)]
struct Map<'a> {
  rooms: [Room<'a>; NUM_ROOMS]
}

impl<'a> Map<'a> {
  pub fn new() -> Self {
    Self { rooms: [Room::new(); NUM_ROOMS] }
  }

  pub fn connect(&mut self, from: RoomId, d: Direction, to: RoomId) {
    self.rooms[from as usize].set_exit(d, to);
    self.rooms[to as usize].set_exit(d.opposite(), from);
  }
}

#[derive(Debug, Copy, Clone)]
enum Direction {
  North,
  South,
  East,
  West,
}

impl Direction {
  pub fn opposite(self) -> Self {
    match self {
      Direction::North => Direction::South,
      Direction::South => Direction::North,
      Direction::East => Direction::West,
      Direction::West => Direction::East,
    }
  }
}

#[derive(Debug, Copy, Clone)]
struct Room<'a> {
  exits: [Option<RoomId>; NUM_DIRECTIONS],
  name: &'a str,
  description: &'a str,
}

impl<'a> Room<'a> {
  pub fn new() -> Self {
    Self {
      exits: [None; NUM_DIRECTIONS],
      name: "",
      description: "",
    }
  }

  pub fn get_exit(self, d: Direction) -> Option<RoomId> {
    self.exits[d as usize]
  }

  pub fn set_exit(&mut self, d: Direction, r: RoomId) -> &mut Self {
    self.exits[d as usize] = Some(r);
    self
  }
}

fn main() {
  let mut map = Map::new();

  map.connect(RoomId::Hallway, Direction::South, RoomId::AudienceChamber);

  println!("Map is {:?}", map);
}
<commit_msg>Add Map::room().<commit_after>const NUM_DIRECTIONS: usize = 4;
const NUM_ROOMS: usize = 2;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway,
  AudienceChamber,
}

#[derive(Debug)]
struct Map<'a> {
  rooms: [Room<'a>; NUM_ROOMS]
}

impl<'a> Map<'a> {
  pub fn new() -> Self {
    Self { rooms: [Room::new(); NUM_ROOMS] }
  }

  pub fn room(&mut self, id: RoomId) -> &mut Room<'a> {
    &mut self.rooms[id as usize]
  }

  pub fn connect(&mut self, from: RoomId, d: Direction, to: RoomId) {
    self.room(from).set_exit(d, to);
    self.room(to).set_exit(d.opposite(), from);
  }
}

#[derive(Debug, Copy, Clone)]
enum Direction {
  North,
  South,
  East,
  West,
}

impl Direction {
  pub fn opposite(self) -> Self {
    match self {
      Direction::North => Direction::South,
      Direction::South => Direction::North,
      Direction::East => Direction::West,
      Direction::West => Direction::East,
    }
  }
}

#[derive(Debug, Copy, Clone)]
struct Room<'a> {
  exits: [Option<RoomId>; NUM_DIRECTIONS],
  name: &'a str,
  description: &'a str,
}

impl<'a> Room<'a> {
  pub fn new() -> Self {
    Self {
      exits: [None; NUM_DIRECTIONS],
      name: "",
      description: "",
    }
  }

  pub fn get_exit(self, d: Direction) -> Option<RoomId> {
    self.exits[d as usize]
  }

  pub fn set_exit(&mut self, d: Direction, r: RoomId) -> &mut Self {
    self.exits[d as usize] = Some(r);
    self
  }
}

fn main() {
  let mut map = Map::new();

  map.connect(RoomId::Hallway, Direction::South, RoomId::AudienceChamber);

  println!("Map is {:?}", map);
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate regex;
extern crate term;
mod retest;

use getopts::Options;
use std::env;
use std::io;
use std::io::Read;

/// Prints the program usage to the console.
fn print_usage(options: Options) {
    let brief = "Usage: retest REGEX [options]

    Tests REGEX by matching it to the text given in stdin.";

    print!("{}", options.usage(brief));
}

/// Parses command-line options and runs retest.
fn main() {
    let args: Vec<String> = env::args().collect();

    let mut options = Options::new();
    options.optflag("h", "help", "Print this help menu");
    options.optopt("s", "subject", "Specify a subject to match against", "TEXT");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    // If the help flag is present or the user forgot to specify a pattern, show
    // the usage message.
    if matches.opt_present("h") || matches.free.is_empty() {
        print_usage(options);
        return;
    }

    // Get the regular expression pattern from the argument list.
    let pattern = matches.free[0].clone();

    // Get the subject to test on. If the -s option is present, get the subject
    // from the argument list, otherwise get the subject from stdin.
    // Get the input text from stdin.
    let mut subject: String;

    if matches.opt_present("s") {
        subject = matches.opt_str("s").unwrap();
    } else {
        subject = String::new();
        let mut stdin = io::stdin();
        stdin.read_to_string(&mut subject).unwrap();
    }
    let subject = subject;

    // Print out the highlighted subject.
    retest::print_matches(&pattern, &subject);
}
<commit_msg>Add regex modifier flags<commit_after>extern crate getopts;
extern crate regex;
extern crate term;
mod retest;

use getopts::Options;
use std::env;
use std::io;
use std::io::Read;

/// Prints the program usage to the console.
fn print_usage(options: Options) {
    let brief = "Usage: retest REGEX [options]

    Tests REGEX by matching it to the text given in stdin.";

    print!("{}", options.usage(brief));
}

/// Parses command-line options and runs retest.
fn main() {
    let args: Vec<String> = env::args().collect();

    let mut options = Options::new();
    options.optflag("h", "help", "Print this help menu");
    options.optopt("s", "subject", "Specify a subject to match against", "TEXT");
    options.optflag("i", "insensitive", "Case-insensitive matching");
    options.optflag("m", "multiline", "Enable multi-line mode: ^ and $ match begin/end of line");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    // If the help flag is present or the user forgot to specify a pattern, show
    // the usage message.
    if matches.opt_present("h") || matches.free.is_empty() {
        print_usage(options);
        return;
    }

    // Get the regular expression pattern from the argument list and add modifiers
    // if given.
    let mut pattern = matches.free[0].clone();
    if matches.opt_present("i") {
        pattern = "(?i)".to_string() + &pattern;
    }
    if matches.opt_present("m") {
        pattern = "(?m)".to_string() + &pattern;
    }

    // Get the subject to test on. If the -s option is present, get the subject
    // from the argument list, otherwise get the subject from stdin.
    // Get the input text from stdin.
    let mut subject: String;

    if matches.opt_present("s") {
        subject = matches.opt_str("s").unwrap();
    } else {
        subject = String::new();
        let mut stdin = io::stdin();
        stdin.read_to_string(&mut subject).unwrap();
    }
    let subject = subject;

    // Print out the highlighted subject.
    retest::print_matches(&pattern, &subject);
}
<|endoftext|>


<commit_before>//! Command line executable.
extern crate pico;
extern crate clap;
extern crate hex;

use std::str::FromStr;
use std::path::Path;
use std::io::stdout;
use pico::{HeaderFormat, major, minor};
use clap::{Arg, App};
use pico::file;
use hex::FromHex;

/// Executable description.
static DESCRIPTION: &str =
"Encode a file as Pico, decode a Pico-encoded file, or dump the header \
from a Pico-encoded file.";

static LONG_DESCRIPTION: &str =
"Input files are encoded by default.  If encoding, a .pico extension \
is added to the file.  If decoding, then the input must be Pico-encoded \
files, and a .raw extension is added by default.  If dumping the header, \
the input files must be Pico-encoded files, and the header is sent to \
standard output in the specified format.

The extension used can be overridden by --extension, which should include \
the dot.  Any provided suffix (by default there is none) is added to the \
file's base name.

The header kinds can be JSON, YAML, DICT (Python), or XML.

Keys must be specified as a list of hexadecimal digits (no spaces).  If \
no key is specified for encoding, a random key is generated.";

/// Entry point when run from the command line.
fn main() {
    // Add some information to the end of the help.
    let after = format!(
        "{}\n\nPico Encoding Version: {}.{}\nSee: {}",
        LONG_DESCRIPTION, major(), minor(), env!("CARGO_PKG_HOMEPAGE")
    );

    // Parse command line arguments.
    let app_matches = App::new("Pico Rust Library")
        .version(env!("CARGO_PKG_VERSION"))
        .author("The Mons Pico Project")
        .about(DESCRIPTION)
        .after_help(after.as_str())
        .arg(Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .help("Increase verbosity.")
            .takes_value(false))
        .arg(Arg::with_name("debug")
            .long("debug")
            .help("Enable debugging.")
            .takes_value(false))
        .arg(Arg::with_name("decode")
            .conflicts_with("encode")
            .conflicts_with("header")
            .short("d")
            .long("decode")
            .help("Decode files.")
            .takes_value(false))
        .arg(Arg::with_name("encode")
            .conflicts_with("decode")
            .conflicts_with("header")
            .short("e")
            .long("encode")
            .help("Encode files.")
            .takes_value(false))
        .arg(Arg::with_name("extension")
            .long("extension")
            .help("Set output file extension.")
            .takes_value(true))
        .arg(Arg::with_name("header")
            .conflicts_with("encode")
            .conflicts_with("decode")
            .possible_values(&["DICT", "JSON", "YAML", "XML"])
            .short("H")
            .long("header")
            .value_name("format")
            .help("Dump header information.")
            .takes_value(true))
        .arg(Arg::with_name("suffix")
            .short("s")
            .long("suffix")
            .default_value("")
            .help("Suffix to add to output files.")
            .takes_value(true))
        .arg(Arg::with_name("key")
            .short("k")
            .long("key")
            .help("Specify key for encoding.")
            .takes_value(true))
        .arg(Arg::with_name("files")
            .help("File names to process.")
            .multiple(true)
            .required(true)
            .takes_value(true))
        .get_matches();

    // Figure out correct operation.
    let filelist = app_matches.values_of("files").unwrap();
    enum Operation {
        Header, Encode, Decode,
    };
    let mut op = Operation::Encode;
    if app_matches.is_present("header") { op = Operation::Header; }
    if app_matches.is_present("decode") { op = Operation::Decode; }
    let header_format = match app_matches.value_of("header") {
        None => HeaderFormat::DICT,
        Some(name) => HeaderFormat::from_str(name).unwrap(),
    };
    let extension = match app_matches.value_of("extension") {
        None => {
            match op {
                Operation::Decode => ".raw",
                _ => ".pico",
            }
        },
        Some(ext) => ext,
    };
    let suffix = app_matches.value_of("suffix").unwrap();

    // Perform the operation for each specified file.
    for file in filelist {
        let filepath = Path::new(&file);
        let basename = filepath.file_stem().unwrap().to_string_lossy().into_owned();
        let oldname: String = filepath.to_string_lossy().into_owned();
        match op {
            Operation::Header => {
                println!("Pico Header as {:?} for: {:?}", header_format, filepath);
                file::dump_header(&oldname, stdout(), &header_format);
            },
            Operation::Encode => {
                // See if the user specified a key; if not, generate one.
                let key = if app_matches.is_present("key") {
                    let hex = app_matches.value_of("key").unwrap();
                    let hex = hex.to_uppercase().into_bytes();
                    let hexlen = hex.len();
                    if hexlen % 2 != 0 {
                        eprintln!("ERROR: Key must be an even number of hex digits.");
                        return;
                    }
                    if hexlen == 0 {
                        eprintln!("ERROR: Key cannot be empty.");
                        return;
                    }
                    match Vec::<u8>::from_hex(hex) {
                        Ok(value) => value,
                        Err(err) => {
                            eprintln!("ERROR: {}", err);
                            return;
                        }
                    }
                } else {
                    pico::gen_random_key(16)
                };
                let newname = basename + suffix + extension;
                println!("Encoding {:?} -> {:?}", oldname, newname);
                file::encode(&oldname, &newname, key, vec![], 0);
            },
            Operation::Decode => {
                let newname = basename + suffix + extension;
                println!("Decoding {:?} -> {:?}", oldname, newname);
                file::decode(&oldname, &newname);
            },
        }
    }
}
<commit_msg>General improvements in error handling and documentation of unwraps.<commit_after>//! Command line executable.
extern crate pico;
extern crate clap;
extern crate hex;

use std::str::FromStr;
use std::path::Path;
use std::io::stdout;
use pico::{HeaderFormat, major, minor};
use clap::{Arg, App};
use pico::file;
use hex::FromHex;

/// Executable description.
static DESCRIPTION: &str =
"Encode a file as Pico, decode a Pico-encoded file, or dump the header \
from a Pico-encoded file.";

static LONG_DESCRIPTION: &str =
"Input files are encoded by default.  If encoding, a .pico extension \
is added to the file.  If decoding, then the input must be Pico-encoded \
files, and a .raw extension is added by default.  If dumping the header, \
the input files must be Pico-encoded files, and the header is sent to \
standard output in the specified format.

The extension used can be overridden by --extension, which should include \
the dot.  Any provided suffix (by default there is none) is added to the \
file's base name.

The header kinds can be JSON, YAML, DICT (Python), or XML.

Keys must be specified as a list of hexadecimal digits (no spaces).  If \
no key is specified for encoding, a random key is generated.";

/// Entry point when run from the command line.
fn main() {
    // Add some information to the end of the help.
    let after = format!(
        "{}\n\nPico Encoding Version: {}.{}\nSee: {}",
        LONG_DESCRIPTION, major(), minor(), env!("CARGO_PKG_HOMEPAGE")
    );

    // Parse command line arguments.
    let app_matches = App::new("Pico Rust Library")
        .version(env!("CARGO_PKG_VERSION"))
        .author("The Mons Pico Project")
        .about(DESCRIPTION)
        .after_help(after.as_str())
        .arg(Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .help("Increase verbosity.")
            .takes_value(false))
        .arg(Arg::with_name("debug")
            .long("debug")
            .help("Enable debugging.")
            .takes_value(false))
        .arg(Arg::with_name("decode")
            .conflicts_with("encode")
            .conflicts_with("header")
            .short("d")
            .long("decode")
            .help("Decode files.")
            .takes_value(false))
        .arg(Arg::with_name("encode")
            .conflicts_with("decode")
            .conflicts_with("header")
            .short("e")
            .long("encode")
            .help("Encode files.")
            .takes_value(false))
        .arg(Arg::with_name("extension")
            .long("extension")
            .help("Set output file extension.")
            .takes_value(true))
        .arg(Arg::with_name("header")
            .conflicts_with("encode")
            .conflicts_with("decode")
            .possible_values(&["DICT", "JSON", "YAML", "XML"])
            .short("H")
            .long("header")
            .value_name("format")
            .help("Dump header information.")
            .takes_value(true))
        .arg(Arg::with_name("suffix")
            .short("s")
            .long("suffix")
            .default_value("")
            .help("Suffix to add to output files.")
            .takes_value(true))
        .arg(Arg::with_name("key")
            .short("k")
            .long("key")
            .help("Specify key for encoding.")
            .takes_value(true))
        .arg(Arg::with_name("files")
            .help("File names to process.")
            .multiple(true)
            .required(true)
            .takes_value(true))
        .get_matches();

    // Figure out correct operation.  This unwrap should not fail since
    // the files are required.
    let filelist = app_matches.values_of("files").unwrap();
    enum Operation {
        Header, Encode, Decode,
    };
    let mut op = Operation::Encode;
    if app_matches.is_present("header") { op = Operation::Header; }
    if app_matches.is_present("decode") { op = Operation::Decode; }
    let header_format = match app_matches.value_of("header") {
        None => HeaderFormat::DICT,
        // This unwrap should not fail, since the format names are checked
        // when parsing the command line.
        Some(name) => HeaderFormat::from_str(name).unwrap(),
    };
    let extension = match app_matches.value_of("extension") {
        None => {
            match op {
                Operation::Decode => ".raw",
                _ => ".pico",
            }
        },
        Some(ext) => ext,
    };
    // This unwrap should never fail since suffix has a default value.
    let suffix = app_matches.value_of("suffix").unwrap();

    // Perform the operation for each specified file.
    for file in filelist {
        // Check the file.
        let filepath = Path::new(&file);
        if filepath.is_dir() {
            eprintln!("ERROR: Argument {:?} is a folder.", file);
            return;
        }
        if !filepath.exists() {
            eprintln!("ERROR: Argument {:?} is not found.", file);
            return;
        }
        let basename = match filepath.file_stem() {
            None => {
                eprintln!("ERROR: Argument {:?} is not a file.", file);
                return;
            },
            Some(value) => value,
        }.to_string_lossy().into_owned();
        let oldname: String = filepath.to_string_lossy().into_owned();

        // Perform the correct operation.
        match op {
            Operation::Header => {
                println!("Pico Header as {:?} for: {:?}", header_format, filepath);
                file::dump_header(&oldname, stdout(), &header_format);
            },

            Operation::Encode => {
                // See if the user specified a key; if not, generate one.
                let key = match app_matches.value_of("key") {
                    None => pico::gen_random_key(16),
                    Some(hex) => {
                        let hex = hex.to_uppercase().into_bytes();
                        let hexlen = hex.len();
                        if hexlen % 2 != 0 {
                            // I think this is more helpful than the default given
                            // by the hex package.
                            eprintln!("ERROR: Key must be an even number of hex digits.");
                            return;
                        }
                        if hexlen == 0 {
                            // The hex package permits an empth string, so we have
                            // to trap this here.
                            eprintln!("ERROR: Key cannot be empty.");
                            return;
                        }
                        match Vec::<u8>::from_hex(hex) {
                            Ok(value) => value,
                            Err(err) => {
                                eprintln!("ERROR: {}", err);
                                return;
                            }
                        }
                    }
                };
                let newname = basename + suffix + extension;
                println!("Encoding {:?} -> {:?}", oldname, newname);
                file::encode(&oldname, &newname, key, vec![], 0);
            },

            Operation::Decode => {
                let newname = basename + suffix + extension;
                println!("Decoding {:?} -> {:?}", oldname, newname);
                file::decode(&oldname, &newname);
            },
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};

use rand::{random, Closed01, Rng};
use rand::distributions::{IndependentSample, Range, Sample};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let Closed01(x) = random::<Closed01<f64>>();

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
            }
        }
        ret
    }
}

fn lda(num_topics: usize, dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, num_samples: usize) {
    // Initialization
    let mut rng = rand::thread_rng();
    let topics = Range::new(0, num_topics);

    let vocab_size: usize = {
        let mut have_some = false;
        let mut max_index = 0;
        for bag in &dataset {
            for &index in bag.keys() {
                have_some = true;
                if index > max_index {
                    max_index = index;
                }
            }
        }
        if have_some {
            max_index + 1
        }
        else {
            0
        }
    };
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    for s in 0..num_samples {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                z[d][i] = cat.ind_sample(&mut rand::thread_rng());
            }
        }
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    lda(3, dataset, vec![1.0, 1.0, 1.0], vec![1.0, 1.0, 1.0], 100);
}
<commit_msg>Add Dirichlet distribution<commit_after>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};

use rand::{random, Closed01, Rng};
use rand::distributions::{IndependentSample, Range, Sample, Gamma};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let Closed01(x) = random::<Closed01<f64>>();

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
            }
        }
        ret
    }
}

#[derive(Clone)]
struct Dirichlet {
    alpha: Vec<f64>,
}

impl Dirichlet {
    fn new(alpha: Vec<f64>) -> Dirichlet {
        Dirichlet {
            alpha: alpha,
        }
    }
}

impl Sample<Vec<f64>> for Dirichlet {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Vec<f64> {
        self.ind_sample(rng)
    }
}

impl IndependentSample<Vec<f64>> for Dirichlet {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Vec<f64> {
        let mut sum = 0.0;
        let mut xs = Vec::new();
        for &a in &self.alpha {
            let gamma = Gamma::new(a, 1.0);
            let y = gamma.ind_sample(rng);
            xs.push(y);
            sum += y;
        }
        for x in xs.iter_mut() {
            *x /= sum;
        }
        xs
    }
}

fn lda(num_topics: usize, dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, num_samples: usize) {
    // Initialization
    let mut rng = rand::thread_rng();
    let topics = Range::new(0, num_topics);

    let vocab_size: usize = {
        let mut have_some = false;
        let mut max_index = 0;
        for bag in &dataset {
            for &index in bag.keys() {
                have_some = true;
                if index > max_index {
                    max_index = index;
                }
            }
        }
        if have_some {
            max_index + 1
        }
        else {
            0
        }
    };
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    for s in 0..num_samples {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                z[d][i] = cat.ind_sample(&mut rand::thread_rng());
            }
        }
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    lda(3, dataset, vec![1.0, 1.0, 1.0], vec![1.0, 1.0, 1.0], 100);
}
<|endoftext|>