<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

extern crate clap;
extern crate daemonize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate serde;
extern crate serde_json;
extern crate blake2_rfc as blake2;

extern crate grin_api as api;
extern crate grin_grin as grin;
extern crate grin_wallet as wallet;
extern crate grin_config as config;
extern crate grin_core as core;
extern crate secp256k1zkp as secp;

use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{Arg, App, SubCommand, ArgMatches};
use daemonize::Daemonize;

use secp::Secp256k1;

use config::GlobalConfig;
use wallet::WalletConfig;
use core::global;

fn start_from_config_file(mut global_config: GlobalConfig) {
	info!(
		"Starting the Grin server from configuration file at {}",
		global_config.config_file_path.unwrap().to_str().unwrap()
	);

	global::set_mining_mode(global_config.members.as_mut().unwrap().server.clone().mining_parameter_mode.unwrap());

	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

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

	let args = App::new("Grin")
    .version("0.1")
    .author("The Grin Team")
    .about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
				.arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true)
                     .multiple(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
				.arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
					 .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

    // specification of the wallet commands and options
    .subcommand(SubCommand::with_name("wallet")
                .about("Wallet software for Grin")
                .arg(Arg::with_name("pass")
                     .short("p")
                     .long("pass")
                     .help("Wallet passphrase used to generate the private key seed")
                     .takes_value(true))
				.arg(Arg::with_name("data_dir")
                     .short("dd")
                     .long("data_dir")
                     .help("Directory in which to store wallet files (defaults to current directory)")
                     .takes_value(true))
				.arg(Arg::with_name("port")
                     .short("r")
                     .long("port")
                     .help("Port on which to run the wallet receiver when in receiver mode")
                     .takes_value(true))
				.arg(Arg::with_name("api_server_address")
                     .short("a")
                     .long("api_server_address")
                     .help("The api address of a running node on which to check inputs and post transactions")
                     .takes_value(true))
                .subcommand(SubCommand::with_name("receive")
                            .about("Run the wallet in receiving mode. If an input file is provided, will process it, otherwise runs in server mode waiting for send requests.")
                            .arg(Arg::with_name("input")
                                 .help("Partial transaction to receive, expects as a JSON file.")
                                 .short("i")
                                 .long("input")
                                 .takes_value(true)))
                .subcommand(SubCommand::with_name("send")
                            .about("Builds a transaction to send someone some coins. By default, the transaction will just be printed to stdout. If a destination is provided, the command will attempt to contact the receiver at that address and send the transaction directly.")
                            .arg(Arg::with_name("amount")
                                 .help("Amount to send in the smallest denomination")
                                 .index(1))
                            .arg(Arg::with_name("dest")
                                 .help("Send the transaction to the provided server")
                                 .short("d")
                                 .long("dest")
                                 .takes_value(true))))
    .get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args);
		}

		// client commands and options
		("client", Some(client_args)) => {
			match client_args.subcommand() {
				("status", _) => {
					println!("status info...");
				}
				_ => panic!("Unknown client command, use 'grin help client' for details"),
			}
		}

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		// If nothing is specified, try to load up and use a config file instead
		// this should possibly become the way to configure most things
		// with most command line options being phased out
		_ => {
			// This will return a global config object,
			// which will either contain defaults for all
			// of the config structures or a configuration
			// read from a config file

			let global_config = GlobalConfig::new(None);
			match global_config {
				Ok(gc) => {
					if gc.using_config_file {
						start_from_config_file(gc);
					} else {
						// won't attempt to just start with defaults,
						// and will reject
						println!("Unknown command, and no configuration file was found.");
						println!("Use 'grin help' for a list of all commands.");
					}
				}
				Err(e) => {
					println!("{}", e);
				}
			}

		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches) {
	info!("Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = GlobalConfig::default().members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "127.0.0.1";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config
			.mining_config
			.as_mut()
			.unwrap()
			.wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	/*let mut sc = GlobalConfig::default();
	sc.members.as_mut().unwrap().server = server_config.clone();
	println!("{}", sc.ser_config().unwrap());*/

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!("Grin server succesfully started."),
				Err(e) => error!("Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		_ => panic!("Unknown server command, use 'grin help server' for details"),
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let hd_seed = wallet_args.value_of("pass").expect(
		"Wallet passphrase required.",
	);

	// TODO do something closer to BIP39, eazy solution right now
	let seed = blake2::blake2b::blake2b(32, &[], hd_seed.as_bytes());

	let s = Secp256k1::new();
	let key = wallet::ExtendedKey::from_seed(&s, seed.as_bytes()).expect(
		"Error deriving extended key from seed.",
	);

	let mut wallet_config = WalletConfig::default();
	if let Some(port) = wallet_args.value_of("port") {
		let default_ip = "127.0.0.1";
		wallet_config.api_http_addr = format!("{}:{}", default_ip, port);
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	match wallet_args.subcommand() {

		("receive", Some(receive_args)) => {
			if let Some(f) = receive_args.value_of("input") {
				let mut file = File::open(f).expect("Unable to open transaction file.");
				let mut contents = String::new();
				file.read_to_string(&mut contents).expect(
					"Unable to read transaction file.",
				);
				wallet::receive_json_tx(&wallet_config, &key, contents.as_str()).unwrap();
			} else {
				info!(
					"Starting the Grin wallet receiving daemon at {}...",
					wallet_config.api_http_addr
				);
				let mut apis = api::ApiServer::new("/v1".to_string());
				apis.register_endpoint(
					"/receive".to_string(),
					wallet::WalletReceiver {
						key: key,
						config: wallet_config.clone(),
					},
				);
				apis.start(wallet_config.api_http_addr).unwrap_or_else(|e| {
					error!("Failed to start Grin wallet receiver: {}.", e);
				});
			}
		}
		("send", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(&wallet_config, &key, amount, dest.to_string()).unwrap();
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}
<commit_msg>Reconcile config file with command line switches (#113)<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

extern crate clap;
extern crate daemonize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate serde;
extern crate serde_json;
extern crate blake2_rfc as blake2;

extern crate grin_api as api;
extern crate grin_grin as grin;
extern crate grin_wallet as wallet;
extern crate grin_config as config;
extern crate grin_core as core;
extern crate secp256k1zkp as secp;

use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{Arg, App, SubCommand, ArgMatches};
use daemonize::Daemonize;

use secp::Secp256k1;

use config::GlobalConfig;
use wallet::WalletConfig;
use core::global;

fn start_from_config_file(mut global_config: GlobalConfig) {
	info!(
		"Starting the Grin server from configuration file at {}",
		global_config.config_file_path.unwrap().to_str().unwrap()
	);

	global::set_mining_mode(
		global_config
			.members
			.as_mut()
			.unwrap()
			.server
			.clone()
			.mining_parameter_mode
			.unwrap(),
	);

	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

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

	// First, load a global config object,
	// then modify that object with any switches
	// found so that the switches override the
	// global config file

	// This will return a global config object,
	// which will either contain defaults for all // of the config structures or a
	// configuration
	// read from a config file

	let mut global_config = GlobalConfig::new(None).unwrap_or_else(|e| {
		panic!("Error parsing config file: {}", e);
	});

	if global_config.using_config_file {
		info!(
			"Using configuration file at: {}",
			global_config
				.config_file_path
				.clone()
				.unwrap()
				.to_str()
				.unwrap()
		);
		global::set_mining_mode(
			global_config
				.members
				.as_mut()
				.unwrap()
				.server
				.clone()
				.mining_parameter_mode
				.unwrap(),
		);
	}

	let args = App::new("Grin")
    .version("0.1")
    .author("The Grin Team")
    .about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
                .arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true)
                     .multiple(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
                .arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
                .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

    // specification of the wallet commands and options
    .subcommand(SubCommand::with_name("wallet")
                .about("Wallet software for Grin")
                .arg(Arg::with_name("pass")
                     .short("p")
                     .long("pass")
                     .help("Wallet passphrase used to generate the private key seed")
                     .takes_value(true))
				.arg(Arg::with_name("data_dir")
                     .short("dd")
                     .long("data_dir")
                     .help("Directory in which to store wallet files (defaults to current \
                     directory)")
                     .takes_value(true))
				.arg(Arg::with_name("port")
                     .short("r")
                     .long("port")
                     .help("Port on which to run the wallet receiver when in receiver mode")
                     .takes_value(true))
				.arg(Arg::with_name("api_server_address")
                     .short("a")
                     .long("api_server_address")
                     .help("The api address of a running node on which to check inputs and \
                     post transactions")
                     .takes_value(true))
                .subcommand(SubCommand::with_name("receive")
                            .about("Run the wallet in receiving mode. If an input file is \
                            provided, will process it, otherwise runs in server mode waiting \
                            for send requests.")
                            .arg(Arg::with_name("input")
                                 .help("Partial transaction to receive, expects as a JSON file.")
                                 .short("i")
                                 .long("input")
                                 .takes_value(true)))
                .subcommand(SubCommand::with_name("send")
                            .about("Builds a transaction to send someone some coins. By default, \
                            the transaction will just be printed to stdout. If a destination is \
                            provided, the command will attempt to contact the receiver at that \
                            address and send the transaction directly.")
                            .arg(Arg::with_name("amount")
                                 .help("Amount to send in the smallest denomination")
                                 .index(1))
                            .arg(Arg::with_name("dest")
                                 .help("Send the transaction to the provided server")
                                 .short("d")
                                 .long("dest")
                                 .takes_value(true))))
    .get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args, global_config);
		}

		// client commands and options
		("client", Some(client_args)) => {
			match client_args.subcommand() {
				("status", _) => {
					println!("status info...");
				}
				_ => panic!("Unknown client command, use 'grin help client' for details"),
			}
		}

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		// If nothing is specified, try to just use the config file instead
		// this could possibly become the way to configure most things
		// with most command line options being phased out
		_ => {
			if global_config.using_config_file {
				start_from_config_file(global_config);
			} else {
				// won't attempt to just start with defaults,
				// and will reject
				println!("Unknown command, and no configuration file was found.");
				println!("Use 'grin help' for a list of all commands.");
			}
		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches, global_config: GlobalConfig) {
	info!("Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = global_config.members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "127.0.0.1";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config
			.mining_config
			.as_mut()
			.unwrap()
			.wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!("Grin server succesfully started."),
				Err(e) => error!("Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		_ => panic!("Unknown server command, use 'grin help server' for details"),
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let hd_seed = wallet_args.value_of("pass").expect(
		"Wallet passphrase required.",
	);

	// TODO do something closer to BIP39, eazy solution right now
	let seed = blake2::blake2b::blake2b(32, &[], hd_seed.as_bytes());

	let s = Secp256k1::new();
	let key = wallet::ExtendedKey::from_seed(&s, seed.as_bytes()).expect(
		"Error deriving extended key from seed.",
	);

	let mut wallet_config = WalletConfig::default();
	if let Some(port) = wallet_args.value_of("port") {
		let default_ip = "127.0.0.1";
		wallet_config.api_http_addr = format!("{}:{}", default_ip, port);
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	match wallet_args.subcommand() {

		("receive", Some(receive_args)) => {
			if let Some(f) = receive_args.value_of("input") {
				let mut file = File::open(f).expect("Unable to open transaction file.");
				let mut contents = String::new();
				file.read_to_string(&mut contents).expect(
					"Unable to read transaction file.",
				);
				wallet::receive_json_tx(&wallet_config, &key, contents.as_str()).unwrap();
			} else {
				info!(
					"Starting the Grin wallet receiving daemon at {}...",
					wallet_config.api_http_addr
				);
				let mut apis = api::ApiServer::new("/v1".to_string());
				apis.register_endpoint(
					"/receive".to_string(),
					wallet::WalletReceiver {
						key: key,
						config: wallet_config.clone(),
					},
				);
				apis.start(wallet_config.api_http_addr).unwrap_or_else(|e| {
					error!("Failed to start Grin wallet receiver: {}.", e);
				});
			}
		}
		("send", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(&wallet_config, &key, amount, dest.to_string()).unwrap();
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}
<|endoftext|>


<commit_before>
extern crate mprovision;
extern crate docopt;
#[macro_use(version)]
extern crate version;
extern crate chrono;

use std::io::{self, Write};
use std::process;
use std::path::Path;
use std::error;
use std::fmt;
use docopt::Docopt;
use mprovision as mp;

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision search <text> [<directory>]
  mprovision remove <uuid> [<directory>]
  mprovision show-xml <uuid> [<directory>]
  mprovision show-expired --days <days> [<directory>]
  mprovision remove-expired [<directory>]
  mprovision (-h | --help)
  mprovision --version

Options:
  -h --help     Show this help message.
  --version     Show version.
";

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(format!("mprovision {}", version!()))).parse())
        .unwrap_or_else(|e| e.exit());

    match Command::from_args(&args).execute() {
        Ok(_) => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        }
    }
}

struct Command<'a> {
    args: &'a ::docopt::ArgvMap,
}

impl<'a> Command<'a> {
    fn from_args(args: &'a ::docopt::ArgvMap) -> Self {
        Command { args: args }
    }

    fn execute(&self) -> CliResult {
        if self.args.get_bool("search") {
            search(self.args)
        } else if self.args.get_bool("remove") {
            remove(self.args)
        } else if self.args.get_bool("show-xml") {
            show_xml(self.args)
        } else if self.args.get_bool("show-expired") {
            show_expired(self.args)
        } else if self.args.get_bool("remove-expired") {
            remove_expired(self.args)
        } else {
            Err(CliError::Custom("Command is not implemented".to_string()))
        }
    }
}

type CliResult = std::result::Result<(), CliError>;

#[derive(Debug)]
enum CliError {
    Lib(mp::Error),
    Custom(String),
    EmptyParameter(&'static str),
}

impl error::Error for CliError {
    fn description(&self) -> &str {
        match *self {
            CliError::Lib(ref e) => e.description(),
            CliError::Custom(ref e) => e,
            CliError::EmptyParameter(_) => "parameter is empty",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        if let CliError::Lib(ref e) = *self {
            Some(e)
        } else {
            None
        }
    }
}

impl fmt::Display for CliError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CliError::Lib(ref e) => error::Error::description(e).fmt(f),
            CliError::Custom(ref e) => e.fmt(f),
            CliError::EmptyParameter(p) => write!(f, "{} should not be empty.", p),
        }
    }
}

impl From<mp::Error> for CliError {
    fn from(e: mp::Error) -> Self {
        CliError::Lib(e)
    }
}

fn search(args: &::docopt::ArgvMap) -> CliResult {
    let text = args.get_str("<text>");
    if text.is_empty() {
        return Err(CliError::EmptyParameter("<text>"));
    }

    let info = try!(mp::with_dir(directory(args), |dir| mp::search(dir, text)));
    if info.profiles.is_empty() {
        println!("Nothing found for '{}'", text);
    } else {
        for profile in &info.profiles {
            println!("\n{}", profile.description());
        }
        println!("\nFound {} of {}", info.profiles.len(), info.total);
    }
    Ok(())
}

fn remove(args: &::docopt::ArgvMap) -> CliResult {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err(CliError::EmptyParameter("<uuid>"));
    }

    let _ = try!(mp::with_dir(directory(args), |dir| mp::remove(dir, uuid)));
    println!("'{}' was removed", uuid);
    Ok(())
}

fn show_xml(args: &::docopt::ArgvMap) -> CliResult {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err(CliError::EmptyParameter("<uuid>"));
    }

    let xml = try!(mp::with_dir(directory(args), |dir| mp::xml(dir, uuid)));
    println!("{}", xml);
    Ok(())
}

fn show_expired(args: &::docopt::ArgvMap) -> CliResult {
    use chrono::*;

    let mut date = UTC::now();
    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
        if days < 0 || days > 365 {
            return Err(CliError::Custom("<days> should be between 0 and 365".to_string()));
        }
        date = date + Duration::days(days);
    }

    let info = try!(mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, date)));
    if info.profiles.is_empty() {
        println!("All provisioning profiles are valid");
    } else {
        for profile in &info.profiles {
            println!("\n{}", profile.description());
        }
        println!("\nFound {} of {}", info.profiles.len(), info.total);
    }
    Ok(())
}

