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

#![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,
    unstable_name_collisions
)]
#![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 {
    (@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, unused_assignments)]
        if $from >= $max {
            $from -= $max - $min;
            $to += 1;
        } else if $from < $min {
            $from += $max - $min;
            $to -= 1;
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($ordinal:ident => $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@$ordinal);
        cascade!(@$year);
        #[allow(unused_assignments)]
        if $ordinal > crate::util::days_in_year($year) {
            $year += 1;
            $ordinal = 1;
        } else if $ordinal == 0 {
            $year -= 1;
            $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) => {{
        let _start = $start;
        let _end = $end;
        #[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) => {{
        let _start = $start;
        let _end = $end;
        #[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")))]
pub 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;
mod month;
/// 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::month::Month;
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>Prevent `year => ordinal` cascade<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,
    unstable_name_collisions
)]
#![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 {
    (@ordinal ordinal) => {};
    (@year 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, unused_assignments)]
        if $from >= $max {
            $from -= $max - $min;
            $to += 1;
        } else if $from < $min {
            $from += $max - $min;
            $to -= 1;
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($ordinal:ident => $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@ordinal $ordinal);
        cascade!(@year $year);
        #[allow(unused_assignments)]
        if $ordinal > crate::util::days_in_year($year) {
            $year += 1;
            $ordinal = 1;
        } else if $ordinal == 0 {
            $year -= 1;
            $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) => {{
        let _start = $start;
        let _end = $end;
        #[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) => {{
        let _start = $start;
        let _end = $end;
        #[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")))]
pub 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;
mod month;
/// 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::month::Month;
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>#![cfg_attr(not(target_family = "unix"), no_std)]
#![crate_name = "klogger"]
#![crate_type = "lib"]

#[cfg(not(target_os = "none"))]
extern crate core;

use core::fmt;
use core::ops;

#[macro_use]
pub mod macros;

extern crate log;
extern crate termcodes;

#[cfg(target_arch = "x86_64")]
extern crate x86;

#[cfg(any(feature = "use_ioports", all(target_arch = "x86_64", target_os = "none")))]
#[path = "arch/x86.rs"]
mod arch;

#[cfg(all(not(feature = "use_ioports"), target_family = "unix"))]
#[path = "arch/unix.rs"]
mod arch;

use log::{Level, Metadata, Record, SetLoggerError};
use termcodes::color;

/// One Mhz is that many Hz.
const MHZ_TO_HZ: u64 = 1000 * 1000;

/// One Khz is that many Hz.
const KHZ_TO_HZ: u64 = 1000;

/// One sec has that many ns.
const NS_PER_SEC: u64 = 1_000_000_000u64;

/// Global lock to protect serial line from concurrent printing.
static mut SERIAL_LINE_MUTEX: spin::Mutex<bool> = spin::Mutex::new(false);

#[derive(Debug)]
struct KLogger {
    /// Do we even have a TSC?
    ///
    /// If not bad.
    has_tsc: bool,
    /// Is the underlying TSC invariant?
    ///
    /// If not, bad.
    has_invariant_tsc: bool,
    /// Point in time when this Klogger got initialized
    tsc_start: u64,
    /// Frequency in Hz
    ///
    /// Sometimes we can't figure this out (yet)
    tsc_frequency: Option<u64>,
}

enum ElapsedTime {
    Undetermined,
    Nanoseconds(u64),
    Cycles(u64),
}

impl fmt::Display for ElapsedTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ElapsedTime::Nanoseconds(ns) => write!(f, "{:>10}", ns),
            // the cyc is added here so we are made aware it's not nano-seconds
            ElapsedTime::Cycles(cycles) => write!(f, "{:>10} cyc", cycles),
            ElapsedTime::Undetermined => write!(f, ""),
        }
    }
}

impl KLogger {
    /// Time in nano seconds since KLogger init.
    fn elapsed(&self) -> ElapsedTime {
        if self.has_tsc {
            let cur = unsafe { x86::time::rdtsc() };

            if self.has_invariant_tsc && self.tsc_frequency.is_some() {
                let elapsed_cycles = cur - self.tsc_start;
                let tsc_frequency_hz = self.tsc_frequency.unwrap_or(1); // This won't fail, checked by if above

                // Basic is: let ns = elapsed_cycles / (tsc_frequency / NS_PER_SEC);
                // But we avoid removing all precision with division:
                let ns = (elapsed_cycles * NS_PER_SEC) / tsc_frequency_hz;

                ElapsedTime::Nanoseconds(ns)
            } else {
                // We can't convert cycles to a time
                ElapsedTime::Cycles(cur)
            }
        } else {
            // We don't know
            ElapsedTime::Undetermined
        }
    }
}

impl log::Log for KLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Trace
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let color = match record.level() {
                Level::Error => color::AnsiValue(202),
                Level::Warn => color::AnsiValue(167),
                Level::Info => color::AnsiValue(136),
                Level::Debug => color::AnsiValue(64),
                Level::Trace => color::AnsiValue(32),
            };

            sprintln!(
                "{}{}{} [{}{:5}{}] - {}: {}{}{}",
                color::Fg(color::LightYellow),
                self.elapsed(),
                color::Fg(color::Reset),
                color::Fg(color),
                record.level(),
                color::Fg(color::Reset),
                record.target(),
                color::Fg(color::LightWhite),
                record.args(),
                color::Fg(color::Reset),
            );
        }
    }

    fn flush(&self) {}
}

static mut LOGGER: KLogger = KLogger {
    has_tsc: false,
    has_invariant_tsc: false,
    tsc_start: 0,
    tsc_frequency: None,
};

/// A writer for the serial line. It holds a lock so
/// multiple cores/threads can print at the same time.
pub struct Writer<'a> {
    /// Lock on the serial line, it is implicitly released on a drop.
    #[allow(dead_code)]
    line_lock: spin::MutexGuard<'a, bool>,
}

impl<'a> Writer<'a> {
    /// Obtain a logger for the specified module.
    pub fn get_module(module: &str) -> Writer<'a> {
        use core::fmt::Write;
        let line_lock = unsafe { SERIAL_LINE_MUTEX.lock() };
        let mut ret = Writer { line_lock };
        write!(&mut ret, "[{}] ", module).expect("Writer");
        ret
    }

    /// Obtain a logger.
    pub fn get() -> Writer<'a> {
        let line_lock = unsafe { SERIAL_LINE_MUTEX.lock() };
        Writer { line_lock }
    }
}

impl<'a> ops::Drop for Writer<'a> {
    /// Release the logger (and the line_lock), end output with a newline.
    ///
    /// Serial standard mandates the use of '\r\n' for a newline and
    /// resetting the curser to the beginning.
    fn drop(&mut self) {
        use core::fmt::Write;
        #[allow(clippy::write_with_newline)]
        write!(self, "\r\n").expect("Newline");
    }
}

impl<'a> fmt::Write for Writer<'a> {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}

/// A writer that doesn't respect the locking procedure and tries to write at all costs.
///
/// It's used by sprint at the moment. It can also be useful as part of panics handlers
/// where we really want to print in all circumstances.
pub struct WriterNoDrop;

impl WriterNoDrop {
    pub fn get() -> WriterNoDrop {
        WriterNoDrop
    }
}

impl fmt::Write for WriterNoDrop {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}

pub fn init(level: Level) -> Result<(), SetLoggerError> {
    let cpuid = x86::cpuid::CpuId::new();

    unsafe {
        LOGGER.has_tsc = cpuid
            .get_feature_info()
            .map_or(false, |finfo| finfo.has_tsc());
        LOGGER.has_invariant_tsc = cpuid
            .get_extended_function_info()
            .map_or(false, |efinfo| efinfo.has_invariant_tsc());

        if LOGGER.has_tsc {
            LOGGER.tsc_start = x86::time::rdtsc();
        }

        let tsc_frequency_hz: Option<u64> = cpuid.get_tsc_info().and_then(|tinfo| {
            if tinfo.nominal_frequency() != 0 {
                // If we have a crystal clock we can calculate the tsc frequency directly
                Some(tinfo.tsc_frequency())
            } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
                // Skylake and Kabylake don't report the crystal clock frequency,
                // so we approximate with CPU base frequency:
                cpuid.get_processor_frequency_info().map(|pinfo| {
                    let cpu_base_freq_hz = pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ;
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
            } else {
                // We couldn't figure out the TSC frequency
                None
            }
        });

        // Check if we run in a VM and the hypervisor can give us the TSC frequency
        let vmm_tsc_frequency_hz: Option<u64> = cpuid
            .get_hypervisor_info()
            .and_then(|hv| hv.tsc_frequency().map(|tsc_khz| tsc_khz as u64 * KHZ_TO_HZ));

        if tsc_frequency_hz.is_some() {
            LOGGER.tsc_frequency = tsc_frequency_hz;
        } else if vmm_tsc_frequency_hz.is_some() {
            LOGGER.tsc_frequency = vmm_tsc_frequency_hz;
        }

        // Another way that segfaults in KVM:
        // The scalable bus frequency is encoded in the bit field MSR_PLATFORM_INFO[15:8]
        // and the nominal TSC frequency can be determined by multiplying this number
        // by a bus speed of 100 MHz.
        //(&mut LOGGER).tsc_frequency =
        //    ((x86::msr::rdmsr(x86::msr::MSR_PLATFORM_INFO) >> 8) & 0xff) * 1000000;

        log::set_logger(&LOGGER).map(|()| log::set_max_level(level.to_level_filter()))
    }
}

pub fn putchar(c: char) {
    unsafe {
        arch::putc(c);
    }
}
<commit_msg>Remove mut for the lock.<commit_after>#![cfg_attr(not(target_family = "unix"), no_std)]
#![crate_name = "klogger"]
#![crate_type = "lib"]

#[cfg(not(target_os = "none"))]
extern crate core;

use core::fmt;
use core::ops;

#[macro_use]
pub mod macros;

extern crate log;
extern crate termcodes;

#[cfg(target_arch = "x86_64")]
extern crate x86;

#[cfg(any(
    feature = "use_ioports",
    all(target_arch = "x86_64", target_os = "none")
))]
#[path = "arch/x86.rs"]
mod arch;

