<commit_before>//! # Slog -  Structured, composable logging for Rust
//!
//! ## Features
//!
//! * easy to use
//! * great performance; see: [slog bench log](https://github.com/dpc/slog-rs/wiki/Bench-log)
//! * `#![no_std]` support (with opt-out `std` cargo feature flag)
//! * hierarchical loggers
//! * lazily evaluated values
//! * modular, lightweight and very extensible
//! 	* tiny core crate that does not pull any dependencies
//! 	* feature-crates for specific functionality
//! * backward compatibility for standard `log` crate (`slog-stdlog` crate)
//! 	* supports logging-scopes
//! 	* using slog in library does not force users of the library to use slog
//! 	  (but gives benefits); see `crates/example-lib`
//! * drains & output formatting
//! 	* filtering
//! 		* compile-time log level filter using cargo features (same as in `log` crate)
//! 		* by level, msg, and any other meta-data
//! 		* [`slog-envlogger`](https://github.com/slog-rs/envlogger) - port of `env_logger`
//! 	* multiple outputs
//! 	* asynchronous IO writing
//! 	* terminal output, with color support (`slog-term` crate)
//! 	* Json (`slog-json` crate)
//! 		* Bunyan (`slog-bunyan` crate)
//! 	* syslog (`slog-syslog` crate)
//! 	* first class custom drains
//!
//! ## Advantages over `log` crate
//!
//! * **extensible** - `slog` provides core functionality, and some standard
//!   feature-set. But using traits, anyone can easily implement as
//!   powerful fully-custom features, publish separately and grow `slog` feature-set
//!   for everyone.
//! * **composable** - Wouldn't it be nice if you could use
//!   [`env_logger`][env_logger], but output authentication messages to syslog,
//!   while reporting errors over network in json format? With `slog` drains can
//!   reuse other drains! You can combine them together, chain, wrap - you name it.
//! * **context aware** - It's not just one global logger. Hierarchical
//!   loggers carry information about context of logging. When logging an error
//!   condition, you want to know which resource was being handled, on which
//!   instance of your service, using which source code build, talking with what
//!   peer, etc. In standard `log` you would have to repeat this information in
//!   every log statement. In `slog` it will happen automatically. See
//!   [slog-rs functional overview page][functional-overview] to understand better
//!   logger and drain hierarchies and log record flow through them.
//! * both **human and machine readable** - By keeping the key-value data format,
//!   meaning of logging data is preserved. Dump your logging to a JSON file, and
//!   send it to your data-mining system for further analysis. Don't parse it from
//!   lines of text anymore!
//! * **lazy evaluation** and **asynchronous IO** included. Waiting to
//!   finish writing logging information to disk, or spending time calculating
//!   data that will be thrown away at the current logging level, are sources of big
//!   performance waste. Use `AsyncStreamer` drain, and closures to make your logging fast.
//! * **run-time configuration** - [`AtomicSwitch`][atomic-switch] drain allows
//!   changing logging behavior in the running program. You could use eg. signal
//!   handlers to change logging level or logging destinations. See
//!   [`signal` example][signal].
//!
//! ## Notable details
//!
//! `slog` by default removes at compile time trace and debug level statements
//! in release builds, and trace level records in debug builds. This makes
//! `trace` and `debug` level logging records practically free, which should
//! encourage using them freely. If you want to enable trace/debug messages
//! or raise the compile time logging level limit, use the following in your
//! `Cargo.toml`:
//!
//! ```norust
//! slog = { version = "1.2", features = ["max_level_trace", "release_max_level_warn"] }
//! ```
//!
//! Due to the `macro_rules` limitation log macros syntax comes in several
//! versions. See `log!` macro, and pay attention to `;` and `,`
//! details.
//!
//! Root drain (passed to `Logger::root`) must be one that does not ever
//! return errors, which forces user to pick error handing strategy. You
//! can use `.fuse()` or `.ignore_err()` methods from `DrainExt` to do
//! it conveniently.
//!
//! [signal]: https://github.com/slog-rs/misc/blob/master/examples/signal.rs
//! [env_logger]: https://crates.io/crates/env_logger
//! [functional-overview]: https://github.com/dpc/slog-rs/wiki/Functional-overview
//! [atomic-switch]: https://docs.rs/slog-atomic/0.4.3/slog_atomic/
//!
//! ## Examples & help
//!
//! Look at [slog-rs examples in `slog-misc`
//! repository](https://github.com/slog-rs/misc/tree/master/examples)
//!
//! Read [slog-rs wiki pages](https://github.com/slog-rs/slog/wiki)
//!
//! Check sources of other [software using
//! slog-rs](https://crates.io/crates/slog/reverse_dependencies)
//!
//! Visit [slog-rs gitter channel](https://gitter.im/slog-rs/slog) for immediate help.

#![cfg_attr(not(feature = "std"), feature(alloc))]
#![cfg_attr(not(feature = "std"), feature(collections))]
#![warn(missing_docs)]

#![no_std]

#[macro_use]
#[cfg(feature = "std")]
extern crate std;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate collections;

use core::str::FromStr;
use core::fmt;
use core::result;

#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(not(feature = "std"))]
use alloc::arc::Arc;

#[cfg(feature = "std")]
use std::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;

#[cfg(feature = "std")]
use std::string::String;
#[cfg(not(feature = "std"))]
use collections::string::String;

/// This type is here just to abstract away lack of `!` type support in stable
/// rust during time of the release. It will be switched to `!` at some point
/// and `Never` should not be considered "stable" API.
#[doc(hidden)]
pub type Never = ();

