<commit_before>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate clap;
extern crate libc;
extern crate yaml_rust;
#[cfg(test)] extern crate rand;

mod tmux;
mod command;
mod project;

use project::parser;
use project::processor;
use tmux::config::Config;
use clap::{Arg, App, AppSettings};
use command::Command;
use std::{process, env};
use std::process::exit;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
              println!("Muxed ran in to a problem:");
              println!("{}", e);
              exit(1);
            }
        }
    })
);

pub fn help(mut app: App) -> () {
    let _ = &app.print_help();
    println!("\n");
    println!("SUBCOMMANDS:");
    println!("    new    The name of your poject to create\n");
}

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let mut app = App::new("Muxed")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Brian Pearce")
                      .about("Another TMUX project manager")
                      .setting(AppSettings::TrailingVarArg)
                      .usage("muxed [FLAGS] [OPTIONS] <PROJECT_NAME>")
                      .arg(Arg::with_name("PROJECT_NAME")
                           .help("The name of your poject to open")
                           .index(1)
                           .multiple(false)
                           .takes_value(true))
                      .arg(Arg::with_name("daemonize")
                           .short("d")
                           .multiple(false)
                           .help("If you want to create a muxed session without connecting to it"))
                      .arg(Arg::with_name("help")
                           .short("h")
                           .long("help")
                           .help("Prints help information")
                           .takes_value(false))
                      .arg(Arg::with_name("PROJECT_DIR")
                           .short("p")
                           .multiple(false)
                           .value_name("PROJECT_DIR")
                           .takes_value(true)
                           .help("The directory your project config files live in. Defaults to ~/.muxed/"))
                      .arg(Arg::with_name("REST")
                          .multiple(true)
                          .hidden(true));

    let matches = &app.get_matches_from_safe_borrow(env::args()).unwrap();

    // We check for help twice. We don't want to short circuit early incase help
    // is supposed to get passed to the subcommand.
    let project_name: &str;
    if matches.value_of("PROJECT_NAME").is_some() {
        project_name = matches.value_of("PROJECT_NAME").unwrap();
    } else if matches.is_present("help") {
        help(app);
        exit(0);
    } else {
        println!("No project name specified.");
        println!("error: The following required arguments were not provided:
<PROJECT_NAME>

USAGE:
muxed <PROJECT_NAME>");
        exit(1);
    };

    match project_name {
        "new" => {
            let mut cmd = process::Command::new("muxednew");
            if matches.is_present("REST") {
                let trail: Vec<&str> = matches.values_of("REST").unwrap().collect();
                trail.iter().fold(&mut cmd, |c, i| c.arg(i));
            };

            if matches.is_present("help") { cmd.arg("--help"); };

            let result = try_or_err!(cmd.output().map_err(|e| format!("It looks like muxednew might not be installed or we don't have access to it.\nWe received this system error while trying to call the subcommand `new`: `{}`", e)));
            // Lets add an error code they can call on for more details. Why
            // isn't muxed new installed?
            println!("{}", String::from_utf8_lossy(&result.stdout));
            println!("{}", String::from_utf8_lossy(&result.stderr));
            if let Some(c) = result.status.code() { exit(c); };
        }
        // No SubCommands found continue on.
        _     => {}
    }

    if matches.is_present("help") {
        help(app);
        exit(0);
    };

    let project_name = project_name.to_string();
    let daemonize = matches.is_present("daemonize");
    let muxed_dir = matches.value_of("PROJECT_DIR");

    let commands: Vec<Command>;
    match project::session_exists(&project_name) {
        Some(c) => {
            commands = vec!(c);
        },
        None => {
            let config = Config::from_string(tmux::get_config());
            let yaml = try_or_err!(project::read(&project_name, &muxed_dir));
            commands = try_or_err!(parser::call(&yaml, &project_name, daemonize, config));
        }
    };

    processor::main(&commands)
}
<commit_msg>refactor(main.rs): Remove an un-needed loop<commit_after>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate clap;
extern crate libc;
extern crate yaml_rust;
#[cfg(test)] extern crate rand;

mod tmux;
mod command;
mod project;

use project::parser;
use project::processor;
use tmux::config::Config;
use clap::{Arg, App, AppSettings};
use command::Command;
use std::{process, env};
use std::process::exit;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
              println!("Muxed ran in to a problem:");
              println!("{}", e);
              exit(1);
            }
        }
    })
);

pub fn help(mut app: App) -> () {
    let _ = &app.print_help();
    println!("\n");
    println!("SUBCOMMANDS:");
    println!("    new    The name of your poject to create\n");
}

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let mut app = App::new("Muxed")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Brian Pearce")
                      .about("Another TMUX project manager")
                      .setting(AppSettings::TrailingVarArg)
                      .usage("muxed [FLAGS] [OPTIONS] <PROJECT_NAME>")
                      .arg(Arg::with_name("PROJECT_NAME")
                           .help("The name of your poject to open")
                           .index(1)
                           .multiple(false)
                           .takes_value(true))
                      .arg(Arg::with_name("daemonize")
                           .short("d")
                           .multiple(false)
                           .help("If you want to create a muxed session without connecting to it"))
                      .arg(Arg::with_name("help")
                           .short("h")
                           .long("help")
                           .help("Prints help information")
                           .takes_value(false))
                      .arg(Arg::with_name("PROJECT_DIR")
                           .short("p")
                           .multiple(false)
                           .value_name("PROJECT_DIR")
                           .takes_value(true)
                           .help("The directory your project config files live in. Defaults to ~/.muxed/"))
                      .arg(Arg::with_name("REST")
                          .multiple(true)
                          .hidden(true));

    let matches = &app.get_matches_from_safe_borrow(env::args()).unwrap();

    // We check for help twice. We don't want to short circuit early incase help
    // is supposed to get passed to the subcommand.
    let project_name: &str;
    if matches.value_of("PROJECT_NAME").is_some() {
        project_name = matches.value_of("PROJECT_NAME").unwrap();
    } else if matches.is_present("help") {
        help(app);
        exit(0);
    } else {
        println!("No project name specified.");
        println!("error: The following required arguments were not provided:
<PROJECT_NAME>

USAGE:
muxed <PROJECT_NAME>");
        exit(1);
    };

    match project_name {
        "new" => {
            let mut cmd = process::Command::new("muxednew");
            if matches.is_present("REST") {
                let trail: Vec<&str> = matches.values_of("REST").unwrap().collect();
                cmd.args(trail.as_slice());
            };

            if matches.is_present("help") { cmd.arg("--help"); };

            let result = try_or_err!(cmd.output().map_err(|e| format!("It looks like muxednew might not be installed or we don't have access to it.\nWe received this system error while trying to call the subcommand `new`: `{}`", e)));
            // Lets add an error code they can call on for more details. Why
            // isn't muxed new installed?
            println!("{}", String::from_utf8_lossy(&result.stdout));
            println!("{}", String::from_utf8_lossy(&result.stderr));
            if let Some(c) = result.status.code() { exit(c); };
        }
        // No SubCommands found continue on.
        _     => {}
    }

    if matches.is_present("help") {
        help(app);
        exit(0);
    };

    let project_name = project_name.to_string();
    let daemonize = matches.is_present("daemonize");
    let muxed_dir = matches.value_of("PROJECT_DIR");

    let commands: Vec<Command>;
    match project::session_exists(&project_name) {
        Some(c) => {
            commands = vec!(c);
        },
        None => {
            let config = Config::from_string(tmux::get_config());
            let yaml = try_or_err!(project::read(&project_name, &muxed_dir));
            commands = try_or_err!(parser::call(&yaml, &project_name, daemonize, config));
        }
    };

    processor::main(&commands)
}
<|endoftext|>


<commit_before>#![feature(fs_walk, custom_derive, plugin, iter_arith, convert, result_expect)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
use serde::Deserialize;
use serde_json::Value as JsonValue;
use serde_json::Deserializer;

use std::io::{BufReader, BufRead};
use std::fs::{File, WalkDir, read_dir, walk_dir};
use std::env::args;
use std::collections::HashMap;
use std::mem::swap;

#[derive(Debug, Serialize, Deserialize)]
struct Package {
    name: String,
    vers: String,
    deps: Vec<Dep>,
    cksum: String,
    features: JsonValue,
    yanked: bool,
}

