<commit_before>// Make-related variables are capitalized:
// This is not Rust-way, but makes code readable where we interface with Make
#![allow(non_snake_case)]

static COMPONENTS_VERSION: &'static str = env!("CARGO_PKG_VERSION");
static COMPONENTS_DATE:    &'static str = "2015-12-31";

use std::process;
use std::process::Command;
use std::process::Stdio;
use std::env;
use std::fs;
use std::fs::File;
use std::os::unix::prelude::*;

fn main() {
    let command: String;
    let explain_mode: bool;
    let debug_mode: bool = env::vars().any(|k| k.0 == "DEBUG" );

    if debug_mode {
        println!("Debug mode is enabled");
    }

    let mut args = env::args();

    if args.len() == 1 {
        println!("Components {} ({})\n\n{}", COMPONENTS_VERSION, COMPONENTS_DATE, COMPONENTS_USAGE_INSTRUCTIONS);

        process::exit(0);
    }

    args.next(); // skipping arg[0]

    let explain_or_command = args.next().unwrap();
    if explain_or_command == "explain" {
         command = args.next().unwrap_or_else(|| {
             println!("provide a command to explain: install, update, purge etc");
             process::exit(1);
         });

         explain_mode = true;
    } else {
         command = explain_or_command;
         explain_mode = false;
    }

    if debug_mode {
         println!("command is: {}", &command);
    }

    let available_commands = ["install", "purge", "clean", "uninstall", "update"];

    let index = available_commands.iter().position(|&r| r == command);
    if index.is_some() == false {
        println!("invalid command: {}", command);
        process::exit(1);
    }

    let current_dir = env::current_dir().unwrap();
    let home_dir    = env::home_dir().unwrap();

    if debug_mode {
        println!("The current directory is: {}", current_dir.display());
        println!("The home directory is: {}", home_dir.display());
    }

    // Local
    let COMPONENTS_TEMP_PATH: &'static str = "/tmp/Components";

    // Global (we'll pass them to Make)
    let COMPONENTS_BUILD_CACHE_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_BUILD_CACHE_PATH") {
	COMPONENTS_BUILD_CACHE_PATH = std::path::PathBuf::from(value);
    } else {
	COMPONENTS_BUILD_CACHE_PATH = home_dir.join("Library/Caches/Components");
    }

    let COMPONENTS_INSTALL_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_INSTALL_PATH") {
	COMPONENTS_INSTALL_PATH = std::path::PathBuf::from(value);
    } else {
	COMPONENTS_INSTALL_PATH = current_dir.join("Components");
    }

    let COMPONENTS_MAKE_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_MAKE_PATH") {
        COMPONENTS_MAKE_PATH  = std::path::PathBuf::from(value);
    } else {
        COMPONENTS_MAKE_PATH  = current_dir.join("Components.make");
    }

    if debug_mode {
        println!("COMPONENTS_MAKE_PATH: {}", COMPONENTS_MAKE_PATH.display());
        println!("COMPONENTS_INSTALL_PATH: {}", COMPONENTS_INSTALL_PATH.display());
        println!("COMPONENTS_BUILD_CACHE_PATH: {}", COMPONENTS_BUILD_CACHE_PATH.display());
    }

    if COMPONENTS_MAKE_PATH.exists() == false {
        println!("Directory COMPONENTS_MAKE_PATH does not exist: {:?}", COMPONENTS_MAKE_PATH);
        process::exit(1);
    }

    fs::create_dir_all(&COMPONENTS_BUILD_CACHE_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_BUILD_CACHE_PATH: {:?}", COMPONENTS_BUILD_CACHE_PATH);
        process::exit(1);
    });

    fs::create_dir_all(&COMPONENTS_INSTALL_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_INSTALL_PATH: {:?}", COMPONENTS_INSTALL_PATH);
        process::exit(1);
    });

    fs::create_dir_all(&COMPONENTS_TEMP_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_TEMP_PATH: {:?}", COMPONENTS_TEMP_PATH);
        process::exit(1);
    });

    let mut makeflags: Vec<&str> = vec!["--warn-undefined-variables"];

    if explain_mode {
        makeflags.push("-n");
    }

    if debug_mode {
        makeflags.push("-r");
        makeflags.push("-d");
        println!("Makeflags: {:?}", makeflags);
    }

    let components: Vec<String> = args.collect();

    let component_paths: Vec<std::path::PathBuf>;

    if components.len() > 0 {
        if debug_mode {
            println!("Components: {:?}", components);
        }

        let mut should_break = false;

        let existing_components = {
            let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

            existing_component_paths_iterator.map(|entry| {
                let entry = entry.unwrap();
                let entry_path = entry.path();
                entry_path.file_stem().unwrap().to_str().unwrap().to_string()
            }).collect::<Vec<String>>()
        };

        for component in &components {
            let component_exists = existing_components.iter().any(|existing_component| existing_component == component);

            if component_exists == false {
                println!("Could not find component: {}", component);
                should_break = true;
            }
        }

        if should_break {
            process::exit(1);
        }

        let selected_component_paths_iterator = {
            let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

            existing_component_paths_iterator.filter(|entry| {
                let entry = entry.as_ref().unwrap();
                let entry_path = entry.path();
                let component_name = entry_path.file_stem().unwrap().to_str().unwrap();
                components.iter().any(|c| c == component_name)
            })
        };

        component_paths = selected_component_paths_iterator.map(|entry| {
            let entry = entry.unwrap();
            let entry_path = entry.path();
            entry_path
        }).collect::<Vec<std::path::PathBuf>>();
    } else {
        let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

        component_paths = existing_component_paths_iterator.map(|entry| {
            let entry = entry.unwrap();
            let entry_path = entry.path();
            entry_path
        }).collect::<Vec<std::path::PathBuf>>();
    }

    let mut success = true;
    for path in component_paths {
        let path_is_valid_component_make = path.is_file() && path.extension().is_some() && path.extension().unwrap() == "make";

        if path_is_valid_component_make == false {
            println!("COMPONENTS_MAKE_PATH directory contains non-builable artefacts (must only consist of *.make)");
            process::exit(1);
        }

        unsafe {
            let component_name = path.file_stem().unwrap().to_str().unwrap();

            let logpath = format!("/tmp/Components/{}.log", component_name);

            let logfile = File::create(&logpath).unwrap();

            let fd = logfile.as_raw_fd();

            let (stdout, stderr) = if debug_mode || explain_mode {
                (Stdio::inherit(), Stdio::inherit())
            } else {
                (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd))
            };

            print!("[{}] {}:", command, component_name);

            let status = Command::new("make")
                .arg(&command)
                .args(&makeflags)
                .arg("-f")
                .arg(path.to_str().unwrap())
                .env("COMPONENTS_INSTALL_PATH", COMPONENTS_INSTALL_PATH.as_os_str())
                .env("COMPONENTS_MAKE_PATH", COMPONENTS_MAKE_PATH.as_os_str())
                .stdout(stdout)
                .stderr(stderr)
                .status().unwrap_or_else(|e| {
                    panic!("failed to execute process: {}", e)
                });

            if status.success() {
                print!(" done.\n");
            } else {
                print!(" failed. See log for details:\n{}\n", &logpath);
                success = false;
            }
        }
    }

    if success {
        process::exit(0);
    } else {
        process::exit(1);
    }
}

static COMPONENTS_USAGE_INSTRUCTIONS: &'static str = "\
Usage:
  components [explain] command [components]

  command:
    install   - downloads, builds (if needed) and installs component
                into a vendor directory (COMPONENTS_INSTALL_PATH)
    uninstall - removes component from a vendor directory (COMPONENTS_INSTALL_PATH)
    clean     - removes downloaded files and built artefacts from
                cache directory (COMPONENTS_BUILD_CACHE_PATH)
    purge     - cleans and uninstalls component
    update    - uninstalls current and installs new version of a component

  explain:
    print the commands that would be executed, but do not execute them

  components:
    one or more component name, enumerates all components in the components
    directory (COMPONENTS_MAKE_PATH) if the parameter is omitted

Directories:
  COMPONENTS_MAKE_PATH         - directory contains all components used in the current project
                               $COMPONENTS_MAKE_PATH
  COMPONENTS_INSTALL_PATH      - directory contains all installed components for the current project
                               $COMPONENTS_INSTALL_PATH
  COMPONENTS_BUILD_CACHE_PATH  - stores zip/tarballs, built artefacts, or source code of used components
                               $COMPONENTS_BUILD_CACHE_PATH

Debugging:
  Set environment variable 'DEBUG' to 'YES' to enable debugging output.
  It will run make with additional parameters '-r -d' and will send output to 'STDOUT'.

  From 'man make':
    -d  Print debugging information in addition to normal processing.
    -r  Eliminate use of the built−in implicit rules.

Examples:
  components install                # installs every component from the components directory (COMPONENTS_MAKE_PATH)
  components purge Cedar            # cleans and uninstalls Cedar library
  components update BloodMagic      # uninstalls current and installs new version of BloodMagic library
  components clean BloodMagic Cedar # cleans up Cedar' and BloodMagic' artefacts
  components explain install        # prints commands that would be executed to install each component
  DEBUG=YES components install      # prints additional information to 'STDOUT'\
";

