<commit_before>#![doc(html_root_url = "https://docs.rs/phf_shared/0.7")]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

extern crate siphasher;

#[cfg(feature = "unicase")]
extern crate unicase;

use core::fmt;
use core::hash::{Hasher, Hash};
use core::num::Wrapping;
use siphasher::sip128::{Hash128, Hasher128, SipHasher13};

pub struct Hashes {
    pub g: u32,
    pub f1: u32,
    pub f2: u32,
    _priv: (),
}

/// A central typedef for hash keys
///
/// Makes experimentation easier by only needing to be updated here.
pub type HashKey = u64;

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    (Wrapping(d2) + Wrapping(f1) * Wrapping(d1) + Wrapping(f2)).0
}

/// `key` is from `phf_generator::HashState`.
#[inline]
pub fn hash<T: ?Sized + PhfHash>(x: &T, key: &HashKey) -> Hashes {
    let mut hasher = SipHasher13::new_with_keys(0, *key);
    x.phf_hash(&mut hasher);

    let Hash128 { h1: lower, h2: upper} = hasher.finish128();

    Hashes {
        g: (lower >> 32) as u32,
        f1: lower as u32,
        f2: upper as u32,
        _priv: (),
    }
}

/// Return an index into `phf_generator::HashState::map`.
///
/// * `hash` is from `hash()` in this crate.
/// * `disps` is from `phf_generator::HashState::disps`.
/// * `len` is the length of `phf_generator::HashState::map`.
#[inline]
pub fn get_index(hashes: &Hashes, disps: &[(u32, u32)], len: usize) -> u32 {
    let (d1, d2) = disps[(hashes.g % (disps.len() as u32)) as usize];
    displace(hashes.f1, hashes.f2, d1, d2) % (len as u32)
}

/// A trait implemented by types which can be used in PHF data structures.
///
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
/// results must be architecture independent so that hashes will be consistent
/// between the host and target when cross compiling.
pub trait PhfHash {
    /// Feeds the value into the state given, updating the hasher as necessary.
    fn phf_hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
        where Self: Sized
    {
        for piece in data {
            piece.phf_hash(state);
        }
    }
}

/// Trait for printing types with `const` constructors, used by `phf_codegen` and `phf_macros`.
pub trait FmtConst {
    /// Print a `const` expression representing this value.
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result;
}

/// Create an impl of `FmtConst` delegating to `fmt::Debug` for types that can deal with it.
///
/// Ideally with specialization this could be just one default impl and then specialized where
/// it doesn't apply.
macro_rules! delegate_debug (
    ($ty:ty) => {
        impl FmtConst for $ty {
            fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    }
);

delegate_debug!(str);
delegate_debug!(char);
delegate_debug!(u8);
delegate_debug!(i8);
delegate_debug!(u16);
delegate_debug!(i16);
delegate_debug!(u32);
delegate_debug!(i32);
delegate_debug!(u64);
delegate_debug!(i64);
delegate_debug!(u128);
delegate_debug!(i128);
delegate_debug!(bool);

#[cfg(feature = "std")]
impl PhfHash for String {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

#[cfg(feature = "std")]
impl PhfHash for Vec<u8> {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

impl<'a, T: 'a + PhfHash + ?Sized> PhfHash for &'a T {
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self).phf_hash(state)
    }
}

impl<'a, T: 'a + FmtConst + ?Sized> FmtConst for &'a T {
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (*self).fmt_const(f)
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.as_bytes().phf_hash(state)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        state.write(self);
    }
}

impl FmtConst for [u8] {
    #[inline]
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // slices need a leading reference
        write!(f, "&{:?}", self)
    }
}

#[cfg(feature = "unicase")]
impl<S> PhfHash for unicase::UniCase<S>
    where unicase::UniCase<S>: Hash {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "unicase")]
impl<S> FmtConst for unicase::UniCase<S> where S: AsRef<str> {
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_ascii() {
            f.write_str("UniCase::ascii(")?;
        } else {
            f.write_str("UniCase::unicode(")?;
        }

        self.as_ref().fmt_const(f)?;
        f.write_str(")")
    }
}

macro_rules! sip_impl (
    (le $t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.to_le().hash(state);
            }
        }
    );
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.hash(state);
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(le u16);
sip_impl!(le i16);
sip_impl!(le u32);
sip_impl!(le i32);
sip_impl!(le u64);
sip_impl!(le i64);
sip_impl!(le u128);
sip_impl!(le i128);
sip_impl!(bool);

impl PhfHash for char {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self as u32).phf_hash(state)
    }
}

// minimize duplicated code since formatting drags in quite a bit
fn fmt_array(array: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", array)
}

macro_rules! array_impl (
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                state.write(self);
            }
        }

        impl FmtConst for [$t; $n] {
            fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt_array(self, f)
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<commit_msg>Allow using the owned `String` type for `phf` dynamic code generation.<commit_after>#![doc(html_root_url = "https://docs.rs/phf_shared/0.7")]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

extern crate siphasher;

#[cfg(feature = "unicase")]
extern crate unicase;

use core::fmt;
use core::hash::{Hasher, Hash};
use core::num::Wrapping;
use siphasher::sip128::{Hash128, Hasher128, SipHasher13};

pub struct Hashes {
    pub g: u32,
    pub f1: u32,
    pub f2: u32,
    _priv: (),
}

/// A central typedef for hash keys
///
/// Makes experimentation easier by only needing to be updated here.
pub type HashKey = u64;

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    (Wrapping(d2) + Wrapping(f1) * Wrapping(d1) + Wrapping(f2)).0
}

/// `key` is from `phf_generator::HashState`.
#[inline]
pub fn hash<T: ?Sized + PhfHash>(x: &T, key: &HashKey) -> Hashes {
    let mut hasher = SipHasher13::new_with_keys(0, *key);
    x.phf_hash(&mut hasher);

    let Hash128 { h1: lower, h2: upper} = hasher.finish128();

    Hashes {
        g: (lower >> 32) as u32,
        f1: lower as u32,
        f2: upper as u32,
        _priv: (),
    }
}

/// Return an index into `phf_generator::HashState::map`.
///
/// * `hash` is from `hash()` in this crate.
/// * `disps` is from `phf_generator::HashState::disps`.
/// * `len` is the length of `phf_generator::HashState::map`.
#[inline]
pub fn get_index(hashes: &Hashes, disps: &[(u32, u32)], len: usize) -> u32 {
    let (d1, d2) = disps[(hashes.g % (disps.len() as u32)) as usize];
    displace(hashes.f1, hashes.f2, d1, d2) % (len as u32)
}

/// A trait implemented by types which can be used in PHF data structures.
///
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
/// results must be architecture independent so that hashes will be consistent
/// between the host and target when cross compiling.
pub trait PhfHash {
    /// Feeds the value into the state given, updating the hasher as necessary.
    fn phf_hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
        where Self: Sized
    {
        for piece in data {
            piece.phf_hash(state);
        }
    }
}

/// Trait for printing types with `const` constructors, used by `phf_codegen` and `phf_macros`.
pub trait FmtConst {
    /// Print a `const` expression representing this value.
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result;
}

/// Create an impl of `FmtConst` delegating to `fmt::Debug` for types that can deal with it.
///
/// Ideally with specialization this could be just one default impl and then specialized where
/// it doesn't apply.
macro_rules! delegate_debug (
    ($ty:ty) => {
        impl FmtConst for $ty {
            fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{:?}", self)
            }
        }
    }
);

delegate_debug!(str);
delegate_debug!(char);
delegate_debug!(u8);
delegate_debug!(i8);
delegate_debug!(u16);
delegate_debug!(i16);
delegate_debug!(u32);
delegate_debug!(i32);
delegate_debug!(u64);
delegate_debug!(i64);
delegate_debug!(u128);
delegate_debug!(i128);
delegate_debug!(bool);

#[cfg(feature = "std")]
delegate_debug!(String);

