<commit_before>// Copyright (c) 2019 Chef Software Inc. and/or applicable contributors
//
// 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.

use std::fs::create_dir_all;
use std::fs::{File, read_to_string};
use std::io::{Write};
use std::path::Path;
use serde_json::{self, json, Value as Json};
use toml::Value;

use crate::common::templating::TemplateRenderer;
use crate::common::ui::{Status, UIWriter, UI};
use crate::error::Result;

pub fn start(
    ui: &mut UI,
    template_path: &Path,
    default_toml_path: &Path,
    user_toml_path: Option<&Path>,
    mock_data_path: Option<&Path>,
    print: bool,
    no_render_dir: bool,
    render_dir: &Path,
    quiet: bool,
) -> Result<()> {
    // Strip the file name out of our passed template
    let file_name = match Path::new(&template_path).file_name() {
        Some(name) => name.to_str().clone().unwrap(),
        None => panic!(format!("Something went wrong getting filename of {:?}", &template_path)),
    };

    if !(quiet) {
      ui.begin(format!("Rendering: {:?} into: {:?} as: {:?}", template_path, render_dir, file_name))?;
      ui.br()?;
    }

    // read our template from file
    let template = read_to_string(&template_path)?;

    // create a "data" json struct
    let mut data = json!({});

    if !(quiet) {
        // import default.toml values, convert to JSON
        ui.begin(format!("Importing default.toml: {:?}", &default_toml_path))?;
    }

    // we should always have a default.toml, would be nice to "autodiscover" based on package name,
    // for now assume we're working in the plan dir if --default-toml not passed
    let default_toml = read_to_string(&default_toml_path)?;

    // merge default into data struct
    merge(&mut data, toml_to_json(&default_toml));

    // import default.toml values, convert to JSON
    let user_toml = match user_toml_path {
        Some(path) => {
            if !(quiet) {
              // print helper message, maybe only print if '--verbose'? how?
              ui.begin(format!("Importing user.toml: {:?}", path))?;
            }
            read_to_string(path)?
        },
        None => String::new(),
    };
    // merge default into data struct
    merge(&mut data, toml_to_json(&user_toml));

    // read mock data if provided
    let mock_data = match mock_data_path {
        Some(path) => {
            if !(quiet) {
                // print helper message, maybe only print if '--verbose'? how?
                ui.begin(format!("Importing override file: {:?}", path))?;
            }
            read_to_string(path)?
        },
        // return an empty json block if '--mock-data' isn't defined.
        // this allows us to merge an empty JSON block
        None => "{}".to_string(),
    };
    // merge mock data into data
    merge(&mut data, serde_json::from_str(&mock_data).unwrap());

    // create a template renderer
    let mut renderer = TemplateRenderer::new();
    // register our template
    renderer
        .register_template_string(&template, &template)
        .expect("Could not register template content");
    // render our JSON override in our template.
    let rendered_template = renderer.render(&template, &data).ok().unwrap();

    if print {
        if !(quiet) {
          ui.br()?;
          ui.warn(format!("###======== Rendered template: {:?}", &template_path))?;
        }

        println!("{}", rendered_template);

        if !(quiet) {
          ui.warn(format!("========### End rendered template: {:?}", &template_path))?;
        }
    }

    // if not no render dir (aka "unless no_render_dir == true")
    if !(no_render_dir) {
      // Render our template file
      create_with_template(ui, &Path::new(render_dir).join(file_name), &rendered_template, quiet)?;
    }

    if !(quiet) {
      ui.br()?;
    }
    // not really sure this is correct...
    Ok(())
}

