<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

#[macro_use]
extern crate habitat_sup as sup;
extern crate habitat_core as hcore;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate ansi_term;
extern crate libc;
#[macro_use]
extern crate clap;

use std::process;
use std::result;
use std::str::FromStr;

use ansi_term::Colour::Yellow;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use hcore::env as henv;
use hcore::fs;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::crypto::init as crypto_init;
use hcore::package::PackageIdent;
use hcore::url::{DEFAULT_DEPOT_URL, DEPOT_URL_ENVVAR};

use sup::config::{Command, Config, UpdateStrategy};
use sup::error::{Error, Result, SupError};
use sup::command::*;
use sup::topology::Topology;
use sup::util::parse_ip_port_with_defaults;
use sup::util::sys::ip;

/// Our output key
static LOGKEY: &'static str = "MN";

/// The version number
const VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));

/// CLI defaults
static DEFAULT_GROUP: &'static str = "default";

static DEFAULT_HTTP_LISTEN_IP: &'static str = "0.0.0.0";
static DEFAULT_HTTP_LISTEN_PORT: u16 = 9631;

const DEFAULT_GOSSIP_LISTEN_PORT: u16 = 9634;

static RING_ENVVAR: &'static str = "HAB_RING";
static RING_KEY_ENVVAR: &'static str = "HAB_RING_KEY";

/// Creates a [Config](config/struct.Config.html) from global args
/// and subcommand args.
fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) -> Result<Config> {
    let mut config = Config::new();
    let command = try!(Command::from_str(subcommand));
    config.set_command(command);
    if let Some(ref strategy) = sub_args.value_of("strategy") {
        config.set_update_strategy(UpdateStrategy::from_str(strategy));
    }
    if let Some(ref archive) = sub_args.value_of("archive") {
        config.set_archive(archive.to_string());
    }
    if let Some(ref package) = sub_args.value_of("package") {
        let ident = try!(PackageIdent::from_str(package));
        config.set_package(ident);
    }
    if let Some(key) = sub_args.value_of("key") {
        config.set_key(key.to_string());
    }
    if let Some(email) = sub_args.value_of("email") {
        config.set_email(email.to_string());
    }
    if let Some(user) = sub_args.value_of("user") {
        config.set_user_key(user.to_string());
    }
    if let Some(service) = sub_args.value_of("service") {
        config.set_service_key(service.to_string());
    }
    if let Some(infile) = sub_args.value_of("infile") {
        config.set_infile(infile.to_string());
    }
    if let Some(outfile) = sub_args.value_of("outfile") {
        config.set_outfile(outfile.to_string());
    }
    if let Some(topology) = sub_args.value_of("topology") {
        match topology.as_ref() {
            "standalone" => {
                config.set_topology(Topology::Standalone);
            }
            "leader" => {
                config.set_topology(Topology::Leader);
            }
            "initializer" => {
                config.set_topology(Topology::Initializer);
            }
            t => return Err(sup_error!(Error::UnknownTopology(String::from(t)))),
        }
    }
    if sub_args.value_of("expire-days").is_some() {
        let ed = value_t!(sub_args.value_of("expire-days"), u16).unwrap_or_else(|e| e.exit());
        config.set_expire_days(ed);
    }
    let env_or_default = henv::var(DEPOT_URL_ENVVAR).unwrap_or(DEFAULT_DEPOT_URL.to_string());
    let url = sub_args.value_of("url").unwrap_or(&env_or_default);
    config.set_url(url.to_string());
    config.set_group(sub_args.value_of("group").unwrap_or(DEFAULT_GROUP).to_string());
    let bindings = match sub_args.values_of("bind") {
        Some(bind) => bind.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_bind(bindings);
    config.set_path(sub_args.value_of("path")
        .unwrap_or(fs::svc_path(sup::PROGRAM_NAME.as_str())
            .join("data")
            .to_string_lossy()
            .as_ref())
        .to_string());

    let default_gossip_ip = try!(ip());
    let (gossip_ip, gossip_port) = try!(parse_ip_port_with_defaults(
                                        sub_args.value_of("listen-peer"),
                                        &default_gossip_ip,
                                        DEFAULT_GOSSIP_LISTEN_PORT));

    debug!("Gossip IP = {}", &gossip_ip);
    debug!("Gossip port = {}", &gossip_port);
    config.set_gossip_listen_ip(gossip_ip);
    config.set_gossip_listen_port(gossip_port);

    let (sidecar_ip, sidecar_port) = try!(parse_ip_port_with_defaults(
                                            sub_args.value_of("listen-http"),
                                            DEFAULT_HTTP_LISTEN_IP,
                                            DEFAULT_HTTP_LISTEN_PORT));

    debug!("HTTP IP = {}", &sidecar_ip);
    debug!("HTTP port = {}", &sidecar_port);

    config.set_http_listen_ip(sidecar_ip);
    config.set_http_listen_port(sidecar_port);

    let gossip_peers = match sub_args.values_of("peer") {
        Some(gp) => gp.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_gossip_peer(gossip_peers);
    if sub_args.value_of("permanent-peer").is_some() {
        config.set_gossip_permanent(true);
    }
    if let Some(sg) = sub_args.value_of("service-group") {
        config.set_service_group(sg.to_string());
    }
    if let Some(fp) = sub_args.value_of("file-path") {
        config.set_file_path(fp.to_string());
    }
    config.set_version_number(value_t!(sub_args, "version-number", u64).unwrap_or(0));
    let ring = match sub_args.value_of("ring") {
        Some(val) => Some(try!(SymKey::get_latest_pair_for(&val, &default_cache_key_path(None)))),
        None => {
            match henv::var(RING_KEY_ENVVAR) {
                Ok(val) => {
                    let (key, _) = try!(SymKey::write_file_from_str(&val,
                                                                    &default_cache_key_path(None)));
                    Some(key)
                }
                Err(_) => {
                    match henv::var(RING_ENVVAR) {
                        Ok(val) => {
                            Some(try!(SymKey::get_latest_pair_for(&val,
                                                                  &default_cache_key_path(None))))
                        }
                        Err(_) => None,
                    }
                }
            }
        }
    };
    if let Some(ring) = ring {
        config.set_ring(ring.name_with_rev());
    }
    if args.value_of("verbose").is_some() {
        sup::output::set_verbose(true);
    }
    if args.value_of("no-color").is_some() {
        sup::output::set_no_color(true);
    }

    if let Some(org) = sub_args.value_of("organization") {
        config.set_organization(org.to_string());
    }
    debug!("Config:\n{:?}", config);
    Ok(config)
}

type Handler = fn(&Config) -> result::Result<(), sup::error::SupError>;

/// The entrypoint for the Supervisor.
///
/// * Set up the logger
/// * Pull in the arguments from the Command Line, push through clap
/// * Dispatch to a function that handles that action called
/// * Exit cleanly, or if we return an `Error`, call `exit_with(E, 1)`
#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();
    crypto_init();

    let arg_url = || {
        Arg::with_name("url")
            .short("u")
            .long("url")
            .takes_value(true)
            .help("Use the specified package depot url")
    };
    let arg_group = || {
        Arg::with_name("group")
            .long("group")
            .takes_value(true)
            .help("The service group; shared config and topology [default: default].")
    };

    let arg_org = || {
        Arg::with_name("organization")
            .long("org")
            .takes_value(true)
            .help("The organization that a service is part of")
    };

    let arg_strategy = || {
        Arg::with_name("strategy")
            .long("strategy")
            .short("s")
            .takes_value(true)
            .possible_values(&["none", "at-once"])
            .help("The update strategy; [default: none].")
    };

    let sub_start = SubCommand::with_name("start")
        .about("Start a Habitat-supervised service from a package")
        .aliases(&["st", "sta", "star"])
        .arg(Arg::with_name("package")
            .index(1)
            .required(true)
            .help("Name of package to start"))
        .arg(arg_url())
        .arg(arg_group())
        .arg(arg_org())
        .arg(arg_strategy())
        .arg(Arg::with_name("topology")
            .short("t")
            .long("topology")
            .value_name("topology")
            .help("Service topology"))
        .arg(Arg::with_name("bind")
            .long("bind")
            .value_name("bind")
            .multiple(true)
            .help("One or more service groups to bind to a configuration"))
        .arg(Arg::with_name("ring")
            .short("r")
            .long("ring")
            .value_name("ring")
            .help("Ring key name"))
        .arg(Arg::with_name("peer")
            .long("peer")
            .value_name("ip:port")
            .multiple(true)
            .help("The listen address of an initial peer"))
        .arg(Arg::with_name("listen-peer")
            .long("listen-peer")
            .value_name("ip:port")
            .help("The listen address [default: ip_with_default_route:9634]"))
        .arg(Arg::with_name("listen-http")
            .long("listen-http")
            .value_name("ip:port")
            .help("The HTTP API listen address [default: 0.0.0.0:9631]"))
        .arg(Arg::with_name("permanent-peer")
            .short("I")
            .long("permanent-peer")
            .help("If this service is a permanent peer"));
    let sub_bash = SubCommand::with_name("bash")
        .about("Start an interactive shell (bash)")
        .aliases(&["b", "ba", "bas"]);
    let sub_sh = SubCommand::with_name("sh").about("Start an interactive shell (sh)");
    let sub_config = SubCommand::with_name("config")
        .about("Print the default.toml for a given package")
        .aliases(&["c", "co", "con", "conf", "confi"])
        .arg(Arg::with_name("package")
            .index(1)
            .required(true)
            .help("Name of package"));
    let args = App::new(sup::PROGRAM_NAME.as_str())
        .version(VERSION)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbose")
            .short("v")
            .global(true)
            .help("Verbose output; shows line numbers"))
        .arg(Arg::with_name("no-color")
            .long("no-color")
            .global(true)
            .help("Turn ANSI color off :("))
        .subcommand(sub_start)
        .subcommand(sub_bash)
        .subcommand(sub_sh)
        .subcommand(sub_config);
    let matches = args.get_matches();

    debug!("clap matches {:?}", matches);

    let subcommand_name = matches.subcommand_name().unwrap();
    let subcommand_matches = matches.subcommand_matches(subcommand_name).unwrap();

    let config = match config_from_args(&matches, subcommand_name, &subcommand_matches) {
        Ok(config) => config,
        Err(e) => return exit_with(e, 1),
    };

    let result = match config.command() {
        Command::ShellBash => shell_bash(&config),
        Command::ShellSh => shell_sh(&config),
        Command::Config => configure(&config),
        Command::Start => start(&config),
    };

    match result {
        Ok(_) => std::process::exit(0),
        Err(e) => exit_with(e, 1),
    }
}