fn remove_expired(args: &::docopt::ArgvMap) -> CliResult {
    use chrono::*;

    let info = try!(mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, UTC::now())));
    if info.profiles.is_empty() {
        println!("All provisioning profiles are valid");
    } else {
        let mut errors_counter = 0;
        let mut removals_counter = 0;
        for profile in info.profiles {
            match std::fs::remove_file(&profile.path) {
                Ok(_) => {
                    removals_counter += 1;
                    println!("'{}' was removed", profile.uuid)
                }
                Err(e) => {
                    errors_counter += 1;
                    println!("Error while trying to remove '{}'", profile.uuid);
                    println!("{}", e);
                }
            }
        }
        println!("Removed {} of {}", removals_counter, info.total);
        if errors_counter > 0 {
            println!("Errors: {}", errors_counter);
        }
    }
    Ok(())
}

fn directory(args: &::docopt::ArgvMap) -> Option<&Path> {
    let dir_name = args.get_str("<directory>");
    if dir_name.is_empty() {
        None
    } else {
        Some(dir_name.as_ref())
    }
}
<commit_msg>Minor fix.<commit_after>
extern crate mprovision;
extern crate docopt;
#[macro_use(version)]
extern crate version;
extern crate chrono;

use std::io::{self, Write};
use std::process;
use std::path::Path;
use std::error;
use std::fmt;
use docopt::Docopt;
use mprovision as mp;

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision search <text> [<directory>]
  mprovision remove <uuid> [<directory>]
  mprovision show-xml <uuid> [<directory>]
  mprovision show-expired --days <days> [<directory>]
  mprovision remove-expired [<directory>]
  mprovision (-h | --help)
  mprovision --version

