<commit_before>//! # Feature flags
//!
//! This crate exposes a number of features. These can be enabled or disabled as shown
//! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features
//! are _disabled_ by default unless otherwise noted.
//!
//! Reliance on a given feature is always indicated alongside the item definition.
//!
//! - `std` (_enabled by default, implicitly enables `alloc`_)
//!
//!   This enables a number of features that depend on the standard library. [`Instant`] is the
//!   primary item that requires this feature, though some   others methods may rely on [`Instant`]
//!   internally.
//!
//! - `alloc` (_enabled by default via `std`_)
//!
//!   Enables a number of features that require the ability to dynamically allocate memory.
//!
//! - `macros`
//!
//!   Enables macros that provide compile-time verification of values and intuitive syntax.
//!
//! - `formatting` (_implicitly enables `std`_)
//!
//!   Enables formatting of most structs.
//!
//! - `parsing`
//!
//!   Enables parsing of most structs.
//!
//! - `local-offset` (_implicitly enables `std`_)
//!
//!   This feature enables a number of methods that allow obtaining the system's UTC offset.
//!
//! - `large-dates`
//!
//!   By default, only years within the ±9999 range (inclusive) are supported. If you need support
//!   for years outside this range, consider enabling this feature; the supported range will be
//!   increased to ±999,999.
//!
//!   Note that enabling this feature has some costs, as it means forgoing some optimizations.
//!   Ambiguities may be introduced when parsing that would not otherwise exist.
//!
//!   If you are using this feature, **please leave a comment**
//!   [on this discussion](https://github.com/time-rs/time/discussions/306) with your use case. If
//!   there is not sufficient demand for this feature, it will be dropped in a future release.
//!
//! - `serde`
//!
//!   Enables [serde](https://docs.rs/serde) support for all types.
//!
//! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_)
//!
//!   Allows serde representations to use a human-readable format. This is determined by the
//!   serializer, not the user. If this feature is not enabled or if the serializer requests a
//!   non-human-readable format, a format optimized for binary representation will be used.
//!
//! - `rand`
//!
//!   Enables [rand](https://docs.rs/rand) support for all types.
//!
//! - `quickcheck` (_implicitly enables `alloc`_)
//!
//!   Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`].
//!
//! One pseudo-feature flag that is only available to end users is the `unsound_local_offset` cfg.
//! As the name indicates, using the feature is unsound, and [may cause unexpected segmentation
//! faults](https://github.com/time-rs/time/issues/293). Unlike other flags, this is deliberately
//! only available to end users; this is to ensure that a user doesn't have unsound behavior without
//! knowing it. To enable this behavior, you must use `RUSTFLAGS="--cfg unsound_local_offset" cargo
//! build` or similar. Note: This flag is _not tested anywhere_, including in the regular test of
//! the powerset of all feature flags. Use at your own risk.

#![cfg_attr(__time_03_docs, feature(doc_cfg))]
#![cfg_attr(
    __time_03_docs,
    deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
    anonymous_parameters,
    clippy::all,
    const_err,
    illegal_floating_point_literal_pattern,
    late_bound_lifetime_arguments,
    path_statements,
    patterns_in_fns_without_body,
    rust_2018_idioms,
    trivial_casts,
    trivial_numeric_casts,
    unreachable_pub,
    unsafe_code,
    unused_extern_crates
)]
#![warn(
    clippy::dbg_macro,
    clippy::decimal_literal_representation,
    clippy::get_unwrap,
    clippy::missing_docs_in_private_items,
    clippy::nursery,
    clippy::pedantic,
    clippy::print_stdout,
    clippy::todo,
    clippy::unimplemented,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    missing_copy_implementations,
    missing_debug_implementations,
    unused_qualifications,
    variant_size_differences
)]
#![allow(
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::enum_glob_use,
    clippy::map_err_ignore,
    clippy::missing_errors_doc,
    clippy::must_use_candidate,
    clippy::redundant_pub_crate
)]
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(test(attr(deny(warnings))))]

#[allow(unused_extern_crates)]
#[cfg(feature = "alloc")]
extern crate alloc;

// region: macros
/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;

        let (_quotient, _remainder) = (_a / _b, _a % _b);

        if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
            _quotient - 1
        } else {
            _quotient
        }
    }};
}

/// Euclidean remainder. Useful for `const` contexts.
macro_rules! rem_euclid {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;
        let r = _a % _b;
        if r < 0 {
            if _b < 0 { r - _b } else { r + _b }
        } else {
            r
        }
    }};
}

/// Cascade an out-of-bounds value.
macro_rules! cascade {
    (@discard_if_underscore(_); $($x:tt)*) => {};
    (@discard_if_underscore($i:ident); $($x:tt)*) => { $($x)* };
    (@discard_if_not_mut(mut); $($x:tt)*) => {};
    (@discard_if_not_mut(); $($x:tt)*) => { $($x)* };
    (@ordinal) => {};
    (@year) => {};

    // Cascade an out-of-bounds value from "from" to "to".
    ($(!$from_not_mut:ident)? $from:ident in $min:literal.. $max:literal => $to:tt) => {
        #[allow(unused_comparisons)]
        if $from >= $max {
            cascade!(@discard_if_not_mut($($from_not_mut)?); $from -= $max - $min);
            cascade!(@discard_if_underscore($to); $to += 1);
        } else if $from < $min {
            cascade!(@discard_if_not_mut($($from_not_mut)?); $from += $max - $min);
            cascade!(@discard_if_underscore($to); $to -= 1);
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($(!$ordinal_not_mut:ident)? $ordinal:ident => $(!$year_not_mut:ident)? $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@$ordinal);
        cascade!(@$year);
        if $ordinal > crate::util::days_in_year($year) {
            cascade!(@discard_if_not_mut($($year_not_mut)?); $year += 1);
            cascade!(@discard_if_not_mut($($ordinal_not_mut)?); $ordinal = 1);
        } else if $ordinal == 0 {
            cascade!(@discard_if_not_mut($($year_not_mut)?); $year -= 1);
            cascade!(@discard_if_not_mut($($ordinal_not_mut)?);
                $ordinal = crate::util::days_in_year($year)
            );
        }
    };
}

/// Returns `Err(error::ComponentRange)` if the value is not in range.
macro_rules! ensure_value_in_range {
    ($value:ident in $start:expr => $end:expr) => {
        #[allow(clippy::manual_range_contains)] // rust-lang/rust-clippy#6373
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < $start || $value > $end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: $start as _,
                maximum: $end as _,
                value: $value as _,
                conditional_range: false,
            });
        }
    };

    ($value:ident conditionally in $start:expr => $end:expr) => {
        #[allow(clippy::manual_range_contains)] // rust-lang/rust-clippy#6373
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < $start || $value > $end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: $start as _,
                maximum: $end as _,
                value: $value as _,
                conditional_range: true,
            });
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
/// usable in `const` contexts.
macro_rules! const_try {
    ($e:expr) => {
        match $e {
            Ok(value) => value,
            Err(error) => return Err(error),
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
    ($e:expr) => {
        match $e {
            Some(value) => value,
            None => return None,
        }
    };
}
// endregion macros

/// The [`Date`] struct and its associated `impl`s.
mod date;
/// The [`Duration`] struct and its associated `impl`s.
mod duration;
/// Various error types returned by methods in the time crate.
pub mod error;
/// Extension traits.
pub mod ext;
#[cfg(any(feature = "formatting", feature = "parsing"))]
#[cfg_attr(
    __time_03_docs,
    doc(cfg(any(feature = "formatting", feature = "parsing")))
)]
pub mod format_description;
#[cfg(feature = "formatting")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "formatting")))]
mod formatting;
/// The [`Instant`] struct and its associated `impl`s.
#[cfg(feature = "std")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "std")))]
mod instant;
/// Macros to construct statically known values.
#[cfg(feature = "macros")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "macros")))]
pub mod macros;
/// The [`OffsetDateTime`] struct and its associated `impl`s.
mod offset_date_time;
#[cfg(feature = "parsing")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))]
pub mod parsing;
/// The [`PrimitiveDateTime`] struct and its associated `impl`s.
mod primitive_date_time;
#[cfg(feature = "quickcheck")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "quickcheck")))]
mod quickcheck;
#[cfg(feature = "rand")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
mod rand;
#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
#[cfg(test)]
mod tests;
/// The [`Time`] struct and its associated `impl`s.
mod time;
/// The [`UtcOffset`] struct and its associated `impl`s.
mod utc_offset;
pub mod util;
/// Days of the week.
mod weekday;