/// Exit with an error message and the right status code
#[allow(dead_code)]
fn exit_with(e: SupError, code: i32) {
    println!("{:?}", e);
    process::exit(code)
}

/// Start a sh shell
#[allow(dead_code)]
fn shell_sh(_config: &Config) -> Result<()> {
    shell::sh()
}

/// Start a bash shell
#[allow(dead_code)]
fn shell_bash(_config: &Config) -> Result<()> {
    shell::bash()
}

/// Show the configuration options for a service
#[allow(dead_code)]
fn configure(config: &Config) -> Result<()> {
    try!(configure::display(config));
    Ok(())
}

/// Start a service
#[allow(dead_code)]
fn start(config: &Config) -> Result<()> {
    outputln!("Starting {}",
              Yellow.bold().paint(config.package().to_string()));
    try!(start::package(config));
    outputln!("Finished with {}",
              Yellow.bold().paint(config.package().to_string()));
    Ok(())
}
<commit_msg>Prettier error formatting upon error exit from supervisor<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

#[macro_use]
extern crate habitat_sup as sup;
extern crate habitat_core as hcore;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate ansi_term;
extern crate libc;
#[macro_use]
extern crate clap;

use std::process;
use std::result;
use std::str::FromStr;

use ansi_term::Colour::Yellow;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use hcore::env as henv;
use hcore::fs;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::crypto::init as crypto_init;
use hcore::package::PackageIdent;
use hcore::url::{DEFAULT_DEPOT_URL, DEPOT_URL_ENVVAR};

use sup::config::{Command, Config, UpdateStrategy};
use sup::error::{Error, Result, SupError};
use sup::command::*;
use sup::topology::Topology;
use sup::util::parse_ip_port_with_defaults;
use sup::util::sys::ip;

