<commit_before>mod base;

#[macro_use]
extern crate chan;
extern crate chan_signal;
extern crate unix_daemonize;
extern crate getopts;
extern crate syslog;
extern crate ini;

use ini::Ini;
use base::{Daemon, DebugPrint, Ls, FakeSpinner, Worker};
use getopts::Options;
use std::env;
use std::sync::mpsc::{self};
use std::process::{exit};
use std::sync::{Arc, Mutex};
use std::thread::{spawn};
use chan::{Receiver};
use chan_signal::{Signal, notify};
use unix_daemonize::{daemonize_redirect, ChdirMode};
use syslog::{Facility, Severity};
use std::sync::mpsc::{Sender};

static SIGNALING_ERROR_EXIT_CODE: i32 = 0x1;
static CPU_ANTI_HOG_MILLIS_OFFSET: u64 = 100;
static STD_OUT_ERR_REDIR: &'static str = "/dev/null";

#[derive(Debug, PartialEq, Clone)]
pub enum LogDest {
    StdOut,
    Syslog,
}

#[derive(Debug, Clone)]
pub struct Logger {
    dest: LogDest
}

impl Logger {
    pub fn new(dest: LogDest) -> Logger {
        Logger { dest: dest }
    }

    fn log(&self, msg: &str) -> () {
        match self.dest {
            LogDest::StdOut => {
                println!("LOGGER STDOUT {}", msg);
            },
            LogDest::Syslog => {
                println!("LOGGER SYSLOG {}", msg);

                match syslog::unix(Facility::LOG_DAEMON) {
                    Err(e) => println!("[!] impossible to connect to syslog: {:?}", e),
                    Ok(writer) => {
                        let r = writer.send(Severity::LOG_INFO, msg);
                        if r.is_err() {
                            println!("[!] error sending the log {}", r.err().expect("got error"));
                        }
                    }
                }
            }
        }
    }
}

//fn initiator() {
//    loop {
//        let w = Worker::new();
//        w.start();
//        let signal = signal_chan_rx.recv();
//    }
//}

fn sig_handler(
    signal_chan_rx: Receiver<Signal>,
    matches: &getopts::Matches,
    finish_chan_tx: Sender<()>,
    logger: Logger
) {
    loop {
        let w = Worker::new();
        w.start();
        let signal = signal_chan_rx.recv();
        match signal {
            Some(Signal::INT) => {
                let msg = format!("Handling {:?}", Signal::INT);
                logger.log(&msg);
                logger.log(&msg);
                finish_chan_tx.send(());
            },
            Some(Signal::HUP) => {
                load_config(&matches);
                let msg = format!("HUP reload status {:?}", "OK");
                logger.log(&msg);
            },
            Some(_) => {
                ();
            },
            None => {
                exit(SIGNALING_ERROR_EXIT_CODE);
            }
        }
    }
}