pub use crate::date::Date;
pub use crate::duration::Duration;
pub use crate::error::Error;
#[cfg(feature = "std")]
pub use crate::instant::Instant;
pub use crate::offset_date_time::OffsetDateTime;
pub use crate::primitive_date_time::PrimitiveDateTime;
pub use crate::time::Time;
pub use crate::utc_offset::UtcOffset;
pub use crate::weekday::Weekday;

/// An alias for [`std::result::Result`] with a generic error from the time crate.
pub type Result<T> = core::result::Result<T, Error>;
<commit_msg>Add button to run examples in playground<commit_after>//! # Feature flags
//!
//! This crate exposes a number of features. These can be enabled or disabled as shown
//! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features
//! are _disabled_ by default unless otherwise noted.
//!
//! Reliance on a given feature is always indicated alongside the item definition.
//!
//! - `std` (_enabled by default, implicitly enables `alloc`_)
//!
//!   This enables a number of features that depend on the standard library. [`Instant`] is the
//!   primary item that requires this feature, though some   others methods may rely on [`Instant`]
//!   internally.
//!
//! - `alloc` (_enabled by default via `std`_)
//!
//!   Enables a number of features that require the ability to dynamically allocate memory.
//!
//! - `macros`
//!
//!   Enables macros that provide compile-time verification of values and intuitive syntax.
//!
//! - `formatting` (_implicitly enables `std`_)
//!
//!   Enables formatting of most structs.
//!
//! - `parsing`
//!
//!   Enables parsing of most structs.
//!
//! - `local-offset` (_implicitly enables `std`_)
//!
//!   This feature enables a number of methods that allow obtaining the system's UTC offset.
//!
//! - `large-dates`
//!
//!   By default, only years within the ±9999 range (inclusive) are supported. If you need support
//!   for years outside this range, consider enabling this feature; the supported range will be
//!   increased to ±999,999.
//!
//!   Note that enabling this feature has some costs, as it means forgoing some optimizations.
//!   Ambiguities may be introduced when parsing that would not otherwise exist.
//!
//!   If you are using this feature, **please leave a comment**
//!   [on this discussion](https://github.com/time-rs/time/discussions/306) with your use case. If
//!   there is not sufficient demand for this feature, it will be dropped in a future release.
//!
//! - `serde`
//!
//!   Enables [serde](https://docs.rs/serde) support for all types.
//!
//! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_)
//!
//!   Allows serde representations to use a human-readable format. This is determined by the
//!   serializer, not the user. If this feature is not enabled or if the serializer requests a
//!   non-human-readable format, a format optimized for binary representation will be used.
//!
//! - `rand`
//!
//!   Enables [rand](https://docs.rs/rand) support for all types.
//!
//! - `quickcheck` (_implicitly enables `alloc`_)
//!
//!   Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`].
//!
//! One pseudo-feature flag that is only available to end users is the `unsound_local_offset` cfg.
//! As the name indicates, using the feature is unsound, and [may cause unexpected segmentation
//! faults](https://github.com/time-rs/time/issues/293). Unlike other flags, this is deliberately
//! only available to end users; this is to ensure that a user doesn't have unsound behavior without
//! knowing it. To enable this behavior, you must use `RUSTFLAGS="--cfg unsound_local_offset" cargo
//! build` or similar. Note: This flag is _not tested anywhere_, including in the regular test of
//! the powerset of all feature flags. Use at your own risk.

#![doc(html_playground_url = "https://play.rust-lang.org")]
#![cfg_attr(__time_03_docs, feature(doc_cfg))]
#![cfg_attr(
    __time_03_docs,
    deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
    anonymous_parameters,
    clippy::all,
    const_err,
    illegal_floating_point_literal_pattern,
    late_bound_lifetime_arguments,
    path_statements,
    patterns_in_fns_without_body,
    rust_2018_idioms,
    trivial_casts,
    trivial_numeric_casts,
    unreachable_pub,
    unsafe_code,
    unused_extern_crates
)]
#![warn(
    clippy::dbg_macro,
    clippy::decimal_literal_representation,
    clippy::get_unwrap,
    clippy::missing_docs_in_private_items,
    clippy::nursery,
    clippy::pedantic,
    clippy::print_stdout,
    clippy::todo,
    clippy::unimplemented,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    missing_copy_implementations,
    missing_debug_implementations,
    unused_qualifications,
    variant_size_differences
)]
#![allow(
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::enum_glob_use,
    clippy::map_err_ignore,
    clippy::missing_errors_doc,
    clippy::must_use_candidate,
    clippy::redundant_pub_crate
)]
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(test(attr(deny(warnings))))]

#[allow(unused_extern_crates)]
#[cfg(feature = "alloc")]
extern crate alloc;

// region: macros
/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;

        let (_quotient, _remainder) = (_a / _b, _a % _b);

        if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
            _quotient - 1
        } else {
            _quotient
        }
    }};
}

/// Euclidean remainder. Useful for `const` contexts.
macro_rules! rem_euclid {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;
        let r = _a % _b;
        if r < 0 {
            if _b < 0 { r - _b } else { r + _b }
        } else {
            r
        }
    }};
}

/// Cascade an out-of-bounds value.
macro_rules! cascade {
    (@discard_if_underscore(_); $($x:tt)*) => {};
    (@discard_if_underscore($i:ident); $($x:tt)*) => { $($x)* };
    (@discard_if_not_mut(mut); $($x:tt)*) => {};
    (@discard_if_not_mut(); $($x:tt)*) => { $($x)* };
    (@ordinal) => {};
    (@year) => {};

    // Cascade an out-of-bounds value from "from" to "to".
    ($(!$from_not_mut:ident)? $from:ident in $min:literal.. $max:literal => $to:tt) => {
        #[allow(unused_comparisons)]
        if $from >= $max {
            cascade!(@discard_if_not_mut($($from_not_mut)?); $from -= $max - $min);
            cascade!(@discard_if_underscore($to); $to += 1);
        } else if $from < $min {
            cascade!(@discard_if_not_mut($($from_not_mut)?); $from += $max - $min);
            cascade!(@discard_if_underscore($to); $to -= 1);
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($(!$ordinal_not_mut:ident)? $ordinal:ident => $(!$year_not_mut:ident)? $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@$ordinal);
        cascade!(@$year);
        if $ordinal > crate::util::days_in_year($year) {
            cascade!(@discard_if_not_mut($($year_not_mut)?); $year += 1);
            cascade!(@discard_if_not_mut($($ordinal_not_mut)?); $ordinal = 1);
        } else if $ordinal == 0 {
            cascade!(@discard_if_not_mut($($year_not_mut)?); $year -= 1);
            cascade!(@discard_if_not_mut($($ordinal_not_mut)?);
                $ordinal = crate::util::days_in_year($year)
            );
        }
    };
}

/// Returns `Err(error::ComponentRange)` if the value is not in range.
macro_rules! ensure_value_in_range {
    ($value:ident in $start:expr => $end:expr) => {
        #[allow(clippy::manual_range_contains)] // rust-lang/rust-clippy#6373
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < $start || $value > $end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: $start as _,
                maximum: $end as _,
                value: $value as _,
                conditional_range: false,
            });
        }
    };

    ($value:ident conditionally in $start:expr => $end:expr) => {
        #[allow(clippy::manual_range_contains)] // rust-lang/rust-clippy#6373
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < $start || $value > $end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: $start as _,
                maximum: $end as _,
                value: $value as _,
                conditional_range: true,
            });
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
/// usable in `const` contexts.
macro_rules! const_try {
    ($e:expr) => {
        match $e {
            Ok(value) => value,
            Err(error) => return Err(error),
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
    ($e:expr) => {
        match $e {
            Some(value) => value,
            None => return None,
        }
    };
}
// endregion macros

/// The [`Date`] struct and its associated `impl`s.
mod date;
/// The [`Duration`] struct and its associated `impl`s.
mod duration;
/// Various error types returned by methods in the time crate.
pub mod error;
/// Extension traits.
pub mod ext;
#[cfg(any(feature = "formatting", feature = "parsing"))]
#[cfg_attr(
    __time_03_docs,
    doc(cfg(any(feature = "formatting", feature = "parsing")))
)]
pub mod format_description;
#[cfg(feature = "formatting")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "formatting")))]
mod formatting;
/// The [`Instant`] struct and its associated `impl`s.
#[cfg(feature = "std")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "std")))]
mod instant;
/// Macros to construct statically known values.
#[cfg(feature = "macros")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "macros")))]
pub mod macros;
/// The [`OffsetDateTime`] struct and its associated `impl`s.
mod offset_date_time;
#[cfg(feature = "parsing")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))]
pub mod parsing;
/// The [`PrimitiveDateTime`] struct and its associated `impl`s.
mod primitive_date_time;
#[cfg(feature = "quickcheck")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "quickcheck")))]
mod quickcheck;
#[cfg(feature = "rand")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
mod rand;
#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
#[cfg(test)]
mod tests;
/// The [`Time`] struct and its associated `impl`s.
mod time;
/// The [`UtcOffset`] struct and its associated `impl`s.
mod utc_offset;
pub mod util;
/// Days of the week.
mod weekday;