/// Our output key
static LOGKEY: &'static str = "MN";

/// The version number
const VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));

/// CLI defaults
static DEFAULT_GROUP: &'static str = "default";

static DEFAULT_HTTP_LISTEN_IP: &'static str = "0.0.0.0";
static DEFAULT_HTTP_LISTEN_PORT: u16 = 9631;

const DEFAULT_GOSSIP_LISTEN_PORT: u16 = 9634;

static RING_ENVVAR: &'static str = "HAB_RING";
static RING_KEY_ENVVAR: &'static str = "HAB_RING_KEY";

/// Creates a [Config](config/struct.Config.html) from global args
/// and subcommand args.
fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) -> Result<Config> {
    let mut config = Config::new();
    let command = try!(Command::from_str(subcommand));
    config.set_command(command);
    if let Some(ref strategy) = sub_args.value_of("strategy") {
        config.set_update_strategy(UpdateStrategy::from_str(strategy));
    }
    if let Some(ref archive) = sub_args.value_of("archive") {
        config.set_archive(archive.to_string());
    }
    if let Some(ref package) = sub_args.value_of("package") {
        let ident = try!(PackageIdent::from_str(package));
        config.set_package(ident);
    }
    if let Some(key) = sub_args.value_of("key") {
        config.set_key(key.to_string());
    }
    if let Some(email) = sub_args.value_of("email") {
        config.set_email(email.to_string());
    }
    if let Some(user) = sub_args.value_of("user") {
        config.set_user_key(user.to_string());
    }
    if let Some(service) = sub_args.value_of("service") {
        config.set_service_key(service.to_string());
    }
    if let Some(infile) = sub_args.value_of("infile") {
        config.set_infile(infile.to_string());
    }
    if let Some(outfile) = sub_args.value_of("outfile") {
        config.set_outfile(outfile.to_string());
    }
    if let Some(topology) = sub_args.value_of("topology") {
        match topology.as_ref() {
            "standalone" => {
                config.set_topology(Topology::Standalone);
            }
            "leader" => {
                config.set_topology(Topology::Leader);
            }
            "initializer" => {
                config.set_topology(Topology::Initializer);
            }
            t => return Err(sup_error!(Error::UnknownTopology(String::from(t)))),
        }
    }
    if sub_args.value_of("expire-days").is_some() {
        let ed = value_t!(sub_args.value_of("expire-days"), u16).unwrap_or_else(|e| e.exit());
        config.set_expire_days(ed);
    }
    let env_or_default = henv::var(DEPOT_URL_ENVVAR).unwrap_or(DEFAULT_DEPOT_URL.to_string());
    let url = sub_args.value_of("url").unwrap_or(&env_or_default);
    config.set_url(url.to_string());
    config.set_group(sub_args.value_of("group").unwrap_or(DEFAULT_GROUP).to_string());
    let bindings = match sub_args.values_of("bind") {
        Some(bind) => bind.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_bind(bindings);
    config.set_path(sub_args.value_of("path")
        .unwrap_or(fs::svc_path(sup::PROGRAM_NAME.as_str())
            .join("data")
            .to_string_lossy()
            .as_ref())
        .to_string());

    let default_gossip_ip = try!(ip());
    let (gossip_ip, gossip_port) = try!(parse_ip_port_with_defaults(
                                        sub_args.value_of("listen-peer"),
                                        &default_gossip_ip,
                                        DEFAULT_GOSSIP_LISTEN_PORT));

    debug!("Gossip IP = {}", &gossip_ip);
    debug!("Gossip port = {}", &gossip_port);
    config.set_gossip_listen_ip(gossip_ip);
    config.set_gossip_listen_port(gossip_port);

    let (sidecar_ip, sidecar_port) = try!(parse_ip_port_with_defaults(
                                            sub_args.value_of("listen-http"),
                                            DEFAULT_HTTP_LISTEN_IP,
                                            DEFAULT_HTTP_LISTEN_PORT));

    debug!("HTTP IP = {}", &sidecar_ip);
    debug!("HTTP port = {}", &sidecar_port);

    config.set_http_listen_ip(sidecar_ip);
    config.set_http_listen_port(sidecar_port);

    let gossip_peers = match sub_args.values_of("peer") {
        Some(gp) => gp.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_gossip_peer(gossip_peers);
    if sub_args.value_of("permanent-peer").is_some() {
        config.set_gossip_permanent(true);
    }
    if let Some(sg) = sub_args.value_of("service-group") {
        config.set_service_group(sg.to_string());
    }
    if let Some(fp) = sub_args.value_of("file-path") {
        config.set_file_path(fp.to_string());
    }
    config.set_version_number(value_t!(sub_args, "version-number", u64).unwrap_or(0));
    let ring = match sub_args.value_of("ring") {
        Some(val) => Some(try!(SymKey::get_latest_pair_for(&val, &default_cache_key_path(None)))),
        None => {
            match henv::var(RING_KEY_ENVVAR) {
                Ok(val) => {
                    let (key, _) = try!(SymKey::write_file_from_str(&val,
                                                                    &default_cache_key_path(None)));
                    Some(key)
                }
                Err(_) => {
                    match henv::var(RING_ENVVAR) {
                        Ok(val) => {
                            Some(try!(SymKey::get_latest_pair_for(&val,
                                                                  &default_cache_key_path(None))))
                        }
                        Err(_) => None,
                    }
                }
            }
        }
    };
    if let Some(ring) = ring {
        config.set_ring(ring.name_with_rev());
    }
    if args.value_of("verbose").is_some() {
        sup::output::set_verbose(true);
    }
    if args.value_of("no-color").is_some() {
        sup::output::set_no_color(true);
    }

    if let Some(org) = sub_args.value_of("organization") {
        config.set_organization(org.to_string());
    }
    debug!("Config:\n{:?}", config);
    Ok(config)
}

type Handler = fn(&Config) -> result::Result<(), sup::error::SupError>;

/// The entrypoint for the Supervisor.
///
/// * Set up the logger
/// * Pull in the arguments from the Command Line, push through clap
/// * Dispatch to a function that handles that action called
/// * Exit cleanly, or if we return an `Error`, call `exit_with(E, 1)`
#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();
    crypto_init();

    let arg_url = || {
        Arg::with_name("url")
            .short("u")
            .long("url")
            .takes_value(true)
            .help("Use the specified package depot url")
    };
    let arg_group = || {
        Arg::with_name("group")
            .long("group")
            .takes_value(true)
            .help("The service group; shared config and topology [default: default].")
    };

    let arg_org = || {
        Arg::with_name("organization")
            .long("org")
            .takes_value(true)
            .help("The organization that a service is part of")
    };

    let arg_strategy = || {
        Arg::with_name("strategy")
            .long("strategy")
            .short("s")
            .takes_value(true)
            .possible_values(&["none", "at-once"])
            .help("The update strategy; [default: none].")
    };

    let sub_start = SubCommand::with_name("start")
        .about("Start a Habitat-supervised service from a package")
        .aliases(&["st", "sta", "star"])
        .arg(Arg::with_name("package")
            .index(1)
            .required(true)
            .help("Name of package to start"))
        .arg(arg_url())
        .arg(arg_group())
        .arg(arg_org())
        .arg(arg_strategy())
        .arg(Arg::with_name("topology")
            .short("t")
            .long("topology")
            .value_name("topology")
            .help("Service topology"))
        .arg(Arg::with_name("bind")
            .long("bind")
            .value_name("bind")
            .multiple(true)
            .help("One or more service groups to bind to a configuration"))
        .arg(Arg::with_name("ring")
            .short("r")
            .long("ring")
            .value_name("ring")
            .help("Ring key name"))
        .arg(Arg::with_name("peer")
            .long("peer")
            .value_name("ip:port")
            .multiple(true)
            .help("The listen address of an initial peer"))
        .arg(Arg::with_name("listen-peer")
            .long("listen-peer")
            .value_name("ip:port")
            .help("The listen address [default: ip_with_default_route:9634]"))
        .arg(Arg::with_name("listen-http")
            .long("listen-http")
            .value_name("ip:port")
            .help("The HTTP API listen address [default: 0.0.0.0:9631]"))
        .arg(Arg::with_name("permanent-peer")
            .short("I")
            .long("permanent-peer")
            .help("If this service is a permanent peer"));
    let sub_bash = SubCommand::with_name("bash")
        .about("Start an interactive shell (bash)")
        .aliases(&["b", "ba", "bas"]);
    let sub_sh = SubCommand::with_name("sh").about("Start an interactive shell (sh)");
    let sub_config = SubCommand::with_name("config")
        .about("Print the default.toml for a given package")
        .aliases(&["c", "co", "con", "conf", "confi"])
        .arg(Arg::with_name("package")
            .index(1)
            .required(true)
            .help("Name of package"));
    let args = App::new(sup::PROGRAM_NAME.as_str())
        .version(VERSION)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbose")
            .short("v")
            .global(true)
            .help("Verbose output; shows line numbers"))
        .arg(Arg::with_name("no-color")
            .long("no-color")
            .global(true)
            .help("Turn ANSI color off :("))
        .subcommand(sub_start)
        .subcommand(sub_bash)
        .subcommand(sub_sh)
        .subcommand(sub_config);
    let matches = args.get_matches();

    debug!("clap matches {:?}", matches);

    let subcommand_name = matches.subcommand_name().unwrap();
    let subcommand_matches = matches.subcommand_matches(subcommand_name).unwrap();

    let config = match config_from_args(&matches, subcommand_name, &subcommand_matches) {
        Ok(config) => config,
        Err(e) => return exit_with(e, 1),
    };

    let result = match config.command() {
        Command::ShellBash => shell_bash(&config),
        Command::ShellSh => shell_sh(&config),
        Command::Config => configure(&config),
        Command::Start => start(&config),
    };

    match result {
        Ok(_) => std::process::exit(0),
        Err(e) => exit_with(e, 1),
    }
}