#[derive(Debug, Serialize, Deserialize)]
struct Dep {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

fn get_packages(path: &str) -> Vec<Package> {
    read_dir(path)
        .unwrap()
        .map(Result::unwrap)
        .filter(|dir| {
            let path = dir.path();
            let file = path.file_name().unwrap().to_str().unwrap();
            file != ".git" && file != "config.json"
        })
        .flat_map::<WalkDir, _>(|dir| walk_dir(dir.path()).unwrap())
        .map(Result::unwrap)
        .filter(|file| file.file_type().unwrap().is_file())
        .map(|file| {
            let reader = BufReader::new(File::open(file.path()).unwrap());
            let latest_version = reader.lines().last().unwrap().unwrap();
            let mut deserializer = Deserializer::new(latest_version.as_bytes().iter().map(|b| Ok(*b)));
            let pkg = Package::deserialize(&mut deserializer).unwrap();
            pkg
        })
        .collect()
}

fn cargo_rank(packages: &[Package]) -> Vec<(&Package, f64)> {
    let damp = 0.85;
    let starting_rank = 1.0 / packages.len() as f64;
    let mut cargo_ranks: HashMap<_, _> = packages.iter().map(|pkg| (pkg.name.as_str(), (pkg, starting_rank))).collect();
    let mut new_ranks: HashMap<_, _>;
    let mut delta = std::f64::MAX;
    let threshold = 0.000001;
    let iterative_starting_rank = (1.0 - damp) / packages.len() as f64;
    while delta > threshold {
        new_ranks = packages.iter().map(|pkg| (&pkg.name[..], (pkg, iterative_starting_rank))).collect();
        for &(pkg, rank) in cargo_ranks.values() {
            let num_deps = pkg.deps.len();
            let boost;
            if num_deps == 0 { // distribute evenly when there are no deps
                boost = damp * rank / (packages.len() as f64 - 1.0);
                for dep in packages.iter().filter(|dep| dep.name != pkg.name) {
                    new_ranks.get_mut(dep.name.as_str()).unwrap().1 += boost;
                }
            } else {
                boost = damp * rank / num_deps as f64;
                for dep in &pkg.deps {
                    new_ranks.get_mut(dep.name.as_str()).unwrap().1 += boost;
                }
            }
        }
        delta = cargo_ranks.values().map(|&(ref pkg, ref rank)| (new_ranks[pkg.name.as_str()].1 - rank).abs()).sum();
        cargo_ranks.clear();
        swap(&mut cargo_ranks, &mut new_ranks);
        println!("Delta: {}", delta);
    }
    let mut ranks: Vec<_> = cargo_ranks.into_iter().map(|(_, pkg_rank)| pkg_rank).collect();
    ranks.sort_by(|&(_, rank1), &(_, ref rank2)| rank1.partial_cmp(rank2).unwrap().reverse());
    ranks
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().unwrap();
    let packages = get_packages(&path);
    let ranks = cargo_rank(&packages);

    for (i, (pkg, rank)) in ranks.into_iter().take(args.next().unwrap().parse().expect("Not a number?")).enumerate() {
        println!("{}. {} ({})", i + 1, pkg.name, rank);
    }
}
<commit_msg>be consistent in using as_str() in some cases<commit_after>#![feature(fs_walk, custom_derive, plugin, iter_arith, convert, result_expect)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
use serde::Deserialize;
use serde_json::Value as JsonValue;
use serde_json::Deserializer;

use std::io::{BufReader, BufRead};
use std::fs::{File, WalkDir, read_dir, walk_dir};
use std::env::args;
use std::collections::HashMap;
use std::mem::swap;

#[derive(Debug, Serialize, Deserialize)]
struct Package {
    name: String,
    vers: String,
    deps: Vec<Dep>,
    cksum: String,
    features: JsonValue,
    yanked: bool,
}

#[derive(Debug, Serialize, Deserialize)]
struct Dep {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

fn get_packages(path: &str) -> Vec<Package> {
    read_dir(path)
        .unwrap()
        .map(Result::unwrap)
        .filter(|dir| {
            let path = dir.path();
            let file = path.file_name().unwrap().to_str().unwrap();
            file != ".git" && file != "config.json"
        })
        .flat_map::<WalkDir, _>(|dir| walk_dir(dir.path()).unwrap())
        .map(Result::unwrap)
        .filter(|file| file.file_type().unwrap().is_file())
        .map(|file| {
            let reader = BufReader::new(File::open(file.path()).unwrap());
            let latest_version = reader.lines().last().unwrap().unwrap();
            let mut deserializer = Deserializer::new(latest_version.as_bytes().iter().map(|b| Ok(*b)));
            let pkg = Package::deserialize(&mut deserializer).unwrap();
            pkg
        })
        .collect()
}

fn cargo_rank(packages: &[Package]) -> Vec<(&Package, f64)> {
    let damp = 0.85;
    let starting_rank = 1.0 / packages.len() as f64;
    let mut cargo_ranks: HashMap<_, _> = packages.iter().map(|pkg| (pkg.name.as_str(), (pkg, starting_rank))).collect();
    let mut new_ranks: HashMap<_, _>;
    let mut delta = std::f64::MAX;
    let threshold = 0.000001;
    let iterative_starting_rank = (1.0 - damp) / packages.len() as f64;
    while delta > threshold {
        new_ranks = packages.iter().map(|pkg| (pkg.name.as_str(), (pkg, iterative_starting_rank))).collect();
        for &(pkg, rank) in cargo_ranks.values() {
            let num_deps = pkg.deps.len();
            let boost;
            if num_deps == 0 { // distribute evenly when there are no deps
                boost = damp * rank / (packages.len() as f64 - 1.0);
                for dep in packages.iter().filter(|dep| dep.name != pkg.name) {
                    new_ranks.get_mut(dep.name.as_str()).unwrap().1 += boost;
                }
            } else {
                boost = damp * rank / num_deps as f64;
                for dep in &pkg.deps {
                    new_ranks.get_mut(dep.name.as_str()).unwrap().1 += boost;
                }
            }
        }
        delta = cargo_ranks.values().map(|&(pkg, rank)| (new_ranks[pkg.name.as_str()].1 - rank).abs()).sum();
        cargo_ranks.clear();
        swap(&mut cargo_ranks, &mut new_ranks);
        println!("Delta: {}", delta);
    }
    let mut ranks: Vec<_> = cargo_ranks.into_iter().map(|(_, pkg_rank)| pkg_rank).collect();
    ranks.sort_by(|&(_, rank1), &(_, ref rank2)| rank1.partial_cmp(rank2).unwrap().reverse());
    ranks
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().unwrap();
    let packages = get_packages(&path);
    let ranks = cargo_rank(&packages);

    for (i, (pkg, rank)) in ranks.into_iter().take(args.next().unwrap().parse().expect("Not a number?")).enumerate() {
        println!("{}. {} ({})", i + 1, pkg.name, rank);
    }
}
<|endoftext|>


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

extern crate rustc_serialize;

mod loader;
mod db;
mod dbFsDirType;
mod dbFsDir;
mod dbFsFile;
mod dbProvider;
mod dbJob;
mod dbJobProvide;
mod dbJobDepend;
mod dbVariableName;
mod dbJobRequireVariable;
mod dbVariablePair;
mod dbJobRequireVariablePair;
mod json_loader_elephant;
mod cli_clap;
mod jobs_load;
mod elephant;

fn main() {
    let conn = db::connect();
    db::create_tables(&conn);

    cli_clap::cli_clap(&conn);
    jobs_load::load(&conn);
}
<commit_msg>Clean up deligation<commit_after>extern crate clap;
extern crate rusqlite;
#[macro_use]

extern crate rustc_serialize;

mod loader;
mod db;
mod dbFsDirType;
mod dbFsDir;
mod dbFsFile;
mod dbProvider;
mod dbJob;
mod dbJobProvide;
mod dbJobDepend;
mod dbVariableName;
mod dbJobRequireVariable;
mod dbVariablePair;
mod dbJobRequireVariablePair;
mod json_loader_elephant;
mod cli_clap;
mod jobs_load;
mod elephant;

fn main() {
    let conn = db::connect();
    db::create_tables(&conn);

    let clp_matches = cli_clap::cli_clap(&conn);
    loader::deligate(&conn, clp_matches);

    jobs_load::load(&conn);
}
<|endoftext|>


<commit_before>extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate docopt;

use docopt::Docopt;

use std::thread;

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

use columnar::Columnar;

mod typedrw;
mod graphmap;
use graphmap::GraphMMap;

mod sorting;
use sorting::{SegmentList, radix_sort_32};

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      file containing list of host:port for workers
";

#[derive(Copy, Clone, Debug)]
struct NodeRank { node: u32, rank: f32, }
impl Columnar for NodeRank { type Stack = Vec<NodeRank>; }

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_spawn(communicators, source);
    }
    else if workers > 1 { pagerank_spawn(ProcessCommunicator::new_vector(workers), source); }
    else { pagerank_spawn(vec![ThreadCommunicator], source); };
}

fn pagerank_spawn<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank_thread(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

// returns [src/peers] degrees, (dst, deg) pairs, and a list of [src/peers] endpoints
fn transpose(mut edges: Vec<Vec<(u32, u32)>>, peers: usize, nodes: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let mut deg = vec![0; (nodes as usize / peers) + 1];
    for list in &edges {
        for &(s, _) in list {
            deg[s as usize / peers] += 1;
        }
    }

    // let start = time::precise_time_s();
    radix_sort_32(&mut edges, &mut Vec::new(), &|&(_,d)| d);
    // println!("sorted in {}s", time::precise_time_s() - start);

    let mut rev = Vec::<(u32,u32)>::with_capacity(deg.len());
    let mut trn = Vec::with_capacity(edges.len() * 1024);
    for list in edges {
        for (s,d) in list {
            let len = rev.len();
            if (len == 0) || (rev[len-1].0 < d) {
                rev.push((d, 0u32));
            }

            let len = rev.len();
            rev[len-1].1 += 1;
            trn.push(s / peers as u32);
        }
    }

    return (deg, rev, trn);
}

// pagerank dataflow graph has a set of edges as input, and a binary vertex that for each epoch of
// received edges initiates an iterative subcomputation to compute the pagerank.

fn pagerank_thread<C>(communicator: C, filename: String, _workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    let start = time::precise_time_s();

    let nodes = GraphMMap::new(&filename).nodes();

    let mut segments = SegmentList::new(1024); // list of edge segments

    let mut src = vec![];   // holds ranks
    let mut deg = vec![];   // holds source degrees
    let mut rev = vec![];   // holds (dst, deg) pairs
    let mut trn = vec![];   // holds transposed sources

    let mut input = root.subcomputation(|builder| {

        let (input, edges) = builder.new_input::<(u32, u32)>();
        let (cycle, ranks) = builder.loop_variable::<NodeRank>(RootTimestamp::new(20), Local(1));

        edges.binary_notify(&ranks,
                            Exchange::new(|x: &(u32,u32)| x.0 as u64),
                            Exchange::new(|x: &NodeRank| x.node as u64),
                            format!("pagerank"),
                            vec![RootTimestamp::new(0)],
                            move |input1, input2, output, notificator| {

            // receive incoming edges
            while let Some((_index, data)) = input1.pull() {
                segments.push(data.drain_temp());
            }

            while let Some((iter, _)) = notificator.next() {

                // if the very first iteration, prepare some stuff
                if iter.inner == 0 {
                    let (a, b, c) = transpose(segments.finalize(), peers, nodes);
                    deg = a; rev = b; trn = c;
                    src = vec![0.0f32; deg.len()];
                }

                println!("{:.3}\tworker {}: notify[{}] begin", time::precise_time_s() - start, index, iter.inner);

                for s in 0..src.len() { src[s] = 0.15 + 0.85 * src[s] / deg[s] as f32; }

                let mut trn_slice = &trn[..];
                let mut rev_slice = &rev[..];
                while rev_slice.len() > 0 {
                    // TODO: session should just flush...
                    let mut session = output.session(&iter);
                    let next = std::cmp::min(200_000, rev_slice.len());
                    for &(dst, deg) in &rev_slice[..next] {
                        let mut accum = 0.0;
                        for &s in &trn_slice[..deg as usize] {
                            accum += src[s as usize];
                        }
                        trn_slice = &trn_slice[deg as usize..];
                        // session.give(NodeRank { node: dst, rank: accum });
                    }
                    rev_slice = &rev_slice[next..];
                }

                for s in &mut src { *s = 0.0; }

                println!("{:.3}\tworker {}: notify[{}] ended", time::precise_time_s() - start, index, iter.inner);
            }

            while let Some((iter, data)) = input2.pull() {
                notificator.notify_at(&iter);
                for x in data.drain_temp() {
                    src[x.node as usize / peers] += x.rank;
                }
            }
        })
        .connect_loop(cycle);

        input
    });

    {
        let graph = GraphMMap::new(&filename);

        let mut edges = Vec::new();
        for node in 0..graph.nodes() {
            if node % peers == index {
                for dst in graph.edges(node) {
                    edges.push((node as u32, *dst as u32));
                }
                if edges.len() > 100_000 {
                    input.send_at(0, edges.drain_temp());
                    root.step();
                }
            }
        }

        input.send_at(0, edges.drain_temp());
    }
    input.close();
    while root.step() { }

    if index == 0 { println!("elapsed: {}", time::precise_time_s() - start); }
}

    // .unary_notify(
    //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
    //     format!("Aggregation"),
    //     vec![],
    //     move |input, output, iterator| {
    //         while let Some((iter, data)) = input.pull() {
    //             iterator.notify_at(&iter);
    //             for (node, rank) in data.drain_temp() {
    //                 acc[node as usize / workers] += rank;
    //             }
    //         }
    //
    //         while let Some((item, _)) = iterator.next() {
    //
    //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
    //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
    //
    //             for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
    //             assert!(acc.len() == (1 + (nodes/workers)));
    //         }
    //     }
    // )
<commit_msg>test w/o sending any data (maybe reveals bug)<commit_after>extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate docopt;

use docopt::Docopt;

use std::thread;

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

use columnar::Columnar;

mod typedrw;
mod graphmap;
use graphmap::GraphMMap;

mod sorting;
use sorting::{SegmentList, radix_sort_32};

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      file containing list of host:port for workers
";

#[derive(Copy, Clone, Debug)]
struct NodeRank { node: u32, rank: f32, }
impl Columnar for NodeRank { type Stack = Vec<NodeRank>; }

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_spawn(communicators, source);
    }
    else if workers > 1 { pagerank_spawn(ProcessCommunicator::new_vector(workers), source); }
    else { pagerank_spawn(vec![ThreadCommunicator], source); };
}