#[cfg(all(not(feature = "use_ioports"), target_family = "unix"))]
#[path = "arch/unix.rs"]
mod arch;

use log::{Level, Metadata, Record, SetLoggerError};
use termcodes::color;

/// One Mhz is that many Hz.
const MHZ_TO_HZ: u64 = 1000 * 1000;

/// One Khz is that many Hz.
const KHZ_TO_HZ: u64 = 1000;

/// One sec has that many ns.
const NS_PER_SEC: u64 = 1_000_000_000u64;

/// Global lock to protect serial line from concurrent printing.
pub static SERIAL_LINE_MUTEX: spin::Mutex<bool> = spin::Mutex::new(false);

#[derive(Debug)]
struct KLogger {
    /// Do we even have a TSC?
    ///
    /// If not bad.
    has_tsc: bool,
    /// Is the underlying TSC invariant?
    ///
    /// If not, bad.
    has_invariant_tsc: bool,
    /// Point in time when this Klogger got initialized
    tsc_start: u64,
    /// Frequency in Hz
    ///
    /// Sometimes we can't figure this out (yet)
    tsc_frequency: Option<u64>,
}

enum ElapsedTime {
    Undetermined,
    Nanoseconds(u64),
    Cycles(u64),
}

impl fmt::Display for ElapsedTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ElapsedTime::Nanoseconds(ns) => write!(f, "{:>10}", ns),
            // the cyc is added here so we are made aware it's not nano-seconds
            ElapsedTime::Cycles(cycles) => write!(f, "{:>10} cyc", cycles),
            ElapsedTime::Undetermined => write!(f, ""),
        }
    }
}

impl KLogger {
    /// Time in nano seconds since KLogger init.
    fn elapsed(&self) -> ElapsedTime {
        if self.has_tsc {
            let cur = unsafe { x86::time::rdtsc() };

            if self.has_invariant_tsc && self.tsc_frequency.is_some() {
                let elapsed_cycles = cur - self.tsc_start;
                let tsc_frequency_hz = self.tsc_frequency.unwrap_or(1); // This won't fail, checked by if above

                // Basic is: let ns = elapsed_cycles / (tsc_frequency / NS_PER_SEC);
                // But we avoid removing all precision with division:
                let ns = (elapsed_cycles * NS_PER_SEC) / tsc_frequency_hz;

                ElapsedTime::Nanoseconds(ns)
            } else {
                // We can't convert cycles to a time
                ElapsedTime::Cycles(cur)
            }
        } else {
            // We don't know
            ElapsedTime::Undetermined
        }
    }
}

impl log::Log for KLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Trace
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let color = match record.level() {
                Level::Error => color::AnsiValue(202),
                Level::Warn => color::AnsiValue(167),
                Level::Info => color::AnsiValue(136),
                Level::Debug => color::AnsiValue(64),
                Level::Trace => color::AnsiValue(32),
            };

            sprintln!(
                "{}{}{} [{}{:5}{}] - {}: {}{}{}",
                color::Fg(color::LightYellow),
                self.elapsed(),
                color::Fg(color::Reset),
                color::Fg(color),
                record.level(),
                color::Fg(color::Reset),
                record.target(),
                color::Fg(color::LightWhite),
                record.args(),
                color::Fg(color::Reset),
            );
        }
    }

    fn flush(&self) {}
}

static mut LOGGER: KLogger = KLogger {
    has_tsc: false,
    has_invariant_tsc: false,
    tsc_start: 0,
    tsc_frequency: None,
};

/// A writer for the serial line. It holds a lock so
/// multiple cores/threads can print at the same time.
pub struct Writer<'a> {
    /// Lock on the serial line, it is implicitly released on a drop.
    #[allow(dead_code)]
    line_lock: spin::MutexGuard<'a, bool>,
}

impl<'a> Writer<'a> {
    /// Obtain a logger for the specified module.
    pub fn get_module(module: &str) -> Writer<'a> {
        use core::fmt::Write;
        let line_lock = SERIAL_LINE_MUTEX.lock();
        let mut ret = Writer { line_lock };
        write!(&mut ret, "[{}] ", module).expect("Writer");
        ret
    }

    /// Obtain a logger.
    pub fn get() -> Writer<'a> {
        let line_lock = SERIAL_LINE_MUTEX.lock();
        Writer { line_lock }
    }
}

impl<'a> ops::Drop for Writer<'a> {
    /// Release the logger (and the line_lock), end output with a newline.
    ///
    /// Serial standard mandates the use of '\r\n' for a newline and
    /// resetting the curser to the beginning.
    fn drop(&mut self) {
        use core::fmt::Write;
        #[allow(clippy::write_with_newline)]
        write!(self, "\r\n").expect("Newline");
    }
}

impl<'a> fmt::Write for Writer<'a> {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}

/// A writer that doesn't respect the locking procedure and tries to write at all costs.
///
/// It's used by sprint at the moment. It can also be useful as part of panics handlers
/// where we really want to print in all circumstances.
pub struct WriterNoDrop;

impl WriterNoDrop {
    pub fn get() -> WriterNoDrop {
        WriterNoDrop
    }
}

impl fmt::Write for WriterNoDrop {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}

pub fn init(level: Level) -> Result<(), SetLoggerError> {
    let cpuid = x86::cpuid::CpuId::new();

    unsafe {
        LOGGER.has_tsc = cpuid
            .get_feature_info()
            .map_or(false, |finfo| finfo.has_tsc());
        LOGGER.has_invariant_tsc = cpuid
            .get_extended_function_info()
            .map_or(false, |efinfo| efinfo.has_invariant_tsc());

        if LOGGER.has_tsc {
            LOGGER.tsc_start = x86::time::rdtsc();
        }

        let tsc_frequency_hz: Option<u64> = cpuid.get_tsc_info().and_then(|tinfo| {
            if tinfo.nominal_frequency() != 0 {
                // If we have a crystal clock we can calculate the tsc frequency directly
                Some(tinfo.tsc_frequency())
            } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
                // Skylake and Kabylake don't report the crystal clock frequency,
                // so we approximate with CPU base frequency:
                cpuid.get_processor_frequency_info().map(|pinfo| {
                    let cpu_base_freq_hz = pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ;
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
            } else {
                // We couldn't figure out the TSC frequency
                None
            }
        });

        // Check if we run in a VM and the hypervisor can give us the TSC frequency
        let vmm_tsc_frequency_hz: Option<u64> = cpuid
            .get_hypervisor_info()
            .and_then(|hv| hv.tsc_frequency().map(|tsc_khz| tsc_khz as u64 * KHZ_TO_HZ));

        if tsc_frequency_hz.is_some() {
            LOGGER.tsc_frequency = tsc_frequency_hz;
        } else if vmm_tsc_frequency_hz.is_some() {
            LOGGER.tsc_frequency = vmm_tsc_frequency_hz;
        }

        // Another way that segfaults in KVM:
        // The scalable bus frequency is encoded in the bit field MSR_PLATFORM_INFO[15:8]
        // and the nominal TSC frequency can be determined by multiplying this number
        // by a bus speed of 100 MHz.
        //(&mut LOGGER).tsc_frequency =
        //    ((x86::msr::rdmsr(x86::msr::MSR_PLATFORM_INFO) >> 8) & 0xff) * 1000000;

        log::set_logger(&LOGGER).map(|()| log::set_max_level(level.to_level_filter()))
    }
}

pub fn putchar(c: char) {
    unsafe {
        arch::putc(c);
    }
}
<|endoftext|>


<commit_before>extern crate libc;
#[macro_use]
extern crate log;
extern crate env_logger as logger;
use log::LogLevel;
use std::io::prelude::*;
use std::str;
use std::char;
use std::ptr;
use std::path::Path;
use std::fs;
use std::fs::File;
use std::ffi::CStr;
use std::ffi::CString;

enum spsps_loc_ {}
enum spsps_errno {}

/*
#[repr(C)]
struct Loc{
	name: *const libc::c_char,
	line: u32,
	column: u32,
}
*/
//This is for the opaque C pointer
enum spsps_parser_ {}
//this will be the safe abstraction
#[derive(Debug)]
struct Parser{
	_ptr: *mut spsps_parser_,
	_fd: *mut libc::FILE
}

#[derive(Debug)]
struct Loc{
	ptr: *mut spsps_loc_
}

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *const libc::c_char, stream: *mut libc::FILE) -> *mut spsps_parser_;
	fn spsps_free(parser: *mut spsps_parser_);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut spsps_loc_) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut spsps_parser_) -> libc::c_char;
	fn spsps_consume_n(parser: *mut spsps_parser_, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut spsps_parser_);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut spsps_parser_) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut spsps_parser_) -> *mut spsps_loc_;
	fn spsps_peek(parser: *mut spsps_parser_) -> libc::c_char;
	fn spsps_peek_n(parser: *mut spsps_parser_, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut spsps_parser_, next: *const libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut spsps_parser_, next: *const libc::c_char) -> libc::c_int;
}