/// Exit with an error message and the right status code
#[allow(dead_code)]
fn exit_with(e: SupError, code: i32) {
    println!("{}", e.to_string());
    process::exit(code)
}

/// Start a sh shell
#[allow(dead_code)]
fn shell_sh(_config: &Config) -> Result<()> {
    shell::sh()
}

/// Start a bash shell
#[allow(dead_code)]
fn shell_bash(_config: &Config) -> Result<()> {
    shell::bash()
}

/// Show the configuration options for a service
#[allow(dead_code)]
fn configure(config: &Config) -> Result<()> {
    try!(configure::display(config));
    Ok(())
}

/// Start a service
#[allow(dead_code)]
fn start(config: &Config) -> Result<()> {
    outputln!("Starting {}",
              Yellow.bold().paint(config.package().to_string()));
    try!(start::package(config));
    outputln!("Finished with {}",
              Yellow.bold().paint(config.package().to_string()));
    Ok(())
}
<|endoftext|>


<commit_before>use std::env;
use ansi_term::Colour::{Red, Purple};

const SYMBOL:&str = "❯";

pub fn display() {
  let var = env::var("_LAST_RETURN_STATUS");
  let last_command = match var {
    Ok(val) => val.parse::<u8>().unwrap(),
    Err(_e) => 1
  };

  let printable_prompt = match last_command {
    0 => Purple.paint(SYMBOL),
    _ => Red.paint(SYMBOL),
  };

  print!("{}", printable_prompt);
}<commit_msg>Outputs real zsh escape sequences<commit_after>use std::env;

const SYMBOL:&str = "❯";

pub fn display() {
  let var = env::var("_LAST_RETURN_STATUS");
  let last_command = match var {
    Ok(val) => val.parse::<u8>().unwrap(),
    Err(_e) => 1
  };

  let shell_color = match last_command {
    0 => 5,
    _ => 9,
  };

  print!("%F{{{}}}{}%f", shell_color, SYMBOL);
}<|endoftext|>


<commit_before>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::scoped::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// });
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::scoped::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// });
/// ```
///
/// Much more straightforward.
// FIXME(jeehoonkang): maybe we should create a new crate for scoped threads.

