<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always neccesary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! *It is not recommended to use the core library*. The stable
//! functionality of libcore is reexported from the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time; only the interface exposed through libstd is
//! intended to be stable.
//!
//! # How to use the core library
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `fmt::Arguments`, a `&str`, and a `u32`. These three arguments dictate
//!   the panic message, the file at which panic was invoked, and the line.
//!   It is up to consumers of this core library to define this panic
//!   function; it is only required to never return.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "core"]
#![unstable(feature = "core",
            reason = "the libcore library has not yet been scrutinized for \
                      stabilization in terms of structure and naming",
            issue = "27701")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]

#![no_core]
#![deny(missing_docs)]

#![feature(allow_internal_unstable)]
#![feature(associated_type_defaults)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(reflect)]
#![feature(rustc_attrs)]
#![feature(unwind_attributes)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

#[macro_use]
mod macros;

#[macro_use]
mod cmp_macros;

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod nonzero;
pub mod ptr;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

#[cfg(stage0)]
#[path = "simd_old.rs"]
pub mod simd;
#[cfg(not(stage0))]
pub mod simd;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;

// note: does not need to be public
mod tuple;
<commit_msg>Auto merge of #29906 - ranma42:doc-typo, r=steveklabnik<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! *It is not recommended to use the core library*. The stable
//! functionality of libcore is reexported from the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time; only the interface exposed through libstd is
//! intended to be stable.
//!
//! # How to use the core library
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `fmt::Arguments`, a `&str`, and a `u32`. These three arguments dictate
//!   the panic message, the file at which panic was invoked, and the line.
//!   It is up to consumers of this core library to define this panic
//!   function; it is only required to never return.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "core"]
#![unstable(feature = "core",
            reason = "the libcore library has not yet been scrutinized for \
                      stabilization in terms of structure and naming",
            issue = "27701")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]

#![no_core]
#![deny(missing_docs)]

#![feature(allow_internal_unstable)]
#![feature(associated_type_defaults)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(reflect)]
#![feature(rustc_attrs)]
#![feature(unwind_attributes)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

#[macro_use]
mod macros;

#[macro_use]
mod cmp_macros;

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod nonzero;
pub mod ptr;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

#[cfg(stage0)]
#[path = "simd_old.rs"]
pub mod simd;
#[cfg(not(stage0))]
pub mod simd;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;

// note: does not need to be public
mod tuple;
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust core library
//!
//! This library is meant to represent the core functionality of rust that is
//! maximally portable to other platforms. To that extent, this library has no
//! knowledge of things like allocation, threads, I/O, etc. This library is
//! built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these funcitons. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by `librlibc` which is distributed with the standard rust
//!   distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
//!   the failure message, the file at which failure was invoked, and the line.
//!   It is up to consumers of this core library to define this failure
//!   function; it is only required to never return.
//!
//! Currently, it is *not* recommended to use the core library. The stable
//! functionality of libcore is exported directly into the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time, only the interface exposed through libstd is
//! intended to be stable.

#![crate_id = "core#0.11.0-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes, phase)]
#![deny(missing_doc)]

#[cfg(test)] extern crate realcore = "core";
#[cfg(test)] extern crate libc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate realstd = "std";

#[cfg(test)] pub use cmp = realcore::cmp;
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use ty = realcore::ty;

mod macros;

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

#[cfg(not(test))] pub mod kinds;
#[cfg(not(test))] pub mod ops;
#[cfg(not(test))] pub mod ty;
#[cfg(not(test))] pub mod cmp;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
pub mod any;
pub mod atomics;
pub mod bool;
pub mod cell;
pub mod char;
pub mod failure;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod fmt;

// FIXME: this module should not exist. Once owned allocations are no longer a
//        language type, this module can move outside to the owned allocation
//        crate.
mod should_not_exist;

mod core {
    pub use failure;
}

mod std {
    pub use clone;
    pub use cmp;
    pub use kinds;
    pub use option;
    pub use fmt;

    #[cfg(test)] pub use realstd::rt;     // needed for fail!()
    // #[cfg(test)] pub use realstd::option; // needed for fail!()
    // #[cfg(test)] pub use realstd::fmt;    // needed for fail!()
    #[cfg(test)] pub use realstd::os;     // needed for tests
    #[cfg(test)] pub use realstd::slice;  // needed for tests
    #[cfg(test)] pub use realstd::vec;    // needed for vec![]
}
<commit_msg>Fix typo in libcore<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust core library
//!
//! This library is meant to represent the core functionality of rust that is
//! maximally portable to other platforms. To that extent, this library has no
//! knowledge of things like allocation, threads, I/O, etc. This library is
//! built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by `librlibc` which is distributed with the standard rust
//!   distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
//!   the failure message, the file at which failure was invoked, and the line.
//!   It is up to consumers of this core library to define this failure
//!   function; it is only required to never return.
//!
//! Currently, it is *not* recommended to use the core library. The stable
//! functionality of libcore is exported directly into the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time, only the interface exposed through libstd is
//! intended to be stable.

#![crate_id = "core#0.11.0-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes, phase)]
#![deny(missing_doc)]

#[cfg(test)] extern crate realcore = "core";
#[cfg(test)] extern crate libc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate realstd = "std";

#[cfg(test)] pub use cmp = realcore::cmp;
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use ty = realcore::ty;

mod macros;

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

#[cfg(not(test))] pub mod kinds;
#[cfg(not(test))] pub mod ops;
#[cfg(not(test))] pub mod ty;
#[cfg(not(test))] pub mod cmp;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
pub mod any;
pub mod atomics;
pub mod bool;
pub mod cell;
pub mod char;
pub mod failure;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod fmt;

// FIXME: this module should not exist. Once owned allocations are no longer a
//        language type, this module can move outside to the owned allocation
//        crate.
mod should_not_exist;

mod core {
    pub use failure;
}

mod std {
    pub use clone;
    pub use cmp;
    pub use kinds;
    pub use option;
    pub use fmt;

    #[cfg(test)] pub use realstd::rt;     // needed for fail!()
    // #[cfg(test)] pub use realstd::option; // needed for fail!()
    // #[cfg(test)] pub use realstd::fmt;    // needed for fail!()
    #[cfg(test)] pub use realstd::os;     // needed for tests
    #[cfg(test)] pub use realstd::slice;  // needed for tests
    #[cfg(test)] pub use realstd::vec;    // needed for vec![]
}
<|endoftext|>


<commit_before>//! Module converting command-line arguments into test configuration.

use getopts;
use std::env;
use std::path::PathBuf;

use super::helpers::isatty;
use super::options::{ColorConfig, Options, OutputFormat, RunIgnored};
use super::time::TestTimeOptions;

#[derive(Debug)]
pub struct TestOpts {
    pub list: bool,
    pub filter: Option<String>,
    pub filter_exact: bool,
    pub force_run_in_process: bool,
    pub exclude_should_panic: bool,
    pub run_ignored: RunIgnored,
    pub run_tests: bool,
    pub bench_benchmarks: bool,
    pub logfile: Option<PathBuf>,
    pub nocapture: bool,
    pub color: ColorConfig,
    pub format: OutputFormat,
    pub test_threads: Option<usize>,
    pub skip: Vec<String>,
    pub time_options: Option<TestTimeOptions>,
    pub options: Options,
}

impl TestOpts {
    pub fn use_color(&self) -> bool {
        match self.color {
            ColorConfig::AutoColor => !self.nocapture && isatty::stdout_isatty(),
            ColorConfig::AlwaysColor => true,
            ColorConfig::NeverColor => false,
        }
    }
}

/// Result of parsing the options.
pub type OptRes = Result<TestOpts, String>;
/// Result of parsing the option part.
type OptPartRes<T> = Result<T, String>;