#[cfg(feature = "std")]
impl PhfHash for String {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

#[cfg(feature = "std")]
impl PhfHash for Vec<u8> {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (**self).phf_hash(state)
    }
}

impl<'a, T: 'a + PhfHash + ?Sized> PhfHash for &'a T {
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self).phf_hash(state)
    }
}

impl<'a, T: 'a + FmtConst + ?Sized> FmtConst for &'a T {
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (*self).fmt_const(f)
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.as_bytes().phf_hash(state)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        state.write(self);
    }
}

impl FmtConst for [u8] {
    #[inline]
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // slices need a leading reference
        write!(f, "&{:?}", self)
    }
}

#[cfg(feature = "unicase")]
impl<S> PhfHash for unicase::UniCase<S>
    where unicase::UniCase<S>: Hash {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        self.hash(state)
    }
}

#[cfg(feature = "unicase")]
impl<S> FmtConst for unicase::UniCase<S> where S: AsRef<str> {
    fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_ascii() {
            f.write_str("UniCase::ascii(")?;
        } else {
            f.write_str("UniCase::unicode(")?;
        }

        self.as_ref().fmt_const(f)?;
        f.write_str(")")
    }
}

macro_rules! sip_impl (
    (le $t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.to_le().hash(state);
            }
        }
    );
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                self.hash(state);
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(le u16);
sip_impl!(le i16);
sip_impl!(le u32);
sip_impl!(le i32);
sip_impl!(le u64);
sip_impl!(le i64);
sip_impl!(le u128);
sip_impl!(le i128);
sip_impl!(bool);

impl PhfHash for char {
    #[inline]
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
        (*self as u32).phf_hash(state)
    }
}

// minimize duplicated code since formatting drags in quite a bit
fn fmt_array(array: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", array)
}

macro_rules! array_impl (
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
                state.write(self);
            }
        }

        impl FmtConst for [$t; $n] {
            fn fmt_const(&self, f: &mut fmt::Formatter) -> fmt::Result {
                fmt_array(self, f)
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};

struct ELBLogEntry {
    time_stamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: String,
    response_processing_time: String,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, Error> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
struct ParsingErrors;

fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, ParsingErrors> {
    let split_line: Vec<_> = line.split(" ").collect();

    let ts = split_line[0].parse().unwrap();

    let elb_log_entry = ELBLogEntry {
        time_stamp: ts, //TODO This needs to be error checked once I figure out how to handle errors.
        elb_name: split_line[1].to_string(),
        client_address: split_line[2].to_string(),
        backend_address: split_line[3].to_string(),
        request_processing_time: split_line[4].parse::<f32>().unwrap(),  //TODO This needs to be error checked once I figure out how to handle errors.
        backend_processing_time: split_line[5].to_string(),
        response_processing_time: split_line[6].to_string(),
        elb_status_code: split_line[7].to_string(),
        backend_status_code: split_line[8].to_string(),
        received_bytes: split_line[9].to_string(),
        sent_bytes: split_line[10].to_string(),
        request_method: split_line[11].trim_matches('"').to_string(),
        request_url: split_line[12].to_string(),
        request_http_version: split_line[13].trim_matches('"').to_string()
    };

    Ok(Box::new(elb_log_entry))
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, "0.00003")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, "0.145507")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_time_stamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.time_stamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<commit_msg>Worked out more of the error handling for the line parsing.<commit_after>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error as WalkDirError};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};
use std::collections::HashMap;
use std::error::Error;

struct ELBLogEntry {
    time_stamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: String,
    response_processing_time: String,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, WalkDirError> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
struct ParsingErrors;

fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, HashMap<String, String>> {
    let split_line: Vec<_> = line.split(" ").collect();
    let mut errors = HashMap::new();

    let ts = match split_line[0].parse() {
        Ok(parsed_ts) => Some(parsed_ts),

        Err(e) => {
            errors.insert("timestamp".to_string(), "timestamp_error".to_string());
            None
        }
    };

    if errors.is_empty() {
        let elb_log_entry = ELBLogEntry {
            time_stamp: ts.unwrap(),
            elb_name: split_line[1].to_string(),
            client_address: split_line[2].to_string(),
            backend_address: split_line[3].to_string(),
            request_processing_time: split_line[4].parse::<f32>().unwrap(),  //TODO This needs to be error checked once I figure out how to handle errors.
            backend_processing_time: split_line[5].to_string(),
            response_processing_time: split_line[6].to_string(),
            elb_status_code: split_line[7].to_string(),
            backend_status_code: split_line[8].to_string(),
            received_bytes: split_line[9].to_string(),
            sent_bytes: split_line[10].to_string(),
            request_method: split_line[11].trim_matches('"').to_string(),
            request_url: split_line[12].to_string(),
            request_http_version: split_line[13].trim_matches('"').to_string()
        };

        Ok(Box::new(elb_log_entry))
    } else {
        Err(errors)
    }
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, "0.00003")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, "0.145507")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_time_stamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.time_stamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<|endoftext|>


<commit_before>use std::ffi;
use std::io;
use std::path::{Path, PathBuf};
use std::vec;

use env::Env;

/// Provides inspection and manipulation of a simulated process's environment.
#[derive(Default)]
pub struct SimulatedEnv {
    args: Vec<String>,
    args_os: Vec<ffi::OsString>,
    current_dir: PathBuf,
}

impl SimulatedEnv {
    /// Creates a new virtual environment.
    pub fn new() -> SimulatedEnv {
        SimulatedEnv {
            args: Vec::new(),
            args_os: Vec::new(),
            current_dir: PathBuf::from("/"),
        }
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args(&mut self, args: Vec<String>) {
        self.args = args;
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args_os(&mut self, args: Vec<ffi::OsString>) {
        self.args_os = args;
    }
}

impl Env for SimulatedEnv {
    type ArgsIter = vec::IntoIter<String>;
    type ArgsOsIter = vec::IntoIter<ffi::OsString>;

    fn args(&self) -> Self::ArgsIter {
        self.args.clone().into_iter()
    }

    fn args_os(&self) -> Self::ArgsOsIter {
        self.args_os.clone().into_iter()
    }

    fn current_dir(&self) -> io::Result<PathBuf> {
        Ok(self.current_dir.clone())
    }

    fn set_current_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<()> {
        self.current_dir = PathBuf::from(path.as_ref());
        Ok(())
    }
}

#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
    use std::ffi::OsString;
    use std::path::{Path, PathBuf};
    use super::SimulatedEnv;
    use env::Env;

    #[test]
    fn current_dir__default__returns_root() {
        let provider = SimulatedEnv::new();
        let result = provider.current_dir().unwrap();
        assert_eq!(PathBuf::from("/"), result);
    }

    #[test]
    fn current_dir__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let path = Path::new("/foo/bar");

        provider.set_current_dir(path).unwrap();
        let result = provider.current_dir().unwrap();

        assert_eq!(path, result.as_path());
    }

    #[test]
    fn args__default__returns_empty() {
        let provider = SimulatedEnv::new();
        let result = provider.args();
        assert_eq!(0, result.len());
    }

    #[test]
    fn args__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec!["app".to_string(), "arg1".to_string(), "arg2".to_string()];

        provider.set_args(args.clone());
        let result: Vec<String> = provider.args().collect();

        assert_eq!(args, result);
    }

    #[test]
    fn args_os__default__returns_empty() {
        let provider = SimulatedEnv::new();
        let result = provider.args_os();
        assert_eq!(0, result.len());
    }

    #[test]
    fn args_os__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec![OsString::from("app"), OsString::from("arg1"), OsString::from("arg2")];

        provider.set_args_os(args.clone());
        let result: Vec<OsString> = provider.args_os().collect();

        assert_eq!(args, result);
    }
}
<commit_msg>Make SimulatedEnv panic if something is used before a fake value is set for it<commit_after>use std::ffi;
use std::io;
use std::path::{Path, PathBuf};
use std::vec;

use env::Env;

