<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;

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 secp256k1zkp as secp;

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

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

use secp::Secp256k1;

use wallet::WalletConfig;

use config::{GlobalConfig, ConfigError};

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());
	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 mut 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 = blake2b(32, &[], hd_seed.as_bytes());

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

	let default_ip = "127.0.0.1";
	let mut addr = format!("{}:13416", default_ip);

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

	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,
				                       });
				apis.start(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>Last (hopefully) blake2 loose ends<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 secp256k1zkp as secp;

use std::env;
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 wallet::WalletConfig;

use config::{GlobalConfig, ConfigError};

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());
	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 mut 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 default_ip = "127.0.0.1";
	let mut addr = format!("{}:13416", default_ip);

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

	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,
				                       });
				apis.start(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>#![deny(warnings)]

// TODO support reading from standard input

extern crate coreutils;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use coreutils::extra::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Key, Style, RawTerminal};

static LONG_HELP: &'static str = r#"
    NAME
        less - view a text file.
    SYNOPSIS
        less [-h | --help] [input]
    DESCRIPTION
        This utility views text files. If no input file is specified as an argument, standard input is used.
    OPTIONS
        --help, -h
            Print this manual page.
    AUTHOR
        This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 MovingtoMars

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(&mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(&mut file, &mut stdin, &mut stdout, &mut stderr);
        } else {
            writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
            //run(&mut stdin, t, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, t, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        let _ = w;

        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            bytes_written += try!(to.write(line.as_bytes()));

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off != 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self) {
        if (self.y_off as usize) < self.lines.len() - 1 {
            self.y_off += 1;
        }
    }
}

fn run(file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.style(Style::Bold).try(stderr);
    stdout.write(b"Press q to exit.").try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Up => buffer.scroll_up(),
            Key::Down => buffer.scroll_down(),
            _ => {},
        }

        stdout.clear().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.style(Style::Bold).try(stderr);
        stdout.write(b"Press q to exit.").try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<commit_msg>Truncate lines to width, cleanup main function<commit_after>#![deny(warnings)]

// TODO support reading from standard input

extern crate coreutils;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use coreutils::extra::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Key, Style, RawTerminal};

static LONG_HELP: &'static str = r#"
    NAME
        less - view a text file.
    SYNOPSIS
        less [-h | --help] [input]
    DESCRIPTION
        This utility views text files. If no input file is specified as an argument, standard input is used.
    OPTIONS
        --help, -h
            Print this manual page.
    AUTHOR
        This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 MovingtoMars

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let mut stdout = io::stdout().lock();
    let mut stdin = io::stdin().lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(&mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(&mut file, &mut stdin, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, t, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            if line.len() > w as usize {
                bytes_written += try!(to.write(line[..w as usize].as_bytes()));
            } else {
                bytes_written += try!(to.write(line.as_bytes()));
            }

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off != 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self) {
        if (self.y_off as usize) < self.lines.len() - 1 {
            self.y_off += 1;
        }
    }
}

fn run(file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.style(Style::Bold).try(stderr);
    stdout.write(b"Press q to exit.").try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Up => buffer.scroll_up(),
            Key::Down => buffer.scroll_down(),
            _ => {},
        }

        stdout.clear().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.style(Style::Bold).try(stderr);
        stdout.write(b"Press q to exit.").try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<|endoftext|>


<commit_before>use rustbox;
use yoga;
use yoga_wrapper;
use yoga::Backend as B;
use yoga::Renders as R;

use measurer;
use renderer;

pub struct Backend<'r> {
    renderer: renderer::Renderer<'r>,
    measurer: measurer::Measurer,
}

impl<'r> Backend<'r> {
    pub fn new(rustbox: &rustbox::RustBox) -> Backend {
        Backend {
            renderer: renderer::Renderer::new(rustbox),
            measurer: measurer::Measurer {},
        }
    }

    pub fn draw(&self, node: &yoga_wrapper::Node) {
        self.render(&self.renderer, node);
        self.renderer.rustbox.present();
    }
}

impl<'r> yoga::Backend for Backend<'r> {
    type Color = i32;
    type Renderer = renderer::Renderer<'r>;
    type Measurer = measurer::Measurer;

    fn render(&self, renderer: &renderer::Renderer, node: &yoga_wrapper::Node) {
        renderer.render(node)
    }
}
<commit_msg>feat(backend): impl create_context<commit_after>use rustbox;
use yoga;
use yoga_wrapper;

use yoga::Backend as B;
use yoga::Renders as R;

use measurer;
use renderer;

pub struct Backend<'r> {
    renderer: renderer::Renderer<'r>,
    measurer: measurer::Measurer,
}

impl<'r> Backend<'r> {
    pub fn new(rustbox: &rustbox::RustBox) -> Backend {
        Backend {
            renderer: renderer::Renderer::new(rustbox),
            measurer: measurer::Measurer {},
        }
    }

    pub fn draw(&self, node: &yoga_wrapper::Node) {
        self.render(&self.renderer, node);
        self.renderer.rustbox.present();
    }
}

impl<'r, 'm> yoga::Backend<'m> for Backend<'r> {
    type Color = i32;
    type Renderer = renderer::Renderer<'r>;
    type Measurer = measurer::Measurer;

    fn render(&self, renderer: &renderer::Renderer, node: &yoga_wrapper::Node) {
        renderer.render(node)
    }

    fn create_context<'s>(&'m self, text: &'s str) -> yoga_wrapper::Context<'s, 'm> {
        yoga_wrapper::Context::new(text, &self.measurer)
    }
}
<|endoftext|>


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

extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::process;

extern crate cargo_edit;
use cargo_edit::{Manifest, list_section, list_tree};

static USAGE: &'static str = r"
Usage:
    cargo list [<section>] [options]

Options:
    --manifest-path PATH    Path to the manifest to add a dependency to.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.

Display a crate's dependencies using its Cargo.toml file.
";

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
struct Args {
    arg_section: Option<String>,
    flag_manifest_path: Option<String>,
    flag_tree: bool,
}

impl Args {
    pub fn get_section(&self) -> String {
        let section = self.arg_section.clone().unwrap_or("dependencies".to_owned());

        let toml_field = match &(section[..]) {
            // Handle shortcuts
            "deps" => "dependencies",
            "dev-deps" => "dev-dependencies",
            "build-deps" => "build-dependencies",
            // No shortcut
            field => field
        };

        String::from(toml_field)
    }
}

fn handle_list(args: &Args) -> Result<(), Box<Error>> {
    let listing = if args.flag_tree {
        let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path.as_ref()));
        list_tree(&manifest)
    } else {
        let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref()));
        list_section(&manifest, &args.get_section())
    };

    listing
    .map(|listing| println!("{}", listing) )
    .or_else(|err| {
        println!("Could not list your stuff.\n\nERROR: {}", err);
        Err(err)
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode::<Args>())
        .unwrap_or_else(|err| err.exit());

    if let Err(err) = handle_list(&args) {
        println!("{}", err);
        process::exit(1);
    }
}
<commit_msg>Add `cargo list --version`<commit_after>#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::process;