fn optgroups() -> getopts::Options {
    let mut opts = getopts::Options::new();
    opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
        .optflag("", "ignored", "Run only ignored tests")
        .optflag("", "force-run-in-process", "Forces tests to run in-process when panic=abort")
        .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
        .optflag("", "test", "Run tests and not benchmarks")
        .optflag("", "bench", "Run benchmarks instead of tests")
        .optflag("", "list", "List all tests and benchmarks")
        .optflag("h", "help", "Display this message (longer with --help)")
        .optopt(
            "",
            "logfile",
            "Write logs to the specified file instead \
             of stdout",
            "PATH",
        )
        .optflag(
            "",
            "nocapture",
            "don't capture stdout/stderr of each \
             task, allow printing directly",
        )
        .optopt(
            "",
            "test-threads",
            "Number of threads used for running tests \
             in parallel",
            "n_threads",
        )
        .optmulti(
            "",
            "skip",
            "Skip tests whose names contain FILTER (this flag can \
             be used multiple times)",
            "FILTER",
        )
        .optflag(
            "q",
            "quiet",
            "Display one character per test instead of one line. \
             Alias to --format=terse",
        )
        .optflag("", "exact", "Exactly match filters rather than by substring")
        .optopt(
            "",
            "color",
            "Configure coloring of output:
            auto   = colorize if stdout is a tty and tests are run on serially (default);
            always = always colorize output;
            never  = never colorize output;",
            "auto|always|never",
        )
        .optopt(
            "",
            "format",
            "Configure formatting of output:
            pretty = Print verbose output;
            terse  = Display one character per test;
            json   = Output a json document",
            "pretty|terse|json",
        )
        .optflag("", "show-output", "Show captured stdout of successful tests")
        .optopt(
            "Z",
            "",
            "Enable nightly-only flags:
            unstable-options = Allow use of experimental features",
            "unstable-options",
        )
        .optflagopt(
            "",
            "report-time",
            "Show execution time of each test. Awailable values:
            plain   = do not colorize the execution time (default);
            colored = colorize output according to the `color` parameter value;

            Threshold values for colorized output can be configured via
            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
            `RUST_TEST_TIME_DOCTEST` environment variables.

            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.

            Not available for --format=terse",
            "plain|colored",
        )
        .optflag(
            "",
            "ensure-time",
            "Treat excess of the test execution time limit as error.

            Threshold values for this option can be configured via
            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
            `RUST_TEST_TIME_DOCTEST` environment variables.

            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.

            `CRITICAL_TIME` here means the limit that should not be exceeded by test.
            ",
        );
    opts
}

fn usage(binary: &str, options: &getopts::Options) {
    let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
    println!(
        r#"{usage}

The FILTER string is tested against the name of all tests, and only those
tests whose names contain the filter are run.

By default, all tests are run in parallel. This can be altered with the
--test-threads flag or the RUST_TEST_THREADS environment variable when running
tests (set it to 1).

All tests have their standard output and standard error captured by default.
This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
environment variable to a value other than "0". Logging is not captured by default.

Test Attributes:

    `#[test]`        - Indicates a function is a test to be run. This function
                       takes no arguments.
    `#[bench]`       - Indicates a function is a benchmark to be run. This
                       function takes one argument (test::Bencher).
    `#[should_panic]` - This function (also labeled with `#[test]`) will only pass if
                        the code causes a panic (an assertion failure or panic!)
                        A message may be provided, which the failure string must
                        contain: #[should_panic(expected = "foo")].
    `#[ignore]`       - When applied to a function which is already attributed as a
                        test, then the test runner will ignore these tests during
                        normal test runs. Running with --ignored or --include-ignored will run
                        these tests."#,
        usage = options.usage(&message)
    );
}

/// Parses command line arguments into test options.
/// Returns `None` if help was requested (since we only show help message and don't run tests),
/// returns `Some(Err(..))` if provided arguments are incorrect,
/// otherwise creates a `TestOpts` object and returns it.
pub fn parse_opts(args: &[String]) -> Option<OptRes> {
    // Parse matches.
    let opts = optgroups();
    let args = args.get(1..).unwrap_or(args);
    let matches = match opts.parse(args) {
        Ok(m) => m,
        Err(f) => return Some(Err(f.to_string())),
    };

    // Check if help was requested.
    if matches.opt_present("h") {
        // Show help and do nothing more.
        usage(&args[0], &opts);
        return None;
    }

    // Actually parse the opts.
    let opts_result = parse_opts_impl(matches);

    Some(opts_result)
}

// Gets the option value and checks if unstable features are enabled.
macro_rules! unstable_optflag {
    ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{
        let opt = $matches.opt_present($option_name);
        if !$allow_unstable && opt {
            return Err(format!(
                "The \"{}\" flag is only accepted on the nightly compiler",
                $option_name
            ));
        }

        opt
    }};
}

// Implementation of `parse_opts` that doesn't care about help message
// and returns a `Result`.
fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
    let allow_unstable = get_allow_unstable(&matches)?;

    // Unstable flags
    let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process");
    let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic");
    let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored");
    let time_options = get_time_options(&matches, allow_unstable)?;

    let quiet = matches.opt_present("quiet");
    let exact = matches.opt_present("exact");
    let list = matches.opt_present("list");
    let skip = matches.opt_strs("skip");

    let bench_benchmarks = matches.opt_present("bench");
    let run_tests = !bench_benchmarks || matches.opt_present("test");

    let logfile = get_log_file(&matches)?;
    let run_ignored = get_run_ignored(&matches, include_ignored)?;
    let filter = get_filter(&matches)?;
    let nocapture = get_nocapture(&matches)?;
    let test_threads = get_test_threads(&matches)?;
    let color = get_color_config(&matches)?;
    let format = get_format(&matches, quiet, allow_unstable)?;

    let options = Options::new().display_output(matches.opt_present("show-output"));

    let test_opts = TestOpts {
        list,
        filter,
        filter_exact: exact,
        force_run_in_process,
        exclude_should_panic,
        run_ignored,
        run_tests,
        bench_benchmarks,
        logfile,
        nocapture,
        color,
        format,
        test_threads,
        skip,
        time_options,
        options,
    };

    Ok(test_opts)
}

// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
fn is_nightly() -> bool {
    // Whether this is a feature-staged build, i.e., on the beta or stable channel
    let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
    // Whether we should enable unstable features for bootstrapping
    let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();

    bootstrap || !disable_unstable_features
}

// Gets the CLI options assotiated with `report-time` feature.
fn get_time_options(
    matches: &getopts::Matches,
    allow_unstable: bool,
) -> OptPartRes<Option<TestTimeOptions>> {
    let report_time = unstable_optflag!(matches, allow_unstable, "report-time");
    let colored_opt_str = matches.opt_str("report-time");
    let mut report_time_colored = report_time && colored_opt_str == Some("colored".into());
    let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-time");

    // If `ensure-test-time` option is provided, time output is enforced,
    // so user won't be confused if any of tests will silently fail.
    let options = if report_time || ensure_test_time {
        if ensure_test_time && !report_time {
            report_time_colored = true;
        }
        Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored))
    } else {
        None
    };

    Ok(options)
}

fn get_test_threads(matches: &getopts::Matches) -> OptPartRes<Option<usize>> {
    let test_threads = match matches.opt_str("test-threads") {
        Some(n_str) => match n_str.parse::<usize>() {
            Ok(0) => return Err("argument for --test-threads must not be 0".to_string()),
            Ok(n) => Some(n),
            Err(e) => {
                return Err(format!(
                    "argument for --test-threads must be a number > 0 \
                     (error: {})",
                    e
                ));
            }
        },
        None => None,
    };

    Ok(test_threads)
}

