<commit_before>use columnvalueops::{ColumnValueOps, ColumnValueOpsExt};
use super::super::sexpression::AggregateOp;

pub trait AggregateFunction<ColumnValue> {
    fn feed(&mut self, value: ColumnValue);
    fn finish(self: Box<Self>) -> ColumnValue;
}

struct Count {
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Count
{
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        ColumnValueOps::from_u64(self.count)
    }
}

struct Avg {
    sum: f64,
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Avg {
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.sum += value.to_f64().unwrap();
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        if self.count == 0 {
            ColumnValueOpsExt::null()
        } else {
            ColumnValueOps::from_f64(self.sum / (self.count as f64))
        }
    }
}

struct Sum {
    sum: f64,
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Sum {
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.sum += value.to_f64().unwrap();
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        if self.count == 0 {
            ColumnValueOpsExt::null()
        } else {
            ColumnValueOps::from_f64(self.sum)
        }
    }
}

pub fn get_aggregate_function<ColumnValue>(op: AggregateOp) -> Box<AggregateFunction<ColumnValue> + 'static>
where ColumnValue: Sized + ColumnValueOps + 'static
{
    match op {
        AggregateOp::Count => Box::new(Count { count: 0 }),
        AggregateOp::Avg => Box::new(Avg { sum: 0.0, count: 0 }),
        AggregateOp::Sum => Box::new(Sum { sum: 0.0, count: 0 }),
        AggregateOp::Min => unimplemented!(),
        AggregateOp::Max => unimplemented!()
    }
}
<commit_msg>Add MIN, MAX aggregate functions<commit_after>use columnvalueops::{ColumnValueOps, ColumnValueOpsExt};
use super::super::sexpression::AggregateOp;

pub trait AggregateFunction<ColumnValue> {
    fn feed(&mut self, value: ColumnValue);
    fn finish(self: Box<Self>) -> ColumnValue;
}

struct Count {
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Count
{
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        ColumnValueOps::from_u64(self.count)
    }
}

struct Avg {
    sum: f64,
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Avg {
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.sum += value.to_f64().unwrap();
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        if self.count == 0 {
            ColumnValueOpsExt::null()
        } else {
            ColumnValueOps::from_f64(self.sum / (self.count as f64))
        }
    }
}

struct Sum {
    sum: f64,
    count: u64
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Sum {
    fn feed(&mut self, value: ColumnValue) {
        if !value.is_null() {
            self.sum += value.to_f64().unwrap();
            self.count += 1;
        }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        if self.count == 0 {
            ColumnValueOpsExt::null()
        } else {
            ColumnValueOps::from_f64(self.sum)
        }
    }
}

struct Min<ColumnValue> {
    value: Option<ColumnValue>
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Min<ColumnValue> {
    fn feed(&mut self, value: ColumnValue) {
        let set = !value.is_null() && if let Some(r) = self.value.as_ref() {
            match value.compare(r) {
                Some(-1) => true,
                _ => false
            }
        } else {
            true
        };

        if set { self.value = Some(value); }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        self.value.unwrap_or_else(|| ColumnValueOpsExt::null())
    }
}

struct Max<ColumnValue> {
    value: Option<ColumnValue>
}

impl<ColumnValue: ColumnValueOps> AggregateFunction<ColumnValue> for Max<ColumnValue> {
    fn feed(&mut self, value: ColumnValue) {
        let set = !value.is_null() && if let Some(r) = self.value.as_ref() {
            match value.compare(r) {
                Some(1) => true,
                _ => false
            }
        } else {
            true
        };

        if set { self.value = Some(value); }
    }