fn pagerank_spawn<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank_thread(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

// returns [src/peers] degrees, (dst, deg) pairs, and a list of [src/peers] endpoints
fn transpose(mut edges: Vec<Vec<(u32, u32)>>, peers: usize, nodes: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let mut deg = vec![0; (nodes as usize / peers) + 1];
    for list in &edges {
        for &(s, _) in list {
            deg[s as usize / peers] += 1;
        }
    }

    // let start = time::precise_time_s();
    radix_sort_32(&mut edges, &mut Vec::new(), &|&(_,d)| d);
    // println!("sorted in {}s", time::precise_time_s() - start);

    let mut rev = Vec::<(u32,u32)>::with_capacity(deg.len());
    let mut trn = Vec::with_capacity(edges.len() * 1024);
    for list in edges {
        for (s,d) in list {
            let len = rev.len();
            if (len == 0) || (rev[len-1].0 < d) {
                rev.push((d, 0u32));
            }

            let len = rev.len();
            rev[len-1].1 += 1;
            trn.push(s / peers as u32);
        }
    }

    return (deg, rev, trn);
}

// pagerank dataflow graph has a set of edges as input, and a binary vertex that for each epoch of
// received edges initiates an iterative subcomputation to compute the pagerank.

fn pagerank_thread<C>(communicator: C, filename: String, _workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    let start = time::precise_time_s();

    let nodes = GraphMMap::new(&filename).nodes();

    let mut segments = SegmentList::new(1024); // list of edge segments

    let mut src = vec![];   // holds ranks
    let mut deg = vec![];   // holds source degrees
    let mut rev = vec![];   // holds (dst, deg) pairs
    let mut trn = vec![];   // holds transposed sources

    let mut input = root.subcomputation(|builder| {

        let (input, edges) = builder.new_input::<(u32, u32)>();
        let (cycle, ranks) = builder.loop_variable::<NodeRank>(RootTimestamp::new(20), Local(1));

        edges.binary_notify(&ranks,
                            Exchange::new(|x: &(u32,u32)| x.0 as u64),
                            Exchange::new(|x: &NodeRank| x.node as u64),
                            format!("pagerank"),
                            vec![RootTimestamp::new(0)],
                            move |input1, input2, output, notificator| {

            // receive incoming edges
            while let Some((_index, data)) = input1.pull() {
                segments.push(data.drain_temp());
            }

            while let Some((iter, _)) = notificator.next() {

                // if the very first iteration, prepare some stuff
                if iter.inner == 0 {
                    let (a, b, c) = transpose(segments.finalize(), peers, nodes);
                    deg = a; rev = b; trn = c;
                    src = vec![0.0f32; deg.len()];
                }

                println!("{:.3}\tworker {}: notify[{}] begin", time::precise_time_s() - start, index, iter.inner);

                for s in 0..src.len() { src[s] = 0.15 + 0.85 * src[s] / deg[s] as f32; }

                let mut trn_slice = &trn[..];
                let mut rev_slice = &rev[..];
                while rev_slice.len() > 0 {
                    // TODO: session should just flush...
                    // let mut session = output.session(&iter);
                    let next = std::cmp::min(200_000, rev_slice.len());
                    for &(dst, deg) in &rev_slice[..next] {
                        let mut accum = 0.0;
                        for &s in &trn_slice[..deg as usize] {
                            accum += src[s as usize];
                        }
                        trn_slice = &trn_slice[deg as usize..];
                        // session.give(NodeRank { node: dst, rank: accum });
                    }
                    rev_slice = &rev_slice[next..];
                }

                for s in &mut src { *s = 0.0; }

                println!("{:.3}\tworker {}: notify[{}] ended", time::precise_time_s() - start, index, iter.inner);
            }

            while let Some((iter, data)) = input2.pull() {
                notificator.notify_at(&iter);
                for x in data.drain_temp() {
                    src[x.node as usize / peers] += x.rank;
                }
            }
        })
        .connect_loop(cycle);

        input
    });

    {
        let graph = GraphMMap::new(&filename);

        let mut edges = Vec::new();
        for node in 0..graph.nodes() {
            if node % peers == index {
                for dst in graph.edges(node) {
                    edges.push((node as u32, *dst as u32));
                }
                if edges.len() > 100_000 {
                    input.send_at(0, edges.drain_temp());
                    root.step();
                }
            }
        }

        input.send_at(0, edges.drain_temp());
    }
    input.close();
    while root.step() { }

    if index == 0 { println!("elapsed: {}", time::precise_time_s() - start); }
}

    // .unary_notify(
    //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
    //     format!("Aggregation"),
    //     vec![],
    //     move |input, output, iterator| {
    //         while let Some((iter, data)) = input.pull() {
    //             iterator.notify_at(&iter);
    //             for (node, rank) in data.drain_temp() {
    //                 acc[node as usize / workers] += rank;
    //             }
    //         }
    //
    //         while let Some((item, _)) = iterator.next() {
    //
    //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
    //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
    //
    //             for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
    //             assert!(acc.len() == (1 + (nodes/workers)));
    //         }
    //     }
    // )
<|endoftext|>


<commit_before>extern crate ghqrs;
extern crate clap;

mod cli;

fn main() {
  let matches = cli::build_cli().get_matches();

  let exitcode = if let Some(ref s) = matches.subcommand_name() {
    let ref matches = matches.subcommand_matches(s).unwrap();
    match *s {
      "get" => {
        let projects = matches.values_of("project").unwrap().map(ToOwned::to_owned).collect();
        let pull = matches.is_present("pull");
        let depth =
          matches.value_of("depth").map(ToOwned::to_owned).map(|d| d.parse::<i32>().unwrap());
        ghqrs::command_get(projects, pull, depth)
      }
      "list" => {
        let exact = matches.is_present("exact");
        let format = matches.value_of("format").unwrap_or("default");
        let query = matches.value_of("query").map(ToOwned::to_owned);
        ghqrs::command_list(exact, format, query)
      }
      "root" => {
        let all = matches.is_present("all");
        ghqrs::command_root(all)
      }
      _ => unreachable!(),
    }
  } else {
    unreachable!()
  };
  std::process::exit(exitcode);
}
<commit_msg>simplify the procedure of pattern match<commit_after>extern crate ghqrs;
extern crate clap;

mod cli;

fn main() {
  let matches = cli::build_cli().get_matches();

  let exitcode = match matches.subcommand() {
    ("get", Some(m)) => {
      let projects = m.values_of("project").unwrap().map(ToOwned::to_owned).collect();
      let pull = m.is_present("pull");
      let depth = m.value_of("depth").map(|ref d| d.parse::<i32>().unwrap());
      ghqrs::command_get(projects, pull, depth)
    }
    ("list", Some(m)) => {
      let exact = m.is_present("exact");
      let format = m.value_of("format").unwrap_or("default");
      let query = m.value_of("query").map(ToOwned::to_owned);
      ghqrs::command_list(exact, format, query)
    }
    ("root", Some(m)) => {
      let all = m.is_present("all");
      ghqrs::command_root(all)
    }
    (_, _) => unreachable!(),
  };

  std::process::exit(exitcode);
}
<|endoftext|>


<commit_before>extern crate mqtt3;
extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_timer;
extern crate bytes;
#[macro_use]
extern crate slog;
extern crate slog_term;
#[macro_use]
extern crate quick_error;

pub mod error;
pub mod codec;
pub mod broker;
pub mod client;

use std::io;
use std::io::ErrorKind;
use std::time::Duration;

use mqtt3::*;
use tokio_core::reactor::{Core, Interval};
use tokio_core::net::TcpListener;
use tokio_io::AsyncRead;

use futures::stream::Stream;
use futures::Future;
use futures::sync::mpsc;

use slog::{Logger, Drain};

use client::Client;
use broker::Broker;
use codec::MqttCodec;
use error::Error;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let address = "0.0.0.0:1883".parse().unwrap();
    let logger = rumqttd_logger();

    info!(logger, "⚡   starting broker");

    let listener = TcpListener::bind(&address, &core.handle()).unwrap();

    let broker = Broker::new();
    info!(logger, "👂🏼   listening for connections");
    let welcomes = listener.incoming()
                           .and_then(|(socket, addr)| {
        let framed = socket.framed(MqttCodec);
        info!(logger, "🌟   new connection from {}", addr );
        let broker = broker.clone();

        // Creates a 'Self' from stream, whose error match to that of and_then's closure
        let handshake = framed.into_future()
                                  .map_err(|(err, _)| err) // for accept errors, get error and discard the stream
                                  .and_then(move |(packet,framed)| { // only accepted connections from here

                let broker = broker.clone();
                if let Some(Packet::Connect(c)) = packet {
                    // TODO: Do connect packet validation here
                    let (tx, rx) = mpsc::channel::<Packet>(100);

                    let client = Client::new(&c.client_id, addr, tx.clone());
                    broker.add_client(client.clone());

                    Ok((framed, client, rx))
                } else {
                    error!(broker.logger, "invalid handshake packet");
                    Err(io::Error::new(io::ErrorKind::Other, "Invalid Handshake Packet"))
                }
            });

        handshake

    });

    let server = welcomes.map(|w| Some(w))
                         .or_else(|e| {
                                      error!(logger, "{:?}", e);
                                      Ok::<_, ()>(None)
                                  })
                         .for_each(|handshake| {

        let broker = broker.clone();
        let broker2 = broker.clone();

        // handle each connections n/w send and recv here
        if let Some((framed, client, rx)) = handshake {
            let id = client.id.clone();
            let (sender, receiver) = framed.split();

            let connack = Packet::Connack(Connack {
                                              session_present: false,
                                              code: ConnectReturnCode::Accepted,
                                          });

            let _ = client.send(connack);

            // current connections incoming n/w packets
            let rx_future = receiver.for_each(move |msg| {
                match msg {
                    Packet::Publish(p) => broker.handle_publish(p, &client),
                    Packet::Subscribe(s) => broker.handle_subscribe(s, &client),
                    Packet::Puback(pkid) => broker.handle_puback(pkid, &client),
                    Packet::Pubrec(pkid) => broker.handle_pubrec(pkid, &client),
                    Packet::Pubrel(pkid) => broker.handle_pubrel(pkid, &client),
                    Packet::Pubcomp(pkid) => broker.handle_pubcomp(pkid, &client),
                    Packet::Pingreq => broker.handle_pingreq(&client),
                    _ => panic!("Incoming Misc: {:?}", msg),
                }
                Ok(())
            }).then(move |_| {
                Ok::<_, ()>(())
            });

            let interval = Interval::new(Duration::new(5, 0), &handle).unwrap();

            let timer_future =
                interval.for_each(|_| { return Err(io::Error::new(ErrorKind::Other, "Ping Timer Error")); })
                        .then(|_| Ok(()));

            let rx_future = timer_future.select(rx_future);

            // current connections outgoing n/w packets
            let tx_future = rx.map_err(|_| Error::Other)
                              .map(|r| match r {
                                       Packet::Publish(p) => Packet::Publish(p),
                                       Packet::Connack(c) => Packet::Connack(c),
                                       Packet::Suback(sa) => Packet::Suback(sa),
                                       Packet::Puback(pa) => Packet::Puback(pa),
                                       Packet::Pubrec(prec) => Packet::Pubrec(prec),
                                       Packet::Pubrel(prel) => Packet::Pubrel(prel),
                                       Packet::Pubcomp(pc) => Packet::Pubcomp(pc),
                                       Packet::Pingresp => Packet::Pingresp,
                                       _ => panic!("Outgoing Misc: {:?}", r),
                                   })
                              .forward(sender)
                              .then(move |_| -> ::std::result::Result<(), ()> {
                                        // forward error. n/w disconnections.
                                        Ok(())
                                    });

            let rx_future = rx_future.then(|_| Ok(()));

            let connection = rx_future.select(tx_future);
            let connection = connection.then(move |_| {
                                                 error!(broker2.logger, "disconnecting client: {:?}", id );
                                                 broker2.remove_client(&id);
                                                 Ok(())
                                             });

            handle.spawn(connection);
        }
        Ok(())
    });

    core.run(server).unwrap();
}