extern crate cargo_edit;
use cargo_edit::{Manifest, list_section, list_tree};

static USAGE: &'static str = r"
Usage:
    cargo list [<section>] [options]
    cargo list (-h|--help)
    cargo list --version

Options:
    --manifest-path=<path>  Path to the manifest to add a dependency to.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.

Display a crate's dependencies using its Cargo.toml file.
";

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
struct Args {
    arg_section: Option<String>,
    flag_manifest_path: Option<String>,
    flag_tree: bool,
    flag_version: bool,
}

impl Args {
    pub fn get_section(&self) -> String {
        let section = self.arg_section.clone().unwrap_or("dependencies".to_owned());

        let toml_field = match &(section[..]) {
            // Handle shortcuts
            "deps" => "dependencies",
            "dev-deps" => "dev-dependencies",
            "build-deps" => "build-dependencies",
            // No shortcut
            field => field
        };

        String::from(toml_field)
    }
}

fn handle_list(args: &Args) -> Result<(), Box<Error>> {
    let listing = if args.flag_tree {
        let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path.as_ref()));
        list_tree(&manifest)
    } else {
        let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref()));
        list_section(&manifest, &args.get_section())
    };

    listing
    .map(|listing| println!("{}", listing) )
    .or_else(|err| {
        println!("Could not list your stuff.\n\nERROR: {}", err);
        Err(err)
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-list version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = handle_list(&args) {
        println!("{}", err);
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>pub mod record;
pub mod header;

use std::ffi;
use std::path;
use std::ffi::AsOsStr;
use std::os::unix::prelude::OsStrExt;

use htslib;

pub trait BAMRead {
    fn read(&self, record: &mut record::Record) -> Result<(), ReadError>;
}

pub struct BAMReader {
    f: *mut htslib::Struct_BGZF,
    header: *mut htslib::bam_hdr_t,
}

impl BAMReader {
     pub fn new<P: path::AsPath>(path: P) -> Self {
        let f = unsafe {
            htslib::bgzf_open(
                path.as_path().as_os_str().to_cstring().unwrap().as_ptr(),
                ffi::CString::new(b"r").unwrap().as_ptr()
            )
        };
        let header = unsafe { htslib::bam_hdr_read(f) };
        BAMReader { f : f, header : header }
    }

    pub fn records(self) -> Records {
        Records { bam: self }
    }
}

impl BAMRead for BAMReader {
    fn read(&self, record: &mut record::Record) -> Result<(), ReadError> {
        match unsafe { htslib::bam_read1(self.f, &mut record.inner) } {
            -1 => Err(ReadError::EOF),
            -2 => Err(ReadError::Truncated),
            -4 => Err(ReadError::Invalid),
            _  => Ok(())
        }
    }
}

impl Drop for BAMReader {
    fn drop(&mut self) {
        unsafe {
            htslib::bam_hdr_destroy(self.header);
            htslib::bgzf_close(self.f);
        }
    }
}

pub struct BAMWriter {
    f: *mut htslib::Struct_BGZF,
    header: *mut htslib::bam_hdr_t,
}

impl BAMWriter {
    pub fn new<P: path::AsPath>(path: P, header: &header::Header) -> Self {
        let f = unsafe {
            htslib::bgzf_open(
                path.as_path().as_os_str().to_cstring().unwrap().as_ptr(),
                ffi::CString::new(b"w").unwrap().as_ptr()
            )
        };
        let header_record = unsafe {
            let header_string = header.to_bytes();
            htslib::sam_hdr_parse(
                header_string.len() as i32,
                ffi::CString::new(header_string).unwrap().as_ptr()
            )
        };
        BAMWriter { f: f, header: header_record }
    }

    pub fn write(&mut self, record: &record::Record) -> Result<(), ()> {
        if unsafe { htslib::bam_write1(self.f, &record.inner) } == -1 {
            Err(())
        }
        else {
            Ok(())
        }
    }
}

impl Drop for BAMWriter {
    fn drop(&mut self) {
        unsafe {
            htslib::bam_hdr_destroy(self.header);
            htslib::bgzf_close(self.f);
        }
    }
}

pub struct Records {
    bam: BAMReader
}

impl Iterator for Records {
    type Item = Result<record::Record, ReadError>;

    fn next(&mut self) -> Option<Result<record::Record, ReadError>> {
        let mut record = record::Record::new();
        match self.bam.read(&mut record) {
            Err(ReadError::EOF) => None,
            Ok(())   => Some(Ok(record)),
            Err(err) => Some(Err(err))
        }
    }
}

pub enum ReadError {
    Truncated,
    Invalid,
    EOF,
}

#[cfg(test)]
mod tests {
    use super::record::*;
    use super::*;
    use std::str;

    #[test]
    fn test_read() {
        let names = [b"I", b"II.14978392", b"III", b"IV", b"V", b"VI"];
        let flags = [16u16, 16u16, 16u16, 16u16, 16u16, 2048u16];
        let seqs = [
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"ACTAAGCCTAAGCCTAAGCCTAAGCCAATTATCGATTTCTGAAAAAATTATCGAATTTTCTAGAAATTTTGCAAATTTTTTCATAAAATTATCGATTTTA",
        ];
        let cigars = [
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(100000), Cigar::Match(73)],
        ];

        let bam = BAMReader::new("test.bam");

        for (i, record) in bam.records().enumerate() {
            let rec = record.ok().expect("Expected valid record");
            println!("{}", str::from_utf8(rec.qname()).ok().unwrap());
            assert_eq!(rec.qname(), names[i]);
            assert_eq!(rec.flags(), flags[i]);
            assert_eq!(rec.seq().as_bytes(), seqs[i]);
            assert_eq!(rec.cigar(), cigars[i]);
        }
    }

    #[test]
    fn test_set_record() {
        let qname = b"I";
        let cigar = [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)];
        let seq =  b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGC";
        let qual = b"JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ";

        let mut rec = record::Record::new();
        rec.set_reverse();
        rec.set(qname, &cigar, seq, qual);
        rec.push_aux(b"NM", &Aux::Integer(15));
        assert_eq!(rec.qname(), qname);
        assert_eq!(rec.cigar(), cigar);
        assert_eq!(rec.seq().as_bytes(), seq);
        assert_eq!(rec.qual(), qual);
        assert!(rec.is_reverse());
        assert_eq!(rec.aux(b"NM").unwrap(), Aux::Integer(15));
    }
}
<commit_msg>writing bams.<commit_after>pub mod record;
pub mod header;

use std::ffi;
use std::path;
use std::ffi::AsOsStr;
use std::os::unix::prelude::OsStrExt;

use htslib;

pub trait BAMRead {
    fn read(&self, record: &mut record::Record) -> Result<(), ReadError>;
}

pub struct BAMReader {
    f: *mut htslib::Struct_BGZF,
    header: *mut htslib::bam_hdr_t,
}

impl BAMReader {
     pub fn new<P: path::AsPath>(path: P) -> Self {
        let f = unsafe {
            htslib::bgzf_open(
                path.as_path().as_os_str().to_cstring().unwrap().as_ptr(),
                ffi::CString::new(b"r").unwrap().as_ptr()
            )
        };
        let header = unsafe { htslib::bam_hdr_read(f) };
        BAMReader { f : f, header : header }
    }

    pub fn records(self) -> Records {
        Records { bam: self }
    }
}

impl BAMRead for BAMReader {
    fn read(&self, record: &mut record::Record) -> Result<(), ReadError> {
        match unsafe { htslib::bam_read1(self.f, &mut record.inner) } {
            -1 => Err(ReadError::EOF),
            -2 => Err(ReadError::Truncated),
            -4 => Err(ReadError::Invalid),
            _  => Ok(())
        }
    }
}

impl Drop for BAMReader {
    fn drop(&mut self) {
        unsafe {
            htslib::bam_hdr_destroy(self.header);
            htslib::bgzf_close(self.f);
        }
    }
}

fn bgzf_open<P: path::AsPath>(path: &P, mode: &[u8]) -> *mut htslib::Struct_BGZF {
    unsafe {
        htslib::bgzf_open(
            path.as_path().as_os_str().to_cstring().unwrap().as_ptr(),
            ffi::CString::new(mode).unwrap().as_ptr()
        )
    }
}

pub struct BAMWriter {
    f: *mut htslib::Struct_BGZF,
    header: *mut htslib::bam_hdr_t,
}

impl BAMWriter {
    pub fn new<P: path::AsPath>(path: &P, header: &header::Header) -> Self {
        let f = bgzf_open(path, b"w");
        let header_record = unsafe {
            let header_string = header.to_bytes();
            htslib::sam_hdr_parse(
                header_string.len() as i32,
                ffi::CString::new(header_string).unwrap().as_ptr()
            )
        };
        unsafe { htslib::bam_hdr_write(f, header_record); }
        BAMWriter { f: f, header: header_record }
    }

    pub fn with_template<P: path::AsPath, T: path::AsPath>(path: &P, template: &T) -> Self {
        let t = bgzf_open(template, b"r");
        let header = unsafe { htslib::bam_hdr_read(t) };
        unsafe { htslib::bgzf_close(t); }
        let f = bgzf_open(path, b"w");
        unsafe { htslib::bam_hdr_write(f, header); }
        BAMWriter { f: f, header: header }
    }

    pub fn write(&mut self, record: &record::Record) -> Result<(), ()> {
        if unsafe { htslib::bam_write1(self.f, &record.inner) } == -1 {
            Err(())
        }
        else {
            Ok(())
        }
    }
}

impl Drop for BAMWriter {
    fn drop(&mut self) {
        unsafe {
            htslib::bam_hdr_destroy(self.header);
            htslib::bgzf_close(self.f);
        }
    }
}

pub struct Records {
    bam: BAMReader
}

impl Iterator for Records {
    type Item = Result<record::Record, ReadError>;

    fn next(&mut self) -> Option<Result<record::Record, ReadError>> {
        let mut record = record::Record::new();
        match self.bam.read(&mut record) {
            Err(ReadError::EOF) => None,
            Ok(())   => Some(Ok(record)),
            Err(err) => Some(Err(err))
        }
    }
}

pub enum ReadError {
    Truncated,
    Invalid,
    EOF,
}

#[cfg(test)]
mod tests {
    use super::record::*;
    use super::*;
    use std::str;

    #[test]
    fn test_read() {
        let names = [b"I", b"II.14978392", b"III", b"IV", b"V", b"VI"];
        let flags = [16u16, 16u16, 16u16, 16u16, 16u16, 2048u16];
        let seqs = [
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA",
            b"ACTAAGCCTAAGCCTAAGCCTAAGCCAATTATCGATTTCTGAAAAAATTATCGAATTTTCTAGAAATTTTGCAAATTTTTTCATAAAATTATCGATTTTA",
        ];
        let cigars = [
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)],
            [Cigar::Match(27), Cigar::Del(100000), Cigar::Match(73)],
        ];

        let bam = BAMReader::new("test.bam");

        for (i, record) in bam.records().enumerate() {
            let rec = record.ok().expect("Expected valid record");
            println!("{}", str::from_utf8(rec.qname()).ok().unwrap());
            assert_eq!(rec.qname(), names[i]);
            assert_eq!(rec.flags(), flags[i]);
            assert_eq!(rec.seq().as_bytes(), seqs[i]);
            assert_eq!(rec.cigar(), cigars[i]);
        }
    }

    #[test]
    fn test_set_record() {
        let qname = b"I";
        let cigar = [Cigar::Match(27), Cigar::Del(1), Cigar::Match(73)];
        let seq =  b"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGC";
        let qual = b"JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ";

        let mut rec = record::Record::new();
        rec.set_reverse();
        rec.set(qname, &cigar, seq, qual);
        rec.push_aux(b"NM", &Aux::Integer(15));
        assert_eq!(rec.qname(), qname);
        assert_eq!(rec.cigar(), cigar);
        assert_eq!(rec.seq().as_bytes(), seq);
        assert_eq!(rec.qual(), qual);
        assert!(rec.is_reverse());
        assert_eq!(rec.aux(b"NM").unwrap(), Aux::Integer(15));
    }
}
<|endoftext|>


