<commit_before>extern crate clap;
extern crate serde_json;
extern crate wdsapi;
extern crate rayon;

mod cli;

use rayon::prelude::*;
use serde_json::de::from_reader;
use serde_json::ser::to_string_pretty;
use std::thread::{JoinHandle, spawn};

use wdsapi::collection;
use wdsapi::collection::{Collection, NewCollection};
use wdsapi::common::{Credentials, Status, credentials_from_file};
use wdsapi::configuration;
use wdsapi::configuration::Configuration;
use wdsapi::environment;
use wdsapi::environment::{Environment, NewEnvironment};

#[derive(Clone, Debug)]
struct EnvironmentInfo {
    environment: Environment,
    configurations: Vec<Configuration>,
    collections: Vec<Collection>,
}

#[derive(Clone, Debug)]
struct DiscoveryServiceInfo {
    creds: Credentials,
    environments: Vec<EnvironmentInfo>,
}

fn get_configurations_thread(creds: &Credentials,
                             env_id: &str)
                             -> JoinHandle<Vec<Configuration>> {
    let creds = creds.clone();
    let env_id = env_id.to_string();
    spawn(move || {
        configuration::list(&creds, &env_id)
            .expect("Failed to get configuration information, in thread")
            .configurations
    })
}

fn get_collections_thread(creds: &Credentials,
                          env_id: &str)
                          -> JoinHandle<Vec<Collection>> {
    let creds = creds.clone();
    let env_id = env_id.to_string();
    spawn(move || {
        collection::list(&creds, &env_id)
            .expect("Failed to get collection information, in thread")
            .collections
            .par_iter()
            .map({
                |col| {
                    collection::detail(&creds, &env_id, &col.collection_id)
                        .expect("Failed to get collection detail, in thread")
                }
            })
            .weight_max()
            .collect()
    })
}

fn environment_info(creds: &Credentials, env: &Environment) -> EnvironmentInfo {
    let env_id = env.environment_id.clone();
    // launch threads for these API calls
    let conf_thread = get_configurations_thread(creds, &env_id);
    let col_thread = get_collections_thread(creds, &env_id);
    // Gather the results from the threads
    let configurations = conf_thread.join()
                                    .expect("Failed to get configuration \
                                             information");
    let collections = col_thread.join()
                                .expect("Failed to get collection information");
    EnvironmentInfo {
        environment: env.clone(),
        configurations: configurations,
        collections: collections,
    }
}

fn discovery_service_info(matches: &clap::ArgMatches) -> DiscoveryServiceInfo {
    let creds_file = matches.value_of("credentials")
                            .expect("Internal error: Missing credentials?");
    let creds = credentials_from_file(creds_file).expect("Invalid credentials");
    let environments = environment::list(&creds)
        .expect("Failed to get environment information")
        .environments
        .par_iter()
        .map({
            |env| environment_info(&creds, env)
        })
        .weight_max()
        .collect();
    DiscoveryServiceInfo {
        creds: creds,
        environments: environments,
    }
}

fn writable_environment(info: &DiscoveryServiceInfo) -> EnvironmentInfo {
    let writables: Vec<EnvironmentInfo> =
        info.environments
            .clone()
            .into_iter()
            .filter({
                |env| !env.environment.read_only
            })
            .collect();

    assert!(writables.len() <= 1,
            format!("Multiple writable environments found {:?}", writables));

    writables.first()
             .expect("No writable environment found")
             .clone()
}

fn newest_configuration(env: &EnvironmentInfo) -> Configuration {
    env.configurations
       .clone()
       .into_iter()
       .max_by_key({
           |i| i.created
       })
       .expect("No configurations found")
}

fn oldest_collection(env: &EnvironmentInfo) -> Collection {
    env.collections
       .clone()
       .into_iter()
       .min_by_key({
           |i| i.created
       })
       .expect("No collections found")
}

fn newest_collection(env: &EnvironmentInfo) -> Collection {
    env.collections
       .clone()
       .into_iter()
       .max_by_key({
           |i| i.created
       })
       .expect("No collections found")
}

fn collection_with_name(env: &EnvironmentInfo, name: &str) -> Collection {
    let f: Vec<Collection> = env.collections
                                .clone()
                                .into_iter()
                                .filter({
                                    |i| i.name == name
                                })
                                .collect();
    assert!(f.len() == 1, format!("No collection matched {}", name));
    f.first().expect("Internal error: count=1, but no last!?").clone()
}

fn collection_with_id(env: &EnvironmentInfo, id: &str) -> Collection {
    let f: Vec<Collection> = env.collections
                                .clone()
                                .into_iter()
                                .filter({
                                    |i| i.collection_id == id
                                })
                                .collect();
    assert!(f.len() == 1, format!("No collection matched {}", id));
    f.last().expect("Internal error: count=1, but no last!?").clone()
}

fn configuration(env: &EnvironmentInfo,
                 configuration_id: &str)
                 -> Configuration {
    env.configurations
       .clone()
       .into_iter()
       .filter({
           |c| c.configuration_id == Some(configuration_id.to_string())
       })
       .last()
       .expect("No configuration found")
       .clone()
}

fn print_env_children(env: &EnvironmentInfo) {
    let mut first = true;
    let configs: &Vec<Configuration> = &env.configurations;
    let collections: &Vec<Collection> = &env.collections;
    for conf in configs {
        if first {
            first = false;
            println!("   Configurations: {}", conf.name)
        } else {
            println!("                   {}", conf.name)
        }
    }
    first = true;
    for col in collections {
        let counts = col.document_counts.clone().unwrap();
        let formatted_counts = if counts.failed > 0 {
            format!("{} available, {} processing, {} failed",
                    counts.available,
                    counts.processing,
                    counts.failed)
        } else if counts.processing > 0 {
            format!("{} available, {} processing",
                    counts.available,
                    counts.processing)
        } else {
            format!("{} available", counts.available)
        };

        if first {
            first = false;
            println!("   Collections: {}, {}", col.name, formatted_counts)
        } else {
            println!("                {}, {}", col.name, formatted_counts)
        }
    }
}

fn show(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    for env_info in info.environments {
        let status = match env_info.environment.status {
            Status::Pending => " - pending",
            _ => {
                if env_info.environment.read_only {
                    " - read only"
                } else {
                    ""
                }
            }
        };
        let capacity = env_info.environment.index_capacity.as_ref();
        match capacity {
            Some(index_capacity) => {
                println!("Environment: {}, {} disk, {} memory{}",
                         env_info.environment.name,
                         index_capacity.disk_usage.total,
                         index_capacity.memory_usage.total,
                         status)
            }
            None => {
                println!("Environment: {}{}",
                         env_info.environment.name,
                         status);
            }
        }
        print_env_children(&env_info)
    }
}

// I suppose there is a standard library way to do this...
fn optional_string(s: &Option<&str>) -> Option<String> {
    match *s {
        Some(s) => Some(s.to_string()),
        None => None,
    }
}

fn create_environment(matches: &clap::ArgMatches) {
    let creds_file = matches.value_of("credentials").unwrap();
    let creds = credentials_from_file(creds_file).unwrap(); // FIXME

    let env_options = NewEnvironment {
        name: matches.value_of("name").unwrap().to_string(),
        description: optional_string(&matches.value_of("description")),
        size: matches.value_of("size").unwrap_or("0").parse::<u64>().unwrap(),
    };
    match environment::create(&creds, &env_options) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_environment response"))
        }
        Err(e) => println!("Failed to create environment {}", e),
    }
}

fn delete_environment(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_id = writable_environment(&info).environment.environment_id;

    match environment::delete(&info.creds, &env_id) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  delete_environment response"))
        }
        Err(e) => println!("Failed to delete environment {}", e),
    }
}

fn create_collection(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();

    let col_options = NewCollection {
        name: matches.value_of("name").unwrap().to_string(),
        description: optional_string(&matches.value_of("description")),
        configuration_id: match matches.value_of("configuration_id") {
            Some(s) => Some(s.to_string()),
            None => newest_configuration(&env_info).configuration_id,
        },
    };

    match collection::create(&info.creds, &env_id, &col_options) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_collection response"))
        }
        Err(e) => println!("Failed to create collection {}", e),
    }
}

fn select_collection(env_info: &EnvironmentInfo,
                     matches: &clap::ArgMatches)
                     -> Collection {
    if matches.is_present("name") {
        collection_with_name(env_info, matches.value_of("name").unwrap())
    } else if matches.is_present("id") {
        collection_with_id(env_info, matches.value_of("id").unwrap())
    } else if matches.is_present("oldest") {
        oldest_collection(env_info)
    } else {
        newest_collection(env_info)
    }
}

fn delete_collection(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();
    if matches.is_present("all") {
        assert!(false, "Deleting all collections is not yet implemented")
    }
    let collection_id = select_collection(&env_info, matches).collection_id;

    match collection::delete(&info.creds, &env_id, &collection_id) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  delete_collection response"))
        }
        Err(e) => println!("Failed to delete collection {}", e),
    }
}