/// This is not part of "stable" API
#[doc(hidden)]
pub static STATIC_TERMINATOR_UNIT : () = ();

// One main namespace is enough, but for conveniance break
// the code into parts.
//
// Use include so we don't have to deal with privacy between modules.
include!("_record.rs");
include!("_macros.rs");
include!("_kv.rs");
include!("_level.rs");
include!("_logger.rs");
include!("_drain.rs");
include!("_ser.rs");
include!("_compat.rs");

#[cfg(test)]
mod tests;
<commit_msg>Tiny documentation fix<commit_after>//! # Slog -  Structured, extensible, composable logging for Rust
//!
//! ## Features
//!
//! * easy to use
//! * great performance; see: [slog bench log](https://github.com/dpc/slog-rs/wiki/Bench-log)
//! * `#![no_std]` support (with opt-out `std` cargo feature flag)
//! * hierarchical loggers
//! * lazily evaluated values
//! * modular, lightweight and very extensible
//! 	* tiny core crate that does not pull any dependencies
//! 	* feature-crates for specific functionality
//! * backward compatibility for standard `log` crate (`slog-stdlog` crate)
//! 	* supports logging-scopes
//! 	* using slog in library does not force users of the library to use slog
//! 	  (but gives benefits); see `crates/example-lib`
//! * drains & output formatting
//! 	* filtering
//! 		* compile-time log level filter using cargo features (same as in `log` crate)
//! 		* by level, msg, and any other meta-data
//! 		* [`slog-envlogger`](https://github.com/slog-rs/envlogger) - port of `env_logger`
//! 	* multiple outputs
//! 	* asynchronous IO writing
//! 	* terminal output, with color support (`slog-term` crate)
//! 	* Json (`slog-json` crate)
//! 		* Bunyan (`slog-bunyan` crate)
//! 	* syslog (`slog-syslog` crate)
//! 	* first class custom drains
//!
//! ## Advantages over `log` crate
//!
//! * **extensible** - `slog` provides core functionality, and some standard
//!   feature-set. But using traits, anyone can easily implement as
//!   powerful fully-custom features, publish separately and grow `slog` feature-set
//!   for everyone.
//! * **composable** - Wouldn't it be nice if you could use
//!   [`env_logger`][env_logger], but output authentication messages to syslog,
//!   while reporting errors over network in json format? With `slog` drains can
//!   reuse other drains! You can combine them together, chain, wrap - you name it.
//! * **context aware** - It's not just one global logger. Hierarchical
//!   loggers carry information about context of logging. When logging an error
//!   condition, you want to know which resource was being handled, on which
//!   instance of your service, using which source code build, talking with what
//!   peer, etc. In standard `log` you would have to repeat this information in
//!   every log statement. In `slog` it will happen automatically. See
//!   [slog-rs functional overview page][functional-overview] to understand better
//!   logger and drain hierarchies and log record flow through them.
//! * both **human and machine readable** - By keeping the key-value data format,
//!   meaning of logging data is preserved. Dump your logging to a JSON file, and
//!   send it to your data-mining system for further analysis. Don't parse it from
//!   lines of text anymore!
//! * **lazy evaluation** and **asynchronous IO** included. Waiting to
//!   finish writing logging information to disk, or spending time calculating
//!   data that will be thrown away at the current logging level, are sources of big
//!   performance waste. Use `AsyncStreamer` drain, and closures to make your logging fast.
//! * **run-time configuration** - [`AtomicSwitch`][atomic-switch] drain allows
//!   changing logging behavior in the running program. You could use eg. signal
//!   handlers to change logging level or logging destinations. See
//!   [`signal` example][signal].
//!
//! ## Notable details
//!
//! `slog` by default removes at compile time trace and debug level statements
//! in release builds, and trace level records in debug builds. This makes
//! `trace` and `debug` level logging records practically free, which should
//! encourage using them freely. If you want to enable trace/debug messages
//! or raise the compile time logging level limit, use the following in your
//! `Cargo.toml`:
//!
//! ```norust
//! slog = { version = "1.2", features = ["max_level_trace", "release_max_level_warn"] }
//! ```
//!
//! Due to the `macro_rules` limitation log macros syntax comes in several
//! versions. See `log!` macro, and pay attention to `;` and `,`
//! details.
//!
//! Root drain (passed to `Logger::root`) must be one that does not ever
//! return errors, which forces user to pick error handing strategy. You
//! can use `.fuse()` or `.ignore_err()` methods from `DrainExt` to do
//! it conveniently.
//!
//! [signal]: https://github.com/slog-rs/misc/blob/master/examples/signal.rs
//! [env_logger]: https://crates.io/crates/env_logger
//! [functional-overview]: https://github.com/dpc/slog-rs/wiki/Functional-overview
//! [atomic-switch]: https://docs.rs/slog-atomic/0.4.3/slog_atomic/
//!
//! ## Examples & help
//!
//! Look at [slog-rs examples in `slog-misc`
//! repository](https://github.com/slog-rs/misc/tree/master/examples)
//!
//! Read [slog-rs wiki pages](https://github.com/slog-rs/slog/wiki)
//!
//! Check sources of other [software using
//! slog-rs](https://crates.io/crates/slog/reverse_dependencies)
//!
//! Visit [slog-rs gitter channel](https://gitter.im/slog-rs/slog) for immediate help.

#![cfg_attr(not(feature = "std"), feature(alloc))]
#![cfg_attr(not(feature = "std"), feature(collections))]
#![warn(missing_docs)]

#![no_std]

#[macro_use]
#[cfg(feature = "std")]
extern crate std;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate collections;

use core::str::FromStr;
use core::fmt;
use core::result;