fn demonize() {
    daemonize_redirect(
        Some(STD_OUT_ERR_REDIR),
        Some(STD_OUT_ERR_REDIR),
        ChdirMode::ChdirRoot).unwrap(); //TODO handle unwrap
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn load_config(matches: &getopts::Matches) {
    let config_file = matches.opt_str("c").unwrap();
    let i = Ini::load_from_file(&config_file).unwrap();

    println!("configuration");
    let general_section_name = "__General__".into();
    for (sec, prop) in i.iter() {
        let section_name = sec.as_ref().unwrap_or(&general_section_name);
        println!("-- Section: {:?} begins", section_name);
        for (k, v) in prop.iter() {
            println!("{}: {:?}", *k, *v);
        }
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.reqopt("c", "", "ini configuration file path", "[FILE]");
    opts.optflag("d", "demonize", "demonize in old unix fashion");
    opts.optflag("h", "help", "print this message");
    match opts.parse(&args[1..]) {
        Ok(matches) => {
            if matches.opt_present("h") {
                print_usage(&program, opts);
                return;
            }
            let mut ini_logger = Logger::new(LogDest::StdOut);
            if matches.opt_present("d") {
                demonize();
            }
            let logger = ini_logger;

            let msg = format!("daemon start status {:?}", 123);
            logger.log(&msg);
            load_config(&matches);
            let signal = notify(&[Signal::INT, Signal::HUP, Signal::TERM]);

            let (end_signal_tx, end_signal_rx) = mpsc::channel();
            let handler_thread_logger = logger.clone();
            spawn(move || {
                sig_handler(
                    signal,
                    &matches,
                    end_signal_tx,
                    handler_thread_logger);
            });

            let finish_result = end_signal_rx.recv();
            let msg = format!("finishing in {:?} status", finish_result.unwrap());
            logger.log(&msg);
        }
        Err(f) => {
            print_usage(&program, opts);
            panic!(f.to_string())
            //            exit(0);
        }
    };
}

<commit_msg>initiator thread<commit_after>mod base;

#[macro_use]
extern crate chan;
extern crate chan_signal;
extern crate unix_daemonize;
extern crate getopts;
extern crate syslog;
extern crate ini;

use ini::Ini;
use base::{Worker};
use getopts::Options;
use std::env;
use std::sync::mpsc::{self};
use std::process::{exit};
use std::thread::{spawn};
use chan::{Receiver};
use chan_signal::{Signal, notify};
use unix_daemonize::{daemonize_redirect, ChdirMode};
use syslog::{Facility, Severity};
use std::sync::mpsc::{Sender};

static SIGNALING_ERROR_EXIT_CODE: i32 = 0x1;
static STD_OUT_ERR_REDIR: &'static str = "/dev/null";

#[derive(Debug, PartialEq, Clone)]
pub enum LogDest {
    StdOut,
    Syslog,
}

#[derive(Debug, Clone)]
pub struct Logger {
    dest: LogDest
}

impl Logger {
    pub fn new(dest: LogDest) -> Logger {
        Logger { dest: dest }
    }

    fn log(&self, msg: &str) -> () {
        match self.dest {
            LogDest::StdOut => {
                println!("LOGGER STDOUT {}", msg);
            },
            LogDest::Syslog => {
                println!("LOGGER SYSLOG {}", msg);

                match syslog::unix(Facility::LOG_DAEMON) {
                    Err(e) => println!("[!] impossible to connect to syslog: {:?}", e),
                    Ok(writer) => {
                        let r = writer.send(Severity::LOG_INFO, msg);
                        if r.is_err() {
                            println!("[!] error sending the log {}", r.err().expect("got error"));
                        }
                    }
                }
            }
        }
    }
}

fn load_config(matches: &getopts::Matches) {
    let config_file = matches.opt_str("c").unwrap();
    let i = Ini::load_from_file(&config_file).unwrap();

    println!("configuration");
    let general_section_name = "__General__".into();
    for (sec, prop) in i.iter() {
        let section_name = sec.as_ref().unwrap_or(&general_section_name);
        println!("-- Section: {:?} begins", section_name);
        for (k, v) in prop.iter() {
            println!("{}: {:?}", *k, *v);
        }
    }
}

fn initiator(
    reload_trigger_rx: std::sync::mpsc::Receiver<()>,
    logger: Logger
) {
    loop {
        //        load_config(path);
        let w = Worker::new();
        w.start();
        let reload = reload_trigger_rx.recv();
        let msg = format!("Worker reload {:?}", reload);
        logger.log(&msg);

    }
}

fn signal_handler(
    signal_channel_rx: Receiver<Signal>,
    reload_trigger_tx: Sender<()>,
    finish_channel_tx: Sender<()>,
    logger: Logger
) {
    loop {
        let signal = signal_channel_rx.recv();
        match signal {
            Some(Signal::INT) => {
                let msg = format!("Handling {:?}", Signal::INT);
                logger.log(&msg);
                let finish = finish_channel_tx.send(());
                let msg = format!("INT finish status {:?}", finish);
                logger.log(&msg);

            },
            Some(Signal::HUP) => {
                let msg = format!("Handling {:?}", Signal::HUP);
                logger.log(&msg);
                let reload = reload_trigger_tx.send(());
                let msg = format!("HUP reload status {:?}", reload);
                logger.log(&msg);
            },
            Some(_) => {
                ();
            },
            None => {
                exit(SIGNALING_ERROR_EXIT_CODE);
            }
        }
    }
}

fn demonize() {
    daemonize_redirect(
        Some(STD_OUT_ERR_REDIR),
        Some(STD_OUT_ERR_REDIR),
        ChdirMode::ChdirRoot).unwrap(); //TODO handle unwrap
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.reqopt("c", "", "ini configuration file path", "[FILE]");
    opts.optflag("d", "demonize", "demonize in old unix fashion");
    opts.optflag("h", "help", "print this message");

    match opts.parse(&args[1..]) {
        Ok(matches) => {
            if matches.opt_present("h") {
                print_usage(&program, opts);
                return;
            }
            let mut ini_logger = Logger::new(LogDest::StdOut);
            if matches.opt_present("d") {
                demonize();
                ini_logger = Logger::new(LogDest::Syslog);
            }
            let logger = ini_logger;
            let signal_handler_logger = logger.clone();
            let initiator_logger = logger.clone();

            let signal_channel_rx = notify(&[Signal::INT, Signal::HUP, Signal::TERM]);
            let (finish_channel_tx, finish_channel_rx) = mpsc::channel();
            let (reload_trigger_tx, reload_trigger_rx) = mpsc::channel();

            spawn(move || {
                initiator(reload_trigger_rx, initiator_logger);
            });

            spawn(move || {
                signal_handler(
                    signal_channel_rx,
                    reload_trigger_tx,
                    finish_channel_tx,
                    signal_handler_logger);
            });

            let finish_result = finish_channel_rx.recv();
            let msg = format!("shutdown {:?} status", finish_result.unwrap());
            logger.log(&msg);
        }
        Err(_) => {
            print_usage(&program, opts);
            return;
        }
    };
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

mod lib;

use clap::{App, Arg};
use lib::Petnames;

fn main() {
    let matches = App::new("rust-petname")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generate human readable random names.")
        .after_help(concat!(
            "Based on Dustin Kirkland's petname project ",
            "<https://github.com/dustinkirkland/petname>."
        ))
        .arg(
            Arg::with_name("words")
                .short("w")
                .long("words")
                .value_name("WORDS")
                .default_value("2")
                .help("Number of words in name")
                .takes_value(true)
                .validator(is_u8),
        )
        .arg(
            Arg::with_name("separator")
                .short("s")
                .long("separator")
                .value_name("SEP")
                .default_value("-")
                .help("Separator between words")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("complexity")
                .short("c")
                .long("complexity")
                .value_name("COMPLEXITY")
                .possible_values(&["0", "1", "2"])
                .hide_possible_values(true)
                .default_value("0")
                .help("Use small words (0), medium words (1), or large words (2)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("count")
                .long("count")
                .value_name("COUNT")
                .default_value("1")
                .help("Generate multiple names. Set to 0 to produce infinite names!")
                .takes_value(true)
                .validator(is_u64),
        )
        .get_matches();

    // Unwrapping is safe because these options have defaults.
    let opt_separator = matches.value_of("separator").unwrap();
    let opt_words = matches.value_of("words").unwrap();
    let opt_complexity = matches.value_of("complexity").unwrap();
    let opt_count = matches.value_of("count").unwrap();

    // Parse words and count into numbers. Validated so unwrapping is okay.
    let opt_words: u8 = opt_words.parse().unwrap();
    let opt_count: u64 = opt_count.parse().unwrap();

    // Select the appropriate word list.
    let petnames = match opt_complexity {
        "0" => Petnames::small(),
        "1" => Petnames::medium(),
        "2" => Petnames::large(),
        _ => Petnames::small(),
    };

    // We're going to need a source of randomness.
    let mut rng = rand::thread_rng();

    // Stream if count is 0.
    if opt_count == 0 {
        loop {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    } else {
        for _ in 1..=opt_count {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    }
}

fn is_u8(value: String) -> Result<(), String> {
    match value.parse::<u8>() {
        Err(e) => Err(format!("{}", e)),
        Ok(_) => Ok(()),
    }
}

fn is_u64(value: String) -> Result<(), String> {
    match value.parse::<u64>() {
        Err(e) => Err(format!("{}", e)),
        Ok(_) => Ok(()),
    }
}
<commit_msg>Type magic to make is_u8 and is_u64 into a single function!<commit_after>#[macro_use]
extern crate clap;

mod lib;

use clap::{App, Arg};
use lib::Petnames;
use std::str::FromStr;

fn main() {
    let matches = App::new("rust-petname")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generate human readable random names.")
        .after_help(concat!(
            "Based on Dustin Kirkland's petname project ",
            "<https://github.com/dustinkirkland/petname>."
        ))
        .arg(
            Arg::with_name("words")
                .short("w")
                .long("words")
                .value_name("WORDS")
                .default_value("2")
                .help("Number of words in name")
                .takes_value(true)
                .validator(can_be_parsed::<u8>),
        )
        .arg(
            Arg::with_name("separator")
                .short("s")
                .long("separator")
                .value_name("SEP")
                .default_value("-")
                .help("Separator between words")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("complexity")
                .short("c")
                .long("complexity")
                .value_name("COMPLEXITY")
                .possible_values(&["0", "1", "2"])
                .hide_possible_values(true)
                .default_value("0")
                .help("Use small words (0), medium words (1), or large words (2)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("count")
                .long("count")
                .value_name("COUNT")
                .default_value("1")
                .help("Generate multiple names. Set to 0 to produce infinite names!")
                .takes_value(true)
                .validator(can_be_parsed::<u64>),
        )
        .get_matches();

    // Unwrapping is safe because these options have defaults.
    let opt_separator = matches.value_of("separator").unwrap();
    let opt_words = matches.value_of("words").unwrap();
    let opt_complexity = matches.value_of("complexity").unwrap();
    let opt_count = matches.value_of("count").unwrap();

    // Parse words and count into numbers. Validated so unwrapping is okay.
    let opt_words: u8 = opt_words.parse().unwrap();
    let opt_count: u64 = opt_count.parse().unwrap();

    // Select the appropriate word list.
    let petnames = match opt_complexity {
        "0" => Petnames::small(),
        "1" => Petnames::medium(),
        "2" => Petnames::large(),
        _ => Petnames::small(),
    };

    // We're going to need a source of randomness.
    let mut rng = rand::thread_rng();

    // Stream if count is 0.
    if opt_count == 0 {
        loop {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    } else {
        for _ in 1..=opt_count {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    }
}

fn can_be_parsed<INTO>(value: String) -> Result<(), String>
where
    INTO: FromStr,
    <INTO as FromStr>::Err: std::fmt::Display,
{
    match value.parse::<INTO>() {
        Err(e) => Err(format!("{}", e)),
        Ok(_) => Ok(()),
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::io::Read;
use std::net::TcpListener;
use std::thread;

mod server;
mod message;

fn main() {
    let listener = TcpListener::bind(("0.0.0.0", 1883)).unwrap();
    for stream in listener.incoming() {
        thread::spawn(|| {
            {
                let mut stream = stream.unwrap();
                let mut buffer = vec![0u8; 1024];
                let read_result = stream.read(&mut buffer);

                match read_result {
                    Ok(length) => {
                        let message_bytes = &buffer[0..length];
                        let message_type = message::message_type(message_bytes);
                        match message_type {
                            message::MqttType::Connect => {
                                stream.write(&[32, 2, 0, 0]).unwrap();
                            }
                            message::MqttType::PingReq => {
                                stream.write(&[0xd0, 0]).unwrap();
                            }
                            _ => println!("Unknown message type"),
                        }
                    }
                    _ => panic!("Error reading bytes from stream"),
                }
            }
        });
    }
}
<commit_msg>ping.feature passes<commit_after>use std::io::Write;
use std::io::Read;
use std::net::TcpListener;
use std::thread;

mod server;
mod message;

fn main() {
    let listener = TcpListener::bind(("0.0.0.0", 1883)).unwrap();
    for stream in listener.incoming() {
        thread::spawn(|| {
            let mut stream = stream.unwrap();
            loop {
                let mut buffer = vec![0u8; 1024];
                let read_result = stream.read(&mut buffer);

                match read_result {
                    Ok(length) => {
                        let message_bytes = &buffer[0..length];
                        let message_type = message::message_type(message_bytes);
                        match message_type {
                            message::MqttType::Connect => {
                                stream.write(&[32, 2, 0, 0]).unwrap();
                            }
                            message::MqttType::PingReq => {
                                stream.write(&[0xd0, 0]).unwrap();
                            }
                            _ => println!("Unknown message type"),
                        }
                    }
                    _ => panic!("Error reading bytes from stream"),
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(path)]

#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex;
extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::collections::HashMap;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;
use regex::Regex;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
            println!("\tnew_filename={}",       output[i].new_filename);
            println!("\told_filename={}",       output[i].old_filename);
    }
}

#[derive(Debug, PartialEq, Eq)]
enum FoundState {
    Added, Deleted
}

fn dump_diffline(line: &DiffLine) {
    // 'origin' is wrapped in pipes to ease displaying space characters.
    print!("line: old={:?} new={:?} offset={} |origin|=|{}|\n      content={}",
             line.old_lineno(), line.new_lineno(), line.content_offset(),
             line.origin(), str::from_utf8(line.content()).unwrap());
}

fn dump_diffdelta(delta: &DiffDelta) {
    println!("delta: nfiles={} status={:?} old_file=(id={} path_bytes={:?} path={:?} tsize={}) new_file=(id={} path_bytes={:?} path={:?} tsize={})",
            delta.nfiles(), delta.status(),
            delta.old_file().id(), delta.old_file().path_bytes(), delta.old_file().path(), delta.old_file().size(),
            delta.new_file().id(), delta.new_file().path_bytes(), delta.new_file().path(), delta.new_file().size());
}

fn format_key(key: String) -> String {
    let remove_whitespace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    let trim = regex!(r"^[\s]+|[\s]+$");
    let result = remove_whitespace.replace_all(key.as_slice(), "");
    trim.replace_all(result.as_slice(), "")
}

#[derive(Debug)]
struct Found {
    filename: Path,
    key: String,
    state: FoundState,
    start_position: u32,
    line_count: u32,
}

fn find_keys(diff: Diff) -> Vec<Found> {

    #[derive(Debug)]
    enum State {
        Other, Addition, Deletion
    }

    let mut founds: Vec<Found> = Vec::new();

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();
    let mut old_path = Path::new("");
    let mut new_path = Path::new("");

    let mut line_count: u32 = 0;
    let mut start_position: u32 = 0;

	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

        assert!(delta.nfiles() == 2, "This only works on diffs between exactly 2 files.");

		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("top of loop: founds={:?}", founds);
        println!("top of loop: added={:?} deleted={:?}", added, deleted);
        println!("top of loop: line_count={:?}", line_count);

        dump_diffline(&line);
        //dump_diffdelta(&delta);

        old_path = delta.old_file().path().unwrap().clone();
        new_path = delta.new_file().path().unwrap().clone();

		match line.origin() {
			// Additions
			'+' | '>' => {
                println!("In additions. state={:?}", state);

                added.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                        line_count = 0;
                        start_position = line.new_lineno().unwrap();
                    },
                    State::Addition => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = line.new_lineno().unwrap();
                    },
                }

                state = State::Addition;
				true
			},
			// Deletions
			'-' | '<' => {
                println!("In deletion. state={:?}", state);

                deleted.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                        line_count = 0;
                        start_position = line.old_lineno().unwrap();
                    },
                    State::Deletion => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = line.old_lineno().unwrap();
                    },
                }

                state = State::Deletion;
				true
			},
			// Other
			_         => {
                println!("in _. state={:?}", state);

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                    },
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                    },
                    _ => (),
                }

                state = State::Other;
                true
            }
		}
	});

    // Grab one.
    match state {
        State::Addition => {
            if added.len() > 0 {
                founds.push(Found {
                    filename: new_path,
                    key: format_key(added.clone()),
                    state: FoundState::Added,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        State::Deletion => {
            if deleted.len() > 0 {
                founds.push(Found {
                    filename: old_path,
                    key: format_key(deleted.clone()),
                    state: FoundState::Deleted,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        _ => (),
    }

    return founds;
}

fn path_to_string(path: Path) -> String {
    String::from_utf8(path.into_vec()).unwrap()
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    let founds: Vec<Found> = find_keys(diff);

    println!("FOUNDS={:?}", founds);

    let mut moves: Vec<Output> = Vec::new();

    let mut map: HashMap<String, Found> = HashMap::new();

    for f in founds {
        if map.contains_key(&f.key) {
            let q = map.get(&f.key).unwrap();
            if q.line_count == f.line_count {
                let mut origin_line: u32;
                let mut destination_line: u32;
                let mut old_filename: String;
                let mut new_filename: String;

                assert!(f.state != q.state, "One state must be an addition and the other state must be a deletion.");

                match f.state {
                    FoundState::Added => {
                        origin_line = q.start_position;
                        destination_line = f.start_position;
                        old_filename = path_to_string(q.filename.clone());
                        new_filename = path_to_string(f.filename.clone());
                    },
                    FoundState::Deleted => {
                        origin_line = f.start_position;
                        destination_line = q.start_position;
                        old_filename = path_to_string(f.filename.clone());
                        new_filename = path_to_string(q.filename.clone());
                    },
                }

                moves.push(
                    Output {
                        old_commit: old.id(),
	                    new_commit: new.id(),
                        old_filename: old_filename,
                        new_filename: new_filename,
	                    origin_line: origin_line,
	                    destination_line: destination_line,
	                    num_lines: f.line_count,
                    }
                );
            }
        } else {
            map.insert(f.key.clone(), f);
        }
    }

    return Ok(moves);
}

#[derive(Debug)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    old_filename: String,
    new_filename: String,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<commit_msg>Fix comment.<commit_after>#![feature(core)]
#![feature(path)]

#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex;
extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::collections::HashMap;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;
use regex::Regex;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
            println!("\tnew_filename={}",       output[i].new_filename);
            println!("\told_filename={}",       output[i].old_filename);
    }
}

#[derive(Debug, PartialEq, Eq)]
enum FoundState {
    Added, Deleted
}

fn dump_diffline(line: &DiffLine) {
    // 'origin' is wrapped in pipes to ease displaying space characters.
    print!("line: old={:?} new={:?} offset={} |origin|=|{}|\n      content={}",
             line.old_lineno(), line.new_lineno(), line.content_offset(),
             line.origin(), str::from_utf8(line.content()).unwrap());
}

fn dump_diffdelta(delta: &DiffDelta) {
    println!("delta: nfiles={} status={:?} old_file=(id={} path_bytes={:?} path={:?} tsize={}) new_file=(id={} path_bytes={:?} path={:?} tsize={})",
            delta.nfiles(), delta.status(),
            delta.old_file().id(), delta.old_file().path_bytes(), delta.old_file().path(), delta.old_file().size(),
            delta.new_file().id(), delta.new_file().path_bytes(), delta.new_file().path(), delta.new_file().size());
}

fn format_key(key: String) -> String {
    let remove_whitespace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    let trim = regex!(r"^[\s]+|[\s]+$");
    let result = remove_whitespace.replace_all(key.as_slice(), "");
    trim.replace_all(result.as_slice(), "")
}

#[derive(Debug)]
struct Found {
    filename: Path,
    key: String,
    state: FoundState,
    start_position: u32,
    line_count: u32,
}

fn find_keys(diff: Diff) -> Vec<Found> {

    #[derive(Debug)]
    enum State {
        Other, Addition, Deletion
    }

    let mut founds: Vec<Found> = Vec::new();

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();
    let mut old_path = Path::new("");
    let mut new_path = Path::new("");

    let mut line_count: u32 = 0;
    let mut start_position: u32 = 0;

	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

        assert!(delta.nfiles() == 2, "This only works on diffs between exactly 2 files.");

		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("top of loop: founds={:?}", founds);
        println!("top of loop: added={:?} deleted={:?}", added, deleted);
        println!("top of loop: line_count={:?}", line_count);

        dump_diffline(&line);
        //dump_diffdelta(&delta);

        old_path = delta.old_file().path().unwrap().clone();
        new_path = delta.new_file().path().unwrap().clone();

		match line.origin() {
			// Additions
			'+' | '>' => {
                println!("In additions. state={:?}", state);

                added.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                        line_count = 0;
                        start_position = line.new_lineno().unwrap();
                    },
                    State::Addition => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = line.new_lineno().unwrap();
                    },
                }

                state = State::Addition;
				true
			},
			// Deletions
			'-' | '<' => {
                println!("In deletion. state={:?}", state);

                deleted.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                        line_count = 0;
                        start_position = line.old_lineno().unwrap();
                    },
                    State::Deletion => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = line.old_lineno().unwrap();
                    },
                }

                state = State::Deletion;
				true
			},
			// Other
			_         => {
                println!("in _. state={:?}", state);

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                    },
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                    },
                    _ => (),
                }

                state = State::Other;
                true
            }
		}
	});

    // Grab last one.
    match state {
        State::Addition => {
            if added.len() > 0 {
                founds.push(Found {
                    filename: new_path,
                    key: format_key(added.clone()),
                    state: FoundState::Added,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        State::Deletion => {
            if deleted.len() > 0 {
                founds.push(Found {
                    filename: old_path,
                    key: format_key(deleted.clone()),
                    state: FoundState::Deleted,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        _ => (),
    }

    return founds;
}

fn path_to_string(path: Path) -> String {
    String::from_utf8(path.into_vec()).unwrap()
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    let founds: Vec<Found> = find_keys(diff);

    println!("FOUNDS={:?}", founds);

    let mut moves: Vec<Output> = Vec::new();

    let mut map: HashMap<String, Found> = HashMap::new();

    for f in founds {
        if map.contains_key(&f.key) {
            let q = map.get(&f.key).unwrap();
            if q.line_count == f.line_count {
                let mut origin_line: u32;
                let mut destination_line: u32;
                let mut old_filename: String;
                let mut new_filename: String;

                assert!(f.state != q.state, "One state must be an addition and the other state must be a deletion.");

                match f.state {
                    FoundState::Added => {
                        origin_line = q.start_position;
                        destination_line = f.start_position;
                        old_filename = path_to_string(q.filename.clone());
                        new_filename = path_to_string(f.filename.clone());
                    },
                    FoundState::Deleted => {
                        origin_line = f.start_position;
                        destination_line = q.start_position;
                        old_filename = path_to_string(f.filename.clone());
                        new_filename = path_to_string(q.filename.clone());
                    },
                }

                moves.push(
                    Output {
                        old_commit: old.id(),
	                    new_commit: new.id(),
                        old_filename: old_filename,
                        new_filename: new_filename,
	                    origin_line: origin_line,
	                    destination_line: destination_line,
	                    num_lines: f.line_count,
                    }
                );
            }
        } else {
            map.insert(f.key.clone(), f);
        }
    }

    return Ok(moves);
}

#[derive(Debug)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    old_filename: String,
    new_filename: String,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<|endoftext|>


<commit_before>#![crate_type = "bin"]

extern crate metrics;

use metrics::gauge;
use metrics::counter::StdCounter;
use metrics::counter::Counter;

fn main() {
    // Create a metric w val 0
    let mut g1: gauge::Gauge = gauge::Gauge{value: 0};
    println!("{}", g1.value);
    g1.update(100);

    // Get a snapshot of it to g2
    let g2: gauge::Gauge = g1.snapshot();

    // Update g1 to 200
    g1.update(200);

    println!("g1 {} g2 {}", g1.value, g2.value);

    println!("{}", g1.value);

    let mut c1 = StdCounter{value: 0};
    c1.inc(1);
    c1.inc(5);
    println!("{}", c1.value)
}<commit_msg>Fixup according to latest changes<commit_after>#![crate_type = "bin"]

extern crate metrics;

use metrics::gauge;
use metrics::counter::{Counter,StdCounter};

use metrics::meter::{Meter,StdMeter};
use metrics::metric::Metric;

fn main() {
    // Create a metric w val 0
    let mut g1: gauge::Gauge = gauge::Gauge{value: 0};
    println!("{}", g1.value);
    g1.update(100);

    // Get a snapshot of it to g2
    let g2: gauge::Gauge = g1.snapshot();

    // Update g1 to 200
    g1.update(200);

    println!("g1 {} g2 {}", g1.value, g2.value);

    println!("{}", g1.value);

    let mut c1 = StdCounter::new();
    c1.inc(1);
    c1.inc(5);
    println!("{}", c1.value);

    let mut meter = StdMeter::new();
    meter.mark(3i64);
    meter.tick();
    println!("Meter count: {}", meter.count());
    println!("Meter rate: {}", meter.rate(1));
}<|endoftext|>


<commit_before>// Copyright © 2016 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// Rocket pastebin demo

#![feature(plugin)]
#![feature(plugin, custom_derive)]
#![feature(proc_macro)]
#![plugin(rocket_codegen)]

static UPLOAD: &'static str = "upload";
static NID: usize = 8;

extern crate rocket;
extern crate rocket_contrib;
extern crate rand;
extern crate serde;
#[macro_use] extern crate serde_derive;

use std::io;
use std::io::{Read, BufRead, Write};
use std::path::Path;
use std::collections::HashMap;
use std::fs::{File, create_dir, metadata, remove_file};

use rocket::Data;
use rocket::response::NamedFile;
use rocket_contrib::Template;
use rocket::request::Form;
use rocket::response::Redirect;

mod paste_id;
use paste_id::PasteID;

#[derive(Serialize)]
struct PasteInfo {
    paste_id: String,
    snippet: String,
    ellipsis: bool
}

#[get("/")]
fn index() -> io::Result<Template> {
    let dirents = std::fs::read_dir(UPLOAD)
                  .expect("could not open upload directory");
    let pastes = dirents.map(|d| {
        let paste_id = d.unwrap().file_name().into_string().unwrap();
        let paste_filename = Path::new(UPLOAD).join(&paste_id);
        let paste_file = NamedFile::open(&paste_filename)
                         .expect("could not open paste file");
        let mut paste_reader = io::BufReader::new(paste_file);
        let mut paste_line = String::new();
        let paste_len = paste_reader.read_line(&mut paste_line)
                        .expect("could not read first line of paste");
        let (ellipsis, snippet) =
            if paste_len < 24 {
                (false, paste_line)
            } else {
                let result = (&paste_line)[0..24].to_string();
                (true, result)
            };
        PasteInfo { paste_id: paste_id, snippet: snippet, ellipsis: ellipsis }
    }).collect::<Vec<PasteInfo>>();
    let mut context: HashMap<&str, _> = HashMap::new();
    context.insert("pastes", &pastes);
    Ok(Template::render("index", &context))
}

#[post("/", data = "<paste>")]
fn upload(paste: Data) -> io::Result<String> {
    let paste_id = PasteID::new(NID);
    let path = Path::new(UPLOAD).join(&paste_id.to_string());
    paste.stream_to_file(path)?;
    Ok(format!("/{}\n", paste_id))
}

fn open_paste(id: &PasteID) -> io::Result<NamedFile> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    NamedFile::open(&filename)
}

fn create_paste(id: &PasteID) -> io::Result<File> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    File::create(&filename)
}

#[get("/<id>")]
fn retrieve(id: PasteID) -> Option<NamedFile> {
    open_paste(&id).ok()
}

#[get("/new")]
fn edit_new() -> io::Result<Redirect> {
    let paste_id = PasteID::new(NID);
    let f = try!(create_paste(&paste_id));
    drop(f);
    Ok(Redirect::to(&format!("/edit/{}", paste_id.to_string())))
}

#[get("/edit/<id>")]
fn make_edit(id: PasteID) -> io::Result<Template> {
    let paste = open_paste(&id)?;
    let mut paste_reader = io::BufReader::new(paste);
    let mut paste_contents = String::new();
    paste_reader.read_to_string(&mut paste_contents)?;
    let paste_id = id.to_string();
    let paste_rows = format!("{}", 100);
    let mut context: HashMap<&str, _> = HashMap::new();
    context.insert("contents", &paste_contents);
    context.insert("paste_id", &paste_id);
    context.insert("paste_rows", &paste_rows);
    Ok(Template::render("edit", &context))
}

#[derive(FromForm)]
struct EditForm {
    paste: String
}

#[post("/edit/<id>", data = "<form>")]
fn accept_edit(id: PasteID, form: Form<EditForm>) -> io::Result<Redirect> {
    let edit = form.get();
    let paste = create_paste(&id)?;
    let mut paste_writer = io::BufWriter::new(paste);
    let paste_contents =
        edit.paste.chars().map(|c|{c as u8}).collect::<Vec<u8>>();
    paste_writer.write_all(paste_contents.as_slice())?;
    paste_writer.flush()?;
    Ok(Redirect::to("/"))
}

#[get("/delete/<id>")]
fn delete(id: PasteID) -> io::Result<Redirect> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    try!(remove_file(&filename));
    Ok(Redirect::to("/"))
}

fn ok_dir<P: AsRef<Path>>(path: P) -> bool {
    match metadata(path.as_ref()) {
        Ok(md) => md.is_dir(),
        _ => false
    }
}

fn check_upload_dir() {
    if !ok_dir(UPLOAD) {
        create_dir(UPLOAD).expect("could not create upload directory");
    }
}

fn main() {
    check_upload_dir();
    let rocket = rocket::ignite();
    let rocket = rocket.mount("/", routes![index, upload, edit_new, retrieve,
                                           make_edit, accept_edit, delete]);
    rocket.launch()
}

#[cfg(test)]
mod test {
    extern crate scraper;

    use super::rocket;
    use rocket::testing::MockRequest;
    use rocket::http::{Status, Method};
    use self::scraper::{Html, Selector};

    #[test]
    fn index() {
        let rocket = rocket::ignite().mount("/", routes![super::index]);

        let mut req = MockRequest::new(Method::Get, "/");
        let mut response = req.dispatch_with(&rocket);

        assert_eq!(response.status(), Status::Ok);

        let body_str = response.body().and_then(|b| b.into_string()).unwrap_or(String::from(""));
        assert_has_text(body_str.clone(), String::from("Pastebin!"));
        assert_has_selector(body_str.clone(), String::from("ul"));
        assert_no_selector(body_str.clone(), String::from("ul li"));
    }

    fn assert_has_text(body: String, expected: String) {
      let body_html = Html::parse_fragment(&body.to_string());
      let selector = Selector::parse("*").unwrap();
      let elements = body_html.select(&selector);
      let texts = elements.map(|e| e.text().collect::<Vec<_>>().concat());
      let actual = texts.fold("".to_string(), (|acc, str| format!("{}:{}", acc, str)));
      assert!(&actual.contains(&expected));
    }

    fn assert_has_selector(body: String, selector_text: String) {
      let body_html = Html::parse_fragment(&body.to_string());
      let selector = Selector::parse(&selector_text).unwrap();
      let count = body_html.select(&selector).count();
      assert!(count > 0);
    }

    fn assert_no_selector(body: String, selector_text: String) {
      let body_html = Html::parse_fragment(&body.to_string());
      let selector = Selector::parse(&selector_text).unwrap();
      let count = body_html.select(&selector).count();
      assert_eq!(0, count);
    }
}
<commit_msg>cleaned up some noise in test<commit_after>// Copyright © 2016 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// Rocket pastebin demo

#![feature(plugin)]
#![feature(plugin, custom_derive)]
#![feature(proc_macro)]
#![plugin(rocket_codegen)]

static UPLOAD: &'static str = "upload";
static NID: usize = 8;

extern crate rocket;
extern crate rocket_contrib;
extern crate rand;
extern crate serde;
#[macro_use] extern crate serde_derive;

use std::io;
use std::io::{Read, BufRead, Write};
use std::path::Path;
use std::collections::HashMap;
use std::fs::{File, create_dir, metadata, remove_file};

use rocket::Data;
use rocket::response::NamedFile;
use rocket_contrib::Template;
use rocket::request::Form;
use rocket::response::Redirect;

mod paste_id;
use paste_id::PasteID;

#[derive(Serialize)]
struct PasteInfo {
    paste_id: String,
    snippet: String,
    ellipsis: bool
}

#[get("/")]
fn index() -> io::Result<Template> {
    let dirents = std::fs::read_dir(UPLOAD)
                  .expect("could not open upload directory");
    let pastes = dirents.map(|d| {
        let paste_id = d.unwrap().file_name().into_string().unwrap();
        let paste_filename = Path::new(UPLOAD).join(&paste_id);
        let paste_file = NamedFile::open(&paste_filename)
                         .expect("could not open paste file");
        let mut paste_reader = io::BufReader::new(paste_file);
        let mut paste_line = String::new();
        let paste_len = paste_reader.read_line(&mut paste_line)
                        .expect("could not read first line of paste");
        let (ellipsis, snippet) =
            if paste_len < 24 {
                (false, paste_line)
            } else {
                let result = (&paste_line)[0..24].to_string();
                (true, result)
            };
        PasteInfo { paste_id: paste_id, snippet: snippet, ellipsis: ellipsis }
    }).collect::<Vec<PasteInfo>>();
    let mut context: HashMap<&str, _> = HashMap::new();
    context.insert("pastes", &pastes);
    Ok(Template::render("index", &context))
}

#[post("/", data = "<paste>")]
fn upload(paste: Data) -> io::Result<String> {
    let paste_id = PasteID::new(NID);
    let path = Path::new(UPLOAD).join(&paste_id.to_string());
    paste.stream_to_file(path)?;
    Ok(format!("/{}\n", paste_id))
}

fn open_paste(id: &PasteID) -> io::Result<NamedFile> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    NamedFile::open(&filename)
}

fn create_paste(id: &PasteID) -> io::Result<File> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    File::create(&filename)
}

#[get("/<id>")]
fn retrieve(id: PasteID) -> Option<NamedFile> {
    open_paste(&id).ok()
}

#[get("/new")]
fn edit_new() -> io::Result<Redirect> {
    let paste_id = PasteID::new(NID);
    let f = try!(create_paste(&paste_id));
    drop(f);
    Ok(Redirect::to(&format!("/edit/{}", paste_id.to_string())))
}

#[get("/edit/<id>")]
fn make_edit(id: PasteID) -> io::Result<Template> {
    let paste = open_paste(&id)?;
    let mut paste_reader = io::BufReader::new(paste);
    let mut paste_contents = String::new();
    paste_reader.read_to_string(&mut paste_contents)?;
    let paste_id = id.to_string();
    let paste_rows = format!("{}", 100);
    let mut context: HashMap<&str, _> = HashMap::new();
    context.insert("contents", &paste_contents);
    context.insert("paste_id", &paste_id);
    context.insert("paste_rows", &paste_rows);
    Ok(Template::render("edit", &context))
}

#[derive(FromForm)]
struct EditForm {
    paste: String
}

#[post("/edit/<id>", data = "<form>")]
fn accept_edit(id: PasteID, form: Form<EditForm>) -> io::Result<Redirect> {
    let edit = form.get();
    let paste = create_paste(&id)?;
    let mut paste_writer = io::BufWriter::new(paste);
    let paste_contents =
        edit.paste.chars().map(|c|{c as u8}).collect::<Vec<u8>>();
    paste_writer.write_all(paste_contents.as_slice())?;
    paste_writer.flush()?;
    Ok(Redirect::to("/"))
}

#[get("/delete/<id>")]
fn delete(id: PasteID) -> io::Result<Redirect> {
    let filename = Path::new(UPLOAD).join(id.to_string());
    try!(remove_file(&filename));
    Ok(Redirect::to("/"))
}

fn ok_dir<P: AsRef<Path>>(path: P) -> bool {
    match metadata(path.as_ref()) {
        Ok(md) => md.is_dir(),
        _ => false
    }
}

fn check_upload_dir() {
    if !ok_dir(UPLOAD) {
        create_dir(UPLOAD).expect("could not create upload directory");
    }
}

fn main() {
    check_upload_dir();
    let rocket = rocket::ignite();
    let rocket = rocket.mount("/", routes![index, upload, edit_new, retrieve,
                                           make_edit, accept_edit, delete]);
    rocket.launch()
}

#[cfg(test)]
mod test {
    extern crate scraper;

    use super::rocket;
    use rocket::testing::MockRequest;
    use rocket::http::{Status, Method};
    use self::scraper::{Html, Selector};

    #[test]
    fn index() {
        let rocket = rocket::ignite().mount("/", routes![super::index]);

        let mut req = MockRequest::new(Method::Get, "/");
        let mut response = req.dispatch_with(&rocket);

        assert_eq!(response.status(), Status::Ok);

        let body_str = response.body().and_then(|b| b.into_string()).unwrap_or(String::from(""));
        assert_has_text(&body_str, &"Pastebin!");
        assert_has_selector(&body_str, &"ul");
        assert_no_selector(&body_str, &"ul li");
    }

    fn assert_has_text(body: &str, expected: &str) {
      let body_html = Html::parse_fragment(body);
      let selector = Selector::parse("*").unwrap();
      let elements = body_html.select(&selector);
      let texts = elements.map(|e| e.text().collect::<Vec<_>>().concat());
      let actual = texts.fold(String::new(), |acc, s| format!("{}:{}", acc, s));
      assert!(&actual.contains(expected));
    }

    fn assert_has_selector(body: &str, selector_text: &str) {
      let body_html = Html::parse_fragment(body);
      let selector = Selector::parse(selector_text).unwrap();
      let count = body_html.select(&selector).count();
      assert!(count > 0);
    }

    fn assert_no_selector(body: &str, selector_text: &str) {
      let body_html = Html::parse_fragment(body);
      let selector = Selector::parse(selector_text).unwrap();
      let count = body_html.select(&selector).count();
      assert_eq!(0, count);
    }
}
<|endoftext|>


<commit_before>
use InstructionSet;

#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL{value: i32},
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL{value:0}; 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
				//[DEBUG]
				println!("PSH {0}", match self.program[self.ip] {InstructionSet::VAL{value} => value, _=> 0,});
			},
			POP => {
				let val_popped = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;
				println!("POP {0}", val_popped);
			},
			ADD => {
				// first we pop the stack and store it as a
				let a = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				// we then pop the top of the stack and store it as b
				let b = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				//[DEBUG]
				println!("ADD {0}; {1}", a, b);

				// we then add the result and push it to the stack
				let result = b + a;
				self.sp += 1; // increment stack pointer **before**
				self.stack[self.sp as usize] = InstructionSet::VAL{value: result}; // set the value to the top of the stack

			},
			_ => println!("Instruction does not exist in instruction set."),
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL{value: 5},
		InstructionSet::PSH, InstructionSet::VAL{value: 6},
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		let instr = vm.fetch();
		vm.eval(instr);
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<commit_msg>cleaning in process<commit_after>
#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL{value: i32},
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL{value:0}; 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
				//[DEBUG]
				println!("PSH {0}", match self.program[self.ip] {
					InstructionSet::VAL{value} => value,
					_ => 0,});
			},
			POP => {
				let val_popped = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;
				println!("POP {0}", val_popped);
			},
			ADD => {
				// first we pop the stack and store it as a
				let a = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				// we then pop the top of the stack and store it as b
				let b = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				//[DEBUG]
				println!("ADD {0}; {1}", a, b);

				// we then add the result and push it to the stack
				let result = b + a;
				self.sp += 1; // increment stack pointer **before**
				self.stack[self.sp as usize] = InstructionSet::VAL{value: result}; // set the value to the top of the stack
			},
			_ => println!("[ERROR]: Unkown instruction"),
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL{value: 5},
		InstructionSet::PSH, InstructionSet::VAL{value: 6},
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		let instr = vm.fetch();
		vm.eval(instr);
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate curl;
extern crate git;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