fn toml_to_json(cfg: &str) -> Json {
    let toml_value = cfg.parse::<Value>().expect("Error parsing TOML");
    let toml_string = serde_json::to_string(&toml_value).expect("Error encoding JSON");
    serde_json::from_str(&format!(r#"{{ "cfg": {} }}"#, &toml_string)).unwrap()
}

// merge two Json structs
fn merge(a: &mut Json, b: Json) {
    match (a, b) {
        // not sure I understand this...
        (a @ &mut Json::Object(_), Json::Object(b)) => {
            // not sure I understand why we unwrap this
            let a = a.as_object_mut().unwrap();
            // Iterate through key/values in Json object b,
            // merge with Json object b
            for (k, v) in b {
                merge(a.entry(k).or_insert(Json::Null), v);
            }
        }
        // or this...
        (a, b) => *a = b,
    }
}

// This is almost a dupe of the method in plan/init, except we don't care if the file exists and go
// ahead and overwite it.  I feel like maybe a different name would be good?
fn create_with_template(ui: &mut UI, location: &std::path::PathBuf, template: &str, quiet: bool) -> Result<()> {
    let path = Path::new(&location);
    if !(quiet) {
        ui.status(Status::Creating, format!("file: {:?}", location))?;
    }
    // If the directory doesn't exist we need to make it.
    if let Some(directory) = path.parent() {
        create_dir_all(directory)?;
    }
    // Write file to disk
    File::create(path).and_then(|mut file| file.write(template.as_bytes()))?;
    Ok(())
}
<commit_msg>remove unneeded comments<commit_after>// Copyright (c) 2019 Chef Software Inc. and/or applicable contributors
//
// 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.

use std::fs::create_dir_all;
use std::fs::{File, read_to_string};
use std::io::{Write};
use std::path::Path;
use serde_json::{self, json, Value as Json};
use toml::Value;

use crate::common::templating::TemplateRenderer;
use crate::common::ui::{Status, UIWriter, UI};
use crate::error::Result;

pub fn start(
    ui: &mut UI,
    template_path: &Path,
    default_toml_path: &Path,
    user_toml_path: Option<&Path>,
    mock_data_path: Option<&Path>,
    print: bool,
    no_render_dir: bool,
    render_dir: &Path,
    quiet: bool,
) -> Result<()> {
    // Strip the file name out of our passed template
    let file_name = match Path::new(&template_path).file_name() {
        Some(name) => name.to_str().clone().unwrap(),
        None => panic!(format!("Something went wrong getting filename of {:?}", &template_path)),
    };

    if !(quiet) {
      ui.begin(format!("Rendering: {:?} into: {:?} as: {:?}", template_path, render_dir, file_name))?;
      ui.br()?;
    }

    // read our template from file
    let template = read_to_string(&template_path)?;

    // create a "data" json struct
    let mut data = json!({});

    if !(quiet) {
        // import default.toml values, convert to JSON
        ui.begin(format!("Importing default.toml: {:?}", &default_toml_path))?;
    }

    // we should always have a default.toml, would be nice to "autodiscover" based on package name,
    // for now assume we're working in the plan dir if --default-toml not passed
    let default_toml = read_to_string(&default_toml_path)?;

    // merge default into data struct
    merge(&mut data, toml_to_json(&default_toml));

    // import default.toml values, convert to JSON
    let user_toml = match user_toml_path {
        Some(path) => {
            if !(quiet) {
              // print helper message, maybe only print if '--verbose'? how?
              ui.begin(format!("Importing user.toml: {:?}", path))?;
            }
            read_to_string(path)?
        },
        None => String::new(),
    };
    // merge default into data struct
    merge(&mut data, toml_to_json(&user_toml));

    // read mock data if provided
    let mock_data = match mock_data_path {
        Some(path) => {
            if !(quiet) {
                // print helper message, maybe only print if '--verbose'? how?
                ui.begin(format!("Importing override file: {:?}", path))?;
            }
            read_to_string(path)?
        },
        // return an empty json block if '--mock-data' isn't defined.
        // this allows us to merge an empty JSON block
        None => "{}".to_string(),
    };
    // merge mock data into data
    merge(&mut data, serde_json::from_str(&mock_data).unwrap());

    // create a template renderer
    let mut renderer = TemplateRenderer::new();
    // register our template
    renderer
        .register_template_string(&template, &template)
        .expect("Could not register template content");
    // render our JSON override in our template.
    let rendered_template = renderer.render(&template, &data).ok().unwrap();

    if print {
        if !(quiet) {
          ui.br()?;
          ui.warn(format!("###======== Rendered template: {:?}", &template_path))?;
        }

        println!("{}", rendered_template);

        if !(quiet) {
          ui.warn(format!("========### End rendered template: {:?}", &template_path))?;
        }
    }

    // if not no render dir (aka "unless no_render_dir == true")
    if !(no_render_dir) {
      // Render our template file
      create_with_template(ui, &Path::new(render_dir).join(file_name), &rendered_template, quiet)?;
    }

    if !(quiet) {
      ui.br()?;
    }
    Ok(())
}

fn toml_to_json(cfg: &str) -> Json {
    let toml_value = cfg.parse::<Value>().expect("Error parsing TOML");
    let toml_string = serde_json::to_string(&toml_value).expect("Error encoding JSON");
    serde_json::from_str(&format!(r#"{{ "cfg": {} }}"#, &toml_string)).unwrap()
}

// merge two Json structs
fn merge(a: &mut Json, b: Json) {
    match (a, b) {
        // not sure I understand this...
        (a @ &mut Json::Object(_), Json::Object(b)) => {
            // not sure I understand why we unwrap this
            let a = a.as_object_mut().unwrap();
            // Iterate through key/values in Json object b,
            // merge with Json object b
            for (k, v) in b {
                merge(a.entry(k).or_insert(Json::Null), v);
            }
        }
        // or this...
        (a, b) => *a = b,
    }
}

fn create_with_template(ui: &mut UI, location: &std::path::PathBuf, template: &str, quiet: bool) -> Result<()> {
    let path = Path::new(&location);
    if !(quiet) {
        ui.status(Status::Creating, format!("file: {:?}", location))?;
    }
    // If the directory doesn't exist we need to make it.
    if let Some(directory) = path.parent() {
        create_dir_all(directory)?;
    }
    // Write file to disk
    File::create(path).and_then(|mut file| file.write(template.as_bytes()))?;
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{constants, error::Error, SecureBackends};
use libra_crypto::{hash::CryptoHash, x25519, ValidCryptoMaterial};
use libra_network_address::{NetworkAddress, RawNetworkAddress};
use libra_secure_storage::{Storage, Value};
use libra_secure_time::{RealTimeService, TimeService};
use libra_types::{
    account_address::AccountAddress,
    transaction::{RawTransaction, SignedTransaction, Transaction},
};
use std::{
    convert::{TryFrom, TryInto},
    time::Duration,
};
use structopt::StructOpt;

// TODO(davidiw) add operator_address, since that will eventually be the identity producing this.
#[derive(Debug, StructOpt)]
pub struct ValidatorConfig {
    #[structopt(long)]
    owner_address: AccountAddress,
    #[structopt(long)]
    validator_address: NetworkAddress,
    #[structopt(long)]
    fullnode_address: NetworkAddress,
    #[structopt(flatten)]
    backends: SecureBackends,
}

impl ValidatorConfig {
    pub fn execute(self) -> Result<Transaction, Error> {
        let mut local: Box<dyn Storage> = self.backends.local.try_into()?;
        if !local.available() {
            return Err(Error::LocalStorageUnavailable);
        }

        let consensus_key = local
            .get_public_key(constants::CONSENSUS_KEY)
            .map_err(|e| Error::LocalStorageReadError(e.to_string()))?
            .public_key;
        let fullnode_network_key = local
            .get_public_key(constants::FULLNODE_NETWORK_KEY)
            .map_err(|e| Error::LocalStorageReadError(e.to_string()))?
            .public_key;
        let validator_network_key = local
            .get_public_key(constants::VALIDATOR_NETWORK_KEY)
            .map_err(|e| Error::LocalStorageReadError(e.to_string()))?
            .public_key;

        let fullnode_address = RawNetworkAddress::try_from(&self.fullnode_address)
            .expect("Unable to serialize fullnode network address from config");
        let validator_address = RawNetworkAddress::try_from(&self.validator_address)
            .expect("Unable to serialize validator network address from config");

        let fullnode_network_key = fullnode_network_key.to_bytes();
        let fullnode_network_key: x25519::PublicKey = fullnode_network_key
            .as_ref()
            .try_into()
            .expect("Unable to decode x25519 from fullnode_network_key");

        let validator_network_key = validator_network_key.to_bytes();
        let validator_network_key: x25519::PublicKey = validator_network_key
            .as_ref()
            .try_into()
            .expect("Unable to decode x25519 from validator_network_key");

        let owner_key = local
            .get_public_key(constants::OWNER_KEY)
            .map_err(|e| Error::LocalStorageReadError(e.to_string()))?
            .public_key;

        // TODO(davidiw): The signing key, parameter 2, will be deleted soon, so this is a
        // temporary hack to reduce over-engineering.
        let script = transaction_builder::encode_register_validator_script(
            consensus_key.to_bytes().to_vec(),
            owner_key.to_bytes().to_vec(),
            validator_network_key.to_bytes(),
            validator_address.into(),
            fullnode_network_key.to_bytes(),
            fullnode_address.into(),
        );

        let sender = self.owner_address;
        // TODO(davidiw): In genesis this is irrelevant -- afterward we need to obtain the
        // current sequence number by querying the blockchain.
        let sequence_number = 0;
        let expiration_time = RealTimeService::new().now() + constants::TXN_EXPIRATION_SECS;
        let raw_transaction = RawTransaction::new_script(
            sender,
            sequence_number,
            script,
            constants::MAX_GAS_AMOUNT,
            constants::GAS_UNIT_PRICE,
            Duration::from_secs(expiration_time),
        );
        let signature = local
            .sign_message(constants::OWNER_KEY, &raw_transaction.hash())
            .map_err(|e| Error::LocalStorageSigningError(e.to_string()))?;
        let signed_txn = SignedTransaction::new(raw_transaction, owner_key, signature);
        let txn = Transaction::UserTransaction(signed_txn);

        if let Some(remote) = self.backends.remote {
            let mut remote: Box<dyn Storage> = remote.try_into()?;
            if !remote.available() {
                return Err(Error::RemoteStorageUnavailable);
            }

            let txn = Value::Transaction(txn.clone());
            remote
                .create_with_default_policy(constants::VALIDATOR_CONFIG, txn)
                .map_err(|e| Error::RemoteStorageWriteError(e.to_string()))?;
        }

        Ok(txn)
    }
}
<commit_msg>[managment] improve readability of validator_config.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{constants, error::Error, SecureBackends};
use libra_crypto::{ed25519::Ed25519PublicKey, hash::CryptoHash, x25519, ValidCryptoMaterial};
use libra_network_address::{NetworkAddress, RawNetworkAddress};
use libra_secure_storage::{Storage, Value};
use libra_secure_time::{RealTimeService, TimeService};
use libra_types::{
    account_address::AccountAddress,
    transaction::{RawTransaction, SignedTransaction, Transaction},
};
use std::{
    convert::{TryFrom, TryInto},
    time::Duration,
};
use structopt::StructOpt;

// TODO(davidiw) add operator_address, since that will eventually be the identity producing this.
#[derive(Debug, StructOpt)]
pub struct ValidatorConfig {
    #[structopt(long)]
    owner_address: AccountAddress,
    #[structopt(long)]
    validator_address: NetworkAddress,
    #[structopt(long)]
    fullnode_address: NetworkAddress,
    #[structopt(flatten)]
    backends: SecureBackends,
}

impl ValidatorConfig {
    pub fn execute(self) -> Result<Transaction, Error> {
        let mut local: Box<dyn Storage> = self.backends.local.try_into()?;
        if !local.available() {
            return Err(Error::LocalStorageUnavailable);
        }

        // Step 1) Retrieve keys from local storage
        let consensus_key = ed25519_from_storage(constants::CONSENSUS_KEY, local.as_mut())?;
        let fullnode_network_key =
            x25519_from_storage(constants::FULLNODE_NETWORK_KEY, local.as_mut())?;
        let validator_network_key =
            x25519_from_storage(constants::VALIDATOR_NETWORK_KEY, local.as_mut())?;
        let owner_key = ed25519_from_storage(constants::OWNER_KEY, local.as_mut())?;

        let fullnode_address = RawNetworkAddress::try_from(&self.fullnode_address)
            .map_err(|e| Error::UnexpectedError(format!("(fullnode_address) {}", e)))?;
        let validator_address = RawNetworkAddress::try_from(&self.validator_address)
            .map_err(|e| Error::UnexpectedError(format!("(validator_address) {}", e)))?;

        // Step 2) Generate transaction

        // TODO(davidiw): The signing key, parameter 2, will be deleted soon, so this is a
        // temporary hack to reduce over-engineering.
        let script = transaction_builder::encode_register_validator_script(
            consensus_key.to_bytes().to_vec(),
            owner_key.to_bytes().to_vec(),
            validator_network_key.to_bytes(),
            validator_address.into(),
            fullnode_network_key.to_bytes(),
            fullnode_address.into(),
        );

        let sender = self.owner_address;
        // TODO(davidiw): In genesis this is irrelevant -- afterward we need to obtain the
        // current sequence number by querying the blockchain.
        let sequence_number = 0;
        let expiration_time = RealTimeService::new().now() + constants::TXN_EXPIRATION_SECS;
        let raw_transaction = RawTransaction::new_script(
            sender,
            sequence_number,
            script,
            constants::MAX_GAS_AMOUNT,
            constants::GAS_UNIT_PRICE,
            Duration::from_secs(expiration_time),
        );
        let signature = local
            .sign_message(constants::OWNER_KEY, &raw_transaction.hash())
            .map_err(|e| Error::LocalStorageSigningError(e.to_string()))?;
        let signed_txn = SignedTransaction::new(raw_transaction, owner_key, signature);
        let txn = Transaction::UserTransaction(signed_txn);

        // Step 3) Submit to remote storage

        if let Some(remote) = self.backends.remote {
            let mut remote: Box<dyn Storage> = remote.try_into()?;
            if !remote.available() {
                return Err(Error::RemoteStorageUnavailable);
            }

            let txn = Value::Transaction(txn.clone());
            remote
                .create_with_default_policy(constants::VALIDATOR_CONFIG, txn)
                .map_err(|e| Error::RemoteStorageWriteError(e.to_string()))?;
        }

        Ok(txn)
    }
}

fn ed25519_from_storage(
    key_name: &str,
    storage: &mut dyn Storage,
) -> Result<Ed25519PublicKey, Error> {
    Ok(storage
        .get_public_key(key_name)
        .map_err(|e| Error::LocalStorageReadError(e.to_string()))?
        .public_key)
}

fn x25519_from_storage(
    key_name: &str,
    storage: &mut dyn Storage,
) -> Result<x25519::PublicKey, Error> {
    let edkey = ed25519_from_storage(key_name, storage)?.to_bytes();
    edkey
        .as_ref()
        .try_into()
        .map_err(|e| Error::UnexpectedError(format!("({}) {}", key_name, e)))
}
<|endoftext|>


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

//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.

use rand::{Rng, SeedableRng};
use default::Default;

/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024;

/// A wrapper around any RNG which reseeds the underlying RNG after it
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
    priv rng: R,
    priv generation_threshold: uint,
    priv bytes_generated: uint,
    /// Controls the behaviour when reseeding the RNG.
    reseeder: Rsdr
}

impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
    /// * `reseeder`: the reseeding object to use.
    pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        ReseedingRng {
            rng: rng,
            generation_threshold: generation_threshold,
            bytes_generated: 0,
            reseeder: reseeder
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    pub fn reseed_if_necessary(&mut self) {
        if self.bytes_generated >= self.generation_threshold {
            self.reseeder.reseed(&mut self.rng);
            self.bytes_generated = 0;
        }
    }
}

impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        self.reseed_if_necessary();
        self.bytes_generated += 4;
        self.rng.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.reseed_if_necessary();
        self.bytes_generated += 8;
        self.rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len();
        self.fill_bytes(dest)
    }
}

impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
     SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
    fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
        self.rng.reseed(seed);
        self.reseeder = rsdr;
        self.bytes_generated = 0;
    }
    /// Create a new `ReseedingRng` from the given reseeder and
    /// seed. This uses a default value for `generation_threshold`.
    fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
        ReseedingRng {
            rng: SeedableRng::from_seed(seed),
            generation_threshold: DEFAULT_GENERATION_THRESHOLD,
            bytes_generated: 0,
            reseeder: rsdr
        }
    }
}

