<commit_before>//! AHash is a hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to `FxHash`, or a fast equivalent to `SipHash`.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a `HashMap` without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! aHash is not a cryptographically secure hash.
//!
//! # Example
//! ```
//! use ahash::{AHasher, RandomState};
//! use std::collections::HashMap;
//!
//! let mut map: HashMap<i32, i32, RandomState> = HashMap::default();
//! map.insert(12, 34);
//! ```
//! For convinence wrappers called `AHashMap` and `AHashSet` are also provided.
//! These to the same thing with slightly less typing.
//! ```ignore
//! use ahash::AHashMap;
//!
//! let mut map: AHashMap<i32, i32> = AHashMap::with_capacity(4);
//! map.insert(12, 34);
//! map.insert(56, 78);
//! ```
#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(feature = "specialize", feature(specialization))]

#[macro_use]
mod convert;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
mod aes_hash;
mod fallback_hash;
#[cfg(test)]
mod hash_quality_test;

mod operations;
#[cfg(feature = "std")]
mod hash_map;
#[cfg(feature = "std")]
mod hash_set;
mod random_state;
mod specialize;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri))))]
pub use crate::fallback_hash::AHasher;
pub use crate::random_state::RandomState;

pub use crate::specialize::CallHasher;

#[cfg(feature = "std")]
pub use crate::hash_map::AHashMap;
#[cfg(feature = "std")]
pub use crate::hash_set::AHashSet;
use core::hash::Hasher;
use core::hash::BuildHasher;

/// Provides a default [Hasher] with fixed keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// Generally it is preferable to use [RandomState] instead, so that different
/// hashmaps will have different keys. However if fixed keys are desireable this
/// may be used instead.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, RandomState};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, BuildHasherDefault<AHasher>> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {

    /// Constructs a new [AHasher] with fixed keys.
    /// If `std` is enabled these will be generated upon first invocation.
    /// Otherwise if the `compile-time-rng`feature is enabled these will be generated at compile time.
    /// If neither of these features are available, hardcoded constants will be used.
    ///
    /// Because the values are fixed, different hashers will all hash elements the same way.
    /// This could make hash values predictable, if DOS attacks are a concern. If this behaviour is
    /// not required, it may be preferable to use [RandomState] instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        RandomState::with_fixed_keys().build_hasher()
    }
}

/// Used for specialization. (Sealed)
pub(crate) trait HasherExt: Hasher {
    #[doc(hidden)]
    fn hash_u64(self, value: u64) -> u64;

    #[doc(hidden)]
    fn short_finish(&self) -> u64;
}

impl<T: Hasher> HasherExt for T {
    #[inline]
    #[cfg(feature = "specialize")]
    default fn hash_u64(self, value: u64) -> u64 {
        value.get_hash(self)
    }
    #[inline]
    #[cfg(not(feature = "specialize"))]
    fn hash_u64(self, value: u64) -> u64 {
        value.get_hash(self)
    }
    #[inline]
    #[cfg(feature = "specialize")]
    default fn short_finish(&self) -> u64 {
        self.finish()
    }
    #[inline]
    #[cfg(not(feature = "specialize"))]
    fn short_finish(&self) -> u64 {
        self.finish()
    }
}

// #[inline(never)]
// #[doc(hidden)]
// pub fn hash_test(input: &[u8]) -> u64 {
//     let a = AHasher::new_with_keys(11111111111_u128, 2222222222_u128);
//     input.get_hash(a)
// }

#[cfg(feature = "std")]
#[cfg(test)]
mod test {
    use crate::convert::Convert;
    use crate::*;
    use std::collections::HashMap;

    #[test]
    fn test_default_builder() {
        use core::hash::BuildHasherDefault;

        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, RandomState>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = b"dddddddd";
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

    #[test]
    fn test_ahasher_construction() {
        let _ = AHasher::new_with_keys(1234, 5678);
    }
}
<commit_msg>Switch to min_specialization<commit_after>//! AHash is a hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to `FxHash`, or a fast equivalent to `SipHash`.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a `HashMap` without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! aHash is not a cryptographically secure hash.
//!
//! # Example
//! ```
//! use ahash::{AHasher, RandomState};
//! use std::collections::HashMap;
//!
//! let mut map: HashMap<i32, i32, RandomState> = HashMap::default();
//! map.insert(12, 34);
//! ```
//! For convinence wrappers called `AHashMap` and `AHashSet` are also provided.
//! These to the same thing with slightly less typing.
//! ```ignore
//! use ahash::AHashMap;
//!
//! let mut map: AHashMap<i32, i32> = AHashMap::with_capacity(4);
//! map.insert(12, 34);
//! map.insert(56, 78);
//! ```
#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(feature = "specialize", feature(min_specialization))]

#[macro_use]
mod convert;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
mod aes_hash;
mod fallback_hash;
#[cfg(test)]
mod hash_quality_test;

mod operations;
#[cfg(feature = "std")]
mod hash_map;
#[cfg(feature = "std")]
mod hash_set;
mod random_state;
mod specialize;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri))))]
pub use crate::fallback_hash::AHasher;
pub use crate::random_state::RandomState;