fn rumqttd_logger() -> Logger {
    use std::sync::Mutex;

    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = Mutex::new(drain).fuse();
    Logger::root(drain, o!("rumqttd" => env!("CARGO_PKG_VERSION")))
}
<commit_msg>changing some names<commit_after>extern crate mqtt3;
extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_timer;
extern crate bytes;
#[macro_use]
extern crate slog;
extern crate slog_term;
#[macro_use]
extern crate quick_error;

pub mod error;
pub mod codec;
pub mod broker;
pub mod client;

use std::io;
use std::io::ErrorKind;
use std::time::Duration;

use mqtt3::*;
use tokio_core::reactor::{Core, Interval};
use tokio_core::net::TcpListener;
use tokio_io::AsyncRead;

use futures::stream::Stream;
use futures::Future;
use futures::sync::mpsc;

use slog::{Logger, Drain};

use client::Client;
use broker::Broker;
use codec::MqttCodec;
use error::Error;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let address = "0.0.0.0:1883".parse().unwrap();
    let logger = rumqttd_logger();

    info!(logger, "⚡   starting broker");

    let listener = TcpListener::bind(&address, &core.handle()).unwrap();

    let broker = Broker::new();
    info!(logger, "👂🏼   listening for connections");
    let connections = listener.incoming()
                           .and_then(|(socket, addr)| {
        let framed = socket.framed(MqttCodec);
        info!(logger, "🌟   new connection from {}", addr );
        let broker = broker.clone();

        // Creates a 'Self' from stream, whose error match to that of and_then's closure
        let handshake = framed.into_future()
                                  .map_err(|(err, _)| err) // for accept errors, get error and discard the stream
                                  .and_then(move |(packet,framed)| { // only accepted connections from here

                let broker = broker.clone();
                if let Some(Packet::Connect(c)) = packet {
                    // TODO: Do connect packet validation here
                    let (tx, rx) = mpsc::channel::<Packet>(100);

                    let client = Client::new(&c.client_id, addr, tx.clone());
                    broker.add_client(client.clone());

                    Ok((framed, client, rx))
                } else {
                    error!(broker.logger, "invalid handshake packet");
                    Err(io::Error::new(io::ErrorKind::Other, "Invalid Handshake Packet"))
                }
        });

        handshake

    });

    let mqtt = connections.map(|w| Some(w))
                         .or_else(|e| {
                                      error!(logger, "{:?}", e);
                                      Ok::<_, ()>(None)
                                  })
                         .for_each(|handshake| {

        let broker = broker.clone();
        let broker2 = broker.clone();

        // handle each connections n/w send and recv here
        if let Some((framed, client, rx)) = handshake {
            let id = client.id.clone();
            let (sender, receiver) = framed.split();

            let connack = Packet::Connack(Connack {
                                              session_present: false,
                                              code: ConnectReturnCode::Accepted,
                                          });

            let _ = client.send(connack);

            // current connections incoming n/w packets
            let rx_future = receiver.for_each(move |msg| {
                match msg {
                    Packet::Publish(p) => broker.handle_publish(p, &client),
                    Packet::Subscribe(s) => broker.handle_subscribe(s, &client),
                    Packet::Puback(pkid) => broker.handle_puback(pkid, &client),
                    Packet::Pubrec(pkid) => broker.handle_pubrec(pkid, &client),
                    Packet::Pubrel(pkid) => broker.handle_pubrel(pkid, &client),
                    Packet::Pubcomp(pkid) => broker.handle_pubcomp(pkid, &client),
                    Packet::Pingreq => broker.handle_pingreq(&client),
                    _ => panic!("Incoming Misc: {:?}", msg),
                }
                Ok(())
            }).then(move |_| {
                Ok::<_, ()>(())
            });

            let interval = Interval::new(Duration::new(5, 0), &handle).unwrap();

            let timer_future =
                interval.for_each(|_| { return Err(io::Error::new(ErrorKind::Other, "Ping Timer Error")); })
                        .then(|_| Ok(()));

            let rx_future = timer_future.select(rx_future);

            // current connections outgoing n/w packets
            let tx_future = rx.map_err(|_| Error::Other)
                              .map(|r| match r {
                                       Packet::Publish(p) => Packet::Publish(p),
                                       Packet::Connack(c) => Packet::Connack(c),
                                       Packet::Suback(sa) => Packet::Suback(sa),
                                       Packet::Puback(pa) => Packet::Puback(pa),
                                       Packet::Pubrec(prec) => Packet::Pubrec(prec),
                                       Packet::Pubrel(prel) => Packet::Pubrel(prel),
                                       Packet::Pubcomp(pc) => Packet::Pubcomp(pc),
                                       Packet::Pingresp => Packet::Pingresp,
                                       _ => panic!("Outgoing Misc: {:?}", r),
                                   })
                              .forward(sender)
                              .then(move |_| -> ::std::result::Result<(), ()> {
                                        // forward error. n/w disconnections.
                                        Ok(())
                                    });

            let rx_future = rx_future.then(|_| Ok(()));

            let connection = rx_future.select(tx_future);
            let connection = connection.then(move |_| {
                                                 error!(broker2.logger, "disconnecting client: {:?}", id );
                                                 broker2.remove_client(&id);
                                                 Ok(())
                                             });

            handle.spawn(connection);
        }
        Ok(())
    });

    core.run(mqtt).unwrap();
}