#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(not(feature = "std"))]
use alloc::arc::Arc;

#[cfg(feature = "std")]
use std::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;

#[cfg(feature = "std")]
use std::string::String;
#[cfg(not(feature = "std"))]
use collections::string::String;

/// This type is here just to abstract away lack of `!` type support in stable
/// rust during time of the release. It will be switched to `!` at some point
/// and `Never` should not be considered "stable" API.
#[doc(hidden)]
pub type Never = ();

/// This is not part of "stable" API
#[doc(hidden)]
pub static STATIC_TERMINATOR_UNIT : () = ();

// One main namespace is enough, but for conveniance break
// the code into parts.
//
// Use include so we don't have to deal with privacy between modules.
include!("_record.rs");
include!("_macros.rs");
include!("_kv.rs");
include!("_level.rs");
include!("_logger.rs");
include!("_drain.rs");
include!("_ser.rs");
include!("_compat.rs");

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: function that takes arbitrary input and returns whether
 *      the invariant held.
 *
 *   returns whether all the tests passed.
 */
fn quick_check<T:Arbitrary>(description : &str,
                            f : extern fn(T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t : T = Arbitrary::gen();
        if f(t.clone()) {
            passing += 1;
        } else {
            failed.push(t);
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, T)] =
                failed.iter().transform(|x| (x.size(), x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

/**
 * quick_check2
 *   description: a string describing what the property being tested is
 *   f: function that takes two arbitrary inputs and returns whether
 *      the invariant held.
 *
 *   returns whether all the tests passed.
 */
fn quick_check2<T:Arbitrary>(description : &str,
                             f : extern fn(T,T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t1 : T = Arbitrary::gen();
        let t2 : T = Arbitrary::gen();
        if f(t1.clone(), t2.clone()) {
            passing += 1;
        } else {
            failed.push((t1, t2));
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, (T,T))] =
                failed.iter().transform(|x| (x.first().size() + x.second().size(),
                                             x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy - should be unshift.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check("reversing a list twice yields the same list",
                    prop_reverse_reverse_uints));
    assert!(
        !quick_check("reversing a list moves first to last",
                     prop_reverse_moves_first_to_last));
}

#[test]
fn struct_gen() {

    #[deriving(Clone, Eq)]
    struct Foo { n: uint, xs: ~[int] }

    impl Arbitrary for Foo {
        fn gen() -> Foo {
            Foo { n: Arbitrary::gen(), xs: Arbitrary::gen() }
        }
        fn size(&self) -> uint {
            self.xs.len()
        }
    }
    // NOTE(dbp 2013-07-27): Not sure why this isn't covered by `deriving`,
    // is it a not-yet-implemented feature?
    impl Clone for Foo {
        fn clone(&self) -> Foo {
            Foo { n: self.n, xs: self.xs.clone() }
        }
    }
    impl Eq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.n == other.n && self.xs == other.xs
        }
    }

    fn add_foos(a1: &Foo, a2: &Foo) -> Foo {
        let mut new_xs = ~[];
        new_xs = vec::append(new_xs, a1.xs);
        new_xs = vec::append(new_xs, a2.xs);
        Foo {n: a1.n + a2.n, xs: new_xs}
    }

    // NOTE(dbp 2013-07-27): This is obviously not true.
    fn prop_add_foos_commutes(a1: Foo, a2: Foo) -> bool {
        add_foos(&a1, &a2) == add_foos(&a2, &a1)
    }

    fn prop_add_zero_foo_identity(a: Foo) -> bool {
        add_foos(&a, &Foo {n: 0, xs: ~[]}) == a
    }

    assert!(
        !quick_check2("add_foos is commutative",
                    prop_add_foos_commutes));

    assert!(
        quick_check("add_foos with a zero Foo is an identity",
                    prop_add_zero_foo_identity));
}<commit_msg>add Testable trait, eliminate code duplication<commit_after>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * Result is what is returned from property tests; it includes
 * representations of the generated input in the case of failure.
 */
#[deriving(Clone)]
enum Result {
    Pass,
    Failure(uint, ~str)
}

fn result_str(r : ~Result) -> ~str {
    match r {
        ~Pass => ~"",
        ~Failure(_, s) => s.clone()
    }
}

/**
 * Testable is a trait for things that can be tested. This generally means
 * functions that take arguments of trait Arbitrary.
 */
trait Testable {
    fn apply(&self) -> ~Result;
}

impl<T:Arbitrary> Testable for extern fn(T) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        if (*self)(t.clone()) {
            ~Pass
        } else {
            ~Failure(t.size(), fmt!("%?",t))
        }
    }
}

impl<T:Arbitrary, U:Arbitrary> Testable for extern fn(T,U) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        let u : U = Arbitrary::gen();
        if (*self)(t.clone(), u.clone()) {
            ~Pass
        } else {
            ~Failure(t.size() + u.size(), fmt!("%?, %?",t, u))
        }
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: a Testable (ie, function taking arguments that are Arbitrary)
 *
 *   returns whether all the tests passed.
 */
fn quick_check<F:Testable>(description : &str,
                           f : F) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        match f.apply() {
            ~Pass            => { passing += 1; }
            ~Failure(s,args) => { failed.push(~Failure(s,args)); }
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i].clone()));
                i += 1;
            }
        } else {
            sort::quick_sort(failed, |e1, e2| {
                match (e1,e2) {
                    (&~Failure(s1,_), &~Failure(s2,_)) => { s1 <= s2 }
                    _ => { fail!() }
                }
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", result_str(failed[i].clone())));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy - should be unshift.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check("reversing a list twice yields the same list",
                    prop_reverse_reverse_uints));
    assert!(
        !quick_check("reversing a list moves first to last",
                     prop_reverse_moves_first_to_last));
}