pub use crate::specialize::CallHasher;

#[cfg(feature = "std")]
pub use crate::hash_map::AHashMap;
#[cfg(feature = "std")]
pub use crate::hash_set::AHashSet;
use core::hash::Hasher;
use core::hash::BuildHasher;

/// Provides a default [Hasher] with fixed keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// Generally it is preferable to use [RandomState] instead, so that different
/// hashmaps will have different keys. However if fixed keys are desireable this
/// may be used instead.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, RandomState};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, BuildHasherDefault<AHasher>> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {

    /// Constructs a new [AHasher] with fixed keys.
    /// If `std` is enabled these will be generated upon first invocation.
    /// Otherwise if the `compile-time-rng`feature is enabled these will be generated at compile time.
    /// If neither of these features are available, hardcoded constants will be used.
    ///
    /// Because the values are fixed, different hashers will all hash elements the same way.
    /// This could make hash values predictable, if DOS attacks are a concern. If this behaviour is
    /// not required, it may be preferable to use [RandomState] instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        RandomState::with_fixed_keys().build_hasher()
    }
}

/// Used for specialization. (Sealed)
pub(crate) trait HasherExt: Hasher {
    #[doc(hidden)]
    fn hash_u64(self, value: u64) -> u64;

    #[doc(hidden)]
    fn short_finish(&self) -> u64;
}

impl<T: Hasher> HasherExt for T {
    #[inline]
    #[cfg(feature = "specialize")]
    default fn hash_u64(self, value: u64) -> u64 {
        value.get_hash(self)
    }
    #[inline]
    #[cfg(not(feature = "specialize"))]
    fn hash_u64(self, value: u64) -> u64 {
        value.get_hash(self)
    }
    #[inline]
    #[cfg(feature = "specialize")]
    default fn short_finish(&self) -> u64 {
        self.finish()
    }
    #[inline]
    #[cfg(not(feature = "specialize"))]
    fn short_finish(&self) -> u64 {
        self.finish()
    }
}

// #[inline(never)]
// #[doc(hidden)]
// pub fn hash_test(input: &[u8]) -> u64 {
//     let a = AHasher::new_with_keys(11111111111_u128, 2222222222_u128);
//     input.get_hash(a)
// }

#[cfg(feature = "std")]
#[cfg(test)]
mod test {
    use crate::convert::Convert;
    use crate::*;
    use std::collections::HashMap;

    #[test]
    fn test_default_builder() {
        use core::hash::BuildHasherDefault;

        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, RandomState>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = b"dddddddd";
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

    #[test]
    fn test_ahasher_construction() {
        let _ = AHasher::new_with_keys(1234, 5678);
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![deny(missing_docs)]

//! A logger configured via an environment variable which writes to standard
//! error with nice colored output for log levels.
//!
//! ## Example
//!
//! ```
//! extern crate pretty_env_logger;
//! #[macro_use] extern crate log;
//!
//! fn main() {
//!     pretty_env_logger::init();
//!
//!     trace!("a trace example");
//!     debug!("deboogging");
//!     info!("such information");
//!     warn!("o_O");
//!     error!("boom");
//! }
//! ```

extern crate env_logger;
extern crate log;
extern crate chrono;

use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use chrono::Local;
use env_logger::{fmt::{Color, Style, StyledValue}, Builder};
use log::Level;

fn colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str> {
    match level {
        Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
        Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
        Level::Info => style.set_color(Color::Green).value("INFO "),
        Level::Warn => style.set_color(Color::Yellow).value("WARN "),
        Level::Error => style.set_color(Color::Red).value("ERROR"),
    }
}

static MAX_MODULE_WIDTH: AtomicUsize = ATOMIC_USIZE_INIT;

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init() {
    try_init().unwrap();
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init_timed() {
    try_init_timed().unwrap();
}

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init() -> Result<(), log::SetLoggerError> {
    try_init_custom_env("RUST_LOG")
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed() -> Result<(), log::SetLoggerError> {
    try_init_timed_custom_env("RUST_LOG")
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
pub fn init_custom_env(environment_variable_name: &str) {
    try_init_custom_env(environment_variable_name).unwrap();
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse(&s);
    }

    builder.try_init()
}

/// Initialized the global logger with a timed pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_timed_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse(&s);
    }

    builder.try_init()
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} > {}",
            level,
            target,
            record.args(),
        )
    });

    builder
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and time formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_timed_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} {} > {}",
            Local::now().format("%Y-%m-%d %H:%M:%S"),
            level,
            target,
            record.args(),
        )
    });

    builder
}
<commit_msg>timestamps with milliseconds<commit_after>#![deny(warnings)]
#![deny(missing_docs)]

