<commit_before>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Create a retryable operation by passing two mutable closure references to `Retry::new`. The
//! first argument, `value_fn`, will be executed to produce a value. The second argument,
//! `condition_fn`, takes the value produced by `value_fn` and returns a boolean indicating whether
//! or not some desired condition is true. Call `execute` on the returned `Retry` object to begin
//! executing the operation, ultimately returning a `Result` containing the final value or an
//! error.
//!
//! By default, the operation will be retried an infinite number of times with no delay between
//! tries. To change either of these values, you may call the following two methods on the `Retry`
//! object:
//!
//! 1. `try`: The maximum number of tries to make.  If the operation reaches this number of tries
//!    without passsing the condition, an error will be returned.
//! 2. `wait` The number of milliseconds to wait after each unsuccessful try.
//!
//! # Failures
//!
//! Executing a `Retry` will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied to `try`. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt.

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        let mut try = 0;

        loop {
            if self.tries.is_some() && self.tries.unwrap() == try {
                return Err(RetryError { message: "reached last try without condition match" })
            }

            let value = (self.value_fn)();

            if (self.condition_fn)(&value) {
                return Ok(value);
            }

            if self.wait != 0 {
                sleep_ms(self.wait);
            }

            try += 1;
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// Invokes a function a certain number of times or until a condition is satisfied with a fixed
/// wait after each unsuccessful try.
pub fn retry<F, G, R>(
    tries: u32,
    wait: u32,
    mut value_fn: F,
    mut condition_fn: G
) -> Result<R, RetryError> where F: FnMut() -> R, G: FnMut(&R) -> bool {
    Retry::new(&mut value_fn, &mut condition_fn).try(tries).wait(wait).execute()
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

impl Error for RetryError {
    fn description(&self) -> &str {
        self.message
    }
}

#[cfg(test)]
mod tests {
    use super::{Retry, retry};

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn retry_function() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(2, 0, || collection.next().unwrap(), |value| *value == 2).ok().unwrap();

        assert_eq!(value, 2);
    }
}
<commit_msg>Update documentation to account for retry function.<commit_after>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Retry an operation by calling the `retry` function, supplying a maximum number of times to try,
//! the number of milliseconds to wait after each unsuccessful try, a closure that produces a value,
//! and a closure that takes a reference to that value and returns a boolean indicating the success
//! or failure of the operation. The function will return a `Result` containing either the value
//! that satisfied the condition or an error indicating that a satisfactory value could not be
//! produced.
//!
//! You can also construct a retryable operation incrementally using the `Retry` type. `Retry::new`
//! takes the same two closures as mutable references, and returns a `Retry` value. You can then
//! call the `try` and `wait` methods on this value to add a maximum number of tries and a wait
//! time, respectively. Finally, run the `execute` method to produce the `Result`.
//!
//! If a maximum number of tries is not supplied, the operation will be executed infinitely or until
//! success. If a wait time is not supplied, there will be no wait between attempts.
//!
//! # Failures
//!
//! Retrying will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied for the maximum number of tries. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match retry(10, 500, || api_client.query_job_status(), |response| response.code == 200) {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt. The same result can be achieved by building a `Retry` object incrementally:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        let mut try = 0;

        loop {
            if self.tries.is_some() && self.tries.unwrap() == try {
                return Err(RetryError { message: "reached last try without condition match" })
            }

            let value = (self.value_fn)();

            if (self.condition_fn)(&value) {
                return Ok(value);
            }

            if self.wait != 0 {
                sleep_ms(self.wait);
            }

            try += 1;
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// Invokes a function a certain number of times or until a condition is satisfied with a fixed
/// wait after each unsuccessful try.
pub fn retry<F, G, R>(
    tries: u32,
    wait: u32,
    mut value_fn: F,
    mut condition_fn: G
) -> Result<R, RetryError> where F: FnMut() -> R, G: FnMut(&R) -> bool {
    Retry::new(&mut value_fn, &mut condition_fn).try(tries).wait(wait).execute()
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

impl Error for RetryError {
    fn description(&self) -> &str {
        self.message
    }
}

#[cfg(test)]
mod tests {
    use super::{Retry, retry};

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn retry_function() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(2, 0, || collection.next().unwrap(), |value| *value == 2).ok().unwrap();

        assert_eq!(value, 2);
    }
}
<|endoftext|>


<commit_before>
//! # mruby
//! mruby binding

extern crate libc;
mod mruby;

#[test]
fn test_mrb_open() {
    unsafe {
        let mrb : *mut mruby::mrb_state = mruby::mrb_open();
        mruby::mrb_close(mrb);
    }
}
<commit_msg>add Mrb open&close<commit_after>
//! # mruby
//! mruby binding

extern crate libc;
mod mruby;

pub struct Mrb {
    mrb : *mut mruby::mrb_state,
}

pub fn new_mrb() -> Mrb {
    let mrb = unsafe {
        mruby::mrb_open()
    };
    Mrb{mrb:mrb}
}

impl Mrb {
    fn close(&self) {
        unsafe {
            mruby::mrb_close(self.mrb);
        }
        std::mem::drop(self);
    }
}

#[test]
fn test_mrb_open() {
    let m = new_mrb();
    m.close();
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support code for encoding and decoding types.
//!
//! # Usage
//!
//! This crates is [on crates.io](https://crates.io/crates/rustc-serialize) and can be used by
//! adding `rustc-serialize` to your dependencies in your project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//! rustc-serialize = "0.3"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate rustc_serialize;
//! ```

#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/rustc-serialize/")]
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, feature(test))]
#![allow(trivial_numeric_casts)]

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
                          DecoderHelpers, EncoderHelpers};

mod serialize;
mod collection_impls;

pub mod base64;
pub mod hex;
pub mod json;

mod rustc_serialize {
    pub use serialize::*;
}
<commit_msg>Typos<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support code for encoding and decoding types.
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/rustc-serialize) and
//! can be used by adding `rustc-serialize` to the dependencies in your
//! project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//! rustc-serialize = "0.3"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate rustc_serialize;
//! ```

#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/rustc-serialize/")]
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, feature(test))]
#![allow(trivial_numeric_casts)]

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
                          DecoderHelpers, EncoderHelpers};

mod serialize;
mod collection_impls;

pub mod base64;
pub mod hex;
pub mod json;

mod rustc_serialize {
    pub use serialize::*;
}
<|endoftext|>


<commit_before>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current machine.
/// If not possible on the particular architecture returns same as get() which
/// is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(target_os = "linux"))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashMap;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut map = HashMap::new();
    let mut coreid: u64 = 0;
    let mut physid: u64 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value: u64 = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => {break;}
            };
            match parts[0] {
                "core id"     => { coreid = value;},
                "physical id" => { physid = value;},
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            map.insert((physid<<32)|coreid, true);
            chgcount = 0;
        }
    }
    let count = map.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
        target_os = "fuchsia",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}
#[cfg(target_os = "emscripten")]
fn get_num_cpus() -> usize {
    1
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
    assert!(get_physical() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
    assert!(get_physical() < 236_451);
}
<commit_msg>use hashset in get_physical<commit_after>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current machine.
/// If not possible on the particular architecture returns same as get() which
/// is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(target_os = "linux"))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
        target_os = "fuchsia",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}