/// Provides inspection and manipulation of a simulated process's environment.
#[derive(Default)]
pub struct SimulatedEnv {
    args: Option<Vec<String>>,
    args_os: Option<Vec<ffi::OsString>>,
    current_dir: Option<PathBuf>,
}

impl SimulatedEnv {
    /// Creates a new virtual environment.
    pub fn new() -> SimulatedEnv {
        SimulatedEnv {
            args: None,
            args_os: None,
            current_dir: None,
        }
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args(&mut self, args: Vec<String>) {
        self.args = Some(args);
    }

    /// Sets the arguments which this program was started with (normally passed via the command
    /// line).
    pub fn set_args_os(&mut self, args: Vec<ffi::OsString>) {
        self.args_os = Some(args);
    }
}

impl Env for SimulatedEnv {
    type ArgsIter = vec::IntoIter<String>;
    type ArgsOsIter = vec::IntoIter<ffi::OsString>;

    fn args(&self) -> Self::ArgsIter {
        self.args.clone()
            .expect("Env::args() was called before a simulated value was set")
            .into_iter()
    }

    fn args_os(&self) -> Self::ArgsOsIter {
        self.args_os.clone()
            .expect("Env::args_os() was called before a simulated value was set")
            .into_iter()
    }

    fn current_dir(&self) -> io::Result<PathBuf> {
        Ok(self.current_dir.clone()
            .expect("Env::current_dir() was called before a simulated value was set"))
    }

    fn set_current_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<()> {
        self.current_dir = Some(PathBuf::from(path.as_ref()));
        Ok(())
    }
}

#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
    use std::ffi::OsString;
    use std::path::Path;
    use super::SimulatedEnv;
    use env::Env;

    #[test]
    #[should_panic]
    fn current_dir__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.current_dir().unwrap();
    }

    #[test]
    fn current_dir__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let path = Path::new("/foo/bar");

        provider.set_current_dir(path).unwrap();
        let result = provider.current_dir().unwrap();

        assert_eq!(path, result.as_path());
    }

    #[test]
    #[should_panic]
    fn args__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.args();
    }

    #[test]
    fn args__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec!["app".to_string(), "arg1".to_string(), "arg2".to_string()];

        provider.set_args(args.clone());
        let result: Vec<String> = provider.args().collect();

        assert_eq!(args, result);
    }

    #[test]
    #[should_panic]
    fn args_os__called_before_set__panics() {
        let provider = SimulatedEnv::new();
        let _ = provider.args_os();
    }

    #[test]
    fn args_os__set_and_get__success() {
        let mut provider = SimulatedEnv::new();
        let args = vec![OsString::from("app"), OsString::from("arg1"), OsString::from("arg2")];

        provider.set_args_os(args.clone());
        let result: Vec<OsString> = provider.args_os().collect();

        assert_eq!(args, result);
    }
}
<|endoftext|>


<commit_before>use time;
use std::io::timer::sleep;
use gl;
use gl::types::GLint;

use {
    Gl,
    GameWindow,
};
use keyboard;
use mouse;
use event;

/// Render argument.
pub struct RenderArgs<'a> {
    /// Extrapolated time in seconds, used to do smooth animation.
    pub ext_dt: f64,
    /// OpenGL back-end for Rust-Graphics.
    pub gl: &'a mut Gl,
    /// The width of rendered area.
    pub width: u32,
    /// The height of rendered area.
    pub height: u32,
}

/// Update argument.
pub struct UpdateArgs {
    /// Delta time in seconds.
    pub dt: f64,
}

/// Key press arguments.
pub struct KeyPressArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Key release arguments.
pub struct KeyReleaseArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Mouse press arguments.
pub struct MousePressArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse release arguments.
pub struct MouseReleaseArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse move arguments.
pub struct MouseMoveArgs {
    /// y.
    pub x: f64,
    /// x.
    pub y: f64,
}

/// Mouse relative move arguments.
pub struct MouseRelativeMoveArgs {
    /// Delta x.
    pub dx: f64,
    /// Delta y.
    pub dy: f64,
}

/// Contains the different game events.
pub enum GameEvent<'a> {
    /// Render graphics.
    Render(RenderArgs<'a>),
    /// Update physical state of the game.
    Update(UpdateArgs),
    /// Pressed a keyboard key.
    KeyPress(KeyPressArgs),
    /// Released a keyboard key.
    KeyRelease(KeyReleaseArgs),
    /// Pressed a mouse button.
    MousePress(MousePressArgs),
    /// Released a mouse button.
    MouseRelease(MouseReleaseArgs),
    /// Moved mouse cursor.
    MouseMove(MouseMoveArgs),
    /// Moved mouse relative, not bounded by cursor.
    MouseRelativeMove(MouseRelativeMoveArgs)
}

impl<'a> GameEvent<'a> {
    /// Maps event to something that can be sent between tasks if possible.
    ///
    /// Render events are not sendable between tasks.
    pub fn to_sendable(&'a self) -> Option<GameEvent<'static>> {
        match *self {
            Render(_) => None,
            Update(args) => Some(Update(args)),
            KeyPress(args) => Some(KeyPress(args)),
            KeyRelease(args) => Some(KeyRelease(args)),
            MousePress(args) => Some(MousePress(args)),
            MouseRelease(args) => Some(MouseRelease(args)),
            MouseMove(args) => Some(MouseMove(args)),
            MouseRelativeMove(args) => Some(MouseRelativeMove(args)),
        }
    }
}

enum GameIteratorState {
    RenderState,
    SwapBuffersState,
    PrepareUpdateLoopState,
    UpdateLoopState,
    HandleEventsState,
    MouseRelativeMoveState(f64, f64),
    UpdateState,
}

/// Settings for the game loop behavior.
pub struct GameIteratorSettings {
    /// The number of updates per second (UPS).
    pub updates_per_second: u64,
    /// The maximum number of frames per second (FPS target).
    pub max_frames_per_second: u64,
}

/// A game loop iterator.
pub struct GameIterator<'a, W> {
    game_window: &'a mut W,
    state: GameIteratorState,
    gl: Gl,
    bg_color: [f32, ..4],
    last_update: u64,
    update_time_in_ns: u64,
    dt: f64,
    min_updates_per_frame: u64,
    min_ns_per_frame: u64,
    start_render: u64,
    next_render: u64,
    updated: u64,
}

static billion: u64 = 1_000_000_000;