Options:
  -h --help     Show this help message.
  --version     Show version.
";

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(format!("mprovision {}", version!()))).parse())
        .unwrap_or_else(|e| e.exit());

    match Command::from_args(&args).execute() {
        Ok(_) => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        }
    }
}

struct Command<'a> {
    args: &'a ::docopt::ArgvMap,
}

impl<'a> Command<'a> {
    fn from_args(args: &'a ::docopt::ArgvMap) -> Self {
        Command { args: args }
    }

    fn execute(&self) -> CliResult {
        if self.args.get_bool("search") {
            search(self.args)
        } else if self.args.get_bool("remove") {
            remove(self.args)
        } else if self.args.get_bool("show-xml") {
            show_xml(self.args)
        } else if self.args.get_bool("show-expired") {
            show_expired(self.args)
        } else if self.args.get_bool("remove-expired") {
            remove_expired(self.args)
        } else {
            Err(CliError::Custom("Command is not implemented".to_string()))
        }
    }
}

type CliResult = std::result::Result<(), CliError>;

#[derive(Debug)]
enum CliError {
    Lib(mp::Error),
    Custom(String),
    EmptyParameter(&'static str),
}

impl error::Error for CliError {
    fn description(&self) -> &str {
        match *self {
            CliError::Lib(ref e) => e.description(),
            CliError::Custom(ref e) => e,
            CliError::EmptyParameter(_) => "parameter is empty",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        if let CliError::Lib(ref e) = *self {
            Some(e)
        } else {
            None
        }
    }
}

impl fmt::Display for CliError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CliError::Lib(ref e) => error::Error::description(e).fmt(f),
            CliError::Custom(ref e) => e.fmt(f),
            CliError::EmptyParameter(p) => write!(f, "{} should not be empty.", p),
        }
    }
}