use git::Result as GitResult;
use std::default::Default;
use std::io::IoResult;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            if let Err(e) = $result {
                error(e);
                std::os::set_exit_status(1);
                return;
            }
        );
    );

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&mut std::io::stdio::stdout(), &path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn error<T: std::fmt::Show>(e: T) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn status<T: Writer>(writer: &mut T, path: &Path) -> IoResult<()> {
    use std::io::MemWriter;
    use std::io::{IoError, OtherIoError};

    macro_rules! display(
        ($writer:expr, $title:expr, $paths:expr) => {
            if !$paths.is_empty() {
                try!(display($writer, $title, &$paths));
            }
        };
    );

    let (new, updated, removed) = match summarize(path) {
        Ok(result) => result,
        Err(error) => return Err(IoError {
            kind: OtherIoError,
            desc: "cannot check the status of the repository",
            detail: Some(error.to_string()),
        }),
    };

    let mut buffer = MemWriter::new();

    display!(&mut buffer, "New", new);
    display!(&mut buffer, "Updated", updated);
    display!(&mut buffer, "Deleted", removed);

    let data = buffer.into_inner();

    if data.len() > 0 {
        try!(writeln!(writer, "### {}", timestamp()));
        try!(writeln!(writer, ""));
        try!(writer.write(data.as_slice()));
    }

    Ok(())
}