<commit_msg>Print "[install] Component" in correct order (fixes #23)<commit_after>// Make-related variables are capitalized:
// This is not Rust-way, but makes code readable where we interface with Make
#![allow(non_snake_case)]

static COMPONENTS_VERSION: &'static str = env!("CARGO_PKG_VERSION");
static COMPONENTS_DATE:    &'static str = "2015-12-31";

use std::env;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::process;
use std::process::Command;
use std::process::Stdio;
use std::os::unix::prelude::*;

fn main() {
    let command: String;
    let explain_mode: bool;
    let debug_mode: bool = env::vars().any(|k| k.0 == "DEBUG" );

    if debug_mode {
        println!("Debug mode is enabled");
    }

    let mut args = env::args();

    if args.len() == 1 {
        println!("Components {} ({})\n\n{}", COMPONENTS_VERSION, COMPONENTS_DATE, COMPONENTS_USAGE_INSTRUCTIONS);

        process::exit(0);
    }

    args.next(); // skipping arg[0]

    let explain_or_command = args.next().unwrap();
    if explain_or_command == "explain" {
         command = args.next().unwrap_or_else(|| {
             println!("provide a command to explain: install, update, purge etc");
             process::exit(1);
         });

         explain_mode = true;
    } else {
         command = explain_or_command;
         explain_mode = false;
    }

    if debug_mode {
         println!("command is: {}", &command);
    }

    let available_commands = ["install", "purge", "clean", "uninstall", "update"];

    let index = available_commands.iter().position(|&r| r == command);
    if index.is_some() == false {
        println!("invalid command: {}", command);
        process::exit(1);
    }

    let current_dir = env::current_dir().unwrap();
    let home_dir    = env::home_dir().unwrap();

    if debug_mode {
        println!("The current directory is: {}", current_dir.display());
        println!("The home directory is: {}", home_dir.display());
    }

    // Local
    let COMPONENTS_TEMP_PATH: &'static str = "/tmp/Components";

    // Global (we'll pass them to Make)
    let COMPONENTS_BUILD_CACHE_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_BUILD_CACHE_PATH") {
	COMPONENTS_BUILD_CACHE_PATH = std::path::PathBuf::from(value);
    } else {
	COMPONENTS_BUILD_CACHE_PATH = home_dir.join("Library/Caches/Components");
    }

    let COMPONENTS_INSTALL_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_INSTALL_PATH") {
	COMPONENTS_INSTALL_PATH = std::path::PathBuf::from(value);
    } else {
	COMPONENTS_INSTALL_PATH = current_dir.join("Components");
    }

    let COMPONENTS_MAKE_PATH: std::path::PathBuf;
    if let Ok(value) = std::env::var("COMPONENTS_MAKE_PATH") {
        COMPONENTS_MAKE_PATH  = std::path::PathBuf::from(value);
    } else {
        COMPONENTS_MAKE_PATH  = current_dir.join("Components.make");
    }

    if debug_mode {
        println!("COMPONENTS_MAKE_PATH: {}", COMPONENTS_MAKE_PATH.display());
        println!("COMPONENTS_INSTALL_PATH: {}", COMPONENTS_INSTALL_PATH.display());
        println!("COMPONENTS_BUILD_CACHE_PATH: {}", COMPONENTS_BUILD_CACHE_PATH.display());
    }

    if COMPONENTS_MAKE_PATH.exists() == false {
        println!("Directory COMPONENTS_MAKE_PATH does not exist: {:?}", COMPONENTS_MAKE_PATH);
        process::exit(1);
    }

    fs::create_dir_all(&COMPONENTS_BUILD_CACHE_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_BUILD_CACHE_PATH: {:?}", COMPONENTS_BUILD_CACHE_PATH);
        process::exit(1);
    });

    fs::create_dir_all(&COMPONENTS_INSTALL_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_INSTALL_PATH: {:?}", COMPONENTS_INSTALL_PATH);
        process::exit(1);
    });

    fs::create_dir_all(&COMPONENTS_TEMP_PATH).unwrap_or_else(|_| {
        println!("failed to create dir COMPONENTS_TEMP_PATH: {:?}", COMPONENTS_TEMP_PATH);
        process::exit(1);
    });

    let mut makeflags: Vec<&str> = vec!["--warn-undefined-variables"];

    if explain_mode {
        makeflags.push("-n");
    }

    if debug_mode {
        makeflags.push("-r");
        makeflags.push("-d");
        println!("Makeflags: {:?}", makeflags);
    }

    let components: Vec<String> = args.collect();

    let component_paths: Vec<std::path::PathBuf>;

    if components.len() > 0 {
        if debug_mode {
            println!("Components: {:?}", components);
        }

        let mut should_break = false;

        let existing_components = {
            let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

            existing_component_paths_iterator.map(|entry| {
                let entry = entry.unwrap();
                let entry_path = entry.path();
                entry_path.file_stem().unwrap().to_str().unwrap().to_string()
            }).collect::<Vec<String>>()
        };

        for component in &components {
            let component_exists = existing_components.iter().any(|existing_component| existing_component == component);

            if component_exists == false {
                println!("Could not find component: {}", component);
                should_break = true;
            }
        }

        if should_break {
            process::exit(1);
        }

        let selected_component_paths_iterator = {
            let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

            existing_component_paths_iterator.filter(|entry| {
                let entry = entry.as_ref().unwrap();
                let entry_path = entry.path();
                let component_name = entry_path.file_stem().unwrap().to_str().unwrap();
                components.iter().any(|c| c == component_name)
            })
        };

        component_paths = selected_component_paths_iterator.map(|entry| {
            let entry = entry.unwrap();
            let entry_path = entry.path();
            entry_path
        }).collect::<Vec<std::path::PathBuf>>();
    } else {
        let existing_component_paths_iterator: fs::ReadDir = fs::read_dir(&COMPONENTS_MAKE_PATH).unwrap();

        component_paths = existing_component_paths_iterator.map(|entry| {
            let entry = entry.unwrap();
            let entry_path = entry.path();
            entry_path
        }).collect::<Vec<std::path::PathBuf>>();
    }

    let mut success = true;
    for path in component_paths {
        let path_is_valid_component_make = path.is_file() && path.extension().is_some() && path.extension().unwrap() == "make";

        if path_is_valid_component_make == false {
            println!("COMPONENTS_MAKE_PATH directory contains non-builable artefacts (must only consist of *.make)");
            process::exit(1);
        }

        unsafe {
            let component_name = path.file_stem().unwrap().to_str().unwrap();

            let logpath = format!("/tmp/Components/{}.log", component_name);

            let logfile = File::create(&logpath).unwrap();

            let fd = logfile.as_raw_fd();

            let (stdout, stderr) = if debug_mode || explain_mode {
                (Stdio::inherit(), Stdio::inherit())
            } else {
                (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd))
            };

            print!("[{}] {}:", command, component_name);

            std::io::stdout().flush().unwrap();

            let status = Command::new("make")
                .arg(&command)
                .args(&makeflags)
                .arg("-f")
                .arg(path.to_str().unwrap())
                .env("COMPONENTS_INSTALL_PATH", COMPONENTS_INSTALL_PATH.as_os_str())
                .env("COMPONENTS_MAKE_PATH", COMPONENTS_MAKE_PATH.as_os_str())
                .stdout(stdout)
                .stderr(stderr)
                .status().unwrap_or_else(|e| {
                    panic!("failed to execute process: {}", e)
                });

            if status.success() {
                print!(" done.\n");
            } else {
                print!(" failed. See log for details:\n{}\n", &logpath);
                success = false;
            }
        }
    }

    if success {
        process::exit(0);
    } else {
        process::exit(1);
    }
}

static COMPONENTS_USAGE_INSTRUCTIONS: &'static str = "\
Usage:
  components [explain] command [components]

  command:
    install   - downloads, builds (if needed) and installs component
                into a vendor directory (COMPONENTS_INSTALL_PATH)
    uninstall - removes component from a vendor directory (COMPONENTS_INSTALL_PATH)
    clean     - removes downloaded files and built artefacts from
                cache directory (COMPONENTS_BUILD_CACHE_PATH)
    purge     - cleans and uninstalls component
    update    - uninstalls current and installs new version of a component

  explain:
    print the commands that would be executed, but do not execute them

  components:
    one or more component name, enumerates all components in the components
    directory (COMPONENTS_MAKE_PATH) if the parameter is omitted

Directories:
  COMPONENTS_MAKE_PATH         - directory contains all components used in the current project
                               $COMPONENTS_MAKE_PATH
  COMPONENTS_INSTALL_PATH      - directory contains all installed components for the current project
                               $COMPONENTS_INSTALL_PATH
  COMPONENTS_BUILD_CACHE_PATH  - stores zip/tarballs, built artefacts, or source code of used components
                               $COMPONENTS_BUILD_CACHE_PATH

Debugging:
  Set environment variable 'DEBUG' to 'YES' to enable debugging output.
  It will run make with additional parameters '-r -d' and will send output to 'STDOUT'.

  From 'man make':
    -d  Print debugging information in addition to normal processing.
    -r  Eliminate use of the built−in implicit rules.

Examples:
  components install                # installs every component from the components directory (COMPONENTS_MAKE_PATH)
  components purge Cedar            # cleans and uninstalls Cedar library
  components update BloodMagic      # uninstalls current and installs new version of BloodMagic library
  components clean BloodMagic Cedar # cleans up Cedar' and BloodMagic' artefacts
  components explain install        # prints commands that would be executed to install each component
  DEBUG=YES components install      # prints additional information to 'STDOUT'\