    fn finish(self: Box<Self>) -> ColumnValue {
        self.value.unwrap_or_else(|| ColumnValueOpsExt::null())
    }
}

pub fn get_aggregate_function<ColumnValue>(op: AggregateOp) -> Box<AggregateFunction<ColumnValue> + 'static>
where ColumnValue: Sized + ColumnValueOps + 'static
{
    match op {
        AggregateOp::Count => Box::new(Count { count: 0 }),
        AggregateOp::Avg => Box::new(Avg { sum: 0.0, count: 0 }),
        AggregateOp::Sum => Box::new(Sum { sum: 0.0, count: 0 }),
        AggregateOp::Min => Box::new(Min { value: None }),
        AggregateOp::Max => Box::new(Max { value: None })
    }
}
<|endoftext|>


<commit_before><commit_msg>Fixed macos<commit_after><|endoftext|>


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

//! Macro for implementing Structure for vertex and constant buffers.

#[macro_export]
macro_rules! gfx_impl_struct {
    ($runtime_format:ty : $compile_format:path = $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta! {
        impl_struct_meta $runtime_format : $compile_format = $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_impl_struct_meta {
    ($(#[$attr:meta])* impl_struct_meta $runtime_format:ty : $compile_format:path = $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => {
        #[allow(missing_docs)]
        #[derive(Clone, Copy, Debug)]
        $(#[$attr])*
        pub struct $root {
            $( pub $field: $ty, )*
        }

        unsafe impl $crate::traits::Pod for $root {}

        impl $crate::pso::buffer::Structure<$runtime_format> for $root {
            fn query(name: &str) -> Option<$crate::pso::buffer::Element<$runtime_format>> {
                use std::mem::size_of;
                use $crate::pso::buffer::{Element, ElemOffset};
                let tmp: &$root = unsafe{ ::std::mem::uninitialized() };
                let base = tmp as *const _ as usize;
                //HACK: special treatment of array queries
                let (sub_name, big_offset) = {
                    let mut split = name.split(|c| c == '[' || c == ']');
                    let _ = split.next().unwrap();
                    match split.next() {
                        Some(s) => {
                            let array_id: ElemOffset = s.parse().unwrap();
                            let sub_name = match split.next() {
                                Some(s) if s.starts_with('.') => &s[1..],
                                _ => name,
                            };
                            (sub_name, array_id * (size_of::<$root>() as ElemOffset))
                        },
                        None => (name, 0),
                    }
                };
                match sub_name {
                $(
                    $name => Some(Element {
                        format: <$ty as $compile_format>::get_format(),
                        offset: ((&tmp.$field as *const _ as usize) - base) as ElemOffset + big_offset,
                    }),
                )*
                    _ => None,
                }
            }
        }
    }
}

#[macro_export]
macro_rules! gfx_vertex_struct {
    ($root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_vertex_struct_meta! {
        vertex_struct_meta $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_vertex_struct_meta {
    ($(#[$attr:meta])* vertex_struct_meta $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta!{
        $(#[$attr])* impl_struct_meta
        $crate::format::Format : $crate::format::Formatted =
        $root {
            $( $field: $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_constant_struct {
    ($root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_constant_struct_meta!{
        constant_struct_meta $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_constant_struct_meta {
    ($(#[$attr:meta])* constant_struct_meta $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta!{
        $(#[$attr])* impl_struct_meta
        $crate::shade::ConstFormat : $crate::shade::Formatted =
        $root {
            $( $field: $ty = $name, )*
        }
    })
}
<commit_msg>Auto merge of #1189 - gfx-rs:kvark-query, r=kvark<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Macro for implementing Structure for vertex and constant buffers.

#[macro_export]
macro_rules! gfx_impl_struct {
    ($runtime_format:ty : $compile_format:path = $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta! {
        impl_struct_meta $runtime_format : $compile_format = $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_impl_struct_meta {
    ($(#[$attr:meta])* impl_struct_meta $runtime_format:ty : $compile_format:path = $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => {
        #[allow(missing_docs)]
        #[derive(Clone, Copy, Debug)]
        $(#[$attr])*
        pub struct $root {
            $( pub $field: $ty, )*
        }

        unsafe impl $crate::traits::Pod for $root {}

        impl $crate::pso::buffer::Structure<$runtime_format> for $root {
            fn query(name: &str) -> Option<$crate::pso::buffer::Element<$runtime_format>> {
                use std::mem::{size_of, transmute};
                use $crate::pso::buffer::{Element, ElemOffset};
                // using "1" here as a simple non-zero pointer addres
                let tmp: &$root = unsafe{ transmute(1usize) };
                let base = tmp as *const _ as usize;
                //HACK: special treatment of array queries
                let (sub_name, big_offset) = {
                    let mut split = name.split(|c| c == '[' || c == ']');
                    let _ = split.next().unwrap();
                    match split.next() {
                        Some(s) => {
                            let array_id: ElemOffset = s.parse().unwrap();
                            let sub_name = match split.next() {
                                Some(s) if s.starts_with('.') => &s[1..],
                                _ => name,
                            };
                            (sub_name, array_id * (size_of::<$root>() as ElemOffset))
                        },
                        None => (name, 0),
                    }
                };
                match sub_name {
                $(
                    $name => Some(Element {
                        format: <$ty as $compile_format>::get_format(),
                        offset: ((&tmp.$field as *const _ as usize) - base) as ElemOffset + big_offset,
                    }),
                )*
                    _ => None,
                }
            }
        }
    }
}

#[macro_export]
macro_rules! gfx_vertex_struct {
    ($root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_vertex_struct_meta! {
        vertex_struct_meta $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_vertex_struct_meta {
    ($(#[$attr:meta])* vertex_struct_meta $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta!{
        $(#[$attr])* impl_struct_meta
        $crate::format::Format : $crate::format::Formatted =
        $root {
            $( $field: $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_constant_struct {
    ($root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_constant_struct_meta!{
        constant_struct_meta $root {
            $( $field : $ty = $name, )*
        }
    })
}

#[macro_export]
macro_rules! gfx_constant_struct_meta {
    ($(#[$attr:meta])* constant_struct_meta $root:ident {
        $( $field:ident: $ty:ty = $name:expr, )*
    }) => (gfx_impl_struct_meta!{
        $(#[$attr])* impl_struct_meta
        $crate::shade::ConstFormat : $crate::shade::Formatted =
        $root {
            $( $field: $ty = $name, )*
        }
    })
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! # Code generator for Move script builders
//!
//! '''bash
//! cargo run -p aptos-sdk-builder -- --help
//! '''

use serde_generate as serdegen;
use serde_reflection::Registry;
use std::path::PathBuf;
use structopt::{clap::arg_enum, StructOpt};

arg_enum! {
#[derive(Debug, StructOpt)]
enum Language {
    Rust,
    Go,
}
}

#[derive(Debug, StructOpt)]
#[structopt(name = "Aptos SDK Builder", about = "Generate boilerplate Aptos SDKs")]
struct Options {
    /// Path to the directory containing ABI files in BCS encoding.
    abi_directories: Vec<PathBuf>,

    /// Language for code generation.
    #[structopt(long, possible_values = &Language::variants(), case_insensitive = true, default_value = "Python3")]
    language: Language,

    /// Directory where to write generated modules (otherwise print code on stdout).
    #[structopt(long)]
    target_source_dir: Option<PathBuf>,

    /// Also install the aptos types described by the given YAML file, along with the BCS runtime.
    #[structopt(long)]
    with_aptos_types: Option<PathBuf>,

    /// Module name for the transaction builders installed in the `target_source_dir`.
    /// * Rust crates may contain a version number, e.g. "test:1.2.0".
    /// * In Java, this is expected to be a package name, e.g. "com.test" to create Java files in `com/test`.
    /// * In Go, this is expected to be of the format "go_module/path/go_package_name",
    /// and `aptos_types` is assumed to be in "go_module/path/aptos_types".
    #[structopt(long)]
    module_name: Option<String>,

    /// Optional package name (Python) or module path (Go) of the Serde and BCS runtime dependencies.
    #[structopt(long)]
    serde_package_name: Option<String>,

    /// Optional version number for the `aptos_types` module (useful in Rust).
    /// If `--with-aptos-types` is passed, this will be the version of the generated `aptos_types` module.
    #[structopt(long, default_value = "0.1.0")]
    aptos_version_number: String,

    /// Optional package name (Python) or module path (Go) of the `aptos_types` dependency.
    #[structopt(long)]
    package_name: Option<String>,
}

fn main() {
    let options = Options::from_args();
    let abis = aptos_sdk_builder::read_abis(&options.abi_directories)
        .expect("Failed to read ABI in directory");

    let install_dir = match options.target_source_dir {
        None => {
            // Nothing to install. Just print to stdout.
            let stdout = std::io::stdout();
            let mut out = stdout.lock();
            match options.language {
                Language::Rust => {
                    aptos_sdk_builder::rust::output(&mut out, &abis, /* local types */ false)
                        .unwrap()
                }
                Language::Go => {
                    aptos_sdk_builder::golang::output(
                        &mut out,
                        options.serde_package_name.clone(),
                        options.package_name.clone(),
                        options.module_name.as_deref().unwrap_or("main").to_string(),
                        &abis,
                    )
                    .unwrap();
                }
            }
            return;
        }
        Some(dir) => dir,
    };

    // Aptos types
    if let Some(registry_file) = options.with_aptos_types {
        let installer: Box<dyn serdegen::SourceInstaller<Error = Box<dyn std::error::Error>>> =
            match options.language {
                Language::Rust => Box::new(serdegen::rust::Installer::new(install_dir.clone())),
                Language::Go => Box::new(serdegen::golang::Installer::new(
                    install_dir.clone(),
                    options.serde_package_name.clone(),
                )),
            };

        let content =
            std::fs::read_to_string(registry_file).expect("registry file must be readable");
        let mut registry = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
        // update the registry to prevent language keyword being used
        if let Language::Rust = options.language {
            aptos_sdk_builder::rust::replace_keywords(&mut registry)
        }

        let (package_name, _package_path) = match options.language {
            Language::Rust => (
                if options.aptos_version_number == "0.1.0" {
                    "aptos-types".to_string()
                } else {
                    format!("aptos-types:{}", options.aptos_version_number)
                },
                vec!["aptos-types"],
            ),
            Language::Go => ("aptostypes".to_string(), vec!["aptostypes"]),
        };

        let config = serdegen::CodeGeneratorConfig::new(package_name)
            .with_encodings(vec![serdegen::Encoding::Bcs]);

        installer.install_module(&config, &registry).unwrap();
    }

    // Transaction builders
    let installer: Box<dyn aptos_sdk_builder::SourceInstaller<Error = Box<dyn std::error::Error>>> =
        match options.language {
            Language::Rust => Box::new(aptos_sdk_builder::rust::Installer::new(
                install_dir,
                options.aptos_version_number,
            )),
            Language::Go => Box::new(aptos_sdk_builder::golang::Installer::new(
                install_dir,
                options.serde_package_name,
                options.package_name,
            )),
        };

    if let Some(name) = options.module_name {
        installer
            .install_transaction_builders(&name, abis.as_slice())
            .unwrap();
    }
}
<commit_msg>[sdk-builder] Fix default sdk builder language<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! # Code generator for Move script builders
//!
//! '''bash
//! cargo run -p aptos-sdk-builder -- --help
//! '''

use serde_generate as serdegen;
use serde_reflection::Registry;
use std::path::PathBuf;
use structopt::{clap::arg_enum, StructOpt};

arg_enum! {
#[derive(Debug, StructOpt)]
enum Language {
    Rust,
    Go,
}
}

#[derive(Debug, StructOpt)]
#[structopt(name = "Aptos SDK Builder", about = "Generate boilerplate Aptos SDKs")]
struct Options {
    /// Path to the directory containing ABI files in BCS encoding.
    abi_directories: Vec<PathBuf>,

    /// Language for code generation.
    #[structopt(long, possible_values = &Language::variants(), case_insensitive = true, default_value = "Rust")]
    language: Language,

    /// Directory where to write generated modules (otherwise print code on stdout).
    #[structopt(long)]
    target_source_dir: Option<PathBuf>,

    /// Also install the aptos types described by the given YAML file, along with the BCS runtime.
    #[structopt(long)]
    with_aptos_types: Option<PathBuf>,

    /// Module name for the transaction builders installed in the `target_source_dir`.
    /// * Rust crates may contain a version number, e.g. "test:1.2.0".
    /// * In Java, this is expected to be a package name, e.g. "com.test" to create Java files in `com/test`.
    /// * In Go, this is expected to be of the format "go_module/path/go_package_name",
    /// and `aptos_types` is assumed to be in "go_module/path/aptos_types".
    #[structopt(long)]
    module_name: Option<String>,

    /// Optional package name (Python) or module path (Go) of the Serde and BCS runtime dependencies.
    #[structopt(long)]
    serde_package_name: Option<String>,

    /// Optional version number for the `aptos_types` module (useful in Rust).
    /// If `--with-aptos-types` is passed, this will be the version of the generated `aptos_types` module.
    #[structopt(long, default_value = "0.1.0")]
    aptos_version_number: String,

    /// Optional package name (Python) or module path (Go) of the `aptos_types` dependency.
    #[structopt(long)]
    package_name: Option<String>,
}

fn main() {
    let options = Options::from_args();
    let abis = aptos_sdk_builder::read_abis(&options.abi_directories)
        .expect("Failed to read ABI in directory");

    let install_dir = match options.target_source_dir {
        None => {
            // Nothing to install. Just print to stdout.
            let stdout = std::io::stdout();
            let mut out = stdout.lock();
            match options.language {
                Language::Rust => {
                    aptos_sdk_builder::rust::output(&mut out, &abis, /* local types */ false)
                        .unwrap()
                }
                Language::Go => {
                    aptos_sdk_builder::golang::output(
                        &mut out,
                        options.serde_package_name.clone(),
                        options.package_name.clone(),
                        options.module_name.as_deref().unwrap_or("main").to_string(),
                        &abis,
                    )
                    .unwrap();
                }
            }
            return;
        }
        Some(dir) => dir,
    };

    // Aptos types
    if let Some(registry_file) = options.with_aptos_types {
        let installer: Box<dyn serdegen::SourceInstaller<Error = Box<dyn std::error::Error>>> =
            match options.language {
                Language::Rust => Box::new(serdegen::rust::Installer::new(install_dir.clone())),
                Language::Go => Box::new(serdegen::golang::Installer::new(
                    install_dir.clone(),
                    options.serde_package_name.clone(),
                )),
            };

        let content =
            std::fs::read_to_string(registry_file).expect("registry file must be readable");
        let mut registry = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
        // update the registry to prevent language keyword being used
        if let Language::Rust = options.language {
            aptos_sdk_builder::rust::replace_keywords(&mut registry)
        }

        let (package_name, _package_path) = match options.language {
            Language::Rust => (
                if options.aptos_version_number == "0.1.0" {
                    "aptos-types".to_string()
                } else {
                    format!("aptos-types:{}", options.aptos_version_number)
                },
                vec!["aptos-types"],
            ),
            Language::Go => ("aptostypes".to_string(), vec!["aptostypes"]),
        };

        let config = serdegen::CodeGeneratorConfig::new(package_name)
            .with_encodings(vec![serdegen::Encoding::Bcs]);

        installer.install_module(&config, &registry).unwrap();
    }

    // Transaction builders
    let installer: Box<dyn aptos_sdk_builder::SourceInstaller<Error = Box<dyn std::error::Error>>> =
        match options.language {
            Language::Rust => Box::new(aptos_sdk_builder::rust::Installer::new(
                install_dir,
                options.aptos_version_number,
            )),
            Language::Go => Box::new(aptos_sdk_builder::golang::Installer::new(
                install_dir,
                options.serde_package_name,
                options.package_name,
            )),
        };

    if let Some(name) = options.module_name {
        installer
            .install_transaction_builders(&name, abis.as_slice())
            .unwrap();
    }
}
<|endoftext|>


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

use time::precise_time_s;
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 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![[0f64; nGridProductivity]; nGridCapital];
    let mut mValueFunctionNew = mValueFunction.clone();
    let mut mPolicyFunction = mValueFunction.clone();
    let mut expectedValueFunction = mValueFunction.clone();

    // 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, value_fns) in expectedValueFunction.iter_mut()
                                                                 .zip(mValueFunction.iter()) {
            for (expected_value, transitions) in expected_values.iter_mut().zip(mTransition.iter()) {
                *expected_value = transitions.iter()
                                             .zip(value_fns.iter())
                                             .fold(0.0f64, |acc, (transition, value_fn)| {
                    acc + (transition * value_fn)
                });
            }
        }

        for nProductivity in 0..nGridProductivity {
            // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for nCapital in 0..nGridCapital {
                let mut valueHighSoFar = -100000.0;
                let mut capitalChoice = vGridCapital[0];
                let mOutput_cache = &mOutput[nCapital][nProductivity];

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

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

                mValueFunctionNew[nCapital][nProductivity] = valueHighSoFar;
                mPolicyFunction[nCapital][nProductivity] = capitalChoice;
            }
        }

        {
            let old_vals = mValueFunction.iter().flat_map(|arr| arr.iter());
            let new_vals = mValueFunctionNew.iter().flat_map(|arr| arr.iter());

            maxDifference = -100000.0;
            for diff in old_vals.zip(new_vals).map(|(old, new)| (old - new).abs()) {
                if diff > maxDifference {
                    maxDifference = diff
                }
            }
        }

        // swap buffers after the loop
        mem::swap(&mut mValueFunction, &mut mValueFunctionNew);

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

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

    mPolicyFunction[999][2]
}

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>Calculate the diff iteratively<commit_after>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;

use time::precise_time_s;
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 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![[0f64; nGridProductivity]; nGridCapital];
    let mut mPolicyFunction = mValueFunction.clone();
    let mut expectedValueFunction = mValueFunction.clone();

    // 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, value_fns) in expectedValueFunction.iter_mut()
                                                                 .zip(mValueFunction.iter()) {
            for (expected_value, transitions) in expected_values.iter_mut().zip(mTransition.iter()) {
                *expected_value = transitions.iter()
                                             .zip(value_fns.iter())
                                             .fold(0.0f64, |acc, (transition, value_fn)| {
                    acc + (transition * value_fn)
                });
            }
        }

        maxDifference = -100000.0;
        for nProductivity in 0..nGridProductivity {
            // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for nCapital in 0..nGridCapital {
                let mut valueHighSoFar = -100000.0;
                let mut capitalChoice = vGridCapital[0];
                let mOutput_cache = &mOutput[nCapital][nProductivity];

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

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

                let old = mem::replace(&mut mValueFunction[nCapital][nProductivity], valueHighSoFar);
                let diff = (old - valueHighSoFar).abs();
                if diff > maxDifference {
                    maxDifference = diff
                }

                mPolicyFunction[nCapital][nProductivity] = capitalChoice;
            }
        }

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

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

    mPolicyFunction[999][2]
}

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>use lucet_idl::{codegen, Backend, Config, Package, Target};
use std::fs::File;
use std::process::Command;
use tempfile::TempDir;

pub fn rust_codegen(package: &Package) {
    let config = Config {
        backend: Backend::Rust,
        target: Target::Generic,
    };

    let tempdir = TempDir::new().expect("create tempdir");

    let gen_file = tempdir.path().join("out.rs");

    codegen(
        package,
        &config,
        Box::new(File::create(gen_file.clone()).expect("create file")),
    )
    .expect("lucet_idl codegen");

    let cmd_rustc = Command::new("rustc")
        .arg(gen_file.clone())
        .arg("--test")
        .arg("--allow=dead_code")
        .arg("-o")
        .arg(tempdir.path().join("example"))
        .status()
        .expect("run rustcc");
    assert!(cmd_rustc.success(), "failure to compile generated code");
    /*
        let cmd_run = Command::new(tempdir.path().join("example"))
            .status()
            .expect("run generated code");
        assert!(cmd_run.success(), "failure to run generated code");
    */
}

pub fn c_codegen(package: &Package) {
    let config = lucet_idl::Config {
        backend: lucet_idl::Backend::C,
        target: lucet_idl::Target::Generic,
    };

    let tempdir = TempDir::new().expect("create tempdir");

    codegen(
        package,
        &config,
        Box::new(File::create(tempdir.path().join("example.c")).expect("create file")),
    )
    .expect("lucet_idl codegen");

    let cmd_cc = Command::new("cc")
        .arg("--std=c99")
        .arg("-c")
        .arg(tempdir.path().join("example.c"))
        .arg("-o")
        .arg(tempdir.path().join("example.o"))
        .status()
        .expect("run cc");
    assert!(cmd_cc.success(), "failure to compile generated code");

    /*
    let cmd_run = Command::new(tempdir.path().join("example"))
        .status()
        .expect("run generated code");
    assert!(cmd_run.success(), "failure to run generated code");
    */
}
<commit_msg>lucet-idl: debug compilation failures<commit_after>use lucet_idl::{codegen, Backend, Config, Package, Target};
use std::fs::File;
use std::process::Command;
use tempfile::TempDir;

pub fn rust_codegen(package: &Package) {
    let config = Config {
        backend: Backend::Rust,
        target: Target::Generic,
    };

    let tempdir = TempDir::new().expect("create tempdir");

    let gen_file = tempdir.path().join("out.rs");

    codegen(
        package,
        &config,
        Box::new(File::create(gen_file.clone()).expect("create file")),
    )
    .expect("lucet_idl codegen");

    let cmd_rustc = Command::new("rustc")
        .arg(gen_file.clone())
        .arg("--test")
        .arg("--allow=dead_code")
        .arg("-o")
        .arg(tempdir.path().join("example"))
        .status()
        .expect("run rustc");

    if !cmd_rustc.success() {
        Command::new("cat")
            .arg(gen_file.clone())
            .status()
            .expect("debug output");
    }
    assert!(cmd_rustc.success(), "failure to compile generated code");

    /*
        let cmd_run = Command::new(tempdir.path().join("example"))
            .status()
            .expect("run generated code");
        assert!(cmd_run.success(), "failure to run generated code");
    */
}

pub fn c_codegen(package: &Package) {
    let config = lucet_idl::Config {
        backend: lucet_idl::Backend::C,
        target: lucet_idl::Target::Generic,
    };

    let tempdir = TempDir::new().expect("create tempdir");

    codegen(
        package,
        &config,
        Box::new(File::create(tempdir.path().join("example.c")).expect("create file")),
    )
    .expect("lucet_idl codegen");

    let cmd_cc = Command::new("cc")
        .arg("--std=c99")
        .arg("-c")
        .arg(tempdir.path().join("example.c"))
        .arg("-o")
        .arg(tempdir.path().join("example.o"))
        .status()
        .expect("run cc");

    if !cmd_cc.success() {
        Command::new("cat")
            .arg(tempdir.path().join("example.c"))
            .status()
            .expect("debug output");
    }
    assert!(cmd_cc.success(), "failure to compile generated code");

    /*
    let cmd_run = Command::new(tempdir.path().join("example"))
        .status()
        .expect("run generated code");
    assert!(cmd_run.success(), "failure to run generated code");
    */
}
<|endoftext|>


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

#![deny(unsafe_code)]

extern crate gfx;
extern crate ipc_channel;
extern crate metrics;
extern crate msg;
extern crate net_traits;
extern crate profile_traits;
extern crate script_traits;
extern crate servo_url;
extern crate webrender_api;

// This module contains traits in layout used generically
//   in the rest of Servo.
// The traits are here instead of in layout so
//   that these modules won't have to depend on layout.

use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use metrics::PaintTimeMetrics;
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::TopLevelBrowsingContextId;
use net_traits::image_cache::ImageCache;
use profile_traits::{mem, time};
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
use script_traits::LayoutMsg as ConstellationMsg;
use servo_url::ServoUrl;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};

// A static method creating a layout thread
// Here to remove the compositor -> layout dependency
pub trait LayoutThreadFactory {
    type Message;
    fn create(id: PipelineId,
              top_level_browsing_context_id: TopLevelBrowsingContextId,
              url: ServoUrl,
              is_iframe: bool,
              chan: (Sender<Self::Message>, Receiver<Self::Message>),
              pipeline_port: IpcReceiver<LayoutControlMsg>,
              constellation_chan: IpcSender<ConstellationMsg>,
              script_chan: IpcSender<ConstellationControlMsg>,
              image_cache: Arc<ImageCache>,
              font_cache_thread: FontCacheThread,
              time_profiler_chan: time::ProfilerChan,
              mem_profiler_chan: mem::ProfilerChan,
              content_process_shutdown_chan: Option<IpcSender<()>>,
              webrender_api_sender: webrender_api::RenderApiSender,
              webrender_document: webrender_api::DocumentId,
              layout_threads: usize,
              paint_time_metrics: PaintTimeMetrics);
}
<commit_msg>Rustfmt layout_traits crate<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]

extern crate gfx;
extern crate ipc_channel;
extern crate metrics;
extern crate msg;
extern crate net_traits;
extern crate profile_traits;
extern crate script_traits;
extern crate servo_url;
extern crate webrender_api;

// This module contains traits in layout used generically
//   in the rest of Servo.
// The traits are here instead of in layout so
//   that these modules won't have to depend on layout.

use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use metrics::PaintTimeMetrics;
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::TopLevelBrowsingContextId;
use net_traits::image_cache::ImageCache;
use profile_traits::{mem, time};
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
use script_traits::LayoutMsg as ConstellationMsg;
use servo_url::ServoUrl;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};

// A static method creating a layout thread
// Here to remove the compositor -> layout dependency
pub trait LayoutThreadFactory {
    type Message;
    fn create(
        id: PipelineId,
        top_level_browsing_context_id: TopLevelBrowsingContextId,
        url: ServoUrl,
        is_iframe: bool,
        chan: (Sender<Self::Message>, Receiver<Self::Message>),
        pipeline_port: IpcReceiver<LayoutControlMsg>,
        constellation_chan: IpcSender<ConstellationMsg>,
        script_chan: IpcSender<ConstellationControlMsg>,
        image_cache: Arc<ImageCache>,
        font_cache_thread: FontCacheThread,
        time_profiler_chan: time::ProfilerChan,
        mem_profiler_chan: mem::ProfilerChan,
        content_process_shutdown_chan: Option<IpcSender<()>>,
        webrender_api_sender: webrender_api::RenderApiSender,
        webrender_document: webrender_api::DocumentId,
        layout_threads: usize,
        paint_time_metrics: PaintTimeMetrics,
    );
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

use clap::{App, Arg};

include!("../clap-test.rs");

static HIDDEN_ARGS: &'static str = "test 1.4
Kevin K.
tests stuff

USAGE:
    test [FLAGS] [OPTIONS] [DUMMY]

FLAGS:
    -F, --flag2      some other flag
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --option <opt>    some option";

#[test]
fn hidden_args() {
    let app = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.4")
        .args(&[Arg::from_usage("-f, --flag 'some flag'").hidden(true),
                    Arg::from_usage("-F, --flag2 'some other flag'"),
                    Arg::from_usage("--option [opt] 'some option'"),
                    Arg::with_name("DUMMY").required(false).hidden(true)]);
    assert!(test::compare_output(app, "test --help", HIDDEN_ARGS, false));
}
<commit_msg>tests: fixes failing hidden args test<commit_after>extern crate clap;
extern crate regex;

use clap::{App, Arg};

include!("../clap-test.rs");

static HIDDEN_ARGS: &'static str = "test 1.4
Kevin K.
tests stuff

USAGE:
    test [FLAGS] [OPTIONS]

FLAGS:
    -F, --flag2      some other flag
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --option <opt>    some option";

#[test]
fn hidden_args() {
    let app = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.4")
        .args(&[Arg::from_usage("-f, --flag 'some flag'").hidden(true),
                    Arg::from_usage("-F, --flag2 'some other flag'"),
                    Arg::from_usage("--option [opt] 'some option'"),
                    Arg::with_name("DUMMY").required(false).hidden(true)]);
    assert!(test::compare_output(app, "test --help", HIDDEN_ARGS, false));
}
<|endoftext|>


<commit_before>extern crate env_logger;
#[macro_use] extern crate log;
extern crate futures;
extern crate tokio_core;
extern crate hyper;
extern crate alacrity;
extern crate reqwest;

use std::io::Read;
use std::net::SocketAddr;
use std::sync::mpsc::channel;
use std::thread;

use hyper::{Get, Post, StatusCode};
use hyper::server::{Server, Service, Request, Response};
use hyper::header::{ContentLength, TransferEncoding};

use alacrity::pool::Pool;

#[derive(Clone, Copy)]
struct Origin;

impl Service for Origin {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = ::futures::Finished<Response, hyper::Error>;

    fn call(&self, req: Request) -> Self::Future {
        ::futures::finished(match (req.method(), req.path()) {
            (&Get, Some("/")) => {
                let body = "Hello World";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_body(body)
            },
            (_, Some("/method")) => {
                let body = format!("hello {}", req.method());
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_body(body)
            },
            (&Post, Some("/echo")) => {
                let mut res = Response::new();
                if let Some(len) = req.headers().get::<ContentLength>() {
                    res.headers_mut().set(len.clone());
                }
                res.with_body(req.body())
            },
            (_, Some("/chunked")) => {
                Response::new()
                    .with_header(TransferEncoding::chunked())
                    .with_body("Hello Chunky World!")
            },
            _ => {
                Response::new()
                    .with_status(StatusCode::NotFound)
            }
        })
    }
}

/// Send a request through the proxy and get back a response.
///
/// The client request is to created via the callback. The callback provides the host so the client
/// can connect to the correct proxy.
fn with_server<R> (req: R) where R: Fn(String)
{
    let _ = env_logger::init();

    let pool = Pool::with_servers(vec![]);

    let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
    let (_, proxy) = alacrity::proxy::listen(addr, pool.clone()).expect("Failed to start server");

    let (tx, rx) = channel();
    thread::spawn(move || {
        let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
        let (listening, server) = Server::standalone(|tokio| {
            Server::http(&addr, tokio)?
                .handle(|| Ok(Origin), tokio)
        }).unwrap();
        tx.send(listening).unwrap();
        server.run();
    });

    let origin = rx.recv().unwrap();
    pool.add(*origin.addr());

    req(format!("http://localhost:{}", origin.addr().port()));

    proxy.close();
    origin.close();
}

#[test]
fn test_method_on_http_server() {
    use reqwest::Method;
    use std::str::FromStr;

    let methods = vec!("GET", "DELETE", "PATCH", "OPTIONS", "POST", "PUT", "TRACE", "HEAD", "CONNECT");
    for method in methods.iter() {
        with_server(|host| {

            let h_method = Method::from_str(&method).unwrap();
            let url = format!("{}{}", host, "/method");
            let client = reqwest::Client::new().expect("client failed to construct");
            let mut res = client.request(h_method, &url).send().unwrap();

            debug!("Response: {}", res.status());
            debug!("Headers: \n{}", res.headers());

            assert_eq!(res.status(), &reqwest::StatusCode::Ok);

            // HEAD, CONNECT cannot return any body
            if *method != "HEAD" && *method != "CONNECT" {
                let mut body = String::new();
                res.read_to_string(&mut body).unwrap();
                let expected = format!("hello {}", method);
                assert_eq!(expected, body);
            } else {
                let mut body = String::new();
                res.read_to_string(&mut body).unwrap();
                assert_eq!("".to_string(), body);
            }
        });
    }
}

#[test]
fn test_request_body() {
    with_server(|host| {

        let url = format!("{}{}", host, "/echo");
        let client = reqwest::Client::new().expect("client failed to construct");
        let mut res = client.post(&url)
            .body("hello")
            .send().unwrap();

        assert_eq!(res.status(), &reqwest::StatusCode::Ok);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "hello");
    });
}

#[test]
fn test_response_body_streaming() {
    with_server(|host| {
        let url = format!("{}{}", host, "/chunked");
        let mut res = reqwest::get(&url).unwrap();

        assert_eq!(res.status(), &reqwest::StatusCode::Ok);

        assert_eq!(res.headers().get::<reqwest::header::TransferEncoding>(),
            Some(&reqwest::header::TransferEncoding(vec![reqwest::header::Encoding::Chunked])));

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "Hello Chunky World!");
    });
}
<commit_msg>Test chunked request body<commit_after>extern crate env_logger;
#[macro_use] extern crate log;
extern crate futures;
extern crate tokio_core;
extern crate hyper;
extern crate alacrity;
extern crate reqwest;

use std::io::{Read, Write};
use std::net::{TcpStream, SocketAddr};
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;

use hyper::{Get, Post, StatusCode};
use hyper::server::{Server, Service, Request, Response};
use hyper::header::{ContentLength, TransferEncoding};

use alacrity::pool::Pool;

#[derive(Clone, Copy)]
struct Origin;

impl Service for Origin {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = ::futures::Finished<Response, hyper::Error>;

    fn call(&self, req: Request) -> Self::Future {
        ::futures::finished(match (req.method(), req.path()) {
            (&Get, Some("/")) => {
                let body = "Hello World";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_body(body)
            },
            (_, Some("/method")) => {
                let body = format!("hello {}", req.method());
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_body(body)
            },
            (&Post, Some("/echo")) => {
                let mut res = Response::new();
                if let Some(len) = req.headers().get::<ContentLength>() {
                    res.headers_mut().set(len.clone());
                }
                res.with_body(req.body())
            },
            (_, Some("/chunked")) => {
                Response::new()
                    .with_header(TransferEncoding::chunked())
                    .with_body("Hello Chunky World!")
            },
            _ => {
                Response::new()
                    .with_status(StatusCode::NotFound)
            }
        })
    }
}

/// Send a request through the proxy and get back a response.
///
/// The client request is to created via the callback. The callback provides the host so the client
/// can connect to the correct proxy.
fn with_server<R> (req: R) where R: Fn(String)
{
    let _ = env_logger::init();

    let pool = Pool::with_servers(vec![]);

    let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
    let (_, proxy) = alacrity::proxy::listen(addr, pool.clone()).expect("Failed to start server");

    let (tx, rx) = channel();
    thread::spawn(move || {
        let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
        let (listening, server) = Server::standalone(|tokio| {
            Server::http(&addr, tokio)?
                .handle(|| Ok(Origin), tokio)
        }).unwrap();
        tx.send(listening).unwrap();
        server.run();
    });

    let origin = rx.recv().unwrap();
    pool.add(*origin.addr());

    req(format!("http://127.0.0.1:{}", origin.addr().port()));

    proxy.close();
    origin.close();
}

/// Utility function for creating a raw request to the proxy
fn connect(host: &str) -> TcpStream {
    // strip out the "http://"
    let addr: SocketAddr = host[7..].parse().unwrap();
    let req = TcpStream::connect(&addr).unwrap();
    req.set_read_timeout(Some(Duration::from_secs(1))).unwrap();
    req.set_write_timeout(Some(Duration::from_secs(1))).unwrap();
    req
}

#[test]
fn test_method_on_http_server() {
    use reqwest::Method;
    use std::str::FromStr;

    let methods = vec!("GET", "DELETE", "PATCH", "OPTIONS", "POST", "PUT", "TRACE", "HEAD", "CONNECT");
    for method in methods.iter() {
        with_server(|host| {

            let h_method = Method::from_str(&method).unwrap();
            let url = format!("{}{}", host, "/method");
            let client = reqwest::Client::new().expect("client failed to construct");
            let mut res = client.request(h_method, &url).send().unwrap();

            debug!("Response: {}", res.status());
            debug!("Headers: \n{}", res.headers());

            assert_eq!(res.status(), &reqwest::StatusCode::Ok);

            // HEAD, CONNECT cannot return any body
            if *method != "HEAD" && *method != "CONNECT" {
                let mut body = String::new();
                res.read_to_string(&mut body).unwrap();
                let expected = format!("hello {}", method);
                assert_eq!(expected, body);
            } else {
                let mut body = String::new();
                res.read_to_string(&mut body).unwrap();
                assert_eq!("".to_string(), body);
            }
        });
    }
}

#[test]
fn test_request_body() {
    with_server(|host| {

        let url = format!("{}{}", host, "/echo");
        let client = reqwest::Client::new().expect("client failed to construct");
        let mut res = client.post(&url)
            .body("hello")
            .send().unwrap();

        assert_eq!(res.status(), &reqwest::StatusCode::Ok);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "hello");
    });
}

#[test]
fn test_request_and_response_body_chunked() {
    with_server(|host| {

        // reqwest does not currently support chunked requests
        let mut req = connect(&host);
        req.write_all(b"\
            POST /echo HTTP/1.1\r\n\
            Host: www.example.com\r\n\
            Accept: */*\r\n\
            Connection: close\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            5\r\n\
            hello\r\n\
            0\r\n\r\n\
        ").expect("Raw request failed");
        let mut body = String::new();
        req.read_to_string(&mut body).expect("Raw response failed");
        let n = body.find("\r\n\r\n").unwrap() + 4;

        assert_eq!(&body[n..], "5\r\nhello\r\n0\r\n\r\n");
    });
}

#[test]
fn test_response_body_streaming() {
    with_server(|host| {
        let url = format!("{}{}", host, "/chunked");
        let mut res = reqwest::get(&url).unwrap();

        assert_eq!(res.status(), &reqwest::StatusCode::Ok);

        assert_eq!(res.headers().get::<reqwest::header::TransferEncoding>(),
            Some(&reqwest::header::TransferEncoding(vec![reqwest::header::Encoding::Chunked])));

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "Hello Chunky World!");
    });
}
<|endoftext|>


<commit_before>//! The forwarder module shall act as wrapper for the ffi mangled lib.rs
//! calls, which shall be very thin and spare there, but extensive here
//! to prepare clean calls to adbfflutter.
use crate::{
    common::paths::SearchPath,
    ctrl::{ForwardNetMsg, UiUpdateMsg},
    data::{
        collection::Collection,
        ipc::{
            IFCollectionOutputData,
            IPC::{self, DoneSearching},
        },
    },
    net::subs::peer_representation::peer_to_hash_string,
    shared,
};
use async_std::task;
use crossbeam::{
    channel::{unbounded, Receiver, Sender},
    sync::WaitGroup,
};
use libp2p::core::PeerId;
use serde_json;
use std::{
    sync::{Arc, Mutex},
    thread,
};

lazy_static! {
    /// a static immutable runtime for all network activity
    static ref NET_RUNTIME: Mutex<(Receiver<UiUpdateMsg>,Sender<IPC>)> = Mutex::new(create_net_runtime());
    /// a static mutable data collection
    static ref NET_UI : Mutex<UIList> = Mutex::new(UIList { cnt: Vec::new() });
}

/// just return the number of audio files found for now
pub fn ffi_file_count_good(input_path: Vec<String>) -> u32 {
    // prepare data
    let cleaned_paths = SearchPath::new(&input_path);
    let search_path = Arc::new(Mutex::new(cleaned_paths));

    let (tx, _rx) = unbounded::<UiUpdateMsg>();
    let synced_to_ui_messages = Arc::new(Mutex::new(tx.clone()));
    let has_ui = false;

    // set up data and run search
    let collection_protected = Arc::new(Mutex::new(Collection::new()));
    let output_data_return_handle = shared::collection_search(
        collection_protected,
        search_path,
        synced_to_ui_messages,
        has_ui,
    );

    // scope and block trickery for lifetime and mutability
    output_data_return_handle.nr_found_songs
}

/// Return the json of peer uis which holds a vector of UIListInner
pub async fn ffi_ui_messages_as_json() -> String {
    // todo: unwrap using NET_UI is save unless you
    //       run this function simultaneously many instances, secure this because
    //       at least 2 functions now use net component, and simultaneous usage
    //       is more probable now!

    // get network runtime
    let (net_receiver, _) = &*NET_RUNTIME.lock().unwrap();

    // break loop if a yet noticeable change happens
    loop {
        if let Ok(reaction) = net_receiver.recv() {
            match reaction {
                UiUpdateMsg::CollectionUpdate(_, _) => {}
                UiUpdateMsg::NetUpdate(net_message) => match net_message {
                    ForwardNetMsg::Add(peer) => {
                        let ui_list = &mut NET_UI.lock().unwrap();
                        {
                            ui_list.add_peer(&peer.id);
                            break;
                        }
                    }
                    ForwardNetMsg::Delete(peer_id) => {
                        let ui_list = &mut NET_UI.lock().unwrap();
                        {
                            ui_list.remove_peer(&peer_id);
                            break;
                        }
                    }
                    ForwardNetMsg::Stats(_) => {}
                },
                UiUpdateMsg::PeerSearchFinished(peer_id, data) => {
                    let ui_list = &mut NET_UI.lock().unwrap();
                    {
                        ui_list.add_search_finished(&peer_id, &data);
                        break;
                    }
                }
                UiUpdateMsg::StopUI => unreachable!(),
            }
        }
    }
    let ui_list = &NET_UI.lock().unwrap();
    {
        let json: &UIList = &*ui_list;
        let peers_ui_json = serde_json::to_string(&json.cnt).unwrap();
        peers_ui_json
    }
}

/// send ipc found out
pub async fn ffi_send_ipc_search_done(nr_searched_files: u32, nr_found_songs: u32) -> bool {
    //
    // get network runtime
    let (_, ipc_sender) = &mut *NET_RUNTIME.lock().unwrap();
    let sending = IFCollectionOutputData {
        nr_searched_files,
        nr_found_songs,
        size_of_data_in_kb: 0,
        nr_internal_duplicates: 0,
    };
    ipc_sender.send(DoneSearching(sending)).is_ok()
}

// ------------------------------------------------------------------------------------------

/// Opens a net thread and return ui message receiver and ipc message sender
/// to be used as static instance for Dart-to-backend communication.
fn create_net_runtime() -> (Receiver<UiUpdateMsg>, Sender<IPC>) {
    // outgoing crossbeam receiver
    let (ui_sender, reactor) = unbounded::<UiUpdateMsg>();
    let (ipc_sender, ipc_receive) = unbounded::<IPC>();
    thread::Builder::new()
        .name("app_net".into())
        .spawn(move || {
            task::block_on(async move {
                // mock input parameters
                let dummy_wait_net_thread = WaitGroup::new();

                match shared::net_search(dummy_wait_net_thread, Some(ui_sender), ipc_receive).await
                {
                    Ok(_) => {}
                    Err(e) => error!("network error: {}", e),
                }
            });
        })
        .unwrap();
    (reactor, ipc_sender)
}

/// Struct viewable for ffi inner part and used as json export
/// !!! change Dart names as well, cause variable names MUST be in sync
#[derive(Serialize, Deserialize, Clone)]
#[allow(non_camel_case_types)]
struct UIListInner {
    // normally peer would be the hash key, but since we use it as json container
    // it's a bit itchy
    peerid: String,
    finished: i32,
    searched: u32,
}
/// Container and helper to fill UIListInner easier
struct UIList {
    pub cnt: Vec<UIListInner>,
}
impl UIList {
    fn add_peer(&mut self, peer_id: &PeerId) {
        let peer_string = peer_to_hash_string(peer_id);
        if self.cnt.iter().find(|e| e.peerid == peer_string).is_none() {
            self.cnt.push(UIListInner {
                peerid: peer_string,
                finished: -1, // -1 on dart side should show that it is not yet completed
                searched: 0,
            });
        }
    }
    fn remove_peer(&mut self, peer_id: &PeerId) {
        //todo: as soon as this is not experimental:
        //      self.cnt.drain_filter(|e| e.peer_id == peer_to_hash(peer_id));
        let peer_string = peer_to_hash_string(peer_id);
        let mut i = 0;
        while i != self.cnt.len() {
            if self.cnt[i].peerid == peer_string {
                self.cnt.remove(i);
                break;
            } else {
                i += 1;
            }
        }
    }
    fn add_search_finished(&mut self, peer_id: &PeerId, data: &IFCollectionOutputData) {
        let peer_string = peer_to_hash_string(peer_id);
        let mut i = 0;
        while i != self.cnt.len() {
            if self.cnt[i].peerid == peer_string {
                self.cnt[i].finished = data.nr_found_songs as i32;
                self.cnt[i].searched = data.nr_searched_files;
                break;
            } else {
                i += 1;
            }
        }
    }
}
<commit_msg>[documentation] clarify<commit_after>//! The forwarder module shall act as wrapper for the ffi mangled lib.rs
//! calls, which shall be very thin and spare there, but extensive here
//! to prepare clean calls to adbfflutter.
use crate::{
    common::paths::SearchPath,
    ctrl::{ForwardNetMsg, UiUpdateMsg},
    data::{
        collection::Collection,
        ipc::{
            IFCollectionOutputData,
            IPC::{self, DoneSearching},
        },
    },
    net::subs::peer_representation::peer_to_hash_string,
    shared,
};
use async_std::task;
use crossbeam::{
    channel::{unbounded, Receiver, Sender},
    sync::WaitGroup,
};
use libp2p::core::PeerId;
use serde_json;
use std::{
    sync::{Arc, Mutex},
    thread,
};

lazy_static! {
    /// a static immutable runtime for all network activity
    static ref NET_RUNTIME: Mutex<(Receiver<UiUpdateMsg>,Sender<IPC>)> = Mutex::new(create_net_runtime());
    /// a static mutable data collection
    static ref NET_UI : Mutex<UIList> = Mutex::new(UIList { cnt: Vec::new() });
}

/// just return the number of audio files found for now
pub fn ffi_file_count_good(input_path: Vec<String>) -> u32 {
    // prepare data
    let cleaned_paths = SearchPath::new(&input_path);
    let search_path = Arc::new(Mutex::new(cleaned_paths));

    let (tx, _rx) = unbounded::<UiUpdateMsg>();
    let synced_to_ui_messages = Arc::new(Mutex::new(tx.clone()));
    let has_ui = false;

    // set up data and run search
    let collection_protected = Arc::new(Mutex::new(Collection::new()));
    let output_data_return_handle = shared::collection_search(
        collection_protected,
        search_path,
        synced_to_ui_messages,
        has_ui,
    );

    // scope and block trickery for lifetime and mutability
    output_data_return_handle.nr_found_songs
}

/// Return the json of peer uis which holds a vector of UIListInner
pub async fn ffi_ui_messages_as_json() -> String {
    // todo: unwrap using NET_UI is save unless you
    //       run this function simultaneously many instances, secure this because
    //       at least 2 functions now use net component, and simultaneous usage
    //       is more probable now!

    // get network runtime
    let (net_receiver, _) = &*NET_RUNTIME.lock().unwrap();

    // break loop if a yet noticeable change happens
    loop {
        if let Ok(reaction) = net_receiver.recv() {
            match reaction {
                UiUpdateMsg::CollectionUpdate(_, _) => {}
                UiUpdateMsg::NetUpdate(net_message) => match net_message {
                    ForwardNetMsg::Add(peer) => {
                        let ui_list = &mut NET_UI.lock().unwrap();
                        {
                            ui_list.add_peer(&peer.id);
                            break;
                        }
                    }
                    ForwardNetMsg::Delete(peer_id) => {
                        let ui_list = &mut NET_UI.lock().unwrap();
                        {
                            ui_list.remove_peer(&peer_id);
                            break;
                        }
                    }
                    ForwardNetMsg::Stats(_) => {}
                },
                UiUpdateMsg::PeerSearchFinished(peer_id, data) => {
                    let ui_list = &mut NET_UI.lock().unwrap();
                    {
                        ui_list.add_search_finished(&peer_id, &data);
                        break;
                    }
                }
                UiUpdateMsg::StopUI => unreachable!(),
            }
        }
    }
    let ui_list = &NET_UI.lock().unwrap();
    {
        let json: &UIList = &*ui_list;
        let peers_ui_json = serde_json::to_string(&json.cnt).unwrap();
        peers_ui_json
    }
}

/// Send ipc found files (yet only 2 of 4 values)
pub async fn ffi_send_ipc_search_done(nr_searched_files: u32, nr_found_songs: u32) -> bool {
    //
    // get network runtime
    let (_, ipc_sender) = &mut *NET_RUNTIME.lock().unwrap();
    let sending = IFCollectionOutputData {
        nr_searched_files,
        nr_found_songs,
        size_of_data_in_kb: 0,
        nr_internal_duplicates: 0,
    };
    ipc_sender.send(DoneSearching(sending)).is_ok()
}

// ------------------------------------------------------------------------------------------

/// Opens a net thread and return ui message receiver and ipc message sender
/// to be used as static instance for Dart-to-backend communication.
fn create_net_runtime() -> (Receiver<UiUpdateMsg>, Sender<IPC>) {
    // outgoing crossbeam receiver
    let (ui_sender, reactor) = unbounded::<UiUpdateMsg>();
    let (ipc_sender, ipc_receive) = unbounded::<IPC>();
    thread::Builder::new()
        .name("app_net".into())
        .spawn(move || {
            task::block_on(async move {
                // mock input parameters
                let dummy_wait_net_thread = WaitGroup::new();

                match shared::net_search(dummy_wait_net_thread, Some(ui_sender), ipc_receive).await
                {
                    Ok(_) => {}
                    Err(e) => error!("network error: {}", e),
                }
            });
        })
        .unwrap();
    (reactor, ipc_sender)
}

/// Struct viewable for ffi inner part and used as json export
/// !!! change Dart names as well, cause variable names MUST be in sync
#[derive(Serialize, Deserialize, Clone)]
#[allow(non_camel_case_types)]
struct UIListInner {
    // normally peer would be the hash key, but since we use it as json container
    // it's a bit itchy
    peerid: String,
    finished: i32,
    searched: u32,
}
/// Container and helper to fill UIListInner easier
struct UIList {
    pub cnt: Vec<UIListInner>,
}
impl UIList {
    fn add_peer(&mut self, peer_id: &PeerId) {
        let peer_string = peer_to_hash_string(peer_id);
        if self.cnt.iter().find(|e| e.peerid == peer_string).is_none() {
            self.cnt.push(UIListInner {
                peerid: peer_string,
                finished: -1, // -1 on dart side should show that it is not yet completed
                searched: 0,
            });
        }
    }
    fn remove_peer(&mut self, peer_id: &PeerId) {
        //todo: as soon as this is not experimental:
        //      self.cnt.drain_filter(|e| e.peer_id == peer_to_hash(peer_id));
        let peer_string = peer_to_hash_string(peer_id);
        let mut i = 0;
        while i != self.cnt.len() {
            if self.cnt[i].peerid == peer_string {
                self.cnt.remove(i);
                break;
            } else {
                i += 1;
            }
        }
    }
    fn add_search_finished(&mut self, peer_id: &PeerId, data: &IFCollectionOutputData) {
        let peer_string = peer_to_hash_string(peer_id);
        let mut i = 0;
        while i != self.cnt.len() {
            if self.cnt[i].peerid == peer_string {
                self.cnt[i].finished = data.nr_found_songs as i32;
                self.cnt[i].searched = data.nr_searched_files;
                break;
            } else {
                i += 1;
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::collections::Map;
use config::*;
use glob::glob;

fn main() {
    // Option 1
    // --------
    // Gather all conf files from conf/ manually
    let mut settings = Config::default();
    settings
        // File::with_name(..) is shorthand for File::from(Path::new(..))
        .merge(File::with_name("conf/00-default.toml")).unwrap()
        .merge(File::from(Path::new("conf/05-some.yml"))).unwrap()
        .merge(File::from(Path::new("conf/99-extra.json"))).unwrap();

    // Print out our settings (as a Map)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<Map<String, String>>().unwrap());

    // Option 2
    // --------
    // Gather all conf files from conf/ manually, but put in 1 merge call.
    let mut settings = Config::default();
    settings
        .merge(vec![File::with_name("conf/00-default.toml"),
                    File::from(Path::new("conf/05-some.yml")),
                    File::from(Path::new("conf/99-extra.json"))])
        .unwrap();

    // Print out our settings (as a Map)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<Map<String, String>>().unwrap());

    // Option 3
    // --------
    // Gather all conf files from conf/ using glob and put in 1 merge call.
    let mut settings = Config::default();
    settings
        .merge(glob("conf/*")
                   .unwrap()
                   .map(|path| File::from(path.unwrap()))
                   .collect::<Vec<_>>())
        .unwrap();

    // Print out our settings (as a Map)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<Map<String, String>>().unwrap());
}
<commit_msg>Fix: Import HashMap instead of Map<commit_after>use std::path::Path;
use std::collections::HashMap;
use config::*;
use glob::glob;

fn main() {
    // Option 1
    // --------
    // Gather all conf files from conf/ manually
    let mut settings = Config::default();
    settings
        // File::with_name(..) is shorthand for File::from(Path::new(..))
        .merge(File::with_name("conf/00-default.toml")).unwrap()
        .merge(File::from(Path::new("conf/05-some.yml"))).unwrap()
        .merge(File::from(Path::new("conf/99-extra.json"))).unwrap();

    // Print out our settings (as a HashMap)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<HashMap<String, String>>().unwrap());

    // Option 2
    // --------
    // Gather all conf files from conf/ manually, but put in 1 merge call.
    let mut settings = Config::default();
    settings
        .merge(vec![File::with_name("conf/00-default.toml"),
                    File::from(Path::new("conf/05-some.yml")),
                    File::from(Path::new("conf/99-extra.json"))])
        .unwrap();

    // Print out our settings (as a HashMap)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<HashMap<String, String>>().unwrap());

    // Option 3
    // --------
    // Gather all conf files from conf/ using glob and put in 1 merge call.
    let mut settings = Config::default();
    settings
        .merge(glob("conf/*")
                   .unwrap()
                   .map(|path| File::from(path.unwrap()))
                   .collect::<Vec<_>>())
        .unwrap();

    // Print out our settings (as a HashMap)
    println!("\n{:?} \n\n-----------",
             settings.try_into::<HashMap<String, String>>().unwrap());
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::ffi::CString;
use std::fmt;
use std::ptr;
use std::str;

use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use instance::PhysicalDevice;
use instance::loader;
use instance::loader::LoadingError;
use vk;
use check_errors;

macro_rules! extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        /// List of extensions that are enabled or available.
        #[derive(Copy, Clone, PartialEq, Eq)]
        #[allow(missing_docs)]
        pub struct $sname {
            $(
                pub $ext: bool,
            )*

            /// This field ensures that an instance of this `Extensions` struct
            /// can only be created through Vulkano functions and the update
            /// syntax. This way, extensions can be added to Vulkano without
            /// breaking existing code.
            pub _unbuildable: Unbuildable,
        }

        impl $sname {
            /// Returns an `Extensions` object with all members set to `false`.
            #[inline]
            pub fn none() -> $sname {
                $sname {
                    $($ext: false,)*
                    _unbuildable: Unbuildable(())
                }
            }

            /// Builds a Vec containing the list of extensions.
            pub fn build_extensions_list(&self) -> Vec<CString> {
                let mut data = Vec::new();
                $(if self.$ext { data.push(CString::new(&$s[..]).unwrap()); })*
                data
            }

            /// Returns the intersection of this list and another list.
            #[inline]
            pub fn intersection(&self, other: &$sname) -> $sname {
                $sname {
                    $(
                        $ext: self.$ext && other.$ext,
                    )*
                    _unbuildable: Unbuildable(())
                }
            }
        }

        impl fmt::Debug for $sname {
            #[allow(unused_assignments)]
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                try!(write!(f, "["));

                let mut first = true;

                $(
                    if self.$ext {
                        if !first { try!(write!(f, ", ")); }
                        else { first = false; }
                        try!(f.write_str(str::from_utf8($s).unwrap()));
                    }
                )*

                write!(f, "]")
            }
        }
    );
}

macro_rules! instance_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_core().
            pub fn supported_by_core_raw() -> Result<$sname, SupportedExtensionsError> {
                let entry_points = try!(loader::entry_points());

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    let name = property.extensionName;
                    $(
                        // TODO: this is VERY inefficient
                        // TODO: Check specVersion?
                        let same = {
                            let mut i = 0;
                            while name[i] != 0 && $s[i] != 0 && name[i] as u8 == $s[i] && i < $s.len() { i += 1; }
                            name[i] == 0 && (i >= $s.len() || name[i] as u8 == $s[i])
                        };
                        if same {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the core driver.
            pub fn supported_by_core() -> Result<$sname, LoadingError> {
                match $sname::supported_by_core_raw() {
                    Ok(l) => Ok(l),
                    Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

macro_rules! device_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_device().
            pub fn supported_by_device_raw(physical_device: &PhysicalDevice) -> Result<$sname, SupportedExtensionsError> {
                let vk = physical_device.instance().pointers();

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(vk.EnumerateDeviceExtensionProperties(
                        physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(vk.EnumerateDeviceExtensionProperties(
                        physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    let name = property.extensionName;
                    $(
                        // TODO: this is VERY inefficient
                        // TODO: Check specVersion?
                        let same = {
                            let mut i = 0;
                            while name[i] != 0 && $s[i] != 0 && name[i] as u8 == $s[i] && i < $s.len() { i += 1; }
                            name[i] == 0 && (i >= $s.len() || name[i] as u8 == $s[i])
                        };
                        if same {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
            pub fn supported_by_device(physical_device: &PhysicalDevice) -> $sname {
                match $sname::supported_by_device_raw(physical_device) {
                    Ok(l) => l,
                    Err(SupportedExtensionsError::LoadingError(e)) => unreachable!(),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

instance_extensions! {
    InstanceExtensions,
    khr_surface => b"VK_KHR_surface",
    khr_display => b"VK_KHR_display",
    khr_xlib_surface => b"VK_KHR_xlib_surface",
    khr_xcb_surface => b"VK_KHR_xcb_surface",
    khr_wayland_surface => b"VK_KHR_wayland_surface",
    khr_mir_surface => b"VK_KHR_mir_surface",
    khr_android_surface => b"VK_KHR_android_surface",
    khr_win32_surface => b"VK_KHR_win32_surface",
    ext_debug_report => b"VK_EXT_debug_report",
    nn_vi_surface => b"VK_NN_vi_surface",
    ext_swapchain_colorspace => b"VK_EXT_swapchain_colorspace",
}

device_extensions! {
    DeviceExtensions,
    khr_swapchain => b"VK_KHR_swapchain",
    khr_display_swapchain => b"VK_KHR_display_swapchain",
    khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
}

/// Error that can happen when loading the list of layers.
#[derive(Clone, Debug)]
pub enum SupportedExtensionsError {
    /// Failed to load the Vulkan shared library.
    LoadingError(LoadingError),
    /// Not enough memory.
    OomError(OomError),
}

impl error::Error for SupportedExtensionsError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
            SupportedExtensionsError::OomError(_) => "not enough memory available",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SupportedExtensionsError::LoadingError(ref err) => Some(err),
            SupportedExtensionsError::OomError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for SupportedExtensionsError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for SupportedExtensionsError {
    #[inline]
    fn from(err: OomError) -> SupportedExtensionsError {
        SupportedExtensionsError::OomError(err)
    }
}

impl From<LoadingError> for SupportedExtensionsError {
    #[inline]
    fn from(err: LoadingError) -> SupportedExtensionsError {
        SupportedExtensionsError::LoadingError(err)
    }
}

impl From<Error> for SupportedExtensionsError {
    #[inline]
    fn from(err: Error) -> SupportedExtensionsError {
        match err {
            err @ Error::OutOfHostMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// This helper type can only be instantiated inside this module.
/// See `*Extensions::_unbuildable`.
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Unbuildable(());

#[cfg(test)]
mod tests {
    use instance::InstanceExtensions;
    use instance::DeviceExtensions;

    #[test]
    fn empty_extensions() {
        let i = InstanceExtensions::none().build_extensions_list();
        assert!(i.is_empty());

        let d = DeviceExtensions::none().build_extensions_list();
        assert!(d.is_empty());
    }
}
<commit_msg>Compare extension names more elegantly<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::ffi::CString;
use std::fmt;
use std::ptr;
use std::str;

use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use instance::PhysicalDevice;
use instance::loader;
use instance::loader::LoadingError;
use vk;
use check_errors;

macro_rules! extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        /// List of extensions that are enabled or available.
        #[derive(Copy, Clone, PartialEq, Eq)]
        #[allow(missing_docs)]
        pub struct $sname {
            $(
                pub $ext: bool,
            )*

            /// This field ensures that an instance of this `Extensions` struct
            /// can only be created through Vulkano functions and the update
            /// syntax. This way, extensions can be added to Vulkano without
            /// breaking existing code.
            pub _unbuildable: Unbuildable,
        }

        impl $sname {
            /// Returns an `Extensions` object with all members set to `false`.
            #[inline]
            pub fn none() -> $sname {
                $sname {
                    $($ext: false,)*
                    _unbuildable: Unbuildable(())
                }
            }

            /// Builds a Vec containing the list of extensions.
            pub fn build_extensions_list(&self) -> Vec<CString> {
                let mut data = Vec::new();
                $(if self.$ext { data.push(CString::new(&$s[..]).unwrap()); })*
                data
            }

            /// Returns the intersection of this list and another list.
            #[inline]
            pub fn intersection(&self, other: &$sname) -> $sname {
                $sname {
                    $(
                        $ext: self.$ext && other.$ext,
                    )*
                    _unbuildable: Unbuildable(())
                }
            }
        }

        impl fmt::Debug for $sname {
            #[allow(unused_assignments)]
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                try!(write!(f, "["));

                let mut first = true;

                $(
                    if self.$ext {
                        if !first { try!(write!(f, ", ")); }
                        else { first = false; }
                        try!(f.write_str(str::from_utf8($s).unwrap()));
                    }
                )*

                write!(f, "]")
            }
        }
    );
}

macro_rules! instance_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_core().
            pub fn supported_by_core_raw() -> Result<$sname, SupportedExtensionsError> {
                let entry_points = try!(loader::entry_points());

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    use std::ffi::CStr;
                    let name = unsafe { CStr::from_ptr(property.extensionName.as_ptr()) };
                    $(
                        // TODO: Check specVersion?
                        if name.to_bytes() == &$s[..] {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the core driver.
            pub fn supported_by_core() -> Result<$sname, LoadingError> {
                match $sname::supported_by_core_raw() {
                    Ok(l) => Ok(l),
                    Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

macro_rules! device_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_device().
            pub fn supported_by_device_raw(physical_device: &PhysicalDevice) -> Result<$sname, SupportedExtensionsError> {
                let vk = physical_device.instance().pointers();

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(vk.EnumerateDeviceExtensionProperties(
                        physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(vk.EnumerateDeviceExtensionProperties(
                        physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    use std::ffi::CStr;
                    let name = unsafe { CStr::from_ptr(property.extensionName.as_ptr()) };
                    $(
                        // TODO: Check specVersion?
                        if name.to_bytes() == &$s[..] {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
            pub fn supported_by_device(physical_device: &PhysicalDevice) -> $sname {
                match $sname::supported_by_device_raw(physical_device) {
                    Ok(l) => l,
                    Err(SupportedExtensionsError::LoadingError(e)) => unreachable!(),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

instance_extensions! {
    InstanceExtensions,
    khr_surface => b"VK_KHR_surface",
    khr_display => b"VK_KHR_display",
    khr_xlib_surface => b"VK_KHR_xlib_surface",
    khr_xcb_surface => b"VK_KHR_xcb_surface",
    khr_wayland_surface => b"VK_KHR_wayland_surface",
    khr_mir_surface => b"VK_KHR_mir_surface",
    khr_android_surface => b"VK_KHR_android_surface",
    khr_win32_surface => b"VK_KHR_win32_surface",
    ext_debug_report => b"VK_EXT_debug_report",
    nn_vi_surface => b"VK_NN_vi_surface",
    ext_swapchain_colorspace => b"VK_EXT_swapchain_colorspace",
}

device_extensions! {
    DeviceExtensions,
    khr_swapchain => b"VK_KHR_swapchain",
    khr_display_swapchain => b"VK_KHR_display_swapchain",
    khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
}

/// Error that can happen when loading the list of layers.
#[derive(Clone, Debug)]
pub enum SupportedExtensionsError {
    /// Failed to load the Vulkan shared library.
    LoadingError(LoadingError),
    /// Not enough memory.
    OomError(OomError),
}

impl error::Error for SupportedExtensionsError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
            SupportedExtensionsError::OomError(_) => "not enough memory available",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SupportedExtensionsError::LoadingError(ref err) => Some(err),
            SupportedExtensionsError::OomError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for SupportedExtensionsError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for SupportedExtensionsError {
    #[inline]
    fn from(err: OomError) -> SupportedExtensionsError {
        SupportedExtensionsError::OomError(err)
    }
}

impl From<LoadingError> for SupportedExtensionsError {
    #[inline]
    fn from(err: LoadingError) -> SupportedExtensionsError {
        SupportedExtensionsError::LoadingError(err)
    }
}

impl From<Error> for SupportedExtensionsError {
    #[inline]
    fn from(err: Error) -> SupportedExtensionsError {
        match err {
            err @ Error::OutOfHostMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// This helper type can only be instantiated inside this module.
/// See `*Extensions::_unbuildable`.
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Unbuildable(());

#[cfg(test)]
mod tests {
    use instance::InstanceExtensions;
    use instance::DeviceExtensions;

    #[test]
    fn empty_extensions() {
        let i = InstanceExtensions::none().build_extensions_list();
        assert!(i.is_empty());

        let d = DeviceExtensions::none().build_extensions_list();
        assert!(d.is_empty());
    }
}
<|endoftext|>