#[test]
fn struct_gen() {

    #[deriving(Clone, Eq)]
    struct Foo { n: uint, xs: ~[int] }

    impl Arbitrary for Foo {
        fn gen() -> Foo {
            Foo { n: Arbitrary::gen(), xs: Arbitrary::gen() }
        }
        fn size(&self) -> uint {
            self.xs.len()
        }
    }
    // NOTE(dbp 2013-07-27): Not sure why this isn't covered by `deriving`,
    // is it a not-yet-implemented feature?
    impl Clone for Foo {
        fn clone(&self) -> Foo {
            Foo { n: self.n, xs: self.xs.clone() }
        }
    }
    impl Eq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.n == other.n && self.xs == other.xs
        }
    }

    fn add_foos(a1: &Foo, a2: &Foo) -> Foo {
        let mut new_xs = ~[];
        new_xs = vec::append(new_xs, a1.xs);
        new_xs = vec::append(new_xs, a2.xs);
        Foo {n: a1.n + a2.n, xs: new_xs}
    }

    // NOTE(dbp 2013-07-27): This is obviously not true.
    fn prop_add_foos_commutes(a1: Foo, a2: Foo) -> bool {
        add_foos(&a1, &a2) == add_foos(&a2, &a1)
    }

    fn prop_add_zero_foo_identity(a: Foo) -> bool {
        add_foos(&a, &Foo {n: 0, xs: ~[]}) == a
    }

    assert!(
        !quick_check("add_foos is commutative",
                    prop_add_foos_commutes));

    assert!(
        quick_check("add_foos with a zero Foo is an identity",
                    prop_add_zero_foo_identity));
}<|endoftext|>


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

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Wrap<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    srgb: bool,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn does_convert_gamma(&self) -> bool {
        self.srgb
    }
}

/// Result of successful context initialization.
pub type Success = (
    Wrap<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window builder.
pub fn init<'a>(builder: glutin::WindowBuilder<'a>)
            -> Result<Success, glutin::CreationError>
{
    let (mask, srgb) = {
        let attribs = builder.get_attributes();
        let mut mask = gfx::Mask::empty();
        match attribs.color_bits {
            Some(b) if b>0 => mask.insert(gfx::COLOR),
            _ => (),
        }
        match attribs.depth_bits {
            Some(b) if b>0 => mask.insert(gfx::DEPTH),
            _ => (),
        }
        match attribs.stencil_bits {
            Some(b) if b>0 => mask.insert(gfx::STENCIL),
            _ => (),
        }
        (mask, attribs.srgb == Some(true))
    };
    // create window
    builder.build().map(|window| {
        unsafe { window.make_current() };
        let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
        let wrap = Wrap {
            window: window,
            frame: factory.get_main_frame_buffer(),
            mask: mask,
            srgb: srgb,
        };
        (wrap, device, factory)
    })
}

/// Initialize with just a title string.
pub fn init_titled(title: &str) -> Result<Success, glutin::CreationError>
{
    let builder = glutin::WindowBuilder::new()
        .with_title(title.to_string());
    init(builder)
}
<commit_msg>Setting color+depth+stencil by default<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Wrap<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    srgb: bool,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn does_convert_gamma(&self) -> bool {
        self.srgb
    }
}

/// Result of successful context initialization.
pub type Success = (
    Wrap<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window builder.
pub fn init<'a>(builder: glutin::WindowBuilder<'a>)
            -> Result<Success, glutin::CreationError>
{
    let (mask, srgb) = {
        let attribs = builder.get_attributes();
        //let mut mask = gfx::Mask::empty(); // need Glutin to really expose defaults
        let mut mask = gfx::COLOR | gfx::DEPTH | gfx::STENCIL;
        match attribs.color_bits {
            Some(b) if b>0 => mask.insert(gfx::COLOR),
            _ => (),
        }
        match attribs.depth_bits {
            Some(b) if b>0 => mask.insert(gfx::DEPTH),
            _ => (),
        }
        match attribs.stencil_bits {
            Some(b) if b>0 => mask.insert(gfx::STENCIL),
            _ => (),
        }
        (mask, attribs.srgb == Some(true))
    };
    // create window
    builder.build().map(|window| {
        unsafe { window.make_current() };
        let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
        let wrap = Wrap {
            window: window,
            frame: factory.get_main_frame_buffer(),
            mask: mask,
            srgb: srgb,
        };
        (wrap, device, factory)
    })
}

/// Initialize with just a title string.
pub fn init_titled(title: &str) -> Result<Success, glutin::CreationError>
{
    let builder = glutin::WindowBuilder::new()
        .with_title(title.to_string());
    init(builder)
}
<|endoftext|>