/// Something that can be used to reseed an RNG via `ReseedingRng`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::{Rng, SeedableRng};
/// use std::rand::reseeding::{Reseeder, ReseedingRng};
///
/// struct TickTockReseeder { tick: bool }
/// impl Reseeder<rand::StdRng> for TickTockReseeder {
///     fn reseed(&mut self, rng: &mut rand::StdRng) {
///         let val = if self.tick {0} else {1};
///         rng.reseed(&[val]);
///         self.tick = !self.tick;
///     }
/// }
/// fn main() {
///     let rsdr = TickTockReseeder { tick: true };
///     let mut rng = ReseedingRng::new(rand::StdRng::new(), 10, rsdr);
///
///     // this will repeat, because it gets reseeded very regularly.
///     println(rng.gen_ascii_str(100));
/// }
///
/// ```
pub trait Reseeder<R> {
    /// Reseed the given RNG.
    fn reseed(&mut self, rng: &mut R);
}

/// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;

impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
    fn reseed(&mut self, rng: &mut R) {
        *rng = Default::default();
    }
}
impl Default for ReseedWithDefault {
    fn default() -> ReseedWithDefault { ReseedWithDefault }
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::{SeedableRng, Rng};
    use default::Default;
    use iter::range;
    use option::{None, Some};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
    }
    impl Default for Counter {
        fn default() -> Counter {
            Counter { i: 0 }
        }
    }
    impl SeedableRng<u32> for Counter {
        fn reseed(&mut self, seed: u32) {
            self.i = seed;
        }
        fn from_seed(seed: u32) -> Counter {
            Counter { i: seed }
        }
    }
    type MyRng = ReseedingRng<Counter, ReseedWithDefault>;

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);

        let mut i = 0;
        for _ in range(0, 1000) {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }

    #[test]
    fn test_rng_seeded() {
        let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
    }

    #[test]
    fn test_rng_reseed() {
        let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
        let string1 = r.gen_ascii_str(100);

        r.reseed((ReseedWithDefault, 3));

        let string2 = r.gen_ascii_str(100);
        assert_eq!(string1, string2);
    }
}
<commit_msg>Fix infinite recursion in `fill_bytes()`<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.

use rand::{Rng, SeedableRng};
use default::Default;

/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024;

/// A wrapper around any RNG which reseeds the underlying RNG after it
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
    priv rng: R,
    priv generation_threshold: uint,
    priv bytes_generated: uint,
    /// Controls the behaviour when reseeding the RNG.
    reseeder: Rsdr
}

impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
    /// * `reseeder`: the reseeding object to use.
    pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        ReseedingRng {
            rng: rng,
            generation_threshold: generation_threshold,
            bytes_generated: 0,
            reseeder: reseeder
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    pub fn reseed_if_necessary(&mut self) {
        if self.bytes_generated >= self.generation_threshold {
            self.reseeder.reseed(&mut self.rng);
            self.bytes_generated = 0;
        }
    }
}

impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        self.reseed_if_necessary();
        self.bytes_generated += 4;
        self.rng.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.reseed_if_necessary();
        self.bytes_generated += 8;
        self.rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len();
        self.rng.fill_bytes(dest)
    }
}

impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
     SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
    fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
        self.rng.reseed(seed);
        self.reseeder = rsdr;
        self.bytes_generated = 0;
    }
    /// Create a new `ReseedingRng` from the given reseeder and
    /// seed. This uses a default value for `generation_threshold`.
    fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
        ReseedingRng {
            rng: SeedableRng::from_seed(seed),
            generation_threshold: DEFAULT_GENERATION_THRESHOLD,
            bytes_generated: 0,
            reseeder: rsdr
        }
    }
}

/// Something that can be used to reseed an RNG via `ReseedingRng`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::{Rng, SeedableRng};
/// use std::rand::reseeding::{Reseeder, ReseedingRng};
///
/// struct TickTockReseeder { tick: bool }
/// impl Reseeder<rand::StdRng> for TickTockReseeder {
///     fn reseed(&mut self, rng: &mut rand::StdRng) {
///         let val = if self.tick {0} else {1};
///         rng.reseed(&[val]);
///         self.tick = !self.tick;
///     }
/// }
/// fn main() {
///     let rsdr = TickTockReseeder { tick: true };
///     let mut rng = ReseedingRng::new(rand::StdRng::new(), 10, rsdr);
///
///     // this will repeat, because it gets reseeded very regularly.
///     println(rng.gen_ascii_str(100));
/// }
///
/// ```
pub trait Reseeder<R> {
    /// Reseed the given RNG.
    fn reseed(&mut self, rng: &mut R);
}

/// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;

impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
    fn reseed(&mut self, rng: &mut R) {
        *rng = Default::default();
    }
}
impl Default for ReseedWithDefault {
    fn default() -> ReseedWithDefault { ReseedWithDefault }
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::{SeedableRng, Rng};
    use default::Default;
    use iter::range;
    use option::{None, Some};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
    }
    impl Default for Counter {
        fn default() -> Counter {
            Counter { i: 0 }
        }
    }
    impl SeedableRng<u32> for Counter {
        fn reseed(&mut self, seed: u32) {
            self.i = seed;
        }
        fn from_seed(seed: u32) -> Counter {
            Counter { i: seed }
        }
    }
    type MyRng = ReseedingRng<Counter, ReseedWithDefault>;

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);

        let mut i = 0;
        for _ in range(0, 1000) {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }

    #[test]
    fn test_rng_seeded() {
        let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
        assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
    }

    #[test]
    fn test_rng_reseed() {
        let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
        let string1 = r.gen_ascii_str(100);

        r.reseed((ReseedWithDefault, 3));

        let string2 = r.gen_ascii_str(100);
        assert_eq!(string1, string2);
    }

    static fill_bytes_v_len: uint = 13579;
    #[test]
    fn test_rng_fill_bytes() {
        use rand::task_rng;
        let mut v = ~[0u8, .. fill_bytes_v_len];
        task_rng().fill_bytes(v);

        // Sanity test: if we've gotten here, `fill_bytes` has not infinitely
        // recursed.
        assert_eq!(v.len(), fill_bytes_v_len);

        // To test that `fill_bytes` actually did something, check that the
        // average of `v` is not 0.
        let mut sum = 0.0;
        for &x in v.iter() {
            sum += x as f64;
        }
        assert!(sum / v.len() as f64 != 0.0);
    }
}
<|endoftext|>