impl From<mp::Error> for CliError {
    fn from(e: mp::Error) -> Self {
        CliError::Lib(e)
    }
}

fn search(args: &::docopt::ArgvMap) -> CliResult {
    let text = args.get_str("<text>");
    if text.is_empty() {
        return Err(CliError::EmptyParameter("<text>"));
    }

    let info = try!(mp::with_dir(directory(args), |dir| mp::search(dir, text)));
    if info.profiles.is_empty() {
        println!("Nothing found for '{}'", text);
    } else {
        for profile in &info.profiles {
            println!("\n{}", profile.description());
        }
        println!("\nFound {} of {}", info.profiles.len(), info.total);
    }
    Ok(())
}

fn remove(args: &::docopt::ArgvMap) -> CliResult {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err(CliError::EmptyParameter("<uuid>"));
    }

    try!(mp::with_dir(directory(args), |dir| mp::remove(dir, uuid)));
    println!("'{}' was removed", uuid);
    Ok(())
}

fn show_xml(args: &::docopt::ArgvMap) -> CliResult {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err(CliError::EmptyParameter("<uuid>"));
    }

    let xml = try!(mp::with_dir(directory(args), |dir| mp::xml(dir, uuid)));
    println!("{}", xml);
    Ok(())
}

fn show_expired(args: &::docopt::ArgvMap) -> CliResult {
    use chrono::*;

    let mut date = UTC::now();
    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
        if days < 0 || days > 365 {
            return Err(CliError::Custom("<days> should be between 0 and 365".to_string()));
        }
        date = date + Duration::days(days);
    }

    let info = try!(mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, date)));
    if info.profiles.is_empty() {
        println!("All provisioning profiles are valid");
    } else {
        for profile in &info.profiles {
            println!("\n{}", profile.description());
        }
        println!("\nFound {} of {}", info.profiles.len(), info.total);
    }
    Ok(())
}

fn remove_expired(args: &::docopt::ArgvMap) -> CliResult {
    use chrono::*;

    let info = try!(mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, UTC::now())));
    if info.profiles.is_empty() {
        println!("All provisioning profiles are valid");
    } else {
        let mut errors_counter = 0;
        let mut removals_counter = 0;
        for profile in info.profiles {
            match std::fs::remove_file(&profile.path) {
                Ok(_) => {
                    removals_counter += 1;
                    println!("'{}' was removed", profile.uuid)
                }
                Err(e) => {
                    errors_counter += 1;
                    println!("Error while trying to remove '{}'", profile.uuid);
                    println!("{}", e);
                }
            }
        }
        println!("Removed {} of {}", removals_counter, info.total);
        if errors_counter > 0 {
            println!("Errors: {}", errors_counter);
        }
    }
    Ok(())
}