<commit_before>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, target: Rc<RefCell<Node>>) -> Result<(), String> {
        if child.borrow().id == target.borrow().id {
            return Err("Cannot make node a child of itself.".to_string());
        }
        if  !Node::is_child_of(target.clone(), child.clone()) { // check for cycles
            match child.borrow().parent() {
                Some(old_parent) => {
                    old_parent.borrow_mut().remove_child(child.clone());
                },
                None => {}
            }
            child.borrow_mut().parent = Some(Rc::downgrade(&target.clone()));
            target.borrow_mut().add_child(child.clone());
            Ok(())
        } else {
            Err("Node cycle detected. Child is a parent of reparent target.".to_string()) // format for better debug msg
        }
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn siblings(&self) -> Option<&Vec<Rc<RefCell<Node>>>> {
        match self.parent() {
            Some(p) => {
                Some(&p.borrow().children)
            },
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    let result = Node::reparent(im.clone(), root2.clone());

    assert!( result.is_ok() );
    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}

#[test]
fn fails_to_reparent_to_self() {
    let root = Node::create(0, None);
    let result = Node::reparent(root.clone(), root.clone());
    assert!( result.is_err() );
}

#[test]
fn fails_to_reparent_causing_a_cycle() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let sibling = Node::create(2, Some(root.clone()));

    let result = Node::reparent(root.clone(), sibling.clone());
    assert!( result.is_err() );
}
<commit_msg>impl siblings call<commit_after>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, target: Rc<RefCell<Node>>) -> Result<(), String> {
        if child.borrow().id == target.borrow().id {
            return Err("Cannot make node a child of itself.".to_string());
        }
        if  !Node::is_child_of(target.clone(), child.clone()) { // check for cycles
            match child.borrow().parent() {
                Some(old_parent) => {
                    old_parent.borrow_mut().remove_child(child.clone());
                },
                None => {}
            }
            child.borrow_mut().parent = Some(Rc::downgrade(&target.clone()));
            target.borrow_mut().add_child(child.clone());
            Ok(())
        } else {
            Err("Node cycle detected. Child is a parent of reparent target.".to_string()) // format for better debug msg
        }
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn siblings(&self) -> Option<Vec<Rc<RefCell<Node>>>> {
        match self.parent() {
            Some(p) => {
                Some(
                    p.borrow().children.iter()
                    .filter(|x| x.borrow().id != self.id)
                    .map(|x| x.clone())
                    .collect()
                )
            },
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    let result = Node::reparent(im.clone(), root2.clone());

    assert!( result.is_ok() );
    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}

#[test]
fn fails_to_reparent_to_self() {
    let root = Node::create(0, None);
    let result = Node::reparent(root.clone(), root.clone());
    assert!( result.is_err() );
}

#[test]
fn fails_to_reparent_causing_a_cycle() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let sibling = Node::create(2, Some(root.clone()));

    let result = Node::reparent(root.clone(), sibling.clone());
    assert!( result.is_err() );
}

#[test]
fn siblings_as_expected() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let sibling = Node::create(2, Some(root.clone()));

    let maybe_siblings = child.borrow().siblings();
    let siblings = maybe_siblings.unwrap();
    assert!( siblings.len() == 1 );
    assert!( sibling.borrow().id == siblings[0].borrow().id );
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    0
}

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

}
<commit_msg>screen struct with new fn<commit_after>
pub fn puzzle(input: &str) -> u32 {
    0
}

#[derive(Debug, PartialEq)]
pub struct Screen {
    display: Vec<Vec<char>>,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        Screen {
            display: vec![vec!['.'; width]; height],
        }
    }
}

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

    #[test]
    fn new_screen(){
        let s = Screen::new(1, 2);
        assert_eq!(s, Screen {
            display: vec![vec!['.'], vec!['.']],
        });
    }

}
<|endoftext|>


<commit_before>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//! // Produces a compilation failure:
//! // assert_eq_size!(u32, u8);
//! # }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//! const_assert_eq!(NUM + NUM, 64);
//!
//! const TWO: usize = 2;
//! const_assert_eq!(TWO * TWO, TWO + TWO, 4);
//! # }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, [`assert_eq_size`], [`const_assert`], and
//! [`const_assert_eq`] can only be used from within the context of a function.
//!
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// # fn main() {
/// assert_eq_size!(Byte, u8);
///
/// // Supports unlimited arguments:
/// assert_eq_size!([Byte; 4], [u16; 2], u32);
///
/// // Fails to compile:
/// // assert_eq_size!(Byte, u16);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read(&$x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read(&$xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Fails to compile:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($cond:expr) => {
        // Causes overflow if condition is false
        let _ = [(); 0 - (!($cond) as usize)];
    };
    ($($xs:expr),+) => {
        const_assert!($($xs)&&+);
    };
    ($($xs:expr);+ $(;)*) => {
        const_assert!($($xs),+);
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    }
}
<commit_msg>Create assert_eq_size_ptr macro<commit_after>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//! // Produces a compilation failure:
//! // assert_eq_size!(u32, u8);
//! # }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//! const_assert_eq!(NUM + NUM, 64);
//!
//! const TWO: usize = 2;
//! const_assert_eq!(TWO * TWO, TWO + TWO, 4);
//! # }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, [`assert_eq_size`], [`const_assert`], and
//! [`const_assert_eq`] can only be used from within the context of a function.
//!
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// # fn main() {
/// assert_eq_size!(Byte, u8);
///
/// // Supports unlimited arguments:
/// assert_eq_size!([Byte; 4], [u16; 2], u32);
///
/// // Fails to compile:
/// // assert_eq_size!(Byte, u16);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    }
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Fails to compile:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($cond:expr) => {
        // Causes overflow if condition is false
        let _ = [(); 0 - (!($cond) as usize)];
    };
    ($($xs:expr),+) => {
        const_assert!($($xs)&&+);
    };
    ($($xs:expr);+ $(;)*) => {
        const_assert!($($xs),+);
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    }
}
<|endoftext|>


<commit_before>//! # quicksort
//!
//! Quicksort is an efficient in-place sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;

/// In-place sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