pub use crate::date::Date;
pub use crate::duration::Duration;
pub use crate::error::Error;
#[cfg(feature = "std")]
pub use crate::instant::Instant;
pub use crate::offset_date_time::OffsetDateTime;
pub use crate::primitive_date_time::PrimitiveDateTime;
pub use crate::time::Time;
pub use crate::utc_offset::UtcOffset;
pub use crate::weekday::Weekday;

/// An alias for [`std::result::Result`] with a generic error from the time crate.
pub type Result<T> = core::result::Result<T, Error>;
<|endoftext|>


<commit_before>pub mod ui {
    extern crate term;
    use net;

    pub fn update(state: Result<net::State, net::State>) {
        match state {
            Ok(net::State::Online)  => online(),
            Err(net::State::Offline) => offline(),
            _ => println!("WHAT?"),
        }
    }

    pub fn online() {
        let mut t = term::stdout().unwrap();
        t.fg(term::color::GREEN).unwrap();
        writeln!(t, "Online").unwrap();
        t.reset();
    }
    pub fn offline() {
        let mut t = term::stdout().unwrap();
        t.fg(term::color::RED).unwrap();
        writeln!(t, "Offline").unwrap();
        t.reset();
    }
    pub fn clear_screen() {
        println!("\x1b[2J\x1b[1;1H");
    }
}

pub mod net {
    extern crate curl;
    use self::curl::http;
    pub enum State { Online, Offline }
    pub fn is_online() -> Result<State, State> {
        let resp = http::handle()
            .get("http://localhost:8000")
            .exec();

        match resp {
            Ok(r) => Ok(State::Online),
            Err(e) => Err(State::Offline)
        }
    }

}
<commit_msg>Use net Enum for passing the result of is_online<commit_after>pub mod ui {
    extern crate term;
    use net;

    pub fn update(state: net::State) {
        match state {
            net::State::Online  => online(),
            net::State::Offline => offline()
        }
    }

    pub fn online() {
        let mut t = term::stdout().unwrap();
        t.fg(term::color::GREEN).unwrap();
        writeln!(t, "Online").unwrap();
        t.reset();
    }
    pub fn offline() {
        let mut t = term::stdout().unwrap();
        t.fg(term::color::RED).unwrap();
        writeln!(t, "Offline").unwrap();
        t.reset();
    }
    pub fn clear_screen() {
        println!("\x1b[2J\x1b[1;1H");
    }
}

pub mod net {
    extern crate curl;
    use self::curl::http;
    pub enum State { Online, Offline }
    pub fn is_online() -> State {
        let resp = http::handle()
            .get("http://localhost:8000")
            .exec();

        match resp {
            Ok(r) => State::Online,
            Err(e) => State::Offline
        }
    }

}
<|endoftext|>


<commit_before>#![crate_id = "base58"]
#![crate_type = "rlib"]
#![license = "Apache License, Version 2.0"]
#![deny(missing_doc)]

//! Rust-Base58 provides functions to encode and decode base58 values.

static BASE_256:u16 = 256;
static BASE_58:u16 = 58;

/// Encode a String into base58 String.
pub fn encode_base58 (input: String) -> String {
  let mut copied = input.into_bytes();
  let mut output:Vec<u8> = vec!();
  let len = copied.len();

  if len == 0 {
    return String::new();
  }

  let mut count = 0;
  while count < len {
    let modulo = divide_mode58(&mut copied);
    let letter = from_alphabet(modulo);
    output.unshift(letter);

    if *copied.get(count) == 0 {
      count += 1;
    }
  }

  match String::from_utf8(output) {
    Ok(result) => result,
    Err(e) => fail!(e)
  }
}

/// Give the letter from the base58 alphabet
fn from_alphabet(position: u16) -> u8 {
  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".char_at(position as uint) as u8
}

/// This function make the division of a big number stored in a Vec
/// and returns the modulo of the division.
/// The given Vec is modified and becomes the result of the division.
fn divide_mode58(input: &mut Vec<u8>) -> u16 {
  let mut remainder = 0;

  for x in input.mut_iter() {

    let num_base256: u16 = (*x as u16) & 255;
    let temp = remainder * BASE_256 + num_base256;
    *x = (temp / BASE_58) as u8;
    remainder = temp % BASE_58;
  }

  remainder
}

#[cfg(test)]
mod tests {
  mod tests_encode_base58 {
    use super::super::encode_base58;

    #[test] // TODO Put this test to test.rs file
    fn should_encode_from_string_to_base58_string() {
      // Given
      let empty = String::from_str("");
      let azerty = String::from_str("azerty");
      let lorem = String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");

      // When
      let empty_encoded = encode_base58(empty);
      let azerty_encoded = encode_base58(azerty);
      let lorem_encoded = encode_base58(lorem);

      // Then
      assert_eq!(empty_encoded, String::from_str(""));
      assert_eq!(azerty_encoded, String::from_str("qYPmmAqv"));
      assert_eq!(lorem_encoded, String::from_str("RKDitRLwUhnQCAmM9hhenQXRAiKrL3ByvJ4CYouvhmw6yV8fapqyM95bN6KQVJbKvEN3uHeMdP9G7b5HNxmwRGqGibzcjrKaRLL2Nn1GFZRRv2Q8AvQU7MtRagLLzcZcwBDzkMqEpbRy9CvGr3BE7t2rH4wXmdExSGNKqV5XxAG7QT2S4ZQ4nzom8QFmoUgkfj8ykPye3z8FU9gJzSf2cDRA1ecYwFJtNdycgKTYCQ92pcfq95DoWfTBhnJfkKZXe1Dv3guVKk5otHz4XtWFJjcSC2GLrkRhTAEtgkySmaePs5YyoQHKb8PU5paS3dxAWc7sV5rqwrJbSbj7ybK6FQDN2mgbBxy7Wc7CnX6Q3Jm4B8cmo4oGixuHKdufABEs4FM3PAhF5CTk9xFsyw3CVJGxE2sMyC5EKnAv5Zc4kGfzzTxQe7VZrm188XqGZKZVRhjSW9CeceAf9bvqefLahgGiKps13595WSErpo1HpHb6Qt22QLSMJFGB2Aq7asXXUj55wPxCfVCz8NiqewcNpxF9bvjW9xsaMGqgD4dpgrBFzUw6irds1X481DHnRDi98yAhQJVUoxP8WSm3qJ93qhq8Hx7Eg4aiy"));
    }
  }

  mod tests_divide_mode58 {
    use super::super::divide_mode58;

    #[test]
    fn should_divide_zero_without_modulo() {
      // Given
      let mut input = vec!(0u8, 0, 0, 0);

      // When
      let modulo = divide_mode58(&mut input);

      // Then
      assert_eq!(*input.get(0), 0);
      assert_eq!(*input.get(1), 0);
      assert_eq!(*input.get(2), 0);
      assert_eq!(*input.get(3), 0);
      assert_eq!(modulo, 0);
    }