";

<|endoftext|>


<commit_before>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;
extern crate num_cpus;
extern crate scoped_threadpool;

use time::precise_time_s;
use scoped_threadpool::Pool;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
const mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                   [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                   [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                   [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                   [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let thread_count = num_cpus::get();
    let mut pool = Pool::new(thread_count as u32);

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let mut vGridCapital = [0f64; nGridCapital];

    for (i, val) in vGridCapital.iter_mut().enumerate() {
        *val = 0.5 * capitalSteadyState + 0.00001 * (i as f64)
    }

    // 3. Required matrices and vectors
    let mut mValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut mPolicyFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut expectedValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    // 4. We pre-build output for each point in the grid
    let mOutput : Vec<[f64; nGridProductivity]> = (0..nGridCapital).map(|nCapital| {
        let mut arr = [0.0; nGridProductivity];

        for (nProductivity, slot) in arr.iter_mut().enumerate() {
            *slot = vProductivity[nProductivity] * vGridCapital[nCapital].powf(aalpha)
        }

        arr
    }).collect();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable

    let mut iteration = 0;

    while maxDifference > tolerance {
        for (expected_values, transitions) in expectedValueFunction.iter_mut()
                                                                                .zip(mTransition.iter()) {
            for (idx, expected_value) in expected_values.iter_mut()
                                                        .enumerate() {
                *expected_value = transitions.iter()
                                             .zip(mValueFunction.iter())
                                             .fold(0.0f64, |acc, (transition, value_fns)| {
                    acc + (transition * value_fns[idx])
                });
            }
        }

        // small array to split where the writes are going, so we don't need a mutex
        let mut differences = [-100000.0; nGridProductivity];

        pool.scoped(|scoped| {
            for (nProductivity, ((policies, value_fns), maxDifference)) in mPolicyFunction.iter_mut()
                                                                         .zip(mValueFunction.iter_mut())
                                                                         .zip(differences.iter_mut())
                                                                         .enumerate() {
                // Only capture refs
                let expectedValueFunction = &expectedValueFunction;
                let mOutput = &mOutput;

                scoped.execute(move || {
                    let expected_fn = &expectedValueFunction[nProductivity];

                    // We start from previous choice (monotonicity of policy function)
                    let mut gridCapitalNextPeriod = 0;

                    for ((policy, output), value_fn) in policies.iter_mut()
                                                                .zip(mOutput.iter())
                                                                .zip(value_fns.iter_mut()) {
                        let mut valueHighSoFar = -100000.0;
                        let mut capitalChoice = vGridCapital[0];
                        let mOutput_cache = &output[nProductivity];

                        for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
                            let consumption = mOutput_cache - &vGridCapital[nCapitalNextPeriod];
                            let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                                    bbeta *
                                                    expected_fn[nCapitalNextPeriod];

                            if valueProvisional > valueHighSoFar {
                                valueHighSoFar = valueProvisional;
                                capitalChoice = vGridCapital[nCapitalNextPeriod];
                                gridCapitalNextPeriod = nCapitalNextPeriod;
                            } else {
                                break; // We break when we have achieved the max
                            }
                        }

                        let old = mem::replace(value_fn, valueHighSoFar);
                        let diff = (old - valueHighSoFar).abs();
                        if diff > *maxDifference {
                            *maxDifference = diff
                        }

                        *policy = capitalChoice;
                    }
                })
            }
        });

        maxDifference = -100000.0;
        for &diff in &differences {
            if diff > maxDifference {
                maxDifference = diff
            }
        }

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[2][999]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<commit_msg>Distribute some more work per thread<commit_after>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;
extern crate num_cpus;
extern crate scoped_threadpool;

use time::precise_time_s;
use scoped_threadpool::Pool;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
static mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                    [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                    [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                    [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                    [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let thread_count = num_cpus::get();
    let mut pool = Pool::new(thread_count as u32);

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let mut vGridCapital = [0f64; nGridCapital];

    for (i, val) in vGridCapital.iter_mut().enumerate() {
        *val = 0.5 * capitalSteadyState + 0.00001 * (i as f64)
    }

    // 3. Required matrices and vectors
    let mut mValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut mPolicyFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut expectedValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    // 4. We pre-build output for each point in the grid
    let mOutput : Vec<[f64; nGridProductivity]> = (0..nGridCapital).map(|nCapital| {
        let mut arr = [0.0; nGridProductivity];

        for (nProductivity, slot) in arr.iter_mut().enumerate() {
            *slot = vProductivity[nProductivity] * vGridCapital[nCapital].powf(aalpha)
        }

        arr
    }).collect();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable

    let mut iteration = 0;

    while maxDifference > tolerance {
        // small array to split where the writes are going, so we don't need a mutex
        let mut differences = [-100000.0; nGridProductivity];

        pool.scoped(|scoped| {
            for (expected_values, transitions) in expectedValueFunction.iter_mut()
                                                                       .zip(mTransition.iter()) {
                // Only capture refs
                let mValueFunction = &mValueFunction;

                scoped.execute(move || {
                    for (idx, expected_value) in expected_values.iter_mut().enumerate() {
                        *expected_value = transitions.iter()
                                                     .zip(mValueFunction.iter())
                                                     .fold(0.0f64, |acc, (transition, value_fns)| {
                            acc + (transition * value_fns[idx])
                        });
                    }
                });
            }
        });

        pool.scoped(|scoped| {
            for (nProductivity, (((policies, value_fns), maxDifference), expected_values)) in mPolicyFunction.iter_mut()
                                                                         .zip(mValueFunction.iter_mut())
                                                                         .zip(differences.iter_mut())
                                                                         .zip(expectedValueFunction.iter())
                                                                         .enumerate() {
                // Only capture refs
                let mOutput = &mOutput;

                scoped.execute(move || {
                    // We start from previous choice (monotonicity of policy function)
                    let mut gridCapitalNextPeriod = 0;

                    for ((policy, output), value_fn) in policies.iter_mut()
                                                                .zip(mOutput.iter())
                                                                .zip(value_fns.iter_mut()) {
                        let mut valueHighSoFar = -100000.0;
                        let mut capitalChoice = vGridCapital[0];
                        let mOutput_cache = &output[nProductivity];

                        for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
                            let consumption = mOutput_cache - &vGridCapital[nCapitalNextPeriod];
                            let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                                    bbeta *
                                                    expected_values[nCapitalNextPeriod];

                            if valueProvisional > valueHighSoFar {
                                valueHighSoFar = valueProvisional;
                                capitalChoice = vGridCapital[nCapitalNextPeriod];
                                gridCapitalNextPeriod = nCapitalNextPeriod;
                            } else {
                                break; // We break when we have achieved the max
                            }
                        }

                        let old = mem::replace(value_fn, valueHighSoFar);
                        let diff = (old - valueHighSoFar).abs();
                        if diff > *maxDifference {
                            *maxDifference = diff
                        }

                        *policy = capitalChoice;
                    }
                })
            }
        });

        maxDifference = -100000.0;
        for &diff in &differences {
            if diff > maxDifference {
                maxDifference = diff
            }
        }

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[2][999]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<|endoftext|>


<commit_before>#[link(name = "fibonacci", vers = "1.0", author = "eliovir")];
#[crate_type = "lib"];
#[license = "MIT"];
#[desc = "Fibonacci library" ];
#[comment = "Example of library: compute Fibonacci"];
/**
 * Compute fibonacci.
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */

extern mod extra;
/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
pub fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!(fmt!("%d is negative!", n));
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}
/*
#[cfg(test)]
mod tests {
}
*/
fn RG024_x(n: int, expected: uint) {
	// println(fmt!("RG024_x(%d, %u)", n, expected));
	let found = fibonacci(n);
	assert!(expected == found);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_20(b: &mut extra::test::BenchHarness) {
	do b.iter {
		fibonacci(20);
	}
}
<commit_msg>libfibonacci.rs : Add non reccursive Fibonnacci function<commit_after>#[link(name = "fibonacci", vers = "1.0", author = "eliovir")];
#[crate_type = "lib"];
#[license = "MIT"];
#[desc = "Fibonacci library" ];
#[comment = "Example of library: compute Fibonacci"];
/**
 * Compute fibonacci.
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */

extern mod extra;
/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
pub fn fibonacci_reccursive(n: int) -> uint {
	if n < 0 {
		fail!(fmt!("%d is negative!", n));
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci_reccursive()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}

/**
 * Non reccursive function.
 */
pub fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!(fmt!("%d is negative!", n));
	} else if n == 0 {
		fail!("zero is not a right argument to fibonacci()!");
	} else if n == 1 {
		return 1u;
	}
	let mut i = 0;
	let mut sum = 0;
	let mut last = 0;
	let mut curr = 1;
	while (i < n - 1) {
		sum = last + curr;
		last = curr;
		curr = sum;
		i += 1;
	}
	sum
}

/*
#[cfg(test)]
mod tests {
}
*/
fn RG024_x(n: int, expected: uint) {
	// println(fmt!("RG024_x(%d, %u)", n, expected));
	let found = fibonacci(n);
	assert!(expected == found, fmt!("fib(%d): expected (%u) != found (%u)", n, expected, found));
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_reccursive_20(b: &mut extra::test::BenchHarness) {
	do b.iter {
		fibonacci_reccursive(20);
	}
}
#[bench]
fn bench_fibonacci_20(b: &mut extra::test::BenchHarness) {
	do b.iter {
		fibonacci(20);
	}
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Read;
use toml::{self, Value};
use serde::Deserialize;

use errors::*;

pub mod bookconfig;
pub mod htmlconfig;
pub mod playpenconfig;
pub mod tomlconfig;
pub mod jsonconfig;

// Re-export the config structs
pub use self::bookconfig::BookConfig;
pub use self::htmlconfig::HtmlConfig;
pub use self::playpenconfig::PlaypenConfig;
pub use self::tomlconfig::TomlConfig;

/// The overall configuration object for MDBook.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct Config {
    /// Metadata about the book.
    pub book: BookConfig_,
    /// Arbitrary information which renderers can use during the rendering
    /// stage.
    pub output: BTreeMap<String, Value>,
    /// Information for use by preprocessors.
    pub preprocess: BTreeMap<String, Value>,
    /// Information for use by postprocessors.
    pub postprocess: BTreeMap<String, Value>,
}

impl Config {
    /// Load a `Config` from some string.
    pub fn from_str(src: &str) -> Result<Config> {
        toml::from_str(src).chain_err(|| Error::from("Invalid configuration file"))
    }

    /// Load the configuration file from disk.
    pub fn from_disk<P: AsRef<Path>>(config_file: P) -> Result<Config> {
        let mut buffer = String::new();
        File::open(config_file)
            .chain_err(|| "Unable to open the configuration file")?
            .read_to_string(&mut buffer)
            .chain_err(|| "Couldn't read the file")?;

        Config::from_str(&buffer)
    }

    /// Convenience method for getting the html renderer's configuration.
    ///
    /// # Note
    ///
    /// This is for compatibility only. It will be removed completely once the
    /// rendering and plugin system is established.
    pub fn html_config(&self) -> Option<HtmlConfig_> {
        self.try_get_output("html").ok()
    }

    /// Try to get an output and deserialize it as a `T`.
    pub fn try_get_output<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.output)
    }

    /// Try to get the configuration for a preprocessor, deserializing it as a
    /// `T`.
    pub fn try_get_preprocessor<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.preprocess)
    }

    /// Try to get the configuration for a postprocessor, deserializing it as a
    /// `T`.
    pub fn try_get_postprocessor<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.postprocess)
    }
}

/// Convenience function to load a value from some table then deserialize it.
fn get_deserialized<'de, T: Deserialize<'de>, S: AsRef<str>>(name: S, table: &BTreeMap<String, Value>) -> Result<T> {
    match table.get(name.as_ref()) {
        Some(output) => output
            .clone()
            .try_into()
            .chain_err(|| "Couldn't deserialize the value"),
        None => bail!("Key Not Found"),
    }
}

/// Configuration options which are specific to the book and required for
/// loading it from disk.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct BookConfig_ {
    /// The book's title.
    pub title: Option<String>,
    /// The book's authors.
    pub authors: Vec<String>,
    /// An optional description for the book.
    pub description: Option<String>,
    /// Location of the book source, relative to the book's root directory.
    pub src: PathBuf,
    /// Where to put built artefacts, relative to the book's root directory.
    pub build_dir: PathBuf,
    /// Does this book support more than one language?
    pub multilingual: bool,
}

impl Default for BookConfig_ {
    fn default() -> BookConfig_ {
        BookConfig_ {
            title: None,
            authors: Vec::new(),
            description: None,
            src: PathBuf::from("src"),
            build_dir: PathBuf::from("build"),
            multilingual: false,
        }
    }
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct HtmlConfig_ {
    pub theme: Option<PathBuf>,
    pub curly_quotes: bool,
    pub mathjax_support: bool,
    pub google_analytics: Option<String>,
    pub additional_css: Vec<PathBuf>,
    pub additional_js: Vec<PathBuf>,
    pub playpen: Playpen,
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Playpen;

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

    #[test]
    fn load_a_complex_config_file() {
        let src = r#"
        [book]
        title = "Some Book"
        authors = ["Michael-F-Bryan <michaelfbryan@gmail.com>"]
        description = "A completely useless book"
        multilingual = true
        src = "source"
        build-dir = "outputs"

        [output.html]
        curly-quotes = true
        google-analytics = "123456"
        additional-css = ["./foo/bar/baz.css"]
        "#;

        let book_should_be = BookConfig_ {
            title: Some(String::from("Some Book")),
            authors: vec![String::from("Michael-F-Bryan <michaelfbryan@gmail.com>")],
            description: Some(String::from("A completely useless book")),
            multilingual: true,
            src: PathBuf::from("source"),
            build_dir: PathBuf::from("outputs"),
            ..Default::default()
        };
        let html_should_be = HtmlConfig_ {
            curly_quotes: true,
            google_analytics: Some(String::from("123456")),
            additional_css: vec![PathBuf::from("./foo/bar/baz.css")],
            ..Default::default()
        };

        let got = Config::from_str(src).unwrap();

        assert_eq!(got.book, book_should_be);
        assert_eq!(got.html_config().unwrap(), html_should_be);
    }

    #[test]
    fn load_arbitrary_output_type() {
        #[derive(Debug, Deserialize, PartialEq)]
        struct RandomOutput {
            foo: u32,
            bar: String,
            baz: Vec<bool>,
        }

        let src = r#"
        [output.random]
        foo = 5
        bar = "Hello World"
        baz = [true, true, false]
        "#;

        let should_be = RandomOutput {
            foo: 5,
            bar: String::from("Hello World"),
            baz: vec![true, true, false],
        };

        let cfg = Config::from_str(src).unwrap();
        let got: RandomOutput = cfg.try_get_output("random").unwrap();

        assert_eq!(got, should_be);
    }
}
<commit_msg>Changed to the new config types<commit_after>use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Read;
use toml::{self, Value};
use serde::Deserialize;

use errors::*;

// pub mod bookconfig;
// pub mod htmlconfig;
// pub mod playpenconfig;
// pub mod tomlconfig;
// pub mod jsonconfig;

// Re-export the config structs
// pub use self::bookconfig::BookConfig;
// pub use self::htmlconfig::HtmlConfig;
// pub use self::playpenconfig::PlaypenConfig;
// pub use self::tomlconfig::TomlConfig;

/// The overall configuration object for MDBook.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct Config {
    /// Metadata about the book.
    pub book: BookConfig,
    /// Arbitrary information which renderers can use during the rendering
    /// stage.
    pub output: BTreeMap<String, Value>,
    /// Information for use by preprocessors.
    pub preprocess: BTreeMap<String, Value>,
    /// Information for use by postprocessors.
    pub postprocess: BTreeMap<String, Value>,
}

impl Config {
    /// Load a `Config` from some string.
    pub fn from_str(src: &str) -> Result<Config> {
        toml::from_str(src).chain_err(|| Error::from("Invalid configuration file"))
    }

    /// Load the configuration file from disk.
    pub fn from_disk<P: AsRef<Path>>(config_file: P) -> Result<Config> {
        let mut buffer = String::new();
        File::open(config_file)
            .chain_err(|| "Unable to open the configuration file")?
            .read_to_string(&mut buffer)
            .chain_err(|| "Couldn't read the file")?;

        Config::from_str(&buffer)
    }

    /// Convenience method for getting the html renderer's configuration.
    ///
    /// # Note
    ///
    /// This is for compatibility only. It will be removed completely once the
    /// rendering and plugin system is established.
    pub fn html_config(&self) -> Option<HtmlConfig> {
        self.try_get_output("html").ok()
    }

    /// Try to get an output and deserialize it as a `T`.
    pub fn try_get_output<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.output)
    }

    /// Try to get the configuration for a preprocessor, deserializing it as a
    /// `T`.
    pub fn try_get_preprocessor<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.preprocess)
    }

    /// Try to get the configuration for a postprocessor, deserializing it as a
    /// `T`.
    pub fn try_get_postprocessor<'de, T: Deserialize<'de>, S: AsRef<str>>(&self, name: S) -> Result<T> {
        get_deserialized(name, &self.postprocess)
    }
}