/// In-place sorting of a slice of T using a custom comparison function.
///
/// ```rust
/// # use ironsort::quicksort_by;
/// # use std::cmp::Ordering;
///
/// let presorted: Vec<u64> = vec![9, 6, 5, 5, 4, 3, 3, 2, 1, 1];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
///
/// quicksort_by(&mut vector, &|x, y| x.cmp(y).reverse());
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
pub fn quicksort_by<T, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {

    let len: usize = vec.len();
    if len <= 1 {
        return;
    }

    let pivot: usize = 0;
    vec.swap(pivot, len / 2);

    let mut left: usize = 0;
    let mut right: usize = vec.len() - 1;

    while left < right {
        while left < len && cmp(&vec[left], &vec[pivot]) != Ordering::Greater {
            left += 1
        }
        while cmp(&vec[right], &vec[pivot]) == Ordering::Greater {
            right -= 1
        }

        if left < right {
            vec.swap(left, right);
        }
    }

    vec.swap(pivot, right);
    quicksort_by(&mut vec[0..right], cmp);
    quicksort_by(&mut vec[right+1..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }

    #[test]
    fn test_long_zeroes() {
        let mut vector = vec![0;10000];
        quicksort(&mut vector);
        for i in 0 .. vector.len() - 1 {
            assert!(vector[i] <= vector[i + 1])
        }
    }
}
<commit_msg>fix quicksort_by to be more efficient when dealing with array of all equal elements (also more efficient when the pivot element is repeated many times in the array)<commit_after>//! # quicksort
//!
//! Quicksort is an efficient in-place sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;
use std::cmp;

/// In-place sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

/// In-place sorting of a slice of T using a custom comparison function.
///
/// ```rust
/// # use ironsort::quicksort_by;
/// # use std::cmp::Ordering;
///
/// let presorted: Vec<u64> = vec![9, 6, 5, 5, 4, 3, 3, 2, 1, 1];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
///
/// quicksort_by(&mut vector, &|x, y| x.cmp(y).reverse());
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
pub fn quicksort_by<T, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {

    let len: usize = vec.len();
    if len <= 1 {
        return;
    }

    let pivot: usize = 0;
    vec.swap(pivot, len / 2);

    let mut left: usize = 1;
    let mut right: usize = vec.len() - 1;

    loop {
        while left < len && cmp(&vec[left], &vec[pivot]) != Ordering::Greater {
            left += 1
        }
        while right > 0 && cmp(&vec[right], &vec[pivot]) != Ordering::Less {
            right -= 1
        }
        if left >= right {
            break;
        }
        vec.swap(left, right);
        left += 1;
        right -= 1;
    }
    vec.swap(pivot, right);
    quicksort_by(&mut vec[0..cmp::min(left - 1, right)], cmp);
    quicksort_by(&mut vec[cmp::max(left, right + 1)..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }

    #[test]
    fn test_long_zeroes() {
        let mut vector = vec![0;10000];
        quicksort(&mut vector);
        for i in 0 .. vector.len() - 1 {
            assert!(vector[i] <= vector[i + 1])
        }
    }
}
<|endoftext|>


<commit_before>//! # Packet parsing for the Internet Protocol Suite
//!
//! ## Example usage
//! ```
//! use peel_ip::PeelIp;
//!
//! let mut peel = PeelIp::new();
//! let mut input = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00];
//! let result = peel.traverse(&input, vec![]).unwrap();
//! assert_eq!(result.len(), 1);
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate nom;
extern crate peel;
extern crate path;

#[macro_use]
pub mod memcmp;

pub mod layer1;
pub mod layer2;
pub mod layer3;
pub mod layer4;

use prelude::*;

/// Provides sensible imports for packet parsers
pub mod prelude {
    pub use std::fmt;
    pub use std::str::{self, FromStr};
    pub use std::net::{Ipv4Addr, Ipv6Addr};
    pub use nom::*;
    pub use peel::prelude::*;

    pub use super::{Layer, ParserVariant, PeelIp};

    /// A shorthand for the packet parsing arena
    pub type ProtocolGraph = ParserGraph<Layer, ParserVariant>;

    /// Link
    pub use layer1::*;
    pub use layer1::ethernet::*;

    /// Internet
    pub use layer2::*;
    pub use layer2::ipv4::*;
    pub use layer2::ipv6::*;

    // Transport
    pub use layer3::*;
    pub use layer3::tcp::*;
    pub use layer3::tls::*;
    pub use layer3::udp::*;

    // Application
    pub use layer4::http::*;
    pub use layer4::ntp::*;
}

#[derive(Debug)]
/// The return value for the variant retrieval of the Parser trait
pub enum ParserVariant {
    /// Ethernet protocol parser
    Ethernet(EthernetParser),

    /// Internet Protocol version 4 parser
    Ipv4(Ipv4Parser),

    /// Internet Protocol version 6 parser
    Ipv6(Ipv6Parser),

    /// Transmission Control Protocol parser
    Tcp(TcpParser),

    /// Transport Layer Security parser
    Tls(TlsParser),

    /// Hypertext Transfer Protocol parser
    Http(HttpParser),

    /// User Datagram Protocol parser
    Udp(UdpParser),

    /// Network Time Protocol parser
    Ntp(NtpParser),
}

#[derive(Debug, Eq, PartialEq)]
/// Return values for the actual parsers
pub enum Layer {
    /// Ethernet protocol for layer 1
    Ethernet(EthernetPacket),

    /// Internet Protocol version 4 packet variant
    Ipv4(Ipv4Packet),

    /// Internet Protocol version 6 packet variant
    Ipv6(Ipv6Packet),

    /// Transmission Control Protocol packet variant
    Tcp(TcpPacket),

    /// Transport Layer Security packet variant
    Tls(TlsPacket),

    /// Hypertext Transfer Protocol packet variant
    Http(HttpPacket),

    /// User Datagram Protocol packet variant
    Udp(UdpPacket),

    /// Network Time Protocol packet variant
    Ntp(NtpPacket),
}

macro_rules! impl_fmt_display {
    ($name: ident) => {
        impl fmt::Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $name::Ethernet(_) => write!(f, "Ethernet"),
                    $name::Ipv4(_) => write!(f, "IPv4"),
                    $name::Ipv6(_) => write!(f, "IPv6"),
                    $name::Tcp(_) => write!(f, "TCP"),
                    $name::Tls(_) => write!(f, "TLS"),
                    $name::Http(_) => write!(f, "HTTP"),
                    $name::Udp(_) => write!(f, "UDP"),
                    $name::Ntp(_) => write!(f, "NTP"),
                }
            }
        }
    }
}