impl Parser{
	fn from_file(name: Option<&str>, path: &Path) -> Parser {
		unsafe{
			let c_path = CString::new(path.to_str().unwrap()).unwrap().as_ptr();
			debug!("from_file path: {:?}", CString::new(path.to_str().unwrap()).unwrap());
			let fd = libc::funcs::c95::stdio::fopen(c_path,  CString::new("r").unwrap().as_ptr());
			if fd.is_null() {
				panic!("Unable to open file to parse.");
			}
			match name{
			    Some(n) => Parser{
				    	_ptr: spsps_new(CString::new(n).unwrap().as_ptr(), fd),
				    	_fd: fd
			    	},
			    None => Parser{
				    	_ptr: spsps_new(ptr::null(), fd),
				    	_fd: fd
			    	}
			}
		 }
	}

	fn consume(&self) -> String {
		unsafe {
			char::from_u32(spsps_consume(self._ptr) as u32).unwrap().to_string()
		}
	}

	fn consume_n(&self, n: usize){
		unsafe { spsps_consume_n(self._ptr, n as libc::size_t); }
	}

	fn consume_whitespace(&self){
		unsafe { spsps_consume_whitespace(self._ptr); }
	}

	fn eof(&self) -> bool{
		unsafe { spsps_eof(self._ptr) as usize != 0 }
	}

	fn get_loc(&self) -> Loc {
		unsafe{
			Loc { ptr: spsps_loc(self._ptr) }
		}
	}

	fn peek(&self) -> String{
		let c_char = unsafe { spsps_peek(self._ptr) };
		char::from_u32(c_char as u32).unwrap().to_string()
	}

	fn peek_n(&self, n: usize) -> String{
		let cstr = unsafe{ spsps_peek_n(self._ptr, n as libc::size_t) };
		let safe_cstr = unsafe { CStr::from_ptr(cstr) };
		let retval = str::from_utf8(safe_cstr.to_bytes()).unwrap_or("").to_owned();
		unsafe { libc::free(safe_cstr.as_ptr() as *mut libc::c_void); }
		return retval;
	}

	fn peek_str(&self, needle: &str) -> bool {
		unsafe { spsps_peek_str(self._ptr, CString::new(needle).unwrap().as_ptr()) != 0 }
	}

	fn peek_str_and_consume(&self, needle: &str) -> bool {
		unsafe { spsps_peek_and_consume(self._ptr, CString::new(needle).unwrap().as_ptr()) != 0 }
	}
}

impl Drop for Parser{
	fn drop(&mut self) {
		unsafe{
			libc::fclose(self._fd);
			spsps_free(self._ptr);
		}
	}
}

impl Loc{
	fn to_string(&self) -> String{
		let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(self.ptr)) };
		let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
		unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
		retval
	}
}

impl Drop for Loc{
	fn drop(&mut self) {
		unsafe{ libc::free(self.ptr as *mut libc::c_void); }
	}
}

fn test_parser() -> Parser {
	let mut f = File::create("./foo.txt").unwrap();
	f.write_all(b"This is a test.\n");
	f.sync_data();
	let test_path = Path::new("./foo.txt");
	Parser::from_file(Some("test"), test_path)
}

#[test]
fn test_from_file(){
	logger::init().unwrap();
	let p = test_parser();
	//fs::remove_file("foo.txt").unwrap();
	println!("{:?}", p);
}

#[test]
fn test_peek_n(){
	let p = test_parser();
	let first_chars = p.peek_n(3);
	println!("{:?}", first_chars);
	assert_eq!(first_chars, "Thi");
}

#[test]
fn test_peek(){
	let p = test_parser();
	let first_char = p.peek();
	println!("{:?}", first_char);
	assert_eq!(first_char, "T");
}

#[test]
fn test_consume(){
	let p = test_parser();
	let first_char = p.consume();
	println!("{:?}", first_char);
	assert_eq!(first_char, "T");
}

#[test]
fn test_loc_to_string(){
	let p = test_parser();
	let location = p.get_loc();
	let loc_string = location.to_string();
	println!("{}",loc_string);
	assert_eq!(loc_string, "test:1:1");
}

#[test]
fn test_peek_consume(){
	let parser = test_parser();
	let p = parser.peek();
	let c = parser.consume();
	assert_eq!(p, c);
}

#[test]
fn test_zzz_cleanup()
{
	//fs::remove_file("foo.txt").unwrap();
}<commit_msg>Added test cleanup script to remove the dummy file.<commit_after>extern crate libc;
#[macro_use]
extern crate log;
extern crate env_logger as logger;
use log::LogLevel;
use std::io::prelude::*;
use std::str;
use std::char;
use std::ptr;
use std::path::Path;
use std::fs;
use std::fs::File;
use std::ffi::CStr;
use std::ffi::CString;

enum spsps_loc_ {}
enum spsps_errno {}

/*
#[repr(C)]
struct Loc{
	name: *const libc::c_char,
	line: u32,
	column: u32,
}
*/
//This is for the opaque C pointer
enum spsps_parser_ {}
//this will be the safe abstraction
#[derive(Debug)]
struct Parser{
	_ptr: *mut spsps_parser_,
	_fd: *mut libc::FILE
}

#[derive(Debug)]
struct Loc{
	ptr: *mut spsps_loc_
}

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *const libc::c_char, stream: *mut libc::FILE) -> *mut spsps_parser_;
	fn spsps_free(parser: *mut spsps_parser_);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut spsps_loc_) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut spsps_parser_) -> libc::c_char;
	fn spsps_consume_n(parser: *mut spsps_parser_, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut spsps_parser_);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut spsps_parser_) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut spsps_parser_) -> *mut spsps_loc_;
	fn spsps_peek(parser: *mut spsps_parser_) -> libc::c_char;
	fn spsps_peek_n(parser: *mut spsps_parser_, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut spsps_parser_, next: *const libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut spsps_parser_, next: *const libc::c_char) -> libc::c_int;
}

impl Parser{
	fn from_file(name: Option<&str>, path: &Path) -> Parser {
		unsafe{
			let c_path = CString::new(path.to_str().unwrap()).unwrap().as_ptr();
			debug!("from_file path: {:?}", CString::new(path.to_str().unwrap()).unwrap());
			let fd = libc::funcs::c95::stdio::fopen(c_path,  CString::new("r").unwrap().as_ptr());
			if fd.is_null() {
				panic!("Unable to open file to parse.");
			}
			match name{
			    Some(n) => Parser{
				    	_ptr: spsps_new(CString::new(n).unwrap().as_ptr(), fd),
				    	_fd: fd
			    	},
			    None => Parser{
				    	_ptr: spsps_new(ptr::null(), fd),
				    	_fd: fd
			    	}
			}
		 }
	}

	fn consume(&self) -> String {
		unsafe {
			char::from_u32(spsps_consume(self._ptr) as u32).unwrap().to_string()
		}
	}

	fn consume_n(&self, n: usize){
		unsafe { spsps_consume_n(self._ptr, n as libc::size_t); }
	}

	fn consume_whitespace(&self){
		unsafe { spsps_consume_whitespace(self._ptr); }
	}

	fn eof(&self) -> bool{
		unsafe { spsps_eof(self._ptr) as usize != 0 }
	}

	fn get_loc(&self) -> Loc {
		unsafe{
			Loc { ptr: spsps_loc(self._ptr) }
		}
	}

	fn peek(&self) -> String{
		let c_char = unsafe { spsps_peek(self._ptr) };
		char::from_u32(c_char as u32).unwrap().to_string()
	}

	fn peek_n(&self, n: usize) -> String{
		let cstr = unsafe{ spsps_peek_n(self._ptr, n as libc::size_t) };
		let safe_cstr = unsafe { CStr::from_ptr(cstr) };
		let retval = str::from_utf8(safe_cstr.to_bytes()).unwrap_or("").to_owned();
		unsafe { libc::free(safe_cstr.as_ptr() as *mut libc::c_void); }
		return retval;
	}