fn get_format(
    matches: &getopts::Matches,
    quiet: bool,
    allow_unstable: bool,
) -> OptPartRes<OutputFormat> {
    let format = match matches.opt_str("format").as_ref().map(|s| &**s) {
        None if quiet => OutputFormat::Terse,
        Some("pretty") | None => OutputFormat::Pretty,
        Some("terse") => OutputFormat::Terse,
        Some("json") => {
            if !allow_unstable {
                return Err("The \"json\" format is only accepted on the nightly compiler".into());
            }
            OutputFormat::Json
        }

        Some(v) => {
            return Err(format!(
                "argument for --format must be pretty, terse, or json (was \
                 {})",
                v
            ));
        }
    };

    Ok(format)
}

fn get_color_config(matches: &getopts::Matches) -> OptPartRes<ColorConfig> {
    let color = match matches.opt_str("color").as_ref().map(|s| &**s) {
        Some("auto") | None => ColorConfig::AutoColor,
        Some("always") => ColorConfig::AlwaysColor,
        Some("never") => ColorConfig::NeverColor,

        Some(v) => {
            return Err(format!(
                "argument for --color must be auto, always, or never (was \
                 {})",
                v
            ));
        }
    };

    Ok(color)
}

fn get_nocapture(matches: &getopts::Matches) -> OptPartRes<bool> {
    let mut nocapture = matches.opt_present("nocapture");
    if !nocapture {
        nocapture = match env::var("RUST_TEST_NOCAPTURE") {
            Ok(val) => &val != "0",
            Err(_) => false,
        };
    }

    Ok(nocapture)
}

fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPartRes<RunIgnored> {
    let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
        (true, true) => {
            return Err("the options --include-ignored and --ignored are mutually exclusive".into());
        }
        (true, false) => RunIgnored::Yes,
        (false, true) => RunIgnored::Only,
        (false, false) => RunIgnored::No,
    };

    Ok(run_ignored)
}

fn get_filter(matches: &getopts::Matches) -> OptPartRes<Option<String>> {
    let filter = if !matches.free.is_empty() { Some(matches.free[0].clone()) } else { None };

    Ok(filter)
}

fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes<bool> {
    let mut allow_unstable = false;

    if let Some(opt) = matches.opt_str("Z") {
        if !is_nightly() {
            return Err("the option `Z` is only accepted on the nightly compiler".into());
        }

        match &*opt {
            "unstable-options" => {
                allow_unstable = true;
            }
            _ => {
                return Err("Unrecognized option to `Z`".into());
            }
        }
    };

    Ok(allow_unstable)
}

fn get_log_file(matches: &getopts::Matches) -> OptPartRes<Option<PathBuf>> {
    let logfile = matches.opt_str("logfile").map(|s| PathBuf::from(&s));

    Ok(logfile)
}
<commit_msg>Rollup merge of #68097 - MikailBag:master, r=shepmaster<commit_after>//! Module converting command-line arguments into test configuration.

use getopts;
use std::env;
use std::path::PathBuf;

use super::helpers::isatty;
use super::options::{ColorConfig, Options, OutputFormat, RunIgnored};
use super::time::TestTimeOptions;

#[derive(Debug)]
pub struct TestOpts {
    pub list: bool,
    pub filter: Option<String>,
    pub filter_exact: bool,
    pub force_run_in_process: bool,
    pub exclude_should_panic: bool,
    pub run_ignored: RunIgnored,
    pub run_tests: bool,
    pub bench_benchmarks: bool,
    pub logfile: Option<PathBuf>,
    pub nocapture: bool,
    pub color: ColorConfig,
    pub format: OutputFormat,
    pub test_threads: Option<usize>,
    pub skip: Vec<String>,
    pub time_options: Option<TestTimeOptions>,
    pub options: Options,
}

impl TestOpts {
    pub fn use_color(&self) -> bool {
        match self.color {
            ColorConfig::AutoColor => !self.nocapture && isatty::stdout_isatty(),
            ColorConfig::AlwaysColor => true,
            ColorConfig::NeverColor => false,
        }
    }
}

/// Result of parsing the options.
pub type OptRes = Result<TestOpts, String>;
/// Result of parsing the option part.
type OptPartRes<T> = Result<T, String>;

fn optgroups() -> getopts::Options {
    let mut opts = getopts::Options::new();
    opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
        .optflag("", "ignored", "Run only ignored tests")
        .optflag("", "force-run-in-process", "Forces tests to run in-process when panic=abort")
        .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
        .optflag("", "test", "Run tests and not benchmarks")
        .optflag("", "bench", "Run benchmarks instead of tests")
        .optflag("", "list", "List all tests and benchmarks")
        .optflag("h", "help", "Display this message (longer with --help)")
        .optopt(
            "",
            "logfile",
            "Write logs to the specified file instead \
             of stdout",
            "PATH",
        )
        .optflag(
            "",
            "nocapture",
            "don't capture stdout/stderr of each \
             task, allow printing directly",
        )
        .optopt(
            "",
            "test-threads",
            "Number of threads used for running tests \
             in parallel",
            "n_threads",
        )
        .optmulti(
            "",
            "skip",
            "Skip tests whose names contain FILTER (this flag can \
             be used multiple times)",
            "FILTER",
        )
        .optflag(
            "q",
            "quiet",
            "Display one character per test instead of one line. \
             Alias to --format=terse",
        )
        .optflag("", "exact", "Exactly match filters rather than by substring")
        .optopt(
            "",
            "color",
            "Configure coloring of output:
            auto   = colorize if stdout is a tty and tests are run on serially (default);
            always = always colorize output;
            never  = never colorize output;",
            "auto|always|never",
        )
        .optopt(
            "",
            "format",
            "Configure formatting of output:
            pretty = Print verbose output;
            terse  = Display one character per test;
            json   = Output a json document",
            "pretty|terse|json",
        )
        .optflag("", "show-output", "Show captured stdout of successful tests")
        .optopt(
            "Z",
            "",
            "Enable nightly-only flags:
            unstable-options = Allow use of experimental features",
            "unstable-options",
        )
        .optflagopt(
            "",
            "report-time",
            "Show execution time of each test. Awailable values:
            plain   = do not colorize the execution time (default);
            colored = colorize output according to the `color` parameter value;

            Threshold values for colorized output can be configured via
            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
            `RUST_TEST_TIME_DOCTEST` environment variables.

            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.
            Durations must be specified in milliseconds, e.g. `500,2000` means that the warn time
            is 0.5 seconds, and the critical time is 2 seconds.

            Not available for --format=terse",
            "plain|colored",
        )
        .optflag(
            "",
            "ensure-time",
            "Treat excess of the test execution time limit as error.

            Threshold values for this option can be configured via
            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
            `RUST_TEST_TIME_DOCTEST` environment variables.

            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.

            `CRITICAL_TIME` here means the limit that should not be exceeded by test.
            ",
        );
    opts
}

fn usage(binary: &str, options: &getopts::Options) {
    let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
    println!(
        r#"{usage}

The FILTER string is tested against the name of all tests, and only those
tests whose names contain the filter are run.

By default, all tests are run in parallel. This can be altered with the
--test-threads flag or the RUST_TEST_THREADS environment variable when running
tests (set it to 1).

All tests have their standard output and standard error captured by default.
This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
environment variable to a value other than "0". Logging is not captured by default.

Test Attributes:

    `#[test]`        - Indicates a function is a test to be run. This function
                       takes no arguments.
    `#[bench]`       - Indicates a function is a benchmark to be run. This
                       function takes one argument (test::Bencher).
    `#[should_panic]` - This function (also labeled with `#[test]`) will only pass if
                        the code causes a panic (an assertion failure or panic!)
                        A message may be provided, which the failure string must
                        contain: #[should_panic(expected = "foo")].
    `#[ignore]`       - When applied to a function which is already attributed as a
                        test, then the test runner will ignore these tests during
                        normal test runs. Running with --ignored or --include-ignored will run
                        these tests."#,
        usage = options.usage(&message)
    );
}