/// Convenience function to load a value from some table then deserialize it.
fn get_deserialized<'de, T: Deserialize<'de>, S: AsRef<str>>(name: S, table: &BTreeMap<String, Value>) -> Result<T> {
    match table.get(name.as_ref()) {
        Some(output) => output
            .clone()
            .try_into()
            .chain_err(|| "Couldn't deserialize the value"),
        None => bail!("Key Not Found"),
    }
}

/// Configuration options which are specific to the book and required for
/// loading it from disk.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct BookConfig {
    /// The book's title.
    pub title: Option<String>,
    /// The book's authors.
    pub authors: Vec<String>,
    /// An optional description for the book.
    pub description: Option<String>,
    /// Location of the book source, relative to the book's root directory.
    pub src: PathBuf,
    /// Where to put built artefacts, relative to the book's root directory.
    pub build_dir: PathBuf,
    /// Does this book support more than one language?
    pub multilingual: bool,
}

impl Default for BookConfig {
    fn default() -> BookConfig {
        BookConfig {
            title: None,
            authors: Vec::new(),
            description: None,
            src: PathBuf::from("src"),
            build_dir: PathBuf::from("build"),
            multilingual: false,
        }
    }
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct HtmlConfig {
    pub theme: Option<PathBuf>,
    pub curly_quotes: bool,
    pub mathjax_support: bool,
    pub google_analytics: Option<String>,
    pub additional_css: Vec<PathBuf>,
    pub additional_js: Vec<PathBuf>,
    pub playpen: Playpen,
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Playpen;

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

    #[test]
    fn load_a_complex_config_file() {
        let src = r#"
        [book]
        title = "Some Book"
        authors = ["Michael-F-Bryan <michaelfbryan@gmail.com>"]
        description = "A completely useless book"
        multilingual = true
        src = "source"
        build-dir = "outputs"

        [output.html]
        curly-quotes = true
        google-analytics = "123456"
        additional-css = ["./foo/bar/baz.css"]
        "#;

        let book_should_be = BookConfig_ {
            title: Some(String::from("Some Book")),
            authors: vec![String::from("Michael-F-Bryan <michaelfbryan@gmail.com>")],
            description: Some(String::from("A completely useless book")),
            multilingual: true,
            src: PathBuf::from("source"),
            build_dir: PathBuf::from("outputs"),
            ..Default::default()
        };
        let html_should_be = HtmlConfig_ {
            curly_quotes: true,
            google_analytics: Some(String::from("123456")),
            additional_css: vec![PathBuf::from("./foo/bar/baz.css")],
            ..Default::default()
        };

        let got = Config::from_str(src).unwrap();

        assert_eq!(got.book, book_should_be);
        assert_eq!(got.html_config().unwrap(), html_should_be);
    }

    #[test]
    fn load_arbitrary_output_type() {
        #[derive(Debug, Deserialize, PartialEq)]
        struct RandomOutput {
            foo: u32,
            bar: String,
            baz: Vec<bool>,
        }

        let src = r#"
        [output.random]
        foo = 5
        bar = "Hello World"
        baz = [true, true, false]
        "#;

        let should_be = RandomOutput {
            foo: 5,
            bar: String::from("Hello World"),
            baz: vec![true, true, false],
        };

        let cfg = Config::from_str(src).unwrap();
        let got: RandomOutput = cfg.try_get_output("random").unwrap();

        assert_eq!(got, should_be);
    }
}
<|endoftext|>


<commit_before>#![cfg(all(feature = "elastictranscoder", feature = "s3"))]

extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rusoto_core;
extern crate rusoto_elastictranscoder;
extern crate rusoto_s3;

use std::clone::Clone;
use std::ops::{Deref, DerefMut};

use rand::distributions::Alphanumeric;
use rand::Rng;
use rusoto_core::Region;
use rusoto_elastictranscoder::{Ets, EtsClient};
use rusoto_s3::{CreateBucketRequest, DeleteBucketRequest, S3Client, S3};

const AWS_ETS_WEB_PRESET_ID: &'static str = "1351620000001-100070";
const AWS_ETS_WEB_PRESET_NAME: &'static str = "System preset: Web";
const AWS_REGION: Region = Region::UsEast1;
const AWS_SERVICE_RANDOM_SUFFIX_LENGTH: usize = 20;

struct TestEtsClient {
    region: Region,