	fn peek_str(&self, needle: &str) -> bool {
		unsafe { spsps_peek_str(self._ptr, CString::new(needle).unwrap().as_ptr()) != 0 }
	}

	fn peek_str_and_consume(&self, needle: &str) -> bool {
		unsafe { spsps_peek_and_consume(self._ptr, CString::new(needle).unwrap().as_ptr()) != 0 }
	}
}

impl Drop for Parser{
	fn drop(&mut self) {
		unsafe{
			libc::fclose(self._fd);
			spsps_free(self._ptr);
		}
	}
}

impl Loc{
	fn to_string(&self) -> String{
		let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(self.ptr)) };
		let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
		unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
		retval
	}
}

impl Drop for Loc{
	fn drop(&mut self) {
		unsafe{ libc::free(self.ptr as *mut libc::c_void); }
	}
}

fn test_parser() -> Parser {
	let mut f = File::create("./foo.txt").unwrap();
	f.write_all(b"This is a test.\n");
	f.sync_data();
	let test_path = Path::new("./foo.txt");
	Parser::from_file(Some("test"), test_path)
}

#[test]
fn test_from_file(){
	logger::init().unwrap();
	let p = test_parser();
	//fs::remove_file("foo.txt").unwrap();
	println!("{:?}", p);
}

#[test]
fn test_peek_n(){
	let p = test_parser();
	let first_chars = p.peek_n(3);
	println!("{:?}", first_chars);
	assert_eq!(first_chars, "Thi");
}

#[test]
fn test_peek(){
	let p = test_parser();
	let first_char = p.peek();
	println!("{:?}", first_char);
	assert_eq!(first_char, "T");
}

#[test]
fn test_consume(){
	let p = test_parser();
	let first_char = p.consume();
	println!("{:?}", first_char);
	assert_eq!(first_char, "T");
}

#[test]
fn test_loc_to_string(){
	let p = test_parser();
	let location = p.get_loc();
	let loc_string = location.to_string();
	println!("{}",loc_string);
	assert_eq!(loc_string, "test:1:1");
}

#[test]
fn test_peek_consume(){
	let parser = test_parser();
	let p = parser.peek();
	let c = parser.consume();
	assert_eq!(p, c);
}

#[test]
fn test_zzz_cleanup()
{
	fs::remove_file("foo.txt").unwrap();
}<|endoftext|>


<commit_before>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/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.

//! Composable first-order predicate functions.
//!
//! This library implements an interface to "predicates" - boolean-valued
//! functions of one argument. This allows combinatorial logic to be created and
//! assembled at runtime and then used one or more times for evaluating values.
//! This sort of object is really useful when creating filters and checks that
//! can be changed at runtime with user interaction - it allows a clean
//! separation of concerns where the configuration code can be used to build up
//! a predicate, and then that predicate can be given to the code that does the
//! actual filtering without the filtering code knowing anything about user
//! configuration. See the examples for how this can work.
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! predicates = "0.5"
//! ```
//!
//! ## Examples
//!
//! A few different examples of how predicates might be used:
//!
//! ```
//! use predicates::prelude::*;
//!
//! use std::fmt;
//!
//! // The simplest predicates are `always()` and `never()`, which always returns
//! // `true` and always returns `false`, respectively. The values are simply
//! // ignored when evaluating against these predicates:
//! let always_true = predicate::always();
//! assert_eq!(true, always_true.eval(&5));
//! let always_false = predicate::never();
//! assert_eq!(false, always_false.eval(&5));
//!
//! // Pre-made predicates are available for types that implement the `PartialOrd` and
//! // `PartialEq` traits. The following example uses `lt`, but `eq`, `ne`, `le`, `gt`,
//! // `ge` are also available.
//! let less_than_ten = predicate::lt(10);
//! assert_eq!(true, less_than_ten.eval(&9));
//! assert_eq!(false, less_than_ten.eval(&11));
//!
//! // The `Predicate` type is actually a trait, and that trait implements a
//! // number of useful combinator functions. For example, evaluating for a value
//! // between two other values can be accomplished as follows:
//! let between_5_and_10 = predicate::ge(5).and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&11));
//! assert_eq!(false, between_5_and_10.eval(&4));
//!
//! // The `Predicate` trait is pretty simple, the core of it is an
//! // implementation of a `eval` function that takes a single argument and
//! // returns a `bool`. Implementing a custom `Predicate` still allows all the
//! // usual combinators of the `Predicate` trait to work!
//! struct IsTheAnswer;
//! impl Predicate<i32> for IsTheAnswer {
//!     fn eval(&self, variable: &i32) -> bool {
//!         *variable == 42
//!     }
//! }
//! impl fmt::Display for IsTheAnswer {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "var.is_the_answer()")
//!     }
//! }
//!
//! assert_eq!(true, IsTheAnswer.eval(&42));
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
//! assert_eq!(true, almost_the_answer.eval(&41));
//!
//! // Any function over a reference to the desired `Item` that returns `bool`
//! // can easily be made into a `Predicate` using the `predicate::function`
//! // function.
//! let bound = 5;
//! let predicate_fn = predicate::function(|&x| x >= bound);
//! let between_5_and_10 = predicate_fn.and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&3));
//! ```

#![deny(missing_docs, missing_debug_implementations)]

#[cfg(feature = "difference")]
extern crate difference;
#[cfg(feature = "float-cmp")]
extern crate float_cmp;
#[cfg(feature = "regex")]
extern crate regex;

pub mod prelude;

mod core;
pub use core::Predicate;
mod boxed;
pub use boxed::BoxPredicate;

// core predicates
pub mod constant;
pub mod function;
pub mod iter;
pub mod name;
pub mod ord;

// combinators
pub mod boolean;

// specialized primitive `Predicate` types
pub mod float;
pub mod path;
pub mod str;
<commit_msg>chore: Demote warnings<commit_after>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/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.

//! Composable first-order predicate functions.
//!
//! This library implements an interface to "predicates" - boolean-valued
//! functions of one argument. This allows combinatorial logic to be created and
//! assembled at runtime and then used one or more times for evaluating values.
//! This sort of object is really useful when creating filters and checks that
//! can be changed at runtime with user interaction - it allows a clean
//! separation of concerns where the configuration code can be used to build up
//! a predicate, and then that predicate can be given to the code that does the
//! actual filtering without the filtering code knowing anything about user
//! configuration. See the examples for how this can work.
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! predicates = "0.5"
//! ```
//!
//! ## Examples
//!
//! A few different examples of how predicates might be used:
//!
//! ```
//! use predicates::prelude::*;
//!
//! use std::fmt;
//!
//! // The simplest predicates are `always()` and `never()`, which always returns
//! // `true` and always returns `false`, respectively. The values are simply
//! // ignored when evaluating against these predicates:
//! let always_true = predicate::always();
//! assert_eq!(true, always_true.eval(&5));
//! let always_false = predicate::never();
//! assert_eq!(false, always_false.eval(&5));
//!
//! // Pre-made predicates are available for types that implement the `PartialOrd` and
//! // `PartialEq` traits. The following example uses `lt`, but `eq`, `ne`, `le`, `gt`,
//! // `ge` are also available.
//! let less_than_ten = predicate::lt(10);
//! assert_eq!(true, less_than_ten.eval(&9));
//! assert_eq!(false, less_than_ten.eval(&11));
//!
//! // The `Predicate` type is actually a trait, and that trait implements a
//! // number of useful combinator functions. For example, evaluating for a value
//! // between two other values can be accomplished as follows:
//! let between_5_and_10 = predicate::ge(5).and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&11));
//! assert_eq!(false, between_5_and_10.eval(&4));
//!
//! // The `Predicate` trait is pretty simple, the core of it is an
//! // implementation of a `eval` function that takes a single argument and
//! // returns a `bool`. Implementing a custom `Predicate` still allows all the
//! // usual combinators of the `Predicate` trait to work!
//! struct IsTheAnswer;
//! impl Predicate<i32> for IsTheAnswer {
//!     fn eval(&self, variable: &i32) -> bool {
//!         *variable == 42
//!     }
//! }
//! impl fmt::Display for IsTheAnswer {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "var.is_the_answer()")
//!     }
//! }
//!
//! assert_eq!(true, IsTheAnswer.eval(&42));
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
//! assert_eq!(true, almost_the_answer.eval(&41));
//!
//! // Any function over a reference to the desired `Item` that returns `bool`
//! // can easily be made into a `Predicate` using the `predicate::function`
//! // function.
//! let bound = 5;
//! let predicate_fn = predicate::function(|&x| x >= bound);
//! let between_5_and_10 = predicate_fn.and(predicate::le(10));
//! assert_eq!(true, between_5_and_10.eval(&7));
//! assert_eq!(false, between_5_and_10.eval(&3));
//! ```

#![warn(missing_docs, missing_debug_implementations)]

#[cfg(feature = "difference")]
extern crate difference;
#[cfg(feature = "float-cmp")]
extern crate float_cmp;
#[cfg(feature = "regex")]
extern crate regex;

pub mod prelude;