    #[test]
    fn should_divide_100_43_without_modulo() {
      // Given
      let mut input = vec!(100u8, 43);

      // When
      let modulo = divide_mode58(&mut input);

      // Then
      assert_eq!(*input.get(0), 1);
      assert_eq!(*input.get(1), 186);
      assert_eq!(modulo, 7);
    }
  }

}
<commit_msg>Optimise time of division<commit_after>#![crate_id = "base58"]
#![crate_type = "rlib"]
#![license = "Apache License, Version 2.0"]
#![deny(missing_doc)]

//! Rust-Base58 provides functions to encode and decode base58 values.

static BASE_256:u16 = 256;
static BASE_58:u16 = 58;

/// Encode a String into base58 String.
pub fn encode_base58 (input: String) -> String {
  let mut copied = input.into_bytes();
  let mut output:Vec<u8> = vec!();
  let len = copied.len();

  if len == 0 {
    return String::new();
  }

  let mut count = 0;
  while count < len {
    let modulo = divide_mode58(&mut copied, count);
    let letter = from_alphabet(modulo);
    output.unshift(letter);

    if *copied.get(count) == 0 {
      count += 1;
    }
  }

  match String::from_utf8(output) {
    Ok(result) => result,
    Err(e) => fail!(e)
  }
}

/// Give the letter from the base58 alphabet
fn from_alphabet(position: u16) -> u8 {
  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".char_at(position as uint) as u8
}

/// This function make the division of a big number stored in a Vec
/// and returns the modulo of the division.
/// The given Vec is modified and becomes the result of the division.
fn divide_mode58(input: &mut Vec<u8>, start: uint) -> u16 {
  let mut remainder = 0;

  for x in input.mut_iter().skip(start) {
    let num_base256: u16 = (*x as u16) & 0xFF;
    let temp = remainder * BASE_256 + num_base256;
    *x = (temp / BASE_58) as u8;
    remainder = temp % BASE_58;
  }

  remainder
}

#[cfg(test)] // TODO Put this test to test.rs file
mod bench {
  extern crate test;
  use self::test::Bencher;
  use super::encode_base58;

  #[bench]
  fn encode_lorem_ispum(b: &mut Bencher) {
    b.iter(|| encode_base58(String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")));
  }
}

#[cfg(test)]
mod tests {
  mod tests_encode_base58 {

    use super::super::encode_base58;

    #[test] // TODO Put this test to test.rs file
    fn should_encode_from_string_to_base58_string() {
      // Given
      let empty = String::from_str("");
      let azerty = String::from_str("azerty");
      let lorem = String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");

      // When
      let empty_encoded = encode_base58(empty);
      let azerty_encoded = encode_base58(azerty);
      let lorem_encoded = encode_base58(lorem);

      // Then
      assert_eq!(empty_encoded, String::from_str(""));
      assert_eq!(azerty_encoded, String::from_str("qYPmmAqv"));
      assert_eq!(lorem_encoded, String::from_str("RKDitRLwUhnQCAmM9hhenQXRAiKrL3ByvJ4CYouvhmw6yV8fapqyM95bN6KQVJbKvEN3uHeMdP9G7b5HNxmwRGqGibzcjrKaRLL2Nn1GFZRRv2Q8AvQU7MtRagLLzcZcwBDzkMqEpbRy9CvGr3BE7t2rH4wXmdExSGNKqV5XxAG7QT2S4ZQ4nzom8QFmoUgkfj8ykPye3z8FU9gJzSf2cDRA1ecYwFJtNdycgKTYCQ92pcfq95DoWfTBhnJfkKZXe1Dv3guVKk5otHz4XtWFJjcSC2GLrkRhTAEtgkySmaePs5YyoQHKb8PU5paS3dxAWc7sV5rqwrJbSbj7ybK6FQDN2mgbBxy7Wc7CnX6Q3Jm4B8cmo4oGixuHKdufABEs4FM3PAhF5CTk9xFsyw3CVJGxE2sMyC5EKnAv5Zc4kGfzzTxQe7VZrm188XqGZKZVRhjSW9CeceAf9bvqefLahgGiKps13595WSErpo1HpHb6Qt22QLSMJFGB2Aq7asXXUj55wPxCfVCz8NiqewcNpxF9bvjW9xsaMGqgD4dpgrBFzUw6irds1X481DHnRDi98yAhQJVUoxP8WSm3qJ93qhq8Hx7Eg4aiy"));
    }
  }

  mod tests_divide_mode58 {
    use super::super::divide_mode58;

    #[test]
    fn should_divide_zero_without_modulo() {
      // Given
      let mut input = vec!(0u8, 0, 0, 0);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 0);
      assert_eq!(*input.get(1), 0);
      assert_eq!(*input.get(2), 0);
      assert_eq!(*input.get(3), 0);
      assert_eq!(modulo, 0);
    }

    #[test]
    fn should_divide_100_43_without_modulo() {
      // Given
      let mut input = vec!(100u8, 43);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 1);
      assert_eq!(*input.get(1), 186);
      assert_eq!(modulo, 7);
    }
  }

}
<|endoftext|>


<commit_before>//! Read and write Elasto Mania replay files.
use std::io::{ Read, Write };
use std::fs::File;
use byteorder::{ ReadBytesExt, WriteBytesExt, LittleEndian };
use super::{ Position, trim_string };

// Magic arbitrary number to signify end of replay file.
const EOR: i32 = 0x00492F75;

/// One frame of replay.
#[derive(Debug, Default, PartialEq)]
pub struct Frame {
    /// Bike position?
    pub bike: Position<f32>,
    /// Left wheel position.
    pub left_wheel: Position<i16>,
    /// Right wheel position.
    pub right_wheel: Position<i16>,
    /// Head position.
    pub head: Position<i16>,
    /// Bike rotation. Range 0..10000.
    pub rotation: i16,
    /// Left wheel rotation. Range 0..255.
    pub left_wheel_rotation: u8,
    /// Right wheel rotation. Range 0..255.
    pub right_wheel_rotation: u8,
    /// Throttle.
    pub throttle: bool,
    /// Right direction. True = right, False = left.
    // TODO: consider making right field = direction and enum with right and left?
    pub right: bool,
    /// Spring sound effect volume.
    pub volume: i16
}

impl Frame {
    pub fn new() -> Self {
        Frame {
            bike: Position { x: 0f32, y: 0f32 },
            left_wheel: Position { x: 0, y: 0 },
            right_wheel: Position { x: 0, y: 0 },
            head: Position { x: 0, y: 0 },
            rotation: 0,
            left_wheel_rotation: 0,
            right_wheel_rotation: 0,
            throttle: false,
            right: false,
            volume: 0
        }
    }
}

#[derive(Debug, Default, PartialEq)]
pub struct Event {
    /// Time of event.
    pub time: f64,
    /// Event type.
    // TODO: Make enum.
    pub event_type: [u32; 2]
}

impl Event {
    pub fn new() -> Self {
        Event {
            time: 0f64,
            event_type: [0, 0]
        }
    }
}

/// Replay struct
#[derive(Debug, PartialEq)]
pub struct Replay {
    /// Raw binary data.
    raw: Vec<u8>,
    /// Whether replay is multi-player or not.
    pub multi: bool,
    /// Whether replay is flag-tag or not.
    pub flag_tag: bool,
    /// Random number to link with level file.
    pub link: u32,
    /// Full level filename.
    pub level: String,
    /// Vector with Frame structs.
    pub frames: Vec<Frame>,
    /// Events.
    pub events: Vec<Event>
}

impl Default for Replay {
    fn default() -> Replay { Replay::new() }
}

impl Replay {
    /// Build a new Replay.
    ///
    /// # Examples
    ///
    /// ```
    /// let rec = elma::rec::Replay::new();
    /// ```
    pub fn new() -> Self {
        Replay {
            raw: vec![],
            multi: false,
            flag_tag: false,
            link: 0,
            level: String::new(),
            frames: vec![],
            events: vec![]
        }
    }