//! A logger configured via an environment variable which writes to standard
//! error with nice colored output for log levels.
//!
//! ## Example
//!
//! ```
//! extern crate pretty_env_logger;
//! #[macro_use] extern crate log;
//!
//! fn main() {
//!     pretty_env_logger::init();
//!
//!     trace!("a trace example");
//!     debug!("deboogging");
//!     info!("such information");
//!     warn!("o_O");
//!     error!("boom");
//! }
//! ```

extern crate env_logger;
extern crate log;
extern crate chrono;

use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use chrono::Local;
use env_logger::{fmt::{Color, Style, StyledValue}, Builder};
use log::Level;

fn colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str> {
    match level {
        Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
        Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
        Level::Info => style.set_color(Color::Green).value("INFO "),
        Level::Warn => style.set_color(Color::Yellow).value("WARN "),
        Level::Error => style.set_color(Color::Red).value("ERROR"),
    }
}

static MAX_MODULE_WIDTH: AtomicUsize = ATOMIC_USIZE_INIT;

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init() {
    try_init().unwrap();
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init_timed() {
    try_init_timed().unwrap();
}

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init() -> Result<(), log::SetLoggerError> {
    try_init_custom_env("RUST_LOG")
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed() -> Result<(), log::SetLoggerError> {
    try_init_timed_custom_env("RUST_LOG")
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
pub fn init_custom_env(environment_variable_name: &str) {
    try_init_custom_env(environment_variable_name).unwrap();
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse(&s);
    }

    builder.try_init()
}

/// Initialized the global logger with a timed pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_timed_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse(&s);
    }

    builder.try_init()
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} > {}",
            level,
            target,
            record.args(),
        )
    });

    builder
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and time formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_timed_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} {} > {}",
            Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
            level,
            target,
            record.args(),
        )
    });

    builder
}
<|endoftext|>


<commit_before>extern crate mio;

use mio::tcp::*;
use mio::TryWrite;
use std::net::SocketAddr;
use std::io::Result;
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
//use std::thread;
//use std::thread::JoinHandle;
//use std::sync::{Arc, RwLock, Condvar};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};

const CLIENT_TOKEN: mio::Token = mio::Token(1);

pub struct Client{
    socket: TcpStream,

    pub token: Token,

    interest: EventSet,

    send_queue: Vec<String>,

    debug: AtomicUsize
}

impl Client{
    pub fn new(event_loop: &mut EventLoop<Client>, address: &SocketAddr) -> Result<Client>{
        let stream = TcpStream::connect(address);
        if stream.is_ok(){
            let mut client = Client {
                socket: stream.unwrap(),
                send_queue: Vec::new(),
                token: CLIENT_TOKEN,
                interest: EventSet::readable() | EventSet::writable(),
                debug: AtomicUsize::new(0)
            };

            client.register(event_loop).ok();

            client.send_queue.push(String::from("Hell fucking yeah motherfucker"));
            client.send_queue.push(String::from("And so I wake in the morning"));
            client.send_queue.push(String::from("And I step outside"));
            client.send_queue.push(String::from("And I take a deep breath and I get real high"));
            client.send_queue.push(String::from("And I scream from the top of my lungs"));
            client.send_queue.push(String::from("What's going on?"));

            event_loop.run(&mut client).or_else(|e|{
                println!("Failed to start event loop!");
                Err(e)
            });

            return Ok(client);
        }
        else{
            Err(stream.unwrap_err())
        }
    }

    fn register(&mut self, event_loop: &mut EventLoop<Client>) -> Result<()>{
        event_loop.register(
            &self.socket,
            self.token,
            self.interest,
            PollOpt::edge() | PollOpt::oneshot()
        ).or_else(|e| {
            println!("Failed to register server! {:?}", e);
            Err(e)
        })
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<Client>) -> Result<()>{
        event_loop.reregister(&self.socket, self.token, self.interest, PollOpt::edge())
            .or_else(|e|{
                println!("I am a sad panda, {:?}", e);
                Err(e)
        })
    }
}

impl Handler for Client{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, _: &mut EventLoop<Client>) {
        println!("Begin client tick");

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<Client>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server crash or some shit?!");
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if !self.send_queue.is_empty(){
                if let Some(message) = self.send_queue.pop(){
                    match self.socket.try_write(message.as_bytes()){
                        Ok(Some(n)) => {
                            println!("Wrote {} bytes", n);
                        },
                        Ok(None) => {
                            println!("Nothing happened but it's okay I guess?");
                            self.send_queue.push(message);
                        },
                        Err(e) => {
                            println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                            self.send_queue.push(message);
                        }
                    };
                }
                else{
                    println!("Failed to pop message from queue!");
                }
                self.reregister(event_loop);
            }
            else{
                println!("WTF do you mean there's no messages for me?");
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");
        }