#[cfg(target_os = "emscripten")]
fn get_num_cpus() -> usize {
    1
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
    assert!(get_physical() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
    assert!(get_physical() < 236_451);
}
<|endoftext|>


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

#![feature(step_trait)]
#![feature(zero_one)]

// TODO: remove when done
#![allow(dead_code)]

mod net;
mod strategies;

pub fn add(a: u32, b: u32) -> u32 {
    a + b
}

#[test]
fn it_works() {
    //net::connection::Connection::new("8.8.8.8:4242", 42424)
}
<commit_msg> less linting about useless imports<commit_after>/*
   This Source Code Form is subject to the terms of the Mozilla Public
   License, v. 2.0. If a copy of the MPL was not distributed with this
   file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#![feature(step_trait)]
#![feature(zero_one)]

// TODO: remove when done
#![allow(dead_code)]
#![allow(unused_imports)]

mod net;
mod strategies;

pub fn add(a: u32, b: u32) -> u32 {
    a + b
}

#[test]
fn it_works() {
    //net::connection::Connection::new("8.8.8.8:4242", 42424)
}
<|endoftext|>


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

//! update-ssh-keys library
//!
//! this library is meant to replace github.com/coreos/update-ssh-keys
//! it will provide the functionality for:
//! * listing authorized keys
//! * adding authorized keys
//! * removing an authorized key by name
//! * disabling an authorized key by name
//!
//! the library will take care of the file locking that is expected from users
//! of the `authorized_keys.d` directory.

#[macro_use]
extern crate error_chain;
extern crate fs2;
extern crate openssh_keys;
extern crate users;

pub mod errors {
    error_chain!{
        links {
            ParseError(::openssh_keys::errors::Error, ::openssh_keys::errors::ErrorKind);
        }
        foreign_links {
            Io(::std::io::Error);
        }
        errors {
            KeysDisabled(name: String) {
                description("keys are disabled")
                display("keys with name '{}' are disabled", name)
            }
            KeysExist(name: String) {
                description("keys already exist")
                display("keys with name '{}' already exist", name)
            }
        }
    }
}

use errors::*;
use users::{User, switch};
use users::os::unix::UserExt;
use openssh_keys::PublicKey;
use std::fs::{File, self};
use fs2::FileExt;
use std::path::{Path, PathBuf};
use std::io::Write;
use std::collections::HashMap;

const SSH_DIR: &'static str = ".ssh";
const AUTHORIZED_KEYS_DIR: &'static str = "authorized_keys.d";
const AUTHORIZED_KEYS_FILE: &'static str = "authorized_keys";
const PRESERVED_KEYS_FILE: &'static str = "orig_authorized_keys";
const LOCK_FILE: &'static str = ".authorized_keys.d.lock";
const STAGE_FILE: &'static str = ".authorized_keys.d.stage_file";
const STAGE_DIR: &'static str = ".authorized_keys.d.stage_dir";

fn lock_file(user: &User) -> PathBuf {
    user.home_dir().join(LOCK_FILE)
}

fn ssh_dir(user: &User) -> PathBuf {
    user.home_dir().join(SSH_DIR)
}

fn authorized_keys_dir(user: &User) -> PathBuf {
    ssh_dir(user).join(AUTHORIZED_KEYS_DIR)
}

fn authorized_keys_file(user: &User) -> PathBuf {
    ssh_dir(user).join(AUTHORIZED_KEYS_FILE)
}

fn stage_dir(user: &User) -> PathBuf {
    ssh_dir(user).join(STAGE_DIR)
}

fn stage_file(user: &User) -> PathBuf {
    ssh_dir(user).join(STAGE_FILE)
}

fn switch_user(user: &User) -> Result<switch::SwitchUserGuard> {
    switch::switch_user_group(user.uid(), user.primary_group_id())
        .chain_err(|| "failed to switch user/group")
}

#[derive(Debug)]
struct FileLock {
    pub lock: File,
}

impl Drop for FileLock {
    fn drop(&mut self) {
        self.unlock().unwrap();
    }
}

impl FileLock {
    fn new(path: &Path) -> Result<Self> {
        Ok(FileLock {
            lock: File::create(path)
                .chain_err(|| format!("failed to create lock file: {:?}", path))?,
        })
    }

    fn lock(&self) -> Result<()> {
        self.lock.lock_exclusive()
            .chain_err(|| "failed to lock file")
    }

    fn unlock(&self) -> Result<()> {
        self.lock.unlock()
            .chain_err(|| "failed to unlock file")
    }
}

#[derive(Debug)]
pub struct AuthorizedKeys {
    pub file: PathBuf,
    pub folder: PathBuf,
    pub keys: HashMap<String, AuthorizedKeySet>,
    pub user: User,
    lock: FileLock,
}

impl Drop for AuthorizedKeys {
    fn drop(&mut self) {}
}

#[derive(Clone, Debug)]
pub struct AuthorizedKeySet {
    pub filename: String,
    pub disabled: bool,
    pub keys: Vec<PublicKey>,
}

impl AuthorizedKeys {
    /// write writes all authorized_keys.d changes onto disk. it writes the
    /// current state to a staging directory and then moves that staging
    /// directory to the authorized_keys.d path.
    pub fn write(&self) -> Result<()> {
        // switch users
        let _guard = switch_user(&self.user)?;

        // get our staging directory
        let stage_dir = stage_dir(&self.user);
        if stage_dir.exists() {
            fs::remove_dir_all(&stage_dir)
                .chain_err(|| format!("failed to remove staging directory '{:?}'", stage_dir))?;
        }
        fs::create_dir(&stage_dir)
            .chain_err(|| format!("failed to create staging directory '{:?}'", stage_dir))?;

        // write all the keys to the staging directory
        for keyset in self.keys.values() {
            let keyfilename = stage_dir.join(&keyset.filename);
            let mut keyfile = File::create(&keyfilename)
                .chain_err(|| format!("failed to create file '{:?}'", keyfilename))?;
            // if the keyset is disabled, skip it. we still want to have a
            // zero-sized file with it's name though to signal that it's
            // disabled.
            if keyset.disabled {
                continue
            }
            for key in &keyset.keys {
                write!(keyfile, "{}\n", key)
                    .chain_err(|| format!("failed to write to file '{:?}'", keyfilename))?;
            }
        }

        // destroy the old authorized keys directory and move the staging one to
        // that location. rename expects an existing, empty directory
        fs::remove_dir_all(&self.folder)
            .chain_err(|| format!("failed to remove directory '{:?}'", self.folder))?;
        fs::create_dir(&self.folder)
            .chain_err(|| format!("failed to create directory '{:?}'", self.folder))?;
        fs::rename(&stage_dir, &self.folder)
            .chain_err(|| format!("failed to move '{:?}' to '{:?}'", stage_dir, self.folder))
    }

    /// sync writes all the keys we have to authorized_keys. it writes the
    /// current state to a staging file and then moves that staging file to the
    /// authorized_keys path
    pub fn sync(&self) -> Result<()> {
        // switch users
        let _guard = switch_user(&self.user)?;

        // get our staging directory
        let stage_filename = stage_file(&self.user);
        let mut stage_file = File::create(&stage_filename)
            .chain_err(|| format!("failed to create or truncate staging file '{:?}'", stage_filename))?;

        // write all the keys to the staging file
        for keyset in self.keys.values() {
            // if the keyset is disabled, skip it
            if keyset.disabled {
                continue
            }
            for key in &keyset.keys {
                write!(stage_file, "{}\n", key)
                    .chain_err(|| format!("failed to write to file '{:?}'", stage_filename))?;
            }
        }

        // destroy the old authorized keys file and move the staging one to that
        // location
        fs::rename(&stage_filename, &self.file)
            .chain_err(|| format!("failed to move '{:?}' to '{:?}'", stage_filename, self.file))
    }

    /// read_all_keys reads all of the authorized keys files in a given
    /// directory. it returns an error if there is a nested directory, if any
    /// file operations fail, or if it can't parse any of the authorized_keys
    /// files
    fn read_all_keys(dir: &Path) -> Result<HashMap<String, AuthorizedKeySet>> {
        let dir_contents = fs::read_dir(&dir)
            .chain_err(|| format!("failed to read from directory {:?}", dir))?;
        let mut keys = HashMap::new();
        for entry in dir_contents {
            let entry = entry.chain_err(|| format!("failed to read entry in directory {:?}", dir))?;
            let path = entry.path();
            if path.is_dir() {
                // if it's a directory, we don't know what to do
                return Err(format!("'{:?}' is a directory", path).into());
            } else {
                let name = path.file_name()
                    .ok_or_else(|| format!("failed to get filename for '{:?}'", path))?
                    .to_str()
                    .ok_or_else(|| format!("failed to convert filename '{:?}' to string", path))?;
                let from = File::open(&path)
                    .chain_err(|| format!("failed to open file {:?}", path))?;
                let keyset = PublicKey::read_keys(from)?;
                keys.insert(name.to_string(), AuthorizedKeySet {
                    filename: name.to_string(),
                    disabled: keyset.is_empty(),
                    keys: keyset,
                });
            }
        }
        Ok(keys)
    }

    /// open creates a new authorized_keys object. if there is an existing
    /// authorized_keys directory on disk it reads all the keys from that. if
    /// there is no directory already and we are told to create it, we add the
    /// existing authorized keys file as an entry, if it exists.
    /// /// before open actually does any of that, it switches it's uid for the span
    /// of the function and then switched back. it also opens a file lock on the
    /// directory that other instances of `update-ssh-keys` will respect. the
    /// file lock will automatically close when this structure goes out of
    /// scope. you can make sure it is unlocked by calling `drop` yourself in
    /// cases where you think the memory may leak (like if you are tossing boxes
    /// around etc).
    ///
    /// open blocks until it can grab the file lock.
    ///
    /// open returns an error if any file operations fail, if it failes to parse
    /// any of the public keys in the existing files, if it failes to change
    /// users, if it failes to grab the lock, or if create is false but the
    /// directory doesn't exist.
    pub fn open(user: User, create: bool) -> Result<Self> {
        // switch users
        let _guard = switch_user(&user)?;
        // make a new file lock and lock it
        let lock = FileLock::new(&lock_file(&user))?;
        lock.lock()?;

        let akd = authorized_keys_dir(&user);

        let keys = if akd.is_dir() {
            // read the existing keysets from the dir
            AuthorizedKeys::read_all_keys(&akd)?
        } else if !akd.exists() && create {
            // read the existing keyset from the file
            let filename = authorized_keys_file(&user);
            if filename.exists() {
                let file = File::open(&filename)
                    .chain_err(|| format!("failed to open authorized keys file: '{:?}'", filename))?;
                let mut keys = HashMap::new();
                keys.insert(PRESERVED_KEYS_FILE.to_string(), AuthorizedKeySet {
                    filename: PRESERVED_KEYS_FILE.to_string(),
                    disabled: false,
                    keys: PublicKey::read_keys(file)?,
                });
                keys
            } else {
                // if the authorized_keys file doesn't exist, we don't start
                // with any keys
                HashMap::new()
            }
        } else {
            // either the akd doesn't exist and create is false, or it exists
            // and is not a directory
            return Err(format!("'{:?}' doesn't exist or is not a directory", akd).into())
        };

        Ok(AuthorizedKeys {
            file: authorized_keys_file(&user),
            folder: akd,
            user: user,
            keys: keys,
            lock: lock,
        })
    }

    /// get_keys gets the authorized keyset with the provided name
    pub fn get_keys(&self, name: &str) -> Option<&AuthorizedKeySet> {
        self.keys.get(name)
    }

    /// get_all_keys returns the hashmap from name to keyset containing all the
    /// keys we know about
    pub fn get_all_keys(&self) -> &HashMap<String, AuthorizedKeySet> {
        &self.keys
    }

    /// add_keys adds a list of public keys with the provide name. if replace is
    /// true, it will replace existing keys. if force is true, it will replace
    /// disabled keys.
    ///
    /// add_keys returns an error if the key already exists and replace is
    /// false, or if the key is disabled and force is false
    pub fn add_keys(&mut self, name: &str, keys: Vec<PublicKey>, replace: bool, force: bool) -> Result<()> {
        if let Some(keyset) = self.keys.get(name) {
            if keyset.disabled && !force {
                return Err(ErrorKind::KeysDisabled(name.to_string()).into());
            } else if !replace {
                return Err(ErrorKind::KeysExist(name.to_string()).into());
            }
        }
        self.keys.insert(name.to_string(), AuthorizedKeySet {
            filename: name.to_string(),
            disabled: false,
            keys: keys,
        });
        Ok(())
    }

    /// remove_keys removes the keyset with the given name.
    pub fn remove_keys(&mut self, name: &str) {
        self.keys.remove(name);
    }

    /// disable_keys disables keys with the given name. they can't be added
    /// again unless force is set to true when adding the set. disable_keys will
    /// succeed in disabling the key even if the key doesn't currently exist.
    pub fn disable_keys(&mut self, name: &str) {
        if let Some(keyset) = self.keys.get_mut(name) {
            keyset.disabled = true;
            return;
        }
        self.keys.insert(name.to_string(), AuthorizedKeySet {
            filename: name.to_string(),
            disabled: true,
            keys: vec![],
        });
    }
}
<commit_msg>lib: harden directory manipulation code<commit_after>// Copyright 2017 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! update-ssh-keys library
//!
//! this library is meant to replace github.com/coreos/update-ssh-keys
//! it will provide the functionality for:
//! * listing authorized keys
//! * adding authorized keys
//! * removing an authorized key by name
//! * disabling an authorized key by name
//!
//! the library will take care of the file locking that is expected from users
//! of the `authorized_keys.d` directory.

#[macro_use]
extern crate error_chain;
extern crate fs2;
extern crate openssh_keys;
extern crate users;

pub mod errors {
    error_chain!{
        links {
            ParseError(::openssh_keys::errors::Error, ::openssh_keys::errors::ErrorKind);
        }
        foreign_links {
            Io(::std::io::Error);
        }
        errors {
            KeysDisabled(name: String) {
                description("keys are disabled")
                display("keys with name '{}' are disabled", name)
            }
            KeysExist(name: String) {
                description("keys already exist")
                display("keys with name '{}' already exist", name)
            }
        }
    }
}

use errors::*;
use users::{User, switch};
use users::os::unix::UserExt;
use openssh_keys::PublicKey;
use std::fs::{File, self};
use fs2::FileExt;
use std::path::{Path, PathBuf};
use std::io::Write;
use std::collections::HashMap;

const SSH_DIR: &'static str = ".ssh";
const AUTHORIZED_KEYS_DIR: &'static str = "authorized_keys.d";
const AUTHORIZED_KEYS_FILE: &'static str = "authorized_keys";
const PRESERVED_KEYS_FILE: &'static str = "orig_authorized_keys";
const LOCK_FILE: &'static str = ".authorized_keys.d.lock";
const STAGE_FILE: &'static str = ".authorized_keys.d.stage_file";
const STAGE_DIR: &'static str = ".authorized_keys.d.stage_dir";

fn lock_file(user: &User) -> PathBuf {
    user.home_dir().join(LOCK_FILE)
}

fn ssh_dir(user: &User) -> PathBuf {
    user.home_dir().join(SSH_DIR)
}

fn authorized_keys_dir(user: &User) -> PathBuf {
    ssh_dir(user).join(AUTHORIZED_KEYS_DIR)
}

fn authorized_keys_file(user: &User) -> PathBuf {
    ssh_dir(user).join(AUTHORIZED_KEYS_FILE)
}

fn stage_dir(user: &User) -> PathBuf {
    ssh_dir(user).join(STAGE_DIR)
}

fn stage_file(user: &User) -> PathBuf {
    ssh_dir(user).join(STAGE_FILE)
}

fn switch_user(user: &User) -> Result<switch::SwitchUserGuard> {
    switch::switch_user_group(user.uid(), user.primary_group_id())
        .chain_err(|| "failed to switch user/group")
}

#[derive(Debug)]
struct FileLock {
    pub lock: File,
}

impl Drop for FileLock {
    fn drop(&mut self) {
        self.unlock().unwrap();
    }
}

impl FileLock {
    fn new(path: &Path) -> Result<Self> {
        Ok(FileLock {
            lock: File::create(path)
                .chain_err(|| format!("failed to create lock file: {:?}", path))?,
        })
    }

    fn lock(&self) -> Result<()> {
        self.lock.lock_exclusive()
            .chain_err(|| "failed to lock file")
    }

    fn unlock(&self) -> Result<()> {
        self.lock.unlock()
            .chain_err(|| "failed to unlock file")
    }
}

#[derive(Debug)]
pub struct AuthorizedKeys {
    pub file: PathBuf,
    pub folder: PathBuf,
    pub keys: HashMap<String, AuthorizedKeySet>,
    pub user: User,
    lock: FileLock,
}

impl Drop for AuthorizedKeys {
    fn drop(&mut self) {}
}

#[derive(Clone, Debug)]
pub struct AuthorizedKeySet {
    pub filename: String,
    pub disabled: bool,
    pub keys: Vec<PublicKey>,
}

/// truncate_dir empties a directory and resets it's permission to the current
/// umask. If the directory doesn't exists, it creates it. If the path exists
/// but it's a file, it deletes the file and creates a directory there instead.
fn truncate_dir<P: AsRef<Path>>(dir: P) -> Result<()> {
    let dir = dir.as_ref();

    if dir.exists() {
        if dir.is_dir() {
            fs::remove_dir_all(dir)
                .chain_err(|| format!("failed to remove existing directory '{:?}'", dir))?;
        } else if dir.is_file() {
            fs::remove_file(dir)
                .chain_err(|| format!("failed to remove existing file '{:?}'", dir))?;
        } else {
            return Err(format!("failed to remove existing path '{:?}': not a file or directory", dir).into())
        }
    }

    fs::create_dir_all(dir)
        .chain_err(|| format!("failed to create directory '{:?}'", dir))
}

/// replace_dir moves old to new by deleting new and renaming old. If new
/// doesn't exist, it simply renames old to new. if new is a file, it deletes
/// file and moves the directory. If old doesn't exist, nothing happens. If old
/// is a file and not a directory, nothing happens.
fn replace_dir<P: AsRef<Path>>(old: P, new: P) -> Result<()> {
    let old = old.as_ref();
    let new = new.as_ref();

    if old.exists() && old.is_dir() {
        truncate_dir(new)?;
        fs::rename(old, new)
            .chain_err(|| format!("failed to move '{:?}' to '{:?}'", old, new))?;
    }

    Ok(())
}

impl AuthorizedKeys {
    /// write writes all authorized_keys.d changes onto disk. it writes the
    /// current state to a staging directory and then moves that staging
    /// directory to the authorized_keys.d path.
    pub fn write(&self) -> Result<()> {
        // switch users
        let _guard = switch_user(&self.user)?;

        // get our staging directory
        let stage_dir = stage_dir(&self.user);
        truncate_dir(&stage_dir)
            .chain_err(|| format!("failed to create staging directory"))?;

        // write all the keys to the staging directory
        for keyset in self.keys.values() {
            let keyfilename = stage_dir.join(&keyset.filename);
            let mut keyfile = File::create(&keyfilename)
                .chain_err(|| format!("failed to create file '{:?}'", keyfilename))?;
            // if the keyset is disabled, skip it. we still want to have a
            // zero-sized file with it's name though to signal that it's
            // disabled.
            if keyset.disabled {
                continue
            }
            for key in &keyset.keys {
                write!(keyfile, "{}\n", key)
                    .chain_err(|| format!("failed to write to file '{:?}'", keyfilename))?;
            }
        }

        replace_dir(&stage_dir, &self.folder)
    }

    /// sync writes all the keys we have to authorized_keys. it writes the
    /// current state to a staging file and then moves that staging file to the
    /// authorized_keys path
    pub fn sync(&self) -> Result<()> {
        // switch users
        let _guard = switch_user(&self.user)?;

        // get our staging directory
        let stage_filename = stage_file(&self.user);
        let mut stage_file = File::create(&stage_filename)
            .chain_err(|| format!("failed to create or truncate staging file '{:?}'", stage_filename))?;

        // write all the keys to the staging file
        for keyset in self.keys.values() {
            // if the keyset is disabled, skip it
            if keyset.disabled {
                continue
            }
            for key in &keyset.keys {
                write!(stage_file, "{}\n", key)
                    .chain_err(|| format!("failed to write to file '{:?}'", stage_filename))?;
            }
        }

        // destroy the old authorized keys file and move the staging one to that
        // location
        fs::rename(&stage_filename, &self.file)
            .chain_err(|| format!("failed to move '{:?}' to '{:?}'", stage_filename, self.file))
    }

    /// read_all_keys reads all of the authorized keys files in a given
    /// directory. it returns an error if there is a nested directory, if any
    /// file operations fail, or if it can't parse any of the authorized_keys
    /// files
    fn read_all_keys(dir: &Path) -> Result<HashMap<String, AuthorizedKeySet>> {
        let dir_contents = fs::read_dir(&dir)
            .chain_err(|| format!("failed to read from directory {:?}", dir))?;
        let mut keys = HashMap::new();
        for entry in dir_contents {
            let entry = entry.chain_err(|| format!("failed to read entry in directory {:?}", dir))?;
            let path = entry.path();
            if path.is_dir() {
                // if it's a directory, we don't know what to do
                return Err(format!("'{:?}' is a directory", path).into());
            } else {
                let name = path.file_name()
                    .ok_or_else(|| format!("failed to get filename for '{:?}'", path))?
                    .to_str()
                    .ok_or_else(|| format!("failed to convert filename '{:?}' to string", path))?;
                let from = File::open(&path)
                    .chain_err(|| format!("failed to open file {:?}", path))?;
                let keyset = PublicKey::read_keys(from)?;
                keys.insert(name.to_string(), AuthorizedKeySet {
                    filename: name.to_string(),
                    disabled: keyset.is_empty(),
                    keys: keyset,
                });
            }
        }
        Ok(keys)
    }

    /// open creates a new authorized_keys object. if there is an existing
    /// authorized_keys directory on disk it reads all the keys from that. if
    /// there is no directory already and we are told to create it, we add the
    /// existing authorized keys file as an entry, if it exists.
    /// /// before open actually does any of that, it switches it's uid for the span
    /// of the function and then switched back. it also opens a file lock on the
    /// directory that other instances of `update-ssh-keys` will respect. the
    /// file lock will automatically close when this structure goes out of
    /// scope. you can make sure it is unlocked by calling `drop` yourself in
    /// cases where you think the memory may leak (like if you are tossing boxes
    /// around etc).
    ///
    /// open blocks until it can grab the file lock.
    ///
    /// open returns an error if any file operations fail, if it failes to parse
    /// any of the public keys in the existing files, if it failes to change
    /// users, if it failes to grab the lock, or if create is false but the
    /// directory doesn't exist.
    pub fn open(user: User, create: bool) -> Result<Self> {
        // switch users
        let _guard = switch_user(&user)?;
        // make a new file lock and lock it
        let lock = FileLock::new(&lock_file(&user))?;
        lock.lock()?;

        let akd = authorized_keys_dir(&user);

        let keys = if akd.is_dir() {
            // read the existing keysets from the dir
            AuthorizedKeys::read_all_keys(&akd)?
        } else if !akd.exists() && create {
            // read the existing keyset from the file
            let filename = authorized_keys_file(&user);
            if filename.exists() {
                let file = File::open(&filename)
                    .chain_err(|| format!("failed to open authorized keys file: '{:?}'", filename))?;
                let mut keys = HashMap::new();
                keys.insert(PRESERVED_KEYS_FILE.to_string(), AuthorizedKeySet {
                    filename: PRESERVED_KEYS_FILE.to_string(),
                    disabled: false,
                    keys: PublicKey::read_keys(file)?,
                });
                keys
            } else {
                // if the authorized_keys file doesn't exist, we don't start
                // with any keys
                HashMap::new()
            }
        } else {
            // either the akd doesn't exist and create is false, or it exists
            // and is not a directory
            return Err(format!("'{:?}' doesn't exist or is not a directory", akd).into())
        };

        Ok(AuthorizedKeys {
            file: authorized_keys_file(&user),
            folder: akd,
            user: user,
            keys: keys,
            lock: lock,
        })
    }

    /// get_keys gets the authorized keyset with the provided name
    pub fn get_keys(&self, name: &str) -> Option<&AuthorizedKeySet> {
        self.keys.get(name)
    }

    /// get_all_keys returns the hashmap from name to keyset containing all the
    /// keys we know about
    pub fn get_all_keys(&self) -> &HashMap<String, AuthorizedKeySet> {
        &self.keys
    }

    /// add_keys adds a list of public keys with the provide name. if replace is
    /// true, it will replace existing keys. if force is true, it will replace
    /// disabled keys.
    ///
    /// add_keys returns an error if the key already exists and replace is
    /// false, or if the key is disabled and force is false
    pub fn add_keys(&mut self, name: &str, keys: Vec<PublicKey>, replace: bool, force: bool) -> Result<()> {
        if let Some(keyset) = self.keys.get(name) {
            if keyset.disabled && !force {
                return Err(ErrorKind::KeysDisabled(name.to_string()).into());
            } else if !replace {
                return Err(ErrorKind::KeysExist(name.to_string()).into());
            }
        }
        self.keys.insert(name.to_string(), AuthorizedKeySet {
            filename: name.to_string(),
            disabled: false,
            keys: keys,
        });
        Ok(())
    }

    /// remove_keys removes the keyset with the given name.
    pub fn remove_keys(&mut self, name: &str) {
        self.keys.remove(name);
    }

    /// disable_keys disables keys with the given name. they can't be added
    /// again unless force is set to true when adding the set. disable_keys will
    /// succeed in disabling the key even if the key doesn't currently exist.
    pub fn disable_keys(&mut self, name: &str) {
        if let Some(keyset) = self.keys.get_mut(name) {
            keyset.disabled = true;
            return;
        }
        self.keys.insert(name.to_string(), AuthorizedKeySet {
            filename: name.to_string(),
            disabled: true,
            keys: vec![],
        });
    }
}
<|endoftext|>


<commit_before>#![crate_name = "love2d"]

#[macro_use]
extern crate glium;

#[macro_use]
mod support;
mod draw;
mod events;

pub use support::Action;
pub use events::Event;
pub use glium::glutin::{ElementState, VirtualKeyCode};
use draw::Shape;
use glium::glutin;

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    events: Vec<Event>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            events: Vec::new(),
        }
    }

    pub fn poll_events(&mut self) -> Vec<Event> {
        self.events.drain(..).collect()
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();
            let rtn = callback(self, delta);

            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut events: Vec<Event> = Vec::new();
            self.events_loop.poll_events(|ev| {
                let event = events::translate(ev);
                events.push(event);
            });

            for event in events {
                self.events.push(event);
            }

            rtn
        });
    }
}
<commit_msg>Filtered unsupported events<commit_after>#![crate_name = "love2d"]

#[macro_use]
extern crate glium;

#[macro_use]
mod support;
mod draw;
mod events;

pub use support::Action;
pub use events::Event;
pub use glium::glutin::{ElementState, VirtualKeyCode};
use draw::Shape;
use glium::glutin;

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    events: Vec<Event>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            events: Vec::new(),
        }
    }

    pub fn poll_events(&mut self) -> Vec<Event> {
        self.events.drain(..).collect()
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();
            let rtn = callback(self, delta);

            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut events: Vec<Event> = Vec::new();
            self.events_loop.poll_events(|ev| {
                let event = events::translate(ev);
                match event {
                    Event::Unsupported => (),
                    event => events.push(event),
                }
            });

            for event in events {
                self.events.push(event);
            }

            rtn
        });
    }
}
<|endoftext|>


<commit_before>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.
use std::sync::{Mutex, Condvar};

///A synchronization primitive that signals when its count reaches zero.
///
///With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
///occurring in other threads by making the other threads interact with the counter as they perform
///their work.
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = self.counter.lock().unwrap();

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: fn.add.html
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: fn.signal.html
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = self.counter.lock().unwrap();

        while *count > 0 {
            count = self.lock.wait(count).unwrap();
        }
    }
}
<commit_msg>add docs and doctest for CountdownEvent<commit_after>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.
use std::sync::{Mutex, Condvar};

///A synchronization primitive that signals when its count reaches zero.
///
///With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
///occurring in other threads by making the other threads interact with the counter as they perform
///their work.
///
///The main limitation of a CountdownEvent is that once its counter reaches zero (even by starting
///there), any attempts to update the counter will return `CountdownError::AlreadySet` until the
///counter is reset by calling `reset` or `reset_to_count`.
///
///# Example
///
///```
/// use synchronoise::CountdownEvent;
/// use std::sync::Arc;
/// use std::thread;
/// use std::time::Duration;
///
/// let counter = Arc::new(CountdownEvent::new(5));
///
/// for i in 0..5 {
///     let signal = counter.clone();
///     thread::spawn(move || {
///         thread::sleep(Duration::from_secs(3));
///         println!("thread {} activated!", i);
///         signal.decrement();
///     });
/// }
///
/// counter.wait();
///
/// println!("all done!");
///```
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = self.counter.lock().unwrap();

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: fn.add.html
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: fn.signal.html
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = self.counter.lock().unwrap();

        while *count > 0 {
            count = self.lock.wait(count).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>//! Url Encoded middleware for Iron
//!
//! This middleware focuses on parsing the incoming url parameters from client requests.
#![crate_id = "urlencoded"]
#![license = "MIT"]

extern crate url;
extern crate iron;
extern crate serialize;

use iron::{Request, Response, Middleware, Alloy, Status, Continue};
use iron::mixin::GetUrl;

use std::collections::HashMap;

/// Stores a `HashMap` of a `String` and a `Vec<Strings>` to address
/// client data that is sent with multiple values for a single key.
#[deriving(Clone)]
pub struct Encoded(pub HashMap<String, Vec<String>>);

/// This middleware is used for parsing url parameters and storing
/// the data as conveniently accessible data `insert`ed into an Alloy.
#[deriving(Clone)]
pub struct UrlEncoded;

/// Creates a `UrlEncoded` instance to `link` to `server.chain`. Calling the
/// function will `insert` a new `HashMap` into the `alloy`.
impl UrlEncoded {
    pub fn new() -> UrlEncoded {
        UrlEncoded
    }
}

impl Middleware for UrlEncoded {

    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {

        let raw_url = req.url();

        let path = match raw_url {
            Some(k) => {
                url::path_from_str(k.as_slice())
            },
            None => {
                return Continue;
            }
        };

        let query = match path {
            Ok(e) => {
                e.query
            },
            Err(_) => {
                return Continue;
            }
        };
        alloy.insert::<Encoded>(Encoded(create_hash(query)));
        Continue
    }
}

fn create_hash(q: Vec<(String, String)>) -> HashMap<String, Vec<String>> {

    let mut hashStrVec: HashMap<String, Vec<String>> = HashMap::new();

    for (k, v) in q.move_iter() {
        hashStrVec.find_with_or_insert_with(
            k, v,
            |_, already, new| {
                already.push(new);
            },
            |_, v| vec![v]
        );
    }
    hashStrVec
}

#[test]
fn test_create_hash() {
    let my_vec = vec!(("band".to_string(), "arctic monkeys".to_string()),("band".to_string(), "temper trap".to_string()),("color".to_string(),"green".to_string()));
    let answer = create_hash(my_vec);
    let mut control = HashMap::new();
    control.insert("band".to_string(), vec!("arctic monkeys".to_string(), "temper trap".to_string()));
    control.insert("color".to_string(), vec!("green".to_string()));
    assert!(answer==control);
}
<commit_msg>(refactor) Deleted unused variable<commit_after>//! Url Encoded middleware for Iron
//!
//! This middleware focuses on parsing the incoming url parameters from client requests.
#![crate_id = "urlencoded"]
#![license = "MIT"]

extern crate url;
extern crate iron;
extern crate serialize;

use iron::{Request, Response, Middleware, Alloy, Status, Continue};
use iron::mixin::GetUrl;

use std::collections::HashMap;

/// Stores a `HashMap` of a `String` and a `Vec<Strings>` to address
/// client data that is sent with multiple values for a single key.
#[deriving(Clone)]
pub struct Encoded(pub HashMap<String, Vec<String>>);

/// This middleware is used for parsing url parameters and storing
/// the data as conveniently accessible data `insert`ed into an Alloy.
#[deriving(Clone)]
pub struct UrlEncoded;

/// Creates a `UrlEncoded` instance to `link` to `server.chain`. Calling the
/// function will `insert` a new `HashMap` into the `alloy`.
impl UrlEncoded {
    pub fn new() -> UrlEncoded {
        UrlEncoded
    }
}

impl Middleware for UrlEncoded {

    fn enter(&mut self, req: &mut Request, _ : &mut Response, alloy: &mut Alloy) -> Status {

        let raw_url = req.url();

        let path = match raw_url {
            Some(k) => {
                url::path_from_str(k.as_slice())
            },
            None => {
                return Continue;
            }
        };

        let query = match path {
            Ok(e) => {
                e.query
            },
            Err(_) => {
                return Continue;
            }
        };
        alloy.insert::<Encoded>(Encoded(create_hash(query)));
        Continue
    }
}

fn create_hash(q: Vec<(String, String)>) -> HashMap<String, Vec<String>> {

    let mut hashStrVec: HashMap<String, Vec<String>> = HashMap::new();

    for (k, v) in q.move_iter() {
        hashStrVec.find_with_or_insert_with(
            k, v,
            |_, already, new| {
                already.push(new);
            },
            |_, v| vec![v]
        );
    }
    hashStrVec
}

#[test]
fn test_create_hash() {
    let my_vec = vec!(("band".to_string(), "arctic monkeys".to_string()),("band".to_string(), "temper trap".to_string()),("color".to_string(),"green".to_string()));
    let answer = create_hash(my_vec);
    let mut control = HashMap::new();
    control.insert("band".to_string(), vec!("arctic monkeys".to_string(), "temper trap".to_string()));
    control.insert("color".to_string(), vec!("green".to_string()));
    assert!(answer==control);
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate nalgebra;
extern crate test;
extern crate num;

use num::Zero;
use nalgebra::{DMat, Indexable};
use std::ops::{Add, Sub};
use std::fmt::{Display};

/// This trait describes the type of values within a summed area table source.
/// Implementing this trait for your type allows it to become a value within a source.
pub trait SourceValue<T>: Display  + Clone + Copy + Zero + Add<T,Output=T> + Sub<T,Output=T> {
}

/// This trait describes a generic source for a summed area table.
/// Implementing this trait for your type allows it to become the source for a summed area table calculation.
pub trait SummedAreaTableSource<T: SourceValue<T>>{

	/// Returns a matrix of source values of type T.
	/// The calculated summed area table will be based on these values.
	fn get_values(&self) -> &DMat<T>;

	/// Calculates and returns the summed area table for the source matrix.
	fn calculate_summed_area_table(&self) -> SummedAreaTable<T>{
		let vals = self.get_values();
		let mut table = DMat::new_zeros(vals.nrows(),vals.ncols());

		unsafe {
			for row in (0 ..vals.nrows()) {
				for col in (0 ..vals.ncols()) {

					let mut sum = vals.unsafe_at((row, col));

					if row>0 {
						sum = sum+ table.unsafe_at((row-1, col));
					}
					if col>0 {
						sum = sum+ table.unsafe_at((row, col-1));
					}
					if row>0 && col>0 {
						sum = sum - table.unsafe_at((row-1, col-1));
					}
					table.unsafe_set((row,col), sum);
				}
			}
		}

		SummedAreaTable::<T>{table: table}
	}
}

/// This struct is the result of a summed area table calculation.
pub struct SummedAreaTable<T: SourceValue<T>> {
	pub table: DMat<T>,
}

impl <T: SourceValue<T>>SummedAreaTable<T> {

	/// Returns the sum for a given area,
	/// that is described by its upper left and lower right point.
	/// It will panic in debug mode if the given points are not within the tables bounds.
	/// It will panic in debug mode if `from` is right of or below `to`.
	/// `from` is a x/y coordinate tuple for the upper left point (inclusive)
	/// `to` is a x/y coordinate tuple for the lower right point (inclusive)
	pub fn get_sum(&self, from: (usize,usize), to: (usize,usize)) -> T{
		let (col1, row1) = from;
		let (col2, row2) = to;

		debug_assert!(row1 <= row2 && col1 <= col2, "`from` ({}/{}) must not be right of or below `to`({}/{})", col1, row1, col2, row2);

		debug_assert!( {
			let ncols = self.table.ncols();
			let nrows = self.table.nrows();
			col1 < ncols && col2 < ncols && row1 < nrows && row2 < nrows
		},"`from` ({}/{}) or `to` ({}/{}) not within table bounds [(0/0)..({}/{})]", col1, row1, col2, row2,  self.table.ncols()-1,  self.table.nrows()-1);

		unsafe {
			let mut sum = self.table.unsafe_at((row2,col2));

			if col1 > 0 && row1 > 0 {
				sum = sum + self.table.unsafe_at((col1-1,row1-1));
			}
			if col1 > 0 {
				sum = sum - self.table.unsafe_at((col1-1,row2));
			}
			if row1 > 0 {
				sum = sum - self.table.unsafe_at((col2,row1-1));
			}
			sum
		}
	}
}

impl SourceValue<usize> for usize {
}

impl SummedAreaTableSource<usize> for DMat<usize>{
	fn get_values(&self) -> &DMat<usize> {
		self
	}
}

#[test]
fn zeros() {
	let src: DMat<usize> = DMat::new_zeros(100,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(10000, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones_without_first_col_row() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(10000-199, table.get_sum((1,1),(99,99)));
}

#[test]
fn twos() {
	let src: DMat<usize> = DMat::from_elem(100,100,2);
	let table = src.calculate_summed_area_table();
	assert_eq!(20000, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones_quartered() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(2500, table.get_sum((0,0),(49,49)));
	assert_eq!(2500, table.get_sum((50,50),(99,99)));
	assert_eq!(2500, table.get_sum((50,0),(99,49)));
	assert_eq!(2500, table.get_sum((0,50),(49,99)));
}

#[test]
fn twos_quartered() {
	let src: DMat<usize> = DMat::from_elem(100,100,2);
	let table = src.calculate_summed_area_table();
	assert_eq!(5000, table.get_sum((0,0),(49,49)));
	assert_eq!(5000, table.get_sum((50,50),(99,99)));
	assert_eq!(5000, table.get_sum((50,0),(99,49)));
	assert_eq!(5000, table.get_sum((0,50),(49,99)));
}

#[test]
fn first_row() {
	let src: DMat<usize> = DMat::from_elem(10,20,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(20, table.get_sum((0,0),(19,0)));
}

#[test]
fn first_col() {
	let src: DMat<usize> = DMat::from_elem(50,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(50, table.get_sum((0,0),(0,49)));
}

#[test]
fn from_to_equal() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(1, table.get_sum((0,0),(0,0)));
	assert_eq!(1, table.get_sum((50,50),(50,50)));
	assert_eq!(1, table.get_sum((99,99),(99,99)));
}

#[test]
fn custom() {

	let src = DMat::from_row_vec(5,5, &[
		5,2,3,4,1,
		1,5,4,2,3,
		2,2,1,3,4,
		3,5,6,4,5,
		4,1,3,2,6
	]);
	let expected_table = DMat::from_row_vec(5,5, &[
		5,7,10,14,15,
		6,13,20,26,30,
		8,17,25,34,42,
		11,25,39,52,65,
		15,30,47,62,81
	]);

	let table = src.calculate_summed_area_table();

	unsafe{
		for row in 0 .. 5 {
			for col in 0 .. 5 {
				assert_eq!(expected_table.unsafe_at((row,col)), table.table.unsafe_at((row,col)));
			}
		};
		for x in 0 .. 5 {
			for y in 0 .. 5 {
				assert_eq!(expected_table.unsafe_at((y,x)), table.get_sum((0,0), (x,y)));
			}
		}
	}
}

#[test]
#[should_panic]
fn bound_check_x() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	table.get_sum((0,0),(50,99));
}

#[test]
#[should_panic]
fn bound_check_y() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	table.get_sum((0,0),(49,100));
}

#[test]
#[should_panic]
fn point_order_check1() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(48,98)));
}

#[test]
#[should_panic]
fn point_order_check2() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(48,99)));
}

#[test]
#[should_panic]
fn point_order_check3() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(49,98)));
}

#[bench]
fn large_1k_matrix(b: &mut test::Bencher) {
	let src: DMat<usize> = DMat::from_elem(1000,1000,1);
	b.iter(|| {
		src.calculate_summed_area_table();
	});
}

#[bench]
fn large_2k_matrix(b: &mut test::Bencher) {
	let src: DMat<usize> = DMat::from_elem(2000,2000,1);
	b.iter(|| {
		src.calculate_summed_area_table();
	})
}

#[bench]
fn large_4k_matrix(b: &mut test::Bencher) {
	let src: DMat<usize> = DMat::from_elem(4000,4000,1);
	b.iter(|| {
		src.calculate_summed_area_table();
	})
}
<commit_msg>removed benchmarking in order to be build with stable rust<commit_after>
extern crate nalgebra;
extern crate num;

use num::Zero;
use nalgebra::{DMat, Indexable};
use std::ops::{Add, Sub};
use std::fmt::{Display};

/// This trait describes the type of values within a summed area table source.
/// Implementing this trait for your type allows it to become a value within a source.
pub trait SourceValue<T>: Display  + Clone + Copy + Zero + Add<T,Output=T> + Sub<T,Output=T> {
}

/// This trait describes a generic source for a summed area table.
/// Implementing this trait for your type allows it to become the source for a summed area table calculation.
pub trait SummedAreaTableSource<T: SourceValue<T>>{

	/// Returns a matrix of source values of type T.
	/// The calculated summed area table will be based on these values.
	fn get_values(&self) -> &DMat<T>;

	/// Calculates and returns the summed area table for the source matrix.
	fn calculate_summed_area_table(&self) -> SummedAreaTable<T>{
		let vals = self.get_values();
		let mut table = DMat::new_zeros(vals.nrows(),vals.ncols());

		unsafe {
			for row in (0 ..vals.nrows()) {
				for col in (0 ..vals.ncols()) {

					let mut sum = vals.unsafe_at((row, col));

					if row>0 {
						sum = sum+ table.unsafe_at((row-1, col));
					}
					if col>0 {
						sum = sum+ table.unsafe_at((row, col-1));
					}
					if row>0 && col>0 {
						sum = sum - table.unsafe_at((row-1, col-1));
					}
					table.unsafe_set((row,col), sum);
				}
			}
		}

		SummedAreaTable::<T>{table: table}
	}
}

/// This struct is the result of a summed area table calculation.
pub struct SummedAreaTable<T: SourceValue<T>> {
	pub table: DMat<T>,
}

impl <T: SourceValue<T>>SummedAreaTable<T> {

	/// Returns the sum for a given area,
	/// that is described by its upper left and lower right point.
	/// It will panic in debug mode if the given points are not within the tables bounds.
	/// It will panic in debug mode if `from` is right of or below `to`.
	/// `from` is a x/y coordinate tuple for the upper left point (inclusive)
	/// `to` is a x/y coordinate tuple for the lower right point (inclusive)
	pub fn get_sum(&self, from: (usize,usize), to: (usize,usize)) -> T{
		let (col1, row1) = from;
		let (col2, row2) = to;

		debug_assert!(row1 <= row2 && col1 <= col2, "`from` ({}/{}) must not be right of or below `to`({}/{})", col1, row1, col2, row2);

		debug_assert!( {
			let ncols = self.table.ncols();
			let nrows = self.table.nrows();
			col1 < ncols && col2 < ncols && row1 < nrows && row2 < nrows
		},"`from` ({}/{}) or `to` ({}/{}) not within table bounds [(0/0)..({}/{})]", col1, row1, col2, row2,  self.table.ncols()-1,  self.table.nrows()-1);

		unsafe {
			let mut sum = self.table.unsafe_at((row2,col2));

			if col1 > 0 && row1 > 0 {
				sum = sum + self.table.unsafe_at((col1-1,row1-1));
			}
			if col1 > 0 {
				sum = sum - self.table.unsafe_at((col1-1,row2));
			}
			if row1 > 0 {
				sum = sum - self.table.unsafe_at((col2,row1-1));
			}
			sum
		}
	}
}

impl SourceValue<usize> for usize {
}

impl SummedAreaTableSource<usize> for DMat<usize>{
	fn get_values(&self) -> &DMat<usize> {
		self
	}
}

#[test]
fn zeros() {
	let src: DMat<usize> = DMat::new_zeros(100,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(10000, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones_without_first_col_row() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(10000-199, table.get_sum((1,1),(99,99)));
}

#[test]
fn twos() {
	let src: DMat<usize> = DMat::from_elem(100,100,2);
	let table = src.calculate_summed_area_table();
	assert_eq!(20000, table.get_sum((0,0),(99,99)));
}

#[test]
fn ones_quartered() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(2500, table.get_sum((0,0),(49,49)));
	assert_eq!(2500, table.get_sum((50,50),(99,99)));
	assert_eq!(2500, table.get_sum((50,0),(99,49)));
	assert_eq!(2500, table.get_sum((0,50),(49,99)));
}

#[test]
fn twos_quartered() {
	let src: DMat<usize> = DMat::from_elem(100,100,2);
	let table = src.calculate_summed_area_table();
	assert_eq!(5000, table.get_sum((0,0),(49,49)));
	assert_eq!(5000, table.get_sum((50,50),(99,99)));
	assert_eq!(5000, table.get_sum((50,0),(99,49)));
	assert_eq!(5000, table.get_sum((0,50),(49,99)));
}

#[test]
fn first_row() {
	let src: DMat<usize> = DMat::from_elem(10,20,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(20, table.get_sum((0,0),(19,0)));
}

#[test]
fn first_col() {
	let src: DMat<usize> = DMat::from_elem(50,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(50, table.get_sum((0,0),(0,49)));
}

#[test]
fn from_to_equal() {
	let src: DMat<usize> = DMat::from_elem(100,100,1);
	let table = src.calculate_summed_area_table();
	assert_eq!(1, table.get_sum((0,0),(0,0)));
	assert_eq!(1, table.get_sum((50,50),(50,50)));
	assert_eq!(1, table.get_sum((99,99),(99,99)));
}

#[test]
fn custom() {

	let src = DMat::from_row_vec(5,5, &[
		5,2,3,4,1,
		1,5,4,2,3,
		2,2,1,3,4,
		3,5,6,4,5,
		4,1,3,2,6
	]);
	let expected_table = DMat::from_row_vec(5,5, &[
		5,7,10,14,15,
		6,13,20,26,30,
		8,17,25,34,42,
		11,25,39,52,65,
		15,30,47,62,81
	]);

	let table = src.calculate_summed_area_table();

	unsafe{
		for row in 0 .. 5 {
			for col in 0 .. 5 {
				assert_eq!(expected_table.unsafe_at((row,col)), table.table.unsafe_at((row,col)));
			}
		};
		for x in 0 .. 5 {
			for y in 0 .. 5 {
				assert_eq!(expected_table.unsafe_at((y,x)), table.get_sum((0,0), (x,y)));
			}
		}
	}
}

#[test]
#[should_panic]
fn bound_check_x() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	table.get_sum((0,0),(50,99));
}

#[test]
#[should_panic]
fn bound_check_y() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	table.get_sum((0,0),(49,100));
}

#[test]
#[should_panic]
fn point_order_check1() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(48,98)));
}

#[test]
#[should_panic]
fn point_order_check2() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(48,99)));
}

#[test]
#[should_panic]
fn point_order_check3() {
	let src: DMat<usize> = DMat::new_zeros(50,100);
	let table = src.calculate_summed_area_table();
	assert_eq!(0, table.get_sum((49,99),(49,98)));
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(step_by)]
#![feature(convert)]
#![feature(iter_arith)]
#![feature(vec_push_all)]

// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! # Rust-bio, a bioinformatics library for Rust.
//! This library provides implementations of many algorithms and data structures
//! that are useful for bioinformatics.
//! All provided implementations are rigorously tested via continuous
//! integration (https://travis-ci.org/rust-bio/rust-bio).
//! For installation instructions and a general overview, visit
//! https://github.com/rust-bio/rust-bio.
//!
//! Currently, rust-bio provides
//!
//! * most major pattern matching algorithms,
//! * a convenient alphabet implementation,
//! * pairwise alignment,
//! * suffix arrays,
//! * BWT and FM-Index,
//! * FMD-Index for finding supermaximal exact matches,
//! * a q-gram index,
//! * a rank/select data structure,
//! * FASTQ and FASTA and BED readers and writers,
//! * helper functions for combinatorics and dealing with log probabilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! use bio::data_structures::suffix_array::suffix_array;
//! use bio::data_structures::bwt::bwt;
//! use bio::data_structures::fmindex::FMIndex;
//!
//! let text = b"ACGGATGCTGGATCGGATCGCGCTAGCTA";
//! let pattern = b"ACCG";
//!
//! // Create an FM-Index for a given text.
//! let alphabet = alphabets::dna::iupac_alphabet();
//! let pos = suffix_array(text);
//! let bwt = bwt(text, &pos);
//! let fmindex = FMIndex::new(&bwt, 3, &alphabet);
//!
//! let interval = fmindex.backward_search(pattern.iter());
//! let positions = interval.occ(&pos);
//! ```
//!
//! Documentation and further examples for each module can be found in the module descriptions below.

extern crate test;
extern crate rustc_serialize;
extern crate csv;
extern crate num;
extern crate itertools;
extern crate bit_vec;
extern crate vec_map;
extern crate bit_set;

pub mod utils;
pub mod alphabets;
pub mod pattern_matching;
pub mod data_structures;
#[macro_use]
pub mod alignment;
pub mod io;
pub mod stats;
<commit_msg>remove #[macro_use]<commit_after>#![feature(test)]
#![feature(step_by)]
#![feature(convert)]
#![feature(iter_arith)]
#![feature(vec_push_all)]

// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! # Rust-bio, a bioinformatics library for Rust.
//! This library provides implementations of many algorithms and data structures
//! that are useful for bioinformatics.
//! All provided implementations are rigorously tested via continuous
//! integration (https://travis-ci.org/rust-bio/rust-bio).
//! For installation instructions and a general overview, visit
//! https://github.com/rust-bio/rust-bio.
//!
//! Currently, rust-bio provides
//!
//! * most major pattern matching algorithms,
//! * a convenient alphabet implementation,
//! * pairwise alignment,
//! * suffix arrays,
//! * BWT and FM-Index,
//! * FMD-Index for finding supermaximal exact matches,
//! * a q-gram index,
//! * a rank/select data structure,
//! * FASTQ and FASTA and BED readers and writers,
//! * helper functions for combinatorics and dealing with log probabilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! use bio::data_structures::suffix_array::suffix_array;
//! use bio::data_structures::bwt::bwt;
//! use bio::data_structures::fmindex::FMIndex;
//!
//! let text = b"ACGGATGCTGGATCGGATCGCGCTAGCTA";
//! let pattern = b"ACCG";
//!
//! // Create an FM-Index for a given text.
//! let alphabet = alphabets::dna::iupac_alphabet();
//! let pos = suffix_array(text);
//! let bwt = bwt(text, &pos);
//! let fmindex = FMIndex::new(&bwt, 3, &alphabet);
//!
//! let interval = fmindex.backward_search(pattern.iter());
//! let positions = interval.occ(&pos);
//! ```
//!
//! Documentation and further examples for each module can be found in the module descriptions below.

extern crate test;
extern crate rustc_serialize;
extern crate csv;
extern crate num;
extern crate itertools;
extern crate bit_vec;
extern crate vec_map;
extern crate bit_set;

pub mod utils;
pub mod alphabets;
pub mod pattern_matching;
pub mod data_structures;
pub mod alignment;
pub mod io;
pub mod stats;
<|endoftext|>