impl_fmt_display!(Layer);
impl_fmt_display!(ParserVariant);

/// Peel for TCP/IP packets
pub struct PeelIp;

impl PeelIp {
    /// Creates a new `Peel` structure for TCP/IP based packet parsing
    pub fn new() -> Peel<Layer, ParserVariant> {
        // Create a tree
        let mut p = Peel::new();

        // Ethernet
        let eth = p.new_parser(EthernetParser);

        // IPv4/6
        let ipv4 = p.link_new_parser(eth, Ipv4Parser);
        let ipv6 = p.link_new_parser(eth, Ipv6Parser);
        p.link(ipv4, ipv6);
        p.link(ipv4, ipv4);
        p.link(ipv6, ipv6);

        // TCP
        let tcp = p.new_parser(TcpParser);
        p.link(ipv4, tcp);
        p.link(ipv6, tcp);

        // UDP
        let udp = p.new_parser(UdpParser);
        p.link(ipv4, udp);
        p.link(ipv6, udp);

        // TLS
        let tls = p.new_parser(TlsParser);
        p.link(tcp, tls);

        // HTTP
        let http = p.new_parser(HttpParser);
        p.link(tcp, http);
        p.link(tls, http);

        // NTP
        let ntp = p.new_parser(NtpParser);
        p.link(udp, ntp);

        p
    }
}
<commit_msg>Fixed mut in example<commit_after>//! # Packet parsing for the Internet Protocol Suite
//!
//! ## Example usage
//! ```
//! use peel_ip::PeelIp;
//!
//! let peel = PeelIp::new();
//! let input = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0];
//! let result = peel.traverse(&input, vec![]).unwrap();
//! assert_eq!(result.len(), 1);
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate nom;
extern crate peel;
extern crate path;

#[macro_use]
pub mod memcmp;

pub mod layer1;
pub mod layer2;
pub mod layer3;
pub mod layer4;

use prelude::*;

/// Provides sensible imports for packet parsers
pub mod prelude {
    pub use std::fmt;
    pub use std::str::{self, FromStr};
    pub use std::net::{Ipv4Addr, Ipv6Addr};
    pub use nom::*;
    pub use peel::prelude::*;

    pub use super::{Layer, ParserVariant, PeelIp};

    /// A shorthand for the packet parsing arena
    pub type ProtocolGraph = ParserGraph<Layer, ParserVariant>;

    /// Link
    pub use layer1::*;
    pub use layer1::ethernet::*;

    /// Internet
    pub use layer2::*;
    pub use layer2::ipv4::*;
    pub use layer2::ipv6::*;

    // Transport
    pub use layer3::*;
    pub use layer3::tcp::*;
    pub use layer3::tls::*;
    pub use layer3::udp::*;

    // Application
    pub use layer4::http::*;
    pub use layer4::ntp::*;
}

#[derive(Debug)]
/// The return value for the variant retrieval of the Parser trait
pub enum ParserVariant {
    /// Ethernet protocol parser
    Ethernet(EthernetParser),

    /// Internet Protocol version 4 parser
    Ipv4(Ipv4Parser),

    /// Internet Protocol version 6 parser
    Ipv6(Ipv6Parser),

    /// Transmission Control Protocol parser
    Tcp(TcpParser),

    /// Transport Layer Security parser
    Tls(TlsParser),

    /// Hypertext Transfer Protocol parser
    Http(HttpParser),

    /// User Datagram Protocol parser
    Udp(UdpParser),

    /// Network Time Protocol parser
    Ntp(NtpParser),
}

#[derive(Debug, Eq, PartialEq)]
/// Return values for the actual parsers
pub enum Layer {
    /// Ethernet protocol for layer 1
    Ethernet(EthernetPacket),

    /// Internet Protocol version 4 packet variant
    Ipv4(Ipv4Packet),

    /// Internet Protocol version 6 packet variant
    Ipv6(Ipv6Packet),

    /// Transmission Control Protocol packet variant
    Tcp(TcpPacket),

    /// Transport Layer Security packet variant
    Tls(TlsPacket),

    /// Hypertext Transfer Protocol packet variant
    Http(HttpPacket),

    /// User Datagram Protocol packet variant
    Udp(UdpPacket),

    /// Network Time Protocol packet variant
    Ntp(NtpPacket),
}

macro_rules! impl_fmt_display {
    ($name: ident) => {
        impl fmt::Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $name::Ethernet(_) => write!(f, "Ethernet"),
                    $name::Ipv4(_) => write!(f, "IPv4"),
                    $name::Ipv6(_) => write!(f, "IPv6"),
                    $name::Tcp(_) => write!(f, "TCP"),
                    $name::Tls(_) => write!(f, "TLS"),
                    $name::Http(_) => write!(f, "HTTP"),
                    $name::Udp(_) => write!(f, "UDP"),
                    $name::Ntp(_) => write!(f, "NTP"),
                }
            }
        }
    }
}

impl_fmt_display!(Layer);
impl_fmt_display!(ParserVariant);