    client: EtsClient,

    s3_client: Option<S3Client>,
    input_bucket: Option<String>,
    output_bucket: Option<String>,
}

impl TestEtsClient {
    /// Creates a new `EtsClient` for a test.
    fn new(region: Region) -> TestEtsClient {
        TestEtsClient {
            region: region.clone(),
            client: EtsClient::new(region),
            s3_client: None,
            input_bucket: None,
            output_bucket: None,
        }
    }

    fn create_s3_client(&mut self) {
        self.s3_client = Some(S3Client::new(self.region.clone()));
    }

    async fn create_bucket(&mut self) -> String {
        let bucket_name = generate_unique_name("ets-bucket-1").await;

        let create_bucket_req = CreateBucketRequest {
            bucket: bucket_name.to_owned(),
            ..Default::default()
        };

        let result = self
            .s3_client
            .as_ref()
            .unwrap()
            .create_bucket(create_bucket_req)
            .await;

        let mut location = result.unwrap().location.unwrap();
        // A `Location` is identical to a `BucketName` except that it has a
        // forward slash prepended to it, so we need to remove it.
        location.remove(0);
        info!("Created S3 bucket: {}", location);
        location
    }
}

impl Deref for TestEtsClient {
    type Target = EtsClient;
    fn deref(&self) -> &Self::Target {
        &self.client
    }
}

impl DerefMut for TestEtsClient {
    fn deref_mut<'a>(&'a mut self) -> &'a mut EtsClient {
        &mut self.client
    }
}

impl Drop for TestEtsClient {
    fn drop(&mut self) {
        let mut rt = tokio::runtime::Runtime::new().unwrap();
        let s3_client = self.s3_client.take().unwrap();
        let input_bucket = self.input_bucket.take().unwrap();

        let delete_bucket_req = DeleteBucketRequest {
            bucket: input_bucket.to_owned(),
            ..Default::default()
        };

        rt.block_on(async {
                match s3_client.delete_bucket(delete_bucket_req).await {
                    Ok(_) => info!("Deleted S3 bucket: {}", input_bucket),
                    Err(e) => error!("Failed to delete S3 bucket: {}", e),
                };
            });

        let output_bucket = self.output_bucket.take().unwrap();
        let delete_bucket_req = DeleteBucketRequest {
            bucket: output_bucket.to_owned(),
            ..Default::default()
        };

        rt.block_on(async {
                match s3_client.delete_bucket(delete_bucket_req).await {
                    Ok(_) => info!("Deleted S3 bucket: {}", output_bucket),
                    Err(e) => error!("Failed to delete S3 bucket: {}", e),
                };
            });
    }
}

// TODO: once Rust has proper support for testing frameworks, this code will
// need to be refactored so that it is only called once, instead of per test
// case.
async fn initialize() {
    let _ = env_logger::try_init();
}

async fn create_client() -> TestEtsClient {
    TestEtsClient::new(AWS_REGION)
}

/// Generates a random name for an AWS service by appending a random sequence of
/// ASCII characters to the specified prefix.
/// Keeps it lower case to work with S3 requirements as of 3/1/2018.
async fn generate_unique_name(prefix: &str) -> String {
    let mut rng = rand::thread_rng();
    format!(
        "{}-{}",
        prefix,
        std::iter::repeat(())
            .map(|()| rng.sample(Alphanumeric))
            .take(AWS_SERVICE_RANDOM_SUFFIX_LENGTH)
            .collect::<String>()
    )
    .to_lowercase()
}

#[tokio::test]
#[should_panic(expected = "Role cannot be blank")]
async fn create_pipeline_without_arn() {
    use rusoto_elastictranscoder::CreatePipelineRequest;

    initialize().await;

    let mut client = create_client().await;
    client.create_s3_client();
    client.input_bucket = Some(client.create_bucket().await);
    client.output_bucket = Some(client.create_bucket().await);

    let request = CreatePipelineRequest {
        input_bucket: client.input_bucket.as_ref().cloned().unwrap(),
        output_bucket: client.output_bucket.as_ref().cloned(),
        ..CreatePipelineRequest::default()
    };
    let response = client.create_pipeline(request).await;

    response.unwrap();
}