        self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

#[test]
fn connect(){
    let addr = "127.0.0.1:6969".parse().unwrap();

    let mut event_loop = EventLoop::new().ok().expect("Failed to create event loop!");
    if let Ok(mut client) = Client::new(&mut event_loop, &addr){
        println!("Starting debug loop");

        loop{
            if client.debug.load(Ordering::Relaxed) > 0{
                break;
            }
        }

        println!("Done with this shit");
    }
    else{
        println!("Y u no client??");
    }
}

#[cfg(test)]
mod test {
    use mio::tcp::*;
    use mio::TryWrite;
    use std::net::SocketAddr;
    //use lag_client::Client;

}
<commit_msg>broken; committing so I can access this later<commit_after>extern crate mio;

use mio::tcp::*;
use mio::TryWrite;
use std::net::SocketAddr;
use std::io::Result;
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
use std::thread;
use std::thread::JoinHandle;
use std::sync::{Arc, RwLock, Condvar};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::VecDeque;

const CLIENT_TOKEN: mio::Token = mio::Token(1);

pub struct ClientNetworkInterface{
    socket: TcpStream,

    thread_handle: Option<JoinHandle<()>>
}

impl ClientNetworkInterface{
    pub fn new(event_loop_ref: &mut Arc<RwLock<EventLoop<ClientNetworkInterface>>>, socket: TcpStream) -> ClientNetworkInterface{
        let interface = ClientNetworkInterface{
            socket: socket,
            thread_handle: None
        };

        let thread_event_loop_ref = event_loop_ref.clone();
        let handle = thread::spawn(move||{

            if let Ok(event_loop) = thread_event_loop_ref.write(){
                event_loop.run(&mut interface).ok();
            }
        });

        interface.thread_handle = Some(handle);

        return interface;
    }

    fn register(&mut self, event_loop_ref: &mut Arc<RwLock<EventLoop<ClientNetworkInterface>>>, client: Client){
        if let Ok(event_loop) = event_loop_ref.write(){
            event_loop.register(
                &self.socket,
                client.token,
                client.interest,
                PollOpt::edge() | PollOpt::oneshot()
            ).or_else(|e| {
                println!("Failed to register server! {:?}", e);
                Err(e)
            });
        }
    }

    fn reregister(&mut self, event_loop_ref: &mut Arc<RwLock<EventLoop<ClientNetworkInterface>>>, client: Client){
        if let Ok(event_loop) = event_loop_ref.write(){
            event_loop.reregister(&self.socket, client.token, client.interest, PollOpt::edge())
                .or_else(|e|{
                    println!("I am a sad panda, {:?}", e);
                    Err(e)
            });
        }
    }
}

pub struct Client{
    pub token: Token,

    interest: EventSet,

    send_queue: VecDeque<String>,

    debug: AtomicUsize
}

impl Client{
    pub fn new() -> Client{
        Client {
            send_queue: VecDeque::new(),
            token: CLIENT_TOKEN,
            interest: EventSet::readable() | EventSet::writable(),
            debug: AtomicUsize::new(0)
        }
        // client.register(event_loop).ok();
        //
        // client.send_queue.push_back(String::from("Hell fucking yeah motherfucker"));
        // client.send_queue.push_back(String::from("And so I wake in the morning"));
        // client.send_queue.push_back(String::from("And I step outside"));
        // client.send_queue.push_back(String::from("And I take a deep breath and I get real high"));
        // client.send_queue.push_back(String::from("And I scream from the top of my lungs"));
        // client.send_queue.push_back(String::from("What's going on?"));
        //
        //
        // event_loop.run(&mut client).or_else(|e|{
        //     println!("Failed to start event loop!");
        //     Err(e)
        // });
    }
}

impl Handler for ClientNetworkInterface{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, _: &mut EventLoop<ClientNetworkInterface>) {
        println!("Begin client tick");

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server crash or some shit?!");
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if !self.send_queue.is_empty(){
                if let Some(message) = self.send_queue.pop_front(){
                    match self.socket.try_write(message.as_bytes()){
                        Ok(Some(n)) => {
                            println!("Wrote {} bytes", n);
                        },
                        Ok(None) => {
                            println!("Nothing happened but it's okay I guess?");
                            self.send_queue.push_back(message);
                        },
                        Err(e) => {
                            println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                            self.send_queue.push_back(message);
                        }
                    };
                }
                else{
                    println!("Failed to pop message from queue!");
                }
                self.reregister(event_loop);
            }
            else{
                println!("WTF do you mean there's no messages for me?");
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");
        }