<commit_before> #[feature(struct_variant)];
extern mod extra;
use extra::getopts;
use std::rand;
use std::fmt;

fn randrange(min : uint, max : uint) -> uint {
    min + rand::random::<uint>() % (max - min)
}

#[deriving(Eq)]
struct ServerID(uint);

#[deriving(Eq, Ord)]
struct Term(uint);

#[deriving(Ord)]
struct Index(uint);

#[deriving(Ord)]
struct Time(uint);

struct Environment {
    clock: Time,
    network: ~[Message],
}

impl Environment {
    fn new() -> Environment {
        Environment {
            clock: Time(0),
            network: ~[],
        }
    }
    fn make_time(&self, min: uint, max: uint) -> Time {
        Time(*self.clock + randrange(min, max))
    }
    fn multicast(&mut self, from: ServerID, to: &[ServerID], body: &MessageBody) {
        for peer in to.iter() {
            self.network.push(Message {
                from: from,
                to: *peer,
                body: *body,
            });
        }
    }
    fn reply(&mut self, request: &Message, responseBody: &MessageBody) {
        self.network.push(Message {
            from: request.to,
            to: request.from,
            body: *responseBody,
        });
    }
    fn popMessage(&mut self) -> Option<Message> {
        return self.network.pop_opt();
    }
}

struct Message {
    from: ServerID,
    to: ServerID,
    body: MessageBody,
}

enum MessageBody {
    RequestVoteRequest {
        term: Term,
        lastLogTerm: Term,
        lastLogIndex: Index,
    },
    RequestVoteResponse {
        term: Term,
        granted: bool,
    },
    Heartbeat {
        term: Term,
    },
}

impl fmt::Default for Message {
    fn fmt(msg: &Message, f: &mut fmt::Formatter) {
        write!(f.buf, "{} to {}: {}",
               *msg.from,
               *msg.to,
               msg.body);
    }
}

impl fmt::Default for MessageBody {
    fn fmt(b: &MessageBody, f: &mut fmt::Formatter) {
        match *b {
            RequestVoteRequest{term, lastLogTerm, lastLogIndex} =>
                write!(f.buf, "RequestVoteRequest({}, {}, {})",
                       term, lastLogTerm, lastLogIndex),
            RequestVoteResponse{term, granted} =>
                write!(f.buf, "RequestVoteResponse({}, {})",
                       term, granted),
            Heartbeat{term} =>
                write!(f.buf, "Heartbeat({})",
                       term),
        }
    }
}

enum ServerState {
    Follower  { timer: Time },
    Candidate { timer: Time, votes: uint },
    Leader,
}

impl fmt::Default for Time {
    fn fmt(time: &Time, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **time)
    }
}

impl fmt::Default for Term {
    fn fmt(term: &Term, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **term)
    }
}

impl fmt::Default for Index {
    fn fmt(index: &Index, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **index)
    }
}

impl fmt::Default for ServerState {
    fn fmt(state: &ServerState, f: &mut fmt::Formatter) {
        match *state {
            Follower{timer} => write!(f.buf, "Follower({})", timer),
            Candidate{timer, votes} => write!(f.buf, "Candidate({}, {})", timer, votes),
            Leader => write!(f.buf, "Leader"),
        }
    }
}

struct LogEntry {
    term: Term,
    // command: ~str,
}

struct Log(~[LogEntry]);

impl Log {
    fn new() -> Log {
        Log(~[])
    }
}

struct Server {
    id: ServerID,
    peers: ~[ServerID],
    term: Term,
    state: ServerState,
    vote: Option<ServerID>,
    log: Log,
}

impl Server {
    fn new(id : ServerID, peers: ~[ServerID], env: &Environment) -> Server {
        Server {
            id: id,
            peers: peers,
            term: Term(0),
            state: Follower { timer: env.make_time(150, 300) },
            log: Log::new(),
            vote: None,
        }
    }
    /*
    fn reset_timer(&mut self) {
        self.set_timer(Time(*self.env.clock + randrange(150, 300)));
    }
    fn set_timer(&mut self, time: Time) {
        match self.state {
            Follower  {timer : ref mut timer, _} |
            Candidate {timer : ref mut timer, _} =>
                { *timer = time },
            Leader => {},
        }
    }
    */
    fn tick(&mut self, env: &mut Environment) {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} => {
                if timer <= env.clock {
                    self.term = Term(*self.term + 1);
                    self.vote = None;
                    self.state = Candidate {
                        timer: env.make_time(150, 300),
                        votes: 1,
                    };
                    env.multicast(self.id, self.peers, &RequestVoteRequest {
                        term: self.term,
                        lastLogTerm: Term(0),
                        lastLogIndex: Index(0),
                    });
                }
                self.try_become_leader(env);
            },
            Leader => {},
        }
    }
    fn step_down(&mut self, env: &Environment, term: Term) {
        self.term = term;
        self.vote = None;
        self.state = Follower {
            timer: env.make_time(150, 300),
        };
    }

    fn try_become_leader(&mut self, env: &mut Environment) {
        match self.state {
            Follower {_} => {},
            Candidate {votes, _} => {
                if votes > (self.peers.len() + 1) / 2 {
                    self.state = Leader;
                    env.multicast(self.id, self.peers, &Heartbeat {
                        term: self.term,
                    });
                }
            },
            Leader => {},
        }
    }
    fn handle(&mut self, env: &mut Environment, msg: &Message) {
        match msg.body {
            RequestVoteRequest {term, _} => {
                let reply = |granted| {
                    env.reply(msg, &RequestVoteResponse {
                        term: self.term,
                        granted: granted,
                    });
                };
                if term < self.term {
                    reply(false);
                } else {
                    if term > self.term {
                        self.step_down(env, term);
                    }
                    match self.vote {
                        None => {
                            self.vote = Some(msg.from);
                            reply(true);
                        },
                        Some(c) => {
                            reply(c == msg.from);
                        },
                    }
                }
            },
            RequestVoteResponse {term, granted, _} => {
                if term == self.term && granted {
                    match self.state {
                        Follower {_} => {},
                        Candidate {votes: ref mut votes, _} => {
                            *votes += 1;
                        },
                        Leader => {},
                    }
                    self.try_become_leader(env)
                } else if term > self.term {
                    self.step_down(env, term);
                }
            },
            Heartbeat {term} => {
                if term == self.term {
                    self.state = Follower {
                        timer: env.make_time(150, 300),
                    };
                } else if term > self.term {
                    self.step_down(env, term);
                }
            },
        }
    }

    /*
    fn next_event_time(&self) -> Time {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} =>
                timer,
            Leader => Time(!0)
        }
    }
    */
}

impl ToStr for Server {
    fn to_str(&self) -> ~str {
        format!("Server {}: {}", *self.id, self.state)
    }
}

struct Servers(~[Server]);

impl Servers {
    fn new(env: &Environment, num_servers: uint) -> Servers {
        let mut servers = ~[];
        for i in range(0, num_servers) {
            let mut peers = ~[];
            for j in range(0, num_servers) {
                if i != j {
                    peers.push(ServerID(j + 1));
                }
            }
            let s = Server::new(ServerID(i + 1), peers, env);
            servers.push(s);
        }
        return Servers(servers);
    }
}

fn main() {
    let args = std::os::args();
    let opts = [
        getopts::optflag("h"),
        getopts::optflag("help"),
        getopts::optopt("servers"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m },
        Err(f) => { fail!(f.to_err_msg()) },
    };
    let usage = || {
        println!("Usage: {} [options]", args[0]);
        println("-h, --help   Print this help message");
        println("--servers=N  Simulate cluster with N servers");
    };
    if matches.opt_present("h") || matches.opt_present("help") {
        usage();
        return;
    }
    if !matches.free.is_empty() {
        usage();
        fail!(format!("Extra arguments: {}", matches.free.len()));
    }
    let num_servers : uint = match matches.opt_str("servers") {
        Some(s) => { match std::from_str::from_str(s) {
            Some(i) => { i },
            None => {
                usage();
                fail!(format!("Couldn't parse number of servers from '{}'", s));
            },
        }},
        None => { 5 },
    };
    let env = &mut Environment::new();
    let mut servers = Servers::new(env, num_servers);
    loop {
        env.clock = Time(*env.clock + 1);
        for server in servers.mut_iter() {
            server.tick(env);
        }
        match env.popMessage() {
            None => {},
            Some(msg) => {
                servers[*msg.to - 1].handle(env, &msg);
            },
        }
        for server in servers.iter() {
            println(server.to_str());
        }
        for message in env.network.iter() {
            println!("{}", *message);
        }
        println("");
    }
}