impl<'a, W: GameWindow> GameIterator<'a, W> {
    /// Creates a new game iterator.
    pub fn new(game_window: &'a mut W, settings: &GameIteratorSettings) -> GameIterator<'a, W> {
        let bg_color = game_window.get_settings().background_color;
        let updates_per_second: u64 = settings.updates_per_second;
        let max_frames_per_second: u64 = settings.max_frames_per_second;

        let start = time::precise_time_ns();
        GameIterator {
            game_window: game_window,
            state: RenderState,
            gl: Gl::new(),
            last_update: start,
            update_time_in_ns: billion / updates_per_second,
            dt: 1.0 / updates_per_second as f64,
            // You can make this lower if needed.
            min_updates_per_frame: updates_per_second / max_frames_per_second,
            min_ns_per_frame: billion / max_frames_per_second,
            start_render: start,
            next_render: start,
            bg_color: bg_color,
            updated: 0,
        }
    }

    /// Returns the next game event.
    pub fn next<'a>(&'a mut self) -> Option<GameEvent<'a>> {
        match self.state {
            RenderState => {
                if self.game_window.should_close() { return None; }

                self.start_render = time::precise_time_ns();
                // Rendering code
                let (w, h) = self.game_window.get_size();
                if w != 0 && h != 0 {
                    gl::Viewport(0, 0, w as GLint, h as GLint);
                    let r = self.bg_color[0];
                    let g = self.bg_color[1];
                    let b = self.bg_color[2];
                    let a = self.bg_color[3];
                    gl::ClearColor(r, g, b, a);
                    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
                    // Swap buffers next time.
                    self.state = SwapBuffersState;
                    return Some(Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            // 'start_render' is always bigger than 'last_update'.
                            ext_dt: (self.start_render - self.last_update) as f64 / billion as f64,
                            gl: &mut self.gl,
                            width: w,
                            height: h,
                        }
                    ));
                }

                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            SwapBuffersState => {
                self.game_window.swap_buffers();
                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            PrepareUpdateLoopState => {
                self.updated = 0;
                self.next_render = self.start_render + self.min_ns_per_frame;
                self.state = UpdateLoopState;
                return self.next();
            },
            UpdateLoopState => {
                let got_min_updates = self.updated < self.min_updates_per_frame;
                let got_time_to_update = time::precise_time_ns() < self.next_render;
                let before_next_frame = self.last_update + self.update_time_in_ns < self.next_render;

                if ( got_time_to_update || got_min_updates ) && before_next_frame {
                    self.state = HandleEventsState;
                    return self.next();
                }

                // Wait if possible.
                // Convert to ms because that is what the sleep function takes.
                let t = (self.next_render - time::precise_time_ns() ) / 1_000_000;
                if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                          // which tells us that t should have been negative
                                          // and we are running slow and shouldn't sleep.
                    sleep( t );
                }
                self.state = RenderState;
                return self.next();
            },
            HandleEventsState => {
                // Handle all events before updating.
                return match self.game_window.poll_event() {
                    event::KeyPressed(key) => {
                        Some(KeyPress(KeyPressArgs {
                            key: key,
                        }))
                    },
                    event::KeyReleased(key) => {
                        Some(KeyRelease(KeyReleaseArgs {
                            key: key,
                        }))
                    },
                    event::MouseButtonPressed(mouse_button) => {
                        Some(MousePress(MousePressArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseButtonReleased(mouse_button) => {
                        Some(MouseRelease(MouseReleaseArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseMoved(x, y, relative_move) => {
                        match relative_move {
                            Some((dx, dy)) =>
                                self.state = MouseRelativeMoveState(dx, dy),
                            None => {},
                        };
                        Some(MouseMove(MouseMoveArgs {
                            x: x,
                            y: y,
                        }))
                    },
                    event::NoEvent => {
                        self.state = UpdateState;
                        self.next()
                    },
                }
            },
            MouseRelativeMoveState(dx, dy) => {
                self.state = HandleEventsState;
                return Some(MouseRelativeMove(MouseRelativeMoveArgs {
                    dx: dx,
                    dy: dy,
                }));
            },
            UpdateState => {
                self.updated += 1;
                self.state = UpdateLoopState;
                self.last_update += self.update_time_in_ns;
                return Some(Update(UpdateArgs{
                    dt: self.dt,
                }));
            },
        };

        /*
        // copied.

        while !self.should_close(game_window) {

            let start_render = time::precise_time_ns();

            // Rendering code
            let (w, h) = game_window.get_size();
            if w != 0 && h != 0 {
                self.viewport(game_window);
                let mut gl = Gl::new(&mut gl_data, asset_store);
                bg.clear(&mut gl);
                // Extrapolate time forward to allow smooth motion.
                // 'now' is always bigger than 'last_update'.
                let ext_dt = (start_render - last_update) as f64 / billion as f64;
                self.render(
                    ext_dt,
                    &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                    &mut gl
                        );
                self.swap_buffers(game_window);
            }

            let next_render = start_render + min_ns_per_frame;

            // Update gamestate
            let mut updated = 0;

            while // If we haven't reached the required number of updates yet
                  ( updated < min_updates_per_frame ||
                    // Or we have the time to update further
                    time::precise_time_ns() < next_render ) &&
                  //And we haven't already progressed time to far
                  last_update + update_time_in_ns < next_render {

                self.handle_events(game_window, asset_store);
                self.update(dt, asset_store);

                updated += 1;
                last_update += update_time_in_ns;
            }

            // Wait if possible

            let t = (next_render - time::precise_time_ns() ) / 1_000_000;
            if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                      // which tells us that t should have been negative
                                      // and we are running slow and shouldn't sleep.
                sleep( t );
            }

        }
        */
    }
}

<commit_msg>Added example to `GameIterator` docs<commit_after>use time;
use std::io::timer::sleep;
use gl;
use gl::types::GLint;

use {
    Gl,
    GameWindow,
};
use keyboard;
use mouse;
use event;

/// Render argument.
pub struct RenderArgs<'a> {
    /// Extrapolated time in seconds, used to do smooth animation.
    pub ext_dt: f64,
    /// OpenGL back-end for Rust-Graphics.
    pub gl: &'a mut Gl,
    /// The width of rendered area.
    pub width: u32,
    /// The height of rendered area.
    pub height: u32,
}

/// Update argument.
pub struct UpdateArgs {
    /// Delta time in seconds.
    pub dt: f64,
}

/// Key press arguments.
pub struct KeyPressArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Key release arguments.
pub struct KeyReleaseArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Mouse press arguments.
pub struct MousePressArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse release arguments.
pub struct MouseReleaseArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse move arguments.
pub struct MouseMoveArgs {
    /// y.
    pub x: f64,
    /// x.
    pub y: f64,
}

/// Mouse relative move arguments.
pub struct MouseRelativeMoveArgs {
    /// Delta x.
    pub dx: f64,
    /// Delta y.
    pub dy: f64,
}

/// Contains the different game events.
pub enum GameEvent<'a> {
    /// Render graphics.
    Render(RenderArgs<'a>),
    /// Update physical state of the game.
    Update(UpdateArgs),
    /// Pressed a keyboard key.
    KeyPress(KeyPressArgs),
    /// Released a keyboard key.
    KeyRelease(KeyReleaseArgs),
    /// Pressed a mouse button.
    MousePress(MousePressArgs),
    /// Released a mouse button.
    MouseRelease(MouseReleaseArgs),
    /// Moved mouse cursor.
    MouseMove(MouseMoveArgs),
    /// Moved mouse relative, not bounded by cursor.
    MouseRelativeMove(MouseRelativeMoveArgs)
}

impl<'a> GameEvent<'a> {
    /// Maps event to something that can be sent between tasks if possible.
    ///
    /// Render events are not sendable between tasks.
    pub fn to_sendable(&'a self) -> Option<GameEvent<'static>> {
        match *self {
            Render(_) => None,
            Update(args) => Some(Update(args)),
            KeyPress(args) => Some(KeyPress(args)),
            KeyRelease(args) => Some(KeyRelease(args)),
            MousePress(args) => Some(MousePress(args)),
            MouseRelease(args) => Some(MouseRelease(args)),
            MouseMove(args) => Some(MouseMove(args)),
            MouseRelativeMove(args) => Some(MouseRelativeMove(args)),
        }
    }
}

enum GameIteratorState {
    RenderState,
    SwapBuffersState,
    PrepareUpdateLoopState,
    UpdateLoopState,
    HandleEventsState,
    MouseRelativeMoveState(f64, f64),
    UpdateState,
}

/// Settings for the game loop behavior.
pub struct GameIteratorSettings {
    /// The number of updates per second (UPS).
    pub updates_per_second: u64,
    /// The maximum number of frames per second (FPS target).
    pub max_frames_per_second: u64,
}

/// A game loop iterator.
///
/// Example:
///
/// ```Rust
/// let game_iter_settings = GameIteratorSettings {
///     updates_per_second: 120,
///     max_frames_per_second: 60,
/// };
/// let mut game_iter = GameIterator::new(&mut window, &game_iter_settings);
/// loop {
///     match game_iter.next() {
///         None => { break },
///         Some(e) => match e {
///             Render(args) => {
///                 // Do rendering here.
///             },
///             _ => {},
///         },
///     }
/// }
/// ```
pub struct GameIterator<'a, W> {
    game_window: &'a mut W,
    state: GameIteratorState,
    gl: Gl,
    bg_color: [f32, ..4],
    last_update: u64,
    update_time_in_ns: u64,
    dt: f64,
    min_updates_per_frame: u64,
    min_ns_per_frame: u64,
    start_render: u64,
    next_render: u64,
    updated: u64,
}

static billion: u64 = 1_000_000_000;

impl<'a, W: GameWindow> GameIterator<'a, W> {
    /// Creates a new game iterator.
    pub fn new(game_window: &'a mut W, settings: &GameIteratorSettings) -> GameIterator<'a, W> {
        let bg_color = game_window.get_settings().background_color;
        let updates_per_second: u64 = settings.updates_per_second;
        let max_frames_per_second: u64 = settings.max_frames_per_second;

        let start = time::precise_time_ns();
        GameIterator {
            game_window: game_window,
            state: RenderState,
            gl: Gl::new(),
            last_update: start,
            update_time_in_ns: billion / updates_per_second,
            dt: 1.0 / updates_per_second as f64,
            // You can make this lower if needed.
            min_updates_per_frame: updates_per_second / max_frames_per_second,
            min_ns_per_frame: billion / max_frames_per_second,
            start_render: start,
            next_render: start,
            bg_color: bg_color,
            updated: 0,
        }
    }

    /// Returns the next game event.
    pub fn next<'a>(&'a mut self) -> Option<GameEvent<'a>> {
        match self.state {
            RenderState => {
                if self.game_window.should_close() { return None; }

                self.start_render = time::precise_time_ns();
                // Rendering code
                let (w, h) = self.game_window.get_size();
                if w != 0 && h != 0 {
                    gl::Viewport(0, 0, w as GLint, h as GLint);
                    let r = self.bg_color[0];
                    let g = self.bg_color[1];
                    let b = self.bg_color[2];
                    let a = self.bg_color[3];
                    gl::ClearColor(r, g, b, a);
                    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
                    // Swap buffers next time.
                    self.state = SwapBuffersState;
                    return Some(Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            // 'start_render' is always bigger than 'last_update'.
                            ext_dt: (self.start_render - self.last_update) as f64 / billion as f64,
                            gl: &mut self.gl,
                            width: w,
                            height: h,
                        }
                    ));
                }

                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            SwapBuffersState => {
                self.game_window.swap_buffers();
                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            PrepareUpdateLoopState => {
                self.updated = 0;
                self.next_render = self.start_render + self.min_ns_per_frame;
                self.state = UpdateLoopState;
                return self.next();
            },
            UpdateLoopState => {
                let got_min_updates = self.updated < self.min_updates_per_frame;
                let got_time_to_update = time::precise_time_ns() < self.next_render;
                let before_next_frame = self.last_update + self.update_time_in_ns < self.next_render;

                if ( got_time_to_update || got_min_updates ) && before_next_frame {
                    self.state = HandleEventsState;
                    return self.next();
                }

                // Wait if possible.
                // Convert to ms because that is what the sleep function takes.
                let t = (self.next_render - time::precise_time_ns() ) / 1_000_000;
                if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                          // which tells us that t should have been negative
                                          // and we are running slow and shouldn't sleep.
                    sleep( t );
                }
                self.state = RenderState;
                return self.next();
            },
            HandleEventsState => {
                // Handle all events before updating.
                return match self.game_window.poll_event() {
                    event::KeyPressed(key) => {
                        Some(KeyPress(KeyPressArgs {
                            key: key,
                        }))
                    },
                    event::KeyReleased(key) => {
                        Some(KeyRelease(KeyReleaseArgs {
                            key: key,
                        }))
                    },
                    event::MouseButtonPressed(mouse_button) => {
                        Some(MousePress(MousePressArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseButtonReleased(mouse_button) => {
                        Some(MouseRelease(MouseReleaseArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseMoved(x, y, relative_move) => {
                        match relative_move {
                            Some((dx, dy)) =>
                                self.state = MouseRelativeMoveState(dx, dy),
                            None => {},
                        };
                        Some(MouseMove(MouseMoveArgs {
                            x: x,
                            y: y,
                        }))
                    },
                    event::NoEvent => {
                        self.state = UpdateState;
                        self.next()
                    },
                }
            },
            MouseRelativeMoveState(dx, dy) => {
                self.state = HandleEventsState;
                return Some(MouseRelativeMove(MouseRelativeMoveArgs {
                    dx: dx,
                    dy: dy,
                }));
            },
            UpdateState => {
                self.updated += 1;
                self.state = UpdateLoopState;
                self.last_update += self.update_time_in_ns;
                return Some(Update(UpdateArgs{
                    dt: self.dt,
                }));
            },
        };

        /*
        // copied.

        while !self.should_close(game_window) {

            let start_render = time::precise_time_ns();

            // Rendering code
            let (w, h) = game_window.get_size();
            if w != 0 && h != 0 {
                self.viewport(game_window);
                let mut gl = Gl::new(&mut gl_data, asset_store);
                bg.clear(&mut gl);
                // Extrapolate time forward to allow smooth motion.
                // 'now' is always bigger than 'last_update'.
                let ext_dt = (start_render - last_update) as f64 / billion as f64;
                self.render(
                    ext_dt,
                    &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                    &mut gl
                        );
                self.swap_buffers(game_window);
            }

            let next_render = start_render + min_ns_per_frame;

            // Update gamestate
            let mut updated = 0;

            while // If we haven't reached the required number of updates yet
                  ( updated < min_updates_per_frame ||
                    // Or we have the time to update further
                    time::precise_time_ns() < next_render ) &&
                  //And we haven't already progressed time to far
                  last_update + update_time_in_ns < next_render {

                self.handle_events(game_window, asset_store);
                self.update(dt, asset_store);

                updated += 1;
                last_update += update_time_in_ns;
            }

            // Wait if possible

            let t = (next_render - time::precise_time_ns() ) / 1_000_000;
            if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                      // which tells us that t should have been negative
                                      // and we are running slow and shouldn't sleep.
                sleep( t );
            }

        }
        */
    }
}

<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::utils::mtd;
use failure::ensure;
use pkg_schema::definitions::{
    target_permissions::{Gid, Uid},
    TargetType,
};
use std::path::PathBuf;

/// Utility funtions for [TargetType](pkg_schema::definitions::TargetType)
pub(crate) trait TargetTypeExt {
    /// Checks whether the device is valid to start installation, i.e.,
    /// device exists, use have write permission.
    fn valid(&self) -> Result<&Self, failure::Error>;

    /// Gets device's path for mounting.
    fn get_target(&self) -> Result<PathBuf, failure::Error>;
}

impl TargetTypeExt for TargetType {
    fn valid(&self) -> Result<&Self, failure::Error> {
        Ok(match self {
            TargetType::Device(p) => {
                ensure!(p.exists(), "Target device does not exists");
                ensure!(
                    !p.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    p
                );
                &self
            }
            TargetType::UBIVolume(s) => {
                let dev = mtd::target_device_from_ubi_volume_name(s)?;
                ensure!(
                    !dev.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    dev
                );
                &self
            }
            TargetType::MTDName(n) => {
                let dev = mtd::target_device_from_mtd_name(n)?;
                ensure!(
                    !dev.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    dev
                );
                &self
            }
        })
    }

    fn get_target(&self) -> Result<PathBuf, failure::Error> {
        match self {
            TargetType::Device(p) => Ok(p.clone()),
            TargetType::UBIVolume(s) => mtd::target_device_from_ubi_volume_name(s),
            TargetType::MTDName(s) => mtd::target_device_from_mtd_name(s),
        }
    }
}

/// Utility funtions for [Gid](pkg_schema::definitions::target_permissions::Gid)
/// and [Uid](pkg_schema::definitions::target_permissions::Uid)
pub(crate) trait IdExt {
    /// Gets numeric id;
    fn as_u32(&self) -> u32;
}

impl IdExt for Gid {
    fn as_u32(&self) -> u32 {
        match self {
            Gid::Name(s) => {
                let s = std::ffi::CString::new(s.as_str());
                unsafe { *nix::libc::getgrnam(s.unwrap().as_ptr()) }.gr_gid
            }
            Gid::Number(n) => *n,
        }
    }
}

impl IdExt for Uid {
    fn as_u32(&self) -> u32 {
        match self {
            Uid::Name(s) => {
                let s = std::ffi::CString::new(s.as_str());
                unsafe { *nix::libc::getpwnam(s.unwrap().as_ptr()) }.pw_uid
            }
            Uid::Number(n) => *n,
        }
    }
}
<commit_msg>updatehub: Fix Clippy warning about drop of CSString<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::utils::mtd;
use failure::ensure;
use pkg_schema::definitions::{
    target_permissions::{Gid, Uid},
    TargetType,
};
use std::path::PathBuf;

/// Utility funtions for [TargetType](pkg_schema::definitions::TargetType)
pub(crate) trait TargetTypeExt {
    /// Checks whether the device is valid to start installation, i.e.,
    /// device exists, use have write permission.
    fn valid(&self) -> Result<&Self, failure::Error>;

    /// Gets device's path for mounting.
    fn get_target(&self) -> Result<PathBuf, failure::Error>;
}

impl TargetTypeExt for TargetType {
    fn valid(&self) -> Result<&Self, failure::Error> {
        Ok(match self {
            TargetType::Device(p) => {
                ensure!(p.exists(), "Target device does not exists");
                ensure!(
                    !p.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    p
                );
                &self
            }
            TargetType::UBIVolume(s) => {
                let dev = mtd::target_device_from_ubi_volume_name(s)?;
                ensure!(
                    !dev.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    dev
                );
                &self
            }
            TargetType::MTDName(n) => {
                let dev = mtd::target_device_from_mtd_name(n)?;
                ensure!(
                    !dev.metadata()?.permissions().readonly(),
                    "User doesn't have write permission on target device: {:?}",
                    dev
                );
                &self
            }
        })
    }

    fn get_target(&self) -> Result<PathBuf, failure::Error> {
        match self {
            TargetType::Device(p) => Ok(p.clone()),
            TargetType::UBIVolume(s) => mtd::target_device_from_ubi_volume_name(s),
            TargetType::MTDName(s) => mtd::target_device_from_mtd_name(s),
        }
    }
}

/// Utility funtions for [Gid](pkg_schema::definitions::target_permissions::Gid)
/// and [Uid](pkg_schema::definitions::target_permissions::Uid)
pub(crate) trait IdExt {
    /// Gets numeric id;
    fn as_u32(&self) -> u32;
}

impl IdExt for Gid {
    fn as_u32(&self) -> u32 {
        match self {
            Gid::Name(s) => {
                let s = std::ffi::CString::new(s.as_str()).unwrap();
                unsafe { *nix::libc::getgrnam(s.as_ptr()) }.gr_gid
            }
            Gid::Number(n) => *n,
        }
    }
}

impl IdExt for Uid {
    fn as_u32(&self) -> u32 {
        match self {
            Uid::Name(s) => {
                let s = std::ffi::CString::new(s.as_str()).unwrap();
                unsafe { *nix::libc::getpwnam(s.as_ptr()) }.pw_uid
            }
            Uid::Number(n) => *n,
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate bit_field;

use bit_field::*;

pub trait BitOper {
    const BIT_LEN: usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

pub trait BitArrayOper<T: BitOper> {
    fn get_blen(&self)->usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

impl BitOper for u8 {
    const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;

    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u32 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u64 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl <T:BitOper> BitArrayOper<T> for [T] {
    fn get_blen(&self) -> usize {
        self.len() * T::BIT_LEN
    }

    fn get_b(&self, idx: usize) -> bool {
        self[idx / T::BIT_LEN].get_b(idx % T::BIT_LEN)
    }

    fn set_b(&mut self, idx: usize, val: bool) {
        self[idx / T::BIT_LEN].set_b(idx % T::BIT_LEN, val);
    }

    fn toggle(&mut self, idx: usize) {
        self[idx / T::BIT_LEN].toggle(idx % T::BIT_LEN);
    }
}

extern crate test;

use test::Bencher;

const len: usize = 256;

fn set_bitfield<T:BitField>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            v.as_mut_slice().set_bit(i, true);;
        }
 }

fn get_bitfield<T:BitField>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            let _b = v.as_slice().get_bit(i);
        }
 }

 fn set_trivial<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.set_b(i, true);
        }
}

 fn toggle<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.toggle(i);
        }
}

 fn get_trivial<T:BitOper>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            let _b = v.get_b(i);
        }
}

#[bench]
fn u8_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u8; len];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u8_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u8; len];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u8_get_bitfield(b: &mut Bencher) {
    let v = vec![1u8; len];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u8_get_trivial(b: &mut Bencher) {
    let v = vec![1u8; len];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u32_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u32; len];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u32_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u32; len];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u32_get_bitfield(b: &mut Bencher) {
    let v = vec![1u32; len];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u32_get_trivial(b: &mut Bencher) {
    let v = vec![1u32; len];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u64_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u64; len];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u64_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u64; len];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u64_get_bitfield(b: &mut Bencher) {
    let v = vec![1u64; len];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u64_get_trivial(b: &mut Bencher) {
    let v = vec![1u64; len];
    b.iter(|| {
        get_trivial(&v);
    });
}
<commit_msg>Rename `len` constant to `LEN`<commit_after>#![feature(test)]

extern crate bit_field;

use bit_field::*;

pub trait BitOper {
    const BIT_LEN: usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

pub trait BitArrayOper<T: BitOper> {
    fn get_blen(&self)->usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

impl BitOper for u8 {
    const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;

    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u32 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u64 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl <T:BitOper> BitArrayOper<T> for [T] {
    fn get_blen(&self) -> usize {
        self.len() * T::BIT_LEN
    }

    fn get_b(&self, idx: usize) -> bool {
        self[idx / T::BIT_LEN].get_b(idx % T::BIT_LEN)
    }

    fn set_b(&mut self, idx: usize, val: bool) {
        self[idx / T::BIT_LEN].set_b(idx % T::BIT_LEN, val);
    }

    fn toggle(&mut self, idx: usize) {
        self[idx / T::BIT_LEN].toggle(idx % T::BIT_LEN);
    }
}

extern crate test;

use test::Bencher;

const LEN: usize = 256;

fn set_bitfield<T:BitField>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            v.as_mut_slice().set_bit(i, true);;
        }
 }

fn get_bitfield<T:BitField>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            let _b = v.as_slice().get_bit(i);
        }
 }