use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops::DerefMut;
use std::rc::Rc;
use std::thread;
use std::io;

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without the closure bounds.
pub unsafe fn spawn_unsafe<'a, F>(f: F) -> thread::JoinHandle<()>
where
    F: FnOnce() + Send + 'a,
{
    let builder = thread::Builder::new();
    builder_spawn_unsafe(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without the closure bounds.
pub unsafe fn builder_spawn_unsafe<'a, F>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<()>>
where
    F: FnOnce() + Send + 'a,
{
    let closure: Box<FnBox<()> + 'a> = Box::new(f);
    let closure: Box<FnBox<()> + Send> = mem::transmute(closure);
    builder.spawn(move || closure.call_box())
}

pub struct Scope<'a> {
    /// The list of the deferred functions and thread join jobs.
    dtors: RefCell<Option<DtorChain<'a, ()>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct DtorChain<'a, T> {
    dtor: Box<FnBox<T> + 'a>,
    next: Option<Box<DtorChain<'a, T>>>,
}

impl<'a, T> DtorChain<'a, T> {
    pub fn pop(chain: &mut Option<DtorChain<'a, T>>) -> Option<Box<FnBox<T> + 'a>> {
        chain.take().map(|mut node| {
            *chain = node.next.take().map(|b| *b);
            node.dtor
        })
    }
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: usize,
    _marker: PhantomData<T>,
}

impl<T: Send> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: usize) -> JoinState<T> {
        JoinState {
            join_handle: join_handle,
            result: result,
            _marker: PhantomData,
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle.join().map(|_| {
            unsafe { ManuallyDrop::into_inner(*Box::from_raw(result as *mut ManuallyDrop<T>))}
        })
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'a, T: 'a> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'a T>,
}

/// Create a new `scope`, for deferred destructors.
///
/// Scopes, in particular, support [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::scoped::scope(|scope| {
///     scope.defer(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"))
/// });
/// // Prints messages in the reverse order written
/// ```
///
/// # Panics
///
/// `scoped::scope()` panics if a spawned thread panics but it is not joined inside the scope.
pub fn scope<'a, F, R>(f: F) -> R
where
    F: FnOnce(&Scope<'a>) -> R,
{
    let mut scope = Scope {
        dtors: RefCell::new(None),
        _marker: PhantomData,
    };
    let ret = f(&scope);
    scope.drop_all();
    ret
}

impl<'a> fmt::Debug for Scope<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'a, T> fmt::Debug for ScopedJoinHandle<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to @rust-lang/rust#14875.
    fn drop_all(&mut self) {
        while let Some(dtor) = DtorChain::pop(&mut self.dtors.borrow_mut()) {
            dtor.call_box();
        }
    }

    /// Schedule code to be executed when exiting the scope.
    ///
    /// This is akin to having a destructor on the stack, except that it is
    /// *guaranteed* to be run. It is guaranteed that the function is called
    /// after all the spawned threads are joined.
    pub fn defer<F>(&self, f: F)
    where
        F: FnOnce() + 'a,
    {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new),
        });
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate
    /// before the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'s, F, T>(&'s self, f: F) -> ScopedJoinHandle<'a, T>
    where
        'a: 's,
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'s>(&'s self) -> ScopedThreadBuilder<'s, 'a> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'s, 'a: 's> {
    scope: &'s Scope<'a>,
    builder: thread::Builder,
}