<commit_msg>Schedule delivery times<commit_after> #[feature(struct_variant)];
extern mod extra;
use extra::getopts;
use std::rand;
use std::fmt;

fn randrange(min : uint, max : uint) -> uint {
    min + rand::random::<uint>() % (max - min)
}

#[deriving(Eq)]
struct ServerID(uint);

#[deriving(Eq, Ord)]
struct Term(uint);

#[deriving(Ord)]
struct Index(uint);

#[deriving(Ord)]
struct Time(uint);

struct Environment {
    clock: Time,
    network: ~[~Message],
}

impl Environment {
    fn new() -> Environment {
        Environment {
            clock: Time(0),
            network: ~[],
        }
    }
    fn make_time(&self, min: uint, max: uint) -> Time {
        Time(*self.clock + randrange(min, max))
    }
    fn make_network_latency(&self, from: ServerID, to: ServerID) -> Time {
        Time(*self.clock + randrange(2, 5))
    }
    fn multicast(&mut self, from: ServerID, to: &[ServerID], body: &MessageBody) {
        for peer in to.iter() {
            let m = ~Message {
                from: from,
                to: *peer,
                deliver: self.make_network_latency(from, *peer),
                body: *body,
            };
            self.network.push(m);
        }
    }
    fn reply(&mut self, request: &Message, response_body: &MessageBody) {
        let m = ~Message {
            from: request.to,
            to: request.from,
            deliver: self.make_network_latency(request.to, request.from),
            body: *response_body,
        };
        self.network.push(m);
    }
    fn pop_ready_messages(&mut self) -> ~[~Message] {
        let mut all = ~[];
        std::util::swap(&mut all, &mut self.network);
        let (ready, notready) = all.partition(|msg| msg.deliver <= self.clock);
        self.network = notready;
        return ready;
    }
}

struct Message {
    from: ServerID,
    to: ServerID,
    deliver: Time,
    body: MessageBody,
}

enum MessageBody {
    RequestVoteRequest {
        term: Term,
        lastLogTerm: Term,
        lastLogIndex: Index,
    },
    RequestVoteResponse {
        term: Term,
        granted: bool,
    },
    Heartbeat {
        term: Term,
    },
}

impl fmt::Default for Message {
    fn fmt(msg: &Message, f: &mut fmt::Formatter) {
        write!(f.buf, "{} to {}: {}",
               *msg.from,
               *msg.to,
               msg.body);
    }
}

impl fmt::Default for MessageBody {
    fn fmt(b: &MessageBody, f: &mut fmt::Formatter) {
        match *b {
            RequestVoteRequest{term, lastLogTerm, lastLogIndex} =>
                write!(f.buf, "RequestVoteRequest({}, {}, {})",
                       term, lastLogTerm, lastLogIndex),
            RequestVoteResponse{term, granted} =>
                write!(f.buf, "RequestVoteResponse({}, {})",
                       term, granted),
            Heartbeat{term} =>
                write!(f.buf, "Heartbeat({})",
                       term),
        }
    }
}

enum ServerState {
    Follower  { timer: Time },
    Candidate { timer: Time, votes: uint },
    Leader,
}

impl fmt::Default for Time {
    fn fmt(time: &Time, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **time)
    }
}

impl fmt::Default for Term {
    fn fmt(term: &Term, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **term)
    }
}

impl fmt::Default for Index {
    fn fmt(index: &Index, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **index)
    }
}

impl fmt::Default for ServerState {
    fn fmt(state: &ServerState, f: &mut fmt::Formatter) {
        match *state {
            Follower{timer} => write!(f.buf, "Follower({})", timer),
            Candidate{timer, votes} => write!(f.buf, "Candidate({}, {})", timer, votes),
            Leader => write!(f.buf, "Leader"),
        }
    }
}

struct LogEntry {
    term: Term,
    // command: ~str,
}

struct Log(~[LogEntry]);

impl Log {
    fn new() -> Log {
        Log(~[])
    }
}

struct Server {
    id: ServerID,
    peers: ~[ServerID],
    term: Term,
    state: ServerState,
    vote: Option<ServerID>,
    log: Log,
}

impl Server {
    fn new(id : ServerID, peers: ~[ServerID], env: &Environment) -> Server {
        Server {
            id: id,
            peers: peers,
            term: Term(0),
            state: Follower { timer: env.make_time(150, 300) },
            log: Log::new(),
            vote: None,
        }
    }
    /*
    fn reset_timer(&mut self) {
        self.set_timer(Time(*self.env.clock + randrange(150, 300)));
    }
    fn set_timer(&mut self, time: Time) {
        match self.state {
            Follower  {timer : ref mut timer, _} |
            Candidate {timer : ref mut timer, _} =>
                { *timer = time },
            Leader => {},
        }
    }
    */
    fn tick(&mut self, env: &mut Environment) {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} => {
                if timer <= env.clock {
                    self.term = Term(*self.term + 1);
                    self.vote = None;
                    self.state = Candidate {
                        timer: env.make_time(150, 300),
                        votes: 1,
                    };
                    env.multicast(self.id, self.peers, &RequestVoteRequest {
                        term: self.term,
                        lastLogTerm: Term(0),
                        lastLogIndex: Index(0),
                    });
                }
                self.try_become_leader(env);
            },
            Leader => {},
        }
    }
    fn step_down(&mut self, env: &Environment, term: Term) {
        self.term = term;
        self.vote = None;
        self.state = Follower {
            timer: env.make_time(150, 300),
        };
    }

    fn try_become_leader(&mut self, env: &mut Environment) {
        match self.state {
            Follower {_} => {},
            Candidate {votes, _} => {
                if votes > (self.peers.len() + 1) / 2 {
                    self.state = Leader;
                    env.multicast(self.id, self.peers, &Heartbeat {
                        term: self.term,
                    });
                }
            },
            Leader => {},
        }
    }
    fn handle(&mut self, env: &mut Environment, msg: &Message) {
        match msg.body {
            RequestVoteRequest {term, _} => {
                let reply = |granted| {
                    env.reply(msg, &RequestVoteResponse {
                        term: self.term,
                        granted: granted,
                    });
                };
                if term < self.term {
                    reply(false);
                } else {
                    if term > self.term {
                        self.step_down(env, term);
                    }
                    match self.vote {
                        None => {
                            self.vote = Some(msg.from);
                            reply(true);
                        },
                        Some(c) => {
                            reply(c == msg.from);
                        },
                    }
                }
            },
            RequestVoteResponse {term, granted, _} => {
                if term == self.term && granted {
                    match self.state {
                        Follower {_} => {},
                        Candidate {votes: ref mut votes, _} => {
                            *votes += 1;
                        },
                        Leader => {},
                    }
                    self.try_become_leader(env)
                } else if term > self.term {
                    self.step_down(env, term);
                }
            },
            Heartbeat {term} => {
                if term == self.term {
                    self.state = Follower {
                        timer: env.make_time(150, 300),
                    };
                } else if term > self.term {
                    self.step_down(env, term);
                }
            },
        }
    }

    /*
    fn next_event_time(&self) -> Time {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} =>
                timer,
            Leader => Time(!0)
        }
    }
    */
}

impl ToStr for Server {
    fn to_str(&self) -> ~str {
        format!("Server {}: {}", *self.id, self.state)
    }
}

struct Servers(~[Server]);

impl Servers {
    fn new(env: &Environment, num_servers: uint) -> Servers {
        let mut servers = ~[];
        for i in range(0, num_servers) {
            let mut peers = ~[];
            for j in range(0, num_servers) {
                if i != j {
                    peers.push(ServerID(j + 1));
                }
            }
            let s = Server::new(ServerID(i + 1), peers, env);
            servers.push(s);
        }
        return Servers(servers);
    }

    fn deliver(&mut self, env: &mut Environment, msg: &Message) {
        self[*msg.to - 1].handle(env, msg);
    }
}

fn main() {
    let args = std::os::args();
    let opts = [
        getopts::optflag("h"),
        getopts::optflag("help"),
        getopts::optopt("servers"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m },
        Err(f) => { fail!(f.to_err_msg()) },
    };
    let usage = || {
        println!("Usage: {} [options]", args[0]);
        println("-h, --help   Print this help message");
        println("--servers=N  Simulate cluster with N servers");
    };
    if matches.opt_present("h") || matches.opt_present("help") {
        usage();
        return;
    }
    if !matches.free.is_empty() {
        usage();
        fail!(format!("Extra arguments: {}", matches.free.len()));
    }
    let num_servers : uint = match matches.opt_str("servers") {
        Some(s) => { match std::from_str::from_str(s) {
            Some(i) => { i },
            None => {
                usage();
                fail!(format!("Couldn't parse number of servers from '{}'", s));
            },
        }},
        None => { 5 },
    };
    let env = &mut Environment::new();
    let mut servers = Servers::new(env, num_servers);
    loop {
        env.clock = Time(*env.clock + 1);
        for server in servers.mut_iter() {
            server.tick(env);
        }
        for msg in env.pop_ready_messages().move_iter() {
            servers.deliver(env, msg);
        }
        for server in servers.iter() {
        //    println(server.to_str());
        }
        for message in env.network.iter() {
            println!("{}", **message);
        }
        println("");
    }
}