/// Parses command line arguments into test options.
/// Returns `None` if help was requested (since we only show help message and don't run tests),
/// returns `Some(Err(..))` if provided arguments are incorrect,
/// otherwise creates a `TestOpts` object and returns it.
pub fn parse_opts(args: &[String]) -> Option<OptRes> {
    // Parse matches.
    let opts = optgroups();
    let args = args.get(1..).unwrap_or(args);
    let matches = match opts.parse(args) {
        Ok(m) => m,
        Err(f) => return Some(Err(f.to_string())),
    };

    // Check if help was requested.
    if matches.opt_present("h") {
        // Show help and do nothing more.
        usage(&args[0], &opts);
        return None;
    }

    // Actually parse the opts.
    let opts_result = parse_opts_impl(matches);

    Some(opts_result)
}

// Gets the option value and checks if unstable features are enabled.
macro_rules! unstable_optflag {
    ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{
        let opt = $matches.opt_present($option_name);
        if !$allow_unstable && opt {
            return Err(format!(
                "The \"{}\" flag is only accepted on the nightly compiler",
                $option_name
            ));
        }

        opt
    }};
}

// Implementation of `parse_opts` that doesn't care about help message
// and returns a `Result`.
fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
    let allow_unstable = get_allow_unstable(&matches)?;

    // Unstable flags
    let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process");
    let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic");
    let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored");
    let time_options = get_time_options(&matches, allow_unstable)?;

    let quiet = matches.opt_present("quiet");
    let exact = matches.opt_present("exact");
    let list = matches.opt_present("list");
    let skip = matches.opt_strs("skip");

    let bench_benchmarks = matches.opt_present("bench");
    let run_tests = !bench_benchmarks || matches.opt_present("test");

    let logfile = get_log_file(&matches)?;
    let run_ignored = get_run_ignored(&matches, include_ignored)?;
    let filter = get_filter(&matches)?;
    let nocapture = get_nocapture(&matches)?;
    let test_threads = get_test_threads(&matches)?;
    let color = get_color_config(&matches)?;
    let format = get_format(&matches, quiet, allow_unstable)?;

    let options = Options::new().display_output(matches.opt_present("show-output"));

    let test_opts = TestOpts {
        list,
        filter,
        filter_exact: exact,
        force_run_in_process,
        exclude_should_panic,
        run_ignored,
        run_tests,
        bench_benchmarks,
        logfile,
        nocapture,
        color,
        format,
        test_threads,
        skip,
        time_options,
        options,
    };

    Ok(test_opts)
}

// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
fn is_nightly() -> bool {
    // Whether this is a feature-staged build, i.e., on the beta or stable channel
    let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
    // Whether we should enable unstable features for bootstrapping
    let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();

    bootstrap || !disable_unstable_features
}

// Gets the CLI options assotiated with `report-time` feature.
fn get_time_options(
    matches: &getopts::Matches,
    allow_unstable: bool,
) -> OptPartRes<Option<TestTimeOptions>> {
    let report_time = unstable_optflag!(matches, allow_unstable, "report-time");
    let colored_opt_str = matches.opt_str("report-time");
    let mut report_time_colored = report_time && colored_opt_str == Some("colored".into());
    let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-time");

    // If `ensure-test-time` option is provided, time output is enforced,
    // so user won't be confused if any of tests will silently fail.
    let options = if report_time || ensure_test_time {
        if ensure_test_time && !report_time {
            report_time_colored = true;
        }
        Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored))
    } else {
        None
    };

    Ok(options)
}

fn get_test_threads(matches: &getopts::Matches) -> OptPartRes<Option<usize>> {
    let test_threads = match matches.opt_str("test-threads") {
        Some(n_str) => match n_str.parse::<usize>() {
            Ok(0) => return Err("argument for --test-threads must not be 0".to_string()),
            Ok(n) => Some(n),
            Err(e) => {
                return Err(format!(
                    "argument for --test-threads must be a number > 0 \
                     (error: {})",
                    e
                ));
            }
        },
        None => None,
    };

    Ok(test_threads)
}

fn get_format(
    matches: &getopts::Matches,
    quiet: bool,
    allow_unstable: bool,
) -> OptPartRes<OutputFormat> {
    let format = match matches.opt_str("format").as_ref().map(|s| &**s) {
        None if quiet => OutputFormat::Terse,
        Some("pretty") | None => OutputFormat::Pretty,
        Some("terse") => OutputFormat::Terse,
        Some("json") => {
            if !allow_unstable {
                return Err("The \"json\" format is only accepted on the nightly compiler".into());
            }
            OutputFormat::Json
        }

        Some(v) => {
            return Err(format!(
                "argument for --format must be pretty, terse, or json (was \
                 {})",
                v
            ));
        }
    };

    Ok(format)
}

fn get_color_config(matches: &getopts::Matches) -> OptPartRes<ColorConfig> {
    let color = match matches.opt_str("color").as_ref().map(|s| &**s) {
        Some("auto") | None => ColorConfig::AutoColor,
        Some("always") => ColorConfig::AlwaysColor,
        Some("never") => ColorConfig::NeverColor,

        Some(v) => {
            return Err(format!(
                "argument for --color must be auto, always, or never (was \
                 {})",
                v
            ));
        }
    };

    Ok(color)
}

fn get_nocapture(matches: &getopts::Matches) -> OptPartRes<bool> {
    let mut nocapture = matches.opt_present("nocapture");
    if !nocapture {
        nocapture = match env::var("RUST_TEST_NOCAPTURE") {
            Ok(val) => &val != "0",
            Err(_) => false,
        };
    }

    Ok(nocapture)
}

fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPartRes<RunIgnored> {
    let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
        (true, true) => {
            return Err("the options --include-ignored and --ignored are mutually exclusive".into());
        }
        (true, false) => RunIgnored::Yes,
        (false, true) => RunIgnored::Only,
        (false, false) => RunIgnored::No,
    };

    Ok(run_ignored)
}

fn get_filter(matches: &getopts::Matches) -> OptPartRes<Option<String>> {
    let filter = if !matches.free.is_empty() { Some(matches.free[0].clone()) } else { None };

    Ok(filter)
}

fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes<bool> {
    let mut allow_unstable = false;

    if let Some(opt) = matches.opt_str("Z") {
        if !is_nightly() {
            return Err("the option `Z` is only accepted on the nightly compiler".into());
        }

        match &*opt {
            "unstable-options" => {
                allow_unstable = true;
            }
            _ => {
                return Err("Unrecognized option to `Z`".into());
            }
        }
    };

    Ok(allow_unstable)
}

fn get_log_file(matches: &getopts::Matches) -> OptPartRes<Option<PathBuf>> {
    let logfile = matches.opt_str("logfile").map(|s| PathBuf::from(&s));

    Ok(logfile)
}
<|endoftext|>


<commit_before>use std::num::{Float, FloatMath};
use std::ops::{Add, Sub, Mul};
use std::fmt;
use std::fmt::Show;

pub type Vec2f = Vec2<f32>;
pub type Vec3f = Vec3<f32>;
pub type Vec4f = Vec4<f32>;