fn create_configuration(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();
    let config_filename =
        matches.value_of("configuration").unwrap().to_string();
    let config_file = std::fs::File::open(config_filename)
        .expect("Failed to read configuration JSON file");
    let config: Configuration = from_reader(config_file)
        .expect("Failed to parse configuration JSON");

    match configuration::create(&info.creds, &env_id, &config) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_collection response"))
        }
        Err(e) => println!("Failed to create collection {}", e),
    }
}

fn crawler_configuration(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);

    let collection = select_collection(&env_info, matches);
    let config = configuration(&env_info, &collection.configuration_id);

    println!("# discovery_service.conf \
              generated by https://github.com/bruceadams/wdsapi
{{
    environment_id   = {:?} # {}
    collection_id    = {:?} # {}
    configuration_id = {:?} # {}

    base_url = {:?}
    credentials {{
            username = {:?}
            password = {:?}
    }}

    api_version = \"2016-11-07\"
    concurrent_upload_connection_limit = 2
    http_timeout = 125
    send_stats {{
            jvm = true
            os  = true
    }}
}}
",
             env_info.environment.environment_id,
             env_info.environment.name,
             collection.collection_id,
             collection.name,
             collection.configuration_id,
             config.name,
             info.creds.url,
             info.creds.username,
             info.creds.password);
}

fn main() {
    rayon::initialize(rayon::Configuration::new().set_num_threads(64))
        .expect("Failed to initialize thread pool");

    let matches = cli::build_cli().get_matches();

    match matches.subcommand() {
        ("show", Some(m)) => show(m),
        ("create-environment", Some(m)) => create_environment(m),
        ("delete-environment", Some(m)) => delete_environment(m),
        ("create-collection", Some(m)) => create_collection(m),
        ("delete-collection", Some(m)) => delete_collection(m),
        ("create-configuration", Some(m)) => create_configuration(m),
        ("crawler-configuration", Some(m)) => crawler_configuration(m),
        _ => println!("Not implemented yet; sorry!"),
    }
}
<commit_msg>Turn on Crawler `check_for_completion`<commit_after>extern crate clap;
extern crate serde_json;
extern crate wdsapi;
extern crate rayon;

mod cli;

use rayon::prelude::*;
use serde_json::de::from_reader;
use serde_json::ser::to_string_pretty;
use std::thread::{JoinHandle, spawn};

use wdsapi::collection;
use wdsapi::collection::{Collection, NewCollection};
use wdsapi::common::{Credentials, Status, credentials_from_file};
use wdsapi::configuration;
use wdsapi::configuration::Configuration;
use wdsapi::environment;
use wdsapi::environment::{Environment, NewEnvironment};

#[derive(Clone, Debug)]
struct EnvironmentInfo {
    environment: Environment,
    configurations: Vec<Configuration>,
    collections: Vec<Collection>,
}

#[derive(Clone, Debug)]
struct DiscoveryServiceInfo {
    creds: Credentials,
    environments: Vec<EnvironmentInfo>,
}

fn get_configurations_thread(creds: &Credentials,
                             env_id: &str)
                             -> JoinHandle<Vec<Configuration>> {
    let creds = creds.clone();
    let env_id = env_id.to_string();
    spawn(move || {
        configuration::list(&creds, &env_id)
            .expect("Failed to get configuration information, in thread")
            .configurations
    })
}

fn get_collections_thread(creds: &Credentials,
                          env_id: &str)
                          -> JoinHandle<Vec<Collection>> {
    let creds = creds.clone();
    let env_id = env_id.to_string();
    spawn(move || {
        collection::list(&creds, &env_id)
            .expect("Failed to get collection information, in thread")
            .collections
            .par_iter()
            .map({
                |col| {
                    collection::detail(&creds, &env_id, &col.collection_id)
                        .expect("Failed to get collection detail, in thread")
                }
            })
            .weight_max()
            .collect()
    })
}

fn environment_info(creds: &Credentials, env: &Environment) -> EnvironmentInfo {
    let env_id = env.environment_id.clone();
    // launch threads for these API calls
    let conf_thread = get_configurations_thread(creds, &env_id);
    let col_thread = get_collections_thread(creds, &env_id);
    // Gather the results from the threads
    let configurations = conf_thread.join()
                                    .expect("Failed to get configuration \
                                             information");
    let collections = col_thread.join()
                                .expect("Failed to get collection information");
    EnvironmentInfo {
        environment: env.clone(),
        configurations: configurations,
        collections: collections,
    }
}

fn discovery_service_info(matches: &clap::ArgMatches) -> DiscoveryServiceInfo {
    let creds_file = matches.value_of("credentials")
                            .expect("Internal error: Missing credentials?");
    let creds = credentials_from_file(creds_file).expect("Invalid credentials");
    let environments = environment::list(&creds)
        .expect("Failed to get environment information")
        .environments
        .par_iter()
        .map({
            |env| environment_info(&creds, env)
        })
        .weight_max()
        .collect();
    DiscoveryServiceInfo {
        creds: creds,
        environments: environments,
    }
}

fn writable_environment(info: &DiscoveryServiceInfo) -> EnvironmentInfo {
    let writables: Vec<EnvironmentInfo> =
        info.environments
            .clone()
            .into_iter()
            .filter({
                |env| !env.environment.read_only
            })
            .collect();

    assert!(writables.len() <= 1,
            format!("Multiple writable environments found {:?}", writables));

    writables.first()
             .expect("No writable environment found")
             .clone()
}

fn newest_configuration(env: &EnvironmentInfo) -> Configuration {
    env.configurations
       .clone()
       .into_iter()
       .max_by_key({
           |i| i.created
       })
       .expect("No configurations found")
}

fn oldest_collection(env: &EnvironmentInfo) -> Collection {
    env.collections
       .clone()
       .into_iter()
       .min_by_key({
           |i| i.created
       })
       .expect("No collections found")
}

fn newest_collection(env: &EnvironmentInfo) -> Collection {
    env.collections
       .clone()
       .into_iter()
       .max_by_key({
           |i| i.created
       })
       .expect("No collections found")
}

fn collection_with_name(env: &EnvironmentInfo, name: &str) -> Collection {
    let f: Vec<Collection> = env.collections
                                .clone()
                                .into_iter()
                                .filter({
                                    |i| i.name == name
                                })
                                .collect();
    assert!(f.len() == 1, format!("No collection matched {}", name));
    f.first().expect("Internal error: count=1, but no last!?").clone()
}

fn collection_with_id(env: &EnvironmentInfo, id: &str) -> Collection {
    let f: Vec<Collection> = env.collections
                                .clone()
                                .into_iter()
                                .filter({
                                    |i| i.collection_id == id
                                })
                                .collect();
    assert!(f.len() == 1, format!("No collection matched {}", id));
    f.last().expect("Internal error: count=1, but no last!?").clone()
}

fn configuration(env: &EnvironmentInfo,
                 configuration_id: &str)
                 -> Configuration {
    env.configurations
       .clone()
       .into_iter()
       .filter({
           |c| c.configuration_id == Some(configuration_id.to_string())
       })
       .last()
       .expect("No configuration found")
       .clone()
}

fn print_env_children(env: &EnvironmentInfo) {
    let mut first = true;
    let configs: &Vec<Configuration> = &env.configurations;
    let collections: &Vec<Collection> = &env.collections;
    for conf in configs {
        if first {
            first = false;
            println!("   Configurations: {}", conf.name)
        } else {
            println!("                   {}", conf.name)
        }
    }
    first = true;
    for col in collections {
        let counts = col.document_counts.clone().unwrap();
        let formatted_counts = if counts.failed > 0 {
            format!("{} available, {} processing, {} failed",
                    counts.available,
                    counts.processing,
                    counts.failed)
        } else if counts.processing > 0 {
            format!("{} available, {} processing",
                    counts.available,
                    counts.processing)
        } else {
            format!("{} available", counts.available)
        };

        if first {
            first = false;
            println!("   Collections: {}, {}", col.name, formatted_counts)
        } else {
            println!("                {}, {}", col.name, formatted_counts)
        }
    }
}

fn show(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    for env_info in info.environments {
        let status = match env_info.environment.status {
            Status::Pending => " - pending",
            _ => {
                if env_info.environment.read_only {
                    " - read only"
                } else {
                    ""
                }
            }
        };
        let capacity = env_info.environment.index_capacity.as_ref();
        match capacity {
            Some(index_capacity) => {
                println!("Environment: {}, {} disk, {} memory{}",
                         env_info.environment.name,
                         index_capacity.disk_usage.total,
                         index_capacity.memory_usage.total,
                         status)
            }
            None => {
                println!("Environment: {}{}",
                         env_info.environment.name,
                         status);
            }
        }
        print_env_children(&env_info)
    }
}

// I suppose there is a standard library way to do this...
fn optional_string(s: &Option<&str>) -> Option<String> {
    match *s {
        Some(s) => Some(s.to_string()),
        None => None,
    }
}