<|endoftext|>


<commit_before>use regex::Regex;
use std::collections::HashMap;
use std::str::{FromStr, Lines};

use super::graph::{Graph, Node};
use super::weight::Weight;

// Parses "TSPLIB" files from sources like
//
// http://www.math.uwaterloo.ca/tsp/world/dj38.tsp
//
// The format looks roughly like this, at least for EUC_2D cases:
//
// NAME: dj38
// COMMENT : 38 locations in Djibouti
// COMMENT : Derived from National Imagery and Mapping Agency data
// COMMENT : This file is a corrected version of dj89, where duplications
// COMMENT:  have been removed.  Thanks to Jay Muthuswamy and others for
// COMMENT:  requesting data sets without duplications.
// TYPE: TSP
// DIMENSION: 38
// EDGE_WEIGHT_TYPE: EUC_2D
// NODE_COORD_SECTION
// 1 11003.611100 42102.500000

lazy_static! {
    static ref HEADER: Regex = Regex::new(r"([A-Z_]+)\s*:(.*)").unwrap();
}

lazy_static! {
    static ref COORD: Regex = Regex::new(r"([0-9]+) ([0-9.]+) ([0-9.]+)").unwrap();
}

pub fn parse_tsp_data(text: &str) -> Result<Graph, String> {
    let mut data = Data::new(text);
    let mut num_nodes = None;

    while let Some(header) = parse_tsp_header(&mut data) {
        match header.name {
            "NAME" => {}
            "COMMENT" => {}
            "TYPE" => {
                if header.value != "TSP" {
                    return Err(format!(
                        "line {}: expected \"TSP\" for TYPE, not {:?}",
                        header.line, header.value
                    ));
                }
            }
            "DIMENSION" => match usize::from_str(header.value) {
                Ok(n) => num_nodes = Some(n),
                Err(_) => {
                    return Err(format!(
                        "line {}: expected an integer for DIMENSION, not {:?}",
                        header.line, header.value
                    ));
                }
            },
            "EDGE_WEIGHT_TYPE" => {
                if header.value != "EUC_2D" {
                    return Err(format!(
                        "line {}: expected \"EUC_2D\" for EDGE_WEIGHT_TYPE, not \
                         {:?}",
                        header.line, header.value
                    ));
                }
            }
            _ => {
                return Err(format!(
                    "line {}: unknown header type {}",
                    header.line, header.name
                ));
            }
        }
    }

    let num_nodes = match num_nodes {
        Some(n) => n,
        None => {
            return Err(format!(
                "line {}: never found DIMENSION header",
                data.line_num
            ))
        }
    };
    let mut graph = Graph::new(num_nodes);

    if parse_coord_header(&mut data).is_none() {
        return Err(format!(
            "line {}: expected NODE_COORD_SECTION",
            data.line_num
        ));
    }

    let mut coords = HashMap::new();
    while let Some((node, x, y)) = parse_coord(&mut data) {
        coords.insert(node, (x, y));
    }

    for i in graph.all_nodes() {
        let coord_i = match coords.get(&i) {
            Some(v) => v,
            None => {
                return Err(format!(
                    "line {}: never found coordinate for node {}",
                    data.line_num,
                    i.index()
                ))
            }
        };
        for j in graph.all_nodes().filter(|&j| j != i) {
            let coord_j = match coords.get(&j) {
                Some(v) => v,
                None => {
                    return Err(format!(
                        "line {}: never found coordinate for node {}",
                        data.line_num,
                        j.index()
                    ))
                }
            };

            // "For these instances, the cost of travel between cities
            // is specified by the Eulidean distance rounded to the
            // nearest whole number (the TSPLIB EUC_2D-norm)."
            let distance = (coord_i.0 - coord_j.0).powi(2) + (coord_i.1 - coord_j.1).powi(2);
            let distance = distance.sqrt();
            let distance = distance.round();
            let weight = Weight::new(distance as usize);
            graph.set_weight(i, j, weight);
        }
    }

    while let Some(()) = parse_blank(&mut data) {}

    if data.current_line.is_some() {
        return Err(format!("line {}: expected EOF", data.line_num));
    }

    Ok(graph)
}

pub struct Data<'text> {
    current_line: Option<&'text str>,
    line_num: usize,
    next_lines: Lines<'text>,
}

impl<'text> Data<'text> {
    pub fn new(data: &'text str) -> Data<'text> {
        let mut lines = data.lines();
        let current_line = lines.next();
        Data {
            current_line: current_line,
            line_num: 1,
            next_lines: lines,
        }
    }

    pub fn advance(&mut self) {
        self.current_line = self.next_lines.next();
        self.line_num += 1;
    }
}

pub struct Header<'text> {
    line: usize,
    name: &'text str,
    value: &'text str,
}

pub fn parse_tsp_header<'text>(data: &mut Data<'text>) -> Option<Header<'text>> {
    data.current_line.and_then(|current_line| {
        HEADER.captures(current_line).map(|captures| {
            data.advance();
            Header {
                line: data.line_num - 1,
                name: captures.get(1).unwrap().as_str().trim(),
                value: captures.get(2).unwrap().as_str().trim(),
            }
        })
    })
}

pub fn parse_coord_header<'text>(data: &mut Data<'text>) -> Option<()> {
    data.current_line.and_then(|current_line| {
        if current_line == "NODE_COORD_SECTION" {
            data.advance();
            Some(())
        } else {
            None
        }
    })
}

pub fn parse_coord<'text>(data: &mut Data<'text>) -> Option<(Node, f64, f64)> {
    // 1 11003.611100 42102.500000
    data.current_line.and_then(|current_line| {
        COORD.captures(current_line).and_then(|captures| {
            usize::from_str(captures.get(1).unwrap().as_str())
                .ok()
                .and_then(|n| {
                    f64::from_str(captures.get(2).unwrap().as_str())
                        .ok()
                        .and_then(|x| {
                            f64::from_str(captures.get(3).unwrap().as_str())
                                .ok()
                                .and_then(|y| {
                                    if n > 0 {
                                        data.advance();
                                        Some((Node::new(n - 1), x, y))
                                    } else {
                                        None
                                    }
                                })
                        })
                })
        })
    })
}

pub fn parse_blank<'text>(data: &mut Data<'text>) -> Option<()> {
    data.current_line.and_then(|current_line| {
        if current_line.trim().is_empty() {
            data.advance();
            Some(())
        } else {
            None
        }
    })
}
<commit_msg>cargo fmt (more semicolons in 1.32)<commit_after>use regex::Regex;
use std::collections::HashMap;
use std::str::{FromStr, Lines};

use super::graph::{Graph, Node};
use super::weight::Weight;

// Parses "TSPLIB" files from sources like
//
// http://www.math.uwaterloo.ca/tsp/world/dj38.tsp
//
// The format looks roughly like this, at least for EUC_2D cases:
//
// NAME: dj38
// COMMENT : 38 locations in Djibouti
// COMMENT : Derived from National Imagery and Mapping Agency data
// COMMENT : This file is a corrected version of dj89, where duplications
// COMMENT:  have been removed.  Thanks to Jay Muthuswamy and others for
// COMMENT:  requesting data sets without duplications.
// TYPE: TSP
// DIMENSION: 38
// EDGE_WEIGHT_TYPE: EUC_2D
// NODE_COORD_SECTION
// 1 11003.611100 42102.500000

lazy_static! {
    static ref HEADER: Regex = Regex::new(r"([A-Z_]+)\s*:(.*)").unwrap();
}

lazy_static! {
    static ref COORD: Regex = Regex::new(r"([0-9]+) ([0-9.]+) ([0-9.]+)").unwrap();
}