mod core;
pub use core::Predicate;
mod boxed;
pub use boxed::BoxPredicate;

// core predicates
pub mod constant;
pub mod function;
pub mod iter;
pub mod name;
pub mod ord;

// combinators
pub mod boolean;

// specialized primitive `Predicate` types
pub mod float;
pub mod path;
pub mod str;
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/mio/0.7.0")]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
// Disallow warnings when running tests.
#![cfg_attr(test, deny(warnings))]
// Disallow warnings in examples.
#![doc(test(attr(deny(warnings))))]

//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Features
//!
//! * Non-blocking TCP, UDP
//! * I/O event queue backed by epoll, kqueue, and IOCP
//! * Zero allocations at runtime
//! * Platform specific extensions
//!
//! # Non-goals
//!
//! The following are specifically omitted from Mio and are left to the user or
//! higher-level libraries.
//!
//! * File operations
//! * Thread pools / multi-threaded event loop
//! * Timers
//!
//! # Platforms
//!
//! Currently supported platforms:
//!
//! * Android
//! * DragonFly BSD
//! * FreeBSD
//! * Linux
//! * NetBSD
//! * OpenBSD
//! * Solaris
//! * Windows
//! * iOS
//! * macOS
//!
//! Mio can handle interfacing with each of the event systems of the
//! aforementioned platforms. The details of their implementation are further
//! discussed in [`Poll`].
//!
//! # Usage
//!
//! Using Mio starts by creating a [`Poll`], which reads events from the OS and
//! puts them into [`Events`]. You can handle IO events from the OS with it.
//!
//! For more detail, see [`Poll`].
//!
//! [`Poll`]: struct.Poll.html
//! [`Events`]: struct.Events.html
//!
//! # Example
//!
//! ```
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use mio::*;
//! use mio::net::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse()?;
//!
//! // Setup the server socket
//! let server = TcpListener::bind(addr)?;
//!
//! // Create a poll instance
//! let mut poll = Poll::new()?;
//!
//! // Start listening for incoming connections
//! poll.registry().register(&server, SERVER, Interests::READABLE)?;
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(addr)?;
//!
//! // Register the socket
//! poll.registry().register(&sock, CLIENT, Interests::READABLE)?;
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None)?;
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return Ok(());
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//! # }
//! ```

mod interests;
mod poll;
mod sys;
mod token;
mod waker;

pub mod event;
pub mod net;

#[doc(no_inline)]
pub use event::Events;
pub use interests::Interests;
pub use poll::{Poll, Registry};
pub use token::Token;
pub use waker::Waker;

#[cfg(unix)]
pub mod unix {
    //! Unix only extensions.
    pub use crate::sys::SocketAddr;
    pub use crate::sys::SourceFd;
}

pub mod guide {
    //! # Getting started guide.
    //!
    //! Using Mio starts by creating a [`Poll`] instance, which reads events from
    //! the OS and puts them into [`Events`].
    //!
    //! [`Poll`]: crate::Poll
    //! [`Events`]: crate::Events
    //!
    //! ```
    //! # use mio::{Poll, Events};
    //! # fn main() -> std::io::Result<()> {
    //! // `Poll` allows for polling of readiness events.
    //! let poll = Poll::new()?;
    //! // `Events` is collection of readiness `Event`s and can be filled by calling
    //! // `Poll::poll`.
    //! let events = Events::with_capacity(128);
    //! # drop((poll, events));
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! Next an [event source] needs to be registered with [`Poll`] to receive
    //! events for it. We'll use a [`TcpListener`] for which we'll receive an event
    //! once a connection is ready to be accepted.
    //!
    //! [event source]: crate::event::Source
    //! [`TcpListener`]: crate::net::TcpListener
    //!
    //! ```
    //! # use mio::net::TcpListener;
    //! # use mio::{Poll, Token, Interests};
    //! # fn main() -> std::io::Result<()> {
    //! # let poll = Poll::new()?;
    //! # let address = "127.0.0.1:0".parse().unwrap();
    //! // Create a `TcpListener`, binding it to `address`.
    //! let listener = TcpListener::bind(address)?;
    //!
    //! // Next we register it with `Poll` to receive events for it. The `SERVER`
    //! // `Token` is used to determine that we received an event for the listener
    //! // later on.
    //! const SERVER: Token = Token(0);
    //! poll.registry().register(&listener, SERVER, Interests::READABLE)?;
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! As the name “event source” suggests it a source of events which can poll
    //! using a `Poll` instance. Multiple event sources can be [registered] with
    //! `Poll`. After we've done this we can start polling these events. If we do
    //! this in a loop we've got ourselves an event loop.
    //!
    //! [registered]: crate::Registry::register
    //!
    //! ```
    //! # use std::io;
    //! # use std::time::Duration;
    //! # use mio::net::TcpListener;
    //! # use mio::{Poll, Token, Interests, Events};
    //! # fn main() -> io::Result<()> {
    //! # let mut poll = Poll::new()?;
    //! # let mut events = Events::with_capacity(128);
    //! # let address = "127.0.0.1:0".parse().unwrap();
    //! # let listener = TcpListener::bind(address)?;
    //! # const SERVER: Token = Token(0);
    //! # poll.registry().register(&listener, SERVER, Interests::READABLE)?;
    //! // Start our event loop.
    //! loop {
    //!     // Poll Mio for events, waiting at most 100 milliseconds.
    //!     poll.poll(&mut events, Some(Duration::from_millis(100)))?;
    //!
    //!     // Process each event.
    //!     for event in events.iter() {
    //!         // We can use the token we previously provided to `register` to
    //!         // determine for which type the event is.
    //!         match event.token() {
    //!             SERVER => loop {
    //!                 // One or more connections are ready, so we'll attempt to
    //!                 // accept them in a loop.
    //!                 match listener.accept() {
    //!                     Ok((connection, address)) => {
    //!                         println!("Got a connection from: {}", address);
    //! #                       drop(connection);
    //!                     },
    //!                     // An "would block error" is returned if the operation
    //!                     // is not ready, so we'll stop trying to accept
    //!                     // connections.
    //!                     Err(ref err) if would_block(err) => break,
    //!                     Err(err) => return Err(err),
    //!                 }
    //!             }
    //! #           _ => unreachable!(),
    //!         }
    //!     }
    //! #   return Ok(());
    //! }
    //!
    //! fn would_block(err: &io::Error) -> bool {
    //!     err.kind() == io::ErrorKind::WouldBlock
    //! }
    //! # }
    //! ```
}
<commit_msg>Fix type-o's in getting started guide<commit_after>#![doc(html_root_url = "https://docs.rs/mio/0.7.0")]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
// Disallow warnings when running tests.
#![cfg_attr(test, deny(warnings))]
// Disallow warnings in examples.
#![doc(test(attr(deny(warnings))))]

//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Features
//!
//! * Non-blocking TCP, UDP
//! * I/O event queue backed by epoll, kqueue, and IOCP
//! * Zero allocations at runtime
//! * Platform specific extensions
//!
//! # Non-goals
//!
//! The following are specifically omitted from Mio and are left to the user or
//! higher-level libraries.
//!
//! * File operations
//! * Thread pools / multi-threaded event loop
//! * Timers
//!
//! # Platforms
//!
//! Currently supported platforms:
//!
//! * Android
//! * DragonFly BSD
//! * FreeBSD
//! * Linux
//! * NetBSD
//! * OpenBSD
//! * Solaris
//! * Windows
//! * iOS
//! * macOS
//!
//! Mio can handle interfacing with each of the event systems of the
//! aforementioned platforms. The details of their implementation are further
//! discussed in [`Poll`].
//!
//! # Usage
//!
//! Using Mio starts by creating a [`Poll`], which reads events from the OS and
//! puts them into [`Events`]. You can handle IO events from the OS with it.
//!
//! For more detail, see [`Poll`].
//!
//! [`Poll`]: struct.Poll.html
//! [`Events`]: struct.Events.html
//!
//! # Example
//!
//! ```
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use mio::*;
//! use mio::net::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse()?;
//!
//! // Setup the server socket
//! let server = TcpListener::bind(addr)?;
//!
//! // Create a poll instance
//! let mut poll = Poll::new()?;
//!
//! // Start listening for incoming connections
//! poll.registry().register(&server, SERVER, Interests::READABLE)?;
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(addr)?;
//!
//! // Register the socket
//! poll.registry().register(&sock, CLIENT, Interests::READABLE)?;
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None)?;
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return Ok(());
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//! # }
//! ```

mod interests;
mod poll;
mod sys;
mod token;
mod waker;

pub mod event;
pub mod net;

#[doc(no_inline)]
pub use event::Events;
pub use interests::Interests;
pub use poll::{Poll, Registry};
pub use token::Token;
pub use waker::Waker;

#[cfg(unix)]
pub mod unix {
    //! Unix only extensions.
    pub use crate::sys::SocketAddr;
    pub use crate::sys::SourceFd;
}