<commit_before>extern crate portaudio;

use portaudio::{pa, stream, hostapi, device};

fn main()
{
    println!("version: {} \"{}\"", pa::version(), pa::version_text());
    println!("init: {}", pa::initialize());

    print_info();
    doit();

    println!("term: {}", pa::terminate());
}

fn print_info()
{
    match hostapi::get_count()
    {
        Ok(api_count) => {
            for i in range(0, api_count)
            {
                let name = match hostapi::get_info(i)
                {
                    None => "???".to_string(),
                    Some(ha) => ha.name,
                };
                println!("api {}: {}", i, name);
            }
        },
        _ => {},
    }

    match device::get_count()
    {
        Ok(device_count) => {
            for i in range(0, device_count)
            {
                let name = match device::get_info(i)
                {
                    None => "???".to_string(),
                    Some(d) => d.name,
                };
                println!("dev {}: {}", i, name);
            }
        },
        _ => {},
    }
}

fn doit()
{
    callback_demo();
    write_demo();
}

fn callback_demo()
{
    let callback = |_input: &[f32], output: &mut [f32], _time: stream::StreamTimeInfo, _flags: stream::StreamCallbackFlags| -> stream::StreamCallbackResult
    {
        static mut lp: f32 = 0.0;
        static mut rp: f32 = 0.0;

        let mut left_phase = unsafe { lp };
        let mut right_phase = unsafe { rp };

        for i in range(0, output.len() / 2)
        {
            output[i*2] = left_phase;
            output[i*2+1] = right_phase;

            left_phase += 0.01;
            if left_phase >= 1.0 { left_phase -= 2.0; }

            right_phase += 0.03;
            if right_phase >= 1.0 { right_phase -= 2.0; }
        }

        unsafe { lp = left_phase; }
        unsafe { rp = right_phase; }

        stream::Continue
    };

    let mut stream = match stream::Stream::open_default(0, 2, 44100f64, 0, Some(callback))
    {
        Err(v) => { println!("Err({})", v); return },
        Ok(stream) => stream,
    };
    println!("finished_callback: {}", stream.set_finished_callback(|| println!("Finished callback called")));
    println!("start: {}", stream.start());
    std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    println!("stop: {}", stream.stop());

    println!("finished_callback: {}", stream.unset_finished_callback());
    println!("start: {}", stream.start());
    std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    println!("stop: {}", stream.stop());
}