    /// Loads a replay file and returns a Replay struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let rec = elma::rec::Replay::load_replay("tests/test.rec");
    /// ```
    pub fn load_replay(filename: &str) -> Self {
        let mut replay = Replay::new();
        let mut file = File::open(filename).unwrap();
        let mut buffer = vec![];
        file.read_to_end(&mut buffer).unwrap();
        replay.raw = buffer;
        replay.parse_replay();
        replay
    }

    pub fn parse_replay(&mut self) {
        // TODO: do that.
        let mut remaining = self.raw.as_slice();

        // Frame count.
        let frame_count = remaining.read_i32::<LittleEndian>().unwrap();

        // Some unused value, always 0x83.
        let (_, mut remaining) = remaining.split_at(4);

        // Multi-player replay.
        self.multi = remaining.read_i32::<LittleEndian>().unwrap() > 0;

        // Flag-tag replay.
        self.flag_tag = remaining.read_i32::<LittleEndian>().unwrap() > 0;

        // Level link.
        self.link = remaining.read_u32::<LittleEndian>().unwrap();

        // Level file name, including extension.
        let (level, remaining) = remaining.split_at(12);
        self.level = trim_string(level).unwrap();

        // Unknown, unused.
        let (_, mut remaining) = remaining.split_at(4);

        // Frames.
        for _ in 0..frame_count {
            // Bike X and Y.
            let x = remaining.read_f32::<LittleEndian>().unwrap();
            let y = remaining.read_f32::<LittleEndian>().unwrap();
            let bike = Position { x: x, y: y };

            // Left wheel X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let left_wheel = Position { x: x, y: y };

            // Left wheel X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let right_wheel = Position { x: x, y: y };

            // Head X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let head = Position { x: x, y: y };

            // Rotations.
            let rotation = remaining.read_i16::<LittleEndian>().unwrap();
            let left_wheel_rotation = remaining.read_u8().unwrap();
            let right_wheel_rotation = remaining.read_u8().unwrap();

            // Throttle and turn right.
            let data = remaining.read_u8().unwrap();
            // TODO: figure out how to get these values.
            let throttle = false;
            let right = false;

            // Sound effect volume.
            let volume = remaining.read_i16::<LittleEndian>().unwrap();

            self.frames.push(Frame {
                bike: bike,
                left_wheel: left_wheel,
                right_wheel: right_wheel,
                head: head,
                rotation: rotation,
                left_wheel_rotation: left_wheel_rotation,
                right_wheel_rotation: right_wheel_rotation,
                throttle: throttle,
                right: right,
                volume: volume
            });
        }

        // Events.
        let event_count = remaining.read_i32::<LittleEndian>().unwrap();
        for _ in 0..event_count {
            // TODO: parse this
            let (_, temp_remaining) = remaining.split_at(16);
            remaining = temp_remaining;
        }

        let expected = remaining.read_i32::<LittleEndian>().unwrap();
        if expected != EOR { panic!("EOR marker mismatch: x0{:x} != x0{:x}", expected, EOR); }

        // TODO: Add multi-player replay parsing.
    }
}
<commit_msg>Add preliminary event parsing<commit_after>//! Read and write Elasto Mania replay files.
use std::io::{ Read, Write };
use std::fs::File;
use byteorder::{ ReadBytesExt, WriteBytesExt, LittleEndian };
use super::{ Position, trim_string };

// Magic arbitrary number to signify end of replay file.
const EOR: i32 = 0x00492F75;

/// One frame of replay.
#[derive(Debug, Default, PartialEq)]
pub struct Frame {
    /// Bike position?
    pub bike: Position<f32>,
    /// Left wheel position.
    pub left_wheel: Position<i16>,
    /// Right wheel position.
    pub right_wheel: Position<i16>,
    /// Head position.
    pub head: Position<i16>,
    /// Bike rotation. Range 0..10000.
    pub rotation: i16,
    /// Left wheel rotation. Range 0..255.
    pub left_wheel_rotation: u8,
    /// Right wheel rotation. Range 0..255.
    pub right_wheel_rotation: u8,
    /// Throttle.
    pub throttle: bool,
    /// Right direction. True = right, False = left.
    // TODO: consider making right field = direction and enum with right and left?
    pub right: bool,
    /// Spring sound effect volume.
    pub volume: i16
}

impl Frame {
    /// Returns a new Frame struct with zero values.
    ///
    /// # Examples
    ///
    /// ```
    /// let frame = elma::rec::Frame::new();
    /// ```
    pub fn new() -> Self {
        Frame {
            bike: Position { x: 0f32, y: 0f32 },
            left_wheel: Position { x: 0, y: 0 },
            right_wheel: Position { x: 0, y: 0 },
            head: Position { x: 0, y: 0 },
            rotation: 0,
            left_wheel_rotation: 0,
            right_wheel_rotation: 0,
            throttle: false,
            right: false,
            volume: 0
        }
    }
}

#[derive(Debug, Default, PartialEq)]
/// Replay events.
pub struct Event {
    /// Time of event.
    pub time: f64,
    /// Event type.
    pub event_type: u8
}

#[derive(Debug, PartialEq)]
/// Type of event.
pub enum EventType {
    /// Apple or flower touch, with index of object.
    Touch { index: usize },
    Turn,
    Volt { right: bool },
    /// Ground touch, for sound effects. Two types; if alternative is true, uses the second type.
    Ground { alternative: bool }
}

impl Default for EventType {
    fn default() -> EventType { EventType::Touch { index: 0 } }
}

impl Event {
    pub fn new() -> Self {
        Event {
            time: 0f64,
            event_type: 0
        }
    }
}

/// Replay struct
#[derive(Debug, PartialEq)]
pub struct Replay {
    /// Raw binary data.
    raw: Vec<u8>,
    /// Whether replay is multi-player or not.
    pub multi: bool,
    /// Whether replay is flag-tag or not.
    pub flag_tag: bool,
    /// Random number to link with level file.
    pub link: u32,
    /// Full level filename.
    pub level: String,
    /// Vector with Frame structs.
    pub frames: Vec<Frame>,
    /// Events.
    pub events: Vec<Event>
}

impl Default for Replay {
    fn default() -> Replay { Replay::new() }
}

impl Replay {
    /// Build a new Replay.
    ///
    /// # Examples
    ///
    /// ```
    /// let rec = elma::rec::Replay::new();
    /// ```
    pub fn new() -> Self {
        Replay {
            raw: vec![],
            multi: false,
            flag_tag: false,
            link: 0,
            level: String::new(),
            frames: vec![],
            events: vec![]
        }
    }

    /// Loads a replay file and returns a Replay struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let rec = elma::rec::Replay::load_replay("tests/test.rec");
    /// ```
    pub fn load_replay(filename: &str) -> Self {
        let mut replay = Replay::new();
        let mut file = File::open(filename).unwrap();
        let mut buffer = vec![];
        file.read_to_end(&mut buffer).unwrap();
        replay.raw = buffer;
        replay.parse_replay();
        replay
    }