        self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

#[test]
fn connect(){
    let addr = "127.0.0.1:6969".parse().unwrap();

    let mut event_loop = EventLoop::new().ok().expect("Failed to create event loop!");
    if let Ok(mut client) = Client::new(&mut event_loop, &addr){
        println!("Starting debug loop");

        loop{
            if client.debug.load(Ordering::Relaxed) > 0{
                break;
            }
        }

        println!("Done with this shit");
    }
    else{
        println!("Y u no client??");
    }
}

#[cfg(test)]
mod test {
    use mio::tcp::*;
    use mio::TryWrite;
    use std::net::SocketAddr;
    //use lag_client::Client;

}
<|endoftext|>


<commit_before>//! This crate provides Rust interfaces for [NumPy C APIs][c-api],
//! especially for the [ndarray][ndarray] class.
//!
//! It uses [`pyo3`] for Rust bindings to CPython, and uses
//! [`ndarray`] as the Rust matrix library.
//!
//! To resolve its dependency on NumPy, it calls `import numpy.core` internally.
//! This means that this crate should work if you can use NumPy in your Python environment,
//! e.g. after installing it by `pip install numpy`. It does not matter whether you use
//! the system environment or a dedicated virtual environment.
//!
//! Loading NumPy is done automatically and on demand. So if it is not installed, the functions
//! provided by this crate will panic instead of returning a result.
//!
//! # Example
//!
//! ```
//! use numpy::pyo3::Python;
//! use numpy::ndarray::array;
//! use numpy::{ToPyArray, PyArray};
//!
//! Python::with_gil(|py| {
//!     let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!
//!     assert_eq!(
//!         py_array.readonly().as_array(),
//!         array![[1i64, 2], [3, 4]]
//!     );
//! })
//! ```
//!
//! [c-api]: https://numpy.org/doc/stable/reference/c-api
//! [ndarray]: https://numpy.org/doc/stable/reference/arrays.ndarray.html

// We often want to make the GIL lifetime explicit.
#![allow(clippy::needless_lifetimes)]

pub mod array;
pub mod borrow;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod slice_container;
mod sum_products;

pub use ndarray;
pub use pyo3;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::borrow::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn, PyReadwriteArray, PyReadwriteArray1,
    PyReadwriteArray2, PyReadwriteArray3, PyReadwriteArray4, PyReadwriteArray5, PyReadwriteArray6,
    PyReadwriteArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{dtype, Complex32, Complex64, Element, PyArrayDescr};
pub use crate::error::{DimensionalityError, FromVecError, NotContiguousError, TypeError};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
#[allow(deprecated)]
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::sum_products::{dot, einsum, inner};

pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

#[cfg(doctest)]
mod doctest {
    macro_rules! doc_comment {
        ($doc_string:expr, $mod_name:ident) => {
            #[doc = $doc_string]
            mod $mod_name {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

mod sealed {
    pub trait Sealed {}
}

#[cold]
#[inline(always)]
fn cold() {}

/// Create a [`PyArray`] with one, two or three dimensions.
///
/// This macro is backed by [`ndarray::array`].
///
/// # Example
///
/// ```
/// use numpy::pyo3::Python;
/// use numpy::ndarray::array;
/// use numpy::pyarray;
///
/// Python::with_gil(|py| {
///     let array = pyarray![py, [1, 2], [3, 4]];
///
///     assert_eq!(
///         array.readonly().as_array(),
///         array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<commit_msg>Fix missing re-export of BorrowError.<commit_after>//! This crate provides Rust interfaces for [NumPy C APIs][c-api],
//! especially for the [ndarray][ndarray] class.
//!
//! It uses [`pyo3`] for Rust bindings to CPython, and uses
//! [`ndarray`] as the Rust matrix library.
//!
//! To resolve its dependency on NumPy, it calls `import numpy.core` internally.
//! This means that this crate should work if you can use NumPy in your Python environment,
//! e.g. after installing it by `pip install numpy`. It does not matter whether you use
//! the system environment or a dedicated virtual environment.
//!
//! Loading NumPy is done automatically and on demand. So if it is not installed, the functions
//! provided by this crate will panic instead of returning a result.
//!
//! # Example
//!
//! ```
//! use numpy::pyo3::Python;
//! use numpy::ndarray::array;
//! use numpy::{ToPyArray, PyArray};
//!
//! Python::with_gil(|py| {
//!     let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!
//!     assert_eq!(
//!         py_array.readonly().as_array(),
//!         array![[1i64, 2], [3, 4]]
//!     );
//! })
//! ```
//!
//! [c-api]: https://numpy.org/doc/stable/reference/c-api
//! [ndarray]: https://numpy.org/doc/stable/reference/arrays.ndarray.html

// We often want to make the GIL lifetime explicit.
#![allow(clippy::needless_lifetimes)]

pub mod array;
pub mod borrow;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod slice_container;
mod sum_products;

pub use ndarray;
pub use pyo3;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::borrow::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn, PyReadwriteArray, PyReadwriteArray1,
    PyReadwriteArray2, PyReadwriteArray3, PyReadwriteArray4, PyReadwriteArray5, PyReadwriteArray6,
    PyReadwriteArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{dtype, Complex32, Complex64, Element, PyArrayDescr};
pub use crate::error::{
    BorrowError, DimensionalityError, FromVecError, NotContiguousError, TypeError,
};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
#[allow(deprecated)]
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::sum_products::{dot, einsum, inner};

pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

#[cfg(doctest)]
mod doctest {
    macro_rules! doc_comment {
        ($doc_string:expr, $mod_name:ident) => {
            #[doc = $doc_string]
            mod $mod_name {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

mod sealed {
    pub trait Sealed {}
}

#[cold]
#[inline(always)]
fn cold() {}

/// Create a [`PyArray`] with one, two or three dimensions.
///
/// This macro is backed by [`ndarray::array`].
///
/// # Example
///
/// ```
/// use numpy::pyo3::Python;
/// use numpy::ndarray::array;
/// use numpy::pyarray;
///
/// Python::with_gil(|py| {
///     let array = pyarray![py, [1, 2], [3, 4]];
///
///     assert_eq!(
///         array.readonly().as_array(),
///         array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::io::{IoError, IoErrorKind, Reader};

struct Frame;

// TODO: there should be a way to signal IO error.
// This will be handled by the error reform RFCs, I think.
// For now, use IO error to indicate any failure.
pub type Error = IoError;

fn mk_err() -> Error {
    IoError {
        kind: IoErrorKind::OtherIoError,
        desc: "FLAC decoding error",
        detail: None
    }
}

struct FlacStream {
    metadata_blocks: Vec<MetadataBlock>
}

#[cfg(test)]
fn get_foo_file() -> File {
    File::open(&Path::new("foo.flac")).unwrap()
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_stream_header(input: &mut Reader) -> Result<(), Error> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(mk_err()); } // TODO: provide more error info.
    Ok(())
}

#[test]
fn test_read_stream_header() {
    let mut input = get_foo_file();
    read_stream_header(&mut input).unwrap();
}

// TODO: should this be private or not?
#[deriving(Show)]
pub struct StreamInfo {
    pub min_block_size: u16,
    pub max_block_size: u16,
    pub min_frame_size: Option<u32>,
    pub max_frame_size: Option<u32>,
    pub sample_rate: u32,
    pub n_channels: u8,
    pub bits_per_sample: u8,
    pub n_samples: Option<u64>,
    pub md5sum: [u8, ..16]
}

// TODO: should this be private?
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

// TODO: should this be private?
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture // TODO
}

// TODO: this should be private.
pub struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_metadata_block_header(input: &mut Reader) -> Result<MetadataBlockHeader, Error> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte & 1) == 1;
    let block_type = byte >> 1;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> Result<MetadataBlock, Error> {
    match block_type {
        0 => {
            let streaminfo = try!(read_streaminfo_block(input));
            Ok(MetadataBlock::StreamInfo(streaminfo))
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => Err(mk_err()), // TODO: "invalid, to avoid confusion with a frame sync code"
        _ => Err(mk_err()) // TODO: "reserved", is that an error or do we ignore it?
    }
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_streaminfo_block(input: &mut Reader) -> Result<StreamInfo, Error> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0x7) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0xf;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };

    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // The specification dictates that all bits of the padding block must be 0.
    for _ in range(0, length) {
        if try!(input.read_byte()) != 0 {
            return Err(mk_err()); // TODO: error, nonzero bit in padding block.
        }
    }
    Ok(())
}

fn skip_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // Skip all the padding bytes.
    for _ in range(0, length) { try!(input.read_byte()); }
    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32) -> Result<(u32, Vec<u8>), Error> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

impl FlacStream {
    pub fn new(input: &mut Reader) -> Result<FlacStream, Error> {
        try!(read_stream_header(input));

        let hdr = try!(read_metadata_block_header(input));
        println!("type: {}, length: {}, last: {}",
                 hdr.block_type, hdr.length, hdr.is_last);

        let streaminfo = try!(read_streaminfo_block(input));
        println!("streaminfo: {}", streaminfo);
        // Read the STREAMINFO block
        // Read any metadata
        // Read frames

        let flac_stream = FlacStream {
            metadata_blocks: Vec::new()
        };

        Ok(flac_stream)
    }
}

#[test]
fn test_open_stream() {
    let mut input = get_foo_file();
    let flac_stream = FlacStream::new(&mut input).unwrap();
}
<commit_msg>remove unit tests<commit_after>#![allow(dead_code)]

use std::io::{IoError, IoErrorKind, Reader};

struct Frame;

// TODO: there should be a way to signal IO error.
// This will be handled by the error reform RFCs, I think.
// For now, use IO error to indicate any failure.
pub type Error = IoError;

fn mk_err() -> Error {
    IoError {
        kind: IoErrorKind::OtherIoError,
        desc: "FLAC decoding error",
        detail: None
    }
}

struct FlacStream {
    metadata_blocks: Vec<MetadataBlock>
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_stream_header(input: &mut Reader) -> Result<(), Error> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(mk_err()); } // TODO: provide more error info.
    Ok(())
}

// TODO: should this be private or not?
#[deriving(Show)]
pub struct StreamInfo {
    pub min_block_size: u16,
    pub max_block_size: u16,
    pub min_frame_size: Option<u32>,
    pub max_frame_size: Option<u32>,
    pub sample_rate: u32,
    pub n_channels: u8,
    pub bits_per_sample: u8,
    pub n_samples: Option<u64>,
    pub md5sum: [u8, ..16]
}

// TODO: should this be private?
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

// TODO: should this be private?
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture // TODO
}

// TODO: this should be private.
pub struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_metadata_block_header(input: &mut Reader) -> Result<MetadataBlockHeader, Error> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte & 1) == 1;
    let block_type = byte >> 1;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> Result<MetadataBlock, Error> {
    match block_type {
        0 => {
            let streaminfo = try!(read_streaminfo_block(input));
            Ok(MetadataBlock::StreamInfo(streaminfo))
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => Err(mk_err()), // TODO: "invalid, to avoid confusion with a frame sync code"
        _ => Err(mk_err()) // TODO: "reserved", is that an error or do we ignore it?
    }
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_streaminfo_block(input: &mut Reader) -> Result<StreamInfo, Error> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0x7) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0xf;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };

    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // The specification dictates that all bits of the padding block must be 0.
    for _ in range(0, length) {
        if try!(input.read_byte()) != 0 {
            return Err(mk_err()); // TODO: error, nonzero bit in padding block.
        }
    }
    Ok(())
}

fn skip_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // Skip all the padding bytes.
    for _ in range(0, length) { try!(input.read_byte()); }
    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32) -> Result<(u32, Vec<u8>), Error> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