fn create_environment(matches: &clap::ArgMatches) {
    let creds_file = matches.value_of("credentials").unwrap();
    let creds = credentials_from_file(creds_file).unwrap(); // FIXME

    let env_options = NewEnvironment {
        name: matches.value_of("name").unwrap().to_string(),
        description: optional_string(&matches.value_of("description")),
        size: matches.value_of("size").unwrap_or("0").parse::<u64>().unwrap(),
    };
    match environment::create(&creds, &env_options) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_environment response"))
        }
        Err(e) => println!("Failed to create environment {}", e),
    }
}

fn delete_environment(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_id = writable_environment(&info).environment.environment_id;

    match environment::delete(&info.creds, &env_id) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  delete_environment response"))
        }
        Err(e) => println!("Failed to delete environment {}", e),
    }
}

fn create_collection(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();

    let col_options = NewCollection {
        name: matches.value_of("name").unwrap().to_string(),
        description: optional_string(&matches.value_of("description")),
        configuration_id: match matches.value_of("configuration_id") {
            Some(s) => Some(s.to_string()),
            None => newest_configuration(&env_info).configuration_id,
        },
    };

    match collection::create(&info.creds, &env_id, &col_options) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_collection response"))
        }
        Err(e) => println!("Failed to create collection {}", e),
    }
}

fn select_collection(env_info: &EnvironmentInfo,
                     matches: &clap::ArgMatches)
                     -> Collection {
    if matches.is_present("name") {
        collection_with_name(env_info, matches.value_of("name").unwrap())
    } else if matches.is_present("id") {
        collection_with_id(env_info, matches.value_of("id").unwrap())
    } else if matches.is_present("oldest") {
        oldest_collection(env_info)
    } else {
        newest_collection(env_info)
    }
}

fn delete_collection(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();
    if matches.is_present("all") {
        assert!(false, "Deleting all collections is not yet implemented")
    }
    let collection_id = select_collection(&env_info, matches).collection_id;

    match collection::delete(&info.creds, &env_id, &collection_id) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  delete_collection response"))
        }
        Err(e) => println!("Failed to delete collection {}", e),
    }
}

fn create_configuration(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);
    let env_id = env_info.environment.environment_id.clone();
    let config_filename =
        matches.value_of("configuration").unwrap().to_string();
    let config_file = std::fs::File::open(config_filename)
        .expect("Failed to read configuration JSON file");
    let config: Configuration = from_reader(config_file)
        .expect("Failed to parse configuration JSON");

    match configuration::create(&info.creds, &env_id, &config) {
        Ok(response) => {
            println!("{}",
                     to_string_pretty(&response)
                         .expect("Internal error: failed to format \
                                  create_collection response"))
        }
        Err(e) => println!("Failed to create collection {}", e),
    }
}

fn crawler_configuration(matches: &clap::ArgMatches) {
    let info = discovery_service_info(matches);
    let env_info = writable_environment(&info);

    let collection = select_collection(&env_info, matches);
    let config = configuration(&env_info, &collection.configuration_id);

    println!("# discovery_service.conf \
              generated by https://github.com/bruceadams/wdsapi
{{
    environment_id   = {:?} # {}
    collection_id    = {:?} # {}
    configuration_id = {:?} # {}

    base_url = {:?}
    credentials {{
            username = {:?}
            password = {:?}
    }}

    api_version = \"2016-11-07\"
    check_for_completion = true
    concurrent_upload_connection_limit = 10
    http_timeout = 125
    send_stats {{
            jvm = true
            os  = true
    }}
}}
",
             env_info.environment.environment_id,
             env_info.environment.name,
             collection.collection_id,
             collection.name,
             collection.configuration_id,
             config.name,
             info.creds.url,
             info.creds.username,
             info.creds.password);
}

fn main() {
    rayon::initialize(rayon::Configuration::new().set_num_threads(64))
        .expect("Failed to initialize thread pool");

    let matches = cli::build_cli().get_matches();

    match matches.subcommand() {
        ("show", Some(m)) => show(m),
        ("create-environment", Some(m)) => create_environment(m),
        ("delete-environment", Some(m)) => delete_environment(m),
        ("create-collection", Some(m)) => create_collection(m),
        ("delete-collection", Some(m)) => delete_collection(m),
        ("create-configuration", Some(m)) => create_configuration(m),
        ("crawler-configuration", Some(m)) => crawler_configuration(m),
        _ => println!("Not implemented yet; sorry!"),
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate getopts;

use std::io::{self, Read};
use std::fs::File;
use rand::Rng;
use getopts::Options;

const DEFAULT_DICT_FILE: &'static str = "/usr/share/dict/words";

struct Config {
    min: usize,
    max: usize,
    number: usize,
    count: usize,
    filename: String,
    downcase: bool,
}

impl Config {
    fn new() -> Config {
        Config {
            min: 4,
            max: 6,
            number: 4,
            count: 1,
            filename: DEFAULT_DICT_FILE.to_string(),
            downcase: true,
        }
    }
}

fn read_words(filename: &String) -> io::Result<String> {
    let mut dict = File::open(filename).unwrap();
    let mut buf = String::new();
    try!(dict.read_to_string(&mut buf));
    Ok(buf)
}

fn shuffled_words<'a>(source: &'a String, cfg: &Config) -> Vec<&'a str> {
    // Not ideal, but whatever.

    let mut lines: Vec<_> = source
        .lines()
        .filter(|x| x.len() >= cfg.min && x.len() <= cfg.max)
        .collect();
    rand::thread_rng().shuffle(&mut lines);
    lines
}

fn usage(opts: &Options, err: Option<String>) {
    if let Some(e) = err {
        println!("{}\n", e);
    }
    let brief = "Usage: pwrs [options]";
    println!("{}", opts.usage(&brief));
}

fn config() -> Option<Config> {
    let mut cfg = Config::new();
    let args: Vec<_> = std::env::args().collect();
    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optopt("m", "min", "Minimum number of characters in words", "MIN");
    opts.optopt("M", "max", "Maximum number of characters in words", "MAX");
    opts.optopt("c", "count", "Count of passphrases to print", "COUNT");
    opts.optopt("n", "number", "Number of words to include in passphrases", "NUMBER");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            usage(&opts, Some(f.to_string()));
            // This is only in nightlies and for once I'm writing a thing that works on stable rust
            // ::std::env::set_exit_status(1);
            return None;
        }
    };

    if matches.opt_present("help") {
        usage(&opts, None);
        return None;
    }

    macro_rules! unpack_opt(
        ($name:ident) => {
            if let Some(s) = matches.opt_str(stringify!($name)) {
                match s.parse() {
                    Ok(i) => cfg.$name = i,
                    Err(e) => {
                        usage(&opts, Some(e.to_string()));
                        return None;
                    }
                }
            }
        }
    );

    unpack_opt!(min);
    unpack_opt!(max);
    unpack_opt!(count);
    unpack_opt!(number);

    Some(cfg)
}

fn main() {
    let cfg = match config() {
        Some(c) => c,
        None => return,
    };
    let words = read_words(&cfg.filename).unwrap();

    let print = |word: &str| {
        if cfg.downcase {
            print!("{} ",  word.to_lowercase());
        } else {
            print!("{} ", word);
        }
    };

    for _ in (0..cfg.count) {
        let shuffled = shuffled_words(&words, &cfg);

        for i in (0..(cfg.number)) {
            print(shuffled[i]);
        }
        println!("");
    }
}
<commit_msg>Clean up printing<commit_after>extern crate rand;
extern crate getopts;

use std::io::{self, Read};
use std::fs::File;
use rand::Rng;
use getopts::Options;

const DEFAULT_DICT_FILE: &'static str = "/usr/share/dict/words";

struct Config {
    min: usize,
    max: usize,
    number: usize,
    count: usize,
    filename: String,
    downcase: bool,
}

impl Config {
    fn new() -> Config {
        Config {
            min: 4,
            max: 6,
            number: 4,
            count: 1,
            filename: DEFAULT_DICT_FILE.to_string(),
            downcase: true,
        }
    }
}

fn read_words(filename: &String) -> io::Result<String> {
    let mut dict = File::open(filename).unwrap();
    let mut buf = String::new();
    try!(dict.read_to_string(&mut buf));
    Ok(buf)
}

fn shuffled_words<'a>(source: &'a String, cfg: &Config) -> Vec<&'a str> {
    // Not ideal, but whatever.

    let mut lines: Vec<_> = source
        .lines()
        .filter(|x| x.len() >= cfg.min && x.len() <= cfg.max)
        .collect();
    rand::thread_rng().shuffle(&mut lines);
    lines
}

fn usage(opts: &Options, err: Option<String>) {
    if let Some(e) = err {
        println!("{}\n", e);
    }
    let brief = "Usage: pwrs [options]";
    println!("{}", opts.usage(&brief));
}