    pub fn parse_replay(&mut self) {
        // TODO: do that.
        let mut remaining = self.raw.as_slice();

        // Frame count.
        let frame_count = remaining.read_i32::<LittleEndian>().unwrap();

        // Some unused value, always 0x83.
        let (_, mut remaining) = remaining.split_at(4);

        // Multi-player replay.
        self.multi = remaining.read_i32::<LittleEndian>().unwrap() > 0;

        // Flag-tag replay.
        self.flag_tag = remaining.read_i32::<LittleEndian>().unwrap() > 0;

        // Level link.
        self.link = remaining.read_u32::<LittleEndian>().unwrap();

        // Level file name, including extension.
        let (level, remaining) = remaining.split_at(12);
        self.level = trim_string(level).unwrap();

        // Unknown, unused.
        let (_, mut remaining) = remaining.split_at(4);

        // Frames.
        for _ in 0..frame_count {
            // Bike X and Y.
            let x = remaining.read_f32::<LittleEndian>().unwrap();
            let y = remaining.read_f32::<LittleEndian>().unwrap();
            let bike = Position { x: x, y: y };

            // Left wheel X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let left_wheel = Position { x: x, y: y };

            // Left wheel X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let right_wheel = Position { x: x, y: y };

            // Head X and Y.
            let x = remaining.read_i16::<LittleEndian>().unwrap();
            let y = remaining.read_i16::<LittleEndian>().unwrap();
            let head = Position { x: x, y: y };

            // Rotations.
            let rotation = remaining.read_i16::<LittleEndian>().unwrap();
            let left_wheel_rotation = remaining.read_u8().unwrap();
            let right_wheel_rotation = remaining.read_u8().unwrap();

            // Throttle and turn right.
            let data = remaining.read_u8().unwrap();
            // TODO: figure out how to get these values.
            let throttle = false;
            let right = false;

            // Sound effect volume.
            let volume = remaining.read_i16::<LittleEndian>().unwrap();

            self.frames.push(Frame {
                bike: bike,
                left_wheel: left_wheel,
                right_wheel: right_wheel,
                head: head,
                rotation: rotation,
                left_wheel_rotation: left_wheel_rotation,
                right_wheel_rotation: right_wheel_rotation,
                throttle: throttle,
                right: right,
                volume: volume
            });
        }

        // Events.
        let event_count = remaining.read_i32::<LittleEndian>().unwrap();
        for _ in 0..event_count {
            // Event time
            let time = remaining.read_f64::<LittleEndian>().unwrap();

            // Event details
            let info = remaining.read_i16::<LittleEndian>().unwrap();
            let event_type = remaining.read_u8().unwrap();

            // Unknown
            let _ = remaining.read_u8().unwrap();
            let _ = remaining.read_f32::<LittleEndian>().unwrap();

            self.events.push(Event {
                time: time,
                event_type: event_type
            });
        }

        let expected = remaining.read_i32::<LittleEndian>().unwrap();
        if expected != EOR { panic!("EOR marker mismatch: x0{:x} != x0{:x}", expected, EOR); }

        // TODO: Add multi-player replay parsing.
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate quote;
extern crate reqwest;
extern crate serde_json;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;

use std::fs::File;
use serde_json::{ Value, Map };
use std::collections::HashSet;
use quote::{ Tokens, Ident };

mod util;

use util::*;

mod errors {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        links {
        }

        foreign_links {
            ReqwestError(::reqwest::Error);
            JsonError(::serde_json::Error);
            IoError(::std::io::Error);
        }

        errors {
            MissingSource {
                description("No source for sample specified")
            }
            ExistingType(t: String) {
                display("No code generated, JSON matches existing type {}", t)
            }
        }
    }
}

pub use errors::*;

const RUST_KEYWORDS_ARR: &'static [&'static str] = &["abstract", "alignof", "as", "become", "box",
    "break", "const", "continue", "crate", "do", "else", "enum", "extern", "false", "final", "fn",
    "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof",
    "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", "static",
    "struct", "super", "trait", "true", "type", "typeof", "unsafe", "unsized", "use", "virtual",
    "where", "while", "yield"];

lazy_static! {
    static ref RUST_KEYWORDS: HashSet<&'static str> = {
        RUST_KEYWORDS_ARR.iter().cloned().collect()
    };
}