pub fn parse_tsp_data(text: &str) -> Result<Graph, String> {
    let mut data = Data::new(text);
    let mut num_nodes = None;

    while let Some(header) = parse_tsp_header(&mut data) {
        match header.name {
            "NAME" => {}
            "COMMENT" => {}
            "TYPE" => {
                if header.value != "TSP" {
                    return Err(format!(
                        "line {}: expected \"TSP\" for TYPE, not {:?}",
                        header.line, header.value
                    ));
                }
            }
            "DIMENSION" => match usize::from_str(header.value) {
                Ok(n) => num_nodes = Some(n),
                Err(_) => {
                    return Err(format!(
                        "line {}: expected an integer for DIMENSION, not {:?}",
                        header.line, header.value
                    ));
                }
            },
            "EDGE_WEIGHT_TYPE" => {
                if header.value != "EUC_2D" {
                    return Err(format!(
                        "line {}: expected \"EUC_2D\" for EDGE_WEIGHT_TYPE, not \
                         {:?}",
                        header.line, header.value
                    ));
                }
            }
            _ => {
                return Err(format!(
                    "line {}: unknown header type {}",
                    header.line, header.name
                ));
            }
        }
    }

    let num_nodes = match num_nodes {
        Some(n) => n,
        None => {
            return Err(format!(
                "line {}: never found DIMENSION header",
                data.line_num
            ));
        }
    };
    let mut graph = Graph::new(num_nodes);

    if parse_coord_header(&mut data).is_none() {
        return Err(format!(
            "line {}: expected NODE_COORD_SECTION",
            data.line_num
        ));
    }

    let mut coords = HashMap::new();
    while let Some((node, x, y)) = parse_coord(&mut data) {
        coords.insert(node, (x, y));
    }

    for i in graph.all_nodes() {
        let coord_i = match coords.get(&i) {
            Some(v) => v,
            None => {
                return Err(format!(
                    "line {}: never found coordinate for node {}",
                    data.line_num,
                    i.index()
                ));
            }
        };
        for j in graph.all_nodes().filter(|&j| j != i) {
            let coord_j = match coords.get(&j) {
                Some(v) => v,
                None => {
                    return Err(format!(
                        "line {}: never found coordinate for node {}",
                        data.line_num,
                        j.index()
                    ));
                }
            };

            // "For these instances, the cost of travel between cities
            // is specified by the Eulidean distance rounded to the
            // nearest whole number (the TSPLIB EUC_2D-norm)."
            let distance = (coord_i.0 - coord_j.0).powi(2) + (coord_i.1 - coord_j.1).powi(2);
            let distance = distance.sqrt();
            let distance = distance.round();
            let weight = Weight::new(distance as usize);
            graph.set_weight(i, j, weight);
        }
    }

    while let Some(()) = parse_blank(&mut data) {}

    if data.current_line.is_some() {
        return Err(format!("line {}: expected EOF", data.line_num));
    }

    Ok(graph)
}

pub struct Data<'text> {
    current_line: Option<&'text str>,
    line_num: usize,
    next_lines: Lines<'text>,
}

impl<'text> Data<'text> {
    pub fn new(data: &'text str) -> Data<'text> {
        let mut lines = data.lines();
        let current_line = lines.next();
        Data {
            current_line: current_line,
            line_num: 1,
            next_lines: lines,
        }
    }

    pub fn advance(&mut self) {
        self.current_line = self.next_lines.next();
        self.line_num += 1;
    }
}

pub struct Header<'text> {
    line: usize,
    name: &'text str,
    value: &'text str,
}

pub fn parse_tsp_header<'text>(data: &mut Data<'text>) -> Option<Header<'text>> {
    data.current_line.and_then(|current_line| {
        HEADER.captures(current_line).map(|captures| {
            data.advance();
            Header {
                line: data.line_num - 1,
                name: captures.get(1).unwrap().as_str().trim(),
                value: captures.get(2).unwrap().as_str().trim(),
            }
        })
    })
}

pub fn parse_coord_header<'text>(data: &mut Data<'text>) -> Option<()> {
    data.current_line.and_then(|current_line| {
        if current_line == "NODE_COORD_SECTION" {
            data.advance();
            Some(())
        } else {
            None
        }
    })
}

pub fn parse_coord<'text>(data: &mut Data<'text>) -> Option<(Node, f64, f64)> {
    // 1 11003.611100 42102.500000
    data.current_line.and_then(|current_line| {
        COORD.captures(current_line).and_then(|captures| {
            usize::from_str(captures.get(1).unwrap().as_str())
                .ok()
                .and_then(|n| {
                    f64::from_str(captures.get(2).unwrap().as_str())
                        .ok()
                        .and_then(|x| {
                            f64::from_str(captures.get(3).unwrap().as_str())
                                .ok()
                                .and_then(|y| {
                                    if n > 0 {
                                        data.advance();
                                        Some((Node::new(n - 1), x, y))
                                    } else {
                                        None
                                    }
                                })
                        })
                })
        })
    })
}

pub fn parse_blank<'text>(data: &mut Data<'text>) -> Option<()> {
    data.current_line.and_then(|current_line| {
        if current_line.trim().is_empty() {
            data.advance();
            Some(())
        } else {
            None
        }
    })
}
<|endoftext|>


<commit_before>pub mod disk;
pub mod memory;

#[cfg(test)]
mod tests {
    use db::storage::{Memory, Disk, StorageEngine};

    #[test]
    fn test_storage_interface() {
        let mem = Memory::new().expect("Memory storage");
        let storage = StorageEngine::new(mem);

    }

}
<commit_msg>creating 2 engines<commit_after>pub mod disk;
pub mod memory;

#[cfg(test)]
mod tests {
    use db::storage::{Memory, Disk, StorageEngine};
    use tempdir::TempDir;

    #[test]
    fn test_storage_engine_creation() {
        let mem = Memory::new().expect("Memory storage");
        let storage = StorageEngine::new(mem);

        let tmp = TempDir::new("totalrecallwhatever").expect("Expected dir");
        let mut tmp2 = tmp.into_path();
        tmp2.push("blah");

        let disk = Disk::new(10, tmp2).expect("Disk storage");
        let s2 = StorageEngine::new(disk);
    }

}
<|endoftext|>


<commit_before>use std::f64;
use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use consts;
use error::StatsError;
use function::{gamma, stable};
use result::Result;
use super::{Distribution, Univariate, Continuous};

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Weibull {
    shape: f64,
    scale: f64,
    scale_pow_shape_inv: f64,
}

impl Weibull {
    pub fn new(shape: f64, scale: f64) -> Result<Weibull> {
        if shape <= 0.0 || scale <= 0.0 {
            Err(StatsError::BadParams)
        } else {
            Ok(Weibull {
                shape: shape,
                scale: scale,
                scale_pow_shape_inv: scale.powf(-shape),
            })
        }
    }

    pub fn shape(&self) -> f64 {
        self.shape
    }

    pub fn scale(&self) -> f64 {
        self.scale
    }
}

impl Sample<f64> for Weibull {
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for Weibull {
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution for Weibull {
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        let x = r.next_f64();
        self.scale * (-x.ln()).powf(1.0 / self.shape)
    }
}

impl Univariate for Weibull {
    fn mean(&self) -> f64 {
        self.scale * gamma::gamma(1.0 + 1.0 / self.shape)
    }

    fn variance(&self) -> f64 {
        self.scale * self.scale * gamma::gamma(1.0 + 2.0 / self.shape) - self.mean() * self.mean()
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn entropy(&self) -> f64 {
        consts::EULER_MASCHERONI * (1.0 - 1.0 / self.shape) + (self.scale / self.shape).ln() + 1.0
    }

    fn skewness(&self) -> f64 {
        let mu = self.mean();
        let sigma = self.std_dev();
        let sigma2 = sigma * sigma;
        let sigma3 = sigma2 * sigma;
        self.scale * self.scale * self.scale * gamma::gamma(1.0 + 3.0 / self.shape) -
        3.0 * sigma2 * mu - (mu * mu * mu) / sigma3
    }

    fn median(&self) -> f64 {
        self.scale * f64::consts::LN_2.powf(1.0 / self.shape)
    }

    fn cdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        -stable::exp_minus_one(x.powf(self.shape) * self.scale_pow_shape_inv)
    }
}

impl Continuous for Weibull {
    fn mode(&self) -> f64 {
        if self.shape <= 1.0 {
            0.0
        } else {
            self.scale * ((self.shape - 1.0) / self.shape).powf(1.0 / self.shape)
        }
    }

    fn min(&self) -> f64 {
        0.0
    }

    fn max(&self) -> f64 {
        f64::INFINITY
    }

    fn pdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        match (x, self.shape) {
            (0.0, 1.0) => self.shape / self.scale,
            (_, _) if x >= 0.0 => {
                self.shape * (x / self.scale).powf(self.shape - 1.0) *
                (-(x.powf(self.shape)) * self.scale_pow_shape_inv).exp() /
                self.scale
            }
            (_, _) => 0.0,
        }
    }

    fn ln_pdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        match (x, self.shape) {
            (0.0, 1.0) => self.shape.ln() - self.scale.ln(),
            (_, _) if x >= 0.0 => {
                self.shape.ln() + (self.shape - 1.0) * (x / self.scale).ln() -
                x.powf(self.shape) * self.scale_pow_shape_inv - self.scale.ln()
            }
            (_, _) => f64::NEG_INFINITY,
        }
    }
}
<commit_msg>begin tests for weibull distribution<commit_after>use std::f64;
use rand::Rng;
use rand::distributions::{Sample, IndependentSample};
use consts;
use error::StatsError;
use function::{gamma, stable};
use result::Result;
use super::{Distribution, Univariate, Continuous};

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Weibull {
    shape: f64,
    scale: f64,
    scale_pow_shape_inv: f64,
}