fn directory(args: &::docopt::ArgvMap) -> Option<&Path> {
    let dir_name = args.get_str("<directory>");
    if dir_name.is_empty() {
        None
    } else {
        Some(dir_name.as_ref())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate maplit;
extern crate correlation;
extern crate uuid;

use correlation::{config, conditions, Correlator};
use correlation::message::{Builder, PatternId};
use correlation::action::message;
use correlation::action::ActionHandlers;
use uuid::Uuid;
use std::thread;

struct Printer;

impl message::ActionHandler for Printer {
    fn handle(&mut self, _: message::ExecResult) {
        println!("I'm the message handler");
    }
}

#[allow(dead_code)]
fn main() {
    let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid3 = "3b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let patterns = vec![
        PatternId::Name(uuid1.clone()),
        PatternId::Name(uuid2.clone()),
        PatternId::Name(uuid3.clone()),
    ];
    let condition = conditions::Builder::new(100).patterns(patterns)
                                                .first_opens(true)
                                                .last_closes(true)
                                                .build();
    let actions = vec![ message::Action::new().into() ];
    let contexts = vec!{
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
    };
    let handlers = ActionHandlers::new(Box::new(Printer));
    let mut correlator = Correlator::new(contexts, handlers);
    let _ = correlator.push_message(Builder::new(&uuid1).build());
    thread::sleep_ms(20);
    let _ = correlator.push_message(Builder::new(&uuid2).build());
    thread::sleep_ms(80);
    let _ = correlator.push_message(Builder::new(&uuid3).build());
    let _ = correlator.stop();
}
<commit_msg>test: fix the test program by putting the uuids into the Uuid variant<commit_after>#[macro_use]
extern crate maplit;
extern crate correlation;
extern crate uuid;

use correlation::{config, conditions, Correlator};
use correlation::message::{Builder, PatternId};
use correlation::action::message;
use correlation::action::ActionHandlers;
use uuid::Uuid;
use std::thread;

struct Printer;

impl message::ActionHandler for Printer {
    fn handle(&mut self, _: message::ExecResult) {
        println!("I'm the message handler");
    }
}

#[allow(dead_code)]
fn main() {
    let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid3 = "3b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let patterns = vec![
        PatternId::Uuid(Uuid::parse_str(&uuid1).unwrap()),
        PatternId::Uuid(Uuid::parse_str(&uuid2).unwrap()),
        PatternId::Uuid(Uuid::parse_str(&uuid3).unwrap()),
    ];
    let condition = conditions::Builder::new(100).patterns(patterns)
                                                .first_opens(true)
                                                .last_closes(true)
                                                .build();
    let actions = vec![ message::Action::new().into() ];
    let contexts = vec!{
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
    };
    let handlers = ActionHandlers::new(Box::new(Printer));
    let mut correlator = Correlator::new(contexts, handlers);
    let _ = correlator.push_message(Builder::new(&uuid1).build());
    thread::sleep_ms(20);
    let _ = correlator.push_message(Builder::new(&uuid2).build());
    thread::sleep_ms(80);
    let _ = correlator.push_message(Builder::new(&uuid3).build());
    let _ = correlator.stop();
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty) => {{
        const SIZE: usize = core::mem::size_of::<$ty>();
        let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
        let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;

        if cfg!(target_endian = "little") {
            unsafe {
                core::ptr::copy_nonoverlapping(
                    $src.as_ptr() as *const u8,
                    $dst.as_mut_ptr(),
                    chunk_size_u8);
            }
        } else {
            for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
                let tmp = n.to_le();
                let src_ptr = &tmp as *const $ty as *const u8;
                unsafe {
                    core::ptr::copy_nonoverlapping(
                        src_ptr,
                        chunk.as_mut_ptr(),
                        chunk.len());
                }
            }
        }

        // The following code is a safe replacement, but unfortunately ca. 8%
        // slower.
        /*
        let mut iter_src = $src.iter();
        let mut chunks = $dst.chunks_exact_mut(SIZE);
        for (chunk, n) in (&mut chunks).zip(&mut iter_src) {
            chunk.copy_from_slice(&n.to_le_bytes());
        }
        let rem = chunks.into_remainder();
        if let Some(n) = iter_src.next() {
            rem.copy_from_slice(&n.to_le_bytes()[..rem.len()]);
        }
        */

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

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

    #[test]
    fn test_fill_via_u32_chunks() {
        let src = [1, 2, 3];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

        let mut dst = [0u8; 13];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
        assert_eq!(dst, [1, 0, 0, 0, 2]);
    }

    #[test]
    fn test_fill_via_u64_chunks() {
        let src = [1, 2];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

        let mut dst = [0u8; 17];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
        assert_eq!(dst, [1, 0, 0, 0, 0]);
    }
}
<commit_msg>Delete dead code<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty) => {{
        const SIZE: usize = core::mem::size_of::<$ty>();
        let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
        let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;

        // The following can be replaced with safe code, but unfortunately it's
        // ca. 8% slower.
        if cfg!(target_endian = "little") {
            unsafe {
                core::ptr::copy_nonoverlapping(
                    $src.as_ptr() as *const u8,
                    $dst.as_mut_ptr(),
                    chunk_size_u8);
            }
        } else {
            for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
                let tmp = n.to_le();
                let src_ptr = &tmp as *const $ty as *const u8;
                unsafe {
                    core::ptr::copy_nonoverlapping(
                        src_ptr,
                        chunk.as_mut_ptr(),
                        chunk.len());
                }
            }
        }

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

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

    #[test]
    fn test_fill_via_u32_chunks() {
        let src = [1, 2, 3];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

        let mut dst = [0u8; 13];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
        assert_eq!(dst, [1, 0, 0, 0, 2]);
    }

    #[test]
    fn test_fill_via_u64_chunks() {
        let src = [1, 2];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

        let mut dst = [0u8; 17];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
        assert_eq!(dst, [1, 0, 0, 0, 0]);
    }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[link(name = "bloomfilter", vers = "0.1")];
#[crate_type = "lib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern mod extra;

use std::hash;
use std::num;
use std::rand;
use std::rand::Rng;
use extra::bitv;

struct SipHashKey {
    k1: u64,
    k2: u64
}

impl SipHashKey {
    fn new(k1: u64, k2: u64) -> SipHashKey {
        SipHashKey {
            k1: k1,
            k2: k2
        }
    }

    fn new_random() -> SipHashKey {
        let mut rng = rand::task_rng();
        SipHashKey {
            k1: rand::Rand::rand(& mut rng),
            k2: rand::Rand::rand(& mut rng)
        }
    }
}

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv skeys: [SipHashKey, ..2]
}

impl Bloom {

/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let skeys = [ SipHashKey::new_random(), SipHashKey::new_random() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            skeys: skeys
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: hash::Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: hash::Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: hash::Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        num::max(k_num, 1)
    }

    fn bloom_hash<T: hash::Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let skey = self.skeys[k_i];
            let hash = (*item).hash_keyed(skey.k1, skey.k2);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>hash::Hash is already imported by default<commit_after>// (C)opyleft 2013 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[link(name = "bloomfilter", vers = "0.1")];
#[crate_type = "lib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern mod extra;

use std::num;
use std::rand;
use std::rand::Rng;
use extra::bitv;

struct SipHashKey {
    k1: u64,
    k2: u64
}

impl SipHashKey {
    fn new(k1: u64, k2: u64) -> SipHashKey {
        SipHashKey {
            k1: k1,
            k2: k2
        }
    }

    fn new_random() -> SipHashKey {
        let mut rng = rand::task_rng();
        SipHashKey {
            k1: rand::Rand::rand(& mut rng),
            k2: rand::Rand::rand(& mut rng)
        }
    }
}

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv skeys: [SipHashKey, ..2]
}