fn write_demo()
{
    let stream = match stream::Stream::open_default(0, 2, 44100f64, 0, None)
    {
        Err(v) => { println!("Err({})", v); return },
        Ok(stream) => stream,
    };

    println!("start: {}", stream.start());
    println!("write: {}", stream.write(get_buffer(44100*3).as_slice()));
    println!("stop: {}", stream.stop());
}

fn get_buffer(len: uint) -> Vec<f32>
{
    let mut left = 0.0f32;
    let mut right = 0.0f32;
    let mut result = Vec::with_capacity(len);
    for i in range(0, len / 2)
    {
        result.push(left);
        result.push(right);
        left += 0.03;
        right += 0.01;
        if left >= 1.0 { left -= 2.0; }
        if right >= 1.0 { right -= 2.0; }
    }
    result
}
<commit_msg>Add demo for Stream::open<commit_after>extern crate portaudio;

use portaudio::{pa, stream, hostapi, device};

fn main()
{
    println!("version: {} \"{}\"", pa::version(), pa::version_text());
    println!("init: {}", pa::initialize());

    print_info();
    doit();

    println!("term: {}", pa::terminate());
}

fn print_info()
{
    match hostapi::get_count()
    {
        Ok(api_count) => {
            for i in range(0, api_count)
            {
                let name = match hostapi::get_info(i)
                {
                    None => "???".to_string(),
                    Some(ha) => ha.name,
                };
                println!("api {}: {}", i, name);
            }
        },
        _ => {},
    }

    match device::get_count()
    {
        Ok(device_count) => {
            for i in range(0, device_count)
            {
                let name = match device::get_info(i)
                {
                    None => "???".to_string(),
                    Some(d) => d.name,
                };
                println!("dev {}: {}", i, name);
            }
        },
        _ => {},
    }
}

fn doit()
{
    callback_demo();
    write_demo();
    mixed_demo();
}

fn callback_demo()
{
    let callback = |_input: &[f32], output: &mut [f32], _time: stream::StreamTimeInfo, _flags: stream::StreamCallbackFlags| -> stream::StreamCallbackResult
    {
        static mut lp: f32 = 0.0;
        static mut rp: f32 = 0.0;

        let mut left_phase = unsafe { lp };
        let mut right_phase = unsafe { rp };

        for i in range(0, output.len() / 2)
        {
            output[i*2] = left_phase;
            output[i*2+1] = right_phase;

            left_phase += 0.01;
            if left_phase >= 1.0 { left_phase -= 2.0; }

            right_phase += 0.03;
            if right_phase >= 1.0 { right_phase -= 2.0; }
        }

        unsafe { lp = left_phase; }
        unsafe { rp = right_phase; }

        stream::Continue
    };

    let mut stream = match stream::Stream::open_default(0, 2, 44100f64, 0, Some(callback))
    {
        Err(v) => { println!("Err({})", v); return },
        Ok(stream) => stream,
    };
    println!("finished_callback: {}", stream.set_finished_callback(|| println!("Finished callback called")));
    println!("start: {}", stream.start());
    std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    println!("stop: {}", stream.stop());

    println!("finished_callback: {}", stream.unset_finished_callback());
    println!("start: {}", stream.start());
    std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    println!("stop: {}", stream.stop());
}

fn write_demo()
{
    let stream = match stream::Stream::open_default(0, 2, 44100f64, 0, None)
    {
        Err(v) => { println!("Err({})", v); return },
        Ok(stream) => stream,
    };

    println!("start: {}", stream.start());
    println!("write: {}", stream.write(get_buffer(44100*3).as_slice()));
    println!("stop: {}", stream.stop());
}

fn get_buffer(len: uint) -> Vec<f32>
{
    let mut left = 0.0f32;
    let mut right = 0.0f32;
    let mut result = Vec::with_capacity(len);
    for i in range(0, len / 2)
    {
        result.push(left);
        result.push(right);
        left += 0.03;
        right += 0.01;
        if left >= 1.0 { left -= 2.0; }
        if right >= 1.0 { right -= 2.0; }
    }
    result
}

fn mixed_demo()
{
    let in_idx = match device::get_default_input_index()
    {
        Ok(i) => i,
        Err(_) => return,
    };
    let out_idx = match device::get_default_output_index()
    {
        Ok(o) => o,
        Err(_) => return,
    };
    let in_lat = match device::get_info(in_idx)
    {
        None => return,
        Some(d) => d.default_low_input_latency,
    };
    let out_lat = match device::get_info(out_idx)
    {
        None => return,
        Some(d) => d.default_low_output_latency,
    };
    let input: stream::StreamParameters<f32> = stream::StreamParameters { device: in_idx, channel_count: 2, suggested_latency: in_lat };
    let output: stream::StreamParameters<i8> = stream::StreamParameters { device: out_idx, channel_count: 2, suggested_latency: out_lat };

    let supported = stream::is_format_supported(input, output, 44100f64);
    println!("support? {}", supported);
    if supported.is_err() { return }

    let stream = match stream::Stream::open(input, output, 44100f64, 0, stream::StreamFlags::empty(), None)
    {
        Ok(s) => s,
        Err(o) => { println!("stream: Err({})", o); return },
    };

    let buffer = get_buffer(2*44100).move_iter().map(|v| (v * 127.0) as i8).collect::<Vec<i8>>();
    println!("start: {}", stream.start());
    println!("write: {}", stream.write(buffer.as_slice()));
    println!("stop: {}", stream.stop());
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use rustc_front::intravisit::*;
use syntax::ast::LitKind;
use utils::{span_lint_and_then, in_macro, snippet_opt};

/// **What it does:** This lint checks for boolean expressions that can be written more concisely
///
/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication
///
/// **Known problems:** None
///
/// **Example:** `if a && b || a` should be `if a`
declare_lint! {
    pub NONMINIMAL_BOOL, Warn,
    "checks for boolean expressions that can be written more concisely"
}

#[derive(Copy,Clone)]
pub struct NonminimalBool;

impl LintPass for NonminimalBool {
    fn get_lints(&self) -> LintArray {
        lint_array!(NONMINIMAL_BOOL)
    }
}

impl LateLintPass for NonminimalBool {
    fn check_crate(&mut self, cx: &LateContext, krate: &Crate) {
        krate.visit_all_items(&mut NonminimalBoolVisitor(cx))
    }
}

struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);

