<commit_before>use std::io::{self, BufReader};
use std::io::BufRead;
use std::fs::File;

extern crate time;

extern crate stats;
use stats::median;

extern crate clap;
use clap::{Arg, App};

mod percentile;
use percentile::percentile;

mod http_status;

mod request_response;
use request_response::*;

pub fn open_logfile(path: &str) -> Result<(Vec<Request>,Vec<Response>), io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();

    for line in f.lines() {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            let r = try!(Request::new_from_log_line(&line_value));
            requests.push(r)
        }

        if line_value.contains("<-") {
            let r = try!(Response::new_from_log_line(&line_value));
            responses.push(r)
        }

    }

    responses.sort_by_key(|r| r.id);

    Ok((requests, responses))
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    count: usize,
    max: usize,
    min: usize,
    avg: usize,
    median: usize,
    percentile90: usize,
}

pub fn analyze(request_response_pairs: &Vec<RequestResponsePair>) -> RequestLogAnalyzerResult {
    let times: Vec<i64> = request_response_pairs.iter()
        .map(|rr: &RequestResponsePair| -> i64 {rr.response.response_time.num_milliseconds() })
        .collect();

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile(&times, 0.9) as usize;

    let median = median(times.into_iter()).unwrap() as usize;

    RequestLogAnalyzerResult {
        count: request_response_pairs.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    }
}

fn render_terminal(result: RequestLogAnalyzerResult) {
    println!("count:\t{}", result.count);
    println!("time.avg:\t{}", result.avg);
    println!("time.min:\t{}", result.min);
    println!("time.median:\t{}", result.median);
    println!("time.90percent:\t{}", result.percentile90);
    println!("time.max:\t{}", result.max);
}

fn main() {
    let matches = App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .help("Log file to analyze")
            .takes_value(true))
            .get_matches();

    let filename = matches.value_of("filename").unwrap();

    let lines = open_logfile(filename);
    let (requests, responses) = lines.unwrap();

    let pairs: Vec<RequestResponsePair> = pair_requests_responses(requests, responses);

    let result: RequestLogAnalyzerResult = analyze(&pairs);

    render_terminal(result);
}

#[cfg(test)]
mod tests {
	use super::*;
    extern crate time;
    use time::strptime;
    use::time::Duration;
    use http_status::HttpStatus;
    use request_response::*;

    #[test]
    fn test_open_logfile() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
        assert_eq!(responses.len(), 2);
    }

    #[test]
    fn test_get_matching_response() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        let result = requests[0].get_matching_response(&responses);

        let expected = Response {
            id: 1,
            time: strptime("08/Apr/2016:09:57:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            mime_type: "text/html".to_string(),
            response_time: Duration::milliseconds(7),
            http_status: HttpStatus::OK,
        };

        assert_eq!(*result.unwrap(), expected);
    }

    #[test]
    fn test_get_matching_response_none_found() {
        let lines = open_logfile("src/test/simple-1.log");
        let (_, responses) = lines.unwrap();

        let request_without_matching = Request {
            id: 999,
            time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            url: "/content/some/other.html".to_string()
        };

        let result = request_without_matching.get_matching_response(&responses);

        assert!(result.is_none());
    }

    #[test]
    fn test_pair_requests_resonses() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        let result = pair_requests_responses(requests, responses);

        assert_eq!(result.len(), 2);

        assert_eq!(result[0].request.id, result[0].response.id);
        assert_eq!(result[1].request.id, result[1].response.id);
    }

    #[test]
    fn test_request_log_analyzer_result() {
        let lines = open_logfile("src/test/response-time-calculations.log");
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs);

        let expected = RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        };

        assert_eq!(result, expected);
    }

    #[test]
    fn test_90_percentile_calculation() {
        let lines = open_logfile("src/test/percentile.log");
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs);

        assert_eq!(result.percentile90, 9);
    }
}
<commit_msg>Make test independent from file access<commit_after>use std::io::{self, BufReader};
use std::io::BufRead;
use std::fs::File;

extern crate time;

extern crate stats;
use stats::median;

extern crate clap;
use clap::{Arg, App};

mod percentile;
use percentile::percentile;

mod http_status;

mod request_response;
use request_response::*;

pub fn open_logfile(path: &str) -> Result<(Vec<Request>,Vec<Response>), io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();

    for line in f.lines() {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            let r = try!(Request::new_from_log_line(&line_value));
            requests.push(r)
        }

        if line_value.contains("<-") {
            let r = try!(Response::new_from_log_line(&line_value));
            responses.push(r)
        }

    }

    responses.sort_by_key(|r| r.id);

    Ok((requests, responses))
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    count: usize,
    max: usize,
    min: usize,
    avg: usize,
    median: usize,
    percentile90: usize,
}

pub fn analyze(request_response_pairs: &Vec<RequestResponsePair>) -> RequestLogAnalyzerResult {
    let times: Vec<i64> = request_response_pairs.iter()
        .map(|rr: &RequestResponsePair| -> i64 {rr.response.response_time.num_milliseconds() })
        .collect();

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile(&times, 0.9) as usize;

    let median = median(times.into_iter()).unwrap() as usize;

    RequestLogAnalyzerResult {
        count: request_response_pairs.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    }
}

fn render_terminal(result: RequestLogAnalyzerResult) {
    println!("count:\t{}", result.count);
    println!("time.avg:\t{}", result.avg);
    println!("time.min:\t{}", result.min);
    println!("time.median:\t{}", result.median);
    println!("time.90percent:\t{}", result.percentile90);
    println!("time.max:\t{}", result.max);
}

fn main() {
    let matches = App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .help("Log file to analyze")
            .takes_value(true))
            .get_matches();

    let filename = matches.value_of("filename").unwrap();

    let lines = open_logfile(filename);
    let (requests, responses) = lines.unwrap();

    let pairs: Vec<RequestResponsePair> = pair_requests_responses(requests, responses);

    let result: RequestLogAnalyzerResult = analyze(&pairs);

    render_terminal(result);
}

#[cfg(test)]
mod tests {
	use super::*;
    extern crate time;
    use time::strptime;
    use::time::Duration;
    use http_status::HttpStatus;
    use request_response::*;

    #[test]
    fn test_open_logfile() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
        assert_eq!(responses.len(), 2);
    }

    #[test]
    fn test_get_matching_response() {
        let request = Request {
            id: 2,
            time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            url: "/content/some/other.html".to_string()
        };

        let responses = vec![
            Response {
                id: 1,
                time: strptime("08/Apr/2016:09:57:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
                mime_type: "text/html".to_string(),
                response_time: Duration::milliseconds(7),
                http_status: HttpStatus::OK,
            },
            Response {
                id: 2,
                time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
                mime_type: "text/html".to_string(),
                response_time: Duration::milliseconds(10),
                http_status: HttpStatus::OK,
            },
        ];

        let result = request.get_matching_response(&responses);
        assert_eq!(result.unwrap().id, 2);
    }

    #[test]
    fn test_get_matching_response_none_found() {
        let lines = open_logfile("src/test/simple-1.log");
        let (_, responses) = lines.unwrap();

        let request_without_matching = Request {
            id: 999,
            time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            url: "/content/some/other.html".to_string()
        };

        let result = request_without_matching.get_matching_response(&responses);

        assert!(result.is_none());
    }

    #[test]
    fn test_pair_requests_resonses() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        let result = pair_requests_responses(requests, responses);

        assert_eq!(result.len(), 2);

        assert_eq!(result[0].request.id, result[0].response.id);
        assert_eq!(result[1].request.id, result[1].response.id);
    }

    #[test]
    fn test_request_log_analyzer_result() {
        let lines = open_logfile("src/test/response-time-calculations.log");
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs);

        let expected = RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        };

        assert_eq!(result, expected);
    }

    #[test]
    fn test_90_percentile_calculation() {
        let lines = open_logfile("src/test/percentile.log");
        let (requests, responses) = lines.unwrap();

        let request_response_pairs = pair_requests_responses(requests, responses);

        let result: RequestLogAnalyzerResult = analyze(&request_response_pairs);

        assert_eq!(result.percentile90, 9);
    }
}
<|endoftext|>