impl Bloom {

/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let skeys = [ SipHashKey::new_random(), SipHashKey::new_random() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            skeys: skeys
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        num::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let skey = self.skeys[k_i];
            let hash = (*item).hash_keyed(skey.k1, skey.k2);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>


<commit_before>use crate::loom::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::loom::sync::atomic::{AtomicBool, AtomicUsize};
use crate::loom::sync::{Arc, Mutex};
use crate::spawn;
use crate::tests::loom_oneshot as oneshot;
use crate::thread_pool::ThreadPool;

use std::future::Future;

#[test]
fn pool_multi_spawn() {
    loom::model(|| {
        let pool = ThreadPool::new();

        let c1 = Arc::new(AtomicUsize::new(0));

        let (tx, rx) = oneshot::channel();
        let tx1 = Arc::new(Mutex::new(Some(tx)));

        // Spawn a task
        let c2 = c1.clone();
        let tx2 = tx1.clone();
        pool.spawn(async move {
            spawn(async move {
                if 1 == c1.fetch_add(1, Relaxed) {
                    tx1.lock().unwrap().take().unwrap().send(());
                }
            });
        });

        // Spawn a second task
        pool.spawn(async move {
            spawn(async move {
                if 1 == c2.fetch_add(1, Relaxed) {
                    tx2.lock().unwrap().take().unwrap().send(());
                }
            });
        });

        rx.recv();
    });
}

#[test]
fn pool_multi_notify() {
    loom::model(|| {
        let pool = ThreadPool::new();

        let c1 = Arc::new(AtomicUsize::new(0));

        let (done_tx, done_rx) = oneshot::channel();
        let done_tx1 = Arc::new(Mutex::new(Some(done_tx)));

        // Spawn a task
        let c2 = c1.clone();
        let done_tx2 = done_tx1.clone();
        pool.spawn(async move {
            gated().await;
            gated().await;

            if 1 == c1.fetch_add(1, Relaxed) {
                done_tx1.lock().unwrap().take().unwrap().send(());
            }
        });

        // Spawn a second task
        pool.spawn(async move {
            gated().await;
            gated().await;

            if 1 == c2.fetch_add(1, Relaxed) {
                done_tx2.lock().unwrap().take().unwrap().send(());
            }
        });

        done_rx.recv();
    });
}

#[test]
fn pool_shutdown() {
    loom::model(|| {
        let pool = ThreadPool::new();

        pool.spawn(async move {
            gated2(true).await;
        });

        drop(pool);
    });
}

fn gated() -> impl Future<Output = &'static str> {
    gated2(false)
}

fn gated2(thread: bool) -> impl Future<Output = &'static str> {
    use crate::loom::thread;
    use futures_util::future::poll_fn;
    use std::sync::Arc;
    use std::task::Poll;

    let gate = Arc::new(AtomicBool::new(false));
    let mut fired = false;

    poll_fn(move |cx| {
        if !fired {
            let gate = gate.clone();
            let waker = cx.waker().clone();

            if thread {
                thread::spawn(move || {
                    gate.store(true, Release);
                    waker.wake_by_ref();
                });
            } else {
                spawn(async move {
                    gate.store(true, Release);
                    waker.wake_by_ref();
                });
            }

            fired = true;

            return Poll::Pending;
        }

        if gate.load(Acquire) {
            Poll::Ready("hello world")
        } else {
            Poll::Pending
        }
    })
}
<commit_msg>thread-pool: test additional shutdown cases (#1697)<commit_after>use crate::loom::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::loom::sync::atomic::{AtomicBool, AtomicUsize};
use crate::loom::sync::{Arc, Mutex};
use crate::spawn;
use crate::tests::loom_oneshot as oneshot;
use crate::thread_pool::ThreadPool;

use std::future::Future;

#[test]
fn pool_multi_spawn() {
    loom::model(|| {
        let pool = ThreadPool::new();

        let c1 = Arc::new(AtomicUsize::new(0));

        let (tx, rx) = oneshot::channel();
        let tx1 = Arc::new(Mutex::new(Some(tx)));

        // Spawn a task
        let c2 = c1.clone();
        let tx2 = tx1.clone();
        pool.spawn(async move {
            spawn(async move {
                if 1 == c1.fetch_add(1, Relaxed) {
                    tx1.lock().unwrap().take().unwrap().send(());
                }
            });
        });

        // Spawn a second task
        pool.spawn(async move {
            spawn(async move {
                if 1 == c2.fetch_add(1, Relaxed) {
                    tx2.lock().unwrap().take().unwrap().send(());
                }
            });
        });

        rx.recv();
    });
}

#[test]
fn pool_multi_notify() {
    loom::model(|| {
        let pool = ThreadPool::new();

        let c1 = Arc::new(AtomicUsize::new(0));

        let (done_tx, done_rx) = oneshot::channel();
        let done_tx1 = Arc::new(Mutex::new(Some(done_tx)));

        // Spawn a task
        let c2 = c1.clone();
        let done_tx2 = done_tx1.clone();
        pool.spawn(async move {
            gated().await;
            gated().await;

            if 1 == c1.fetch_add(1, Relaxed) {
                done_tx1.lock().unwrap().take().unwrap().send(());
            }
        });

        // Spawn a second task
        pool.spawn(async move {
            gated().await;
            gated().await;

            if 1 == c2.fetch_add(1, Relaxed) {
                done_tx2.lock().unwrap().take().unwrap().send(());
            }
        });

        done_rx.recv();
    });
}

#[test]
fn pool_shutdown() {
    loom::model(|| {
        let pool = ThreadPool::new();

        pool.spawn(async move {
            gated2(true).await;
        });

        pool.spawn(async move {
            gated2(false).await;
        });

        drop(pool);
    });
}

fn gated() -> impl Future<Output = &'static str> {
    gated2(false)
}

fn gated2(thread: bool) -> impl Future<Output = &'static str> {
    use crate::loom::thread;
    use futures_util::future::poll_fn;
    use std::sync::Arc;
    use std::task::Poll;

    let gate = Arc::new(AtomicBool::new(false));
    let mut fired = false;

    poll_fn(move |cx| {
        if !fired {
            let gate = gate.clone();
            let waker = cx.waker().clone();

            if thread {
                thread::spawn(move || {
                    gate.store(true, Release);
                    waker.wake_by_ref();
                });
            } else {
                spawn(async move {
                    gate.store(true, Release);
                    waker.wake_by_ref();
                });
            }

            fired = true;

            return Poll::Pending;
        }

        if gate.load(Acquire) {
            Poll::Ready("hello world")
        } else {
            Poll::Pending
        }
    })
}
<|endoftext|>


<commit_before>//! Convert a string in IBM codepage 437 to UTF-8

/// Trait to convert IBM codepage 437 to the target type
pub trait FromCp437 {
    /// Target type
    type Target;

    /// Function that does the conversion from cp437.
    /// Gennerally allocations will be avoided if all data falls into the ASCII range.
    fn from_cp437(self) -> Self::Target;
}

impl<'a> FromCp437 for &'a [u8] {
    type Target = ::std::borrow::Cow<'a, str>;