fn config() -> Option<Config> {
    let mut cfg = Config::new();
    let args: Vec<_> = std::env::args().collect();
    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optopt("m", "min", "Minimum number of characters in words", "MIN");
    opts.optopt("M", "max", "Maximum number of characters in words", "MAX");
    opts.optopt("c", "count", "Count of passphrases to print", "COUNT");
    opts.optopt("n", "number", "Number of words to include in passphrases", "NUMBER");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            usage(&opts, Some(f.to_string()));
            // This is only in nightlies and for once I'm writing a thing that works on stable rust
            // ::std::env::set_exit_status(1);
            return None;
        }
    };

    if matches.opt_present("help") {
        usage(&opts, None);
        return None;
    }

    macro_rules! unpack_opt(
        ($name:ident) => {
            if let Some(s) = matches.opt_str(stringify!($name)) {
                match s.parse() {
                    Ok(i) => cfg.$name = i,
                    Err(e) => {
                        usage(&opts, Some(e.to_string()));
                        return None;
                    }
                }
            }
        }
    );

    unpack_opt!(min);
    unpack_opt!(max);
    unpack_opt!(count);
    unpack_opt!(number);

    Some(cfg)
}

fn main() {
    let cfg = match config() {
        Some(c) => c,
        None => return,
    };
    let words = read_words(&cfg.filename).unwrap();

    for _ in (0..cfg.count) {
        let shuffled = shuffled_words(&words, &cfg);

        let out = shuffled[0..cfg.number].connect(" ");
        if cfg.downcase {
            println!("{}",  out.to_lowercase());
        } else {
            println!("{}", out);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate walkdir;

use walkdir::WalkDir;
use rand::{Rng, thread_rng};
use std::env;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::Error;
use std::cmp;

fn main() {
    let mut recursive: bool = false;
    let mut file: String = String::from("");
    let mut i: i32 = -1;

    for argument in env::args() {
        i += 1;
        if i == 0 {
            continue;
        }

        if argument.to_lowercase() == "--help" || argument.to_lowercase() == "-help" {
            help();
            return;
        } else if argument.to_lowercase() == "--v" || argument.to_lowercase() == "-v" ||
           argument.to_lowercase() == "-version" ||
           argument.to_lowercase() == "--version" {
            version();
            return;
        } else if argument.to_lowercase() == "-r" {
            recursive = true;
        } else {
            file = argument;
            break;
        }
    }
    if file == "" {
        help();
        return;
    }
    file = get_path(&file);

    if recursive {
        for entry in WalkDir::new(file) {
            let entry = entry.unwrap();
            trumpify(entry.path().display().to_string());
        }
    } else {
        trumpify(file)
    }
}

fn get_path2(file: &str) -> Result<String, Error> {
    let path = try!(fs::canonicalize(file));
    return Ok(path.display().to_string());
}

fn get_path(file: &str) -> String {
    return get_path2(file).unwrap_or(file.to_string());
}

fn read_file2(file: &str) -> Result<String, Error> {
    let mut file = try!(File::open(file));
    let mut contents: Vec<u8> = Vec::new();
    try!(file.read_to_end(&mut contents));
    let ret = String::from_utf8(contents).unwrap_or("".to_string());
    return Ok(ret);
}

fn read_file(file: &str) -> String {
    return read_file2(file).unwrap_or("".to_string());
}

fn write_file2(file: &str, content: String) -> Result<bool, Error> {
    let mut f = try!(File::create(file));
    try!(f.write_all(content.as_bytes()));

    try!(f.sync_data());
    return Ok(false);
}

fn write_file(file: &str, content: String) {
    write_file2(file, content).unwrap_or(false);
}

fn version() {
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump-0.1.0");
    println!("\x1b[32mWebsite:");
    println!("\x1b[0m    https://github.com/x13machine/trump/");
    println!("\x1b[32mCreator:");
    println!("\x1b[0m    <Googolplexking/x13machine> https://googolplex.ninja/");
}
fn help() {
    println!("\x1b[32mHelp:");
    println!("\x1b[0m    trump --help");
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump -v");
    println!("\x1b[32mFiles:");
    println!("\x1b[0m    trump <File>");
    println!("\x1b[32mDirectories:");
    println!("\x1b[0m    trump -r <Directory>");
}

fn trumpify(file: String) {
    let dirs: Vec<&str> = file.split("/").collect::<Vec<&str>>();
    let mut name: String = String::from(dirs[dirs.len() - 1]);
    name = format!("{}{}",
                   &name[0..1].to_uppercase(),
                   &name[1..name.len()].to_lowercase());
    // Ansi Color Codes!!!
    println!("\x1b[32mMaking Great Again:\x1b[0m {}", file);

    let text = format!("Make {} Great Again!", name);

    let mut content: String = read_file(&file);
    if content == "" {
        return;
    }

    let loops = cmp::max(content.len() / text.len() / 2, 1);
    let mut rng = thread_rng();
    for _ in 0..loops {
        let place: usize = rng.gen_range(0, content.len() as u32) as usize;
        let part1: String = String::from(&content[0..place]);
        let part2: String =
            String::from(&content[cmp::min(place + text.len(), content.len())..content.len()]);
        content = format!("{}{}{}", part1, text, part2);
    }
    write_file(&file, content);
}
<commit_msg>Remove needless return statements<commit_after>extern crate rand;
extern crate walkdir;

use walkdir::WalkDir;
use rand::{Rng, thread_rng};
use std::env;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::Error;
use std::cmp;

fn main() {
    let mut recursive: bool = false;
    let mut file: String = String::from("");
    let mut i: i32 = -1;

    for argument in env::args() {
        i += 1;
        if i == 0 {
            continue;
        }

        if argument.to_lowercase() == "--help" || argument.to_lowercase() == "-help" {
            help();
            return;
        } else if argument.to_lowercase() == "--v" || argument.to_lowercase() == "-v" ||
           argument.to_lowercase() == "-version" ||
           argument.to_lowercase() == "--version" {
            version();
            return;
        } else if argument.to_lowercase() == "-r" {
            recursive = true;
        } else {
            file = argument;
            break;
        }
    }
    if file == "" {
        help();
        return;
    }
    file = get_path(&file);

    if recursive {
        for entry in WalkDir::new(file) {
            let entry = entry.unwrap();
            trumpify(entry.path().display().to_string());
        }
    } else {
        trumpify(file)
    }
}

fn get_path2(file: &str) -> Result<String, Error> {
    let path = try!(fs::canonicalize(file));
    Ok(path.display().to_string())
}

fn get_path(file: &str) -> String {
    get_path2(file).unwrap_or(file.to_string())
}

fn read_file2(file: &str) -> Result<String, Error> {
    let mut file = try!(File::open(file));
    let mut contents: Vec<u8> = Vec::new();
    try!(file.read_to_end(&mut contents));
    let ret = String::from_utf8(contents).unwrap_or("".to_string());
    Ok(ret)
}

fn read_file(file: &str) -> String {
    read_file2(file).unwrap_or("".to_string())
}

fn write_file2(file: &str, content: String) -> Result<bool, Error> {
    let mut f = try!(File::create(file));
    try!(f.write_all(content.as_bytes()));

    try!(f.sync_data());
    Ok(false)
}

fn write_file(file: &str, content: String) {
    write_file2(file, content).unwrap_or(false);
}

fn version() {
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump-0.1.0");
    println!("\x1b[32mWebsite:");
    println!("\x1b[0m    https://github.com/x13machine/trump/");
    println!("\x1b[32mCreator:");
    println!("\x1b[0m    <Googolplexking/x13machine> https://googolplex.ninja/");
}
fn help() {
    println!("\x1b[32mHelp:");
    println!("\x1b[0m    trump --help");
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump -v");
    println!("\x1b[32mFiles:");
    println!("\x1b[0m    trump <File>");
    println!("\x1b[32mDirectories:");
    println!("\x1b[0m    trump -r <Directory>");
}

fn trumpify(file: String) {
    let dirs: Vec<&str> = file.split("/").collect::<Vec<&str>>();
    let mut name: String = String::from(dirs[dirs.len() - 1]);
    name = format!("{}{}",
                   &name[0..1].to_uppercase(),
                   &name[1..name.len()].to_lowercase());
    // Ansi Color Codes!!!
    println!("\x1b[32mMaking Great Again:\x1b[0m {}", file);

    let text = format!("Make {} Great Again!", name);

    let mut content: String = read_file(&file);
    if content == "" {
        return;
    }

    let loops = cmp::max(content.len() / text.len() / 2, 1);
    let mut rng = thread_rng();
    for _ in 0..loops {
        let place: usize = rng.gen_range(0, content.len() as u32) as usize;
        let part1: String = String::from(&content[0..place]);
        let part2: String =
            String::from(&content[cmp::min(place + text.len(), content.len())..content.len()]);
        content = format!("{}{}{}", part1, text, part2);
    }
    write_file(&file, content);
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate getopts;

use std::io::{self, Read};
use std::fs::File;
use rand::Rng;
use getopts::Options;

const DEFAULT_DICT_FILE: &'static str = "/usr/share/dict/words";

struct Config {
    min: usize,
    max: usize,
    number: usize,
    count: usize,
    filename: String,
    downcase: bool,
}

impl Config {
    fn new() -> Config {
        Config {
            min: 4,
            max: 6,
            number: 4,
            count: 1,
            filename: DEFAULT_DICT_FILE.to_string(),
            downcase: true,
        }
    }
}

fn read_words(filename: &String) -> io::Result<String> {
    let mut dict = File::open(filename).unwrap();
    let mut buf = String::new();
    try!(dict.read_to_string(&mut buf));
    Ok(buf)
}

fn shuffled_words<'a>(source: &'a String, cfg: &Config) -> Vec<&'a str> {
    // Not ideal, but whatever.

    let mut lines: Vec<_> = source
        .lines()
        .filter(|x| x.len() >= cfg.min && x.len() <= cfg.max)
        .collect();
    rand::thread_rng().shuffle(&mut lines);
    lines
}

fn usage(opts: &Options, err: Option<String>) {
    if let Some(e) = err {
        println!("{}\n", e);
    }
    let brief = "Usage: pwrs [options]";
    println!("{}", opts.usage(&brief));
}

fn config() -> Option<Config> {
    let mut cfg = Config::new();
    let args: Vec<_> = std::env::args().collect();
    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optopt("m", "min", "Minimum number of characters in words", "MIN");
    opts.optopt("M", "max", "Maximum number of characters in words", "MAX");
    opts.optopt("c", "count", "Count of passphrases to print", "COUNT");
    opts.optopt("n", "number", "Number of words to include in passphrases", "NUMBER");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            usage(&opts, Some(f.to_string()));
            // This is only in nightlies and for once I'm writing a thing that works on stable rust
            // ::std::env::set_exit_status(1);
            return None;
        }
    };

    if matches.opt_present("help") {
        usage(&opts, None);
        return None;
    }

    macro_rules! unpack_opt(
        ($name:ident) => {
            if let Some(s) = matches.opt_str(stringify!($name)) {
                match s.parse() {
                    Ok(i) => cfg.$name = i,
                    Err(e) => {
                        usage(&opts, Some(e.to_string()));
                        return None;
                    }
                }
            }
        }
    );

    unpack_opt!(min);
    unpack_opt!(max);
    unpack_opt!(count);
    unpack_opt!(number);

    Some(cfg)
}