fn rumqttd_logger() -> Logger {
    use std::sync::Mutex;

    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = Mutex::new(drain).fuse();
    Logger::root(drain, o!("rumqttd" => env!("CARGO_PKG_VERSION")))
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate docopt;
extern crate mazes;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use docopt::Docopt;

use mazes::squaregrid::{CoordinateSmallVec, GridCoordinate, GridDisplay, SquareGrid};
use mazes::generators;
use mazes::renderers;
use mazes::pathing;

const USAGE: &'static str = "Mazes

Usage:
    mazes_driver -h | --help
    mazes_driver [--grid-size=<n>]
    mazes_driver render (binary|sidewinder) [text --text-out=<path> (--show-distances|--show-path) (--find-furthest-point-from-start|--path-end-x=<e1> --path-end-y=<e2>) (--path-start-x=<x> --path-start-y=<y>)] [image --image-out=<path> --cell-pixels=<n> --screen-view] [--grid-size=<n>]

Options:
    -h --help           Show this screen.
    --grid-size=<n>     The grid size is n * n [default: 20].
    --text-out=<path>   Output file path for a textual rendering of a maze.
    --path-start-x=<x>
    --path-start-y=<y>
    --end-point-x=<e1>
    --end-point-y=<e2>
    --furthest-point    Show the furthest (points) from the path-start-x/path-start-y coordinate
    --image-out=<path>  Output file path for an image rendering of a maze.
    --cell-pixels=<n>   Pixel count to render one cell wall in a maze [default: 10] max 255.
    --screen-view       When rendering to an image and saving to a file, also show the image on the screen.
";
#[derive(RustcDecodable, Debug)]
struct MazeArgs {
    flag_grid_size: u32,
    cmd_render: bool,
    cmd_binary: bool,
    cmd_sidewinder: bool,
    cmd_text: bool,
    flag_text_out: String,
    cmd_image: bool,
    flag_image_out: String,
    flag_cell_pixels: u8,
    flag_screen_view: bool,
    flag_show_distances: bool,
    flag_show_path: bool,
    flag_find_furthest_point_from_start: bool,
    flag_path_start_x: Option<u32>,
    flag_path_start_y: Option<u32>,
    flag_end_point_x: Option<u32>,
    flag_end_point_y: Option<u32>,
}

fn main() {

    let args: MazeArgs = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());

    let grid_size = args.flag_grid_size;
    let any_render_option = args.cmd_text || args.cmd_image;

    // Do whatever defaults we want if not given a specific 'render' command
    let do_image_render = !args.cmd_render || args.cmd_image ||
                          (!any_render_option && grid_size >= 25);
    let do_text_render = args.cmd_render &&
                         (args.cmd_text || (!any_render_option && grid_size < 25));

    let mut maze_grid = SquareGrid::<u32>::new(grid_size);

    generate_maze_on_grid(&mut maze_grid, &args);

    if do_text_render {

        set_maze_griddisplay(&mut maze_grid, &args);

        if args.flag_text_out.is_empty() {
            println!("{}", maze_grid);
        } else {
            write_text_to_file(&format!("{}", maze_grid), &args.flag_text_out)
                .expect(&format!("Failed to write maze to text file {}", args.flag_text_out));
        }
    }

    if do_image_render {
        let is_image_path_set = !args.flag_image_out.is_empty();
        let out_image_path = if is_image_path_set {
            Some(Path::new(&args.flag_image_out))
        } else {
            None
        };
        let render_opts = renderers::RenderOptions::new(args.flag_screen_view ||
                                                        !is_image_path_set,
                                                        out_image_path,
                                                        args.flag_cell_pixels);
        renderers::render_square_grid(&maze_grid, &render_opts);
    }
}

fn generate_maze_on_grid(mut maze_grid: &mut SquareGrid<u32>, maze_args: &MazeArgs) {

    if maze_args.cmd_render {
        if maze_args.cmd_binary {
            generators::binary_tree(&mut maze_grid);
        }
        if maze_args.cmd_sidewinder {
            generators::sidewinder(&mut maze_grid);
        }
    } else {
        generators::sidewinder(&mut maze_grid);
    }
}

fn set_maze_griddisplay(maze_grid: &mut SquareGrid<u32>, maze_args: &MazeArgs) {

    if let (Some(x), Some(y)) = (maze_args.flag_path_start_x, maze_args.flag_path_start_y) {

        let distances = Rc::new(pathing::DijkstraDistances::<u32>::new(&maze_grid, GridCoordinate::new(x, y))
                .unwrap_or_else(|| exit_with_msg("Provided invalid start coordinate from which to show path distances.")));

        if let (Some(end_x), Some(end_y)) = (maze_args.flag_end_point_x, maze_args.flag_end_point_y) {

            // Given a start and end point - show the shortest path between these two points
            let path_opt = pathing::shortest_path(&maze_grid, &distances, GridCoordinate::new(end_x, end_y));
            if let Some(path) = path_opt {

                let display_path = Rc::new(pathing::PathDisplay::new(&path));
                maze_grid.set_grid_display(Some(display_path as Rc<GridDisplay>));
            } else {

                let start_points = as_coordinate_smallvec(GridCoordinate::new(x, y));
                let end_points = as_coordinate_smallvec(GridCoordinate::new(end_x, end_y));
                let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(start_points, end_points));
                maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
            }
        }
        else if maze_args.flag_find_furthest_point_from_start {

            // Given a start point and asked to show furthest point away from it - find an end point
            let start_points = as_coordinate_smallvec(GridCoordinate::new(x, y));
            let end_points = pathing::furthest_points_on_grid(&maze_grid, &distances);
            let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(start_points, end_points));
            maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));

        } else {

            // Only given a start point - show the distances to everywhere else
            maze_grid.set_grid_display(Some(distances.clone() as Rc<GridDisplay>));
        }

    } else if maze_args.flag_find_furthest_point_from_start {

        // Not given a start point. Asking for the furthest point means find 2 arbitrary places that are max distance from one another.
        let longest_path: Vec<GridCoordinate> = pathing::dijkstra_longest_path::<_, u32>(&maze_grid).expect("Not a perfect maze, no longest path exists.");
        let start = longest_path.first().unwrap();
        let end = longest_path.last().unwrap();
        let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(as_coordinate_smallvec(*start),
                                                                                as_coordinate_smallvec(*end)));
        maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
    }
}

fn as_coordinate_smallvec(coord: GridCoordinate) -> CoordinateSmallVec {
    [coord].into_iter().cloned().collect::<CoordinateSmallVec>()
}

fn write_text_to_file(data: &str, file_name: &str) -> io::Result<()> {
    let mut f = try!(File::create(file_name));
    try!(f.write_all(data.as_bytes()));
    Ok(())
}

fn exit_with_msg(e: &str) -> ! {
    writeln!(&mut io::stderr(), "{}", e).expect(format!("Failed to print error: {}", e).as_str());
    exit(1);
}
<commit_msg>Refactored grid display setup.<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate docopt;
extern crate mazes;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use docopt::Docopt;

use mazes::squaregrid::{CoordinateSmallVec, GridCoordinate, GridDisplay, SquareGrid};
use mazes::generators;
use mazes::renderers;
use mazes::pathing;

const USAGE: &'static str = "Mazes

Usage:
    mazes_driver -h | --help
    mazes_driver [--grid-size=<n>]
    mazes_driver render (binary|sidewinder) [text --text-out=<path> (--show-distances|--show-path) (--find-furthest-point-from-start|--path-end-x=<e1> --path-end-y=<e2>) (--path-start-x=<x> --path-start-y=<y>)] [image --image-out=<path> --cell-pixels=<n> --screen-view] [--grid-size=<n>]

Options:
    -h --help           Show this screen.
    --grid-size=<n>     The grid size is n * n [default: 20].
    --text-out=<path>   Output file path for a textual rendering of a maze.
    --path-start-x=<x>
    --path-start-y=<y>
    --end-point-x=<e1>
    --end-point-y=<e2>
    --furthest-point    Show the furthest (points) from the path-start-x/path-start-y coordinate
    --image-out=<path>  Output file path for an image rendering of a maze.
    --cell-pixels=<n>   Pixel count to render one cell wall in a maze [default: 10] max 255.
    --screen-view       When rendering to an image and saving to a file, also show the image on the screen.
";
#[derive(RustcDecodable, Debug)]
struct MazeArgs {
    flag_grid_size: u32,
    cmd_render: bool,
    cmd_binary: bool,
    cmd_sidewinder: bool,
    cmd_text: bool,
    flag_text_out: String,
    cmd_image: bool,
    flag_image_out: String,
    flag_cell_pixels: u8,
    flag_screen_view: bool,
    flag_show_distances: bool,
    flag_show_path: bool,
    flag_find_furthest_point_from_start: bool,
    flag_path_start_x: Option<u32>,
    flag_path_start_y: Option<u32>,
    flag_end_point_x: Option<u32>,
    flag_end_point_y: Option<u32>,
}

fn main() {

    let args: MazeArgs = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());

    let grid_size = args.flag_grid_size;
    let any_render_option = args.cmd_text || args.cmd_image;

    // Do whatever defaults we want if not given a specific 'render' command
    let do_image_render = !args.cmd_render || args.cmd_image ||
                          (!any_render_option && grid_size >= 25);
    let do_text_render = args.cmd_render &&
                         (args.cmd_text || (!any_render_option && grid_size < 25));

    let mut maze_grid = SquareGrid::<u32>::new(grid_size);

    generate_maze_on_grid(&mut maze_grid, &args);

    if do_text_render {

        set_maze_griddisplay(&mut maze_grid, &args);

        if args.flag_text_out.is_empty() {
            println!("{}", maze_grid);
        } else {
            write_text_to_file(&format!("{}", maze_grid), &args.flag_text_out)
                .expect(&format!("Failed to write maze to text file {}", args.flag_text_out));
        }
    }

    if do_image_render {
        let is_image_path_set = !args.flag_image_out.is_empty();
        let out_image_path = if is_image_path_set {
            Some(Path::new(&args.flag_image_out))
        } else {
            None
        };
        let render_opts = renderers::RenderOptions::new(args.flag_screen_view ||
                                                        !is_image_path_set,
                                                        out_image_path,
                                                        args.flag_cell_pixels);
        renderers::render_square_grid(&maze_grid, &render_opts);
    }
}

fn generate_maze_on_grid(mut maze_grid: &mut SquareGrid<u32>, maze_args: &MazeArgs) {

    if maze_args.cmd_render {
        if maze_args.cmd_binary {
            generators::binary_tree(&mut maze_grid);
        }
        if maze_args.cmd_sidewinder {
            generators::sidewinder(&mut maze_grid);
        }
    } else {
        generators::sidewinder(&mut maze_grid);
    }
}