use quine_mc_cluskey::Bool;
struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>);

impl<'tcx> Hir2Qmm<'tcx> {
    fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
        for a in a {
            if let ExprBinary(binop, ref lhs, ref rhs) = a.node {
                if binop.node == op {
                    v = self.extract(op, &[lhs, rhs], v)?;
                    continue;
                }
            }
            v.push(self.run(a)?);
        }
        Ok(v)
    }

    fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> {
        match e.node {
            ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
            ExprBinary(binop, ref lhs, ref rhs) => {
                match binop.node {
                    BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
                    BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
                    _ => {},
                }
            },
            ExprLit(ref lit) => {
                match lit.node {
                    LitKind::Bool(true) => return Ok(Bool::True),
                    LitKind::Bool(false) => return Ok(Bool::False),
                    _ => {},
                }
            },
            _ => {},
        }
        let n = self.0.len();
        self.0.push(e);
        if n < 32 {
            #[allow(cast_possible_truncation)]
            Ok(Bool::Term(n as u8))
        } else {
            Err("too many literals".to_owned())
        }
    }
}

fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
    fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String {
        use quine_mc_cluskey::Bool::*;
        match *suggestion {
            True => {
                s.extend("true".chars());
                s
            },
            False => {
                s.extend("false".chars());
                s
            },
            Not(ref inner) => {
                s.push('!');
                recurse(true, cx, inner, terminals, s)
            },
            And(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" && ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Or(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" || ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Term(n) => {
                s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars());
                s
            }
        }
    }
    recurse(false, cx, suggestion, terminals, String::new())
}

impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
    fn bool_expr(&self, e: &Expr) {
        let mut h2q = Hir2Qmm(Vec::new());
        if let Ok(expr) = h2q.run(e) {
            let simplified = expr.simplify();
            if !simplified.iter().any(|s| *s == expr) {
                span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| {
                    for suggestion in &simplified {
                        db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0));
                    }
                });
            }
        }
    }
}

impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, e: &'v Expr) {
        if in_macro(self.0, e.span) { return }
        match e.node {
            ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
            ExprUnary(UnNot, ref inner) => {
                if self.0.tcx.node_types()[&inner.id].is_bool() {
                    self.bool_expr(e);
                } else {
                    walk_expr(self, e);
                }
            },
            _ => walk_expr(self, e),
        }
    }
}
<commit_msg>also compute minimal product of sum form<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use rustc_front::intravisit::*;
use syntax::ast::LitKind;
use utils::{span_lint_and_then, in_macro, snippet_opt};

/// **What it does:** This lint checks for boolean expressions that can be written more concisely
///
/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication
///
/// **Known problems:** None
///
/// **Example:** `if a && b || a` should be `if a`
declare_lint! {
    pub NONMINIMAL_BOOL, Warn,
    "checks for boolean expressions that can be written more concisely"
}

#[derive(Copy,Clone)]
pub struct NonminimalBool;

impl LintPass for NonminimalBool {
    fn get_lints(&self) -> LintArray {
        lint_array!(NONMINIMAL_BOOL)
    }
}

impl LateLintPass for NonminimalBool {
    fn check_crate(&mut self, cx: &LateContext, krate: &Crate) {
        krate.visit_all_items(&mut NonminimalBoolVisitor(cx))
    }
}

struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);

use quine_mc_cluskey::Bool;
struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>);

impl<'tcx> Hir2Qmm<'tcx> {
    fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
        for a in a {
            if let ExprBinary(binop, ref lhs, ref rhs) = a.node {
                if binop.node == op {
                    v = self.extract(op, &[lhs, rhs], v)?;
                    continue;
                }
            }
            v.push(self.run(a)?);
        }
        Ok(v)
    }

    fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> {
        match e.node {
            ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
            ExprBinary(binop, ref lhs, ref rhs) => {
                match binop.node {
                    BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
                    BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
                    _ => {},
                }
            },
            ExprLit(ref lit) => {
                match lit.node {
                    LitKind::Bool(true) => return Ok(Bool::True),
                    LitKind::Bool(false) => return Ok(Bool::False),
                    _ => {},
                }
            },
            _ => {},
        }
        let n = self.0.len();
        self.0.push(e);
        if n < 32 {
            #[allow(cast_possible_truncation)]
            Ok(Bool::Term(n as u8))
        } else {
            Err("too many literals".to_owned())
        }
    }
}

fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
    fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String {
        use quine_mc_cluskey::Bool::*;
        match *suggestion {
            True => {
                s.extend("true".chars());
                s
            },
            False => {
                s.extend("false".chars());
                s
            },
            Not(ref inner) => {
                s.push('!');
                recurse(true, cx, inner, terminals, s)
            },
            And(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" && ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Or(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" || ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Term(n) => {
                s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars());
                s
            }
        }
    }
    recurse(false, cx, suggestion, terminals, String::new())
}

fn simple_negate(b: Bool) -> Bool {
    use quine_mc_cluskey::Bool::*;
    match b {
        True => False,
        False => True,
        t @ Term(_) => Not(Box::new(t)),
        And(mut v) => {
            for el in &mut v {
                *el = simple_negate(::std::mem::replace(el, True));
            }
            Or(v)
        },
        Or(mut v) => {
            for el in &mut v {
                *el = simple_negate(::std::mem::replace(el, True));
            }
            And(v)
        },
        Not(inner) => *inner,
    }
}

impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
    fn bool_expr(&self, e: &Expr) {
        let mut h2q = Hir2Qmm(Vec::new());
        if let Ok(expr) = h2q.run(e) {
            let mut simplified = expr.simplify();
            for simple in Bool::Not(Box::new(expr.clone())).simplify() {
                let simple_negated = simple_negate(simple);
                if simplified.iter().any(|s| *s == simple_negated) {
                    continue;
                }
                simplified.push(simple_negated);
            }
            if !simplified.iter().any(|s| *s == expr) {
                span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| {
                    for suggestion in &simplified {
                        db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0));
                    }
                });
            }
        }
    }
}

impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, e: &'v Expr) {
        if in_macro(self.0, e.span) { return }
        match e.node {
            ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
            ExprUnary(UnNot, ref inner) => {
                if self.0.tcx.node_types()[&inner.id].is_bool() {
                    self.bool_expr(e);
                } else {
                    walk_expr(self, e);
                }
            },
            _ => walk_expr(self, e),
        }
    }
}
<|endoftext|>


<commit_before>use url::Url;
use bip_util::sha::ShaHash;

struct BTClient {
    torrents: Vec<Torrent>,
    id: String, // peer_id or client id
}

struct Torrent {
    // MetaInfo
    announce: Url,
    piece_length: usize,
    pieces_sha1: Vec<ShaHash>,
    name: String, // can be file or directory name
    length: Option<usize>,
    md5: Option<String>, // optional, try not to use
    files: Option<File>,

    // From/For tracker
    peers: Vec<Peer>,
    uploaded: usize,
    downloaded: usize,
    left: usize,
    interval: usize, // in seconds
    tracker_id: String,
    num_seeders: usize,
    num_leachers: usize,
}

struct File {
    path: String, // can be file or directory name
    length: usize,
    md5: Option<String>, // optional, try not to use
}

struct Peer {
    id: String, // peer_id
    ip_port: String,

    am_choking: bool,
    peer_choking: bool,
    am_interested: bool,
    peer_interested: bool,
}

impl Peer {
    fn new(id: String, ip_port: String) -> Peer {
        Peer {
            id: id,
            ip_port: ip_port,
            am_choking: true,
            am_interested: false,
            peer_choking: true,
            peer_interested: false,
        }
    }
}

struct TrackerRequest {
    info_hash: String,
    peer_id: String,
    port: usize, // port client is listening on, between 6881-6889
    uploaded: usize,
    downloaded: usize,
    left: usize,
    event: EventType, // TODO think about adding optional fields
}

enum EventType {
    Started,
    Stopped,
    Completed,
}
<commit_msg>Add new for Torrent<commit_after>use url::Url;
use bip_util::sha::ShaHash;

struct BTClient {
    torrents: Vec<Torrent>,
    id: String, // peer_id or client id
}

struct Torrent {
    // MetaInfo
    announce: Url,
    piece_length: usize,
    pieces_sha1: Vec<ShaHash>,
    name: String, // can be file or directory name
    length: Option<usize>,
    md5: Option<String>, // optional, try not to use
    files: Option<File>,

    // From/For tracker
    peers: Vec<Peer>,
    uploaded: usize,
    downloaded: usize,
    left: usize,
    interval: usize, // in seconds
    tracker_id: String,
    num_seeders: usize,
    num_leachers: usize,
}

impl Torrent {
    fn new(url: Url, plen: usize, pieces: Vec<ShaHash>) -> Torrent {
        Torrent {
            announce: url,
            piece_length: plen,
            pieces_sha1: pieces,
            name: String::new(),
            length: None,
            md5: None,
            files: None,

            peers: Vec::new(),
            uploaded: 0,
            downloaded: 0,
            left: 0,
            interval: 0, // in seconds
            tracker_id: String::new(),
            num_seeders: 0,
            num_leachers: 0,
        }
    }
}

struct File {
    path: String, // can be file or directory name
    length: usize,
    md5: Option<String>, // optional, try not to use
}

struct Peer {
    id: String, // peer_id
    ip_port: String,

    am_choking: bool,
    peer_choking: bool,
    am_interested: bool,
    peer_interested: bool,
}

impl Peer {
    fn new(id: String, ip_port: String) -> Peer {
        Peer {
            id: id,
            ip_port: ip_port,
            am_choking: true,
            am_interested: false,
            peer_choking: true,
            peer_interested: false,
        }
    }
}

struct TrackerRequest {
    info_hash: String,
    peer_id: String,
    port: usize, // port client is listening on, between 6881-6889
    uploaded: usize,
    downloaded: usize,
    left: usize,
    event: EventType, // TODO think about adding optional fields
}

enum EventType {
    Started,
    Stopped,
    Completed,
}
<|endoftext|>


<commit_before>use std::fmt;
use std::rc::Rc;
use data::{Value, List, Scope, Function, RuntimeError};
use data::RuntimeError::*;
use scope::{GlobalScope, LocalScope};
use lambda::Lambda;

pub struct BuiltinFn
{
    pub name: &'static str,
    pub do_eval: bool,
    pub func: Box<Fn(&List, &mut Scope) -> Result<Value, RuntimeError>>,
}

impl Function for BuiltinFn
{
    fn call(&self, args: &List, env: &mut Scope, do_ev: bool) -> Result<Value, RuntimeError>
    {
        if do_ev && self.do_eval
        {
            (self.func)(&try!(args.eval(env)), env)
        }
        else
        {
            (self.func)(args, env)
        }
    }
}

impl PartialEq for BuiltinFn
{
    fn eq(&self, other: &Self) -> bool
    {
        self.name == other.name
    }
}

impl fmt::Debug for BuiltinFn
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "BuiltinFn({})", self.name)
    }
}

macro_rules! check_arg
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(val) => val,
        None => return Err(InvalidArgNum($num, $cur)),
    });
    ($it:expr, $ty:ident, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::$ty(val)) => val,
        Some(other) => return Err(InvalidArgType(stringify!($ty), other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    });
}

macro_rules! check_function
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::Builtin(func)) => func as Rc<Function>,
        Some(Value::Lambda(func)) => func as Rc<Function>,
        Some(other) => return Err(InvalidArgType("Function", other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    })
}

macro_rules! map_value
{
    ($v:expr, $ty:ident, $f:expr) => (match $v {
        Value::$ty(val) => Ok($f(val)),
        _ => Err(InvalidArgType(stringify!($ty), $v.type_name())),
    })
}