fn push(path: &Path) -> GitResult<()> {
    let mut git = try!(git::open(path));

    if try!(git.status()).len() > 0 {
        try!(git.add_all());
        try!(git.commit("Synchronized with the official repository"));
    }

    try!(git.push());

    Ok(())
}

fn summarize(dir: &Path) -> GitResult<(Vec<Path>, Vec<Path>, Vec<Path>)> {
    use git::status::{Flag, Flags};

    macro_rules! equal(
        ($one:expr, $two:expr) => ($one.dir_path() == $two.dir_path());
    );

    macro_rules! find(
        ($vector:expr, $element:expr) => (
            $vector.iter().find(|p| equal!(p, $element))
        );
    );

    const NEW: Flags = Flags(Flag::IndexNew as u32 | Flag::WorkDirNew as u32);
    const UPDATED: Flags = Flags(Flag::IndexModified as u32 | Flag::WorkDirModified as u32);
    const REMOVED: Flags = Flags(Flag::IndexDeleted as u32 | Flag::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vector: &mut Vec<Path>, path: &Path) {
        if find!(vector, path).is_none() {
            vector.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path());

        if status.has_any(NEW) {
            push(&mut new, &path);
        } else if status.has_any(UPDATED) {
            push(&mut updated, &path);
        } else if status.has_any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if find!(removed, path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        (find!(updated, path).is_none())
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn display<T: Writer>(writer: &mut T, title: &str, paths: &Vec<Path>) -> IoResult<()> {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = lines.len();
    if len == 0 {
        return Ok(());
    }

    try!(writeln!(writer, "{}:", title));
    try!(writeln!(writer, ""));
    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            try!(writeln!(writer, "* {}.", line));
        } else if i + 2 == len {
            if len == 2 {
                try!(writeln!(writer, "* {} and", line));
            } else {
                try!(writeln!(writer, "* {}, and", line));
            }
        } else {
            try!(writeln!(writer, "* {},", line));
        }
    }
    try!(writeln!(writer, ""));

    Ok(())
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}

fn timestamp() -> String {
    let time = time::now();

    const MONTHS: [&'static str; 12] = ["January", "February", "March", "April",
                                        "May", "June", "July", "August", "September",
                                        "October", "November", "December"];

    format!("{} {}, {}", MONTHS[time.tm_mon as uint], time.tm_mday, 1900 + time.tm_year)
}
<commit_msg>Updated to Rust’s master<commit_after>#![feature(macro_rules, old_orphan_check)]

extern crate curl;
extern crate git;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

use git::Result as GitResult;
use std::default::Default;
use std::io::IoResult;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            if let Err(e) = $result {
                error(e);
                std::os::set_exit_status(1);
                return;
            }
        );
    );

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&mut std::io::stdio::stdout(), &path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn error<T: std::fmt::Show>(e: T) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn status<T: Writer>(writer: &mut T, path: &Path) -> IoResult<()> {
    use std::io::MemWriter;
    use std::io::{IoError, OtherIoError};

    macro_rules! display(
        ($writer:expr, $title:expr, $paths:expr) => {
            if !$paths.is_empty() {
                try!(display($writer, $title, &$paths));
            }
        };
    );

    let (new, updated, removed) = match summarize(path) {
        Ok(result) => result,
        Err(error) => return Err(IoError {
            kind: OtherIoError,
            desc: "cannot check the status of the repository",
            detail: Some(error.to_string()),
        }),
    };

    let mut buffer = MemWriter::new();

    display!(&mut buffer, "New", new);
    display!(&mut buffer, "Updated", updated);
    display!(&mut buffer, "Deleted", removed);

    let data = buffer.into_inner();

    if data.len() > 0 {
        try!(writeln!(writer, "### {}", timestamp()));
        try!(writeln!(writer, ""));
        try!(writer.write(data.as_slice()));
    }

    Ok(())
}