impl Weibull {
    pub fn new(shape: f64, scale: f64) -> Result<Weibull> {
        let is_nan = shape.is_nan() || scale.is_nan();
        match (shape, scale, is_nan) {
            (_, _, true) => Err(StatsError::BadParams),
            (_, _, false) if shape <= 0.0 || scale <= 0.0 => Err(StatsError::BadParams),
            (_, _, false) => {
                Ok(Weibull {
                    shape: shape,
                    scale: scale,
                    scale_pow_shape_inv: scale.powf(-shape),
                })
            }
        }
    }

    pub fn shape(&self) -> f64 {
        self.shape
    }

    pub fn scale(&self) -> f64 {
        self.scale
    }
}

impl Sample<f64> for Weibull {
    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl IndependentSample<f64> for Weibull {
    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
        super::Distribution::sample(self, r)
    }
}

impl Distribution for Weibull {
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        let x = r.next_f64();
        self.scale * (-x.ln()).powf(1.0 / self.shape)
    }
}

impl Univariate for Weibull {
    fn mean(&self) -> f64 {
        self.scale * gamma::gamma(1.0 + 1.0 / self.shape)
    }

    fn variance(&self) -> f64 {
        self.scale * self.scale * gamma::gamma(1.0 + 2.0 / self.shape) - self.mean() * self.mean()
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn entropy(&self) -> f64 {
        consts::EULER_MASCHERONI * (1.0 - 1.0 / self.shape) + (self.scale / self.shape).ln() + 1.0
    }

    fn skewness(&self) -> f64 {
        let mu = self.mean();
        let sigma = self.std_dev();
        let sigma2 = sigma * sigma;
        let sigma3 = sigma2 * sigma;
        self.scale * self.scale * self.scale * gamma::gamma(1.0 + 3.0 / self.shape) -
        3.0 * sigma2 * mu - (mu * mu * mu) / sigma3
    }

    fn median(&self) -> f64 {
        self.scale * f64::consts::LN_2.powf(1.0 / self.shape)
    }

    fn cdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        -stable::exp_minus_one(x.powf(self.shape) * self.scale_pow_shape_inv)
    }
}

impl Continuous for Weibull {
    fn mode(&self) -> f64 {
        if self.shape <= 1.0 {
            0.0
        } else {
            self.scale * ((self.shape - 1.0) / self.shape).powf(1.0 / self.shape)
        }
    }

    fn min(&self) -> f64 {
        0.0
    }

    fn max(&self) -> f64 {
        f64::INFINITY
    }

    fn pdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        match (x, self.shape) {
            (0.0, 1.0) => self.shape / self.scale,
            (_, _) if x >= 0.0 => {
                self.shape * (x / self.scale).powf(self.shape - 1.0) *
                (-(x.powf(self.shape)) * self.scale_pow_shape_inv).exp() /
                self.scale
            }
            (_, _) => 0.0,
        }
    }

    fn ln_pdf(&self, x: f64) -> f64 {
        assert!(x >= 0.0, format!("{}", StatsError::ArgNotNegative("x")));
        match (x, self.shape) {
            (0.0, 1.0) => self.shape.ln() - self.scale.ln(),
            (_, _) if x >= 0.0 => {
                self.shape.ln() + (self.shape - 1.0) * (x / self.scale).ln() -
                x.powf(self.shape) * self.scale_pow_shape_inv - self.scale.ln()
            }
            (_, _) => f64::NEG_INFINITY,
        }
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use distribution::{Univariate, Continuous};
    use prec;
    use super::Weibull;

    fn try_create(shape: f64, scale: f64) -> Weibull {
        let n = Weibull::new(shape, scale);
        assert!(n.is_ok());
        n.unwrap()
    }

    fn create_case(shape: f64, scale: f64) {
        let n = try_create(shape, scale);
        assert_eq!(shape, n.shape());
        assert_eq!(scale, n.scale());
    }

    fn bad_create_case(shape: f64, scale: f64) {
        let n = Weibull::new(shape, scale);
        assert!(n.is_err());
    }

    fn get_value<F>(shape: f64, scale: f64, eval: F) -> f64
        where F: Fn(Weibull) -> f64
    {
        let n = try_create(shape, scale);
        eval(n)
    }

    fn test_case<F>(shape: f64, scale: f64, expected: f64, eval: F)
        where F: Fn(Weibull) -> f64
    {
        let x = get_value(shape, scale, eval);
        assert_eq!(expected, x);
    }

    fn test_almost<F>(shape: f64, scale: f64, expected: f64, acc: f64, eval: F)
        where F: Fn(Weibull) -> f64
    {
        let x = get_value(shape, scale, eval);
        assert!(prec::almost_eq(expected, x, acc));
    }

    #[test]
    fn test_create() {
        create_case(1.0, 0.1);
        create_case(10.0, 1.0);
        create_case(11.0, 10.0);
        create_case(12.0, f64::INFINITY);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(f64::NAN, 1.0);
        bad_create_case(1.0, f64::NAN);
        bad_create_case(f64::NAN, f64::NAN);
        bad_create_case(1.0, -1.0);
        bad_create_case(-1.0, 1.0);
        bad_create_case(-1.0, -1.0);
        bad_create_case(0.0, 0.0);
        bad_create_case(0.0, 1.0);
        bad_create_case(1.0, 0.0);
    }

    #[test]
    fn test_mean() {
        test_case(1.0, 0.1, 0.1, |x| x.mean());
        test_case(1.0, 1.0, 1.0, |x| x.mean());
        test_almost(10.0, 10.0, 9.5135076986687318362924871772654021925505786260884, 1e-14, |x| x.mean());
        test_almost(10.0, 1.0, 0.95135076986687318362924871772654021925505786260884, 1e-15, |x| x.mean());
    }

    #[test]
    fn test_variance() {
        test_almost(1.0, 0.1, 0.01, 1e-16, |x| x.variance());
        test_almost(1.0, 1.0, 1.0, 1e-14, |x| x.variance());
        test_almost(10.0, 10.0, 1.3100455073468309147154581687505295026863354547057, 1e-12, |x| x.variance());
        test_almost(10.0, 1.0, 0.013100455073468309147154581687505295026863354547057, 1e-14, |x| x.variance());
    }

    #[test]
    fn test_std_dev() {
        test_almost(1.0, 0.1, 0.1, 1e-15, |x| x.std_dev());
        test_almost(1.0, 1.0, 1.0, 1e-14, |x| x.std_dev());
        test_almost(10.0, 10.0, 1.1445721940300799194124723631014002560036613065794, 1e-12, |x| x.std_dev());
        test_almost(10.0, 1.0, 0.11445721940300799194124723631014002560036613065794, 1e-13, |x| x.std_dev());
    }

    #[test]
    fn test_entropy() {
        test_almost(1.0, 0.1, -1.302585092994045684018, 1e-15, |x| x.entropy());
        test_case(1.0, 1.0, 1.0, |x| x.entropy());
        test_case(10.0, 10.0, 1.519494098411379574546, |x| x.entropy());
        test_almost(10.0, 1.0, -0.783090994582666109472, 1e-15, |x| x.entropy());
    }
}<|endoftext|>


<commit_before>extern crate spine;
extern crate test;
extern crate clock_ticks;

use std::old_io::BufReader;

#[bench]
fn loading(bencher: &mut test::Bencher) {
    let src: &[u8] = include_bytes!("../tests/example.json");

    bencher.iter(|| {
        spine::SpineDocument::new(BufReader::new(src))
    });
}

#[bench]
fn animation(bencher: &mut test::Bencher) {
    let src: &[u8] = include_bytes!("../tests/example.json");
    let doc = spine::SpineDocument::new(BufReader::new(src)).unwrap();

    bencher.iter(|| {
        doc.calculate("default", Some("walk"), (clock_ticks::precise_time_ns() / 1000000) as f32 / 1000.0)
    })
}
<commit_msg>remove old_io reference<commit_after>#![feature(test)]

extern crate spine;
extern crate test;
extern crate clock_ticks;

use std::io::BufReader;

#[bench]
fn loading(bencher: &mut test::Bencher) {
    let src: &[u8] = include_bytes!("../tests/example.json");

    bencher.iter(|| {
        spine::SpineDocument::new(BufReader::new(src))
    });
}

#[bench]
fn animation(bencher: &mut test::Bencher) {
    let src: &[u8] = include_bytes!("../tests/example.json");
    let doc = spine::SpineDocument::new(BufReader::new(src)).unwrap();

    bencher.iter(|| {
        doc.calculate("default", Some("walk"), (clock_ticks::precise_time_ns() / 1000000) as f32 / 1000.0)
    })
}
<|endoftext|>