/// Wade through all the maze driver argments and decide how the grid should have cells displayed as text
/// - Nothing in the cells
/// - Start and End point markers if supplied else nothing
/// - Distances from some start cell to all other cells
/// - Shortest path between a start and end point
/// Default to finding the start and end point of the longest path in the maze if required to show a path
/// or asked to find the point furthest away from a start point
/// Use the start of the longest path if asked to show distances to all other cells but no start provided
fn set_maze_griddisplay(maze_grid: &mut SquareGrid<u32>, maze_args: &MazeArgs) {

    let longest_path: Vec<GridCoordinate> = pathing::dijkstra_longest_path::<_, u32>(&maze_grid)
                                                     .expect("Not a perfect maze, no longest path exists.");
    fn get_start(maze_args: &MazeArgs, longest_path: &Vec<GridCoordinate>) -> Option<(u32, u32)> {

        if let (Some(start_x), Some(start_y)) = (maze_args.flag_path_start_x, maze_args.flag_path_start_y) {
            Some((start_x, start_y))

        } else if maze_args.flag_find_furthest_point_from_start || maze_args.flag_show_distances || maze_args.flag_show_path {

            // We do not have a start so make one up
            let start = longest_path.first().unwrap();
            Some((start.x, start.y))
        } else {
            None
        }
    }
    fn get_end(maze_args: &MazeArgs, longest_path: &Vec<GridCoordinate>) -> Option<(u32, u32)> {

        if let (Some(end_x), Some(end_y)) = (maze_args.flag_end_point_x, maze_args.flag_end_point_y) {
            Some((end_x, end_y))

        } else if maze_args.flag_show_path || maze_args.flag_find_furthest_point_from_start {

            // We do not have an end but we need to make one up
            let end = longest_path.last().unwrap();
            Some((end.x, end.y))
        } else {
            None
        }
    }

    let start_opt = get_start(&maze_args, &longest_path);
    let end_opt = get_end(&maze_args, &longest_path);

    if maze_args.flag_show_distances || maze_args.flag_show_path {

        let (start_x, start_y) = start_opt.unwrap();
        let distances = Rc::new(pathing::DijkstraDistances::<u32>::new(&maze_grid, GridCoordinate::new(start_x, start_y))
                .unwrap_or_else(|| exit_with_msg("Provided invalid start coordinate from which to show path distances.")));

        if maze_args.flag_show_distances {

            // Ignore any endpoint or furthest point request (docopt cannot nest these mutual exclusions?)
            // Show the distances to everywhere else
            maze_grid.set_grid_display(Some(distances.clone() as Rc<GridDisplay>));

        } else if maze_args.flag_show_path {

            // We need a start and an end
            let (end_x, end_y) = end_opt.unwrap();

            // Given a start and end point - show the shortest path between these two points
            let path_opt = pathing::shortest_path(&maze_grid, &distances, GridCoordinate::new(end_x, end_y));

            if let Some(path) = path_opt {
                let display_path = Rc::new(pathing::PathDisplay::new(&path));
                maze_grid.set_grid_display(Some(display_path as Rc<GridDisplay>));
            } else {
                // Somehow there is no route, maze generation failed to make a perfect maze
                let start_points = as_coordinate_smallvec(GridCoordinate::new(start_x, start_y));
                let end_points = as_coordinate_smallvec(GridCoordinate::new(end_x, end_y));
                let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(start_points, end_points));
                maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
            }
        }
    } else {

        // Show the start and end points that exist.
        let start_points =
            if let Some((start_x, start_y)) = start_opt {
                as_coordinate_smallvec(GridCoordinate::new(start_x, start_y))
            } else {
                CoordinateSmallVec::new()
            };
        let end_points =
            if let Some((end_x, end_y)) = end_opt {
                as_coordinate_smallvec(GridCoordinate::new(end_x, end_y))
            } else {
                CoordinateSmallVec::new()
            };
        let display_start_end_points = Rc::new(pathing::StartEndPointsDisplay::new(start_points, end_points));
        maze_grid.set_grid_display(Some(display_start_end_points as Rc<GridDisplay>));
    }
}

fn as_coordinate_smallvec(coord: GridCoordinate) -> CoordinateSmallVec {
    [coord].into_iter().cloned().collect::<CoordinateSmallVec>()
}

fn write_text_to_file(data: &str, file_name: &str) -> io::Result<()> {
    let mut f = try!(File::create(file_name));
    try!(f.write_all(data.as_bytes()));
    Ok(())
}

fn exit_with_msg(e: &str) -> ! {
    writeln!(&mut io::stderr(), "{}", e).expect(format!("Failed to print error: {}", e).as_str());
    exit(1);
}
<|endoftext|>


<commit_before>extern crate ultra;

fn main() {
    println!("Hello, World War II");
}
<commit_msg>Add basic enciphering functionality to CLI<commit_after>extern crate ultra;

use std::io::{stdin, stdout, Write};
use ultra::enigma::Enigma;

fn main() {
    let mut msg = String::new();
    print!("Message to encrypt: ");
    stdout().flush().unwrap();
    stdin().read_line(&mut msg).unwrap();
    let msg = msg.trim_right();

    if !msg.is_empty() {
        let mut enigma = Enigma::new("123", "AAA", "AAA", 'B', "");
        println!("Ciphertext: {}", enigma.encrypt(msg))
    }
}
<|endoftext|>


<commit_before>extern crate iron;
#[macro_use]
extern crate router;
extern crate staticfile;
extern crate mount;
extern crate urlencoded;
extern crate rustc_serialize;
extern crate html5ever;
extern crate regex;
extern crate uuid;

use std::net::SocketAddrV4;
use std::net::Ipv4Addr;
use std::path::Path;
use iron::prelude::*;
use iron::status;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::Mime;
use staticfile::Static;
use mount::Mount;
use router::{Router};
use urlencoded::UrlEncodedQuery;
use urlencoded::UrlEncodedBody;
use std::str::FromStr;

#[macro_use]
extern crate string_cache;

extern crate pink_spider;

use pink_spider::error::Error;
use pink_spider::scraper::extract;
use pink_spider::model::{Track, Entry, Provider};
use rustc_serialize::json::{ToJson, Json};

static JSON: &'static str = "application/json";

pub fn index_entries(req: &mut Request) -> IronResult<Response> {
    let json_type = Header(ContentType(Mime::from_str(JSON).ok().unwrap()));
    let (page, per_page) = pagination_params(req);
    let entries          = Entry::find(page, per_page);
    let json_obj: Json   = entries.to_json();
    let json_str: String = json_obj.to_string();
    Ok(Response::with((status::Ok, json_type, json_str)))
}

pub fn index_tracks(req: &mut Request) -> IronResult<Response> {
    let json_type = Header(ContentType(Mime::from_str(JSON).ok().unwrap()));
    let (page, per_page) = pagination_params(req);
    let tracks  = Track::find(page, per_page);
    let json_obj: Json   = tracks.to_json();
    let json_str: String = json_obj.to_string();
    Ok(Response::with((status::Ok, json_type, json_str)))
}

pub fn playlistify(req: &mut Request) -> IronResult<Response> {
    let json_type = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
    match req.get_ref::<UrlEncodedQuery>() {
        Ok(ref params) => {
            match params.get("url") {
                Some(url) => {
                    let defaults = &vec!("false".to_string());
                    let force    = params.get("force").unwrap_or(defaults);
                    match find_or_playlistify_entry(&url[0], force.len() > 0 && &force[0] == "true") {
                        Ok(entry) => {
                            let json_obj: Json   = entry.to_json();
                            let json_str: String = json_obj.to_string();
                            Ok(Response::with((status::Ok, json_type, json_str)))
                        },
                        Err(e) => Ok(e.as_response())
                    }
                },
                None => Ok(Error::BadRequest.as_response())
            }
        }
        Err(_) => Ok(Error::BadRequest.as_response())
    }
}

pub fn find_or_playlistify_entry(url: &str, force: bool) -> Result<Entry, Error> {
    match Entry::find_by_url(url) {
        Ok(entry) => {
            println!("Get entry from database cache: {}", url);
            if force {
                println!("Update entry: {}", url);
                let entry = try!(playlistify_entry(entry));
                Ok(entry)
            } else {
                Ok(entry)
            }
        },
        Err(_) => {
            let entry = try!(Entry::create_by_url(url.to_string()));
            let entry = try!(playlistify_entry(entry));
            println!("Create new entry to database cache: {}", url);
            Ok(entry)
        },
    }
}

pub fn playlistify_entry(entry: Entry) -> Result<Entry, Error> {
    let mut e = entry.clone();
    let product = try!(extract(&entry.url));
    match product.og_obj {
        Some(og_obj) => {
            e.title       = Some(og_obj.title);
            e.description = og_obj.description;
            e.locale      = og_obj.locale;
            e.visual_url  = og_obj.images.first().map(|i| i.url.clone());
        },
        None => (),
    }
    for t in product.tracks {
        let track = try!(Track::find_or_create(t.provider,
                                               t.title,
                                               t.url,
                                               t.identifier));
        match entry.tracks.iter().find(|&t| t.id == track.id) {
            Some(_) => (),
            None    => e.add_track(track.clone())
        }
    }
    try!(e.save());
    Ok(e)
}

pub fn show_track(req: &mut Request) -> IronResult<Response> {
    let ref track_id = req.extensions.get::<Router>().unwrap()
                          .find("track_id").unwrap();
    let json_type = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
    match Track::find_by_id(track_id) {
        Ok(track) => {
            Ok(Response::with((status::Ok,
                               json_type,
                               track.to_json().to_string())))
        },
        Err(e) => Ok(e.as_response())
    }
}

pub fn show_track_by_provider_id(req: &mut Request) -> IronResult<Response> {
    let provider   = req.extensions.get::<Router>().unwrap().find("provider").unwrap();
    let identifier = req.extensions.get::<Router>().unwrap().find("id").unwrap();
    let json_type  = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
    let p = &Provider::new(provider.to_string());
    match Track::find_by(p, identifier) {
        Ok(track) => {
            Ok(Response::with((status::Ok,
                               json_type,
                               track.to_json().to_string())))
        },
        Err(e) => Ok(e.as_response())
    }
}

pub fn update_track(req: &mut Request) -> IronResult<Response> {
    let json_type = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
    match Track::find_by_id(&query_as_string(req, "track_id")) {
        Ok(mut track) => {
            match param_as_string(req, "title") {
                Some(title) => track.title = title,
                None        => println!("no title")
            }
            match param_as_string(req, "url") {
                Some(url) => track.url = url,
                None      => println!("no url")
            }
            match track.save() {
                Ok(_) => Ok(Response::with((status::Ok,
                                         json_type,
                                         track.to_json().to_string()))),
                Err(e) =>  Ok(e.as_response())
            }
        },
        Err(e) =>  {
            Ok(e.as_response())
        }
    }
}

fn param_as_string(req: &mut Request, key: &str) -> Option<String> {
    match req.get_ref::<UrlEncodedBody>() {
        Ok(ref params) => match params.get(key) {
            Some(val) => Some(val[0].clone()),
            None      => None
        },
        Err(_) => None
    }
}