fn push(path: &Path) -> GitResult<()> {
    let mut git = try!(git::open(path));

    if try!(git.status()).len() > 0 {
        try!(git.add_all());
        try!(git.commit("Synchronized with the official repository"));
    }

    try!(git.push());

    Ok(())
}

fn summarize(dir: &Path) -> GitResult<(Vec<Path>, Vec<Path>, Vec<Path>)> {
    use git::status::{Flag, Flags};

    macro_rules! equal(
        ($one:expr, $two:expr) => ($one.dir_path() == $two.dir_path());
    );

    macro_rules! find(
        ($vector:expr, $element:expr) => (
            $vector.iter().find(|p| equal!(p, $element))
        );
    );

    const NEW: Flags = Flags(Flag::IndexNew as u32 | Flag::WorkDirNew as u32);
    const UPDATED: Flags = Flags(Flag::IndexModified as u32 | Flag::WorkDirModified as u32);
    const REMOVED: Flags = Flags(Flag::IndexDeleted as u32 | Flag::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vector: &mut Vec<Path>, path: &Path) {
        if find!(vector, path).is_none() {
            vector.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path());

        if status.has_any(NEW) {
            push(&mut new, &path);
        } else if status.has_any(UPDATED) {
            push(&mut updated, &path);
        } else if status.has_any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if find!(removed, path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        (find!(updated, path).is_none())
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn display<T: Writer>(writer: &mut T, title: &str, paths: &Vec<Path>) -> IoResult<()> {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = lines.len();
    if len == 0 {
        return Ok(());
    }

    try!(writeln!(writer, "{}:", title));
    try!(writeln!(writer, ""));
    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            try!(writeln!(writer, "* {}.", line));
        } else if i + 2 == len {
            if len == 2 {
                try!(writeln!(writer, "* {} and", line));
            } else {
                try!(writeln!(writer, "* {}, and", line));
            }
        } else {
            try!(writeln!(writer, "* {},", line));
        }
    }
    try!(writeln!(writer, ""));

    Ok(())
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}

fn timestamp() -> String {
    let time = time::now();

    const MONTHS: [&'static str; 12] = ["January", "February", "March", "April",
                                        "May", "June", "July", "August", "September",
                                        "October", "November", "December"];

    format!("{} {}, {}", MONTHS[time.tm_mon as uint], time.tm_mday, 1900 + time.tm_year)
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::OpenOptions;
use std::path::PathBuf;
use chrono::prelude::*;
use std::collections::HashMap;

extern crate serde;
extern crate serde_json;
extern crate chrono;

#[macro_use]
extern crate serde_derive;

#[derive(Serialize, Deserialize)]
struct Exercise {
    desired: u32,
    current: u32,
    created: DateTime<Local>,
}

#[derive(Serialize, Deserialize)]
struct Regimen {
    exercises: HashMap<String, Exercise>
}

impl Regimen {
    fn add(&mut self, exer: &str, des: &str) {
        self.exercises.insert(String::from(exer), Exercise { desired: des.parse::<u32>().unwrap(), current: 0, created: Local::now()});
    }

    fn list(&self) {
        for (name, details) in &self.exercises {
            println!("{} {}/{}", name, details.current, details.desired);
        }
    }

    fn done(&mut self, exer: &str, des: &str) {
        self.exercises.get_mut(exer).unwrap().current += des.parse::<u32>().unwrap();
    }
}

fn main() {
    let file = get_file()
        .expect("Could not open or create file!");

    let mut reg: Regimen = serde_json::from_reader(file).unwrap();

    let mut args = env::args();
    args.next().expect("Only one argument???");

    match args.next().expect("TODO proper error").as_ref() {
        "add" => reg.add(args.next().expect("Need exercise name").as_ref(), args.next().expect("Need goal number of reps").as_ref()),
        "list" => reg.list(),
        "done" => reg.done(args.next().expect("Need exercise name").as_ref(), args.next().expect("Need completed number of reps").as_ref()),
        _ => println!("Not a valid command")
    };

    let file = get_file()
        .expect("Could not open or create file!");

    serde_json::to_writer(file, &reg)
        .expect("Could not write to file!");
}

fn get_file () -> std::result::Result<std::fs::File, std::io::Error> {
    let mut config = PathBuf::from(env::home_dir().unwrap());
    config.push(".swole.json");

    OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(config)
}
<commit_msg>Added deletion support, as well as output when you do commands and fixed truncation bug<commit_after>use std::env;
use std::fs::OpenOptions;
use std::path::PathBuf;
use chrono::prelude::*;
use std::collections::HashMap;
use std::cmp::Ordering;

extern crate serde;
extern crate serde_json;
extern crate chrono;

#[macro_use]
extern crate serde_derive;

#[derive(Serialize, Deserialize)]
struct Exercise {
    desired: u32,
    current: u32,
    created: DateTime<Local>,
}

#[derive(Serialize, Deserialize)]
struct Regimen {
    exercises: HashMap<String, Exercise>,
    last_updated: DateTime<Local>
}

impl Regimen {
    fn add(&mut self, exer: &str, des: &str) {
        self.exercises.insert(String::from(exer), Exercise { desired: des.parse::<u32>().unwrap(), current: 0, created: Local::now()});
        println!("Added new exercise {}, with a goal for {} per day.", exer, des);
    }

    fn list(&self) {
        for (name, details) in &self.exercises {
            println!("{} {}/{}", name, details.current, details.desired);
        }
    }

    fn done(&mut self, exer: &str, des: &str) {
        let exercises_done: u32 = des.parse::<u32>().unwrap();
        let mut exercise = self.exercises.get_mut(exer).unwrap();
        exercise.current += exercises_done;
        print!("{} of {} {} done.", exercise.current, exercise.desired, exer);
        match exercise.current.cmp(&exercise.desired) {
            Ordering::Less => println!("Still have {} to go.", exercise.desired - exercise.current),
            Ordering::Equal => println!("Exercise complete!"),
            Ordering::Greater => println!("That's {} more than needed!", exercise.current - exercise.desired)
        }
    }

    fn delete(&mut self, exer: &str) {
        if self.exercises.contains_key(exer)
        {
            self.exercises.remove(exer);
            println!("Deleted {}. Was it too hard for you?", exer);
        } else {
            println!("No exercise {} to delete!", exer);
        }
    }

    fn reset_counts(&mut self) {
        for (_, details) in &mut self.exercises {
            details.current = 0;
        }
    }
}

fn main() {
    let file = get_file_read()
        .expect("Could not open file!");

    let mut reg: Regimen = serde_json::from_reader(file).unwrap();

    let mut args = env::args();
    args.next().expect("Only one argument???");

    // If it's not the same day, reset everything
    if reg.last_updated.date() != Local::now().date()
    {
        reg.reset_counts();
    }

    reg.last_updated = Local::now();

    match args.next().expect("TODO proper error").as_ref() {
        "add" => reg.add(args.next().expect("Need exercise name").as_ref(), args.next().expect("Need goal number of reps").as_ref()),
        "list" => reg.list(),
        "done" => reg.done(args.next().expect("Need exercise name").as_ref(), args.next().expect("Need completed number of reps").as_ref()),
        "delete" => reg.delete(args.next().expect("Need exercise name").as_ref()),
        _ => println!("Not a valid command")
    };

    let file = get_file_write()
        .expect("Could not open or create file!");

    serde_json::to_writer(file, &reg)
        .expect("Could not write to file!");
}

fn get_file_read () -> std::result::Result<std::fs::File, std::io::Error> {
    let mut config = PathBuf::from(env::home_dir().unwrap());
    config.push(".swole.json");

    OpenOptions::new()
        .read(true)
        .open(config)
}

fn get_file_write () -> std::result::Result<std::fs::File, std::io::Error> {
    let mut config = PathBuf::from(env::home_dir().unwrap());
    config.push(".swole.json");

    OpenOptions::new()
        .write(true)
        .truncate(true)
        .open(config)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate quick_error;
extern crate serde_json;
extern crate colored;

extern crate rustfix;

use std::fs::File;
use std::io::{Read, Write};
use colored::Colorize;

fn main() {
    if let Err(error) = try_main() {
        writeln!(std::io::stderr(), "An error occured: {}", error).unwrap();
        std::process::exit(1);
    }
}

fn try_main() -> Result<(), ProgramError> {
    let file_name = try!(std::env::args().skip(1).next().ok_or(ProgramError::NoFile));
    let file = try!(read_file_to_string(&file_name));

    for line in file.lines().filter(not_empty) {
        let deserialized: rustfix::diagnostics::Diagnostic = try!(serde_json::from_str(&line));
        for suggestion in &rustfix::collect_suggestions(&deserialized, None) {
            println!(
                "\n{info}: {message}\n\
                {arrow} {file}:{range}\n\
                {suggestion}\n\n\
                {text}\n\n\
                {with}\n\n\
                {replacement}\n",
                info="Info".green().bold(),
                message=split_at_lint_name(&suggestion.message),
                arrow="-->".blue().bold(),
                suggestion="Suggestion - Replace:".yellow().bold(),
                file=suggestion.file_name, range=suggestion.line_range,
                text=indent(&reset_indent(&suggestion.text)),
                with="with:".yellow().bold(),
                replacement=indent(&suggestion.replacement)
            );
        }
    }

    Ok(())
}

quick_error! {
    /// All possible errors in programm lifecycle
    #[derive(Debug)]
    pub enum ProgramError {
        /// Missing File
        NoFile {
            description("No input file given")
        }
        /// Error while dealing with file or stdin/stdout
        Io(err: std::io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        /// Error with deserialization
        Serde(err: serde_json::Error) {
            from()
            cause(err)
            description(err.description())
        }
    }
}

// Helpers
// -------

fn read_file_to_string(file_name: &str) -> Result<String, std::io::Error> {
    let mut file = try!(File::open(file_name));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer));
    Ok(buffer)
}

fn not_empty(s: &&str) -> bool {
    s.trim().len() > 0
}

fn split_at_lint_name(s: &str) -> String {
    s.split(", #[")
    .collect::<Vec<_>>()
    .join("\n      #[")
}

fn reset_indent(s: &str) -> String {
    let leading_whitespace =
        s.lines()
        .nth(0).unwrap_or("")
        .chars()
        .take_while(|&c| char::is_whitespace(c))
        .count();

    s.lines()
        .map(|line| String::from(&line[leading_whitespace..]))
        .collect::<Vec<_>>()
        .join("\n")
}

fn indent(s: &str) -> String {
    s.lines()
    .map(|l| format!("    {}", l))
    .collect::<Vec<_>>()
    .join("\n")
}
<commit_msg>Interactivity<commit_after>#[macro_use]
extern crate quick_error;
extern crate serde_json;
extern crate colored;

extern crate rustfix;

use std::fs::File;
use std::io::{Read, Write};
use colored::Colorize;

const USER_OPTIONS: &'static str = "What do you want to do? [r]eplace/[s]kip/[q]uit";

fn main() {
    if let Err(error) = try_main() {
        writeln!(std::io::stderr(), "An error occured: {}", error).unwrap();
        std::process::exit(1);
    }
}

fn try_main() -> Result<(), ProgramError> {
    let file_name = try!(std::env::args().skip(1).next().ok_or(ProgramError::NoFile));
    let file = try!(read_file_to_string(&file_name));

    'diagnostics: for line in file.lines().filter(not_empty) {
        let deserialized: rustfix::diagnostics::Diagnostic = try!(serde_json::from_str(&line));
        'suggestions: for suggestion in &rustfix::collect_suggestions(&deserialized, None) {
            println!(
                "\n{info}: {message}\n\
                {arrow} {file}:{range}\n\
                {suggestion}\n\n\
                {text}\n\n\
                {with}\n\n\
                {replacement}\n",
                info="Info".green().bold(),
                message=split_at_lint_name(&suggestion.message),
                arrow="-->".blue().bold(),
                suggestion="Suggestion - Replace:".yellow().bold(),
                file=suggestion.file_name, range=suggestion.line_range,
                text=indent(&reset_indent(&suggestion.text)),
                with="with:".yellow().bold(),
                replacement=indent(&suggestion.replacement)
            );

            'userinput: loop {
                println!("{prompt} {user_options}",
                    prompt="==>".green().bold(), user_options=USER_OPTIONS.green());

                let mut input = String::new();
                try!(std::io::stdin().read_line(&mut input));

                match input.trim() {
                    "q" => {
                        println!("Thanks for playing.");
                        break 'diagnostics;
                    }
                    "s" => {
                        println!("Skipped.");
                        continue 'suggestions;
                    }
                    "r" => {
                        unimplemented!();
                    },
                    _ => {
                        println!("{error}: I didn't get that. {user_options}",
                            error="Error".red().bold(), user_options=USER_OPTIONS);
                        continue 'userinput;
                    }
                }
            }
        }
    }

    Ok(())
}