    fn from_cp437(self) -> Self::Target
    {
        if self.iter().all(|c| *c < 0x80) {
            ::std::str::from_utf8(self).unwrap().into()
        }
        else {
            self.iter().map(|c| to_char(*c)).collect::<String>().into()
        }
    }
}

impl FromCp437 for Vec<u8> {
    type Target = String;

    fn from_cp437(self) -> Self::Target {
        if self.iter().all(|c| *c < 0x80) {
            String::from_utf8(self).unwrap()
        }
        else {
            self.into_iter().map(|c| to_char(c)).collect()
        }
    }
}

fn to_char(input: u8) -> char
{
    let output = match input
    {
        0x00 ... 0x7f => input as u32,
        0x80 => 0x00c7,
        0x81 => 0x00fc,
        0x82 => 0x00e9,
        0x83 => 0x00e2,
        0x84 => 0x00e4,
        0x85 => 0x00e0,
        0x86 => 0x00e5,
        0x87 => 0x00e7,
        0x88 => 0x00ea,
        0x89 => 0x00eb,
        0x8a => 0x00e8,
        0x8b => 0x00ef,
        0x8c => 0x00ee,
        0x8d => 0x00ec,
        0x8e => 0x00c4,
        0x8f => 0x00c5,
        0x90 => 0x00c9,
        0x91 => 0x00e6,
        0x92 => 0x00c6,
        0x93 => 0x00f4,
        0x94 => 0x00f6,
        0x95 => 0x00f2,
        0x96 => 0x00fb,
        0x97 => 0x00f9,
        0x98 => 0x00ff,
        0x99 => 0x00d6,
        0x9a => 0x00dc,
        0x9b => 0x00a2,
        0x9c => 0x00a3,
        0x9d => 0x00a5,
        0x9e => 0x20a7,
        0x9f => 0x0192,
        0xa0 => 0x00e1,
        0xa1 => 0x00ed,
        0xa2 => 0x00f3,
        0xa3 => 0x00fa,
        0xa4 => 0x00f1,
        0xa5 => 0x00d1,
        0xa6 => 0x00aa,
        0xa7 => 0x00ba,
        0xa8 => 0x00bf,
        0xa9 => 0x2310,
        0xaa => 0x00ac,
        0xab => 0x00bd,
        0xac => 0x00bc,
        0xad => 0x00a1,
        0xae => 0x00ab,
        0xaf => 0x00bb,
        0xb0 => 0x2591,
        0xb1 => 0x2592,
        0xb2 => 0x2593,
        0xb3 => 0x2502,
        0xb4 => 0x2524,
        0xb5 => 0x2561,
        0xb6 => 0x2562,
        0xb7 => 0x2556,
        0xb8 => 0x2555,
        0xb9 => 0x2563,
        0xba => 0x2551,
        0xbb => 0x2557,
        0xbc => 0x255d,
        0xbd => 0x255c,
        0xbe => 0x255b,
        0xbf => 0x2510,
        0xc0 => 0x2514,
        0xc1 => 0x2534,
        0xc2 => 0x252c,
        0xc3 => 0x251c,
        0xc4 => 0x2500,
        0xc5 => 0x253c,
        0xc6 => 0x255e,
        0xc7 => 0x255f,
        0xc8 => 0x255a,
        0xc9 => 0x2554,
        0xca => 0x2569,
        0xcb => 0x2566,
        0xcc => 0x2560,
        0xcd => 0x2550,
        0xce => 0x256c,
        0xcf => 0x2567,
        0xd0 => 0x2568,
        0xd1 => 0x2564,
        0xd2 => 0x2565,
        0xd3 => 0x2559,
        0xd4 => 0x2558,
        0xd5 => 0x2552,
        0xd6 => 0x2553,
        0xd7 => 0x256b,
        0xd8 => 0x256a,
        0xd9 => 0x2518,
        0xda => 0x250c,
        0xdb => 0x2588,
        0xdc => 0x2584,
        0xdd => 0x258c,
        0xde => 0x2590,
        0xdf => 0x2580,
        0xe0 => 0x03b1,
        0xe1 => 0x00df,
        0xe2 => 0x0393,
        0xe3 => 0x03c0,
        0xe4 => 0x03a3,
        0xe5 => 0x03c3,
        0xe6 => 0x00b5,
        0xe7 => 0x03c4,
        0xe8 => 0x03a6,
        0xe9 => 0x0398,
        0xea => 0x03a9,
        0xeb => 0x03b4,
        0xec => 0x221e,
        0xed => 0x03c6,
        0xee => 0x03b5,
        0xef => 0x2229,
        0xf0 => 0x2261,
        0xf1 => 0x00b1,
        0xf2 => 0x2265,
        0xf3 => 0x2264,
        0xf4 => 0x2320,
        0xf5 => 0x2321,
        0xf6 => 0x00f7,
        0xf7 => 0x2248,
        0xf8 => 0x00b0,
        0xf9 => 0x2219,
        0xfa => 0x00b7,
        0xfb => 0x221a,
        0xfc => 0x207f,
        0xfd => 0x00b2,
        0xfe => 0x25a0,
        0xff => 0x00a0,
        _    => 0x0
    };
    ::std::char::from_u32(output).unwrap()
}

#[cfg(test)]
mod test
{
    #[test]
    fn to_char_valid()
    {
        for i in 0x00_u32 .. 0x100
        {
            super::to_char(i as u8);
        }
    }

    #[test]
    fn ascii() {
        for i in 0x00 .. 0x80 {
            assert_eq!(super::to_char(i), i as char);
        }
    }

    #[test]
    fn example_slice() {
        use super::FromCp437;
        let data = b"Cura\x87ao";
        assert!(::std::str::from_utf8(data).is_err());
        assert_eq!(data.from_cp437(), "Curaçao");
    }

    #[test]
    fn example_vec() {
        use super::FromCp437;
        let data = vec![0xCC, 0xCD, 0xCD, 0xB9];
        assert!(String::from_utf8(data.clone()).is_err());
        assert_eq!(&data.from_cp437(), "╠══╣");
    }
}
<commit_msg>Remove _ - updated rustc<commit_after>//! Convert a string in IBM codepage 437 to UTF-8

/// Trait to convert IBM codepage 437 to the target type
pub trait FromCp437 {
    /// Target type
    type Target;