pub mod guide {
    //! # Getting started guide.
    //!
    //! Using Mio starts by creating a [`Poll`] instance, which reads events from
    //! the OS and puts them into [`Events`].
    //!
    //! [`Poll`]: crate::Poll
    //! [`Events`]: crate::Events
    //!
    //! ```
    //! # use mio::{Poll, Events};
    //! # fn main() -> std::io::Result<()> {
    //! // `Poll` allows for polling of readiness events.
    //! let poll = Poll::new()?;
    //! // `Events` is collection of readiness `Event`s and can be filled by calling
    //! // `Poll::poll`.
    //! let events = Events::with_capacity(128);
    //! # drop((poll, events));
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! Next an [event source] needs to be registered with [`Poll`] to receive
    //! events for it. We'll use a [`TcpListener`] for which we'll receive an event
    //! once a connection is ready to be accepted.
    //!
    //! [event source]: crate::event::Source
    //! [`TcpListener`]: crate::net::TcpListener
    //!
    //! ```
    //! # use mio::net::TcpListener;
    //! # use mio::{Poll, Token, Interests};
    //! # fn main() -> std::io::Result<()> {
    //! # let poll = Poll::new()?;
    //! # let address = "127.0.0.1:0".parse().unwrap();
    //! // Create a `TcpListener`, binding it to `address`.
    //! let listener = TcpListener::bind(address)?;
    //!
    //! // Next we register it with `Poll` to receive events for it. The `SERVER`
    //! // `Token` is used to determine that we received an event for the listener
    //! // later on.
    //! const SERVER: Token = Token(0);
    //! poll.registry().register(&listener, SERVER, Interests::READABLE)?;
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! As the name “event source” suggests it is a source of events which can
    //! be polled using a `Poll` instance. Multiple event sources can be
    //! [registered] with `Poll`. After we've done this we can start polling
    //! these events. If we do this in a loop we've got ourselves an event loop.
    //!
    //! [registered]: crate::Registry::register
    //!
    //! ```
    //! # use std::io;
    //! # use std::time::Duration;
    //! # use mio::net::TcpListener;
    //! # use mio::{Poll, Token, Interests, Events};
    //! # fn main() -> io::Result<()> {
    //! # let mut poll = Poll::new()?;
    //! # let mut events = Events::with_capacity(128);
    //! # let address = "127.0.0.1:0".parse().unwrap();
    //! # let listener = TcpListener::bind(address)?;
    //! # const SERVER: Token = Token(0);
    //! # poll.registry().register(&listener, SERVER, Interests::READABLE)?;
    //! // Start our event loop.
    //! loop {
    //!     // Poll Mio for events, waiting at most 100 milliseconds.
    //!     poll.poll(&mut events, Some(Duration::from_millis(100)))?;
    //!
    //!     // Process each event.
    //!     for event in events.iter() {
    //!         // We can use the token we previously provided to `register` to
    //!         // determine for which type the event is.
    //!         match event.token() {
    //!             SERVER => loop {
    //!                 // One or more connections are ready, so we'll attempt to
    //!                 // accept them in a loop.
    //!                 match listener.accept() {
    //!                     Ok((connection, address)) => {
    //!                         println!("Got a connection from: {}", address);
    //! #                       drop(connection);
    //!                     },
    //!                     // A "would block error" is returned if the operation
    //!                     // is not ready, so we'll stop trying to accept
    //!                     // connections.
    //!                     Err(ref err) if would_block(err) => break,
    //!                     Err(err) => return Err(err),
    //!                 }
    //!             }
    //! #           _ => unreachable!(),
    //!         }
    //!     }
    //! #   return Ok(());
    //! }
    //!
    //! fn would_block(err: &io::Error) -> bool {
    //!     err.kind() == io::ErrorKind::WouldBlock
    //! }
    //! # }
    //! ```
}
<|endoftext|>


<commit_before>#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![cfg_attr(all(test, feature = "unstable"), feature(iter_arith))]

#[cfg(all(test, feature = "unstable"))] extern crate test;

#[macro_use]
extern crate either;

extern crate num;
extern crate rand;

use either::{Either, Left, Right};
use num::Float;
use rand::{Rng, XorShiftRng, weak_rng};
use std::mem::replace;

/// A set of possible criteria to decide when to stop the optimization.
pub enum StopCriterion {
    /// Stop if a specified number of function evaluations has been reached.
    MaxFunctionEvaluations(usize),

    /// Stop if a specified number of iterations has been reached.
    MaxIterations(usize),

    /// Stop if a certain target value range has been reached.
    ///
    /// The first value represents the desired **target value**, while the second one
    /// specifies an **absolute error** which is additionally applied to both directions.
    TargetValue(f64, f64)
}

/// Provide means to adjust the main paramters driving the algorithm.
pub struct Config {
    foods: usize,
    max_trials: usize,
    max_evals: Option<usize>,
    max_iters: Option<usize>,
    value_range: Option<(f64, f64)>
}

impl Config {
    /// Create a new `Config` which describes the behavior of the ABC algorithm.
    ///
    /// By default, this configuration provides sane defaults, i.e., it uses 20 food
    /// sources, a limit of 100 trials per food source
    pub fn new() -> Config {
        Config {
            foods: 20,
            max_trials: 100,
            max_evals: None,
            max_iters: None,
            value_range: None
        }
    }

    /// Set the number of food sources.
    pub fn foods(&mut self, foods: usize) -> &mut Config {
        assert!(foods > 0, "There must be at least 1 food source");
        self.foods = foods;
        self
    }

    /// Set the number of maximum trials per food source, bevore abondining the
    /// source.
    pub fn max_trials(&mut self, max_trials: usize) -> &mut Config {
        self.max_trials = max_trials;
        self
    }

    /// Enable the supplied stop criterion for future optimizations.
    pub fn stop(&mut self, criterion: StopCriterion) -> &mut Config {
        match criterion {
            MaxFunctionEvaluations(v) => self.max_evals = Some(v),
            MaxIterations(v) => self.max_iters = Some(v),
            TargetValue(v, e) => self.value_range = Some((v - e, v + e))
        }
        self
    }

    /// Optimize the given objective function by using the ABC algorithm with
    /// the specified parameters.
    pub fn optimize<F>(&self, dimensions: usize, low: f64, high: f64, objective: F)
        -> Solution
        where //X: Float,
              //Y: NumCast + Zero + PartialOrd + Clone,
              F: Fn(&[f64]) -> f64
    {
        assert!(dimensions > 0, "`dimensions` must be greater than zero");
        assert!(low.is_finite(), "`low` must be a finite number");
        assert!(high.is_finite(), "`high` must be a finite number");
        assert!(low < high, "`low` must be less than `high`");

        Optimizer::new(self, dimensions, low, high, &objective).run().left().unwrap()
    }
}

struct Optimizer<'a> {
    rng: XorShiftRng,
    config: &'a Config,
    dimensions: usize,
    low: f64,
    high: f64,
    objective: &'a Fn(&[f64]) -> f64,
    candidates: Vec<Candidate>,
    optimum: Option<Candidate>,
    evals: usize,
    iter: usize
}