pub trait Numvec<T : Float + FloatMath + Copy>
        : Add<Self, Self> + Mul<T, Self> + Div<T, Self> + Copy {
    fn dot(&self, other : &Self) -> T;

    fn squared_norm(&self) -> T { self.dot(self) }
    fn norm(&self) -> T { self.squared_norm().sqrt() }

    fn normalize(&mut self) {
        *self = self.normalized();
    }

    fn normalized(&self) -> Self {
        let norm = self.norm();
        *self / norm
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec2<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
}
impl<T : Float + FloatMath> Vec2<T> {
    pub fn new(x: T, y: T) -> Vec2<T> { Vec2 { x: x, y: y } }

    pub fn zero()   -> Vec2<T> { Vec2 { x: Float::zero(), y: Float::zero() } }
    pub fn x_axis() -> Vec2<T> { Vec2 { x:  Float::one(), y: Float::zero() } }
    pub fn y_axis() -> Vec2<T> { Vec2 { x: Float::zero(), y:  Float::one() } }

    pub fn cross(&self, rhs: &Vec2<T>) -> T {
        self.x * rhs.y - self.y * rhs.x
    }

    pub fn angle(&self) -> T {
        self.y.atan2(self.x)
    }

    pub fn normal(&self) -> Vec2<T> {
        Vec2::new(-self.y, self.x)
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec2<T> {
    fn dot(&self, rhs : &Vec2<T>) -> T {
        self.x * rhs.x + self.y * rhs.y
    }
}
impl<T : Float + FloatMath> Add<Vec2<T>, Vec2<T>> for Vec2<T> {
    fn add(self, rhs : Vec2<T>) -> Vec2<T> {
        return Vec2::new(self.x + rhs.x, self.y + rhs.y);
    }
}
impl<T : Float + FloatMath> Sub<Vec2<T>, Vec2<T>> for Vec2<T> {
    fn sub(self, rhs : Vec2<T>) -> Vec2<T> {
        return Vec2::new(self.x - rhs.x, self.y - rhs.y);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec2<T>> for Vec2<T> {
    fn mul(self, rhs : T) -> Vec2<T> {
        return Vec2::new(self.x * rhs, self.y * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec2<T>> for Vec2<T> {
    fn div(self, rhs : T) -> Vec2<T> {
        return Vec2::new(self.x / rhs, self.y / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec2<T>> for Vec2<T> {
    fn neg(&self) -> Vec2<T> {
        return Vec2::new(-self.x, -self.y);
    }
}
impl<T : Float + FloatMath + Show> Show for Vec2<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "Vec2({}, {})", self.x, self.y)
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec3<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
    pub z : T,
}
impl<T : Float + FloatMath> Vec3<T> {
    pub fn new(x: T, y: T, z: T) -> Vec3<T> { Vec3 { x: x, y: y, z: z } }

    pub fn zero()   -> Vec3<T> { Vec3 { x: Float::zero(), y: Float::zero(), z: Float::zero() } }
    pub fn x_axis() -> Vec3<T> { Vec3 { x:  Float::one(), y: Float::zero(), z: Float::zero() } }
    pub fn y_axis() -> Vec3<T> { Vec3 { x: Float::zero(), y:  Float::one(), z: Float::zero() } }
    pub fn z_axis() -> Vec3<T> { Vec3 { x: Float::zero(), y: Float::zero(), z:  Float::one() } }

    pub fn cross(&self, rhs : &Vec3<T>) -> Vec3<T> {
        Vec3 { x: self.y * rhs.z - self.z * rhs.y,
               y: self.z * rhs.x - self.x * rhs.z,
               z: self.x * rhs.y - self.y * rhs.x }
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec3<T> {
    fn dot(&self, rhs : &Vec3<T>) -> T {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}
impl<T : Float + FloatMath> Add<Vec3<T>, Vec3<T>> for Vec3<T> {
    fn add(self, rhs : Vec3<T>) -> Vec3<T> {
        return Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z);
    }
}
impl<T : Float + FloatMath> Sub<Vec3<T>, Vec3<T>> for Vec3<T> {
    fn sub(self, rhs : Vec3<T>) -> Vec3<T> {
        return Vec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec3<T>> for Vec3<T> {
    fn mul(self, rhs : T) -> Vec3<T> {
        return Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec3<T>> for Vec3<T> {
    fn div(self, rhs : T) -> Vec3<T> {
        return Vec3::new(self.x / rhs, self.y / rhs, self.z / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec3<T>> for Vec3<T> {
    fn neg(&self) -> Vec3<T> {
        return Vec3::new(-self.x, -self.y, -self.z);
    }
}
impl<T : Float + FloatMath + Show> Show for Vec3<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "Vec3({}, {}, {})", self.x, self.y, self.z)
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec4<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
    pub z : T,
    pub w : T,
}
impl<T : Float + FloatMath> Vec4<T> {
    pub fn new(x: T, y: T, z: T, w: T) -> Vec4<T> {
        Vec4 { x: x, y: y, z: z, w: w }
    }

    pub fn zero()   -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::zero(), w: Float::zero() }
    }

    pub fn x_axis() -> Vec4<T> {
        Vec4 { x: Float::one(), y: Float::zero(), z: Float::zero(), w: Float::zero() }
    }

    pub fn y_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::one(), z: Float::zero(), w: Float::zero() }
    }

    pub fn z_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::one(), w: Float::zero() }
    }

    pub fn w_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::zero(), w: Float::one() }
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec4<T> {
    fn dot(&self, rhs : &Vec4<T>) -> T {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + self.w * rhs.w
    }
}
impl<T : Float + FloatMath> Add<Vec4<T>, Vec4<T>> for Vec4<T> {
    fn add(self, rhs : Vec4<T>) -> Vec4<T> {
        return Vec4::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z,
                         self.w + rhs.w);
    }
}
impl<T : Float + FloatMath> Sub<Vec4<T>, Vec4<T>> for Vec4<T> {
    fn sub(self, rhs : Vec4<T>) -> Vec4<T> {
        return Vec4::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z,
                         self.w - rhs.w);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec4<T>> for Vec4<T> {
    fn mul(self, rhs : T) -> Vec4<T> {
        return Vec4::new(self.x * rhs, self.y * rhs, self.z * rhs,
                         self.w * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec4<T>> for Vec4<T> {
    fn div(self, rhs : T) -> Vec4<T> {
        return Vec4::new(self.x / rhs, self.y / rhs, self.z / rhs,
                         self.w / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec4<T>> for Vec4<T> {
    fn neg(&self) -> Vec4<T> {
        return Vec4::new(-self.x, -self.y, -self.z, -self.w);
    }
}
<commit_msg>Neg is now by value<commit_after>use std::num::{Float, FloatMath};
use std::ops::{Add, Sub, Mul};
use std::fmt;
use std::fmt::Show;

pub type Vec2f = Vec2<f32>;
pub type Vec3f = Vec3<f32>;
pub type Vec4f = Vec4<f32>;

pub trait Numvec<T : Float + FloatMath + Copy>
        : Add<Self, Self> + Mul<T, Self> + Div<T, Self> + Copy {
    fn dot(&self, other : &Self) -> T;

    fn squared_norm(&self) -> T { self.dot(self) }
    fn norm(&self) -> T { self.squared_norm().sqrt() }

    fn normalize(&mut self) {
        *self = self.normalized();
    }

    fn normalized(&self) -> Self {
        let norm = self.norm();
        *self / norm
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec2<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
}
impl<T : Float + FloatMath> Vec2<T> {
    pub fn new(x: T, y: T) -> Vec2<T> { Vec2 { x: x, y: y } }

    pub fn zero()   -> Vec2<T> { Vec2 { x: Float::zero(), y: Float::zero() } }
    pub fn x_axis() -> Vec2<T> { Vec2 { x:  Float::one(), y: Float::zero() } }
    pub fn y_axis() -> Vec2<T> { Vec2 { x: Float::zero(), y:  Float::one() } }

    pub fn cross(&self, rhs: &Vec2<T>) -> T {
        self.x * rhs.y - self.y * rhs.x
    }

    pub fn angle(&self) -> T {
        self.y.atan2(self.x)
    }

    pub fn normal(&self) -> Vec2<T> {
        Vec2::new(-self.y, self.x)
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec2<T> {
    fn dot(&self, rhs : &Vec2<T>) -> T {
        self.x * rhs.x + self.y * rhs.y
    }
}
impl<T : Float + FloatMath> Add<Vec2<T>, Vec2<T>> for Vec2<T> {
    fn add(self, rhs : Vec2<T>) -> Vec2<T> {
        return Vec2::new(self.x + rhs.x, self.y + rhs.y);
    }
}
impl<T : Float + FloatMath> Sub<Vec2<T>, Vec2<T>> for Vec2<T> {
    fn sub(self, rhs : Vec2<T>) -> Vec2<T> {
        return Vec2::new(self.x - rhs.x, self.y - rhs.y);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec2<T>> for Vec2<T> {
    fn mul(self, rhs : T) -> Vec2<T> {
        return Vec2::new(self.x * rhs, self.y * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec2<T>> for Vec2<T> {
    fn div(self, rhs : T) -> Vec2<T> {
        return Vec2::new(self.x / rhs, self.y / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec2<T>> for Vec2<T> {
    fn neg(self) -> Vec2<T> {
        return Vec2::new(-self.x, -self.y);
    }
}
impl<T : Float + FloatMath + Show> Show for Vec2<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "Vec2({}, {})", self.x, self.y)
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec3<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
    pub z : T,
}
impl<T : Float + FloatMath> Vec3<T> {
    pub fn new(x: T, y: T, z: T) -> Vec3<T> { Vec3 { x: x, y: y, z: z } }

    pub fn zero()   -> Vec3<T> { Vec3 { x: Float::zero(), y: Float::zero(), z: Float::zero() } }
    pub fn x_axis() -> Vec3<T> { Vec3 { x:  Float::one(), y: Float::zero(), z: Float::zero() } }
    pub fn y_axis() -> Vec3<T> { Vec3 { x: Float::zero(), y:  Float::one(), z: Float::zero() } }
    pub fn z_axis() -> Vec3<T> { Vec3 { x: Float::zero(), y: Float::zero(), z:  Float::one() } }

    pub fn cross(&self, rhs : &Vec3<T>) -> Vec3<T> {
        Vec3 { x: self.y * rhs.z - self.z * rhs.y,
               y: self.z * rhs.x - self.x * rhs.z,
               z: self.x * rhs.y - self.y * rhs.x }
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec3<T> {
    fn dot(&self, rhs : &Vec3<T>) -> T {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}
impl<T : Float + FloatMath> Add<Vec3<T>, Vec3<T>> for Vec3<T> {
    fn add(self, rhs : Vec3<T>) -> Vec3<T> {
        return Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z);
    }
}
impl<T : Float + FloatMath> Sub<Vec3<T>, Vec3<T>> for Vec3<T> {
    fn sub(self, rhs : Vec3<T>) -> Vec3<T> {
        return Vec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec3<T>> for Vec3<T> {
    fn mul(self, rhs : T) -> Vec3<T> {
        return Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec3<T>> for Vec3<T> {
    fn div(self, rhs : T) -> Vec3<T> {
        return Vec3::new(self.x / rhs, self.y / rhs, self.z / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec3<T>> for Vec3<T> {
    fn neg(self) -> Vec3<T> {
        return Vec3::new(-self.x, -self.y, -self.z);
    }
}
impl<T : Float + FloatMath + Show> Show for Vec3<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "Vec3({}, {}, {})", self.x, self.y, self.z)
    }
}

#[packed]
#[repr(C)]
#[deriving(Copy)]
pub struct Vec4<T: Float + FloatMath> {
    pub x : T,
    pub y : T,
    pub z : T,
    pub w : T,
}
impl<T : Float + FloatMath> Vec4<T> {
    pub fn new(x: T, y: T, z: T, w: T) -> Vec4<T> {
        Vec4 { x: x, y: y, z: z, w: w }
    }

    pub fn zero()   -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::zero(), w: Float::zero() }
    }

    pub fn x_axis() -> Vec4<T> {
        Vec4 { x: Float::one(), y: Float::zero(), z: Float::zero(), w: Float::zero() }
    }

    pub fn y_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::one(), z: Float::zero(), w: Float::zero() }
    }

    pub fn z_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::one(), w: Float::zero() }
    }

    pub fn w_axis() -> Vec4<T> {
        Vec4 { x: Float::zero(), y: Float::zero(), z: Float::zero(), w: Float::one() }
    }
}
impl<T : Float + FloatMath> Numvec<T> for Vec4<T> {
    fn dot(&self, rhs : &Vec4<T>) -> T {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + self.w * rhs.w
    }
}
impl<T : Float + FloatMath> Add<Vec4<T>, Vec4<T>> for Vec4<T> {
    fn add(self, rhs : Vec4<T>) -> Vec4<T> {
        return Vec4::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z,
                         self.w + rhs.w);
    }
}
impl<T : Float + FloatMath> Sub<Vec4<T>, Vec4<T>> for Vec4<T> {
    fn sub(self, rhs : Vec4<T>) -> Vec4<T> {
        return Vec4::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z,
                         self.w - rhs.w);
    }
}
impl<T : Float + FloatMath> Mul<T, Vec4<T>> for Vec4<T> {
    fn mul(self, rhs : T) -> Vec4<T> {
        return Vec4::new(self.x * rhs, self.y * rhs, self.z * rhs,
                         self.w * rhs);
    }
}
impl<T : Float + FloatMath> Div<T, Vec4<T>> for Vec4<T> {
    fn div(self, rhs : T) -> Vec4<T> {
        return Vec4::new(self.x / rhs, self.y / rhs, self.z / rhs,
                         self.w / rhs);
    }
}
impl<T : Float + FloatMath> Neg<Vec4<T>> for Vec4<T> {
    fn neg(self) -> Vec4<T> {
        return Vec4::new(-self.x, -self.y, -self.z, -self.w);
    }
}
<|endoftext|>


<commit_before> #![feature(augmented_assignments)]

extern crate cgmath;
extern crate docopt;
#[macro_use]
extern crate glium;
extern crate rand;
extern crate rayon;
extern crate rustc_serialize;
extern crate time;

use docopt::Docopt;
use rand::{SeedableRng, XorShiftRng};

mod nbody;
mod visualize;
use self::visualize::visualize_benchmarks;
use self::nbody::NBodyBenchmark;

const USAGE: &'static str = "
Usage: nbody bench [--mode MODE --bodies N --ticks N]
       nbody visualize [--mode MODE --bodies N]
       nbody --help

Commands:
    bench              Run the benchmark and print the timings.
    visualize          Show the graphical visualizer.

Options:
    -h, --help         Show this message.
    --mode MODE        Execution mode for the benchmark/visualizer.
    --bodies N         Use N bodies [default: 4000].
    --ticks N          Simulate for N ticks [default: 100].
";

#[derive(Copy, Clone, PartialEq, Eq, RustcDecodable)]
pub enum ExecutionMode {
    Par,
    ParReduce,
    Seq,
}

#[derive(RustcDecodable)]
pub struct Args {
    cmd_bench: bool,
    cmd_visualize: bool,
    flag_mode: Option<ExecutionMode>,
    flag_bodies: usize,
    flag_ticks: usize,
}

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

    if args.cmd_bench {
        run_benchmarks(args.flag_mode, args.flag_bodies, args.flag_ticks);
    }

    if args.cmd_visualize {
        visualize_benchmarks(args.flag_bodies,
                             args.flag_mode.unwrap_or(ExecutionMode::Par));
    }
}

fn run_benchmarks(mode: Option<ExecutionMode>, bodies: usize, ticks: usize) {
    let run_par = mode.map(|m| m == ExecutionMode::Par).unwrap_or(true);
    let run_par_reduce = mode.map(|m| m == ExecutionMode::ParReduce).unwrap_or(true);
    let run_seq = mode.map(|m| m == ExecutionMode::Seq).unwrap_or(true);

    let par_time = if run_par {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_par();
        }

        let par_time = time::precise_time_ns() - par_start;
        println!("Parallel time    : {}", par_time);

        Some(par_time)
    } else {
        None
    };

    let par_reduce_time = if run_par_reduce {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_par_reduce();
        }

        let par_time = time::precise_time_ns() - par_start;
        println!("ParReduce time   : {}", par_time);

        Some(par_time)
    } else {
        None
    };

    let seq_time = if run_seq {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let seq_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_seq();
        }

        let seq_time = time::precise_time_ns() - seq_start;
        println!("Sequential time  : {}", seq_time);

        Some(seq_time)
    } else {
        None
    };

    if let (Some(pt), Some(st)) = (par_time, seq_time) {
        println!("Parallel speedup : {}", (st as f32) / (pt as f32));
    }

    if let (Some(pt), Some(st)) = (par_reduce_time, seq_time) {
        println!("ParReduce speedup: {}", (st as f32) / (pt as f32));
    }
}
<commit_msg>add unit when printing out times<commit_after> #![feature(augmented_assignments)]

extern crate cgmath;
extern crate docopt;
#[macro_use]
extern crate glium;
extern crate rand;
extern crate rayon;
extern crate rustc_serialize;
extern crate time;

use docopt::Docopt;
use rand::{SeedableRng, XorShiftRng};

mod nbody;
mod visualize;
use self::visualize::visualize_benchmarks;
use self::nbody::NBodyBenchmark;

const USAGE: &'static str = "
Usage: nbody bench [--mode MODE --bodies N --ticks N]
       nbody visualize [--mode MODE --bodies N]
       nbody --help

Commands:
    bench              Run the benchmark and print the timings.
    visualize          Show the graphical visualizer.

Options:
    -h, --help         Show this message.
    --mode MODE        Execution mode for the benchmark/visualizer.
    --bodies N         Use N bodies [default: 4000].
    --ticks N          Simulate for N ticks [default: 100].
";

#[derive(Copy, Clone, PartialEq, Eq, RustcDecodable)]
pub enum ExecutionMode {
    Par,
    ParReduce,
    Seq,
}

#[derive(RustcDecodable)]
pub struct Args {
    cmd_bench: bool,
    cmd_visualize: bool,
    flag_mode: Option<ExecutionMode>,
    flag_bodies: usize,
    flag_ticks: usize,
}

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

    if args.cmd_bench {
        run_benchmarks(args.flag_mode, args.flag_bodies, args.flag_ticks);
    }

    if args.cmd_visualize {
        visualize_benchmarks(args.flag_bodies,
                             args.flag_mode.unwrap_or(ExecutionMode::Par));
    }
}

fn run_benchmarks(mode: Option<ExecutionMode>, bodies: usize, ticks: usize) {
    let run_par = mode.map(|m| m == ExecutionMode::Par).unwrap_or(true);
    let run_par_reduce = mode.map(|m| m == ExecutionMode::ParReduce).unwrap_or(true);
    let run_seq = mode.map(|m| m == ExecutionMode::Seq).unwrap_or(true);

    let par_time = if run_par {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_par();
        }

        let par_time = time::precise_time_ns() - par_start;
        println!("Parallel time    : {} ns", par_time);

        Some(par_time)
    } else {
        None
    };

    let par_reduce_time = if run_par_reduce {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_par_reduce();
        }

        let par_time = time::precise_time_ns() - par_start;
        println!("ParReduce time   : {} ns", par_time);

        Some(par_time)
    } else {
        None
    };

    let seq_time = if run_seq {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let seq_start = time::precise_time_ns();

        for _ in 0..ticks {
            benchmark.tick_seq();
        }

        let seq_time = time::precise_time_ns() - seq_start;
        println!("Sequential time  : {} ns", seq_time);

        Some(seq_time)
    } else {
        None
    };

    if let (Some(pt), Some(st)) = (par_time, seq_time) {
        println!("Parallel speedup : {}", (st as f32) / (pt as f32));
    }

    if let (Some(pt), Some(st)) = (par_reduce_time, seq_time) {
        println!("ParReduce speedup: {}", (st as f32) / (pt as f32));
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;
pub mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::str;
use std::io::Read;

use hyper::Client;
use hyper::header;
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::status::{StatusCode,StatusClass};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
  Normal, High
}

/// Represents a GCM message. Construct the GCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use gcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
  to: &'a str,
  registration_ids: Option<Vec<String>>,
  collapse_key: Option<&'a str>,
  priority: Option<Priority>,
  content_available: Option<bool>,
  delay_while_idle: Option<bool>,
  time_to_live: Option<i32>,
  restricted_package_name: Option<&'a str>,
  dry_run: Option<bool>,
  data: Option<HashMap<String, String>>,
  notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
  fn to_json(&self) -> Json {
    let mut root = BTreeMap::new();

    root.insert("to".to_string(), self.to.to_json());

    if self.registration_ids.is_some() {
      root.insert("registration_ids".to_string(),
          self.registration_ids.clone().unwrap().to_json());
    }

    if self.collapse_key.is_some() {
      root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
    }

    if self.priority.is_some() {
      root.insert("priority".to_string(), match self.priority.clone().unwrap() {
        Priority::Normal => Json::String("normal".to_string()),
        Priority::High => Json::String("high".to_string()),
      });
    }

    if self.content_available.is_some() {
      root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
    }

    if self.delay_while_idle.is_some() {
      root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
    }

    if self.time_to_live.is_some() {
      root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
    }

    if self.restricted_package_name.is_some() {
      root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
    }

    if self.dry_run.is_some() {
      root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
    }

    if self.data.is_some() {
      root.insert("data".to_string(), self.data.clone().unwrap().to_json());
    }

    if self.notification.is_some() {
      root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
    }

    Json::Object(root)
  }
}

impl <'a> Message<'a> {
  /// Get a new instance of Message. You need to supply either
  /// a registration id, or a topic (/topic/...).
  pub fn new(to: &'a str) -> Message {
    Message {
      to: to,
      registration_ids: None,
      collapse_key: None,
      priority: None,
      content_available: None,
      delay_while_idle: None,
      time_to_live: None,
      restricted_package_name: None,
      dry_run: None,
      data: None,
      notification: None,
    }
  }

  /// Set various registration ids to which the message ought to be sent.
  pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
    self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
    self
  }

  /// Set this parameter to identify groups of messages that can be collapsed.
  pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
    self.collapse_key = Some(collapse_key);
    self
  }

  /// Set the priority of the message. You can set Normal or High priorities.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, Priority};
  ///
  /// let message = Message::new("<registration id>")
  ///     .priority(Priority::High);
  /// ```
  pub fn priority(mut self, priority: Priority) -> Message<'a> {
    self.priority = Some(priority);
    self
  }

  /// To set the `content-available` field on iOS
  pub fn content_available(mut self, content_available: bool) -> Message<'a> {
    self.content_available = Some(content_available);
    self
  }

  /// When set to `true`, sends the message only when the device is active.
  pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
    self.delay_while_idle = Some(delay_while_idle);
    self
  }

  /// How long (in seconds) to keep the message on GCM servers in case the device
  /// is offline. The maximum and default is 4 weeks.
  pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
    self.time_to_live = Some(time_to_live);
    self
  }

  /// Package name of the application where the registration tokens must match.
  pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
    self.restricted_package_name = Some(restricted_package_name);
    self
  }

  /// When set to `true`, allows you to test GCM without actually sending the message.
  pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
    self.dry_run = Some(dry_run);
    self
  }

  /// Use this to add custom key-value pairs to the message. This data
  /// must be handled appropriately on the client end.
  /// # Examples:
  /// ```rust
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let message = Message::new("<registration id>").data(map);
  /// ```
  pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
    let mut datamap: HashMap<String, String> = HashMap::new();
    for (key, val) in data.iter() {
      datamap.insert(key.to_string(), val.to_string());
    }

    self.data = Some(datamap);
    self
  }

  /// Use this to set a `Notification` for the message.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, NotificationBuilder};
  ///
  /// let notification = NotificationBuilder::new("Hey!")
  ///     .body("Do you want to catch up later?")
  ///     .finalize();
  ///
  /// let message = Message::new("<registration id>")
  ///     .notification(notification);
  /// ```
  pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
    self.notification = Some(notification);
    self
  }

  /// Send the message using your GCM API Key.
  /// # Examples:
  /// ```no_run
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let result = Message::new("<registration id>")
  ///     .data(map)
  ///     .send("<GCM API Key>");
  /// ```
  pub fn send(self, api_key: &'a str) -> Result<response::GcmResponse, response::GcmError> {
  	let ssl = NativeTlsClient::new().unwrap();
  	let connector = HttpsConnector::new(ssl);
  	let client = Client::with_connector(connector);

  	let result = client.post("https://gcm-http.googleapis.com/gcm/send")
  					.body(self.to_json().to_string().as_bytes())
  					.header(header::Authorization("key=".to_string() + api_key))
  					.header(header::ContentType(Mime(TopLevel::Application,SubLevel::Json,vec![(Attr::Charset, Value::Utf8)])))
  					.send();

    match result {
      Ok(mut res) => {
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap(); //unsafe?
        Message::parse_response(res.status, &body)
      },
      Err(_) => {
        Message::parse_response(StatusCode::InternalServerError, "Server Error")
      }
    }
  }

  fn parse_response(status: StatusCode, body: &str) -> Result<response::GcmResponse, response::GcmError> {
  	//200 Ok: Request was successful!
  	if status == StatusCode::Ok {
  		return Ok(try!(json::decode(body)));
  	}
  	//check for server error (5xx)
  	if status.class() == StatusClass::ServerError {
  		return Err(response::GcmError::ServerError);
  	}
  	//match remaining status codes
  	match status {
  		StatusCode::Unauthorized => Err(response::GcmError::Unauthorized),
  		StatusCode::BadRequest => Err(response::GcmError::InvalidMessage(body.to_string())),
  		_ => Err(response::GcmError::InvalidMessage("Unknown Error".to_string()))
  	}
  }
}
<commit_msg>Now reading the body from the response gracefully<commit_after>#[cfg(test)]
mod tests;
pub mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::str;
use std::io::Read;

use hyper::Client;
use hyper::header;
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::status::{StatusCode,StatusClass};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
  Normal, High
}

/// Represents a GCM message. Construct the GCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use gcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
  to: &'a str,
  registration_ids: Option<Vec<String>>,
  collapse_key: Option<&'a str>,
  priority: Option<Priority>,
  content_available: Option<bool>,
  delay_while_idle: Option<bool>,
  time_to_live: Option<i32>,
  restricted_package_name: Option<&'a str>,
  dry_run: Option<bool>,
  data: Option<HashMap<String, String>>,
  notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
  fn to_json(&self) -> Json {
    let mut root = BTreeMap::new();

    root.insert("to".to_string(), self.to.to_json());

    if self.registration_ids.is_some() {
      root.insert("registration_ids".to_string(),
          self.registration_ids.clone().unwrap().to_json());
    }

    if self.collapse_key.is_some() {
      root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
    }

    if self.priority.is_some() {
      root.insert("priority".to_string(), match self.priority.clone().unwrap() {
        Priority::Normal => Json::String("normal".to_string()),
        Priority::High => Json::String("high".to_string()),
      });
    }

    if self.content_available.is_some() {
      root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
    }

    if self.delay_while_idle.is_some() {
      root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
    }

    if self.time_to_live.is_some() {
      root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
    }

    if self.restricted_package_name.is_some() {
      root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
    }

    if self.dry_run.is_some() {
      root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
    }

    if self.data.is_some() {
      root.insert("data".to_string(), self.data.clone().unwrap().to_json());
    }

    if self.notification.is_some() {
      root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
    }

    Json::Object(root)
  }
}

impl <'a> Message<'a> {
  /// Get a new instance of Message. You need to supply either
  /// a registration id, or a topic (/topic/...).
  pub fn new(to: &'a str) -> Message {
    Message {
      to: to,
      registration_ids: None,
      collapse_key: None,
      priority: None,
      content_available: None,
      delay_while_idle: None,
      time_to_live: None,
      restricted_package_name: None,
      dry_run: None,
      data: None,
      notification: None,
    }
  }

  /// Set various registration ids to which the message ought to be sent.
  pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
    self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
    self
  }

  /// Set this parameter to identify groups of messages that can be collapsed.
  pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
    self.collapse_key = Some(collapse_key);
    self
  }

  /// Set the priority of the message. You can set Normal or High priorities.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, Priority};
  ///
  /// let message = Message::new("<registration id>")
  ///     .priority(Priority::High);
  /// ```
  pub fn priority(mut self, priority: Priority) -> Message<'a> {
    self.priority = Some(priority);
    self
  }

  /// To set the `content-available` field on iOS
  pub fn content_available(mut self, content_available: bool) -> Message<'a> {
    self.content_available = Some(content_available);
    self
  }

  /// When set to `true`, sends the message only when the device is active.
  pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
    self.delay_while_idle = Some(delay_while_idle);
    self
  }

  /// How long (in seconds) to keep the message on GCM servers in case the device
  /// is offline. The maximum and default is 4 weeks.
  pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
    self.time_to_live = Some(time_to_live);
    self
  }

  /// Package name of the application where the registration tokens must match.
  pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
    self.restricted_package_name = Some(restricted_package_name);
    self
  }

  /// When set to `true`, allows you to test GCM without actually sending the message.
  pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
    self.dry_run = Some(dry_run);
    self
  }

  /// Use this to add custom key-value pairs to the message. This data
  /// must be handled appropriately on the client end.
  /// # Examples:
  /// ```rust
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let message = Message::new("<registration id>").data(map);
  /// ```
  pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
    let mut datamap: HashMap<String, String> = HashMap::new();
    for (key, val) in data.iter() {
      datamap.insert(key.to_string(), val.to_string());
    }

    self.data = Some(datamap);
    self
  }

  /// Use this to set a `Notification` for the message.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, NotificationBuilder};
  ///
  /// let notification = NotificationBuilder::new("Hey!")
  ///     .body("Do you want to catch up later?")
  ///     .finalize();
  ///
  /// let message = Message::new("<registration id>")
  ///     .notification(notification);
  /// ```
  pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
    self.notification = Some(notification);
    self
  }

  /// Send the message using your GCM API Key.
  /// # Examples:
  /// ```no_run
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let result = Message::new("<registration id>")
  ///     .data(map)
  ///     .send("<GCM API Key>");
  /// ```
  pub fn send(self, api_key: &'a str) -> Result<response::GcmResponse, response::GcmError> {
  	let ssl = NativeTlsClient::new().unwrap();
  	let connector = HttpsConnector::new(ssl);
  	let client = Client::with_connector(connector);

  	let result = client.post("https://gcm-http.googleapis.com/gcm/send")
  					.body(self.to_json().to_string().as_bytes())
  					.header(header::Authorization("key=".to_string() + api_key))
  					.header(
              header::ContentType(
                Mime(
                  TopLevel::Application,
                  SubLevel::Json,
                  vec![(Attr::Charset, Value::Utf8)]
                )
              )
            )
  					.send();

    match result {
      Ok(mut res) => {
        let mut body = String::new();
        match res.read_to_string(&mut body) {
          Ok(_) => Message::parse_response(res.status, &body),
          Err(_) => Message::parse_response(StatusCode::InternalServerError, "Server Error")
        }
      },
      Err(_) => {
        Message::parse_response(StatusCode::InternalServerError, "Server Error")
      }
    }
  }

  fn parse_response(status: StatusCode, body: &str) -> Result<response::GcmResponse, response::GcmError> {
  	//200 Ok: Request was successful!
  	if status == StatusCode::Ok {
  		return Ok(try!(json::decode(body)));
  	}
  	//check for server error (5xx)
  	if status.class() == StatusClass::ServerError {
  		return Err(response::GcmError::ServerError);
  	}
  	//match remaining status codes
  	match status {
  		StatusCode::Unauthorized => Err(response::GcmError::Unauthorized),
  		StatusCode::BadRequest => Err(response::GcmError::InvalidMessage(body.to_string())),
  		_ => Err(response::GcmError::InvalidMessage("Unknown Error".to_string()))
  	}
  }
}
<|endoftext|>