impl FlacStream {
    pub fn new(input: &mut Reader) -> Result<FlacStream, Error> {
        try!(read_stream_header(input));

        let hdr = try!(read_metadata_block_header(input));
        println!("type: {}, length: {}, last: {}",
                 hdr.block_type, hdr.length, hdr.is_last);

        let streaminfo = try!(read_streaminfo_block(input));
        println!("streaminfo: {}", streaminfo);
        // Read the STREAMINFO block
        // Read any metadata
        // Read frames

        let flac_stream = FlacStream {
            metadata_blocks: Vec::new()
        };

        Ok(flac_stream)
    }
}

#[test]
fn test_open_stream() {
    use std::io::File;
    let mut input = File::open(&Path::new("foo.flac")).unwrap();
    let flac_stream = FlacStream::new(&mut input).unwrap();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use nom::{digit, line_ending};
use nom::IResult::Done;
//use nom::{space, alphanumeric, multispace};

use std::str::FromStr;

#[derive(Debug)]
#[repr(C)]
pub struct Osu {
    version: u32,
}

#[derive(Debug)]
struct General<'a> {
    audio_filename: &'a str,
    audio_lead_in:  u32,
    preview_time:   u32,
    countdown:      bool,
    sample_set:     &'a str,
    stack_leniency: f32,
    mode:           u32,
    letterboxin_breaks: bool,
    widescreen_Storyboard: bool,
}