quick_error! {
    /// All possible errors in programm lifecycle
    #[derive(Debug)]
    pub enum ProgramError {
        /// Missing File
        NoFile {
            description("No input file given")
        }
        /// Error while dealing with file or stdin/stdout
        Io(err: std::io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        /// Error with deserialization
        Serde(err: serde_json::Error) {
            from()
            cause(err)
            description(err.description())
        }
    }
}

// Helpers
// -------

fn read_file_to_string(file_name: &str) -> Result<String, std::io::Error> {
    let mut file = try!(File::open(file_name));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer));
    Ok(buffer)
}

fn not_empty(s: &&str) -> bool {
    s.trim().len() > 0
}

fn split_at_lint_name(s: &str) -> String {
    s.split(", #[")
    .collect::<Vec<_>>()
    .join("\n      #[")
}

fn reset_indent(s: &str) -> String {
    let leading_whitespace =
        s.lines()
        .nth(0).unwrap_or("")
        .chars()
        .take_while(|&c| char::is_whitespace(c))
        .count();

    s.lines()
        .map(|line| String::from(&line[leading_whitespace..]))
        .collect::<Vec<_>>()
        .join("\n")
}

fn indent(s: &str) -> String {
    s.lines()
    .map(|l| format!("    {}", l))
    .collect::<Vec<_>>()
    .join("\n")
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate image;
extern crate rand;

mod cpu;
mod display;
mod instruction;
mod keyboard;

use piston_window::*;
use cpu::Cpu;
use keyboard::{ Keyboard, KeyMapping };
use std::fs::File;
use std::io::Read;
use std::env;
use std::process;
use std::time::Instant;

const ENLARGEMENT_FACTOR: u32 = 8;
const WINDOW_WIDTH: u32 = 64;
const WINDOW_HEIGHT: u32 = 32;

// Must be a multiple of 60 for the timers to work properly
const CLOCK_SPEED_HZ: u32 = 360;

struct Arguments {
    rom: String,
    step: bool,
    debug: bool
}

fn main() {
    let arguments = match parse_args() {
        Ok(args) => args,
        Err(_) => {
            println!("Usage: chip8 [rom] [--debug (optional)] [--step (optional)]");
            process::exit(0);
        }
    };

    let width = WINDOW_WIDTH * ENLARGEMENT_FACTOR;
    let height = WINDOW_HEIGHT * ENLARGEMENT_FACTOR;

    let mut window = create_window(width, height);

    let mut file = File::open(arguments.rom)
        .expect("Unable to open the ROM file.");

    let mut game_data = Vec::new();
    file.read_to_end(&mut game_data)
        .expect("Unable to read the ROM file.",);

    let mut cpu = Cpu::new(game_data, CLOCK_SPEED_HZ, arguments.debug);
    let keyboard = Keyboard::new(KeyMapping::Improved);

    let cycle_time_millis: u128 = (1000 / CLOCK_SPEED_HZ).into();

    let mut clock = Instant::now();
    while let Some(e) = window.next() {

        let mut step_forward = false;

        if let Some(_) = e.render_args() {
            if cpu.draw_flag {
                draw_screen(&e, &cpu.get_screen(), &mut window);
                cpu.draw_flag = false
            }
        }

        if let Some(button) = e.press_args() {
            if button == Button::Keyboard(Key::Space) && arguments.step {
                step_forward = true;
            }

            if let Some(key_val) = keyboard.map_key(button) {
                cpu.set_key(key_val, true);
            }
        }

        if let Some(button) = e.release_args() {
            if let Some(key_val) = keyboard.map_key(button) {
                cpu.set_key(key_val, false);
            }
        }

        // If debugging is enabled, only cycle on space bar presses
        if arguments.step {
            if step_forward {
                cpu.cycle();
            }
        } else {
            let elapsed = clock.elapsed().as_millis();
            if elapsed >= cycle_time_millis {
                cpu.cycle();
                clock = Instant::now();
            }
        }
    }
}

fn parse_args() -> Result<Arguments, String> {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return Err(String::from("Too few arguments"))
    }
    let rom = &args[1];
    let debug = args.contains(&String::from("--debug"));
    let step = args.contains(&String::from("--step"));

    let args = Arguments {
        rom: String::from(rom),
        step: step,
        debug: debug
    };
    return Ok(args)
}