impl<'s, 'a: 's> ScopedThreadBuilder<'s, 'a> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'a, T>>
    where
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        // The `Box` constructed below is written only by the spawned thread,
        // and read by the current thread only after the spawned thread is
        // joined (`JoinState::join()`). Thus there are no data races.
        let result = Box::into_raw(Box::<ManuallyDrop<T>>::new(unsafe { mem::uninitialized() })) as usize;

        let join_handle = try!(unsafe {
            builder_spawn_unsafe(self.builder, move || {
                let mut result = Box::from_raw(result as *mut ManuallyDrop<T>);
                *result = ManuallyDrop::new(f());
                mem::forget(result);
            })
        });
        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.defer(move || {
            let state = mem::replace(deferred_handle.borrow_mut().deref_mut(), None);
            if let Some(state) = state {
                state.join().unwrap();
            }
        });

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'a, T: Send + 'a> ScopedJoinHandle<'a, T> {
    /// Join the scoped thread, returning the result it produced.
    pub fn join(self) -> thread::Result<T> {
        let state = mem::replace(self.inner.borrow_mut().deref_mut(), None);
        state.unwrap().join()
    }

    /// Get the underlying thread handle.
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        self.drop_all()
    }
}
<commit_msg>Fix `cargo doc` in nightly (#21)<commit_after>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::scoped::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// });
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
/// [spawn]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::scoped::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// });
/// ```
///
/// Much more straightforward.
// FIXME(jeehoonkang): maybe we should create a new crate for scoped threads.

use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops::DerefMut;
use std::rc::Rc;
use std::thread;
use std::io;

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without the closure bounds.
pub unsafe fn spawn_unsafe<'a, F>(f: F) -> thread::JoinHandle<()>
where
    F: FnOnce() + Send + 'a,
{
    let builder = thread::Builder::new();
    builder_spawn_unsafe(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without the closure bounds.
pub unsafe fn builder_spawn_unsafe<'a, F>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<()>>
where
    F: FnOnce() + Send + 'a,
{
    let closure: Box<FnBox<()> + 'a> = Box::new(f);
    let closure: Box<FnBox<()> + Send> = mem::transmute(closure);
    builder.spawn(move || closure.call_box())
}

pub struct Scope<'a> {
    /// The list of the deferred functions and thread join jobs.
    dtors: RefCell<Option<DtorChain<'a, ()>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct DtorChain<'a, T> {
    dtor: Box<FnBox<T> + 'a>,
    next: Option<Box<DtorChain<'a, T>>>,
}

impl<'a, T> DtorChain<'a, T> {
    pub fn pop(chain: &mut Option<DtorChain<'a, T>>) -> Option<Box<FnBox<T> + 'a>> {
        chain.take().map(|mut node| {
            *chain = node.next.take().map(|b| *b);
            node.dtor
        })
    }
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: usize,
    _marker: PhantomData<T>,
}

impl<T: Send> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: usize) -> JoinState<T> {
        JoinState {
            join_handle: join_handle,
            result: result,
            _marker: PhantomData,
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle.join().map(|_| {
            unsafe { ManuallyDrop::into_inner(*Box::from_raw(result as *mut ManuallyDrop<T>))}
        })
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'a, T: 'a> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'a T>,
}

/// Create a new `scope`, for deferred destructors.
///
/// Scopes, in particular, support [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::scoped::scope(|scope| {
///     scope.defer(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"))
/// });
/// // Prints messages in the reverse order written
/// ```
///
/// # Panics
///
/// `scoped::scope()` panics if a spawned thread panics but it is not joined inside the scope.
pub fn scope<'a, F, R>(f: F) -> R
where
    F: FnOnce(&Scope<'a>) -> R,
{
    let mut scope = Scope {
        dtors: RefCell::new(None),
        _marker: PhantomData,
    };
    let ret = f(&scope);
    scope.drop_all();
    ret
}

impl<'a> fmt::Debug for Scope<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'a, T> fmt::Debug for ScopedJoinHandle<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to @rust-lang/rust#14875.
    fn drop_all(&mut self) {
        while let Some(dtor) = DtorChain::pop(&mut self.dtors.borrow_mut()) {
            dtor.call_box();
        }
    }

    /// Schedule code to be executed when exiting the scope.
    ///
    /// This is akin to having a destructor on the stack, except that it is
    /// *guaranteed* to be run. It is guaranteed that the function is called
    /// after all the spawned threads are joined.
    pub fn defer<F>(&self, f: F)
    where
        F: FnOnce() + 'a,
    {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new),
        });
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate
    /// before the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'s, F, T>(&'s self, f: F) -> ScopedJoinHandle<'a, T>
    where
        'a: 's,
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'s>(&'s self) -> ScopedThreadBuilder<'s, 'a> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'s, 'a: 's> {
    scope: &'s Scope<'a>,
    builder: thread::Builder,
}

impl<'s, 'a: 's> ScopedThreadBuilder<'s, 'a> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'a, T>>
    where
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        // The `Box` constructed below is written only by the spawned thread,
        // and read by the current thread only after the spawned thread is
        // joined (`JoinState::join()`). Thus there are no data races.
        let result = Box::into_raw(Box::<ManuallyDrop<T>>::new(unsafe { mem::uninitialized() })) as usize;

        let join_handle = try!(unsafe {
            builder_spawn_unsafe(self.builder, move || {
                let mut result = Box::from_raw(result as *mut ManuallyDrop<T>);
                *result = ManuallyDrop::new(f());
                mem::forget(result);
            })
        });
        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.defer(move || {
            let state = mem::replace(deferred_handle.borrow_mut().deref_mut(), None);
            if let Some(state) = state {
                state.join().unwrap();
            }
        });

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'a, T: Send + 'a> ScopedJoinHandle<'a, T> {
    /// Join the scoped thread, returning the result it produced.
    pub fn join(self) -> thread::Result<T> {
        let state = mem::replace(self.inner.borrow_mut().deref_mut(), None);
        state.unwrap().join()
    }

    /// Get the underlying thread handle.
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        self.drop_all()
    }
}
<|endoftext|>


<commit_before>use score;
use score::Match;
use sorted_result_set::SortedResultSet;
use std::slice::SliceExt;
use std::cmp::min;
use std::ascii::AsciiExt;

#[derive(Debug)]
pub struct Search<'s> {
    pub query: String,
    pub current: usize,
    pub result: Vec<Match<'s>>,
    choice_stack: ChoiceStack<'s>,
    pub visible_limit: usize,
    done: bool,
}

#[derive(Debug)]
struct ChoiceStack<'s> {
    content: Vec<Vec<&'s String>>,
}

impl <'s>ChoiceStack<'s> {
    pub fn new(input: &'s Vec<String>) -> ChoiceStack<'s> {
        let initial_choices = input.iter().map(|x| x).collect();

        ChoiceStack { content: vec![initial_choices] }
    }

    pub fn push(&mut self, frame: Vec<&'s String>) {
        self.content.push(frame);
    }

    pub fn pop(&mut self) {
        if self.content.len() > 1 {
            self.content.pop();
        }
    }

    pub fn peek(&self) -> &Vec<&'s String> {
        self.content.last().unwrap()
    }

    pub fn last_size(&self) -> usize {
        self.peek().len()
    }
}

impl<'s> Search<'s> {
    pub fn blank(choices: &'s Vec<String>,
                 initial_search: Option<String>,
                 visible_limit: usize) -> Search<'s> {
        let query = initial_search.unwrap_or("".to_string());

        let choice_stack = ChoiceStack::new(&choices);

        let result = choices.iter().take(visible_limit).map(|x| Match::with_empty_range(x)).collect();

        Search::new(query, choice_stack, result, 0, visible_limit, false)
    }

    fn new(query: String, choice_stack: ChoiceStack<'s>, result: Vec<Match<'s>>, index: usize, visible_limit: usize, done: bool) -> Search<'s> {
        Search { current: index,
                 query: query,
                 result: result,
                 choice_stack: choice_stack,
                 visible_limit: visible_limit,
                 done: done}
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search<'s> {
        Search::new(self.query, self.choice_stack, self.result, self.current, self.visible_limit, true)
    }

    pub fn selection(&self) -> Option<String> {
        self.result.get(self.current).map( |t| t.original.clone())
    }

    fn new_for_index(self, index: usize) -> Search<'s> {
        Search::new(self.query, self.choice_stack, self.result, index,self.visible_limit, self.done)
    }

    pub fn iter_matches<F: FnMut(Match<'s>)>(query: &str, choices: &Vec<&'s String>, mut f: F) {
        let lower_query = query.to_ascii_lowercase();

        for choice in choices.iter() {
            match score::score(&choice, &lower_query) {
                None     => continue,
                Some(m) => f(m),
            };
        }
    }

    pub fn down(self) -> Search<'s> {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search<'s> {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(mut self, input: &str) -> Search<'s> {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        let mut heap = SortedResultSet::new(self.visible_limit);
        let mut filtered_choices: Vec<&String> = Vec::new();
        Search::iter_matches(new_query.as_slice(), &self.choice_stack.peek(),
                        |matching| {
                                               let quality = matching.quality.to_f32();
                                               let choice = matching.original;
                                               heap.push(matching.clone(), quality);
                                               filtered_choices.push(&choice)
                                             });

        self.choice_stack.push(filtered_choices);

        let result =  heap.as_sorted_vec();

        Search::new(new_query, self.choice_stack, result, 0, self.visible_limit, self.done)
    }

    pub fn backspace(mut self) -> Search<'s> {
        let mut new_query = self.query.clone();
        new_query.pop();

        self.choice_stack.pop();

        let mut heap = SortedResultSet::new(self.visible_limit);
        Search::iter_matches(new_query.as_slice(), &self.choice_stack.peek(),
                             |matching| {
                                 let quality = matching.quality.to_f32();
                                 heap.push(matching, quality)
                             } );

        let result =  heap.as_sorted_vec();

        Search::new(new_query, self.choice_stack, result, 0, self.visible_limit, self.done)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.visible_limit, self.num_matches())
    }

    pub fn num_matches(&self) -> usize {
        self.choice_stack.last_size()
    }
}
<commit_msg>Rename SortedResultSet 'heap' to 'result'<commit_after>use score;
use score::Match;
use sorted_result_set::SortedResultSet;
use std::slice::SliceExt;
use std::cmp::min;
use std::ascii::AsciiExt;