//named!(section_general<&str, General>,

named!(parse_osu<&str, Osu>,
    do_parse!(
                    tag_s!("osu file format v")
    >>  version:    map_res!(digit, FromStr::from_str)
    >>              line_ending
    //>>  general:    section_general
    >>  (Osu { version: version })
    )
);

#[no_mangle]
pub extern "C" fn parse_osu_file() -> *const Osu {
    //"Hello, world\0".as_ptr()
    let input = include_str!("../test.osu");
    let res = parse_osu(input);
    match res {
        Done(_, x) => return &x,
        _ => return 0 as *const Osu,
    }
}

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

    #[test]
    fn it_works() {
        let input = include_str!("../test.osu");
        let res = parse_osu(input);
        if let Done(_, osu) = res {
            println!("{:?}", osu)
        }
        else {
            assert!(false);
        }
    }
}
<commit_msg>something wrong<commit_after>#[macro_use]
extern crate nom;

use nom::{digit, line_ending};
use nom::IResult::Done;
use nom::{space, anychar, crlf, multispace};

use std::str::FromStr;

#[derive(Debug)]
#[repr(C)]
pub struct Osu<'a> {
    version: u32,
    general: General<'a>,
}

#[derive(Debug, PartialEq, Default)]
struct General<'a> {
    audio_filename: &'a str,
    audio_lead_in:  u32,
    preview_time:   u32,
    countdown:      bool,
    sample_set:     &'a str,
    stack_leniency: f32,
    mode:           u32,
    letterboxin_breaks: bool,
    widescreen_storyboard: bool,
}

#[derive(Debug, Default)]
struct Editor {
    asdf: u32,
}

named_args!(value<'a>(key: &'a str)<&'a [u8]>,
    do_parse!(
           opt!(multispace)
        >> tag_s!(key)
        >> opt!(space)
        >> char!(':')
        >> opt!(space)
        >> val: take_until_s!("\r\n")
        >> opt!(multispace)
        >> (val)
             )
    );