<commit_before>//! A cargo subcommand for displaying line counts of source code in projects,
//! including a niave `unsafe` counter for Rust source files. This subcommand
//! was originally based off and inspired by the project
//! [tokei](https://github.com/aaronepower/tokei) by
//! [Aaronepower](https://github.com/aaronepower)
//!
//! ## Demo
//!
//! To count the source code in the [Rust](https://github.com/rust-lang/rust)
//! repository (checkout `4c99649`), and print some naive statistics on how much
//! "unsafe" code exists.
//!
//! **NOTE:** The Rust repository is quite large, if you're on a slow internet
//! connection consider using a smaller repository, such as the `cargo-count`
//! repo.
//!
//! ```ignore
//! $ git clone https://github.com/rust-lang/rust
//! $ cd rust
//! $ cargo count --separator , --unsafe-statistics
//! Gathering information...
//!          Language    Files  Lines    Blanks  Comments  Code     Unsafe (%)
//!          --------    -----  -----    ------  --------  ----     ----------
//! Rust        6,018  528,510  66,984  133,698   327,792  3,163
//! (0.96%)
//! C           54     9,962    1,445   1,492     7,025    7,025
//! (100.00%)
//!          CSS         4      1,266    149     52        1,065
//!          JavaScript  4      1,118    131     166       821
//!          Python      31     4,797    843     585       3,369
//! C Header    13     1,865    284     585       996      996
//! (100.00%)
//! C++         4      1,611    185     81        1,345    1,345
//! (100.00%)
//!          --------    -----  -----    ------  --------  ----     ----------
//! Totals:              6,128  549,129  70,021  136,659   342,413  12,529
//! (3.66%)
//!
//! ```
//!
//! The `--separator ,` sets a `,` character as the thousands separator, and
//! `--unsafe-statistics` looks for, and counts lines of `unsafe`.
//!
//! ## Compiling
//!
//! Follow these instructions to compile `cargo-count`, then skip down to
//! Installation.
//!
//!  1. Ensure you have current version of `cargo` and
//!     [Rust](https://www.rust-lang.org) installed
//!  2. Clone the project
//!     `$ git clone https://github.com/kbknapp/cargo-count && cd cargo-count`
//!  3. Build the project `$ cargo build --release` (**NOTE:** There is a large
//!     performance differnce when compiling without optimizations, so I
//!     recommend alwasy using `--release` to enable to them)
//!  4. Once complete, the binary will be located at
//!     `target/release/cargo-count`
//!
//! ## Installation and Usage
//!
//! All you need to do is place `cargo-count` somewhere in your `$PATH`. Then
//! run `cargo count` anywhere in your project directory. For full details see
//! below.
//!
//! ### Linux / OS X
//!
//! You have two options, place `cargo-count` into a directory that is already
//! located in your `$PATH` variable (To see which directories those are, open
//! a terminal and type `echo "${PATH//:/\n}"`, the quotation marks are
//! important), or you can add a custom directory to your `$PATH`
//!
//! **Option 1**
//! If you have write permission to a directory listed in your `$PATH` or you
//! have root permission (or via `sudo`), simply copy the `cargo-count` to that
//! directory `# sudo cp cargo-count /usr/local/bin`
//!
//! **Option 2**
//! If you do not have root, `sudo`, or write permission to any directory
//! already in `$PATH` you can create a directory inside your home directory,
//! and add that. Many people use `$HOME/.bin` to keep it hidden (and not
//! clutter your home directory), or `$HOME/bin` if you want it to be always
//! visible. Here is an example to make the directory, add it to `$PATH`, and
//! copy `cargo-count` there.
//!
//! Simply change `bin` to whatever you'd like to name the directory, and
//! `.bashrc` to whatever your shell startup file is (usually `.bashrc`,
//! `.bash_profile`, or `.zshrc`)
//!
//! ```sh
//! $ mkdir ~/bin
//! $ echo "export PATH=$PATH:$HOME/bin" >> ~/.bashrc
//! $ cp cargo-count ~/bin
//! $ source ~/.bashrc
//! ```
//!
//! ### Windows
//!
//! On Windows 7/8 you can add directory to the `PATH` variable by opening a
//! command line as an administrator and running
//!
//! ```sh
//! C:\> setx path "%path%;C:\path\to\cargo-count\binary"
//! ```
//!
//! Otherwise, ensure you have the `cargo-count` binary in the directory which
//! you operating in the command line from, because Windows automatically adds
//! your current directory to PATH (i.e. if you open a command line to
//! `C:\my_project\` to use `cargo-count` ensure `cargo-count.exe` is inside
//! that directory as well).
//!
//!
//! ### Options
//!
//! There are a few options for using `cargo-count` which should be somewhat
//! self explanitory.
//!
//! ```ignore
//! USAGE:
//!     cargo count [FLAGS] [OPTIONS] [--] [ARGS]
//!
//! FLAGS:
//! -S, --follow-symlinks      Follows symlinks and counts source files it
//! finds
//! -a, --all                  Do not ignore .gitignored paths
//!                                (Defaults to false when omitted)
//!     -h, --help                 Prints help information
//! --unsafe-statistics    Displays lines and percentages of "unsafe"
//! code
//!     -V, --version              Prints version information
//!     -v, --verbose              Print verbose output
//!
//! OPTIONS:
//! -l, --language <exts>...    Only count these languges (by source code
//! extension)
//!                                 (i.e. '-l js py cpp')
//! -e, --exclude <paths>...    Files or directories to exclude
//! (automatically includes '.git')
//! --utf8-rule <rule>      Sets the UTF-8 parsing rule (Defaults to
//! 'strict')
//!                                  [values: ignore lossy strict]
//! -s, --separator <sep>       Set the thousands separator for pretty
//! printing
//!
//! ARGS:
//!     to_count...    The files or directories (including children) to count
//!                    (defaults to current working directory when omitted)
//!
//! When using '--exclude <path>' the path given can either be relative to the
//! current
//! directory, or absolute. When '<path>' is a file, it must be relative to the
//! current
//! directory or it will not be found. Example, if the current directory has a
//! child
//! directory named 'target' with a child fild 'test.rs' and you use `--exclude
//! target/test.rs'
//!
//! Globs are also supported. For example, to eclude 'test.rs' files from all
//! child directories
//! of the current directory you could do '--exclude */test.rs'.
//! ```
//!
//! ## License
//!
//! `cargo-count` is released under the terms of the MIT. See the LICENSE-MIT
//! file for the details.
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", allow(explicit_iter_loop))]
#![cfg_attr(feature = "lints", allow(should_implement_trait))]
#![cfg_attr(feature = "lints", allow(unstable_features))]
#![cfg_attr(feature = "lints", deny(warnings))]
#![cfg_attr(not(any(feature = "nightly", feature = "unstable")), deny(unstable_features))]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate clap;
#[cfg(feature = "color")]
extern crate ansi_term;
extern crate tabwriter;
extern crate glob;
extern crate regex;
extern crate gitignore;

use std::io::Write;
#[cfg(feature = "debug")]
use std::env;

use clap::{App, AppSettings, Arg, SubCommand};

use config::Config;
use count::Counts;
use error::{CliError, CliResult};
use fmt::Format;

#[macro_use]
mod macros;
mod comment;
mod config;
mod count;
mod error;
mod fmt;
mod fsutil;
mod language;