#[derive(Debug)]
pub struct Search<'s> {
    pub query: String,
    pub current: usize,
    pub result: Vec<Match<'s>>,
    choice_stack: ChoiceStack<'s>,
    pub visible_limit: usize,
    done: bool,
}

#[derive(Debug)]
struct ChoiceStack<'s> {
    content: Vec<Vec<&'s String>>,
}

impl <'s>ChoiceStack<'s> {
    pub fn new(input: &'s Vec<String>) -> ChoiceStack<'s> {
        let initial_choices = input.iter().map(|x| x).collect();

        ChoiceStack { content: vec![initial_choices] }
    }

    pub fn push(&mut self, frame: Vec<&'s String>) {
        self.content.push(frame);
    }

    pub fn pop(&mut self) {
        if self.content.len() > 1 {
            self.content.pop();
        }
    }

    pub fn peek(&self) -> &Vec<&'s String> {
        self.content.last().unwrap()
    }

    pub fn last_size(&self) -> usize {
        self.peek().len()
    }
}

impl<'s> Search<'s> {
    pub fn blank(choices: &'s Vec<String>,
                 initial_search: Option<String>,
                 visible_limit: usize) -> Search<'s> {
        let query = initial_search.unwrap_or("".to_string());

        let choice_stack = ChoiceStack::new(&choices);

        let result = choices.iter().take(visible_limit).map(|x| Match::with_empty_range(x)).collect();

        Search::new(query, choice_stack, result, 0, visible_limit, false)
    }

    fn new(query: String, choice_stack: ChoiceStack<'s>, result: Vec<Match<'s>>, index: usize, visible_limit: usize, done: bool) -> Search<'s> {
        Search { current: index,
                 query: query,
                 result: result,
                 choice_stack: choice_stack,
                 visible_limit: visible_limit,
                 done: done}
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search<'s> {
        Search::new(self.query, self.choice_stack, self.result, self.current, self.visible_limit, true)
    }

    pub fn selection(&self) -> Option<String> {
        self.result.get(self.current).map( |t| t.original.clone())
    }

    fn new_for_index(self, index: usize) -> Search<'s> {
        Search::new(self.query, self.choice_stack, self.result, index,self.visible_limit, self.done)
    }

    pub fn iter_matches<F: FnMut(Match<'s>)>(query: &str, choices: &Vec<&'s String>, mut f: F) {
        let lower_query = query.to_ascii_lowercase();

        for choice in choices.iter() {
            match score::score(&choice, &lower_query) {
                None     => continue,
                Some(m) => f(m),
            };
        }
    }

    pub fn down(self) -> Search<'s> {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search<'s> {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(mut self, input: &str) -> Search<'s> {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        let mut result = SortedResultSet::new(self.visible_limit);
        let mut filtered_choices: Vec<&String> = Vec::new();
        Search::iter_matches(new_query.as_slice(), &self.choice_stack.peek(),
                        |matching| {
                                               let quality = matching.quality.to_f32();
                                               let choice = matching.original;
                                               result.push(matching.clone(), quality);
                                               filtered_choices.push(&choice)
                                             });

        self.choice_stack.push(filtered_choices);

        Search::new(new_query, self.choice_stack, result.as_sorted_vec(), 0, self.visible_limit, self.done)
    }

    pub fn backspace(mut self) -> Search<'s> {
        let mut new_query = self.query.clone();
        new_query.pop();

        self.choice_stack.pop();

        let mut result = SortedResultSet::new(self.visible_limit);
        Search::iter_matches(new_query.as_slice(), &self.choice_stack.peek(),
                             |matching| {
                                 let quality = matching.quality.to_f32();
                                 result.push(matching, quality)
                             } );

        Search::new(new_query, self.choice_stack, result.as_sorted_vec(), 0, self.visible_limit, self.done)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.visible_limit, self.num_matches())
    }

    pub fn num_matches(&self) -> usize {
        self.choice_stack.last_size()
    }
}
<|endoftext|>