 fn set_trivial<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.set_b(i, true);
        }
}

 fn toggle<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.toggle(i);
        }
}

 fn get_trivial<T:BitOper>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            let _b = v.get_b(i);
        }
}

#[bench]
fn u8_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u8_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u8_get_bitfield(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u8_get_trivial(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u32_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u32_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u32_get_bitfield(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u32_get_trivial(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u64_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u64_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u64_get_bitfield(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u64_get_trivial(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate ipc_channel;
extern crate test;

/// Allows doing multiple inner iterations per bench.iter() run.
///
/// This is mostly to amortise the overhead of spawning a thread in the benchmark
/// when sending larger messages (that might be fragmented).
///
/// Note that you need to compensate the displayed results
/// for the proportionally longer runs yourself,
/// as the benchmark framework doesn't know about the inner iterations...
const ITERATIONS: usize = 1;

mod platform {
    extern crate crossbeam;

    use ipc_channel::platform;
    use ITERATIONS;

    use std::sync::{mpsc, Mutex};
    use test;

    #[bench]
    fn create_channel(b: &mut test::Bencher) {
        b.iter(|| {
            for _ in 0..ITERATIONS {
                platform::channel().unwrap();
            }
        });
    }

    fn bench_transfer_data(b: &mut test::Bencher, size: usize) {
        let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
        let (tx, rx) = platform::channel().unwrap();

        let (wait_tx, wait_rx) = mpsc::channel();
        let wait_rx = Mutex::new(wait_rx);

        if size > platform::OsIpcSender::get_max_fragment_size() {
            b.iter(|| {
                crossbeam::scope(|scope| {
                    let tx = tx.clone();
                    scope.spawn(|| {
                        let wait_rx = wait_rx.lock().unwrap();
                        let tx = tx;
                        for _ in 0..ITERATIONS {
                            tx.send(&data, vec![], vec![]).unwrap();
                            if ITERATIONS > 1 {
                                // Prevent beginning of the next send
                                // from overlapping with receive of last fragment,
                                // as otherwise results of runs with a large tail fragment
                                // are significantly skewed.
                                wait_rx.recv().unwrap();
                            }
                        }
                    });
                    for _ in 0..ITERATIONS {
                        rx.recv().unwrap();
                        if ITERATIONS > 1 {
                            wait_tx.send(()).unwrap();
                        }
                    }
                    // For reasons mysterious to me,
                    // not returning a value *from every branch*
                    // adds some 100 ns or so of overhead to all results --
                    // which is quite significant for very short tests...
                    0
                })
            });
        } else {
            b.iter(|| {
                for _ in 0..ITERATIONS {
                    tx.send(&data, vec![], vec![]).unwrap();
                    rx.recv().unwrap();
                }
                0
            });
        }
    }

    #[bench]
    fn transfer_data_00_1(b: &mut test::Bencher) {
        bench_transfer_data(b, 1);
    }
    #[bench]
    fn transfer_data_01_2(b: &mut test::Bencher) {
        bench_transfer_data(b, 2);
    }
    #[bench]
    fn transfer_data_02_4(b: &mut test::Bencher) {
        bench_transfer_data(b, 4);
    }
    #[bench]
    fn transfer_data_03_8(b: &mut test::Bencher) {
        bench_transfer_data(b, 8);
    }
    #[bench]
    fn transfer_data_04_16(b: &mut test::Bencher) {
        bench_transfer_data(b, 16);
    }
    #[bench]
    fn transfer_data_05_32(b: &mut test::Bencher) {
        bench_transfer_data(b, 32);
    }
    #[bench]
    fn transfer_data_06_64(b: &mut test::Bencher) {
        bench_transfer_data(b, 64);
    }
    #[bench]
    fn transfer_data_07_128(b: &mut test::Bencher) {
        bench_transfer_data(b, 128);
    }
    #[bench]
    fn transfer_data_08_256(b: &mut test::Bencher) {
        bench_transfer_data(b, 256);
    }
    #[bench]
    fn transfer_data_09_512(b: &mut test::Bencher) {
        bench_transfer_data(b, 512);
    }
    #[bench]
    fn transfer_data_10_1k(b: &mut test::Bencher) {
        bench_transfer_data(b, 1 * 1024);
    }
    #[bench]
    fn transfer_data_11_2k(b: &mut test::Bencher) {
        bench_transfer_data(b, 2 * 1024);
    }
    #[bench]
    fn transfer_data_12_4k(b: &mut test::Bencher) {
        bench_transfer_data(b, 4 * 1024);
    }
    #[bench]
    fn transfer_data_13_8k(b: &mut test::Bencher) {
        bench_transfer_data(b, 8 * 1024);
    }
    #[bench]
    fn transfer_data_14_16k(b: &mut test::Bencher) {
        bench_transfer_data(b, 16 * 1024);
    }
    #[bench]
    fn transfer_data_15_32k(b: &mut test::Bencher) {
        bench_transfer_data(b, 32 * 1024);
    }
    #[bench]
    fn transfer_data_16_64k(b: &mut test::Bencher) {
        bench_transfer_data(b, 64 * 1024);
    }
    #[bench]
    fn transfer_data_17_128k(b: &mut test::Bencher) {
        bench_transfer_data(b, 128 * 1024);
    }
    #[bench]
    fn transfer_data_18_256k(b: &mut test::Bencher) {
        bench_transfer_data(b, 256 * 1024);
    }
    #[bench]
    fn transfer_data_19_512k(b: &mut test::Bencher) {
        bench_transfer_data(b, 512 * 1024);
    }
    #[bench]
    fn transfer_data_20_1m(b: &mut test::Bencher) {
        bench_transfer_data(b, 1 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_21_2m(b: &mut test::Bencher) {
        bench_transfer_data(b, 2 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_22_4m(b: &mut test::Bencher) {
        bench_transfer_data(b, 4 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_23_8m(b: &mut test::Bencher) {
        bench_transfer_data(b, 8 * 1024 * 1024);
    }
}

mod ipc {
    mod receiver_set {
        use ipc_channel::ipc::{self, IpcReceiverSet};
        use test;

        fn gen_select_test(b: &mut test::Bencher, to_send: usize, n: usize) -> () {
            let mut active = Vec::with_capacity(to_send);
            let mut dormant = Vec::with_capacity(n - to_send);
            let mut rx_set = IpcReceiverSet::new().unwrap();
            for _ in 0..to_send {
                let (tx, rx) = ipc::channel().unwrap();
                rx_set.add(rx).unwrap();
                active.push(tx);
            }
            for _ in to_send..n {
                let (tx, rx) = ipc::channel::<()>().unwrap();
                rx_set.add(rx).unwrap();
                dormant.push(tx);
            }
            b.iter(|| {
                for tx in active.iter() {
                    tx.send(()).unwrap();
                }
                let mut received = 0;
                while received < to_send {
                    for result in rx_set.select().unwrap().into_iter() {
                        let (_, _) = result.unwrap();
                        received += 1;
                    }
                }
            });
        }

        #[bench]
        fn send_on_1_of_1(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 1);
        }

        #[bench]
        fn send_on_1_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 5);
        }

        #[bench]
        fn send_on_2_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 2, 5);
        }

        #[bench]
        fn send_on_5_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 5);
        }

        #[bench]
        fn send_on_1_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 20);
        }

        #[bench]
        fn send_on_5_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 20);
        }

        #[bench]
        fn send_on_20_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 20, 20);
        }

        #[bench]
        fn send_on_1_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 100);
        }

        #[bench]
        fn send_on_5_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 100);
        }
        #[bench]
        fn send_on_20_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 20, 100);
        }

        #[bench]
        fn send_on_100_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 100, 100);
        }

        fn create_set_of_n(n: usize) -> IpcReceiverSet {
            let mut rx_set = IpcReceiverSet::new().unwrap();
            for _ in 0..n {
                let (_, rx) = ipc::channel::<()>().unwrap();
                rx_set.add(rx).unwrap();
            }
            rx_set
        }

        #[bench]
        fn create_and_destroy_empty_set(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(0);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_1(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(1);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_10(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(10);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_100(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(100);
            });
        }

        #[bench]
        // Benchmark adding and removing closed receivers from the set
        fn add_and_remove_closed_receivers(b: &mut test::Bencher) -> () {
            b.iter(|| {
                let mut rx_set = create_set_of_n(1);
                // On select Receivers with a "ClosedChannel" event
                // will be closed
                rx_set.select().unwrap();
                let (_, rx) = ipc::channel::<()>().unwrap();
                rx_set.add(rx).unwrap();
            });
        }
    }
}
<commit_msg>Benchmarks: Measure dropping receivers from set in more isolation<commit_after>#![feature(test)]