fn create_window(width: u32, height: u32) -> PistonWindow {
    let opengl = OpenGL::V3_2;

    let mut window: PistonWindow = WindowSettings::new("chip8", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    window.set_max_fps(60);

    window
}

fn draw_screen(event: &Event, screen: &display::Screen, window: &mut PistonWindow) {
    window.draw_2d(event, |context, graphics| {
        piston_window::clear(color::BLACK, graphics);

        for (i, row) in screen.iter().enumerate() {
            for (j, val) in row.iter().enumerate() {
                if *val {
                    let dimensions = [
                        (j * ENLARGEMENT_FACTOR as usize) as f64,
                        (i * ENLARGEMENT_FACTOR as usize) as f64,
                        ENLARGEMENT_FACTOR as f64,
                        ENLARGEMENT_FACTOR as f64,
                    ];
                    Rectangle::new(color::WHITE).draw(
                        dimensions,
                        &context.draw_state,
                        context.transform,
                        graphics,
                    );
                }
            }
        }
    });
}

// TODO:
// 1) Fix display issues, it is currently not working at all
//     a) This might (and probably should) involve rewriting the display logic
// 2) Add command line argument for ROM file
// 3) Fix command line arguments, potentially add a create for arg parsing (docopt?)
// 4) Keyboard scheme?
// 5) The display should really be separate from the cpu....not sure how to do this though<commit_msg>Update todos<commit_after>extern crate piston_window;
extern crate image;
extern crate rand;

mod cpu;
mod display;
mod instruction;
mod keyboard;

use piston_window::*;
use cpu::Cpu;
use keyboard::{ Keyboard, KeyMapping };
use std::fs::File;
use std::io::Read;
use std::env;
use std::process;
use std::time::Instant;

const ENLARGEMENT_FACTOR: u32 = 8;
const WINDOW_WIDTH: u32 = 64;
const WINDOW_HEIGHT: u32 = 32;

// Must be a multiple of 60 for the timers to work properly
const CLOCK_SPEED_HZ: u32 = 360;

struct Arguments {
    rom: String,
    step: bool,
    debug: bool
}

fn main() {
    let arguments = match parse_args() {
        Ok(args) => args,
        Err(_) => {
            println!("Usage: chip8 [rom] [--debug (optional)] [--step (optional)]");
            process::exit(0);
        }
    };

    let width = WINDOW_WIDTH * ENLARGEMENT_FACTOR;
    let height = WINDOW_HEIGHT * ENLARGEMENT_FACTOR;

    let mut window = create_window(width, height);

    let mut file = File::open(arguments.rom)
        .expect("Unable to open the ROM file.");

    let mut game_data = Vec::new();
    file.read_to_end(&mut game_data)
        .expect("Unable to read the ROM file.",);

    let mut cpu = Cpu::new(game_data, CLOCK_SPEED_HZ, arguments.debug);
    let keyboard = Keyboard::new(KeyMapping::Improved);

    let cycle_time_millis: u128 = (1000 / CLOCK_SPEED_HZ).into();

    let mut clock = Instant::now();
    while let Some(e) = window.next() {

        let mut step_forward = false;

        if let Some(_) = e.render_args() {
            if cpu.draw_flag {
                draw_screen(&e, &cpu.get_screen(), &mut window);
                cpu.draw_flag = false
            }
        }

        if let Some(button) = e.press_args() {
            if button == Button::Keyboard(Key::Space) && arguments.step {
                step_forward = true;
            }

            if let Some(key_val) = keyboard.map_key(button) {
                cpu.set_key(key_val, true);
            }
        }

        if let Some(button) = e.release_args() {
            if let Some(key_val) = keyboard.map_key(button) {
                cpu.set_key(key_val, false);
            }
        }

        // If debugging is enabled, only cycle on space bar presses
        if arguments.step {
            if step_forward {
                cpu.cycle();
            }
        } else {
            let elapsed = clock.elapsed().as_millis();
            if elapsed >= cycle_time_millis {
                cpu.cycle();
                clock = Instant::now();
            }
        }
    }
}

fn parse_args() -> Result<Arguments, String> {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return Err(String::from("Too few arguments"))
    }
    let rom = &args[1];
    let debug = args.contains(&String::from("--debug"));
    let step = args.contains(&String::from("--step"));

    let args = Arguments {
        rom: String::from(rom),
        step: step,
        debug: debug
    };
    return Ok(args)
}