impl<'a> Optimizer<'a> {
    fn new(config: &'a Config, dimensions: usize, low: f64, high: f64,
        objective: &'a Fn(&[f64]) -> f64) -> Optimizer<'a>
    {
        Optimizer {
            rng: weak_rng(),
            config: config,
            dimensions: dimensions,
            low: low,
            high: high,
            objective: objective,
            candidates: Vec::with_capacity(config.foods),
            optimum: None,
            evals: 0,
            iter: 0
        }
    }

    fn run(mut self) -> Either<Solution, ()> {
        self = try_right!(self.initialize());

        loop {
            self = try_right!(self.send_employed_bees());
            self = try_right!(self.send_onlooker_bees());
            self = try_right!(self.send_scout_bees());

            if self.config.max_iters.map_or(false, |max_iters| max_iters == self.iter + 1) {
                return Left(self.finish());
            }

            self.iter += 1;
        }
    }

    fn initialize(mut self) -> Either<Solution, Self> {
        for _ in 0..self.config.foods {
            self = try_right!(self.new_candidate(None));
        }

        Right(self)
    }

    fn send_employed_bees(mut self) -> Either<Solution, Self> {
        for i in 0..self.config.foods {
            self = try_right!(self.mutate_candidate(i));
        }

        // calculating probabilities
        let max_fitness = self.candidates.iter().fold(self.candidates[0].fitness,
            |acc, candidate| acc.max(candidate.fitness));

        for candidate in &mut self.candidates {
            candidate.probability = 0.9 * candidate.fitness / max_fitness + 0.1;
        }

        Right(self)
    }

    fn send_onlooker_bees(mut self) -> Either<Solution, Self> {
        let mut s = 0;
        let mut t = 0;

        while t < self.config.foods {
            if self.rng.gen::<f64>() < self.candidates[s].probability {
                t += 1;

                self = try_right!(self.mutate_candidate(s));
            }

            s += 1;
            if s == self.config.foods {
                s = 0;
            }
        }

        Right(self)
    }

    fn send_scout_bees(mut self) -> Either<Solution, Self> {
        let max_trials = self.candidates.iter().map(|c| c.trials).max().unwrap();

        if max_trials >= self.config.max_trials {
            for i in 0..self.config.foods {
                if self.candidates[i].trials == max_trials {
                    self = try_right!(self.new_candidate(Some(i)));
                }
            }
        }

        Right(self)
    }

    fn new_candidate(mut self, idx: Option<usize>) -> Either<Solution, Self> {
        let xs: Vec<_> = (0..self.dimensions).map(|_| {
            let x = self.rng.gen_range(self.low, self.high);
            assert!(x.is_finite(), "New random value is not finite!");
            x
            }).collect();
        let y = (self.objective)(&xs);
        let fitness = calc_fitness(y);

        self.evals += 1;

        let candidate = Candidate {
            xs: xs,
            y: y,
            fitness: fitness,
            probability: 0.0,
            trials: 0
        };

        let i = match idx {
            Some(i) => {
                self.candidates[i] = candidate;
                i
            },
            None => {
                self.candidates.push(candidate);
                self.candidates.len() - 1
            }
        };

        self.evaluate_candidate(i)
    }

    fn mutate_candidate(mut self, index: usize) -> Either<Solution, Self> {
        let rand_value = self.rng.gen_range(0, self.dimensions);
        let rand_candidate = (0..).map(|_| self.rng.gen_range(0, self.config.foods))
            .filter(|&other| other != index)
            .next().unwrap();

        let new_value = (self.candidates[index].xs[rand_value] +
            (self.candidates[index].xs[rand_value] - self.candidates[rand_candidate].xs[rand_value]) *
            (self.rng.gen::<f64>() - 0.5) * 2.0)
            .min(self.high).max(self.low);

        assert!(new_value.is_finite(), "Mutated value is not finite!");

        let old_value = replace(&mut self.candidates[index].xs[rand_value], new_value);

        let y = (self.objective)(&(self.candidates[index].xs));
        let fitness = calc_fitness(y);

        self.evals += 1;

        {
            let candidate = &mut self.candidates[index];
            if candidate.fitness < fitness {
                candidate.y = y;
                candidate.fitness = fitness;
                candidate.trials = 0;
            } else {
                candidate.xs[rand_value] = old_value;
                candidate.trials += 1;
            }
        }

        self.evaluate_candidate(index)
    }

    fn evaluate_candidate(mut self, idx: usize) -> Either<Solution, Self> {
        {
            let candidate = &self.candidates[idx];

            // upldate global optimum, if necessary
            if self.optimum.as_ref().map_or(true, |optimum| candidate.y < optimum.y) {
                self.optimum = Some(candidate.clone());
            }
        }

        // abort if the maximum
        if self.config.max_evals.map_or(false, |max_evals| max_evals == self.evals) ||
            self.config.value_range.map_or(false, |(l, h)| self.optimum.as_ref().map_or(false,
                |optimum| l <= optimum.y && optimum.y <= h))
        {
            return Left(self.finish());
        }

        Right(self)
    }

    fn finish(self) -> Solution {
        let optimum = self.optimum.unwrap();

        Solution {
            xs: optimum.xs,
            y: optimum.y,
            fitness: optimum.fitness,
            evals: self.evals,
            iters: self.iter + 1
        }
    }
}

#[derive(Clone, Debug)]
struct Candidate {
    xs: Vec<f64>,
    y: f64,
    fitness: f64,
    probability: f64,
    trials: usize
}

#[derive(Debug)]
pub struct Solution {
    pub xs: Vec<f64>,
    pub y: f64,
    pub fitness: f64,
    pub evals: usize,
    pub iters: usize
}

#[inline(always)]
fn calc_fitness(y: f64) -> f64 {
    if y >= 0.0 {
        1.0 / (1.0 + y)
    } else {
        1.0 + y.abs()
    }
}

// re-exports
pub use StopCriterion::*;

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;

    use super::*;
    use super::problems::*;

    macro_rules! benches {
        ($($name: ident, $d: expr, $l: expr, $u: expr, $y: expr, $e: expr, $f: ident;)*) => {
            $(
                #[bench]
                fn $name(b: &mut Bencher) {
                    let mut abc = Config::new();
                    abc.stop(TargetValue($y, $e));

                    b.iter(|| abc.optimize($d, $l, $u, &$f))
                }
            )*
        }
    }

    benches! {
        ackley_1d, 1, -32.768, 32.768, 0.0, 1.0e-10, ackley;
        ackley_2d, 2, -32.768, 32.768, 0.0, 1.0e-10, ackley;
        ackley_4d, 4, -32.768, 32.768, 0.0, 1.0e-10, ackley;
        ackley_8d, 8, -32.768, 32.768, 0.0, 1.0e-10, ackley;
        ackley_16d, 16, -32.768, 32.768, 0.0, 1.0e-10, ackley;
    }
}

#[cfg(all(test, feature = "unstable"))]
mod problems {
    use std::f64::consts::PI;

    pub fn ackley(xs: &[f64]) -> f64 {
        let a = 20.0;
        let b = 0.2;
        let c = 2.0 * PI;

        -a * (-b * (xs.iter().map(|&x| x.powi(2)).sum::<f64>() / xs.len() as f64).sqrt()).exp() -
            (xs.iter().map(|&x| (c*x).cos()).sum::<f64>() / xs.len() as f64).exp() + a + 1.0f64.exp()
    }

    pub fn sphere(xs: &[f64]) -> f64 {
        xs.iter().map(|v| v * v).sum()
    }

/*
    fn Rastrigin(xs: &[f64]) -> f64 {
        let y = xs.iter().map(|v| {
            v.powi(2) - 10.0 * (2.0 * PI * v).cos()
        }).sum::<f64>() + 10.0;
        println!("y = {}", y);
        return y;
    }*/
}
<commit_msg>Add more benchmarks and verification<commit_after>#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![cfg_attr(all(test, feature = "unstable"), feature(iter_arith))]

#[cfg(all(test, feature = "unstable"))] extern crate test;

#[macro_use]
extern crate either;

extern crate num;
extern crate rand;

use either::{Either, Left, Right};
use num::Float;
use rand::{Rng, XorShiftRng, weak_rng};
use std::mem::replace;

/// A set of possible criteria to decide when to stop the optimization.
pub enum StopCriterion {
    /// Stop if a specified number of function evaluations has been reached.
    MaxFunctionEvaluations(usize),

    /// Stop if a specified number of iterations has been reached.
    MaxIterations(usize),

    /// Stop if a certain target value range has been reached.
    ///
    /// The first value represents the desired **target value**, while the second one
    /// specifies an **absolute error** which is additionally applied to both directions.
    TargetValue(f64, f64)
}

/// Provide means to adjust the main paramters driving the algorithm.
pub struct Config {
    foods: usize,
    max_trials: usize,
    max_evals: Option<usize>,
    max_iters: Option<usize>,
    value_range: Option<(f64, f64)>
}

impl Config {
    /// Create a new `Config` which describes the behavior of the ABC algorithm.
    ///
    /// By default, this configuration provides sane defaults, i.e., it uses 20 food
    /// sources, a limit of 100 trials per food source
    pub fn new() -> Config {
        Config {
            foods: 20,
            max_trials: 100,
            max_evals: None,
            max_iters: None,
            value_range: None
        }
    }

    /// Set the number of food sources.
    pub fn foods(&mut self, foods: usize) -> &mut Config {
        assert!(foods > 0, "There must be at least 1 food source");
        self.foods = foods;
        self
    }

    /// Set the number of maximum trials per food source, bevore abondining the
    /// source.
    pub fn max_trials(&mut self, max_trials: usize) -> &mut Config {
        self.max_trials = max_trials;
        self
    }

    /// Enable the supplied stop criterion for future optimizations.
    pub fn stop(&mut self, criterion: StopCriterion) -> &mut Config {
        match criterion {
            MaxFunctionEvaluations(v) => self.max_evals = Some(v),
            MaxIterations(v) => self.max_iters = Some(v),
            TargetValue(v, e) => self.value_range = Some((v - e, v + e))
        }
        self
    }

    /// Optimize the given objective function by using the ABC algorithm with
    /// the specified parameters.
    pub fn optimize<F>(&self, dimensions: usize, low: f64, high: f64, objective: F)
        -> Solution
        where //X: Float,
              //Y: NumCast + Zero + PartialOrd + Clone,
              F: Fn(&[f64]) -> f64
    {
        assert!(dimensions > 0, "`dimensions` must be greater than zero");
        assert!(low.is_finite(), "`low` must be a finite number");
        assert!(high.is_finite(), "`high` must be a finite number");
        assert!(low < high, "`low` must be less than `high`");

        Optimizer::new(self, dimensions, low, high, &objective).run().left().unwrap()
    }
}

struct Optimizer<'a> {
    rng: XorShiftRng,
    config: &'a Config,
    dimensions: usize,
    low: f64,
    high: f64,
    objective: &'a Fn(&[f64]) -> f64,
    candidates: Vec<Candidate>,
    optimum: Option<Candidate>,
    evals: usize,
    iter: usize
}