extern crate ipc_channel;
extern crate test;

/// Allows doing multiple inner iterations per bench.iter() run.
///
/// This is mostly to amortise the overhead of spawning a thread in the benchmark
/// when sending larger messages (that might be fragmented).
///
/// Note that you need to compensate the displayed results
/// for the proportionally longer runs yourself,
/// as the benchmark framework doesn't know about the inner iterations...
const ITERATIONS: usize = 1;

mod platform {
    extern crate crossbeam;

    use ipc_channel::platform;
    use ITERATIONS;

    use std::sync::{mpsc, Mutex};
    use test;

    #[bench]
    fn create_channel(b: &mut test::Bencher) {
        b.iter(|| {
            for _ in 0..ITERATIONS {
                platform::channel().unwrap();
            }
        });
    }

    fn bench_transfer_data(b: &mut test::Bencher, size: usize) {
        let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
        let (tx, rx) = platform::channel().unwrap();

        let (wait_tx, wait_rx) = mpsc::channel();
        let wait_rx = Mutex::new(wait_rx);

        if size > platform::OsIpcSender::get_max_fragment_size() {
            b.iter(|| {
                crossbeam::scope(|scope| {
                    let tx = tx.clone();
                    scope.spawn(|| {
                        let wait_rx = wait_rx.lock().unwrap();
                        let tx = tx;
                        for _ in 0..ITERATIONS {
                            tx.send(&data, vec![], vec![]).unwrap();
                            if ITERATIONS > 1 {
                                // Prevent beginning of the next send
                                // from overlapping with receive of last fragment,
                                // as otherwise results of runs with a large tail fragment
                                // are significantly skewed.
                                wait_rx.recv().unwrap();
                            }
                        }
                    });
                    for _ in 0..ITERATIONS {
                        rx.recv().unwrap();
                        if ITERATIONS > 1 {
                            wait_tx.send(()).unwrap();
                        }
                    }
                    // For reasons mysterious to me,
                    // not returning a value *from every branch*
                    // adds some 100 ns or so of overhead to all results --
                    // which is quite significant for very short tests...
                    0
                })
            });
        } else {
            b.iter(|| {
                for _ in 0..ITERATIONS {
                    tx.send(&data, vec![], vec![]).unwrap();
                    rx.recv().unwrap();
                }
                0
            });
        }
    }