fn query_as_string(req: &mut Request, key: &str) -> String {
    return req.extensions.get::<Router>().unwrap()
        .find(key).unwrap().to_string();
}

fn pagination_params(req: &mut Request) -> (i64, i64) {
    match req.get_ref::<UrlEncodedQuery>() {
        Ok(ref params) =>
            (params.get("page").unwrap()[0].to_string().parse::<i64>().unwrap(),
             params.get("per_page").unwrap()[0].to_string().parse::<i64>().unwrap()),
        Err(_) =>
            (0, 10)
    }
}

pub fn main() {
    let path = Path::new("public");
    let mut mount = Mount::new();
    mount.mount("/web/", Static::new(Path::new(path)));
    let router = router!(
                         playlistify: get  "/playlistify"          => playlistify,
                          show_track: get  "/tracks/:track_id"     => show_track,
                        update_track: post "/tracks/:track_id"     => update_track,
           show_track_by_provider_id: get  "/tracks/:provider/:id" => show_track_by_provider_id,
                       index_entries: get  "/entries"              => index_entries,
                        index_tracks: get  "/tracks"               => index_tracks,
                                 web: get  "/*"                    => mount,
    );
    let port_str = match std::env::var("PORT") {
        Ok(n)    => n,
        Err(_) => "8080".to_string()
    };
    let port: u16 = match port_str.trim().parse() {
        Ok(n) => n,
        Err(_) => {
            println!("Faild to parse port");
            return;
        }
    };
    println!("PORT {}", port_str);
    let ip = Ipv4Addr::new(0, 0, 0, 0);
    Iron::new(router).http(SocketAddrV4::new(ip, port)).unwrap();
}
<commit_msg>Refactoring: extract application_json method<commit_after>extern crate iron;
#[macro_use]
extern crate router;
extern crate staticfile;
extern crate mount;
extern crate urlencoded;
extern crate rustc_serialize;
extern crate html5ever;
extern crate regex;
extern crate uuid;

use std::net::SocketAddrV4;
use std::net::Ipv4Addr;
use std::path::Path;
use iron::prelude::*;
use iron::status;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::Mime;
use staticfile::Static;
use mount::Mount;
use router::{Router};
use urlencoded::UrlEncodedQuery;
use urlencoded::UrlEncodedBody;
use std::str::FromStr;

#[macro_use]
extern crate string_cache;
extern crate pink_spider;

use pink_spider::error::Error;
use pink_spider::scraper::extract;
use pink_spider::model::{Track, Entry, Provider};
use rustc_serialize::json::{ToJson, Json};

pub fn index_entries(req: &mut Request) -> IronResult<Response> {
    let (page, per_page) = pagination_params(req);
    let entries          = Entry::find(page, per_page);
    let json_obj: Json   = entries.to_json();
    let json_str: String = json_obj.to_string();
    Ok(Response::with((status::Ok, application_json(), json_str)))
}

pub fn index_tracks(req: &mut Request) -> IronResult<Response> {
    let (page, per_page) = pagination_params(req);
    let tracks  = Track::find(page, per_page);
    let json_obj: Json   = tracks.to_json();
    let json_str: String = json_obj.to_string();
    Ok(Response::with((status::Ok, application_json(), json_str)))
}

pub fn playlistify(req: &mut Request) -> IronResult<Response> {
    match req.get_ref::<UrlEncodedQuery>() {
        Ok(ref params) => {
            match params.get("url") {
                Some(url) => {
                    let defaults = &vec!("false".to_string());
                    let force    = params.get("force").unwrap_or(defaults);
                    match find_or_playlistify_entry(&url[0], force.len() > 0 && &force[0] == "true") {
                        Ok(entry) => {
                            let json_obj: Json   = entry.to_json();
                            let json_str: String = json_obj.to_string();
                            Ok(Response::with((status::Ok, application_json(), json_str)))
                        },
                        Err(e) => Ok(e.as_response())
                    }
                },
                None => Ok(Error::BadRequest.as_response())
            }
        }
        Err(_) => Ok(Error::BadRequest.as_response())
    }
}

pub fn find_or_playlistify_entry(url: &str, force: bool) -> Result<Entry, Error> {
    match Entry::find_by_url(url) {
        Ok(entry) => {
            println!("Get entry from database cache: {}", url);
            if force {
                println!("Update entry: {}", url);
                let entry = try!(playlistify_entry(entry));
                Ok(entry)
            } else {
                Ok(entry)
            }
        },
        Err(_) => {
            let entry = try!(Entry::create_by_url(url.to_string()));
            let entry = try!(playlistify_entry(entry));
            println!("Create new entry to database cache: {}", url);
            Ok(entry)
        },
    }
}

pub fn playlistify_entry(entry: Entry) -> Result<Entry, Error> {
    let mut e = entry.clone();
    let product = try!(extract(&entry.url));
    match product.og_obj {
        Some(og_obj) => {
            e.title       = Some(og_obj.title);
            e.description = og_obj.description;
            e.locale      = og_obj.locale;
            e.visual_url  = og_obj.images.first().map(|i| i.url.clone());
        },
        None => (),
    }
    for t in product.tracks {
        let track = try!(Track::find_or_create(t.provider,
                                               t.title,
                                               t.url,
                                               t.identifier));
        match entry.tracks.iter().find(|&t| t.id == track.id) {
            Some(_) => (),
            None    => e.add_track(track.clone())
        }
    }
    try!(e.save());
    Ok(e)
}

pub fn show_track(req: &mut Request) -> IronResult<Response> {
    let ref track_id = req.extensions.get::<Router>().unwrap()
                          .find("track_id").unwrap();
    match Track::find_by_id(track_id) {
        Ok(track) => {
            Ok(Response::with((status::Ok,
                               application_json(),
                               track.to_json().to_string())))
        },
        Err(e) => Ok(e.as_response())
    }
}

pub fn show_track_by_provider_id(req: &mut Request) -> IronResult<Response> {
    let provider   = req.extensions.get::<Router>().unwrap().find("provider").unwrap();
    let identifier = req.extensions.get::<Router>().unwrap().find("id").unwrap();
    let p = &Provider::new(provider.to_string());
    match Track::find_by(p, identifier) {
        Ok(track) => {
            Ok(Response::with((status::Ok,
                               application_json(),
                               track.to_json().to_string())))
        },
        Err(e) => Ok(e.as_response())
    }
}

pub fn update_track(req: &mut Request) -> IronResult<Response> {
    match Track::find_by_id(&query_as_string(req, "track_id")) {
        Ok(mut track) => {
            match param_as_string(req, "title") {
                Some(title) => track.title = title,
                None        => println!("no title")
            }
            match param_as_string(req, "url") {
                Some(url) => track.url = url,
                None      => println!("no url")
            }
            match track.save() {
                Ok(_) => Ok(Response::with((status::Ok,
                                         application_json(),
                                         track.to_json().to_string()))),
                Err(e) =>  Ok(e.as_response())
            }
        },
        Err(e) =>  {
            Ok(e.as_response())
        }
    }
}

fn param_as_string(req: &mut Request, key: &str) -> Option<String> {
    match req.get_ref::<UrlEncodedBody>() {
        Ok(ref params) => match params.get(key) {
            Some(val) => Some(val[0].clone()),
            None      => None
        },
        Err(_) => None
    }
}

fn query_as_string(req: &mut Request, key: &str) -> String {
    return req.extensions.get::<Router>().unwrap()
        .find(key).unwrap().to_string();
}

fn pagination_params(req: &mut Request) -> (i64, i64) {
    match req.get_ref::<UrlEncodedQuery>() {
        Ok(ref params) =>
            (params.get("page").unwrap()[0].to_string().parse::<i64>().unwrap(),
             params.get("per_page").unwrap()[0].to_string().parse::<i64>().unwrap()),
        Err(_) =>
            (0, 10)
    }
}

fn application_json() -> Mime {
    Mime::from_str("application/json").ok().unwrap()
}