    /// Function that does the conversion from cp437.
    /// Gennerally allocations will be avoided if all data falls into the ASCII range.
    fn from_cp437(self) -> Self::Target;
}

impl<'a> FromCp437 for &'a [u8] {
    type Target = ::std::borrow::Cow<'a, str>;

    fn from_cp437(self) -> Self::Target
    {
        if self.iter().all(|c| *c < 0x80) {
            ::std::str::from_utf8(self).unwrap().into()
        }
        else {
            self.iter().map(|c| to_char(*c)).collect::<String>().into()
        }
    }
}

impl FromCp437 for Vec<u8> {
    type Target = String;

    fn from_cp437(self) -> Self::Target {
        if self.iter().all(|c| *c < 0x80) {
            String::from_utf8(self).unwrap()
        }
        else {
            self.into_iter().map(|c| to_char(c)).collect()
        }
    }
}

fn to_char(input: u8) -> char
{
    let output = match input
    {
        0x00 ... 0x7f => input as u32,
        0x80 => 0x00c7,
        0x81 => 0x00fc,
        0x82 => 0x00e9,
        0x83 => 0x00e2,
        0x84 => 0x00e4,
        0x85 => 0x00e0,
        0x86 => 0x00e5,
        0x87 => 0x00e7,
        0x88 => 0x00ea,
        0x89 => 0x00eb,
        0x8a => 0x00e8,
        0x8b => 0x00ef,
        0x8c => 0x00ee,
        0x8d => 0x00ec,
        0x8e => 0x00c4,
        0x8f => 0x00c5,
        0x90 => 0x00c9,
        0x91 => 0x00e6,
        0x92 => 0x00c6,
        0x93 => 0x00f4,
        0x94 => 0x00f6,
        0x95 => 0x00f2,
        0x96 => 0x00fb,
        0x97 => 0x00f9,
        0x98 => 0x00ff,
        0x99 => 0x00d6,
        0x9a => 0x00dc,
        0x9b => 0x00a2,
        0x9c => 0x00a3,
        0x9d => 0x00a5,
        0x9e => 0x20a7,
        0x9f => 0x0192,
        0xa0 => 0x00e1,
        0xa1 => 0x00ed,
        0xa2 => 0x00f3,
        0xa3 => 0x00fa,
        0xa4 => 0x00f1,
        0xa5 => 0x00d1,
        0xa6 => 0x00aa,
        0xa7 => 0x00ba,
        0xa8 => 0x00bf,
        0xa9 => 0x2310,
        0xaa => 0x00ac,
        0xab => 0x00bd,
        0xac => 0x00bc,
        0xad => 0x00a1,
        0xae => 0x00ab,
        0xaf => 0x00bb,
        0xb0 => 0x2591,
        0xb1 => 0x2592,
        0xb2 => 0x2593,
        0xb3 => 0x2502,
        0xb4 => 0x2524,
        0xb5 => 0x2561,
        0xb6 => 0x2562,
        0xb7 => 0x2556,
        0xb8 => 0x2555,
        0xb9 => 0x2563,
        0xba => 0x2551,
        0xbb => 0x2557,
        0xbc => 0x255d,
        0xbd => 0x255c,
        0xbe => 0x255b,
        0xbf => 0x2510,
        0xc0 => 0x2514,
        0xc1 => 0x2534,
        0xc2 => 0x252c,
        0xc3 => 0x251c,
        0xc4 => 0x2500,
        0xc5 => 0x253c,
        0xc6 => 0x255e,
        0xc7 => 0x255f,
        0xc8 => 0x255a,
        0xc9 => 0x2554,
        0xca => 0x2569,
        0xcb => 0x2566,
        0xcc => 0x2560,
        0xcd => 0x2550,
        0xce => 0x256c,
        0xcf => 0x2567,
        0xd0 => 0x2568,
        0xd1 => 0x2564,
        0xd2 => 0x2565,
        0xd3 => 0x2559,
        0xd4 => 0x2558,
        0xd5 => 0x2552,
        0xd6 => 0x2553,
        0xd7 => 0x256b,
        0xd8 => 0x256a,
        0xd9 => 0x2518,
        0xda => 0x250c,
        0xdb => 0x2588,
        0xdc => 0x2584,
        0xdd => 0x258c,
        0xde => 0x2590,
        0xdf => 0x2580,
        0xe0 => 0x03b1,
        0xe1 => 0x00df,
        0xe2 => 0x0393,
        0xe3 => 0x03c0,
        0xe4 => 0x03a3,
        0xe5 => 0x03c3,
        0xe6 => 0x00b5,
        0xe7 => 0x03c4,
        0xe8 => 0x03a6,
        0xe9 => 0x0398,
        0xea => 0x03a9,
        0xeb => 0x03b4,
        0xec => 0x221e,
        0xed => 0x03c6,
        0xee => 0x03b5,
        0xef => 0x2229,
        0xf0 => 0x2261,
        0xf1 => 0x00b1,
        0xf2 => 0x2265,
        0xf3 => 0x2264,
        0xf4 => 0x2320,
        0xf5 => 0x2321,
        0xf6 => 0x00f7,
        0xf7 => 0x2248,
        0xf8 => 0x00b0,
        0xf9 => 0x2219,
        0xfa => 0x00b7,
        0xfb => 0x221a,
        0xfc => 0x207f,
        0xfd => 0x00b2,
        0xfe => 0x25a0,
        0xff => 0x00a0,
    };
    ::std::char::from_u32(output).unwrap()
}

#[cfg(test)]
mod test
{
    #[test]
    fn to_char_valid()
    {
        for i in 0x00_u32 .. 0x100
        {
            super::to_char(i as u8);
        }
    }

    #[test]
    fn ascii() {
        for i in 0x00 .. 0x80 {
            assert_eq!(super::to_char(i), i as char);
        }
    }

    #[test]
    fn example_slice() {
        use super::FromCp437;
        let data = b"Cura\x87ao";
        assert!(::std::str::from_utf8(data).is_err());
        assert_eq!(data.from_cp437(), "Curaçao");
    }

    #[test]
    fn example_vec() {
        use super::FromCp437;
        let data = vec![0xCC, 0xCD, 0xCD, 0xB9];
        assert!(String::from_utf8(data.clone()).is_err());
        assert_eq!(&data.from_cp437(), "╠══╣");
    }
}
<|endoftext|>