    #[bench]
    fn transfer_data_00_1(b: &mut test::Bencher) {
        bench_transfer_data(b, 1);
    }
    #[bench]
    fn transfer_data_01_2(b: &mut test::Bencher) {
        bench_transfer_data(b, 2);
    }
    #[bench]
    fn transfer_data_02_4(b: &mut test::Bencher) {
        bench_transfer_data(b, 4);
    }
    #[bench]
    fn transfer_data_03_8(b: &mut test::Bencher) {
        bench_transfer_data(b, 8);
    }
    #[bench]
    fn transfer_data_04_16(b: &mut test::Bencher) {
        bench_transfer_data(b, 16);
    }
    #[bench]
    fn transfer_data_05_32(b: &mut test::Bencher) {
        bench_transfer_data(b, 32);
    }
    #[bench]
    fn transfer_data_06_64(b: &mut test::Bencher) {
        bench_transfer_data(b, 64);
    }
    #[bench]
    fn transfer_data_07_128(b: &mut test::Bencher) {
        bench_transfer_data(b, 128);
    }
    #[bench]
    fn transfer_data_08_256(b: &mut test::Bencher) {
        bench_transfer_data(b, 256);
    }
    #[bench]
    fn transfer_data_09_512(b: &mut test::Bencher) {
        bench_transfer_data(b, 512);
    }
    #[bench]
    fn transfer_data_10_1k(b: &mut test::Bencher) {
        bench_transfer_data(b, 1 * 1024);
    }
    #[bench]
    fn transfer_data_11_2k(b: &mut test::Bencher) {
        bench_transfer_data(b, 2 * 1024);
    }
    #[bench]
    fn transfer_data_12_4k(b: &mut test::Bencher) {
        bench_transfer_data(b, 4 * 1024);
    }
    #[bench]
    fn transfer_data_13_8k(b: &mut test::Bencher) {
        bench_transfer_data(b, 8 * 1024);
    }
    #[bench]
    fn transfer_data_14_16k(b: &mut test::Bencher) {
        bench_transfer_data(b, 16 * 1024);
    }
    #[bench]
    fn transfer_data_15_32k(b: &mut test::Bencher) {
        bench_transfer_data(b, 32 * 1024);
    }
    #[bench]
    fn transfer_data_16_64k(b: &mut test::Bencher) {
        bench_transfer_data(b, 64 * 1024);
    }
    #[bench]
    fn transfer_data_17_128k(b: &mut test::Bencher) {
        bench_transfer_data(b, 128 * 1024);
    }
    #[bench]
    fn transfer_data_18_256k(b: &mut test::Bencher) {
        bench_transfer_data(b, 256 * 1024);
    }
    #[bench]
    fn transfer_data_19_512k(b: &mut test::Bencher) {
        bench_transfer_data(b, 512 * 1024);
    }
    #[bench]
    fn transfer_data_20_1m(b: &mut test::Bencher) {
        bench_transfer_data(b, 1 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_21_2m(b: &mut test::Bencher) {
        bench_transfer_data(b, 2 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_22_4m(b: &mut test::Bencher) {
        bench_transfer_data(b, 4 * 1024 * 1024);
    }
    #[bench]
    fn transfer_data_23_8m(b: &mut test::Bencher) {
        bench_transfer_data(b, 8 * 1024 * 1024);
    }
}

mod ipc {
    mod receiver_set {
        use ipc_channel::ipc::{self, IpcReceiverSet};
        use test;

        fn gen_select_test(b: &mut test::Bencher, to_send: usize, n: usize) -> () {
            let mut active = Vec::with_capacity(to_send);
            let mut dormant = Vec::with_capacity(n - to_send);
            let mut rx_set = IpcReceiverSet::new().unwrap();
            for _ in 0..to_send {
                let (tx, rx) = ipc::channel().unwrap();
                rx_set.add(rx).unwrap();
                active.push(tx);
            }
            for _ in to_send..n {
                let (tx, rx) = ipc::channel::<()>().unwrap();
                rx_set.add(rx).unwrap();
                dormant.push(tx);
            }
            b.iter(|| {
                for tx in active.iter() {
                    tx.send(()).unwrap();
                }
                let mut received = 0;
                while received < to_send {
                    for result in rx_set.select().unwrap().into_iter() {
                        let (_, _) = result.unwrap();
                        received += 1;
                    }
                }
            });
        }

        #[bench]
        fn send_on_1_of_1(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 1);
        }

        #[bench]
        fn send_on_1_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 5);
        }

        #[bench]
        fn send_on_2_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 2, 5);
        }