impl<'a> Optimizer<'a> {
    fn new(config: &'a Config, dimensions: usize, low: f64, high: f64,
        objective: &'a Fn(&[f64]) -> f64) -> Optimizer<'a>
    {
        Optimizer {
            rng: weak_rng(),
            config: config,
            dimensions: dimensions,
            low: low,
            high: high,
            objective: objective,
            candidates: Vec::with_capacity(config.foods),
            optimum: None,
            evals: 0,
            iter: 0
        }
    }

    fn run(mut self) -> Either<Solution, ()> {
        self = try_right!(self.initialize());

        loop {
            self = try_right!(self.send_employed_bees());
            self = try_right!(self.send_onlooker_bees());
            self = try_right!(self.send_scout_bees());

            if self.config.max_iters.map_or(false, |max_iters| max_iters == self.iter + 1) {
                return Left(self.finish());
            }

            self.iter += 1;
        }
    }

    fn initialize(mut self) -> Either<Solution, Self> {
        for _ in 0..self.config.foods {
            self = try_right!(self.new_candidate(None));
        }

        Right(self)
    }

    fn send_employed_bees(mut self) -> Either<Solution, Self> {
        for i in 0..self.config.foods {
            self = try_right!(self.mutate_candidate(i));
        }

        // calculating probabilities
        let max_fitness = self.candidates.iter().fold(self.candidates[0].fitness,
            |acc, candidate| acc.max(candidate.fitness));

        for candidate in &mut self.candidates {
            candidate.probability = 0.9 * candidate.fitness / max_fitness + 0.1;
        }

        Right(self)
    }

    fn send_onlooker_bees(mut self) -> Either<Solution, Self> {
        let mut s = 0;
        let mut t = 0;

        while t < self.config.foods {
            if self.rng.gen::<f64>() < self.candidates[s].probability {
                t += 1;

                self = try_right!(self.mutate_candidate(s));
            }

            s += 1;
            if s == self.config.foods {
                s = 0;
            }
        }

        Right(self)
    }

    fn send_scout_bees(mut self) -> Either<Solution, Self> {
        let max_trials = self.candidates.iter().map(|c| c.trials).max().unwrap();

        if max_trials >= self.config.max_trials {
            for i in 0..self.config.foods {
                if self.candidates[i].trials == max_trials {
                    self = try_right!(self.new_candidate(Some(i)));
                }
            }
        }

        Right(self)
    }

    fn new_candidate(mut self, idx: Option<usize>) -> Either<Solution, Self> {
        let xs: Vec<_> = (0..self.dimensions).map(|_| {
            let x = self.rng.gen_range(self.low, self.high);
            assert!(x.is_finite(), "New random value is not finite!");
            x
            }).collect();
        let y = (self.objective)(&xs);
        let fitness = calc_fitness(y);

        self.evals += 1;

        let candidate = Candidate {
            xs: xs,
            y: y,
            fitness: fitness,
            probability: 0.0,
            trials: 0
        };

        let i = match idx {
            Some(i) => {
                self.candidates[i] = candidate;
                i
            },
            None => {
                self.candidates.push(candidate);
                self.candidates.len() - 1
            }
        };

        self.evaluate_candidate(i)
    }

    fn mutate_candidate(mut self, index: usize) -> Either<Solution, Self> {
        let rand_value = self.rng.gen_range(0, self.dimensions);
        let rand_candidate = (0..).map(|_| self.rng.gen_range(0, self.config.foods))
            .filter(|&other| other != index)
            .next().unwrap();

        let new_value = (self.candidates[index].xs[rand_value] +
            (self.candidates[index].xs[rand_value] - self.candidates[rand_candidate].xs[rand_value]) *
            (self.rng.gen::<f64>() - 0.5) * 2.0)
            .min(self.high).max(self.low);

        assert!(new_value.is_finite(), "Mutated value is not finite!");

        let old_value = replace(&mut self.candidates[index].xs[rand_value], new_value);

        let y = (self.objective)(&(self.candidates[index].xs));
        let fitness = calc_fitness(y);

        self.evals += 1;

        {
            let candidate = &mut self.candidates[index];
            if candidate.fitness < fitness {
                candidate.y = y;
                candidate.fitness = fitness;
                candidate.trials = 0;
            } else {
                candidate.xs[rand_value] = old_value;
                candidate.trials += 1;
            }
        }

        self.evaluate_candidate(index)
    }

    fn evaluate_candidate(mut self, idx: usize) -> Either<Solution, Self> {
        {
            let candidate = &self.candidates[idx];

            // upldate global optimum, if necessary
            if self.optimum.as_ref().map_or(true, |optimum| candidate.y < optimum.y) {
                self.optimum = Some(candidate.clone());
            }
        }

        // abort if the maximum
        if self.config.max_evals.map_or(false, |max_evals| max_evals == self.evals) ||
            self.config.value_range.map_or(false, |(l, h)| self.optimum.as_ref().map_or(false,
                |optimum| l <= optimum.y && optimum.y <= h))
        {
            return Left(self.finish());
        }

        Right(self)
    }

    fn finish(self) -> Solution {
        let optimum = self.optimum.unwrap();

        Solution {
            xs: optimum.xs,
            y: optimum.y,
            fitness: optimum.fitness,
            evals: self.evals,
            iters: self.iter + 1
        }
    }
}

#[derive(Clone, Debug)]
struct Candidate {
    xs: Vec<f64>,
    y: f64,
    fitness: f64,
    probability: f64,
    trials: usize
}

#[derive(Debug)]
pub struct Solution {
    pub xs: Vec<f64>,
    pub y: f64,
    pub fitness: f64,
    pub evals: usize,
    pub iters: usize
}

#[inline(always)]
fn calc_fitness(y: f64) -> f64 {
    if y >= 0.0 {
        1.0 / (1.0 + y)
    } else {
        1.0 + y.abs()
    }
}

// re-exports
pub use StopCriterion::*;

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;

    use super::*;
    use super::problems::*;

    macro_rules! benches {
        ($($name: ident, $d: expr, $l: expr, $u: expr, $y: expr, $e: expr, $xs: expr, $f: ident;)*) => {
            $(
                #[bench]
                fn $name(b: &mut Bencher) {
                    let optimum = $xs;
                    assert!($d == optimum.len());

                    let mut abc = Config::new();
                    abc.stop(TargetValue($y, $e));

                    b.iter(|| {
                        let solution = abc.optimize($d, $l, $u, &$f);

                        for i in 0..$d {
                            assert!((solution.xs[i] - optimum[i]).abs() < 1.0e-5);
                        }

                        solution
                    })
                }
            )*
        }
    }

    benches! {
        sphere_01d, 1, -5.12, 5.12, 0.0, 1.0e-10, vec![0.0f64; 1], sphere;
        sphere_02d, 2, -5.12, 5.12, 0.0, 1.0e-10, vec![0.0f64; 2], sphere;
        sphere_04d, 4, -5.12, 5.12, 0.0, 1.0e-10, vec![0.0f64; 4], sphere;
        sphere_08d, 8, -5.12, 5.12, 0.0, 1.0e-10, vec![0.0f64; 8], sphere;
        sphere_16d, 16, -5.12, 5.12, 0.0, 1.0e-10, vec![0.0f64; 16], sphere;

        ackley_01d, 1, -32.768, 32.768, 0.0, 1.0e-10, vec![0.0f64; 1], ackley;
        ackley_02d, 2, -32.768, 32.768, 0.0, 1.0e-10, vec![0.0f64; 2], ackley;
        ackley_04d, 4, -32.768, 32.768, 0.0, 1.0e-10, vec![0.0f64; 4], ackley;
        ackley_08d, 8, -32.768, 32.768, 0.0, 1.0e-10, vec![0.0f64; 8], ackley;
        ackley_16d, 16, -32.768, 32.768, 0.0, 1.0e-10, vec![0.0f64; 16], ackley;

        booth_2d, 2, -10.0, 10.0, 0.0, 1.0e-10, vec![1.0, 3.0], booth;
    }
}

#[cfg(all(test, feature = "unstable"))]
mod problems {
    use std::f64::consts::PI;

    // bowl-shaped
    pub fn sphere(xs: &[f64]) -> f64 {
        xs.iter().map(|v| v * v).sum()
    }

    // many local minima
    pub fn ackley(xs: &[f64]) -> f64 {
        let a = 20.0;
        let b = 0.2;
        let c = 2.0 * PI;

        -a * (-b * (xs.iter().map(|&x| x.powi(2)).sum::<f64>() / xs.len() as f64).sqrt()).exp() -
            (xs.iter().map(|&x| (c*x).cos()).sum::<f64>() / xs.len() as f64).exp() + a + 1.0f64.exp()
    }

    // plate-shaped
    pub fn booth(xs: &[f64]) -> f64 {
        assert!(xs.len() == 2);

        (xs[0] + 2.0*xs[1] - 7.0).powi(2) + (2.0*xs[0] + xs[1] - 5.0).powi(2)
    }
}
<|endoftext|>


<commit_before><commit_msg>Added non-blocking question() method.<commit_after><|endoftext|>