named!(section_general<&str, General>,
        do_parse!(
              opt!(multispace)
           >> tag_s!("[General]")
           >> opt!(multispace)
           /*
        >> values: permutation!(
            apply!(value, "AudioFilename"),
            map_res!(apply!(value, "AudioLeadIn"), FromStr::from_str),
            map_res!(apply!(value, "PreviewTime"), FromStr::from_str),
            map_res!(apply!(value, "Countdown"), FromStr::from_str),
            apply!(value, "SampleSet"),
            map_res!(apply!(value, "StackLeniency"), FromStr::from_str),
            map_res!(apply!(value, "Mode"), FromStr::from_str),
            map_res!(apply!(value, "LetterboxInBreaks"), FromStr::from_str),
            map_res!(apply!(value, "WidescreenStoryboard"), FromStr::from_str),
            )
            */
        >> (General {
            /*
            audio_filename: values.0,
            audio_lead_in: values.1,
            preview_time: values.2,
            countdown: values.3,
            sample_set: values.4,
            stack_leniency: values.5,
            mode: values.6,
            letterboxin_breaks: values.7,
            widescreen_storyboard: values.8,
            */
            ..Default::default()
            })
          )
        );

named!(section_editor<&str, Editor>,
        do_parse!(
           tag_s!("[editor]")
          >> (Editor {..Default::default()})
          )
        );

named!(parse_osu<&str, Osu>,
    do_parse!(
                    tag_s!("osu file format v")
    >>  version:    map_res!(digit, FromStr::from_str)
    >>              line_ending
    >>  sections:   permutation!(call!(section_general), call!(line_ending))
    >>  (Osu {
        version: version,
        general: sections.0,
        })
    )
);

#[no_mangle]
pub extern "C" fn parse_osu_file<'a>() -> *const Osu<'a> {
    let input = include_str!("../test.osu");
    let res = parse_osu(input);
    match res {
        Done(_, x) => return &x,
        _ => return 0 as *const Osu,
    }
}

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

    #[test]
    fn it_works() {
        let input = include_str!("../test.osu");
        let res = parse_osu(input);
        if let Done(_, osu) = res {
            println!("{:?}", osu);
        }
        else {
            println!("{:?}", res);
            assert!(false);
        }
    }
}
<|endoftext|>


<commit_before>//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! cfor = "1.0"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; ; x *= 2; {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! extern crate rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! # // avoid our crate being inserted automatically, which gets in
//! # // the way of the feature above.
//! # #[macro_use] extern crate cfor;
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr; $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0;
//!
//!     bad_cfor!{let mut i = 0; i < 10; i += 1; {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.
//!
//! # Handling multiple initializations and steps
//!
//! Like C loops, `cfor!` supports specfying multiple initializations and steps seperated by a comma.
//!
//! ```
//!cfor!(let mut x = 0, let mut y = x; x <= 10 && y <= 100; x+= 1, y += 10; {
//!    println!("{}:{}", x, y);
//!});

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($($init: stmt),+; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($($init),+; !false; $($rest)*)
    };

    // for ($init; $cond; ) { ... }
    ($($init: stmt),+; $cond: expr; ; $body: block) => {
        cfor!{$($init),+; $cond; (); $body}
    };

    // for ($init; $cond; $step) { $body }
    ($($init: stmt),+; $cond: expr; $($step: expr),+; $body: block) => {
        {
            $($init;)+
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $($step;)+
            }
        }
    };
}
<commit_msg>Documentation fixed<commit_after>//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! cfor = "1.0"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; ; x *= 2; {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! extern crate rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! # // avoid our crate being inserted automatically, which gets in
//! # // the way of the feature above.
//! # #[macro_use] extern crate cfor;
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr; $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0;
//!
//!     bad_cfor!{let mut i = 0; i < 10; i += 1; {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.
//!
//! # Handling multiple initializations and steps
//!
//! Like C loops, `cfor!` supports specfying multiple initializations and steps seperated by a comma.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 0, let mut y = x; x <= 10 && y <= 100; x += 1, y += 10; {
//!         println!(x: {}, y: {}", x, y);
//!     }}
//! }
//! ```

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($($init: stmt),+; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($($init),+; !false; $($rest)*)
    };

    // for ($init; $cond; ) { ... }
    ($($init: stmt),+; $cond: expr; ; $body: block) => {
        cfor!{$($init),+; $cond; (); $body}
    };

    // for ($init; $cond; $step) { $body }
    ($($init: stmt),+; $cond: expr; $($step: expr),+; $body: block) => {
        {
            $($init;)+
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $($step;)+
            }
        }
    };
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins)
//! within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.8"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::{Path, PathBuf};

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<commit_msg>Mention capnp prerequisite in documentation<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.8"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::{Path, PathBuf};

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<|endoftext|>