<commit_before>use super::command::{Command, Query};
use super::command::Command::Select;
use std::iter::IntoIterator;
use std::collections::HashMap;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    table: String,
    arguments: HashMap<String, String>,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            table: "".to_string(),
            arguments: HashMap::new(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            table: table,
            arguments: default.arguments,
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    pub fn query(mut self, query: String) -> SelectCommand {
        let encoded = format!("'{}'", query);
        self.arguments.insert("query".to_string(), encoded.clone());
        self
    }

    #[inline]
    fn split_columns_vec(&mut self, columns: Vec<String>) -> String {
        let string = columns.into_iter().collect::<Vec<String>>()
            .join(",").to_owned();
        string.clone()
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: u64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: u64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no"
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }

    pub fn build(self) -> Query {
        let mut query: Query = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        query
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use command::Query;
    use command::Command::Select;
    use std::collections::HashMap;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: HashMap::new(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_query() {
        let select = SelectCommand::new("test".to_string())
            .query("_key:\"http://example.org/\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("query".to_string(),
                   "\'_key:\"http://example.org/\"\'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
            .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
            .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string())
            .offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string())
            .limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string())
            .cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_yes,
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string())
            .cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_no,
        };
        assert_eq!(expected_no, select_no);
    }

    #[test]
    fn test_build() {
        let query = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string()).build();
        let expected: Query =
            vec![("table".to_string(), "test".to_string()),
                 ("filter".to_string(),
                  "'output_column @ \"type_safe\"'".to_string())];
        assert_eq!(expected, query);
    }
}
<commit_msg>select: Return Command and query pair from build()<commit_after>use super::command::{Command, Query};
use super::command::Command::Select;
use std::iter::IntoIterator;
use std::collections::HashMap;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    table: String,
    arguments: HashMap<String, String>,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            table: "".to_string(),
            arguments: HashMap::new(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            table: table,
            arguments: default.arguments,
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    pub fn query(mut self, query: String) -> SelectCommand {
        let encoded = format!("'{}'", query);
        self.arguments.insert("query".to_string(), encoded.clone());
        self
    }

    #[inline]
    fn split_columns_vec(&mut self, columns: Vec<String>) -> String {
        let string = columns.into_iter().collect::<Vec<String>>()
            .join(",").to_owned();
        string.clone()
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: u64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: u64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no"
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }

    pub fn build(self) -> (Command, Query) {
        let mut query: Query = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        (Select, query)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use command::Query;
    use command::Command::Select;
    use std::collections::HashMap;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: HashMap::new(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_query() {
        let select = SelectCommand::new("test".to_string())
            .query("_key:\"http://example.org/\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("query".to_string(),
                   "\'_key:\"http://example.org/\"\'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
            .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
            .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string())
            .offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string())
            .limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string())
            .cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_yes,
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string())
            .cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_no,
        };
        assert_eq!(expected_no, select_no);
    }

    #[test]
    fn test_build() {
        let actual = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string()).build();
        let expected_query: Query =
            vec![("table".to_string(), "test".to_string()),
                 ("filter".to_string(),
                  "'output_column @ \"type_safe\"'".to_string())];
        let expected = (Select, expected_query);
        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::io::{Write, Read};
use std::sync::Mutex;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::net::SocketAddr;

use hyper::header::{ContentLength, ContentType};
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::WebDriverResponse;

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: &WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl <T: WebDriverHandler<U>,
      U: WebDriverExtensionRoute> Dispatcher<T,U> {
    fn new(handler: T) -> Dispatcher<T,U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, &msg),
                        Err(e) => Err(e)
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        },
                        Ok(WebDriverResponse::DeleteSession) => {
                            self.delete_session();
                        },
                        Err(ref x) if x.delete_session() => {
                            self.delete_session();
                        }
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                },
                Ok(DispatchMessage::Quit) => {
                    break;
                },
                Err(_) => panic!("Error receiving message in handler")
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::NewSession => {
                                Err(WebDriverError::new(
                                    ErrorStatus::UnsupportedOperation,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession => Ok(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl <U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }
        debug!("Got request {} {:?}", req.method, req.uri);
        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => {
                            api.decode_request(req.method, &path[..], &body[..])
                        },
                        Err(_) => return
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res = c.send(DispatchMessage::HandleWebDriver(message,
                                                                                send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return
                                    }
                                }
                            },
                            Err(_) => {
                                error!("Something terrible happened");
                                return
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => match data {
                                Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                Err(err) => (err.http_status(), err.to_json_string()),
                            },
                            Err(e) => panic!("Error reading response: {:?}", e)
                        }
                    },
                    Err(err) => {
                        (err.http_status(), err.to_json_string())
                    }
                };
                debug!("Returning status {:?}", status);
                debug!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentLength(resp_body.len() as u64));
                res.headers_mut().set(ContentType::json());
                let mut stream = res.start().unwrap();
                stream.write_all(&resp_body.as_bytes()).unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler<U>,
             U: 'static+WebDriverExtensionRoute>(address: SocketAddr,
                                                 handler: T,
                                                 extension_routes:Vec<(Method, &str, U)>) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let server = Server::http(address).unwrap();

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.handle(http_handler).unwrap();
}
<commit_msg>Don't use keepalive in the http server.<commit_after>use std::marker::PhantomData;
use std::io::Read;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::net::SocketAddr;

use hyper::header::ContentType;
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::WebDriverResponse;

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: &WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl <T: WebDriverHandler<U>,
      U: WebDriverExtensionRoute> Dispatcher<T,U> {
    fn new(handler: T) -> Dispatcher<T,U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, &msg),
                        Err(e) => Err(e)
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        },
                        Ok(WebDriverResponse::DeleteSession) => {
                            self.delete_session();
                        },
                        Err(ref x) if x.delete_session() => {
                            self.delete_session();
                        }
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                },
                Ok(DispatchMessage::Quit) => {
                    break;
                },
                Err(_) => panic!("Error receiving message in handler")
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::NewSession => {
                                Err(WebDriverError::new(
                                    ErrorStatus::UnsupportedOperation,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession => Ok(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl <U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }
        debug!("Got request {} {:?}", req.method, req.uri);
        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => {
                            api.decode_request(req.method, &path[..], &body[..])
                        },
                        Err(_) => return
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res = c.send(DispatchMessage::HandleWebDriver(message,
                                                                                send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return
                                    }
                                }
                            },
                            Err(_) => {
                                error!("Something terrible happened");
                                return
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => match data {
                                Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                Err(err) => (err.http_status(), err.to_json_string()),
                            },
                            Err(e) => panic!("Error reading response: {:?}", e)
                        }
                    },
                    Err(err) => {
                        (err.http_status(), err.to_json_string())
                    }
                };
                debug!("Returning status {:?}", status);
                debug!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentType::json());
                res.send(&resp_body.as_bytes()).unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler<U>,
             U: 'static+WebDriverExtensionRoute>(address: SocketAddr,
                                                 handler: T,
                                                 extension_routes:Vec<(Method, &str, U)>) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let mut server = Server::http(address).unwrap();
    server.keep_alive(None);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.handle(http_handler).unwrap();
}
<|endoftext|>