fn main() {
    let cfg = match config() {
        Some(c) => c,
        None => return,
    };
    let words = read_words(&cfg.filename).unwrap();

    for _ in (0..cfg.count) {
        let shuffled = shuffled_words(&words, &cfg);

        let out = shuffled[0..cfg.number].connect(" ");
        if cfg.downcase {
            println!("{}",  out.to_lowercase());
        } else {
            println!("{}", out);
        }
    }
}
<commit_msg>Add a benchmark for shuffling the wordlists<commit_after>#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

extern crate rand;
extern crate getopts;

use std::io::{self, Read};
use std::fs::File;
use rand::Rng;
use getopts::Options;

const DEFAULT_DICT_FILE: &'static str = "/usr/share/dict/words";

struct Config {
    min: usize,
    max: usize,
    number: usize,
    count: usize,
    filename: String,
    downcase: bool,
}

impl Config {
    fn new() -> Config {
        Config {
            min: 4,
            max: 6,
            number: 4,
            count: 1,
            filename: DEFAULT_DICT_FILE.to_string(),
            downcase: true,
        }
    }
}

fn read_words(filename: &String) -> io::Result<String> {
    let mut dict = File::open(filename).unwrap();
    let mut buf = String::new();
    try!(dict.read_to_string(&mut buf));
    Ok(buf)
}

fn shuffled_words<'a>(source: &'a String, cfg: &Config) -> Vec<&'a str> {
    // Not ideal, but whatever.

    let mut lines: Vec<_> = source
        .lines()
        .filter(|x| x.len() >= cfg.min && x.len() <= cfg.max)
        .collect();
    rand::thread_rng().shuffle(&mut lines);
    lines
}

fn usage(opts: &Options, err: Option<String>) {
    if let Some(e) = err {
        println!("{}\n", e);
    }
    let brief = "Usage: pwrs [options]";
    println!("{}", opts.usage(&brief));
}

fn config() -> Option<Config> {
    let mut cfg = Config::new();
    let args: Vec<_> = std::env::args().collect();
    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optopt("m", "min", "Minimum number of characters in words", "MIN");
    opts.optopt("M", "max", "Maximum number of characters in words", "MAX");
    opts.optopt("c", "count", "Count of passphrases to print", "COUNT");
    opts.optopt("n", "number", "Number of words to include in passphrases", "NUMBER");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            usage(&opts, Some(f.to_string()));
            // This is only in nightlies and for once I'm writing a thing that works on stable rust
            // ::std::env::set_exit_status(1);
            return None;
        }
    };

    if matches.opt_present("help") {
        usage(&opts, None);
        return None;
    }

    macro_rules! unpack_opt(
        ($name:ident) => {
            if let Some(s) = matches.opt_str(stringify!($name)) {
                match s.parse() {
                    Ok(i) => cfg.$name = i,
                    Err(e) => {
                        usage(&opts, Some(e.to_string()));
                        return None;
                    }
                }
            }
        }
    );

    unpack_opt!(min);
    unpack_opt!(max);
    unpack_opt!(count);
    unpack_opt!(number);

    Some(cfg)
}