fn create_window(width: u32, height: u32) -> PistonWindow {
    let opengl = OpenGL::V3_2;

    let mut window: PistonWindow = WindowSettings::new("chip8", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    window.set_max_fps(60);

    window
}

fn draw_screen(event: &Event, screen: &display::Screen, window: &mut PistonWindow) {
    window.draw_2d(event, |context, graphics| {
        piston_window::clear(color::BLACK, graphics);

        for (i, row) in screen.iter().enumerate() {
            for (j, val) in row.iter().enumerate() {
                if *val {
                    let dimensions = [
                        (j * ENLARGEMENT_FACTOR as usize) as f64,
                        (i * ENLARGEMENT_FACTOR as usize) as f64,
                        ENLARGEMENT_FACTOR as f64,
                        ENLARGEMENT_FACTOR as f64,
                    ];
                    Rectangle::new(color::WHITE).draw(
                        dimensions,
                        &context.draw_state,
                        context.transform,
                        graphics,
                    );
                }
            }
        }
    });
}

// TODO:
// 1) Fix display issues, it is currently not working at all
//     a) This might (and probably should) involve rewriting the display logic
// 4) Keyboard scheme?
// 5) The display should really be separate from the cpu....not sure how to do this though<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#![feature(start)]

#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate visualizer;

use visualizer::{Visualizer};

#[cfg(target_os = "android")]
android_start!(main);

pub fn main() {
    let mut visualizer = Visualizer::new();
    while visualizer.is_running() {
        visualizer.tick();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>main.rs: Removed outdated feature 'start'<commit_after>// See LICENSE file for copyright and license details.

#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate visualizer;

use visualizer::{Visualizer};

#[cfg(target_os = "android")]
android_start!(main);

pub fn main() {
    let mut visualizer = Visualizer::new();
    while visualizer.is_running() {
        visualizer.tick();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>