static UTF8_RULES: [&'static str; 3] = ["strict", "lossy", "ignore"];

fn main() {
    debugln!("executing; cmd=cargo-count; args={:?}",
             env::args().collect::<Vec<_>>());
    let m = App::new("cargo-count")
        .version(&*format!("v{}", crate_version!()))
    // We have to lie about our binary name since this will be a third party
    // subcommand for cargo but we want usage strings to generated properly
        .bin_name("cargo")
    // Global version uses the version we supplied (Cargo.toml) for all subcommands
    // as well
        .settings(&[AppSettings::GlobalVersion,
                    AppSettings::SubcommandRequired])
    // We use a subcommand because everything parsed after `cargo` is sent to the
    // third party
    // plugin which will then be interpreted as a subcommand/positional arg by clap
        .subcommand(SubCommand::with_name("count")
            .author("Kevin K. <kbknapp@gmail.com>")
            .about("Displays line counts of code for cargo projects")
            .args_from_usage("-e, --exclude [paths]...    'Files or directories to exclude (automatically includes \'.git\')'
                              -a, --all                   'Do not ignore .gitignore'd paths'
                              --unsafe-statistics         'Displays lines and percentages of \"unsafe\" code'
                              -l, --language [exts]...    'Only count these languges (i.e. \'-l js py cpp\')'
                              -v, --verbose               'Print verbose output'
                              -S, --follow-symlinks       'Follows symlinks and counts source files it finds (Defaults to false when omitted)'
                              [to_count]...               'The files or directories (including children) to count{n}\
                                                           (defaults to current working directory when omitted)'")
            .arg(Arg::from_usage("-s, --separator [sep]   'Set the thousands separator for pretty printing'")
                .validator(single_char))
            .arg(Arg::from_usage("--utf8-rule [rule]     'Sets the UTF-8 parsing rule (Defaults to \'strict\'){n}'")
                .possible_values(&UTF8_RULES))
            .after_help("When using '--exclude <path>' the path given can either be relative to the current \n\
                         directory, or absolute. When '<path>' is a file, it must be relative to the current \n\
                         directory or it will not be found. Example, if the current directory has a child \n\
                         directory named 'target' with a child fild 'test.rs' and you use `--exclude target/test.rs' \n\
                         \n\
                         Globs are also supported. For example, to eclude 'test.rs' files from all child directories \n\
                         of the current directory you could do '--exclude */test.rs'."))
        .get_matches();

    if let Some(m) = m.subcommand_matches("count") {
        let cfg = Config::from_matches(m).unwrap_or_else(|e| e.exit());
        println!("Gathering information...");
        if let Err(e) = execute(cfg) {
            e.exit();
        }
    }
}

fn execute(cfg: Config) -> CliResult<()> {
    debugln!("executing; cmd=execute;");
    verboseln!(cfg, "{}: {:?}", Format::Warning("Excluding"), cfg.exclude);
    verbose!(cfg,
             "{}",
             if cfg.exts.is_some() {
                 format!("{} including files with extension: {}\n",
                         Format::Warning("Only"),
                         cfg.exts
                            .as_ref()
                            .unwrap()
                            .join(", "))
             } else {
                 "".to_owned()
             });

    debugln!("Checking for files or dirs to count from cli");

    let mut counts = Counts::new(&cfg);
    counts.fill_from();
    cli_try!(counts.count());
    cli_try!(counts.write_results());
    Ok(())
}

fn single_char(s: String) -> Result<(), String> {
    if s.len() == 1 {
        Ok(())
    } else {
        Err(
          format!(
            "the --separator argument option only accepts a single character but found '{}'",
             Format::Warning(s)))
    }
}
<commit_msg>style(main): remove unused std::io::Write import<commit_after>//! A cargo subcommand for displaying line counts of source code in projects,
//! including a niave `unsafe` counter for Rust source files. This subcommand
//! was originally based off and inspired by the project
//! [tokei](https://github.com/aaronepower/tokei) by
//! [Aaronepower](https://github.com/aaronepower)
//!
//! ## Demo
//!
//! To count the source code in the [Rust](https://github.com/rust-lang/rust)
//! repository (checkout `4c99649`), and print some naive statistics on how much
//! "unsafe" code exists.
//!
//! **NOTE:** The Rust repository is quite large, if you're on a slow internet
//! connection consider using a smaller repository, such as the `cargo-count`
//! repo.
//!
//! ```ignore
//! $ git clone https://github.com/rust-lang/rust
//! $ cd rust
//! $ cargo count --separator , --unsafe-statistics
//! Gathering information...
//!          Language    Files  Lines    Blanks  Comments  Code     Unsafe (%)
//!          --------    -----  -----    ------  --------  ----     ----------
//! Rust        6,018  528,510  66,984  133,698   327,792  3,163
//! (0.96%)
//! C           54     9,962    1,445   1,492     7,025    7,025
//! (100.00%)
//!          CSS         4      1,266    149     52        1,065
//!          JavaScript  4      1,118    131     166       821
//!          Python      31     4,797    843     585       3,369
//! C Header    13     1,865    284     585       996      996
//! (100.00%)
//! C++         4      1,611    185     81        1,345    1,345
//! (100.00%)
//!          --------    -----  -----    ------  --------  ----     ----------
//! Totals:              6,128  549,129  70,021  136,659   342,413  12,529
//! (3.66%)
//!
//! ```
//!
//! The `--separator ,` sets a `,` character as the thousands separator, and
//! `--unsafe-statistics` looks for, and counts lines of `unsafe`.
//!
//! ## Compiling
//!
//! Follow these instructions to compile `cargo-count`, then skip down to
//! Installation.
//!
//!  1. Ensure you have current version of `cargo` and
//!     [Rust](https://www.rust-lang.org) installed
//!  2. Clone the project
//!     `$ git clone https://github.com/kbknapp/cargo-count && cd cargo-count`
//!  3. Build the project `$ cargo build --release` (**NOTE:** There is a large
//!     performance differnce when compiling without optimizations, so I
//!     recommend alwasy using `--release` to enable to them)
//!  4. Once complete, the binary will be located at
//!     `target/release/cargo-count`
//!
//! ## Installation and Usage
//!
//! All you need to do is place `cargo-count` somewhere in your `$PATH`. Then
//! run `cargo count` anywhere in your project directory. For full details see
//! below.
//!
//! ### Linux / OS X
//!
//! You have two options, place `cargo-count` into a directory that is already
//! located in your `$PATH` variable (To see which directories those are, open
//! a terminal and type `echo "${PATH//:/\n}"`, the quotation marks are
//! important), or you can add a custom directory to your `$PATH`
//!
//! **Option 1**
//! If you have write permission to a directory listed in your `$PATH` or you
//! have root permission (or via `sudo`), simply copy the `cargo-count` to that
//! directory `# sudo cp cargo-count /usr/local/bin`
//!
//! **Option 2**
//! If you do not have root, `sudo`, or write permission to any directory
//! already in `$PATH` you can create a directory inside your home directory,
//! and add that. Many people use `$HOME/.bin` to keep it hidden (and not
//! clutter your home directory), or `$HOME/bin` if you want it to be always
//! visible. Here is an example to make the directory, add it to `$PATH`, and
//! copy `cargo-count` there.
//!
//! Simply change `bin` to whatever you'd like to name the directory, and
//! `.bashrc` to whatever your shell startup file is (usually `.bashrc`,
//! `.bash_profile`, or `.zshrc`)
//!
//! ```sh
//! $ mkdir ~/bin
//! $ echo "export PATH=$PATH:$HOME/bin" >> ~/.bashrc
//! $ cp cargo-count ~/bin
//! $ source ~/.bashrc
//! ```
//!
//! ### Windows
//!
//! On Windows 7/8 you can add directory to the `PATH` variable by opening a
//! command line as an administrator and running
//!
//! ```sh
//! C:\> setx path "%path%;C:\path\to\cargo-count\binary"
//! ```
//!
//! Otherwise, ensure you have the `cargo-count` binary in the directory which
//! you operating in the command line from, because Windows automatically adds
//! your current directory to PATH (i.e. if you open a command line to
//! `C:\my_project\` to use `cargo-count` ensure `cargo-count.exe` is inside
//! that directory as well).
//!
//!
//! ### Options
//!
//! There are a few options for using `cargo-count` which should be somewhat
//! self explanitory.
//!
//! ```ignore
//! USAGE:
//!     cargo count [FLAGS] [OPTIONS] [--] [ARGS]
//!
//! FLAGS:
//! -S, --follow-symlinks      Follows symlinks and counts source files it
//! finds
//! -a, --all                  Do not ignore .gitignored paths
//!                                (Defaults to false when omitted)
//!     -h, --help                 Prints help information
//! --unsafe-statistics    Displays lines and percentages of "unsafe"
//! code
//!     -V, --version              Prints version information
//!     -v, --verbose              Print verbose output
//!
//! OPTIONS:
//! -l, --language <exts>...    Only count these languges (by source code
//! extension)
//!                                 (i.e. '-l js py cpp')
//! -e, --exclude <paths>...    Files or directories to exclude
//! (automatically includes '.git')
//! --utf8-rule <rule>      Sets the UTF-8 parsing rule (Defaults to
//! 'strict')
//!                                  [values: ignore lossy strict]
//! -s, --separator <sep>       Set the thousands separator for pretty
//! printing
//!
//! ARGS:
//!     to_count...    The files or directories (including children) to count
//!                    (defaults to current working directory when omitted)
//!
//! When using '--exclude <path>' the path given can either be relative to the
//! current
//! directory, or absolute. When '<path>' is a file, it must be relative to the
//! current
//! directory or it will not be found. Example, if the current directory has a
//! child
//! directory named 'target' with a child fild 'test.rs' and you use `--exclude
//! target/test.rs'
//!
//! Globs are also supported. For example, to eclude 'test.rs' files from all
//! child directories
//! of the current directory you could do '--exclude */test.rs'.
//! ```
//!
//! ## License
//!
//! `cargo-count` is released under the terms of the MIT. See the LICENSE-MIT
//! file for the details.
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", allow(explicit_iter_loop))]
#![cfg_attr(feature = "lints", allow(should_implement_trait))]
#![cfg_attr(feature = "lints", allow(unstable_features))]
#![cfg_attr(feature = "lints", deny(warnings))]
#![cfg_attr(not(any(feature = "nightly", feature = "unstable")), deny(unstable_features))]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate clap;
#[cfg(feature = "color")]
extern crate ansi_term;
extern crate tabwriter;
extern crate glob;
extern crate regex;
extern crate gitignore;

#[cfg(feature = "debug")]
use std::env;

use clap::{App, AppSettings, Arg, SubCommand};

use config::Config;
use count::Counts;
use error::{CliError, CliResult};
use fmt::Format;

#[macro_use]
mod macros;
mod comment;
mod config;
mod count;
mod error;
mod fmt;
mod fsutil;
mod language;

static UTF8_RULES: [&'static str; 3] = ["strict", "lossy", "ignore"];

fn main() {
    debugln!("executing; cmd=cargo-count; args={:?}",
             env::args().collect::<Vec<_>>());
    let m = App::new("cargo-count")
        .version(&*format!("v{}", crate_version!()))
    // We have to lie about our binary name since this will be a third party
    // subcommand for cargo but we want usage strings to generated properly
        .bin_name("cargo")
    // Global version uses the version we supplied (Cargo.toml) for all subcommands
    // as well
        .settings(&[AppSettings::GlobalVersion,
                    AppSettings::SubcommandRequired])
    // We use a subcommand because everything parsed after `cargo` is sent to the
    // third party
    // plugin which will then be interpreted as a subcommand/positional arg by clap
        .subcommand(SubCommand::with_name("count")
            .author("Kevin K. <kbknapp@gmail.com>")
            .about("Displays line counts of code for cargo projects")
            .args_from_usage("-e, --exclude [paths]...    'Files or directories to exclude (automatically includes \'.git\')'
                              -a, --all                   'Do not ignore .gitignore'd paths'
                              --unsafe-statistics         'Displays lines and percentages of \"unsafe\" code'
                              -l, --language [exts]...    'Only count these languges (i.e. \'-l js py cpp\')'
                              -v, --verbose               'Print verbose output'
                              -S, --follow-symlinks       'Follows symlinks and counts source files it finds (Defaults to false when omitted)'
                              [to_count]...               'The files or directories (including children) to count{n}\
                                                           (defaults to current working directory when omitted)'")
            .arg(Arg::from_usage("-s, --separator [sep]   'Set the thousands separator for pretty printing'")
                .validator(single_char))
            .arg(Arg::from_usage("--utf8-rule [rule]     'Sets the UTF-8 parsing rule (Defaults to \'strict\'){n}'")
                .possible_values(&UTF8_RULES))
            .after_help("When using '--exclude <path>' the path given can either be relative to the current \n\
                         directory, or absolute. When '<path>' is a file, it must be relative to the current \n\
                         directory or it will not be found. Example, if the current directory has a child \n\
                         directory named 'target' with a child fild 'test.rs' and you use `--exclude target/test.rs' \n\
                         \n\
                         Globs are also supported. For example, to eclude 'test.rs' files from all child directories \n\
                         of the current directory you could do '--exclude */test.rs'."))
        .get_matches();

    if let Some(m) = m.subcommand_matches("count") {
        let cfg = Config::from_matches(m).unwrap_or_else(|e| e.exit());
        println!("Gathering information...");
        if let Err(e) = execute(cfg) {
            e.exit();
        }
    }
}

fn execute(cfg: Config) -> CliResult<()> {
    debugln!("executing; cmd=execute;");
    verboseln!(cfg, "{}: {:?}", Format::Warning("Excluding"), cfg.exclude);
    verbose!(cfg,
             "{}",
             if cfg.exts.is_some() {
                 format!("{} including files with extension: {}\n",
                         Format::Warning("Only"),
                         cfg.exts
                            .as_ref()
                            .unwrap()
                            .join(", "))
             } else {
                 "".to_owned()
             });

    debugln!("Checking for files or dirs to count from cli");

    let mut counts = Counts::new(&cfg);
    counts.fill_from();
    cli_try!(counts.count());
    cli_try!(counts.write_results());
    Ok(())
}

fn single_char(s: String) -> Result<(), String> {
    if s.len() == 1 {
        Ok(())
    } else {
        Err(
          format!(
            "the --separator argument option only accepts a single character but found '{}'",
             Format::Warning(s)))
    }
}
<|endoftext|>


<commit_before>type Player = [i8; 7];
struct Game {
    p: [Player; 2],
    t: i8,
}

fn new_player() -> Player {
    [4,4,4,4,4,4,0]
}

fn new_game() -> Game {
    Game{p: [new_player(), new_player()], t: 0}
}

fn print(g: &Game) {
    print!("|{:2}|", g.p[1][6]);
    for i in 0..6 {
        print!(" [{:2}]", g.p[1][5 - i])
    }
    print!(" /--\\");
    if g.t == 1 {
        print!(" <-- turn");
    }
    println!();
    print!("\\__/ ");
    for i in 0..6 {
        print!("[{:2}] ", g.p[0][i])
    }
    print!("|{:2}|", g.p[0][6]);
    if g.t == 0 {
        print!(" <-- turn");
    }
    println!();
}

fn main() {
    print(&new_game());
}
<commit_msg>add generation of a step; next game positions<commit_after>#![allow(dead_code)]

type Player = [i8; 7];

#[derive(Clone, Debug)]
struct Game {
    p: [Player; 2],
    t: i8,
}

fn new_player() -> Player {
    [4,4,4,4,4,4,0]
}

#[derive(Debug, PartialEq)]
enum State {
    InProgress,
    Draw,
    Win(i8),
}

impl Game {
    fn new() -> Game {
        Game{p: [new_player(), new_player()], t: 0}
    }

    fn print(&self) {
        print!("|{:2}|", self.p[1][6]);
        for i in 0..6 {
            print!(" [{:2}]", self.p[1][5 - i])
        }
        print!(" /--\\");
        if self.t == 1 {
            print!(" <-- turn");
        }
        println!();
        print!("\\--/ ");
        for i in 0..6 {
            print!("[{:2}] ", self.p[0][i])
        }
        print!("|{:2}|", self.p[0][6]);
        if self.t == 0 {
            print!(" <-- turn");
        }
        println!();
    }

    fn state(&self) -> State {
        let p0full: i8 = self.p[0].iter().sum();
        let p1full: i8 = self.p[1].iter().sum();
        let p0 = p0full - self.p[0][6];
        let p1 = p1full - self.p[1][6];
        if p0 != 0 && p1 != 0 {
            State::InProgress
        } else {
            if p0full < p1full {
                State::Win(1)
            } else if p0full > p1full {
                State::Win(0)
            } else {
                State::Draw
            }
        }
    }

    fn step(&self, s: usize) -> Option<Game> {
        if s >= 6 { panic!("wrong start index"); }
        let mut n: Game = self.clone();
        let mut leftover = n.p[n.t as usize][s];
        if leftover == 0 { return None; }

        let mut side: usize = n.t as usize;
        let mut pos: usize = s + 1;
        n.p[side][s] = 0;

        loop {
            n.p[side][pos] += 1;
            leftover -= 1;
            if leftover == 0 { break; }
            if (pos == 5 && side != self.t as usize) || (pos == 6) {
                // pos == 6 => we have reached the super bucket and have to switch sides
                // pos == 5 => we have reached opponents 0 bucket and have to return home
                side = 1 - side;
                pos = 0;
            } else {
                pos += 1;
            }
        }

        if pos < 6 { // if we have reached the super bucket, we don't give up turn
            // check for take-over
            if side == self.t as usize && n.p[side][pos] == 1 {
                let opp = 5 - pos;
                n.p[side][6] += n.p[1 - side][opp];
                n.p[1 - side][opp] = 0;
            }
            n.t = 1 - n.t; // switch the turn
        }
        Some(n)
    }
}

// next computes all the posible games for the next turn
fn next(g: &Game) -> Vec<Game> {
    let mut res: Vec<Game> = Vec::new();
    let turn = g.t;
    for i in 0..6 {
        if let Some(cand) = g.step(i) {
            if cand.t == turn && cand.state() == State::InProgress {
                for elem in next(&cand).into_iter() {
                    res.push(elem);
                }
            } else {
                res.push(cand);
            }
        }
    }
    res
}

fn main() {
    let mut g = Game::new();
    //g.p[0][0] = 6;
    g.print();
    println!("{:?}", g.state());
    //g.step(0).unwrap().print();
    for t in next(&g).into_iter() {
        t.print();
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

use std::fmt;

use rocket::http::Status;
use rocket::request::{self, Request, FromRequest};
use rocket::response::content;
use rocket::{Outcome, Response};

struct IndexData(String);

impl<'a, 'r> FromRequest<'a, 'r> for IndexData {
    type Error = ();
    fn from_request(request: &'a Request<'r>) -> request::Outcome<IndexData, ()> {
        Outcome::Success(IndexData(format!("{}", request)))
    }
}

impl fmt::Display for IndexData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[get("/")]
fn index() -> content::HTML<&'static str> {
    content::HTML("<!DOCTYPE html>

            <title>HTTPTIN</title>

HTTPTIN - HTTP tester in Rust and Rocket

    ")
}

#[get("/test")]
fn test(data: IndexData) -> String {
    format!("<!DOCTYPE html><title>HTTPTIN></title>{}", data)
}

#[get("/ip")]
fn origin() -> String {
    String::from("Remote address decoding is not implemented yet")
}

#[get("/get")]
fn get() -> String {
    String::from("method")
}

#[get("/status/<status>")]
pub fn status(status: &str) -> String {
    format!("<!DOCTYPE html><title>HTTPTIN></title>Status: {} (FIX ME)", status)
}

fn main() {
    rocket::ignite().mount("/", routes![index, origin, get, status, test]).launch();
}
<commit_msg>Fix /status endpoint<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

use std::fmt;

use rocket::http::Status;
use rocket::request::{self, Request, FromRequest};
use rocket::response::content;
use rocket::{Outcome, Response};

struct IndexData(String);

impl<'a, 'r> FromRequest<'a, 'r> for IndexData {
    type Error = ();
    fn from_request(request: &'a Request<'r>) -> request::Outcome<IndexData, ()> {
        Outcome::Success(IndexData(format!("{}", request)))
    }
}

impl fmt::Display for IndexData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[get("/")]
fn index() -> content::HTML<&'static str> {
    content::HTML("<!DOCTYPE html>

            <title>HTTPTIN</title>

HTTPTIN - HTTP tester in Rust and Rocket

    ")
}

#[get("/test")]
fn test(data: IndexData) -> String {
    format!("<!DOCTYPE html><title>HTTPTIN></title>{}", data)
}

#[get("/ip")]
fn origin() -> String {
    String::from("Remote address decoding is not implemented yet")
}

#[get("/get")]
fn get() -> String {
    String::from("method")
}

#[get("/status/")]
pub fn status<'r>(code: u16) -> Response<'r> {
    Response::build().status(Status::raw(code)).finalize()
}

fn main() {
    rocket::ignite().mount("/", routes![index, origin, get, status, test]).launch();
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate rand;
extern crate time;

use rand::Rng;

use time::PreciseTime;

use sdl::video::{SurfaceFlag, VideoFlag, Surface};
use sdl::event::{Event, Key};

struct Color {
    r: u8,
    g: u8,
    b: u8
}

struct Stars_3D {
    speed: i32,
    spread: i32,
    stars_x: Vec<f32>,
    stars_y: Vec<f32>,
    stars_z: Vec<f32>
}

impl Stars_3D {
    pub fn new(num_stars: usize, _spread: i32, _speed: i32) -> Stars_3D {
        let mut obj = Stars_3D {
            spread: _spread,
            speed: _speed,
            stars_x: vec![0.0; num_stars],
            stars_y: vec![0.0; num_stars],
            stars_z: vec![0.0; num_stars] };

        for idx in 0..num_stars {
            obj.init_star(idx);
        }

        obj
    }

    fn init_star(&mut self, idx: usize) {
        let mut rng = rand::thread_rng();
        self.stars_x[idx] = (2 as f32) * (rng.next_f32() - 0.5) * (self.spread as f32);
        self.stars_y[idx] = (2 as f32) * (rng.next_f32() - 0.5) * (self.spread as f32);
        self.stars_z[idx] = (rng.next_f32() + 0.00001) * (self.spread as f32);
    }

    pub fn update_and_render(&mut self, screen: &Surface, delta: f32) {
        clear(screen);

        let color = Color{r:233, g:233, b:233};

		let halfWidth  = screen.get_width() as f32 / 2.0f32;
		let halfHeight = screen.get_height()as f32 / 2.0f32;
        for i in 0..self.stars_x.len() {
            self.stars_z[i] -= delta * self.speed as f32;

            if(self.stars_z[i] <= 0f32) {
                self.init_star(i);
            }

            let x = (self.stars_x[i]/self.stars_z[i] * halfWidth + halfWidth);
            let y = (self.stars_y[i]/self.stars_z[i] * halfHeight + halfHeight);

            if x < 0f32 || x >= screen.get_width() as f32 || y < 0f32 || y >= screen.get_height() as f32 {
                self.init_star(i);
            } else {
                set_pixel(x as i32, y as i32, &color, &screen);
            }
        }
	}
}

fn clear(screen: &Surface) {
    screen.fill_rect(Some(sdl::Rect {
                x: 0,
                y: 0,
                w: screen.get_width(),
                h: screen.get_height()
            }), sdl::video::Color::RGB(0,0,0));
}

fn set_pixel(_x: i32, _y:i32, color: &Color, screen: &Surface) {

    // println!("{}",screen.get_width());
    let x: usize = _x as usize * 4;
    let y: usize = _y as usize * 4;
    let idx_blue: usize = x + y * screen.get_width() as usize;
    let idx_green: usize = (x + y * screen.get_width() as usize) + 1;
    let idx_red: usize = (x + y * screen.get_width() as usize) + 2;
    let idx_alpha: usize = (x + y * screen.get_width() as usize) + 3;

    screen.with_lock(|pixels| {
        pixels[idx_blue] = color.b;
        pixels[idx_green] = color.g;
        pixels[idx_red] = color.r;
        pixels[idx_alpha] = 0;

        true
    });
}

fn draw_line(x0: i32, y0: i32, x1: i32, y1: i32, color: &Color, screen: &Surface) {
    for x in x0..x1 {
        // println!("{}", x);
        let t: f32 = (x-x0) as f32 /(x1-x0) as f32;
        let y: i32 = (y0 as f32 *(1.0-t) + y1 as f32 *t) as i32;
        // image.set(x, y, color);
        set_pixel(x, y, color, screen);
    }
}

fn main() {
    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("rust-sdl demo - video", "rust-sdl");

    let mut rng = rand::thread_rng();
    let screen = match sdl::video::set_video_mode(1024, 768, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };

    // let color = Color{r:233, g:233, b:233};

    // set_pixel(400, 300, &color, &screen);

    // draw_line(10, 10, 100, 100, &color, &screen);

    // draw_line(13, 20, 80, 40,  &color, &screen);
    // draw_line(20, 13, 40, 80,  &color, &screen);
    // draw_line(80, 40, 13, 20,  &color, &screen);

    let mut stars = Stars_3D::new(4000, 64, 20);

    let mut start = PreciseTime::now();

    'main : loop {
        'event : loop {
            match sdl::event::poll_event() {
                Event::Quit => break 'main,
                Event::None => break 'event,
                Event::Key(k, _, _, _)
                    if k == Key::Escape
                        => break 'main,
                _ => { }
            }
        }

        let end = PreciseTime::now();
        let delta = start.to(end);
        start = PreciseTime::now();

        println!("{} ms", delta.num_milliseconds());

        stars.update_and_render(&screen, delta.num_milliseconds() as f32 / 1000f32);
        screen.flip();

    }

    sdl::quit();
}
<commit_msg>format<commit_after>extern crate sdl;
extern crate rand;
extern crate time;

use rand::Rng;

use time::PreciseTime;

use sdl::video::{SurfaceFlag, VideoFlag, Surface};
use sdl::event::{Event, Key};

struct Color {
    r: u8,
    g: u8,
    b: u8
}

struct Stars_3D {
    speed: i32,
    spread: i32,
    stars_x: Vec<f32>,
    stars_y: Vec<f32>,
    stars_z: Vec<f32>
}

impl Stars_3D {
    pub fn new(num_stars: usize, _spread: i32, _speed: i32) -> Stars_3D {
        let mut obj = Stars_3D {
            spread: _spread,
            speed: _speed,
            stars_x: vec![0.0; num_stars],
            stars_y: vec![0.0; num_stars],
            stars_z: vec![0.0; num_stars] };

        for idx in 0..num_stars {
            obj.init_star(idx);
        }

        obj
    }

    fn init_star(&mut self, idx: usize) {
        let mut rng = rand::thread_rng();
        self.stars_x[idx] = (2 as f32) * (rng.next_f32() - 0.5) * (self.spread as f32);
        self.stars_y[idx] = (2 as f32) * (rng.next_f32() - 0.5) * (self.spread as f32);
        self.stars_z[idx] = (rng.next_f32() + 0.00001) * (self.spread as f32);
    }

    pub fn update_and_render(&mut self, screen: &Surface, delta: f32) {
        clear(screen);

        let color = Color{r:233, g:233, b:233};

		let halfWidth  = screen.get_width() as f32 / 2.0f32;
		let halfHeight = screen.get_height()as f32 / 2.0f32;
        for i in 0..self.stars_x.len() {
            self.stars_z[i] -= delta * self.speed as f32;

            if(self.stars_z[i] <= 0f32) {
                self.init_star(i);
            }

            let x = (self.stars_x[i]/self.stars_z[i] * halfWidth + halfWidth);
            let y = (self.stars_y[i]/self.stars_z[i] * halfHeight + halfHeight);

            if x < 0f32 || x >= screen.get_width() as f32 || y < 0f32 || y >= screen.get_height() as f32 {
                self.init_star(i);
            } else {
                set_pixel(x as i32, y as i32, &color, &screen);
            }
        }
    }
}

fn clear(screen: &Surface) {
    screen.fill_rect(Some(sdl::Rect {
                x: 0,
                y: 0,
                w: screen.get_width(),
                h: screen.get_height()
            }), sdl::video::Color::RGB(0,0,0));
}

fn set_pixel(_x: i32, _y:i32, color: &Color, screen: &Surface) {

    // println!("{}",screen.get_width());
    let x: usize = _x as usize * 4;
    let y: usize = _y as usize * 4;
    let idx_blue: usize = x + y * screen.get_width() as usize;
    let idx_green: usize = (x + y * screen.get_width() as usize) + 1;
    let idx_red: usize = (x + y * screen.get_width() as usize) + 2;
    let idx_alpha: usize = (x + y * screen.get_width() as usize) + 3;

    screen.with_lock(|pixels| {
        pixels[idx_blue] = color.b;
        pixels[idx_green] = color.g;
        pixels[idx_red] = color.r;
        pixels[idx_alpha] = 0;

        true
    });
}

fn draw_line(x0: i32, y0: i32, x1: i32, y1: i32, color: &Color, screen: &Surface) {
    for x in x0..x1 {
        // println!("{}", x);
        let t: f32 = (x-x0) as f32 /(x1-x0) as f32;
        let y: i32 = (y0 as f32 *(1.0-t) + y1 as f32 *t) as i32;
        // image.set(x, y, color);
        set_pixel(x, y, color, screen);
    }
}

fn main() {
    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("rust-sdl demo - video", "rust-sdl");

    let mut rng = rand::thread_rng();
    let screen = match sdl::video::set_video_mode(1024, 768, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };

    // let color = Color{r:233, g:233, b:233};

    // set_pixel(400, 300, &color, &screen);

    // draw_line(10, 10, 100, 100, &color, &screen);

    // draw_line(13, 20, 80, 40,  &color, &screen);
    // draw_line(20, 13, 40, 80,  &color, &screen);
    // draw_line(80, 40, 13, 20,  &color, &screen);

    let mut stars = Stars_3D::new(4000, 64, 20);

    let mut start = PreciseTime::now();

    'main : loop {
        'event : loop {
            match sdl::event::poll_event() {
                Event::Quit => break 'main,
                Event::None => break 'event,
                Event::Key(k, _, _, _)
                    if k == Key::Escape
                        => break 'main,
                _ => { }
            }
        }

        let end = PreciseTime::now();
        let delta = start.to(end);
        start = PreciseTime::now();

        println!("{} ms", delta.num_milliseconds());

        stars.update_and_render(&screen, delta.num_milliseconds() as f32 / 1000f32);
        screen.flip();

    }

    sdl::quit();
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
use rustc_serialize::json;
use std::io::prelude::*;
use std::fs;
use std::fs::metadata;
use std::fs::File;
use std::error::Error;
use std::path::Path;
use std::env;

#[derive(RustcDecodable, RustcEncodable)]
pub struct TransferParams {
    file_name: String,
    copy_to_path: String
}

fn main() {
    // Get the passed arguments
    let args: Vec<String> = env::args().collect();

    // check to make sure the number of arguments is correct,
    //  if there are not exactly one argument (one plus the program), exit the program.
    if args.len() != 2  {
        // print program usage
        println!("Usage: file_copy_tool <Root Folder Path>");

        // exit the program
        //std::process::exit(0);
    }

    let paths = fs::read_dir("./").unwrap();

    for path in paths {
        //println!("Name: {}", path.unwrap().path().display())
        let filename = path.unwrap().path().as_os_str();

        println!("{}", filename.to_str());
        //let attr = fs::metadata(path.unwrap().path().display()).unwrap();

        //if attr.is_dir() {
            //println!("{}, is a directory!", path.unwrap().path().display());
        //}
        println!("Name: {}", path.unwrap().path().display());
    }

    let startFolder = ".";
    copyFile(startFolder);

    /*
    let temppath = Path::new(&args[1]); //"testfile.json");
    let path = temppath.join("testfile.json");

    let display = path.display();

    //let path = Path::new("testfile.json");
    //let display = path.display();

    // matching is like error checking in rust.  This match tries to open a file and switches through based on
    //  what the result is (Err, Ok, etc.)
    let mut file =  match File::open(&path) {
        Err(why) => panic!("Couldn't open {}: {}", display, why.description()),
        Ok(file) => file
    };//try!(File::open("testfile.json"));

    // define a string for the file contents
    let mut file_contents = String::new();

    match file.read_to_string(&mut file_contents) {
        Err(why) => panic!("Coulding read {}: {}", display, why.description()),
        Ok(_) => print!("{} contains: \n{}", display, file_contents),
    };

    //try!(file.read_to_string(&mut fileContents));

    //println!("contents: {}", fileContents);

    let decoded: TransferParams = json::decode(&file_contents).unwrap();

    //println!("file_name: {}", decoded.file_name);
    //println!("Copy path: {}", decoded.copy_to_path);

    //println!("Trying to copy {} to {}", decoded.file_name, decoded.copy_to_path);

    match fs::copy(decoded.file_name, decoded.copy_to_path) {
        Err(why) => panic!("Couldn't copy the file {}: {}", display, why.description()),
        Ok(_) => println!("File copy complete!")
    };
    */
}

fn copyFile( folder_path: &str ) {

    let temppath = Path::new(&folder_path); //"testfile.json");
    let path = temppath.join("testfile.json");

    let display = path.display();

    // matching is like error checking in rust.  This match tries to open a file and switches through based on
    //  what the result is (Err, Ok, etc.)
    let mut file =  match File::open(&path) {
        Err(why) => panic!("Couldn't open {}: {}", display, why.description()),
        Ok(file) => file
    };//try!(File::open("testfile.json"));

    // define a string for the file contents
    let mut file_contents = String::new();

    match file.read_to_string(&mut file_contents) {
        Err(why) => panic!("Coulding read {}: {}", display, why.description()),
        Ok(_) => { }, // Do nothing // print!("{} contains: \n{}", display, file_contents),
    };

    let decoded: TransferParams = json::decode(&file_contents).unwrap();

    match fs::copy(decoded.file_name, decoded.copy_to_path) {
        Err(why) => panic!("Couldn't copy the file {}: {}", display, why.description()),
        Ok(_) => println!("File copy complete!")
    };
}
<commit_msg>I've decided to change the way the program works.  I don't want this app to traverse folders.<commit_after>extern crate rustc_serialize;
use rustc_serialize::json;
use std::io::prelude::*;
use std::fs;
use std::fs::metadata;
use std::fs::File;
use std::error::Error;
use std::path::Path;
use std::env;

#[derive(RustcDecodable, RustcEncodable)]
pub struct TransferParams {
    file_name: String,
    copy_to_path: String
}

fn main() {
    // Get the passed arguments
    let args: Vec<String> = env::args().collect();

    // check to make sure the number of arguments is correct,
    //  if there are not exactly one argument (one plus the program), exit the program.
    if args.len() != 2  {
        // print program usage
        println!("Usage: file_copy_tool <Copy Folder Path>");

        // exit the program
        std::process::exit(0);
    }

    println!("{}", args[1]);

    let test = args[1].clone();

    copyFile(&test);
}

fn copyFile( folder_path: &str ) {

    let temppath = Path::new(&folder_path); //"testfile.json");
    let path = temppath.join("testfile.json");

    let display = path.display();

    // matching is like error checking in rust.  This match tries to open a file and switches through based on
    //  what the result is (Err, Ok, etc.)
    let mut file =  match File::open(&path) {
        Err(why) => panic!("Couldn't open {}: {}", display, why.description()),
        Ok(file) => file
    };//try!(File::open("testfile.json"));

    // define a string for the file contents
    let mut file_contents = String::new();

    match file.read_to_string(&mut file_contents) {
        Err(why) => panic!("Coulding read {}: {}", display, why.description()),
        Ok(_) => { }, // Do nothing // print!("{} contains: \n{}", display, file_contents),
    };

    let decoded: TransferParams = json::decode(&file_contents).unwrap();

    match fs::copy(decoded.file_name, decoded.copy_to_path) {
        Err(why) => panic!("Couldn't copy the file {}: {}", display, why.description()),
        Ok(_) => println!("File copy complete!")
    };
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate rustc_serialize;
extern crate toml;

use std::collections::btree_map::*;
use std::env;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use docopt::Docopt;

const USAGE: &'static str = "
Usage:
    goto [<name>]
    goto --help

Configuration is stored in ~/.goto.toml
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_name: Option<String>,
}

fn config_path() -> io::Result<PathBuf> {
    match env::home_dir() {
        Some(home) => Ok(home.join(".goto.toml")),
        None => Err(io::Error::new(io::ErrorKind::Other, "unable to determine home directory")),
    }
}

fn read_config() -> io::Result<toml::Table> {
    let mut config_text = String::new();
    let mut file = try!(File::open(try!(config_path())));
    try!(file.read_to_string(&mut config_text));
    let mut parser = toml::Parser::new(&config_text);
    let config = match parser.parse() {
        Some(v) => v,
        None => {
            let mut msg = String::from("failed to parse TOML:");
            for err in &parser.errors {
                let linecol_lo = parser.to_linecol(err.lo);
                let linecol_hi = parser.to_linecol(err.hi);
                msg.push_str(&format!("\n\t{} at {}:{} to {}:{}",
                        err.desc,
                        linecol_lo.0 + 1,
                        linecol_lo.1 + 1,
                        linecol_hi.0 + 1,
                        linecol_hi.1 + 1));
            }
            return Err(io::Error::new(io::ErrorKind::Other, msg));
        }
    };

    Ok(config)
}

type PathMapping = BTreeMap<String, PathBuf>;

#[derive(Debug)]
struct Configuration {
    global: PathMapping,
    contexts: BTreeMap<PathBuf, PathMapping>,
}

fn parse_toml_as_path(t: toml::Value, cwd: Option<&Path>) -> Result<PathBuf, String> {
    if let toml::Value::String(s) = t {
        let path: PathBuf = if s.starts_with("~/") {
            env::home_dir().unwrap().join(&Path::new(&s[2..]))
        } else if s.starts_with("/") {
            PathBuf::from(s)
        } else if cwd.is_some() {
            cwd.unwrap().join(Path::new(&s))
        } else {
            return Err(format!("expected a path starting with \"/\" or \"~/\""));
        };
        Ok(path)
    } else {
        Err(format!("type error: expected a string, not {}", t.type_str()))
    }
}

fn process_config(config_toml: toml::Table) -> Result<Configuration, String> {
    let mut config = Configuration {
        global: PathMapping::new(),
        contexts: BTreeMap::new(),
    };

    for (k, v) in config_toml.into_iter() {
        if let toml::Value::Table(t) = v {
            if k == "global" {
                for (name, path) in t.into_iter() {
                    match parse_toml_as_path(path, None) {
                        Ok(path) => { config.global.insert(name, path); },
                        Err(msg) => { return Err(format!("error at *.{}: {}", name, msg)); },
                    }
                }
            } else {
                let context_path = match parse_toml_as_path(toml::Value::String(k), None) {
                    Ok(path) => path,
                    Err(msg) => { return Err(format!("error: {}", msg)); }
                };

                let mut context_map = PathMapping::new();

                for (name, path) in t.into_iter() {
                    let mapped_path: PathBuf = match parse_toml_as_path(path, Some(&context_path)) {
                        Ok(path) => path,
                        Err(msg) => {
                            return Err(format!("error at {:?}.{}: {}", context_path, name, msg));
                        }
                    };

                    context_map.insert(name, mapped_path);
                }

                config.contexts.insert(context_path, context_map);
            }
        } else {
            return Err(format!("type error at {}: expected a table, not {}", k, v.type_str()));
        }
    }

    Ok(config)
}

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

    let name = args.arg_name.unwrap_or("*".to_owned());

    let cwd = PathBuf::from(env::current_dir().unwrap_or_else(|e| {
        panic!("unable to get current working directory: {}", e);
    }));

    let config_toml = read_config().map_err(|e| {
        panic!("failed to read configuration ~/.goto.toml: {}", e);
    }).unwrap();

    let config = process_config(config_toml).map_err(|msg| {
        panic!("failed to parse configuration ~/.goto.toml: {}", msg);
    }).unwrap();

    let mut matched = false;
    let mut context_paths_by_len: Vec<&PathBuf> = config.contexts.keys().collect();
    context_paths_by_len.sort_by_key(|p| p.as_os_str().len());
    for context_path in context_paths_by_len.iter().rev() {
        if cwd.starts_with(context_path) {
            let map = config.contexts.get(*context_path).unwrap();
            if let Some(path) = map.get(&name) {
                println!("pushd {:?}", path);
                matched = true;
                break;
            }
        }
    }

    if !matched {
        if let Some(path) = config.global.get(&name) {
            println!("pushd {:?}", path);
            matched = true;
        }
    }

    if !matched {
        println!("echo not sure where to go");
    }
}
<commit_msg>print things correctly under eval context<commit_after>extern crate docopt;
extern crate rustc_serialize;
extern crate toml;

use std::collections::btree_map::*;
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use docopt::Docopt;

const USAGE: &'static str = "
Usage:
    goto [<name>]
    goto (--help | --version)

Configuration is stored in ~/.goto.toml

goto is meant to be used as the argument to your shell's 'eval' builtin, like so:
    function goto() {
        eval $(/usr/local/bin/goto $*)
    }
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_name: Option<String>,
}

fn config_path() -> io::Result<PathBuf> {
    match env::home_dir() {
        Some(home) => Ok(home.join(".goto.toml")),
        None => Err(io::Error::new(io::ErrorKind::Other, "unable to determine home directory")),
    }
}

fn read_config() -> io::Result<toml::Table> {
    let mut config_text = String::new();
    let mut file = try!(File::open(try!(config_path())));
    try!(file.read_to_string(&mut config_text));
    let mut parser = toml::Parser::new(&config_text);
    let config = match parser.parse() {
        Some(v) => v,
        None => {
            let mut msg = String::from("failed to parse TOML:");
            for err in &parser.errors {
                let linecol_lo = parser.to_linecol(err.lo);
                let linecol_hi = parser.to_linecol(err.hi);
                msg.push_str(&format!("\n\t{} at {}:{} to {}:{}",
                        err.desc,
                        linecol_lo.0 + 1,
                        linecol_lo.1 + 1,
                        linecol_hi.0 + 1,
                        linecol_hi.1 + 1));
            }
            return Err(io::Error::new(io::ErrorKind::Other, msg));
        }
    };

    Ok(config)
}

type PathMapping = BTreeMap<String, PathBuf>;

#[derive(Debug)]
struct Configuration {
    global: PathMapping,
    contexts: BTreeMap<PathBuf, PathMapping>,
}

fn parse_toml_as_path(t: toml::Value, cwd: Option<&Path>) -> Result<PathBuf, String> {
    if let toml::Value::String(s) = t {
        let path: PathBuf = if s.starts_with("~/") {
            env::home_dir().unwrap().join(&Path::new(&s[2..]))
        } else if s.starts_with("/") {
            PathBuf::from(s)
        } else if cwd.is_some() {
            cwd.unwrap().join(Path::new(&s))
        } else {
            return Err(format!("expected a path starting with \"/\" or \"~/\""));
        };
        Ok(path)
    } else {
        Err(format!("type error: expected a string, not {}", t.type_str()))
    }
}

fn process_config(config_toml: toml::Table) -> Result<Configuration, String> {
    let mut config = Configuration {
        global: PathMapping::new(),
        contexts: BTreeMap::new(),
    };

    for (k, v) in config_toml.into_iter() {
        if let toml::Value::Table(t) = v {
            if k == "global" {
                for (name, path) in t.into_iter() {
                    match parse_toml_as_path(path, None) {
                        Ok(path) => { config.global.insert(name, path); },
                        Err(msg) => { return Err(format!("error at global.{}: {}", name, msg)); },
                    }
                }
            } else {
                let context_path = match parse_toml_as_path(toml::Value::String(k), None) {
                    Ok(path) => path,
                    Err(msg) => { return Err(format!("error: {}", msg)); }
                };

                let mut context_map = PathMapping::new();

                for (name, path) in t.into_iter() {
                    let mapped_path: PathBuf = match parse_toml_as_path(path, Some(&context_path)) {
                        Ok(path) => path,
                        Err(msg) => {
                            return Err(format!("error at {:?}.{}: {}", context_path, name, msg));
                        }
                    };

                    context_map.insert(name, mapped_path);
                }

                config.contexts.insert(context_path, context_map);
            }
        } else {
            return Err(format!("type error at {}: expected a table, not {}", k, v.type_str()));
        }
    }

    Ok(config)
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| {
                                d.version(Some(format!("goto {}", env!("CARGO_PKG_VERSION"))))
                                 .decode()
                            })
                            .unwrap_or_else(|e| {
                                writeln!(io::stderr(), "{}", e).unwrap();
                                ::std::process::exit(if e.fatal() { 1 } else { 0 });
                            });

    let name = args.arg_name.unwrap_or("*".to_owned());

    let cwd = PathBuf::from(env::current_dir().unwrap_or_else(|e| {
        panic!("unable to get current working directory: {}", e);
    }));

    let config_toml = read_config().map_err(|e| {
        panic!("failed to read configuration ~/.goto.toml: {}", e);
    }).unwrap();

    let config = process_config(config_toml).map_err(|msg| {
        panic!("invalid configuration in ~/.goto.toml: {}", msg);
    }).unwrap();

    let mut matched = false;
    let mut context_paths_by_len: Vec<&PathBuf> = config.contexts.keys().collect();
    context_paths_by_len.sort_by_key(|p| p.as_os_str().len());
    for context_path in context_paths_by_len.iter().rev() {
        if cwd.starts_with(context_path) {
            let map = config.contexts.get(*context_path).unwrap();
            if let Some(path) = map.get(&name) {
                println!("pushd {:?}", path);
                matched = true;
                break;
            }
        }
    }

    if !matched {
        if let Some(path) = config.global.get(&name) {
            println!("pushd {:?}", path);
            matched = true;
        }
    }

    if !matched {
        writeln!(io::stderr(), "not sure where to go").unwrap();
    }
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

extern crate cgmath;
extern crate png;

use std::fs::File;

use cgmath::prelude::*;
use cgmath::vec3;
use png::HasParameters;

use camera::Camera;
use light::Light;
use material::Material;
use math::*;
use primitive::Primitive;
use raytracer::Raytracer;
use scene::Scene;
use texture::checkerboard;

mod camera;
mod color;
mod intersection;
mod light;
mod material;
#[macro_use] mod math;
mod primitive;
mod ray;
mod raytracer;
mod scene;
mod texture;

fn main() {
    let mut scene = Scene::new(vec3(0.05, 0.05, 0.10).into());

    scene.add_primitive(Primitive::plane(Material::solid(checkerboard(color!(1.0), color!(0.0), (0.5, 0.5)), 1.0),
                                         vec3(0.0, -1.0, 0.0),
                                         Vector::unit_y()));
    scene.add_primitive(Primitive::sphere(Material::solid(color!(1.0, 0.0, 0.0), 1.0),
                                          vec3(0.0, 0.0, 2.0),
                                          1.0));

    scene.add_light(Light::point(vec3(1.5, 1.5, 1.5).into(), vec3(0.0, 1.0, 0.5)));

    let raytracer = Raytracer {
        scene: scene,
        camera: Camera::new(Point::zero(), Vector::unit_z(), 90.0f32.to_radians()),
    };

    let (w, h) = (512, 512);
    let mut output_data = Vec::with_capacity(w * h);
    for y in 0 .. h {
        for x in 0 .. w {
            let screen_coords = (x as f32 / w as f32, y as f32 / h as f32);
            let ray = raytracer.camera.primary_ray(screen_coords);
            let result = raytracer.trace(ray, 1);

            let (r, g, b) = result.color.as_bytes();
            output_data.push(r);
            output_data.push(g);
            output_data.push(b);
        }
    }

    // TODO: add command line options to configure this.
    let mut output = File::create("output.png").expect("Couldn't create output file.");

    let mut encoder = png::Encoder::new(output, w as u32, h as u32);
    encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
    encoder.write_header()
        .unwrap()
        .write_image_data(&output_data)
        .unwrap();
}
<commit_msg>Create the example scene in a separate function<commit_after>#![feature(conservative_impl_trait)]

extern crate cgmath;
extern crate png;

use std::fs::File;

use cgmath::prelude::*;
use cgmath::vec3;
use png::HasParameters;

use camera::Camera;
use light::Light;
use material::Material;
use math::*;
use primitive::Primitive;
use raytracer::Raytracer;
use scene::Scene;
use texture::checkerboard;

mod camera;
mod color;
mod intersection;
mod light;
mod material;
#[macro_use] mod math;
mod primitive;
mod ray;
mod raytracer;
mod scene;
mod texture;

fn main() {
    let raytracer = Raytracer {
        scene: example_scene(),
        camera: Camera::new(Point::zero(), Vector::unit_z(), 90.0f32.to_radians()),
    };

    let (w, h) = (512, 512);
    let mut output_data = Vec::with_capacity(w * h);
    for y in 0 .. h {
        for x in 0 .. w {
            let screen_coords = (x as f32 / w as f32, y as f32 / h as f32);
            let ray = raytracer.camera.primary_ray(screen_coords);
            let result = raytracer.trace(ray, 1);

            let (r, g, b) = result.color.as_bytes();
            output_data.push(r);
            output_data.push(g);
            output_data.push(b);
        }
    }

    // TODO: add command line options to configure this.
    let mut output = File::create("output.png").expect("Couldn't create output file.");

    let mut encoder = png::Encoder::new(output, w as u32, h as u32);
    encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
    encoder.write_header()
        .unwrap()
        .write_image_data(&output_data)
        .unwrap();
}

fn example_scene() -> Scene {
    let mut scene = Scene::new(vec3(0.05, 0.05, 0.10).into());

    scene.add_primitive(
        Primitive::plane(
            Material::solid(
                checkerboard(color!(1.0), color!(0.0), (0.5, 0.5)),
                1.0,
            ),
            vec3(0.0, -1.0, 0.0),
            Vector::unit_y(),
        )
    );

    scene.add_primitive(
        Primitive::sphere(
            Material::solid(color!(1.0, 0.0, 0.0), 1.0),
            vec3(0.0, 0.0, 2.0),
            1.0,
        )
    );

    scene.add_light(
        Light::point(vec3(1.5, 1.5, 1.5).into(), vec3(0.0, 1.0, 0.5)),
    );

    scene
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![feature(exit_status)]
#![feature(fs)]
#![feature(path)]
#![feature(process)]
#![feature(tempdir)]

#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::fs::{PathExt, TempDir, self};
use std::path::Path;
use std::process::{Command, Stdio};

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

    let args: Vec<_> = env::args().skip(1).collect();

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| *arg != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(&args);

        // Inherit stdio
        cmd.stderr(Stdio::inherit());
        cmd.stdin(Stdio::inherit());
        cmd.stdout(Stdio::inherit());

        info!("cwd: . | cmd: `{:?}`", cmd);
        match cmd.output() {
            Err(e) => panic!("`{:?}` failed: {}", cmd, e),
            Ok(output) =>  {
                env::set_exit_status(output.status.code().unwrap());

                return;
            },
        }
    }

    // Before `--`: arguments for the compiler
    // After `--`: arguments for the executable
    let mut splitted_args = args.split(|arg| *arg == "--");
    let compiler_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if compiler_args.iter().any(|arg| *arg == "--out-dir") {
        panic!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = env::current_dir().ok().expect("Couldn't fetch the current directory");
    for arg in compiler_args.iter().filter(|arg| **arg != "--run") {
        let path = Path::new(arg);

        if path.exists() && path.is_relative() {
            cmd.arg(&current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }

    // Create temporary directory
    let temp_dir = TempDir::new("rust").unwrap();
    let temp_dir_path = temp_dir.path();
    let temp_dir_display = temp_dir_path.display();

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Compile
    info!("cwd: {} | cmd: `{:?}`", temp_dir_display, cmd);
    match cmd.current_dir(temp_dir_path).output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {
            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::read_dir(temp_dir_path) {
        Err(e) => panic!("`ls {}` failed: {}", temp_dir_display, e),
        Ok(mut paths) => match paths.next() {
            Some(Ok(entry)) => Command::new(&entry.path()),
            _ => panic!("no binary found in {}", temp_dir_display),
        }
    };

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Execute
    info!("cwd: . | cmd: `{:?}`", cmd);
    match cmd.output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {

            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }
}
<commit_msg>fix: update to rust nightly<commit_after>#![deny(warnings)]
#![feature(exit_status)]
#![feature(fs)]
#![feature(path)]
#![feature(tempdir)]

#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::fs::{PathExt, TempDir, self};
use std::path::Path;
use std::process::{Command, Stdio};

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

    let args: Vec<_> = env::args().skip(1).collect();

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| *arg != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(&args);

        // Inherit stdio
        cmd.stderr(Stdio::inherit());
        cmd.stdin(Stdio::inherit());
        cmd.stdout(Stdio::inherit());

        info!("cwd: . | cmd: `{:?}`", cmd);
        match cmd.output() {
            Err(e) => panic!("`{:?}` failed: {}", cmd, e),
            Ok(output) =>  {
                env::set_exit_status(output.status.code().unwrap());

                return;
            },
        }
    }

    // Before `--`: arguments for the compiler
    // After `--`: arguments for the executable
    let mut splitted_args = args.split(|arg| *arg == "--");
    let compiler_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if compiler_args.iter().any(|arg| *arg == "--out-dir") {
        panic!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    // Make all paths absolute, filter out the `--run` flag
    let current_dir = env::current_dir().ok().expect("Couldn't fetch the current directory");
    for arg in compiler_args.iter().filter(|arg| **arg != "--run") {
        let path = Path::new(arg);

        if path.exists() && path.is_relative() {
            cmd.arg(&current_dir.join(path));
        } else {
            cmd.arg(arg);
        }
    }

    // Create temporary directory
    let temp_dir = TempDir::new("rust").unwrap();
    let temp_dir_path = temp_dir.path();
    let temp_dir_display = temp_dir_path.display();

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Compile
    info!("cwd: {} | cmd: `{:?}`", temp_dir_display, cmd);
    match cmd.current_dir(temp_dir_path).output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {
            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::read_dir(temp_dir_path) {
        Err(e) => panic!("`ls {}` failed: {}", temp_dir_display, e),
        Ok(mut paths) => match paths.next() {
            Some(Ok(entry)) => Command::new(&entry.path()),
            _ => panic!("no binary found in {}", temp_dir_display),
        }
    };

    // Build the executable command
    match executable_args {
        None => {},
        Some(args) => {
            cmd.args(args);
        },
    }

    // Inherit stdio
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::inherit());
    cmd.stdout(Stdio::inherit());

    // Execute
    info!("cwd: . | cmd: `{:?}`", cmd);
    match cmd.output() {
        Err(e) => panic!("`{:?}` failed: {}", cmd, e),
        Ok(output) => if !output.status.success() {

            env::set_exit_status(output.status.code().unwrap());

            return;
        },
    }
}
<|endoftext|>


<commit_before>extern crate space_colonization;
extern crate nalgebra as na;
extern crate kiss3d;
extern crate rand;
extern crate num;
extern crate clap;

use kiss3d::window::Window;
use na::{Pnt2, Pnt3, Vec2, Vec3, FloatPnt, FloatVec};
use rand::{Rng, Closed01};
use num::Zero;
use clap::{Arg, App};
use std::str::FromStr;
use space_colonization::SpaceColonization;

fn random_closed01<R: Rng>(rng: &mut R) -> f32 {
    rng.gen::<Closed01<f32>>().0
}

fn random_coord<R: Rng>(rng: &mut R) -> f32 {
    2.0 * random_closed01(rng) - 1.0
}

trait MyPoint {
    fn into_pnt3(self) -> Pnt3<f32>;
    fn random<R: Rng>(rng: &mut R) -> Self;
}

impl MyPoint for Pnt3<f32> {
    fn into_pnt3(self) -> Pnt3<f32> {
        self
    }

    fn random<R: Rng>(rng: &mut R) -> Pnt3<f32> {
        Pnt3::new(random_coord(rng), random_coord(rng), random_coord(rng))
    }
}

impl MyPoint for Pnt2<f32> {
    fn into_pnt3(self) -> Pnt3<f32> {
        Pnt3::new(self.x, self.y, 3.0)
    }

    fn random<R: Rng>(rng: &mut R) -> Pnt2<f32> {
        Pnt2::new(random_coord(rng), random_coord(rng))
    }
}

#[derive(Debug)]
struct Config {
    n_attraction_points: usize,
    n_roots: usize,
    influence_radius: f32,
    move_distance: f32,
    kill_distance: f32,
    use_3d: bool,
    max_iter: Option<usize>,
}

impl Config {
    #[allow(dead_code)]
    fn config1() -> Config {
        Config {
            n_attraction_points: 10_000,
            n_roots: 5,
            influence_radius: 0.44,
            kill_distance: 0.22,
            move_distance: 0.02,
            use_3d: true,
            max_iter: None,
        }
    }

    #[allow(dead_code)]
    fn config2() -> Config {
        Config {
            n_attraction_points: 10_000,
            n_roots: 5,
            influence_radius: 0.1,
            kill_distance: 0.07,
            move_distance: 0.01,
            use_3d: false,
            max_iter: None,
        }
    }

    fn from_cmd() -> Config {
        let matches = App::new("space-colonization")
                          .arg(Arg::with_name("NUM_POINTS")
                                   .long("num-points")
                                   .help("Number of attraction points (default: 1000)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("NUM_ROOTS")
                                   .long("num-roots")
                                   .help("Number of root nodes (default: 1)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("IR")
                                   .long("radius")
                                   .help("Influence radius (default: 0.25)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("KD")
                                   .long("kill-distance")
                                   .help("Kill distance (default: 0.1)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("MD")
                                   .long("move-distance")
                                   .help("Kill distance (default: 0.05)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("MAX_ITER")
                                   .long("max-iter")
                                   .help("Maximum iterations (default: infinite)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("USE_3D")
                                   .long("use-3d")
                                   .help("Use 3d mode"))
                          .get_matches();

        Config {
            n_attraction_points: usize::from_str(matches.value_of("NUM_POINTS").unwrap_or("1000"))
                                     .unwrap(),
            n_roots: usize::from_str(matches.value_of("NUM_ROOTS").unwrap_or("1")).unwrap(),
            influence_radius: f32::from_str(matches.value_of("IR").unwrap_or("0.25")).unwrap(),
            kill_distance: f32::from_str(matches.value_of("KD").unwrap_or("0.1")).unwrap(),
            move_distance: f32::from_str(matches.value_of("MD").unwrap_or("0.05")).unwrap(),
            use_3d: matches.is_present("USE_3D"),
            max_iter: usize::from_str(matches.value_of("MAX_ITER").unwrap_or("INVALID")).ok(),
        }
    }
}

fn run<T, F>(config: &Config)
    where T: MyPoint + FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    let mut rng = rand::thread_rng();

    let mut sc: SpaceColonization<T, F> = SpaceColonization::new(10, 1);
    for _ in 0..config.n_roots {
        sc.add_root_node(<T as MyPoint>::random(&mut rng));
    }

    for _ in 0..config.n_attraction_points {
        sc.add_attractor(<T as MyPoint>::random(&mut rng));
    }

    let mut window = Window::new("Space Colonization");
    let white = Pnt3::new(1.0, 1.0, 1.0);
    let red = Pnt3::new(1.0, 0.0, 0.0);

    let mut i = 0;

    while window.render() {
        i += 1;

        if let Some(m) = config.max_iter {
            if i > m {
                break;
            }
        }

        for &pt in sc.attractors() {
            window.draw_point(&pt.into_pnt3(), &white);
        }

        sc.iter_segments(&mut |&a, &b| {
            window.draw_line(&a.into_pnt3(), &b.into_pnt3(), &red);
        });

        let new_nodes = sc.iterate(config.influence_radius,
                                   config.move_distance,
                                   config.kill_distance,
                                   None);

        println!("Iteration: {}. New nodes: {}", i, new_nodes);
        if new_nodes == 0 {
            break;
        }
    }
}

fn main() {
    let config = Config::from_cmd();

    println!("{:?}", config);

    if config.use_3d {
        run::<Pnt3<f32>, Vec3<f32>>(&config);
    } else {
        run::<Pnt2<f32>, Vec2<f32>>(&config);
    }
}
<commit_msg>Add --save-every argument to make a screenshot every n iterations<commit_after>extern crate space_colonization;
extern crate nalgebra as na;
extern crate kiss3d;
extern crate rand;
extern crate num;
extern crate clap;

use kiss3d::window::Window;
use na::{Pnt2, Pnt3, Vec2, Vec3, FloatPnt, FloatVec};
use rand::{Rng, Closed01};
use num::Zero;
use clap::{Arg, App};
use std::str::FromStr;
use space_colonization::SpaceColonization;

fn random_closed01<R: Rng>(rng: &mut R) -> f32 {
    rng.gen::<Closed01<f32>>().0
}

fn random_coord<R: Rng>(rng: &mut R) -> f32 {
    2.0 * random_closed01(rng) - 1.0
}

trait MyPoint {
    fn into_pnt3(self) -> Pnt3<f32>;
    fn random<R: Rng>(rng: &mut R) -> Self;
}

impl MyPoint for Pnt3<f32> {
    fn into_pnt3(self) -> Pnt3<f32> {
        self
    }

    fn random<R: Rng>(rng: &mut R) -> Pnt3<f32> {
        Pnt3::new(random_coord(rng), random_coord(rng), random_coord(rng))
    }
}

impl MyPoint for Pnt2<f32> {
    fn into_pnt3(self) -> Pnt3<f32> {
        Pnt3::new(self.x, self.y, 3.0)
    }

    fn random<R: Rng>(rng: &mut R) -> Pnt2<f32> {
        Pnt2::new(random_coord(rng), random_coord(rng))
    }
}

#[derive(Debug)]
struct Config {
    n_attraction_points: usize,
    n_roots: usize,
    influence_radius: f32,
    move_distance: f32,
    kill_distance: f32,
    use_3d: bool,
    max_iter: Option<usize>,
    save_every: Option<usize>,
}

impl Config {
    #[allow(dead_code)]
    fn config1() -> Config {
        Config {
            n_attraction_points: 10_000,
            n_roots: 5,
            influence_radius: 0.44,
            kill_distance: 0.22,
            move_distance: 0.02,
            use_3d: true,
            max_iter: None,
            save_every: None,
        }
    }

    #[allow(dead_code)]
    fn config2() -> Config {
        Config {
            n_attraction_points: 10_000,
            n_roots: 5,
            influence_radius: 0.1,
            kill_distance: 0.07,
            move_distance: 0.01,
            use_3d: false,
            max_iter: None,
            save_every: None,
        }
    }

    fn from_cmd() -> Config {
        let matches = App::new("space-colonization")
                          .arg(Arg::with_name("NUM_POINTS")
                                   .long("num-points")
                                   .help("Number of attraction points (default: 1000)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("NUM_ROOTS")
                                   .long("num-roots")
                                   .help("Number of root nodes (default: 1)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("IR")
                                   .long("radius")
                                   .help("Influence radius (default: 0.25)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("KD")
                                   .long("kill-distance")
                                   .help("Kill distance (default: 0.1)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("MD")
                                   .long("move-distance")
                                   .help("Kill distance (default: 0.05)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("MAX_ITER")
                                   .long("max-iter")
                                   .help("Maximum iterations (default: infinite)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("SAVE_EVERY")
                                   .long("save-every")
                                   .help("Save a picture every n iterations (default: none)")
                                   .takes_value(true)
                                   .required(false))
                          .arg(Arg::with_name("USE_3D")
                                   .long("use-3d")
                                   .help("Use 3d mode"))
                          .get_matches();

        Config {
            n_attraction_points: usize::from_str(matches.value_of("NUM_POINTS").unwrap_or("1000"))
                                     .unwrap(),
            n_roots: usize::from_str(matches.value_of("NUM_ROOTS").unwrap_or("1")).unwrap(),
            influence_radius: f32::from_str(matches.value_of("IR").unwrap_or("0.25")).unwrap(),
            kill_distance: f32::from_str(matches.value_of("KD").unwrap_or("0.1")).unwrap(),
            move_distance: f32::from_str(matches.value_of("MD").unwrap_or("0.05")).unwrap(),
            use_3d: matches.is_present("USE_3D"),
            max_iter: usize::from_str(matches.value_of("MAX_ITER").unwrap_or("INVALID")).ok(),
            save_every: usize::from_str(matches.value_of("SAVE_EVERY").unwrap_or("INVALID")).ok(),
        }
    }
}

fn run<T, F>(config: &Config)
    where T: MyPoint + FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    let mut rng = rand::thread_rng();

    let mut sc: SpaceColonization<T, F> = SpaceColonization::new(10, 1);
    for _ in 0..config.n_roots {
        sc.add_root_node(<T as MyPoint>::random(&mut rng));
    }

    for _ in 0..config.n_attraction_points {
        sc.add_attractor(<T as MyPoint>::random(&mut rng));
    }

    let mut window = Window::new("Space Colonization");
    let white = Pnt3::new(1.0, 1.0, 1.0);
    let red = Pnt3::new(1.0, 0.0, 0.0);

    let mut i = 0;

    while window.render() {
        if let Some(n) = config.save_every {
            // save previous iteration of window.render()
            if i > 0 && (i - 1) % n == 0 {
                let img = window.snap_image();
                let filename = format!("out_{}.png", i - 1);
                let _ = img.save(&filename).unwrap();
            }
        }
        if let Some(m) = config.max_iter {
            if i > m {
                break;
            }
        }

        for &pt in sc.attractors() {
            window.draw_point(&pt.into_pnt3(), &white);
        }

        sc.iter_segments(&mut |&a, &b| {
            window.draw_line(&a.into_pnt3(), &b.into_pnt3(), &red);
        });

        let new_nodes = sc.iterate(config.influence_radius,
                                   config.move_distance,
                                   config.kill_distance,
                                   None);

        println!("Iteration: {}. New nodes: {}", i, new_nodes);

        // if new_nodes == 0 {
        // break;
        // }
        //

        i += 1;
    }
}

fn main() {
    let config = Config::from_cmd();

    println!("{:?}", config);

    if config.use_3d {
        run::<Pnt3<f32>, Vec3<f32>>(&config);
    } else {
        run::<Pnt2<f32>, Vec2<f32>>(&config);
    }
}
<|endoftext|>