fn main() {
    let cfg = match config() {
        Some(c) => c,
        None => return,
    };
    let words = read_words(&cfg.filename).unwrap();

    for _ in (0..cfg.count) {
        let shuffled = shuffled_words(&words, &cfg);

        let out = shuffled[0..cfg.number].connect(" ");
        if cfg.downcase {
            println!("{}",  out.to_lowercase());
        } else {
            println!("{}", out);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::Bencher;

    #[bench]
    fn with_defaults(b: &mut Bencher) {
        let cfg = ::Config::new();
        let words = ::read_words(&cfg.filename).unwrap();
        b.iter(|| {
            let _ = ::shuffled_words(&words, &cfg);
        })
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(convert)]
#![feature(core)] // old syntax

extern crate toml;
extern crate iron;
extern crate router;
extern crate core;
extern crate liquid;

use std::fs::File;
use std::io::Read;
use std::collections::HashMap;
use core::convert::From as ConvertFrom;

//use iron::Iron;
use iron::prelude::*;
use iron::headers::*;
use iron::{status, headers};

//use core::str::Str;

use router::{Router};

use liquid::Context;
use liquid::Renderable;
use liquid::Value;

use liquidwrapper::LiquidTemplate;
use templatewrapper::TemplateWrapper;

mod templatewrapper;
mod liquidwrapper;

#[derive(Clone)]
struct SbWikiServer {
    listenaddr: String,
    wikipath: String,
    wikifrontpage: String,
}

impl SbWikiServer {
    //TODO: pass config object instead of bunch of argument
    pub fn new(cfgfile: &'static str) -> SbWikiServer {
        let mut listenaddr    = String::new();
        let wikipath      = String::from("/wiki");
        let wikifrontpage = String::from("FrontPage");

        //loading toml configure file
        let mut confs = String::new();
        File::open(cfgfile).unwrap().read_to_string(&mut confs);
        let mut parser = toml::Parser::new(confs.as_str());

        //add portnum to address
        let root = parser.parse().unwrap();

        let port = root["server"].lookup("port").unwrap();
        let host = root["server"].lookup("host").unwrap();

        let portstr = format!("{}:{}",
                              host.as_str().unwrap(),
                              port.as_integer().unwrap());

        listenaddr.push_str(portstr.as_str());

        println!("{}", listenaddr);

        SbWikiServer {
            listenaddr: listenaddr,
            wikipath: wikipath,
            wikifrontpage: wikifrontpage,
        }
    }

    pub fn open(self, isTLS: bool) {
        let mut wikidocument = self.wikipath.clone();
        wikidocument.push_str("/*");

        let mut router = Router::new();
        //TODO: fetch it from toml config.
        let wpath = self.wikipath.clone();
        let listenaddr = self.listenaddr.clone();

        let cloned = self.clone();
        router.get(wpath.as_str(),
                   move |req: &mut Request| -> IronResult<Response>
                   {cloned.wikiredirect(req)});

        let cloned = self.clone();
        router.get(wikidocument.as_str(),
                   move |req: &mut Request| -> IronResult<Response>
                   {cloned.wikihandler(req)});

        let cloned = self.clone();
        router.get("/",
                   move |req: &mut Request| -> IronResult<Response>
                   {cloned.roothandler(req)});

        let cloned = self.clone();
        router.get("/:query",
                   move |req: &mut Request| -> IronResult<Response>
                   {cloned.roothandler(req)});

        Iron::new(router).http(
            listenaddr.as_str()).unwrap();
    }

    fn roothandler(&self, req: &mut Request)
                   -> IronResult<Response> {
        let ref query = req.extensions.get::<Router>()
            .unwrap().find("query").unwrap_or("/");

        Ok(Response::with((status::Ok, *query)))
    }

    fn wikiredirect(&self, req: &mut Request)
                    -> IronResult<Response> {
        let mut url = req.url.path.clone();
        let mut header = Headers::new();
        let mut newpath = String::new();

        //TODO: customizable root page.
        url.push(self.wikifrontpage.clone());

        for i in url.iter() {
            newpath.push_str("/");
            newpath.push_str(i);
        }

        println!("{}", newpath);
        header.set(Location(newpath));

        let mut resp: Response = Response::with((status::MovedPermanently));
        resp.headers = header;

        Ok(resp)
    }

    fn wikihandler(&self, req: &mut Request)
                   -> IronResult<Response> {
        let ref requrl = req.url.clone();
        let mut header = Headers::new();
        let mut urlpath = requrl.path.clone();

        for i in urlpath.iter() {
            println!("{}", i);
        }

        //Liquid testing code
        let mut replace_table: HashMap<String, String> = HashMap::new();
        replace_table.insert(String::from("message"), String::from("Hello, liquid!"));
        let mut con = Context::new();
        for (key, value) in replace_table {
            con.set_val(&key, Value::Str(value));
        }
        let mut template_str = String::from("hello.liquid");
        let template = LiquidTemplate::new(template_str);
        let page = template.render(&mut con).unwrap();

        header.set(
            ContentType(iron::mime::Mime(iron::mime::TopLevel::Text, iron::mime::SubLevel::Html, vec![]))
        );

        let mut resp: Response = Response::with((status::Ok, page));
        resp.headers = header;

        Ok(resp)
    }
}

fn main() {
    //TODO: make it can fetch config file name from command line argument.
    let sbwiki: SbWikiServer = SbWikiServer::new("config.toml");

    sbwiki.open(false);
}

<commit_msg>Rust 1.6 apply & remove Clone in SbWikiServer<commit_after>extern crate toml;
extern crate iron;
extern crate router;
extern crate liquid;

use std::fs::File;
use std::io::Read;
use std::collections::HashMap;
use std::convert::From;
use std::borrow::Borrow;

//use iron::Iron;
use iron::prelude::*;
use iron::headers::{Header, HeaderFormat, Headers, Location, ContentType};
use iron::{status, headers};

//use core::str::Str;

use router::{Router};

use liquid::Context;
use liquid::Renderable;
use liquid::Value;

use liquidwrapper::LiquidTemplate;
use templatewrapper::TemplateWrapper;

mod templatewrapper;
mod liquidwrapper;

struct SbWikiServer {
    listenaddr: String,
    wikipath: String,
    wikifrontpage: String,
}

impl SbWikiServer {
    //TODO: pass config object instead of bunch of argument
    pub fn new(cfgfile: &'static str) -> SbWikiServer {
        let mut listenaddr    = String::new();
        let wikipath      = String::from("/wiki");
        let wikifrontpage = String::from("FrontPage");

        //loading toml configure file
        let mut confs = String::new();
        File::open(cfgfile).unwrap().read_to_string(&mut confs);
        let mut parser = toml::Parser::new(confs.borrow() as &str);

        //add portnum to address
        let root = parser.parse().unwrap();

        let port = root["server"].lookup("port").unwrap();
        let host = root["server"].lookup("host").unwrap();

        let portstr = format!("{}:{}",
                              host.as_str().unwrap(),
                              port.as_integer().unwrap());

        listenaddr.push_str(portstr.borrow());

        println!("{}", listenaddr);

        SbWikiServer {
            listenaddr: listenaddr,
            wikipath: wikipath,
            wikifrontpage: wikifrontpage,
        }
    }

    pub fn open(self, isTLS: bool) {
        let mut wikidocument = self.wikipath.clone();
        wikidocument.push_str("/*");

        let mut router = Router::new();
        //TODO: fetch it from toml config.
        let wpath = self.wikipath.clone();
        let listenaddr = self.listenaddr.clone();

        router.get(wpath.borrow() as &str,
                   move |req: &mut Request| -> IronResult<Response>
                   {SbWikiServer::wikiredirect(&self, req)});

        router.get(wikidocument.borrow() as &str,
                   move |req: &mut Request| -> IronResult<Response>
                   {SbWikiServer::wikihandler(req)});

        router.get("/",
                   move |req: &mut Request| -> IronResult<Response>
                   {SbWikiServer::roothandler(req)});

        router.get("/:query",
                   move |req: &mut Request| -> IronResult<Response>
                   {SbWikiServer::roothandler(req)});

        Iron::new(router).http(
            listenaddr.borrow() as &str).unwrap();
    }

    fn roothandler(req: &mut Request)
                   -> IronResult<Response> {
        let ref query = req.extensions.get::<Router>()
            .unwrap().find("query").unwrap_or("/");

        Ok(Response::with((status::Ok, *query)))
    }

    fn wikiredirect(wiki: &SbWikiServer, req: &mut Request)
                    -> IronResult<Response> {
        let mut url = req.url.path.clone();
        let mut header = Headers::new();
        let mut newpath = String::new();

        //TODO: customizable root page.
        url.push(wiki.wikifrontpage.clone());

        for i in url.iter() {
            newpath.push_str("/");
            newpath.push_str(i);
        }

        println!("{}", newpath);
        header.set(Location(newpath));

        let mut resp: Response = Response::with((status::MovedPermanently));
        resp.headers = header;

        Ok(resp)
    }

    fn wikihandler(req: &mut Request)
                   -> IronResult<Response> {
        let ref requrl = req.url.clone();
        let mut header = Headers::new();
        let mut urlpath = requrl.path.clone();

        for i in urlpath.iter() {
            println!("{}", i);
        }

        //Liquid testing code
        let mut replace_table: HashMap<String, String> = HashMap::new();
        replace_table.insert(String::from("message"), String::from("Hello, liquid!"));
        let mut con = Context::new();
        for (key, value) in replace_table {
            con.set_val(&key, Value::Str(value));
        }
        let mut template_str = String::from("hello.liquid");
        let template = LiquidTemplate::new(template_str);
        let page = template.render(&mut con).unwrap();

        header.set(
            ContentType(iron::mime::Mime(iron::mime::TopLevel::Text, iron::mime::SubLevel::Html, vec![]))
        );

        let mut resp: Response = Response::with((status::Ok, page));
        resp.headers = header;

        Ok(resp)
    }
}

fn main() {
    //TODO: make it can fetch config file name from command line argument.
    let sbwiki: SbWikiServer = SbWikiServer::new("config.toml");

    sbwiki.open(false);
}

<|endoftext|>


<commit_before>use std::fs;
use std::fs::File;
use std::io::SeekFrom;
use std::io::Seek;
use std::io::Read;
use std::io::Write;
use std::io::Take;
use std::io::Error;
use std::io::ErrorKind;
use std::collections::HashMap;
use std::env;
use std::cmp;
use std::path::Path;

static __VERSION__: &str = "0.1.2";

fn advance_magic(magic: &mut u32) -> u32 {
    let old = *magic;
    *magic = magic.wrapping_mul(7) + 3;
    return old;
}

fn ru32(stream: &mut File, result: &mut u32) -> bool {
    let mut buff = [0; 4];
    if let Err(_) = stream.read_exact(&mut buff) {
        return false;
    }

    *result = (((buff[0] as u32) << 0x00) & 0x000000FF) |
              (((buff[1] as u32) << 0x08) & 0x0000FF00) |
              (((buff[2] as u32) << 0x10) & 0x00FF0000) |
              (((buff[3] as u32) << 0x18) & 0xFF000000) ;

    return true;
}

struct EntryData {
    offset: u32,
    magic: u32,
    size: u32,
}

struct Entry {
    offset: u32,
    magic: u32,
    stream: Take<File>,
}

impl Entry {
    fn read(&mut self, buf: &mut [u8]) -> usize {
        let mut maski = self.offset % 4;
        let mut offset = 0;
        let count = self.stream.read(buf).unwrap();
        let pre = ((4 - maski) % 4) as usize;

        self.offset += count as u32;

        for _ in 0..cmp::min(pre, count) {
            buf[offset] ^= ((self.magic >> (maski * 8)) & 0xff) as u8;
            maski += 1; offset += 1;
            if maski % 4 == 0 {
                advance_magic(&mut self.magic);
                maski = 0;
            }
        }

        if maski != 0 { return count; }

        unsafe {
            let len = (count - pre) / 4;
            let dat = buf[..len*4].as_mut_ptr() as *mut u32;

            for i in 0..(len as isize) {
                *dat.offset(i) = *dat.offset(i) ^ advance_magic(&mut self.magic);
            }

            offset += len * 4;
        }

        for _ in 0..(count%4) {
            buf[offset] ^= ((self.magic >> (maski * 8)) & 0xff) as u8;
            maski += 1; offset += 1;
            if maski % 4 == 0 {
                advance_magic(&mut self.magic);
                maski = 0;
            }
        }

        return count;
    }
}

struct RGSSArchive {
    entry: HashMap<String, EntryData>,
    stream: File,
}

impl RGSSArchive {
    fn open(location: &str) -> Result<RGSSArchive, Error> {
        let mut stream = File::open(location)?;

        let mut header = [0u8; 8];
        stream.read_exact(&mut header)?;

        match String::from_utf8(header[..6].to_vec()) {
            Ok(header) => {
                if header != "RGSSAD" {
                    return Err(Error::new(ErrorKind::InvalidData, "File header mismatch."));
                }
            },
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "File header mismatch."))
        }

        // Check rgssad file version.
        if header[7] < 3 { RGSSArchive::open_rgssad(stream) } else { RGSSArchive::open_rgss3a(stream) }
    }

    fn open_rgssad(mut stream: File) -> Result<RGSSArchive, Error> {
        let mut magic = 0xDEADCAFEu32;
        let mut entry = HashMap::new();

        loop {
            let mut name_len: u32 = 0;
            let resp = ru32(&mut stream, &mut name_len);
            if !resp { break }
            name_len ^= advance_magic(&mut magic);

            let mut name_buf = vec![0u8; name_len as usize];
            stream.read_exact(&mut name_buf)?;
            for i in 0..(name_len as usize) {
                name_buf[i] ^= (advance_magic(&mut magic) & 0xff) as u8;
                if name_buf[i] == '\\' as u8 { name_buf[i] = '/' as u8 }
            }
            let name_buf = String::from_utf8(name_buf).unwrap();

            let mut data = EntryData { size: 0, offset: 0, magic: 0 };
            ru32(&mut stream, &mut data.size);
            data.size ^= advance_magic(&mut magic);
            data.offset = stream.seek(SeekFrom::Current(0))? as u32;
            data.magic = magic;

            stream.seek(SeekFrom::Current(data.size as i64))?;
            entry.insert(name_buf, data);
        }

        stream.seek(SeekFrom::Start(0))?;
        return Ok(RGSSArchive { entry: entry, stream: stream });
    }

    fn open_rgss3a(mut stream: File) -> Result<RGSSArchive, Error> {
        let mut magic = 0u32;
        let mut entry = HashMap::new();

        ru32(&mut stream, &mut magic);
        magic = magic * 9 + 3;

        loop {
            let mut offset: u32 = 0;
            let mut size: u32 = 0;
            let mut start_magic: u32 = 0;
            let mut name_len: u32 = 0;

            let resp = ru32(&mut stream, &mut offset);
            if !resp { break }
            offset ^= magic;

            if offset == 0 { break }

            let resp = ru32(&mut stream, &mut size);
            if !resp { break }
            size ^= magic;

            let resp = ru32(&mut stream, &mut start_magic);
            if !resp { break }
            start_magic ^= magic;

            let resp = ru32(&mut stream, &mut name_len);
            if !resp { break }
            name_len ^= magic;

            let mut name_buf = vec![0u8; name_len as usize];
            stream.read_exact(&mut name_buf)?;
            for i in 0..(name_len as usize) {
                name_buf[i] ^= ((magic >> 8*(i%4)) & 0xff) as u8;
                if name_buf[i] == '\\' as u8 { name_buf[i] = '/' as u8 }
            }
            let name_buf = String::from_utf8(name_buf).unwrap();

            let data = EntryData {
                size: size, offset: offset, magic: start_magic
            };

            entry.insert(name_buf, data);
        }

        stream.seek(SeekFrom::Start(0))?;
        return Ok(RGSSArchive { entry: entry, stream: stream });
    }

    fn read_entry(&self, key: &str) -> Option<Entry> {
        match self.entry.get(key) {
            Some(entry) => {
                let mut stream = self.stream.try_clone().unwrap();
                stream.seek(SeekFrom::Start(entry.offset as u64)).unwrap();
                Some(Entry {
                    offset: 0,
                    magic: entry.magic,
                    stream: stream.take(entry.size as u64),
                })
            }
            None => None
        }
    }
}

fn usage() {
    println!("Extract rgssad/rgss2a/rgss3a files.\n");
    println!("Commands:");
    println!("    version");
    println!("    list        <filename>");
    println!("    save        <filename> <location>");
}

fn create(location: String) -> File {
    let path = Path::new(location.as_str());
    fs::create_dir_all(path.parent().unwrap()).unwrap();
    return File::create(path.to_str().unwrap()).unwrap();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    match args.len() {
        1 => usage(),
        2 => {
            if args[1] != "version" { usage(); return; }
            println!("version: {}", __VERSION__);
        },
        3 => {
            if args[1] != "list" { usage(); return; }
            match RGSSArchive::open(args[2].as_str()) {
                Ok(archive) => {
                    for (name, data) in &archive.entry {
                        println!("{}: EntryData {{ size: {}, offset: {}, magic: {} }}", name, data.size, data.offset, data.magic);
                    }
                },
                Err(err) => println!("FAILED: {}", err.to_string())
            }
        },
        4 => {
            if args[1] != "save" { usage(); return; }
            let archive = RGSSArchive::open(args[2].as_str());
            if let Err(err) = archive {
                println!("FAILED: {}", err.to_string()); return;
            }
            let archive = archive.unwrap();
            let entries = archive.entry.iter();

            let mut buf = [0u8; 8192];

            for (name, _) in entries {
                println!("Extracting: {}", name);
                let mut entry = archive.read_entry(name).unwrap();
                let mut file = create(args[3].clone() + &"/".to_string() + &name.to_string());
                loop {
                    let count = entry.read(&mut buf);
                    if count == 0 { break }
                    if count < buf.len() {
                        file.write(&buf[..count]).unwrap();
                    } else {
                        file.write(&buf).unwrap();
                    }
                }
            }
        },
        _ => usage(),
    }
}
<commit_msg>delete some unnecessary code.<commit_after>use std::fs;
use std::fs::File;
use std::io::SeekFrom;
use std::io::Seek;
use std::io::Read;
use std::io::Write;
use std::io::Take;
use std::io::Error;
use std::io::ErrorKind;
use std::collections::HashMap;
use std::env;
use std::cmp;
use std::path::Path;

static __VERSION__: &str = "0.1.2";

fn advance_magic(magic: &mut u32) -> u32 {
    let old = *magic;
    *magic = magic.wrapping_mul(7) + 3;
    return old;
}

fn ru32(stream: &mut File, result: &mut u32) -> bool {
    let mut buff = [0; 4];
    if let Err(_) = stream.read_exact(&mut buff) {
        return false;
    }

    *result = (((buff[0] as u32) << 0x00) & 0x000000FF) |
              (((buff[1] as u32) << 0x08) & 0x0000FF00) |
              (((buff[2] as u32) << 0x10) & 0x00FF0000) |
              (((buff[3] as u32) << 0x18) & 0xFF000000) ;

    return true;
}

struct EntryData {
    offset: u32,
    magic: u32,
    size: u32,
}

struct Entry {
    offset: u32,
    magic: u32,
    stream: Take<File>,
}

impl Entry {
    fn read(&mut self, buf: &mut [u8]) -> usize {
        let mut maski = self.offset % 4;
        let mut offset = 0;
        let count = self.stream.read(buf).unwrap();
        let pre = ((4 - maski) % 4) as usize;

        self.offset += count as u32;

        for _ in 0..cmp::min(pre, count) {
            buf[offset] ^= ((self.magic >> (maski * 8)) & 0xff) as u8;
            maski += 1; offset += 1;
            if maski % 4 == 0 {
                advance_magic(&mut self.magic);
                maski = 0;
            }
        }

        if maski != 0 { return count; }

        unsafe {
            let len = (count - pre) / 4;
            let dat = buf[..len*4].as_mut_ptr() as *mut u32;

            for i in 0..(len as isize) {
                *dat.offset(i) = *dat.offset(i) ^ advance_magic(&mut self.magic);
            }

            offset += len * 4;
        }

        for _ in 0..(count%4) {
            buf[offset] ^= ((self.magic >> (maski * 8)) & 0xff) as u8;
            maski += 1; offset += 1;
            if maski % 4 == 0 {
                advance_magic(&mut self.magic);
                maski = 0;
            }
        }

        return count;
    }
}

struct RGSSArchive {
    entry: HashMap<String, EntryData>,
    stream: File,
}

impl RGSSArchive {
    fn open(location: &str) -> Result<RGSSArchive, Error> {
        let mut stream = File::open(location)?;

        let mut header = [0u8; 8];
        stream.read_exact(&mut header)?;

        match String::from_utf8(header[..6].to_vec()) {
            Ok(header) => {
                if header != "RGSSAD" {
                    return Err(Error::new(ErrorKind::InvalidData, "File header mismatch."));
                }
            },
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "File header mismatch."))
        }

        // Check rgssad file version.
        if header[7] < 3 { RGSSArchive::open_rgssad(stream) } else { RGSSArchive::open_rgss3a(stream) }
    }

    fn open_rgssad(mut stream: File) -> Result<RGSSArchive, Error> {
        let mut magic = 0xDEADCAFEu32;
        let mut entry = HashMap::new();

        loop {
            let mut name_len: u32 = 0;
            let resp = ru32(&mut stream, &mut name_len);
            if !resp { break }
            name_len ^= advance_magic(&mut magic);

            let mut name_buf = vec![0u8; name_len as usize];
            stream.read_exact(&mut name_buf)?;
            for i in 0..(name_len as usize) {
                name_buf[i] ^= (advance_magic(&mut magic) & 0xff) as u8;
                if name_buf[i] == '\\' as u8 { name_buf[i] = '/' as u8 }
            }
            let name_buf = String::from_utf8(name_buf).unwrap();

            let mut data = EntryData { size: 0, offset: 0, magic: 0 };
            ru32(&mut stream, &mut data.size);
            data.size ^= advance_magic(&mut magic);
            data.offset = stream.seek(SeekFrom::Current(0))? as u32;
            data.magic = magic;

            stream.seek(SeekFrom::Current(data.size as i64))?;
            entry.insert(name_buf, data);
        }

        stream.seek(SeekFrom::Start(0))?;
        return Ok(RGSSArchive { entry: entry, stream: stream });
    }

    fn open_rgss3a(mut stream: File) -> Result<RGSSArchive, Error> {
        let mut magic = 0u32;
        let mut entry = HashMap::new();

        ru32(&mut stream, &mut magic);
        magic = magic * 9 + 3;

        loop {
            let mut offset: u32 = 0;
            let mut size: u32 = 0;
            let mut start_magic: u32 = 0;
            let mut name_len: u32 = 0;

            let resp = ru32(&mut stream, &mut offset);
            if !resp { break }
            offset ^= magic;

            if offset == 0 { break }

            let resp = ru32(&mut stream, &mut size);
            if !resp { break }
            size ^= magic;

            let resp = ru32(&mut stream, &mut start_magic);
            if !resp { break }
            start_magic ^= magic;

            let resp = ru32(&mut stream, &mut name_len);
            if !resp { break }
            name_len ^= magic;

            let mut name_buf = vec![0u8; name_len as usize];
            stream.read_exact(&mut name_buf)?;
            for i in 0..(name_len as usize) {
                name_buf[i] ^= ((magic >> 8*(i%4)) & 0xff) as u8;
                if name_buf[i] == '\\' as u8 { name_buf[i] = '/' as u8 }
            }
            let name_buf = String::from_utf8(name_buf).unwrap();

            let data = EntryData {
                size: size, offset: offset, magic: start_magic
            };

            entry.insert(name_buf, data);
        }

        stream.seek(SeekFrom::Start(0))?;
        return Ok(RGSSArchive { entry: entry, stream: stream });
    }

    fn read_entry(&self, key: &str) -> Option<Entry> {
        match self.entry.get(key) {
            Some(entry) => {
                let mut stream = self.stream.try_clone().unwrap();
                stream.seek(SeekFrom::Start(entry.offset as u64)).unwrap();
                Some(Entry {
                    offset: 0,
                    magic: entry.magic,
                    stream: stream.take(entry.size as u64),
                })
            }
            None => None
        }
    }
}