pub fn load_builtins(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1, 0))
    });

    fn assign_impl<'a, F>(args: &List, env: &'a mut Scope, f: F) -> Result<Value, RuntimeError>
        where F: Fn(&'a mut Scope, &str, Value)
    {
        let mut iter = args.iter();
        let key = check_arg!(iter, Symbol, 2, 0);
        let val = try!(check_arg!(iter, 2, 1).eval(env));
        f(env, &key, val.clone());
        Ok(val)
    };

    env.set_builtin("let", false, |args, env| assign_impl(args, env, Scope::decl));
    env.set_builtin("set", false, |args, env| assign_impl(args, env, Scope::set));

    env.set_builtin("funcall", true, |args, env| args.call(env));

    env.set_builtin("apply", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        List::cons(func, lst).call(env)
    });

    env.set_builtin("map", true, |args, env| {
        let mut iter = args.iter();
        let func = check_function!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        lst.iter().map(|val| func.call(&val.wrap(), env, false)).collect::<Result<_, _>>()
            .map(|lst| Value::List(lst))
    });

    env.set_builtin("fold", true, |args, env| {
        let mut iter = args.iter();
        let func = check_function!(iter, 3, 0);
        let init = check_arg!(iter, 3, 1);
        let lst = check_arg!(iter, List, 3, 2);
        lst.fold(init, |acc, val| func.call(&List::cons(acc, val.wrap()), env, false))
    });

    env.set_builtin("car", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => cons.car.clone(),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cdr", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => Value::List(cons.cdr.clone()),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cons", true, |args, _| {
        let mut iter = args.iter();
        let car = check_arg!(iter, 2, 0);
        let cdr = check_arg!(iter, List, 2, 1);
        Ok(Value::List(List::cons(car, cdr)))
    });

    env.set_builtin("list", true, |args, _| {
        Ok(Value::List(args.clone()))
    });

    env.set_builtin("not", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::Nil | Value::Bool(false) => true,
            _ => false,
        }))
    });

    env.set_builtin("and", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(true);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => return Ok(v),
                other => last = other,
            }
        }
        Ok(last)
    });

    env.set_builtin("or", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(false);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => last = v,
                other => return Ok(other),
            }
        }
        Ok(last)
    });

    env.set_builtin("if", false, |args, env| {
        let mut iter = args.iter();
        let cond = check_arg!(iter, 2, 0);
        let then = check_arg!(iter, 2, 1);
        match try!(cond.eval(env)) {
            Value::Nil | Value::Bool(false) => iter.next().unwrap_or(Value::Nil).eval(env),
            _ => then.eval(env),
        }
    });

    env.set_builtin("begin", false, |args, env| {
        let mut local = LocalScope::new(env);
        args.eval_to_value(&mut local)
    });

    env.set_builtin("eval", true, |args, env| {
        let mut iter = args.iter();
        let expr = check_arg!(iter, 1, 0);
        expr.eval(env)
    });

    env.set_builtin("lambda", false, |args, _| {
        let (arg_lst, code) = match *args {
            List::Node(ref cons) => match cons.car {
                Value::List(ref lst) => (lst, cons.cdr.clone()),
                ref other => return Err(InvalidArgType("List", other.type_name())),
            },
            List::End => return Err(InvalidArgNum(1, 0)),
        };
        arg_lst.iter().map(|val| map_value!(val, Symbol, |n: Rc<String>| (*n).clone()))
            .collect::<Result<_, _>>()
            .map(|names| Value::Lambda(Rc::new(Lambda::new(names, code))))
    });

    env.set_builtin("+", true, |args, _| {
        args.fold(0.0, |acc, val| map_value!(val, Number, |n| acc + n)).map(|n| Value::Number(n))
    });

    env.set_builtin("*", true, |args, _| {
        args.fold(1.0, |acc, val| map_value!(val, Number, |n| acc * n)).map(|n| Value::Number(n))
    });

    fn numeric_op<F, G>(args: &List, ident: f64, op: F) -> Result<Value, RuntimeError>
        where F: Fn(f64) -> G, G: Fn(f64) -> f64
    {
        match *args {
            List::Node(ref c1) => match c1.cdr {
                List::Node(_) => match c1.car {
                    Value::Number(num) => c1.cdr.fold(num, |acc, val| map_value!(val, Number, op(acc))),
                    ref other => Err(InvalidArgType("Number", other.type_name())),
                },
                List::End => map_value!(c1.car, Number, op(ident)),
            },
            List::End => Err(InvalidArgNum(1, 0)),
        }.map(|n| Value::Number(n))
    }

    env.set_builtin("-", true, |args, _| numeric_op(args, 0.0, |lhs| move |rhs| lhs - rhs));
    env.set_builtin("/", true, |args, _| numeric_op(args, 1.0, |lhs| move |rhs| lhs / rhs));

    env.set_builtin("equal", true, |args, _| {
        let mut iter = args.iter();
        let va = check_arg!(iter, 2, 0);
        let vb = check_arg!(iter, 2, 1);
        Ok(Value::Bool(va == vb))
    });

    fn comp_op<F, G>(args: &List, op_num: F, op_str: G) -> Result<Value, RuntimeError>
        where F: Fn(f64, f64) -> bool, G: Fn(&str, &str) -> bool
    {
        let mut iter = args.iter();
        let va = check_arg!(iter, 2, 0);
        let vb = check_arg!(iter, 2, 1);
        match (va, vb) {
            (Value::Number(a), Value::Number(b)) => Ok(op_num(a, b)),
            (Value::String(ref a), Value::String(ref b)) => Ok(op_str(a, b)),
            (a, b) => Err(InvalidComp(a.type_name(), b.type_name())),
        }.map(|b| Value::Bool(b))
    }

    env.set_builtin("<", true, |args, _| comp_op(args, |a, b| a < b, |a, b| a < b));
    env.set_builtin(">", true, |args, _| comp_op(args, |a, b| a > b, |a, b| a > b));
    env.set_builtin("<=", true, |args, _| comp_op(args, |a, b| a <= b, |a, b| a <= b));
    env.set_builtin(">=", true, |args, _| comp_op(args, |a, b| a >= b, |a, b| a >= b));

    env.set_builtin("atom", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::List(List::Node(_)) => false,
            _ => true,
        }))
    });

    env.set_builtin("typeof", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::String(Rc::new(val.type_name().to_string())))
    });
}
<commit_msg>added some inline attributes<commit_after>use std::fmt;
use std::rc::Rc;
use data::{Value, List, Scope, Function, RuntimeError};
use data::RuntimeError::*;
use scope::{GlobalScope, LocalScope};
use lambda::Lambda;

pub struct BuiltinFn
{
    pub name: &'static str,
    pub do_eval: bool,
    pub func: Box<Fn(&List, &mut Scope) -> Result<Value, RuntimeError>>,
}

impl Function for BuiltinFn
{
    fn call(&self, args: &List, env: &mut Scope, do_ev: bool) -> Result<Value, RuntimeError>
    {
        if do_ev && self.do_eval
        {
            (self.func)(&try!(args.eval(env)), env)
        }
        else
        {
            (self.func)(args, env)
        }
    }
}

impl PartialEq for BuiltinFn
{
    fn eq(&self, other: &Self) -> bool
    {
        self.name == other.name
    }
}

impl fmt::Debug for BuiltinFn
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "BuiltinFn({})", self.name)
    }
}

macro_rules! check_arg
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(val) => val,
        None => return Err(InvalidArgNum($num, $cur)),
    });
    ($it:expr, $ty:ident, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::$ty(val)) => val,
        Some(other) => return Err(InvalidArgType(stringify!($ty), other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    });
}

macro_rules! check_function
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::Builtin(func)) => func as Rc<Function>,
        Some(Value::Lambda(func)) => func as Rc<Function>,
        Some(other) => return Err(InvalidArgType("Function", other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    })
}