pub fn main() {
    let path = Path::new("public");
    let mut mount = Mount::new();
    mount.mount("/web/", Static::new(Path::new(path)));
    let router = router!(
                         playlistify: get  "/playlistify"          => playlistify,
                          show_track: get  "/tracks/:track_id"     => show_track,
                        update_track: post "/tracks/:track_id"     => update_track,
           show_track_by_provider_id: get  "/tracks/:provider/:id" => show_track_by_provider_id,
                       index_entries: get  "/entries"              => index_entries,
                        index_tracks: get  "/tracks"               => index_tracks,
                                 web: get  "/*"                    => mount,
    );
    let port_str = match std::env::var("PORT") {
        Ok(n)    => n,
        Err(_) => "8080".to_string()
    };
    let port: u16 = match port_str.trim().parse() {
        Ok(n) => n,
        Err(_) => {
            println!("Faild to parse port");
            return;
        }
    };
    println!("PORT {}", port_str);
    let ip = Ipv4Addr::new(0, 0, 0, 0);
    Iron::new(router).http(SocketAddrV4::new(ip, port)).unwrap();
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate git;

use std::default::Default;
use std::os::args;

use git::Error;
use git::status;
use git::status::Flags;

macro_rules! ok(
    ($result:expr) => (
        match $result {
            Ok(_) => {},
            Err(e) => {
                error(e);
                return;
            },
        }
    );
)

fn main() {
    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(&path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn error(e: Error) {
    println!("{}", e);
}

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

const NEW_FLAGS: Flags = Flags(status::IndexNew as u32 |
                               status::WorkDirNew as u32);

const UPDATED_FLAGS: Flags = Flags(status::IndexModified as u32 |
                                   status::WorkDirModified as u32);

const REMOVED_FLAGS: Flags = Flags(status::IndexDeleted as u32 |
                                   status::WorkDirDeleted as u32);

fn status(path: &Path) -> Result<(), Error> {
    let repo = try!(git::Repository::open(path));
    let list = try!(repo.status(&Default::default()));

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

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

        if status.any(NEW_FLAGS) {
            new.push(path);
        } else if status.any(UPDATED_FLAGS) {
            updated.push(path);
        } else if status.any(REMOVED_FLAGS) {
            removed.push(path);
        }
    }

    print("New", &new);
    print("Updated", &updated);
    print("Deleted", &removed);

    Ok(())
}

fn push(_path: &Path) -> Result<(), Error> {
    Ok(())
}

fn print(title: &str, paths: &Vec<Path>) {
    if paths.is_empty() {
        return;
    }

    println!("{}:", title);

    for path in paths.iter() {
        println!("* {}", path.display());
    }

    println!("");
}
<commit_msg>Improved status; implemented push<commit_after>#![feature(macro_rules)]

extern crate git;

use std::default::Default;
use std::os::args;

use git::Error;

macro_rules! ok(
    ($result:expr) => (
        match $result {
            Ok(_) => {},
            Err(e) => {
                error(e);
                return;
            },
        }
    );
)

fn main() {
    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(&path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn status(path: &Path) -> Result<(), Error> {
    #![allow(unused_assignments)]

    macro_rules! print(
        ($title:expr, $paths:expr, $sep:expr) => {
            if !$paths.is_empty() {
                if $sep {
                    println!("");
                }
                $sep = true;
                print($title, &$paths);
            }
        };
    )

    let (new, updated, removed) = try!(check(path));
    let mut sep = false;

    print!("New", new, sep);
    print!("Updated", updated, sep);
    print!("Deleted", removed, sep);

    Ok(())
}

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

    try!(git.add_all());
    try!(git.commit("Synchronized with the official repository"));
    try!(git.push());

    Ok(())
}

fn error(e: Error) {
    println!("{}", e);
}

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

fn check(path: &Path) -> Result<(Vec<Path>, Vec<Path>, Vec<Path>), Error> {
    use git::status;
    use git::status::Flags;

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

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

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

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

        if status.any(NEW) {
            new.push(path);
        } else if status.any(UPDATED) {
            updated.push(path);
        } else if status.any(REMOVED) {
            removed.push(path);
        }
    }

    Ok((new, updated, removed))
}

fn print(title: &str, paths: &Vec<Path>) {
    println!("{}:", title);
    for path in paths.iter() {
        println!("* {}", format(path));
    }
}

fn format(path: &Path) -> String {
    match path.with_extension("").filename_str() {
        Some(s) => String::from_str(s),
        None => "<unrecognized>".to_string(),
    }
}
<|endoftext|>


<commit_before>#![feature(box_syntax)]

extern crate emu_audio_types;
extern crate emu_core_audio_driver;

mod snes_apu;

use std::iter;
use std::env;
use std::io::{Result, Error, ErrorKind, Write, stdout, stdin};
use std::thread;
use std::sync::{Arc, Mutex};

use emu_audio_types::audio_driver::AudioDriver;
use emu_core_audio_driver::core_audio_driver::CoreAudioDriver;

use snes_apu::apu::{Apu, BUFFER_LEN};
use snes_apu::spc::{Spc, Emulator};

fn main() {
    if let Err(e) = play_spc_files() {
        println!("ERROR: {}", e);
        std::process::exit(1);
    }
}

fn play_spc_files() -> Result<()> {
    for file_name in try!(get_file_names()) {
        try!(play_spc_file(&file_name));
    }
    Ok(())
}

fn get_file_names() -> Result<iter::Skip<env::Args>> {
    let args = env::args();
    match args.len() {
        1 => Err(Error::new(ErrorKind::Other, "No file(s) specified")),
        _ => Ok(args.skip(1))
    }
}

fn play_spc_file(file_name: &String) -> Result<()> {
    let spc = try!(Spc::load(file_name));

    println!("SPC: {}", file_name);
    println!(" Version Minor: {}", spc.version_minor);
    println!(" PC: {}", spc.pc);
    println!(" A: {}", spc.a);
    println!(" X: {}", spc.x);
    println!(" Y: {}", spc.y);
    println!(" PSW: {}", spc.psw);
    println!(" SP: {}", spc.sp);

    if let Some(ref id666_tag) = spc.id666_tag {
        println!(" ID666 tag present:");
        println!("  Song title: {}", id666_tag.song_title);
        println!("  Game title: {}", id666_tag.game_title);
        println!("  Dumper name: {}", id666_tag.dumper_name);
        println!("  Comments: {}", id666_tag.comments);
        println!("  Date dumped (MM/DD/YYYY): {}", id666_tag.date_dumped);
        println!("  Seconds to play before fading out: {}", id666_tag.seconds_to_play_before_fading_out);
        println!("  Fade out length: {}ms", id666_tag.fade_out_length);
        println!("  Artist name: {}", id666_tag.artist_name);
        println!("  Default channel disables: {}", id666_tag.default_channel_disables);
        println!("  Dumping emulator: {}", match id666_tag.dumping_emulator {
            Emulator::Unknown => "Unknown",
            Emulator::ZSnes => "ZSnes",
            Emulator::Snes9x => "Snes9x"
        });
    } else {
        println!(" No ID666 tag present.");
    }

    let mut apu = Apu::new();
    apu.set_state(&spc);

    let mut driver = CoreAudioDriver::new();
    driver.set_render_callback(Some(Box::new(move |buffer, num_frames| {
        // TODO: Preallocate and reuse buffers
        let mut left = [0; BUFFER_LEN];
        let mut right = [0; BUFFER_LEN];
        apu.render(&mut left, &mut right, num_frames as i32);
        for i in 0..num_frames {
            let j = i * 2;
            buffer[j + 0] = left[i] as f32 / 32768.0;
            buffer[j + 1] = right[i] as f32 / 32768.0;
        }
    })));

    println!("Return quits.");
    try!(wait_for_key_press_with_busy_icon());

    Ok(())
}

// TODO: This function is super thread-safe but can panic XD
fn wait_for_key_press_with_busy_icon() -> Result<()> {
    let is_done = Arc::new(Mutex::new(false));

    let thread_is_done = is_done.clone();
    let handle = thread::spawn(move || {
        let chars = ['-', '/', '|', '\\'];
        let mut char_index = 0;
        while !*(thread_is_done.lock().unwrap()) {
            print!("\r[{}]", chars[char_index]);
            stdout().flush().unwrap();
            char_index = (char_index + 1) % chars.len();

            thread::sleep_ms(5);
        }
        print!("\r   \r");
    });

    let mut s = String::new();
    try!(stdin().read_line(&mut s));
    *is_done.lock().unwrap() = true;
    handle.join().unwrap();

    Ok(())
}
<commit_msg>Here's to using the right sample rate :D<commit_after>#![feature(box_syntax)]

extern crate emu_audio_types;
extern crate emu_core_audio_driver;

mod snes_apu;

use std::iter;
use std::env;
use std::io::{Result, Error, ErrorKind, Write, stdout, stdin};
use std::thread;
use std::sync::{Arc, Mutex};

use emu_audio_types::audio_driver::AudioDriver;
use emu_core_audio_driver::core_audio_driver::CoreAudioDriver;

use snes_apu::apu::{Apu, BUFFER_LEN};
use snes_apu::spc::{Spc, Emulator};

fn main() {
    if let Err(e) = play_spc_files() {
        println!("ERROR: {}", e);
        std::process::exit(1);
    }
}

fn play_spc_files() -> Result<()> {
    for file_name in try!(get_file_names()) {
        try!(play_spc_file(&file_name));
    }
    Ok(())
}

fn get_file_names() -> Result<iter::Skip<env::Args>> {
    let args = env::args();
    match args.len() {
        1 => Err(Error::new(ErrorKind::Other, "No file(s) specified")),
        _ => Ok(args.skip(1))
    }
}

fn play_spc_file(file_name: &String) -> Result<()> {
    let spc = try!(Spc::load(file_name));

    println!("SPC: {}", file_name);
    println!(" Version Minor: {}", spc.version_minor);
    println!(" PC: {}", spc.pc);
    println!(" A: {}", spc.a);
    println!(" X: {}", spc.x);
    println!(" Y: {}", spc.y);
    println!(" PSW: {}", spc.psw);
    println!(" SP: {}", spc.sp);

    if let Some(ref id666_tag) = spc.id666_tag {
        println!(" ID666 tag present:");
        println!("  Song title: {}", id666_tag.song_title);
        println!("  Game title: {}", id666_tag.game_title);
        println!("  Dumper name: {}", id666_tag.dumper_name);
        println!("  Comments: {}", id666_tag.comments);
        println!("  Date dumped (MM/DD/YYYY): {}", id666_tag.date_dumped);
        println!("  Seconds to play before fading out: {}", id666_tag.seconds_to_play_before_fading_out);
        println!("  Fade out length: {}ms", id666_tag.fade_out_length);
        println!("  Artist name: {}", id666_tag.artist_name);
        println!("  Default channel disables: {}", id666_tag.default_channel_disables);
        println!("  Dumping emulator: {}", match id666_tag.dumping_emulator {
            Emulator::Unknown => "Unknown",
            Emulator::ZSnes => "ZSnes",
            Emulator::Snes9x => "Snes9x"
        });
    } else {
        println!(" No ID666 tag present.");
    }

    let mut apu = Apu::new();
    apu.set_state(&spc);

    let mut driver = CoreAudioDriver::new();
    driver.set_sample_rate(32000);
    driver.set_render_callback(Some(Box::new(move |buffer, num_frames| {
        // TODO: Preallocate and reuse buffers
        let mut left = [0; BUFFER_LEN];
        let mut right = [0; BUFFER_LEN];
        apu.render(&mut left, &mut right, num_frames as i32);
        for i in 0..num_frames {
            let j = i * 2;
            buffer[j + 0] = left[i] as f32 / 32768.0;
            buffer[j + 1] = right[i] as f32 / 32768.0;
        }
    })));

    println!("Return quits.");
    try!(wait_for_key_press_with_busy_icon());

    Ok(())
}

// TODO: This function is super thread-safe but can panic XD
fn wait_for_key_press_with_busy_icon() -> Result<()> {
    let is_done = Arc::new(Mutex::new(false));

    let thread_is_done = is_done.clone();
    let handle = thread::spawn(move || {
        let chars = ['-', '/', '|', '\\'];
        let mut char_index = 0;
        while !*(thread_is_done.lock().unwrap()) {
            print!("\r[{}]", chars[char_index]);
            stdout().flush().unwrap();
            char_index = (char_index + 1) % chars.len();

            thread::sleep_ms(5);
        }
        print!("\r   \r");
    });

    let mut s = String::new();
    try!(stdin().read_line(&mut s));
    *is_done.lock().unwrap() = true;
    handle.join().unwrap();

    Ok(())
}
<|endoftext|>