#[tokio::test]
async fn create_preset() {
    use rusoto_elastictranscoder::{
        AudioCodecOptions, AudioParameters, CreatePresetRequest, DeletePresetRequest,
    };

    initialize().await;

    let client = create_client().await;

    let name = generate_unique_name("ets-preset-1").await;
    let request = CreatePresetRequest {
        audio: Some(AudioParameters {
            channels: Some("2".to_owned()),
            codec: Some("flac".to_owned()),
            codec_options: Some(AudioCodecOptions {
                bit_depth: Some("24".to_owned()),
                ..AudioCodecOptions::default()
            }),
            sample_rate: Some("96000".to_owned()),
            ..AudioParameters::default()
        }),
        container: "flac".to_owned(),
        description: Some("This is an example FLAC preset".to_owned()),
        name: name.clone(),
        ..CreatePresetRequest::default()
    };
    let response = client.create_preset(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    assert!(response.preset.is_some());

    let preset = response.preset.unwrap();

    assert_eq!(preset.container, Some("flac".to_owned()));
    assert_eq!(
        preset.description,
        Some("This is an example FLAC preset".to_owned())
    );
    assert_eq!(preset.name, Some(name));
    assert!(preset.id.is_some());

    let id = preset.id.unwrap();

    info!("Created preset with id: {:?}", &id);

    // Cleanup

    let request = DeletePresetRequest { id: id };
    client.delete_preset(request).await.ok();
}

#[tokio::test]
async fn delete_preset() {
    use rusoto_elastictranscoder::{
        AudioCodecOptions, AudioParameters, CreatePresetRequest, DeletePresetRequest,
    };

    initialize().await;

    let client = create_client().await;

    let name = generate_unique_name("ets-preset-1");
    let request = CreatePresetRequest {
        audio: Some(AudioParameters {
            channels: Some("2".to_owned()),
            codec: Some("flac".to_owned()),
            codec_options: Some(AudioCodecOptions {
                bit_depth: Some("24".to_owned()),
                ..AudioCodecOptions::default()
            }),
            sample_rate: Some("96000".to_owned()),
            ..AudioParameters::default()
        }),
        container: "flac".to_owned(),
        description: Some("This is an example FLAC preset".to_owned()),
        name: name.await.clone(),
        ..CreatePresetRequest::default()
    };
    let response = client.create_preset(request).await.unwrap();
    let preset = response.preset.unwrap();
    let id = preset.id.unwrap();

    let request = DeletePresetRequest { id: id.clone() };
    let response = client.delete_preset(request).await;

    assert!(response.is_ok());
    info!("Deleted preset with id: {:?}", &id);
}

#[tokio::test]
async fn list_jobs_by_status() {
    use rusoto_elastictranscoder::ListJobsByStatusRequest;

    initialize().await;

    let client = create_client().await;

    let status = "Submitted".to_owned();
    let request = ListJobsByStatusRequest {
        status: status.clone(),
        ..ListJobsByStatusRequest::default()
    };
    let response = client.list_jobs_by_status(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    info!(
        "Got list of jobs with status \"{}\": {:?}",
        &status, response.jobs
    );
}

#[tokio::test]
async fn list_pipelines() {
    use rusoto_elastictranscoder::ListPipelinesRequest;

    initialize().await;

    let client = create_client().await;

    let request = ListPipelinesRequest::default();
    let response = client.list_pipelines(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    info!("Got list of pipelines: {:?}", response.pipelines);
}

#[tokio::test]
async fn list_presets() {
    use rusoto_elastictranscoder::ListPresetsRequest;

    initialize().await;
    let client = create_client().await;

    let request = ListPresetsRequest::default();
    let response = client.list_presets(request).await;
    assert!(response.is_ok());

    let response = response.unwrap();
    assert!(response.presets.is_some());

    let presets = response.presets.unwrap();
    info!("Got list of presets.");
    for preset in presets.iter() {
        info!("Preset: {:?}", preset.name);
    }

    let web_preset = presets
        .iter()
        .filter(|x| x.id == Some(AWS_ETS_WEB_PRESET_ID.to_owned()))
        .next();

    let found_preset = match web_preset {
        Some(w) => w.clone(),
        None => {
            // get the next page
            assert!(response.next_page_token.is_some());
            let page_two_request = ListPresetsRequest {
                page_token: response.next_page_token,
                ..Default::default()
            };

            let page_two_response = client.list_presets(page_two_request).await.unwrap();
            let presets_pg_2 = page_two_response.presets.unwrap();
            let web_preset = presets_pg_2
                .iter()
                .filter(|x| x.id == Some(AWS_ETS_WEB_PRESET_ID.to_owned()))
                .next();
            web_preset.unwrap().clone()
        }
    };

    assert_eq!(found_preset.id, Some(AWS_ETS_WEB_PRESET_ID.to_owned()));
    assert_eq!(found_preset.name, Some(AWS_ETS_WEB_PRESET_NAME.to_owned()));
}

#[tokio::test]
async fn read_preset() {
    use rusoto_elastictranscoder::ReadPresetRequest;

    initialize().await;

    let client = create_client().await;

    let request = ReadPresetRequest {
        id: AWS_ETS_WEB_PRESET_ID.to_owned(),
    };
    let response = client.read_preset(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    assert!(response.preset.is_some());

    let preset = response.preset.unwrap();
    info!("Got preset: {:?}", preset.name);

    assert_eq!(preset.id, Some(AWS_ETS_WEB_PRESET_ID.to_owned()));
    assert_eq!(preset.name, Some(AWS_ETS_WEB_PRESET_NAME.to_owned()));
}
<commit_msg>Remove Drop for TestEtsClient<commit_after>#![cfg(all(feature = "elastictranscoder", feature = "s3"))]

extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rusoto_core;
extern crate rusoto_elastictranscoder;
extern crate rusoto_s3;

use std::clone::Clone;
use std::ops::{Deref, DerefMut};

use rand::distributions::Alphanumeric;
use rand::Rng;
use rusoto_core::Region;
use rusoto_elastictranscoder::{Ets, EtsClient};
use rusoto_s3::{CreateBucketRequest, DeleteBucketRequest, S3Client, S3};

const AWS_ETS_WEB_PRESET_ID: &'static str = "1351620000001-100070";
const AWS_ETS_WEB_PRESET_NAME: &'static str = "System preset: Web";
const AWS_REGION: Region = Region::UsEast1;
const AWS_SERVICE_RANDOM_SUFFIX_LENGTH: usize = 20;

struct TestEtsClient {
    region: Region,

    client: EtsClient,
}

impl TestEtsClient {
    /// Creates a new `EtsClient` for a test.
    fn new(region: Region) -> TestEtsClient {
        TestEtsClient {
            region: region.clone(),
            client: EtsClient::new(region),
        }
    }

    fn create_s3_client(&self) -> S3Client {
        S3Client::new(self.region.clone())
    }

    async fn create_bucket(&mut self, s3_client: &S3Client) -> String {
        let bucket_name = generate_unique_name("ets-bucket-1").await;

        let create_bucket_req = CreateBucketRequest {
            bucket: bucket_name.to_owned(),
            ..Default::default()
        };

        let result = s3_client.create_bucket(create_bucket_req).await;

        let mut location = result.unwrap().location.unwrap();
        // A `Location` is identical to a `BucketName` except that it has a
        // forward slash prepended to it, so we need to remove it.
        location.remove(0);
        info!("Created S3 bucket: {}", location);
        location
    }

    async fn delete_bucket(&mut self, s3_client: &S3Client, bucket: &str) {
        let delete_bucket_req = DeleteBucketRequest {
            bucket: bucket.to_owned(),
            ..Default::default()
        };
        s3_client.delete_bucket(delete_bucket_req).await.unwrap();
    }
}

impl Deref for TestEtsClient {
    type Target = EtsClient;
    fn deref(&self) -> &Self::Target {
        &self.client
    }
}

impl DerefMut for TestEtsClient {
    fn deref_mut<'a>(&'a mut self) -> &'a mut EtsClient {
        &mut self.client
    }
}

// TODO: once Rust has proper support for testing frameworks, this code will
// need to be refactored so that it is only called once, instead of per test
// case.
async fn initialize() {
    let _ = env_logger::try_init();
}

async fn create_client() -> TestEtsClient {
    TestEtsClient::new(AWS_REGION)
}

/// Generates a random name for an AWS service by appending a random sequence of
/// ASCII characters to the specified prefix.
/// Keeps it lower case to work with S3 requirements as of 3/1/2018.
async fn generate_unique_name(prefix: &str) -> String {
    let mut rng = rand::thread_rng();
    format!(
        "{}-{}",
        prefix,
        std::iter::repeat(())
            .map(|()| rng.sample(Alphanumeric))
            .take(AWS_SERVICE_RANDOM_SUFFIX_LENGTH)
            .collect::<String>()
    )
    .to_lowercase()
}

#[tokio::test]
#[should_panic(expected = "Role cannot be blank")]
async fn create_pipeline_without_arn() {
    use rusoto_elastictranscoder::CreatePipelineRequest;

    initialize().await;

    let mut client = create_client().await;
    let s3_client = client.create_s3_client();
    let input_bucket = client.create_bucket(&s3_client).await;
    let output_bucket = client.create_bucket(&s3_client).await;

    let request = CreatePipelineRequest {
        input_bucket: input_bucket.clone(),
        output_bucket: Some(output_bucket.clone()),
        ..CreatePipelineRequest::default()
    };
    client.create_pipeline(request).await.unwrap();

    client.delete_bucket(&s3_client, &input_bucket).await;
    client.delete_bucket(&s3_client, &output_bucket).await;
}

#[tokio::test]
async fn create_preset() {
    use rusoto_elastictranscoder::{
        AudioCodecOptions, AudioParameters, CreatePresetRequest, DeletePresetRequest,
    };

    initialize().await;

    let client = create_client().await;

    let name = generate_unique_name("ets-preset-1").await;
    let request = CreatePresetRequest {
        audio: Some(AudioParameters {
            channels: Some("2".to_owned()),
            codec: Some("flac".to_owned()),
            codec_options: Some(AudioCodecOptions {
                bit_depth: Some("24".to_owned()),
                ..AudioCodecOptions::default()
            }),
            sample_rate: Some("96000".to_owned()),
            ..AudioParameters::default()
        }),
        container: "flac".to_owned(),
        description: Some("This is an example FLAC preset".to_owned()),
        name: name.clone(),
        ..CreatePresetRequest::default()
    };
    let response = client.create_preset(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    assert!(response.preset.is_some());

    let preset = response.preset.unwrap();

    assert_eq!(preset.container, Some("flac".to_owned()));
    assert_eq!(
        preset.description,
        Some("This is an example FLAC preset".to_owned())
    );
    assert_eq!(preset.name, Some(name));
    assert!(preset.id.is_some());

    let id = preset.id.unwrap();

    info!("Created preset with id: {:?}", &id);

    // Cleanup

    let request = DeletePresetRequest { id: id };
    client.delete_preset(request).await.ok();
}

#[tokio::test]
async fn delete_preset() {
    use rusoto_elastictranscoder::{
        AudioCodecOptions, AudioParameters, CreatePresetRequest, DeletePresetRequest,
    };

    initialize().await;

    let client = create_client().await;

    let name = generate_unique_name("ets-preset-1");
    let request = CreatePresetRequest {
        audio: Some(AudioParameters {
            channels: Some("2".to_owned()),
            codec: Some("flac".to_owned()),
            codec_options: Some(AudioCodecOptions {
                bit_depth: Some("24".to_owned()),
                ..AudioCodecOptions::default()
            }),
            sample_rate: Some("96000".to_owned()),
            ..AudioParameters::default()
        }),
        container: "flac".to_owned(),
        description: Some("This is an example FLAC preset".to_owned()),
        name: name.await.clone(),
        ..CreatePresetRequest::default()
    };
    let response = client.create_preset(request).await.unwrap();
    let preset = response.preset.unwrap();
    let id = preset.id.unwrap();

    let request = DeletePresetRequest { id: id.clone() };
    let response = client.delete_preset(request).await;

    assert!(response.is_ok());
    info!("Deleted preset with id: {:?}", &id);
}

#[tokio::test]
async fn list_jobs_by_status() {
    use rusoto_elastictranscoder::ListJobsByStatusRequest;

    initialize().await;

    let client = create_client().await;

    let status = "Submitted".to_owned();
    let request = ListJobsByStatusRequest {
        status: status.clone(),
        ..ListJobsByStatusRequest::default()
    };
    let response = client.list_jobs_by_status(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    info!(
        "Got list of jobs with status \"{}\": {:?}",
        &status, response.jobs
    );
}

#[tokio::test]
async fn list_pipelines() {
    use rusoto_elastictranscoder::ListPipelinesRequest;

    initialize().await;

    let client = create_client().await;

    let request = ListPipelinesRequest::default();
    let response = client.list_pipelines(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    info!("Got list of pipelines: {:?}", response.pipelines);
}

#[tokio::test]
async fn list_presets() {
    use rusoto_elastictranscoder::ListPresetsRequest;

    initialize().await;
    let client = create_client().await;

    let request = ListPresetsRequest::default();
    let response = client.list_presets(request).await;
    assert!(response.is_ok());

    let response = response.unwrap();
    assert!(response.presets.is_some());

    let presets = response.presets.unwrap();
    info!("Got list of presets.");
    for preset in presets.iter() {
        info!("Preset: {:?}", preset.name);
    }

    let web_preset = presets
        .iter()
        .filter(|x| x.id == Some(AWS_ETS_WEB_PRESET_ID.to_owned()))
        .next();

    let found_preset = match web_preset {
        Some(w) => w.clone(),
        None => {
            // get the next page
            assert!(response.next_page_token.is_some());
            let page_two_request = ListPresetsRequest {
                page_token: response.next_page_token,
                ..Default::default()
            };

            let page_two_response = client.list_presets(page_two_request).await.unwrap();
            let presets_pg_2 = page_two_response.presets.unwrap();
            let web_preset = presets_pg_2
                .iter()
                .filter(|x| x.id == Some(AWS_ETS_WEB_PRESET_ID.to_owned()))
                .next();
            web_preset.unwrap().clone()
        }
    };

    assert_eq!(found_preset.id, Some(AWS_ETS_WEB_PRESET_ID.to_owned()));
    assert_eq!(found_preset.name, Some(AWS_ETS_WEB_PRESET_NAME.to_owned()));
}

#[tokio::test]
async fn read_preset() {
    use rusoto_elastictranscoder::ReadPresetRequest;

    initialize().await;

    let client = create_client().await;

    let request = ReadPresetRequest {
        id: AWS_ETS_WEB_PRESET_ID.to_owned(),
    };
    let response = client.read_preset(request).await;

    assert!(response.is_ok());

    let response = response.unwrap();

    assert!(response.preset.is_some());

    let preset = response.preset.unwrap();
    info!("Got preset: {:?}", preset.name);

    assert_eq!(preset.id, Some(AWS_ETS_WEB_PRESET_ID.to_owned()));
    assert_eq!(preset.name, Some(AWS_ETS_WEB_PRESET_NAME.to_owned()));
}
<|endoftext|>


<commit_before>extern crate nalgebra;
extern crate num;

use num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use std::ops::Range;

use clamp::{Clamped, ClampedRange};
use math::{Mask, UPoint3, UScalar, UVector3};

pub struct LogWidthRange;

impl ClampedRange<u8> for LogWidthRange {
    fn max_value() -> u8 {
        31
    }

    fn min_value() -> u8 {
        4
    }
}

pub type LogWidth = Clamped<u8, LogWidthRange>;

impl LogWidth {
    pub fn exp(&self) -> UScalar {
        UScalar::one() << self.to_inner()
    }
}

#[derive(Clone, Copy)]
pub enum Axis {
    X = 0,
    Y = 1,
    Z = 2,
}

impl Axis {
    pub fn range() -> Range<usize> {
        (Axis::X as usize)..(Axis::Z as usize + 1)
    }
}

impl From<usize> for Axis {
    fn from(index: usize) -> Self {
        match index {
            0 => Axis::X,
            1 => Axis::Y,
            2 => Axis::Z,
            _ => panic!() // TODO: Use `TryFrom`.
        }
    }
}

pub enum Direction {
    Positive,
    Negative,
}

pub enum Orientation {
    Left,
    Right,
    Top,
    Bottom,
    Front,
    Back,
}

impl Orientation {
    pub fn axis(&self) -> Axis {
        match *self {
            Orientation::Left | Orientation::Right => Axis::X,
            Orientation::Top | Orientation::Bottom => Axis::Y,
            Orientation::Front | Orientation::Back => Axis::Z,
        }
    }

    pub fn direction(&self) -> Direction {
        match *self {
            Orientation::Left | Orientation::Top | Orientation::Front => Direction::Positive,
            Orientation::Right | Orientation::Bottom | Orientation::Back => Direction::Negative,
        }
    }
}

pub struct AABB {
    pub origin: UPoint3,
    pub extent: UVector3,
}

impl AABB {
    pub fn new(origin: UPoint3, extent: UVector3) -> Self {
        AABB {
            origin: origin,
            extent: extent,
        }
    }

    pub fn intersects(&self, other: &Self) -> bool {
        for axis in Axis::range() {
            if (self.origin[axis] + self.extent[axis]) < other.origin[axis] {
                return false;
            }
            if self.origin[axis] > (other.origin[axis] + other.extent[axis]) {
                return false;
            }
        }
        true
    }
}

/// A cubic spatial partition in the `UScalar` space. `Partition`s are
/// represented as an origin and a width.
#[derive(Clone, Copy)]
pub struct Partition {
    origin: UPoint3,
    width: LogWidth,
}

impl Partition {
    /// Constructs a `Partition` at the given point in space with the given
    /// width.
    pub fn at_point(point: &UPoint3, width: LogWidth) -> Self {
        Partition {
            origin: point.mask(!UScalar::zero() << *width),
            width: width,
        }
    }

    /// Constructs the sub-`Partition` at the given index. Returns `None` if
    /// there is no such `Partition`, because the minimum width has been
    /// exceeded.
    ///
    /// # Panics
    ///
    /// Panics if `index` is not within the range [0, 8).
    pub fn at_index(&self, index: usize) -> Option<Self> {
        if self.is_min_width() {
            None
        }
        else {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        }
    }

    /// Gets the origin of the `Partition`.
    pub fn origin(&self) -> &UPoint3 {
        &self.origin
    }

    /// Gets the width of the `Partition`.
    pub fn width(&self) -> LogWidth {
        self.width
    }

    /// Gets the midpoint of the `Partition`.
    pub fn midpoint(&self) -> UPoint3 {
        let m = (self.width - 1).exp();
        self.origin + UVector3::new(m, m, m)
    }

    pub fn extent(&self) -> UVector3 {
        (UVector3::one() * self.width.exp()) - UVector3::one()
    }

    pub fn aabb(&self) -> AABB {
        AABB::new(self.origin, self.extent())
    }

    /// Returns `true` if the `Partition` has the minimum possible width.
    pub fn is_min_width(&self) -> bool {
        self.width == LogWidth::min_value()
    }
}

pub trait Spatial {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;

    fn aabb(&self) -> AABB {
        self.partition().aabb()
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
pub fn index_at_point(point: &UPoint3, width: LogWidth) -> usize {
    let width = width.to_inner();
    ((((point.x >> width) & UScalar::one()) << 0) |
     (((point.y >> width) & UScalar::one()) << 1) |
     (((point.z >> width) & UScalar::one()) << 2)) as usize
}

pub fn vector_at_index(index: usize, width: LogWidth) -> UVector3 {
    assert!(index < 8);
    let index = index as UScalar;
    let width = width.exp();
    UVector3::new(((index >> 0) & UScalar::one()) * width,
                  ((index >> 1) & UScalar::one()) * width,
                  ((index >> 2) & UScalar::one()) * width)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Use `to_inner` (for consistency).<commit_after>extern crate nalgebra;
extern crate num;

use num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use std::ops::Range;

use clamp::{Clamped, ClampedRange};
use math::{Mask, UPoint3, UScalar, UVector3};

pub struct LogWidthRange;

impl ClampedRange<u8> for LogWidthRange {
    fn max_value() -> u8 {
        31
    }

    fn min_value() -> u8 {
        4
    }
}

pub type LogWidth = Clamped<u8, LogWidthRange>;

impl LogWidth {
    pub fn exp(&self) -> UScalar {
        UScalar::one() << self.to_inner()
    }
}

#[derive(Clone, Copy)]
pub enum Axis {
    X = 0,
    Y = 1,
    Z = 2,
}

impl Axis {
    pub fn range() -> Range<usize> {
        (Axis::X as usize)..(Axis::Z as usize + 1)
    }
}

impl From<usize> for Axis {
    fn from(index: usize) -> Self {
        match index {
            0 => Axis::X,
            1 => Axis::Y,
            2 => Axis::Z,
            _ => panic!() // TODO: Use `TryFrom`.
        }
    }
}

pub enum Direction {
    Positive,
    Negative,
}

pub enum Orientation {
    Left,
    Right,
    Top,
    Bottom,
    Front,
    Back,
}

impl Orientation {
    pub fn axis(&self) -> Axis {
        match *self {
            Orientation::Left | Orientation::Right => Axis::X,
            Orientation::Top | Orientation::Bottom => Axis::Y,
            Orientation::Front | Orientation::Back => Axis::Z,
        }
    }

    pub fn direction(&self) -> Direction {
        match *self {
            Orientation::Left | Orientation::Top | Orientation::Front => Direction::Positive,
            Orientation::Right | Orientation::Bottom | Orientation::Back => Direction::Negative,
        }
    }
}

pub struct AABB {
    pub origin: UPoint3,
    pub extent: UVector3,
}

impl AABB {
    pub fn new(origin: UPoint3, extent: UVector3) -> Self {
        AABB {
            origin: origin,
            extent: extent,
        }
    }

    pub fn intersects(&self, other: &Self) -> bool {
        for axis in Axis::range() {
            if (self.origin[axis] + self.extent[axis]) < other.origin[axis] {
                return false;
            }
            if self.origin[axis] > (other.origin[axis] + other.extent[axis]) {
                return false;
            }
        }
        true
    }
}

/// A cubic spatial partition in the `UScalar` space. `Partition`s are
/// represented as an origin and a width.
#[derive(Clone, Copy)]
pub struct Partition {
    origin: UPoint3,
    width: LogWidth,
}

impl Partition {
    /// Constructs a `Partition` at the given point in space with the given
    /// width.
    pub fn at_point(point: &UPoint3, width: LogWidth) -> Self {
        Partition {
            origin: point.mask(!UScalar::zero() << width.to_inner()),
            width: width,
        }
    }

    /// Constructs the sub-`Partition` at the given index. Returns `None` if
    /// there is no such `Partition`, because the minimum width has been
    /// exceeded.
    ///
    /// # Panics
    ///
    /// Panics if `index` is not within the range [0, 8).
    pub fn at_index(&self, index: usize) -> Option<Self> {
        if self.is_min_width() {
            None
        }
        else {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        }
    }

    /// Gets the origin of the `Partition`.
    pub fn origin(&self) -> &UPoint3 {
        &self.origin
    }

    /// Gets the width of the `Partition`.
    pub fn width(&self) -> LogWidth {
        self.width
    }

    /// Gets the midpoint of the `Partition`.
    pub fn midpoint(&self) -> UPoint3 {
        let m = (self.width - 1).exp();
        self.origin + UVector3::new(m, m, m)
    }

    pub fn extent(&self) -> UVector3 {
        (UVector3::one() * self.width.exp()) - UVector3::one()
    }

    pub fn aabb(&self) -> AABB {
        AABB::new(self.origin, self.extent())
    }

    /// Returns `true` if the `Partition` has the minimum possible width.
    pub fn is_min_width(&self) -> bool {
        self.width == LogWidth::min_value()
    }
}

pub trait Spatial {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;

    fn aabb(&self) -> AABB {
        self.partition().aabb()
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
pub fn index_at_point(point: &UPoint3, width: LogWidth) -> usize {
    let width = width.to_inner();
    ((((point.x >> width) & UScalar::one()) << 0) |
     (((point.y >> width) & UScalar::one()) << 1) |
     (((point.z >> width) & UScalar::one()) << 2)) as usize
}

pub fn vector_at_index(index: usize, width: LogWidth) -> UVector3 {
    assert!(index < 8);
    let index = index as UScalar;
    let width = width.exp();
    UVector3::new(((index >> 0) & UScalar::one()) * width,
                  ((index >> 1) & UScalar::one()) * width,
                  ((index >> 2) & UScalar::one()) * width)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>use commands::{Command, CommandExecutor};
use std::error;
use std::sync::Arc;

pub struct AnoncredsAPI {
    command_executor: Arc<CommandExecutor>,
}

impl AnoncredsAPI {
    pub fn new(command_executor: Arc<CommandExecutor>) -> AnoncredsAPI {
        AnoncredsAPI { command_executor: command_executor }
    }

    pub fn create_master_secret(cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn create_keys(schema: String,
                       cb: Box<Fn(Result<((String, String)), Box<error::Error>>) + Send>) {

    }

    pub fn create_context_attribute(i_a: String, user_id: String,
                                    cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn issue_accumulator(schema: String, i_a: String, l: String,
                             public_key_revocation: String,
                             cb: Box<Fn(
                                 Result<((String, String, String, String)),
                                     Box<error::Error>>
                             ) + Send>) {

    }

    pub fn issue_claim(attributes: String, accumulator: String,i_a: String, i: String,
                       claim_request: String, context_attribute: String, public_key: String,
                       secret_key: String, public_key_revocation: String,
                       secret_key_revocation: String, tails: String,
                       secret_key_accumulator: String,
                       cb: Box<Fn(Result<(String, String), Box<error::Error>>) + Send>) {

    }

    pub fn create_claim_request(master_secret: String, public_key: String,
                                public_key_revocation: String, request_non_revocation: String,
                                cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn create_proof(proof_input: String, nonce: String, claims: String,
                        public_key_revocation: String, accum: String, public_key: String,
                        master_secret: String,
                        cb: Box<Fn(Result<(String, String), Box<error::Error>>) + Send>) {

    }

    pub fn verify_proof(proof_input: String, proof: String, revealed_attributes: String,
                        nonce: String, public_key_revocation: String,
                        public_key_accumulator: String, accumulator: String,
                        public_key: String, attributes: String,
                        cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }
}

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

    #[test]
    fn anoncreds_api_can_be_created() {
        let anoncreds_api = AnoncredsAPI::new(Arc::new(CommandExecutor::new()));
        assert! (true, "No crashes on AnoncredsAPI::new");
    }

    #[test]
    fn anoncredsn_api_can_be_dropped() {
        fn drop_test() {
            let anoncreds_api = AnoncredsAPI::new(Arc::new(CommandExecutor::new()));
        }

        drop_test();
        assert! (true, "No crashes on AnoncredsAPI::drop");
    }
}<commit_msg>changed errors<commit_after>use commands::{Command, CommandExecutor};
use std::error;
use std::sync::Arc;
use errors::anoncreds::AnoncredsError;

pub struct AnoncredsAPI {
    command_executor: Arc<CommandExecutor>,
}

impl AnoncredsAPI {
    pub fn new(command_executor: Arc<CommandExecutor>) -> AnoncredsAPI {
        AnoncredsAPI { command_executor: command_executor }
    }

    pub fn create_master_secret(cb: Box<Fn(Result<(String), AnoncredsError>) + Send>) {

    }

    pub fn create_keys(schema: String,
                       cb: Box<Fn(Result<((String, String)), AnoncredsError>) + Send>) {

    }

    pub fn create_context_attribute(i_a: String, user_id: String,
                                    cb: Box<Fn(Result<(String), AnoncredsError>) + Send>) {

    }

    pub fn issue_accumulator(schema: String, i_a: String, l: String,
                             public_key_revocation: String,
                             cb: Box<Fn(
                                 Result<((String, String, String, String)),
                                     AnoncredsError>
                             ) + Send>) {

    }

    pub fn issue_claim(attributes: String, accumulator: String,i_a: String, i: String,
                       claim_request: String, context_attribute: String, public_key: String,
                       secret_key: String, public_key_revocation: String,
                       secret_key_revocation: String, tails: String,
                       secret_key_accumulator: String,
                       cb: Box<Fn(Result<(String, String), AnoncredsError>) + Send>) {

    }

    pub fn create_claim_request(master_secret: String, public_key: String,
                                public_key_revocation: String, request_non_revocation: String,
                                cb: Box<Fn(Result<(String), AnoncredsError>) + Send>) {

    }

    pub fn create_proof(proof_input: String, nonce: String, claims: String,
                        public_key_revocation: String, accum: String, public_key: String,
                        master_secret: String,
                        cb: Box<Fn(Result<(String, String), AnoncredsError>) + Send>) {

    }

    pub fn verify_proof(proof_input: String, proof: String, revealed_attributes: String,
                        nonce: String, public_key_revocation: String,
                        public_key_accumulator: String, accumulator: String,
                        public_key: String, attributes: String,
                        cb: Box<Fn(Result<(String), AnoncredsError>) + Send>) {

    }
}

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

    #[test]
    fn anoncreds_api_can_be_created() {
        let anoncreds_api = AnoncredsAPI::new(Arc::new(CommandExecutor::new()));
        assert! (true, "No crashes on AnoncredsAPI::new");
    }

    #[test]
    fn anoncredsn_api_can_be_dropped() {
        fn drop_test() {
            let anoncreds_api = AnoncredsAPI::new(Arc::new(CommandExecutor::new()));
        }

        drop_test();
        assert! (true, "No crashes on AnoncredsAPI::drop");
    }
}<|endoftext|>