/// Peel for TCP/IP packets
pub struct PeelIp;

impl PeelIp {
    /// Creates a new `Peel` structure for TCP/IP based packet parsing
    pub fn new() -> Peel<Layer, ParserVariant> {
        // Create a tree
        let mut p = Peel::new();

        // Ethernet
        let eth = p.new_parser(EthernetParser);

        // IPv4/6
        let ipv4 = p.link_new_parser(eth, Ipv4Parser);
        let ipv6 = p.link_new_parser(eth, Ipv6Parser);
        p.link(ipv4, ipv6);
        p.link(ipv4, ipv4);
        p.link(ipv6, ipv6);

        // TCP
        let tcp = p.new_parser(TcpParser);
        p.link(ipv4, tcp);
        p.link(ipv6, tcp);

        // UDP
        let udp = p.new_parser(UdpParser);
        p.link(ipv4, udp);
        p.link(ipv6, udp);

        // TLS
        let tls = p.new_parser(TlsParser);
        p.link(tcp, tls);

        // HTTP
        let http = p.new_parser(HttpParser);
        p.link(tcp, http);
        p.link(tls, http);

        // NTP
        let ntp = p.new_parser(NtpParser);
        p.link(udp, ntp);

        p
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "js"]
#![crate_type = "rlib"]

#![feature(core_intrinsics)]
#![feature(filling_drop)]
#![feature(link_args)]
#![feature(unsafe_no_drop_flag)]
#![feature(const_fn)]

#![allow(drop_with_repr_extern)]
#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes)]

#[macro_use]
extern crate heapsize;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mozjs_sys;
extern crate num_traits;
extern crate rustc_serialize as serialize;

pub mod jsapi {
    use libc::FILE;

    #[repr(C)]
    #[unsafe_no_drop_flag]
    #[derive(Debug)]
    pub struct Heap<T: ::rust::GCMethods<T> + Copy> {
        pub ptr: ::std::cell::UnsafeCell<T>,
    }

    unsafe impl Sync for JSClass {}

    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_linux_64.rs");

    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_linux_64_debug.rs");

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_macos_64.rs");

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_macos_64_debug.rs");

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_windows_gcc_64.rs");

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_windows_gcc_64_debug.rs");

    #[cfg(any(target_os = "linux", target_os = "android"))]
    #[cfg(target_pointer_width = "32")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_linux_32.rs");

    #[cfg(any(target_os = "linux", target_os = "android"))]
    #[cfg(target_pointer_width = "32")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_linux_32_debug.rs");
}

mod consts;
pub mod conversions;
pub mod error;
pub mod glue;
pub mod jsval;
pub mod rust;

pub use consts::*;

use heapsize::HeapSizeOf;
use jsapi::{JSContext, Heap};
use jsval::JSVal;
use rust::GCMethods;

#[inline(always)]
pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal {
    vp.offset(2)
}

#[inline(always)]
pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal {
    *vp
}

// This is measured properly by the heap measurement implemented in SpiderMonkey.
impl<T: Copy + GCMethods<T>> HeapSizeOf for Heap<T> {
    fn heap_size_of_children(&self) -> usize {
        0
    }
}
known_heap_size!(0, JSVal);

<commit_msg>Implement jsapi::ObjectOpResult::succeed.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "js"]
#![crate_type = "rlib"]

#![feature(core_intrinsics)]
#![feature(filling_drop)]
#![feature(link_args)]
#![feature(unsafe_no_drop_flag)]
#![feature(const_fn)]

#![allow(drop_with_repr_extern)]
#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes)]

#[macro_use]
extern crate heapsize;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mozjs_sys;
extern crate num_traits;
extern crate rustc_serialize as serialize;

pub mod jsapi {
    use libc::FILE;

    #[repr(C)]
    #[unsafe_no_drop_flag]
    #[derive(Debug)]
    pub struct Heap<T: ::rust::GCMethods<T> + Copy> {
        pub ptr: ::std::cell::UnsafeCell<T>,
    }

    unsafe impl Sync for JSClass {}

    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_linux_64.rs");

    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_linux_64_debug.rs");

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_macos_64.rs");

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_macos_64_debug.rs");

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_windows_gcc_64.rs");

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_windows_gcc_64_debug.rs");

    #[cfg(any(target_os = "linux", target_os = "android"))]
    #[cfg(target_pointer_width = "32")]
    #[cfg(not(feature = "debugmozjs"))]
    include!("jsapi_linux_32.rs");

    #[cfg(any(target_os = "linux", target_os = "android"))]
    #[cfg(target_pointer_width = "32")]
    #[cfg(feature = "debugmozjs")]
    include!("jsapi_linux_32_debug.rs");
}

mod consts;
pub mod conversions;
pub mod error;
pub mod glue;
pub mod jsval;
pub mod rust;

pub use consts::*;

use heapsize::HeapSizeOf;
use jsapi::{JSContext, Heap};
use jsval::JSVal;
use rust::GCMethods;

#[inline(always)]
pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal {
    vp.offset(2)
}

#[inline(always)]
pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal {
    *vp
}

// This is measured properly by the heap measurement implemented in SpiderMonkey.
impl<T: Copy + GCMethods<T>> HeapSizeOf for Heap<T> {
    fn heap_size_of_children(&self) -> usize {
        0
    }
}
known_heap_size!(0, JSVal);

impl jsapi::ObjectOpResult {
    /// Set this ObjectOpResult to true and return true.
    pub fn succeed(&mut self) -> bool {
        self.code_ = jsapi::ObjectOpResult_SpecialCodes::OkCode as usize;
        true
    }
}
<|endoftext|>