        #[bench]
        fn send_on_5_of_5(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 5);
        }

        #[bench]
        fn send_on_1_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 20);
        }

        #[bench]
        fn send_on_5_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 20);
        }

        #[bench]
        fn send_on_20_of_20(b: &mut test::Bencher) -> () {
            gen_select_test(b, 20, 20);
        }

        #[bench]
        fn send_on_1_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 1, 100);
        }

        #[bench]
        fn send_on_5_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 5, 100);
        }
        #[bench]
        fn send_on_20_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 20, 100);
        }

        #[bench]
        fn send_on_100_of_100(b: &mut test::Bencher) -> () {
            gen_select_test(b, 100, 100);
        }

        fn create_set_of_n(n: usize) -> IpcReceiverSet {
            let mut rx_set = IpcReceiverSet::new().unwrap();
            for _ in 0..n {
                let (_, rx) = ipc::channel::<()>().unwrap();
                rx_set.add(rx).unwrap();
            }
            rx_set
        }

        #[bench]
        fn create_and_destroy_empty_set(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(0);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_1(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(1);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_10(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(10);
            });
        }

        #[bench]
        fn create_and_destroy_set_of_100(b: &mut test::Bencher) -> () {
            b.iter(|| {
                create_set_of_n(100);
            });
        }

        #[bench]
        // Benchmark adding and removing closed receivers from the set
        fn add_and_remove_closed_receivers(b: &mut test::Bencher) -> () {
            b.iter(|| {
                let mut rx_set = create_set_of_n(1);
                // On select Receivers with a "ClosedChannel" event
                // will be closed
                rx_set.select().unwrap();
            });
        }
    }
}
<|endoftext|>