macro_rules! map_value
{
    ($v:expr, $ty:ident, $f:expr) => (match $v {
        Value::$ty(val) => Ok($f(val)),
        _ => Err(InvalidArgType(stringify!($ty), $v.type_name())),
    })
}

pub fn load_builtins(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1, 0))
    });

    #[inline(always)]
    fn assign_impl<'a, F>(args: &List, env: &'a mut Scope, f: F) -> Result<Value, RuntimeError>
        where F: Fn(&'a mut Scope, &str, Value)
    {
        let mut iter = args.iter();
        let key = check_arg!(iter, Symbol, 2, 0);
        let val = try!(check_arg!(iter, 2, 1).eval(env));
        f(env, &key, val.clone());
        Ok(val)
    };

    env.set_builtin("let", false, |args, env| assign_impl(args, env, Scope::decl));
    env.set_builtin("set", false, |args, env| assign_impl(args, env, Scope::set));

    env.set_builtin("funcall", true, |args, env| args.call(env));

    env.set_builtin("apply", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        List::cons(func, lst).call(env)
    });

    env.set_builtin("map", true, |args, env| {
        let mut iter = args.iter();
        let func = check_function!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        lst.iter().map(|val| func.call(&val.wrap(), env, false)).collect::<Result<_, _>>()
            .map(|lst| Value::List(lst))
    });

    env.set_builtin("fold", true, |args, env| {
        let mut iter = args.iter();
        let func = check_function!(iter, 3, 0);
        let init = check_arg!(iter, 3, 1);
        let lst = check_arg!(iter, List, 3, 2);
        lst.fold(init, |acc, val| func.call(&List::cons(acc, val.wrap()), env, false))
    });

    env.set_builtin("car", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => cons.car.clone(),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cdr", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => Value::List(cons.cdr.clone()),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cons", true, |args, _| {
        let mut iter = args.iter();
        let car = check_arg!(iter, 2, 0);
        let cdr = check_arg!(iter, List, 2, 1);
        Ok(Value::List(List::cons(car, cdr)))
    });

    env.set_builtin("list", true, |args, _| {
        Ok(Value::List(args.clone()))
    });

    env.set_builtin("not", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::Nil | Value::Bool(false) => true,
            _ => false,
        }))
    });

    env.set_builtin("and", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(true);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => return Ok(v),
                other => last = other,
            }
        }
        Ok(last)
    });

    env.set_builtin("or", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(false);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => last = v,
                other => return Ok(other),
            }
        }
        Ok(last)
    });

    env.set_builtin("if", false, |args, env| {
        let mut iter = args.iter();
        let cond = check_arg!(iter, 2, 0);
        let then = check_arg!(iter, 2, 1);
        match try!(cond.eval(env)) {
            Value::Nil | Value::Bool(false) => iter.next().unwrap_or(Value::Nil).eval(env),
            _ => then.eval(env),
        }
    });

    env.set_builtin("begin", false, |args, env| {
        let mut local = LocalScope::new(env);
        args.eval_to_value(&mut local)
    });

    env.set_builtin("eval", true, |args, env| {
        let mut iter = args.iter();
        let expr = check_arg!(iter, 1, 0);
        expr.eval(env)
    });

    env.set_builtin("lambda", false, |args, _| {
        let (arg_lst, code) = match *args {
            List::Node(ref cons) => match cons.car {
                Value::List(ref lst) => (lst, cons.cdr.clone()),
                ref other => return Err(InvalidArgType("List", other.type_name())),
            },
            List::End => return Err(InvalidArgNum(1, 0)),
        };
        arg_lst.iter().map(|val| map_value!(val, Symbol, |n: Rc<String>| (*n).clone()))
            .collect::<Result<_, _>>()
            .map(|names| Value::Lambda(Rc::new(Lambda::new(names, code))))
    });

    env.set_builtin("+", true, |args, _| {
        args.fold(0.0, |acc, val| map_value!(val, Number, |n| acc + n)).map(|n| Value::Number(n))
    });

    env.set_builtin("*", true, |args, _| {
        args.fold(1.0, |acc, val| map_value!(val, Number, |n| acc * n)).map(|n| Value::Number(n))
    });

    #[inline(always)]
    fn numeric_op<F, G>(args: &List, ident: f64, op: F) -> Result<Value, RuntimeError>
        where F: Fn(f64) -> G, G: Fn(f64) -> f64
    {
        match *args {
            List::Node(ref c1) => match c1.cdr {
                List::Node(_) => match c1.car {
                    Value::Number(num) => c1.cdr.fold(num, |acc, val| map_value!(val, Number, op(acc))),
                    ref other => Err(InvalidArgType("Number", other.type_name())),
                },
                List::End => map_value!(c1.car, Number, op(ident)),
            },
            List::End => Err(InvalidArgNum(1, 0)),
        }.map(|n| Value::Number(n))
    }

    env.set_builtin("-", true, |args, _| numeric_op(args, 0.0, |lhs| move |rhs| lhs - rhs));
    env.set_builtin("/", true, |args, _| numeric_op(args, 1.0, |lhs| move |rhs| lhs / rhs));

    env.set_builtin("equal", true, |args, _| {
        let mut iter = args.iter();
        let va = check_arg!(iter, 2, 0);
        let vb = check_arg!(iter, 2, 1);
        Ok(Value::Bool(va == vb))
    });

    #[inline(always)]
    fn comp_op<F, G>(args: &List, op_num: F, op_str: G) -> Result<Value, RuntimeError>
        where F: Fn(f64, f64) -> bool, G: Fn(&str, &str) -> bool
    {
        let mut iter = args.iter();
        let va = check_arg!(iter, 2, 0);
        let vb = check_arg!(iter, 2, 1);
        match (va, vb) {
            (Value::Number(a), Value::Number(b)) => Ok(op_num(a, b)),
            (Value::String(ref a), Value::String(ref b)) => Ok(op_str(a, b)),
            (a, b) => Err(InvalidComp(a.type_name(), b.type_name())),
        }.map(|b| Value::Bool(b))
    }

    env.set_builtin("<", true, |args, _| comp_op(args, |a, b| a < b, |a, b| a < b));
    env.set_builtin(">", true, |args, _| comp_op(args, |a, b| a > b, |a, b| a > b));
    env.set_builtin("<=", true, |args, _| comp_op(args, |a, b| a <= b, |a, b| a <= b));
    env.set_builtin(">=", true, |args, _| comp_op(args, |a, b| a >= b, |a, b| a >= b));

    env.set_builtin("atom", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::List(List::Node(_)) => false,
            _ => true,
        }))
    });

    env.set_builtin("typeof", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::String(Rc::new(val.type_name().to_string())))
    });
}
<|endoftext|>