fn usage() {
    println!("Extract rgssad/rgss2a/rgss3a files.\n");
    println!("Commands:");
    println!("    version");
    println!("    list        <filename>");
    println!("    save        <filename> <location>");
}

fn create(location: String) -> File {
    let path = Path::new(location.as_str());
    fs::create_dir_all(path.parent().unwrap()).unwrap();
    return File::create(path.to_str().unwrap()).unwrap();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    match args.len() {
        1 => usage(),
        2 => {
            if args[1] != "version" { usage(); return; }
            println!("version: {}", __VERSION__);
        },
        3 => {
            if args[1] != "list" { usage(); return; }
            match RGSSArchive::open(args[2].as_str()) {
                Ok(archive) => {
                    for (name, data) in &archive.entry {
                        println!("{}: EntryData {{ size: {}, offset: {}, magic: {} }}", name, data.size, data.offset, data.magic);
                    }
                },
                Err(err) => println!("FAILED: {}", err.to_string())
            }
        },
        4 => {
            if args[1] != "save" { usage(); return; }
            let archive = RGSSArchive::open(args[2].as_str());
            if let Err(err) = archive {
                println!("FAILED: {}", err.to_string()); return;
            }
            let archive = archive.unwrap();
            let entries = archive.entry.iter();

            let mut buf = [0u8; 8192];

            for (name, _) in entries {
                println!("Extracting: {}", name);
                let mut entry = archive.read_entry(name).unwrap();
                let mut file = create(args[3].clone() + &"/".to_string() + &name.to_string());
                loop {
                    let count = entry.read(&mut buf);
                    if count == 0 { break }
                    file.write(&buf[..count]).unwrap();
                }
            }
        },
        _ => usage(),
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
use clap::Arg;
mod directory;

fn main() {
    let matches = clap::App::new(env!("CARGO_PKG_NAME"))
                      .version(env!("CARGO_PKG_VERSION"))
                      .author(env!("CARGO_PKG_AUTHORS"))
                      .about(env!("CARGO_PKG_DESCRIPTION"))
                      .arg(Arg::with_name("DIRECTORY")
                               .help("Directory to list")
                               .index(1)
                               .default_value("."))
                      .arg(Arg::with_name("all")
                               .help("List all files (including dotfiles)")
                               .short("a"))
                      .get_matches();

    let ignore_dotfiles = matches.occurrences_of("all") == 0;
    let path = matches.value_of("DIRECTORY").unwrap().to_string();

    let tree = directory::read_recursive(&path, ignore_dotfiles);
    directory::print::print_tree(&tree);
}
<commit_msg>don't use env vars not provided by stable cargo<commit_after>#[macro_use]
extern crate clap;
use clap::Arg;
mod directory;

fn main() {
    // TODO: replace strings duplicated from Cargo.toml once 1.9.0 hits stable
    //                           env!("CARGO_PKG_NAME")
    let matches = clap::App::new("treesize")
                      .version(env!("CARGO_PKG_VERSION"))
    //                       env!("CARGO_PKG_DESCRIPTION")
                      .about("Print directory tree (like GNU tree), sorted by size")
    //                        env!("CARGO_PKG_AUTHORS")
                      .author("melak47 <melak47@gmail.com>")
                      .arg(Arg::with_name("DIRECTORY")
                               .help("Directory to list")
                               .index(1)
                               .default_value("."))
                      .arg(Arg::with_name("all")
                               .help("List all files (including dotfiles)")
                               .short("a"))
                      .get_matches();

    let ignore_dotfiles = matches.occurrences_of("all") == 0;
    let path = matches.value_of("DIRECTORY").unwrap().to_string();

    let tree = directory::read_recursive(&path, ignore_dotfiles);
    directory::print::print_tree(&tree);
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::{Arc, Mutex, Condvar};

fn main() {

    let wrapper = Arc::new((Mutex::new(false), Condvar::new()));
    let wrapper_temp = wrapper.clone();

    let (ref lock, ref cvar) = *wrapper;
    let mut state = lock.lock().unwrap();

    thread::spawn(move || {
        let (ref lock, ref cvar) = *wrapper_temp;
        let mut state = lock.lock().unwrap();

        *state = true;
        cvar.notify_one();
        println!("notify main");
    });

    while !*state {
        println!("before main wait");

        state = cvar.wait(state).unwrap();

        println!("after main wait");
    }
}<commit_msg>test: mutex<commit_after>use std::thread;
use std::sync::{Arc, Mutex, Condvar};

fn main() {
    let arc = Arc::new((Mutex::new(false), Condvar::new()));
    let arc_temp = arc.clone();

    thread::spawn(move || {

        let (ref lock, ref condvar) = *arc_temp;
        let mut state = lock.lock().unwrap();

        *state = true;

        condvar.notify_one();

        println!("thread {}", *state);
    });

    let (ref lock, ref condvar) = *arc;
    let mut state = lock.lock().unwrap();

    println!("main {}", *state);

    while !*state {
        println!("main prev {}", *state);
        state = condvar.wait(state).unwrap();
        println!("main next {}", *state);
    }
}

<|endoftext|>


<commit_before>// A terminal shell implementation in Rust
use std::io;

/*enum GenericOperand<T> {
	Present(T),
	Empty,
}

use GenericOperand::Present;

struct Command<T> {
	name : &'static str,
	operand : Present(T),
}*/

fn main() {

	let mut cmd = String::new();
	/*let my_cmd = Command {name:"echo",operand:};*/
	loop {

	print!("{}::","\u{019B}");
	io::stdin().read_line(&mut cmd)
		.ok()
		.expect("Error: Command Not Found");
	let cmd_vec:Vec<&str> = cmd.split(" ").collect();

	/*for i in cmd_vec {
		println!("{:?}",i);
	}*/

	match cmd_vec[0] {
		"echo" => println!("{:?}",cmd_vec[1]),
		"quit" => break,
		_ => println!("Error: Command not found"),

	}

	}
}<commit_msg>Update main.rs<commit_after>// A terminal shell implementation in Rust
use std::io;

fn main() {

	let mut cmd = String::new();
	loop {

	print!("{}::","\u{019B}");
	io::stdin().read_line(&mut cmd)
		.ok()
		.expect("Error: Command Not Found");

	let cmd_vec:Vec<&str> = cmd.split(" ").collect();

	match cmd_vec[0] {
		"echo" => println!("{:?}",cmd_vec[1]),
		"quit" => break,
		_ => println!("Error: Command not found"),

	}

	}
}
<|endoftext|>