pub enum SampleSource<'a> {
    Url(&'a str),
    File(&'a str),
    Text(&'a str),
}

pub struct Options {
    pub use_serde: bool,
    pub extern_crate: bool,
    pub runnable: bool
}

impl Default for Options {
    fn default() -> Options {
        Options {
            use_serde: true,
            extern_crate: false,
            runnable: false
        }
    }
}

struct Ctxt {
    options: Options
}

macro_rules! some_if {
    ($cond:expr, $then:expr) => ({
        if $cond {
            Some($then)
        } else {
            None
        }
    })
}

pub fn from_str_with_defaults(name: &str, json: &str) -> Result<Tokens> {
    codegen(name, &SampleSource::Text(json), Options::default())
}

pub fn codegen(name: &str, source: &SampleSource, options: Options) -> Result<Tokens> {
    let sample = get_and_parse_sample(source)?;
    let mut ctxt = Ctxt {
        options: options
    };
    let (type_name, type_def) = generate_type_from_value(&mut ctxt, name, &sample);

    let example = some_if!(ctxt.options.runnable, {
        ctxt.options.extern_crate = true;
        usage_example(&type_name)
    });

    let crates = some_if!(ctxt.options.extern_crate, quote! {
        #[macro_use]
        extern crate serde_derive;
        extern crate serde_json;
    });

    if type_def.is_none() && !ctxt.options.runnable {
        return Err(ErrorKind::ExistingType(String::from(type_name.as_str())).into());
    }

    Ok(quote! {
        #crates

        #type_def

        #example
    })
}

fn usage_example(type_id: &Tokens) -> Tokens {
    let var_id = Ident::from(snake_case(type_id.as_str()));

    quote! {
        fn main() {
            let #var_id: #type_id = Default::default();

            let serialized = serde_json::to_string(&#var_id).unwrap();

            println!("serialized = {}", serialized);

            let deserialized: #type_id = serde_json::from_str(&serialized).unwrap();

            println!("deserialized = {:?}", deserialized);
        }
    }
}

fn generate_type_from_value(ctxt: &mut Ctxt, path: &str, value: &Value) -> (Tokens, Option<Tokens>) {
    match *value {
        Value::Null => (quote! { Option<::serde_json::Value> }, None),
        Value::Bool(_) => (quote! { bool }, None),
        Value::Number(ref n) => {
            if n.is_i64() {
                (quote! { i64 }, None)
            } else {
                (quote! { f64 }, None)
            }
        },
        Value::String(_) => (quote! { String }, None),
        Value::Array(ref values) => {
            generate_type_for_array(ctxt, path, values)
        },
        Value::Object(ref map) => {
            generate_struct_from_object(ctxt, path, map)
        }
    }
}

fn generate_type_for_array(ctxt: &mut Ctxt, path: &str, values: &[Value]) -> (Tokens, Option<Tokens>) {
    let mut defs = Vec::new();
    let mut types = HashSet::new();

    for value in values.iter() {
        let (elemtype, elemtype_def) = generate_type_from_value(ctxt, path, value);
        types.insert(elemtype.into_string());
        if let Some(def) = elemtype_def {
            defs.push(def);
        }
    }

    if types.len() == 1 {
        let ident = Ident::new(types.into_iter().next().unwrap());
        (quote! { Vec<#ident> }, defs.into_iter().next())
    } else {
        (quote! { Vec<::serde_json::Value> }, None)
    }
}

fn generate_struct_from_object(ctxt: &mut Ctxt, path: &str, map: &Map<String, Value>) -> (Tokens, Option<Tokens>) {
    let type_name = type_case(path);
    let ident = Ident::from(type_name);
    let mut defs = Vec::new();

    let fields: Vec<Tokens> = map.iter()
        .map(|(name, value)| {
            let mut field_name = snake_case(name);
            if RUST_KEYWORDS.contains::<str>(&field_name) {
                field_name.push_str("_field")
            }
            let rename = some_if!(&field_name != name,
                quote! { #[serde(rename = #name)] });

            let field_ident = Ident::from(field_name);
            let (fieldtype, fieldtype_def) = generate_type_from_value(ctxt, name, value);
            if let Some(def) = fieldtype_def {
                defs.push(def);
            }
            quote! {
                #rename
                #field_ident: #fieldtype
            }
        })
        .collect();

    let derives = if ctxt.options.use_serde {
        quote! { #[derive(Default, Debug, Clone, Serialize, Deserialize)] }
    } else {
        quote! { #[derive(Default, Debug, Clone)] }
    };

    let code = quote! {
        #derives
        struct #ident {
            #(#fields),*
        }

        #(#defs)*
    };

    (quote! { #ident }, Some(code))
}

pub fn infer_source_type(s: &str) -> SampleSource {
    let s = s.trim();
    if s.starts_with('{') || s.starts_with('[') {
        return SampleSource::Text(s);
    }
    if s.starts_with("http://") || s.starts_with("https://") {
        return SampleSource::Url(s);
    }
    SampleSource::File(s)
}

fn get_and_parse_sample(source: &SampleSource) -> Result<Value> {
    let parse_result = match *source {
        SampleSource::Url(url) => serde_json::de::from_reader(reqwest::get(url)?),
        SampleSource::File(path) => serde_json::de::from_reader(File::open(path)?),
        SampleSource::Text(text) => serde_json::from_str(text),
    };
    Ok(parse_result.chain_err(|| "Unable to parse JSON sample")?)
}
<commit_msg>shared: Preliminary work on better inference<commit_after>#[macro_use]
extern crate quote;
extern crate reqwest;
extern crate serde_json;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;

use std::fs::File;
use serde_json::{ Value, Map };
use std::collections::{ HashSet, HashMap };
use quote::{ Tokens, Ident };

mod util;

use util::*;

mod errors {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        links {
        }

        foreign_links {
            ReqwestError(::reqwest::Error);
            JsonError(::serde_json::Error);
            IoError(::std::io::Error);
        }

        errors {
            MissingSource {
                description("No source for sample specified")
            }
            ExistingType(t: String) {
                display("No code generated, JSON matches existing type {}", t)
            }
        }
    }
}

pub use errors::*;

const RUST_KEYWORDS_ARR: &'static [&'static str] = &["abstract", "alignof", "as", "become", "box",
    "break", "const", "continue", "crate", "do", "else", "enum", "extern", "false", "final", "fn",
    "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof",
    "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", "static",
    "struct", "super", "trait", "true", "type", "typeof", "unsafe", "unsized", "use", "virtual",
    "where", "while", "yield"];

lazy_static! {
    static ref RUST_KEYWORDS: HashSet<&'static str> = {
        RUST_KEYWORDS_ARR.iter().cloned().collect()
    };
}

pub enum SampleSource<'a> {
    Url(&'a str),
    File(&'a str),
    Text(&'a str),
}

pub struct Options {
    pub use_serde: bool,
    pub extern_crate: bool,
    pub runnable: bool
}

impl Default for Options {
    fn default() -> Options {
        Options {
            use_serde: true,
            extern_crate: false,
            runnable: false
        }
    }
}

struct Ctxt {
    options: Options
}

macro_rules! some_if {
    ($cond:expr, $then:expr) => ({
        if $cond {
            Some($then)
        } else {
            None
        }
    })
}

#[allow(dead_code)]
#[derive(Debug, PartialEq, Clone)]
enum InferredType {
    Null,
    Any,
    Bool,
    StringT,
    Integer,
    Floating,
    VecT { elem_type: Box<InferredType> },
    Struct { fields: HashMap<String, InferredType> },
    Optional(Box<InferredType>)
}

#[allow(dead_code)]
fn unify(a: InferredType, b: InferredType) -> InferredType {
    if a == b {
        return a;
    }
    use InferredType::*;
    match (a, b) {
        (Integer, Floating) |
        (Floating, Integer) => Floating,
        (a, Null) | (Null, a) => make_optional(a),
        (a, Optional(b)) | (Optional(b), a) => make_optional(unify(a, *b)),
        (VecT { elem_type: e1 }, VecT { elem_type: e2 }) => {
            VecT { elem_type: Box::new(unify(*e1, *e2)) }
        }
        (Struct { fields: f1 }, Struct { fields: f2 }) => {
            Struct { fields: unify_struct_fields(f1, f2) }
        }
        _ => Any,
    }
}

fn make_optional(a: InferredType) -> InferredType {
    use InferredType::*;
    match a {
        Null | Any | Optional(_) => a,
        non_nullable => Optional(Box::new(non_nullable)),
    }
}

fn unify_struct_fields(mut f1: HashMap<String, InferredType>,
                       mut f2: HashMap<String, InferredType>)
                       -> HashMap<String, InferredType> {
    if f1 == f2 {
        return f1;
    }
    let mut unified = HashMap::new();
    for (key, val) in f1.drain() {
        match f2.remove(&key) {
            Some(val2) => {
                unified.insert(key, unify(val, val2));
            },
            None => {
                unified.insert(key, make_optional(val));
            }
        }
    }
    for (key, val) in f2.drain() {
        unified.insert(key, make_optional(val));
    }
    unified
}

pub fn from_str_with_defaults(name: &str, json: &str) -> Result<Tokens> {
    codegen(name, &SampleSource::Text(json), Options::default())
}

pub fn codegen(name: &str, source: &SampleSource, options: Options) -> Result<Tokens> {
    let sample = get_and_parse_sample(source)?;
    let mut ctxt = Ctxt {
        options: options
    };
    let (type_name, type_def) = generate_type_from_value(&mut ctxt, name, &sample);

    let example = some_if!(ctxt.options.runnable, {
        ctxt.options.extern_crate = true;
        usage_example(&type_name)
    });

    let crates = some_if!(ctxt.options.extern_crate, quote! {
        #[macro_use]
        extern crate serde_derive;
        extern crate serde_json;
    });

    if type_def.is_none() && !ctxt.options.runnable {
        return Err(ErrorKind::ExistingType(String::from(type_name.as_str())).into());
    }

    Ok(quote! {
        #crates

        #type_def

        #example
    })
}

fn usage_example(type_id: &Tokens) -> Tokens {
    let var_id = Ident::from(snake_case(type_id.as_str()));

    quote! {
        fn main() {
            let #var_id: #type_id = Default::default();

            let serialized = serde_json::to_string(&#var_id).unwrap();

            println!("serialized = {}", serialized);

            let deserialized: #type_id = serde_json::from_str(&serialized).unwrap();

            println!("deserialized = {:?}", deserialized);
        }
    }
}

fn generate_type_from_value(ctxt: &mut Ctxt, path: &str, value: &Value) -> (Tokens, Option<Tokens>) {
    match *value {
        Value::Null => (quote! { Option<::serde_json::Value> }, None),
        Value::Bool(_) => (quote! { bool }, None),
        Value::Number(ref n) => {
            if n.is_i64() {
                (quote! { i64 }, None)
            } else {
                (quote! { f64 }, None)
            }
        },
        Value::String(_) => (quote! { String }, None),
        Value::Array(ref values) => {
            generate_type_for_array(ctxt, path, values)
        },
        Value::Object(ref map) => {
            generate_struct_from_object(ctxt, path, map)
        }
    }
}

fn generate_type_for_array(ctxt: &mut Ctxt, path: &str, values: &[Value]) -> (Tokens, Option<Tokens>) {
    let mut defs = Vec::new();
    let mut types = HashSet::new();

    for value in values.iter() {
        let (elemtype, elemtype_def) = generate_type_from_value(ctxt, path, value);
        types.insert(elemtype.into_string());
        if let Some(def) = elemtype_def {
            defs.push(def);
        }
    }

    if types.len() == 1 {
        let ident = Ident::new(types.into_iter().next().unwrap());
        (quote! { Vec<#ident> }, defs.into_iter().next())
    } else {
        (quote! { Vec<::serde_json::Value> }, None)
    }
}

fn generate_struct_from_object(ctxt: &mut Ctxt, path: &str, map: &Map<String, Value>) -> (Tokens, Option<Tokens>) {
    let type_name = type_case(path);
    let ident = Ident::from(type_name);
    let mut defs = Vec::new();

    let fields: Vec<Tokens> = map.iter()
        .map(|(name, value)| {
            let mut field_name = snake_case(name);
            if RUST_KEYWORDS.contains::<str>(&field_name) {
                field_name.push_str("_field")
            }
            let rename = some_if!(&field_name != name,
                quote! { #[serde(rename = #name)] });

            let field_ident = Ident::from(field_name);
            let (fieldtype, fieldtype_def) = generate_type_from_value(ctxt, name, value);
            if let Some(def) = fieldtype_def {
                defs.push(def);
            }
            quote! {
                #rename
                #field_ident: #fieldtype
            }
        })
        .collect();

    let derives = if ctxt.options.use_serde {
        quote! { #[derive(Default, Debug, Clone, Serialize, Deserialize)] }
    } else {
        quote! { #[derive(Default, Debug, Clone)] }
    };

    let code = quote! {
        #derives
        struct #ident {
            #(#fields),*
        }

        #(#defs)*
    };

    (quote! { #ident }, Some(code))
}

pub fn infer_source_type(s: &str) -> SampleSource {
    let s = s.trim();
    if s.starts_with('{') || s.starts_with('[') {
        return SampleSource::Text(s);
    }
    if s.starts_with("http://") || s.starts_with("https://") {
        return SampleSource::Url(s);
    }
    SampleSource::File(s)
}

fn get_and_parse_sample(source: &SampleSource) -> Result<Value> {
    let parse_result = match *source {
        SampleSource::Url(url) => serde_json::de::from_reader(reqwest::get(url)?),
        SampleSource::File(path) => serde_json::de::from_reader(File::open(path)?),
        SampleSource::Text(text) => serde_json::from_str(text),
    };
    Ok(parse_result.chain_err(|| "Unable to parse JSON sample")?)
}

#[test]
fn test_unify() {
    use InferredType::*;
    assert_eq!(unify(Bool, Bool), Bool);
    assert_eq!(unify(Bool, Integer), Any);
    assert_eq!(unify(Integer, Floating), Floating);
    assert_eq!(unify(Null, Any), Any);
    assert_eq!(unify(Null, Bool), Optional(Box::new(Bool)));
    assert_eq!(unify(Null, Optional(Box::new(Integer))), Optional(Box::new(Integer)));
    assert_eq!(unify(Any, Optional(Box::new(Integer))), Any);
    assert_eq!(unify(Any, Optional(Box::new(Integer))), Any);
    assert_eq!(unify(Optional(Box::new(Integer)), Optional(Box::new(Floating))),
               Optional(Box::new(Floating)));
    assert_eq!(unify(Optional(Box::new(StringT)), Optional(Box::new(Integer))), Any);
}

// based on hashmap! macro from maplit crate
macro_rules! string_hashmap {
    ($($key:expr => $value:expr,)+) => { string_hashmap!($($key => $value),+) };
    ($($key:expr => $value:expr),*) => {
        {
            let mut _map = ::std::collections::HashMap::new();
            $(
                _map.insert($key.to_string(), $value);
            )*
            _map
        }
    };
}

#[test]
fn test_unify_struct_fields() {
    use InferredType::*;
    {
        let f1 = string_hashmap!{
            "a" => Integer,
            "b" => Bool,
            "c" => Integer,
            "d" => StringT,
        };
        let f2 = string_hashmap!{
            "a" => Integer,
            "c" => Floating,
            "d" => Null,
            "e" => Any,
        };
        assert_eq!(unify_struct_fields(f1, f2), string_hashmap!{
            "a" => Integer,
            "b" => Optional(Box::new(Bool)),
            "c" => Floating,
            "d" => Optional(Box::new(StringT)),
            "e" => Any,
        });
    }
}
<|endoftext|>


<commit_before>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "792c645ca7d11a8d254df307d019c5bf01445c37";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/issues/auxiliary/issue-21146-inc.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    // TODO assert that parsing fails on the parse-fail cases
    if path.starts_with("src/test/parse-fail")
        || path.starts_with("src/test/compile-fail")
        || path.starts_with("src/test/rustfix")
    {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Remove parse-fail check no longer present in Rust dist<commit_after>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "792c645ca7d11a8d254df307d019c5bf01445c37";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/issues/auxiliary/issue-21146-inc.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before>#![macro_escape]

#[macro_export]
macro_rules! wnd_proc_thunk(
    (WM_CREATE) => (
        if msg == 0x0001 { // WM_CREATE
            let cs = unsafe {
                let pcs = ::std::mem::transmute::<::windows::ll::types::LPARAM,
                                                   *::windows::ll::all::CREATESTRUCT>(l);
                &(*pcs)
            };
            let ret = self.on_create(cs);
            if ret {
                return 0 as ::windows::ll::types::LRESULT;
            } else {
                return -1 as ::windows::ll::types::LRESULT;
            }
        }
    );
    (WM_DESTROY) => (
        if msg == 0x0002 { // WM_DESTROY
            self.on_destroy();
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    (WM_SIZE) => (
        if msg == 0x0005 { // WM_SIZE
            let l = l as u32;
            let width = (l & 0xFFFF) as int;
            let height = (l >> 16) as int;
            self.on_size(width, height);
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    (WM_SETFOCUS) => (
        if msg == 0x0007 { // WM_SETFOCUS
            let w = ::windows::window::Window { wnd: w as ::windows::ll::types::HWND };
            self.on_focus(w);
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    (WM_PAINT) => (
        if msg == 0x000F { // WM_PAINT
            self.on_paint();
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
)

#[macro_export]
macro_rules! wnd_proc(
    ($wnd:ident, $win:ident, $($msg:ident),+) => (

    impl ::windows::window::WindowImpl for $wnd {
        fn wnd<'a>(&'a self) -> &'a ::windows::window::Window {
            &self.$win
        }

        fn wnd_mut<'a>(&'a mut self) -> &'a mut ::windows::window::Window {
            &mut self.$win
        }

        fn wnd_proc(&self, msg: ::windows::ll::types::UINT, w: ::windows::ll::types::WPARAM,
                    l: ::windows::ll::types::LPARAM) -> ::windows::ll::types::LRESULT {
            $(
                wnd_proc_thunk!($msg)
            )+
            ::windows::def_window_proc(self.wnd().wnd, msg, w, l)
        }
    }

    )
)
<commit_msg>fix macro hygiene issues<commit_after>#![macro_escape]

#[macro_export]
macro_rules! wnd_proc_thunk(
    ($self_:ident, $msg:ident, $w:ident, $l:ident, WM_CREATE) => (
        if $msg == 0x0001 { // WM_CREATE
            let cs = unsafe {
                let pcs = ::std::mem::transmute::<::windows::ll::types::LPARAM,
                                                   *const ::windows::ll::all::CREATESTRUCT>($l);
                &(*pcs)
            };
            let ret = $self_.on_create(cs);
            if ret {
                return 0 as ::windows::ll::types::LRESULT;
            } else {
                return -1 as ::windows::ll::types::LRESULT;
            }
        }
    );
    ($self_:ident, $msg:ident, $w:ident, $l:ident, WM_DESTROY) => (
        if $msg == 0x0002 { // WM_DESTROY
            $self_.on_destroy();
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    ($self_:ident, $msg:ident, $w:ident, $l:ident, WM_SIZE) => (
        if $msg == 0x0005 { // WM_SIZE
            let l = $l as u32;
            let width = (l & 0xFFFF) as int;
            let height = (l >> 16) as int;
            $self_.on_size(width, height);
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    ($self_:ident, $msg:ident, $w:ident, $l:ident, WM_SETFOCUS) => (
        if $msg == 0x0007 { // WM_SETFOCUS
            let w = ::windows::window::Window { wnd: $w as ::windows::ll::types::HWND };
            $self_.on_focus(w);
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
    ($self_:ident, $msg:ident, $w:ident, $l:ident, WM_PAINT) => (
        if $msg == 0x000F { // WM_PAINT
            $self_.on_paint();
            return 0 as ::windows::ll::types::LRESULT;
        }
    );
)

#[macro_export]
macro_rules! wnd_proc(
    ($wnd:ident, $win:ident, $($msg:ident),+) => (

    impl ::windows::window::WindowImpl for $wnd {
        fn wnd<'a>(&'a self) -> &'a ::windows::window::Window {
            &self.$win
        }

        fn wnd_mut<'a>(&'a mut self) -> &'a mut ::windows::window::Window {
            &mut self.$win
        }

        fn wnd_proc(&self, msg: ::windows::ll::types::UINT, w: ::windows::ll::types::WPARAM,
                    l: ::windows::ll::types::LPARAM) -> ::windows::ll::types::LRESULT {
            $(
                wnd_proc_thunk!(self, msg, w, l, $msg)
            )+
            ::windows::def_window_proc(self.wnd().wnd, msg, w, l)
        }
    }

    )
)
<|endoftext|>


<commit_before>// Copyright 2013 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.

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(~[1,2,3,4,5,6,7,8]));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.fill(v) {
            Ok(()) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
#[allow(deprecated_owned_vector)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(~[]));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<commit_msg>De-~[] Mem{Reader,Writer}<commit_after>// Copyright 2013 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.

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.fill(v) {
            Ok(()) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
#[allow(deprecated_owned_vector)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<|endoftext|>