<commit_before>#![allow(unused_imports, unused_variables, unused_attributes, dead_code)]

use crate::cfg::spec::{Nargs, Otto, Param, Spec, Task, Value};
use clap::{arg, Arg, ArgMatches, Command};
use std::env;
use std::path::PathBuf;

#[macro_use]
use super::macros;
use super::error;

#[derive(Debug, Default, PartialEq)]
pub struct TaskArgs {
    name: String,
    args: Vec<String>,
}

impl TaskArgs {
    pub fn new(name: String) -> Self {
        Self { name, args: vec![] }
    }
}

#[derive(Debug, Default, PartialEq)]
pub struct Parser {
    pub spec: Spec,
    pub prog: String,
    pub args: Vec<String>,
}

impl Parser {
    pub fn new(spec: Spec) -> Self {
        let mut args = env::args();
        Self {
            spec,
            prog: args.next().unwrap(),
            args: args.collect(),
        }
    }
    /*
    pub fn from_yaml<'a>(param: Param) -> Arg<'a> {
        let mut arg = Arg::new(param.name.as_str());
        for (k, v) in param.to_kv() {
            arg = match k.as_str().expect("Arg fields must be strings") {
                "short" => str_to_char!(arg, v, short),
                "long" => str_to_str!(arg, v, long),
                //"aliases" => str_vec_or_str!(arg, v, alias),
                "help" => str_to_str!(arg, v, help),
                //"long_help" => str_to_str!(arg, v, long_help),
                "required" => str_to_bool!(arg, v, required),
                //"required_if" => str_tuple2!(arg, v, required_if_eq),
                //"required_ifs" => str_tuple2!(arg, v, required_if_eq),
                "takes_value" => str_to_bool!(arg, v, takes_value),
                //"index" => str_to_usize!(arg, v, index),
                //"global" => str_to_bool!(arg, v, global),
                //"multiple" => str_to_bool!(arg, v, multiple_values), //note: changed multiple -> multiple_values (compiler warning)
                //"hidden" => str_to_bool!(arg, v, hide),
                //"next_line_help" => str_to_bool!(arg, v, next_line_help),
                //"group" => str_to_str!(arg, v, group),
                //"number_of_values" => str_to_usize!(arg, v, number_of_values),
                //"max_values" => str_to_usize!(arg, v, max_values),
                //"min_values" => str_to_usize!(arg, v, min_values),
                "value_name" => str_to_str!(arg, v, value_name),
                //"use_delimiter" => str_to_bool!(arg, v, use_delimiter),
                "allow_hyphen_values" => str_to_bool!(arg, v, allow_hyphen_values),
                "last" => str_to_bool!(arg, v, last),
                //"require_delimiter" => str_to_bool!(arg, v, require_delimiter),
                //"value_delimiter" => str_to_char!(arg, v, value_delimiter),
                //"required_unless" => str_to_str!(arg, v, required_unless_present),
                //"display_order" => str_to_usize!(arg, v, display_order),
                "default_value" => str_to_str!(arg, v, default_value),
                //"default_value_if" => str_tuple3!(arg, v, default_value_if),
                //"default_value_ifs" => str_tuple3!(arg, v, default_value_if),
                /*
                #[cfg(feature = "env")]
                "env" => str_to_str!(arg, v, env),
                "value_names" => str_vec_or_str!(arg, v, value_name),
                "groups" => str_vec_or_str!(arg, v, group),
                "requires" => str_vec_or_str!(arg, v, requires),
                "requires_if" => str_tuple2!(arg, v, requires_if),
                "requires_ifs" => str_tuple2!(arg, v, requires_if),
                "conflicts_with" => str_vec_or_str!(arg, v, conflicts_with),
                "overrides_with" => str_to_str!(arg, v, overrides_with),
                "possible_values" => str_vec_or_str!(arg, v, possible_value),
                "case_insensitive" => str_to_bool!(arg, v, ignore_case),
                "required_unless_one" => str_vec!(arg, v, required_unless_present_any),
                "required_unless_all" => str_vec!(arg, v, required_unless_present_all),
                */
                s => {
                    panic!(
                        "Unknown setting '{}' in YAML file for arg '{}'",
                        s, name_str
                    )
                }
            }
        }
        arg
    }
    */
    fn task_names(&self) -> Vec<String> {
        self.spec.otto.tasks.keys().cloned().collect()
    }
    fn tasks(&self) -> Vec<&Task> {
        self.spec.otto.tasks.values().collect()
    }

    pub fn parse(&self) -> Vec<ArgMatches> {
        let task_names = self.task_names();
        println!("task_names={:#?}", task_names);
        let taskargs_v = self.partition();
        println!("{:#?}", taskargs_v);
        let commands = self.tasks_to_commands();
        //println!("{:#?}", commands);
        vec![]
    }
    fn tasks_to_commands(&self) -> Vec<Command> {
        fn param_to_arg(param: &Param) -> Arg {
            println!("param={:#?}", param);
            let mut arg = Arg::new(&*param.name);
            if let Some(help) = &param.help {
                println!("help={:?}", help);
                arg = arg.help(Some(&help[..]));
            }
            arg
        }
        fn task_to_command(task: &Task) -> Command {
            let args: Vec<Arg> = task.params.values().map(param_to_arg).collect();
            Command::new(task.name.to_owned()).args(args)
        }
        self.tasks().iter().map(|t| task_to_command(t)).collect()
    }
    fn partition(&self) -> Vec<TaskArgs> {
        let args: Vec<String> = env::args().skip(1).collect();
        let mut results = vec![];
        let path = std::env::current_exe().unwrap();
        let prog = path.file_name().unwrap();
        let mut taskargs = TaskArgs::new(prog.to_str().unwrap().into());
        for arg in args {
            if self.task_names().iter().any(|t| *t == arg) {
                results.push(taskargs);
                taskargs = TaskArgs::new(arg);
            } else {
                taskargs.args.push(arg);
            }
        }
        results.push(taskargs);
        results
    }
}
<commit_msg>replaced TaskArgs with PartitionedArgs<commit_after>#![allow(unused_imports, unused_variables, unused_attributes, dead_code)]

use crate::cfg::spec::{Nargs, Otto, Param, Spec, Task, Value};
use clap::{arg, Arg, ArgMatches, Command};
use std::env;
use std::ops::Range;
use std::path::PathBuf;

#[macro_use]
use super::macros;
use super::error;

fn print_type_of<T: ?Sized>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}

#[derive(Debug, Default, PartialEq)]
pub struct Parser {
    pub spec: Spec,
    pub prog: String,
    pub args: Vec<String>,
}

#[derive(Debug, Default, PartialEq, Clone)]
struct PartitionedArgs {
    args: Vec<String>,
    partitions: Vec<Range<usize>>,
}
impl PartitionedArgs {
    fn new(tasknames: &[&str]) -> Self {
        let args: Vec<String> = env::args().collect();
        let mut beg = 0;
        let mut partitions = vec![];
        for (i, arg) in args.iter().skip(1).enumerate() {
            if tasknames.iter().any(|t| t == arg) {
                let end = i + 1;
                partitions.push(Range::<usize> { start: beg, end });
                beg = end;
            }
        }
        partitions.push(Range::<usize> {
            start: beg,
            end: args.len(),
        });
        Self { args, partitions }
    }
    fn partitions(&self) -> Vec<&[String]> {
        self.partitions
            .iter()
            .map(|p| &self.args[p.clone()])
            .collect()
    }
    fn partition(&self, index: usize) -> Option<&[String]> {
        if index < self.len() {
            return Some(&self.args[self.partitions[index].clone()]);
        }
        None
    }
    fn len(&self) -> usize {
        self.partitions.len()
    }
}

impl Parser {
    pub fn new(spec: Spec) -> Self {
        let mut args = env::args();
        Self {
            spec,
            prog: args.next().unwrap(),
            args: args.collect(),
        }
    }
    /*
    pub fn from_yaml<'a>(param: Param) -> Arg<'a> {
        let mut arg = Arg::new(param.name.as_str());
        for (k, v) in param.to_kv() {
            arg = match k.as_str().expect("Arg fields must be strings") {
                "short" => str_to_char!(arg, v, short),
                "long" => str_to_str!(arg, v, long),
                //"aliases" => str_vec_or_str!(arg, v, alias),
                "help" => str_to_str!(arg, v, help),
                //"long_help" => str_to_str!(arg, v, long_help),
                "required" => str_to_bool!(arg, v, required),
                //"required_if" => str_tuple2!(arg, v, required_if_eq),
                //"required_ifs" => str_tuple2!(arg, v, required_if_eq),
                "takes_value" => str_to_bool!(arg, v, takes_value),
                //"index" => str_to_usize!(arg, v, index),
                //"global" => str_to_bool!(arg, v, global),
                //"multiple" => str_to_bool!(arg, v, multiple_values), //note: changed multiple -> multiple_values (compiler warning)
                //"hidden" => str_to_bool!(arg, v, hide),
                //"next_line_help" => str_to_bool!(arg, v, next_line_help),
                //"group" => str_to_str!(arg, v, group),
                //"number_of_values" => str_to_usize!(arg, v, number_of_values),
                //"max_values" => str_to_usize!(arg, v, max_values),
                //"min_values" => str_to_usize!(arg, v, min_values),
                "value_name" => str_to_str!(arg, v, value_name),
                //"use_delimiter" => str_to_bool!(arg, v, use_delimiter),
                "allow_hyphen_values" => str_to_bool!(arg, v, allow_hyphen_values),
                "last" => str_to_bool!(arg, v, last),
                //"require_delimiter" => str_to_bool!(arg, v, require_delimiter),
                //"value_delimiter" => str_to_char!(arg, v, value_delimiter),
                //"required_unless" => str_to_str!(arg, v, required_unless_present),
                //"display_order" => str_to_usize!(arg, v, display_order),
                "default_value" => str_to_str!(arg, v, default_value),
                //"default_value_if" => str_tuple3!(arg, v, default_value_if),
                //"default_value_ifs" => str_tuple3!(arg, v, default_value_if),
                /*
                #[cfg(feature = "env")]
                "env" => str_to_str!(arg, v, env),
                "value_names" => str_vec_or_str!(arg, v, value_name),
                "groups" => str_vec_or_str!(arg, v, group),
                "requires" => str_vec_or_str!(arg, v, requires),
                "requires_if" => str_tuple2!(arg, v, requires_if),
                "requires_ifs" => str_tuple2!(arg, v, requires_if),
                "conflicts_with" => str_vec_or_str!(arg, v, conflicts_with),
                "overrides_with" => str_to_str!(arg, v, overrides_with),
                "possible_values" => str_vec_or_str!(arg, v, possible_value),
                "case_insensitive" => str_to_bool!(arg, v, ignore_case),
                "required_unless_one" => str_vec!(arg, v, required_unless_present_any),
                "required_unless_all" => str_vec!(arg, v, required_unless_present_all),
                */
                s => {
                    panic!(
                        "Unknown setting '{}' in YAML file for arg '{}'",
                        s, name_str
                    )
                }
            }
        }
        arg
    }
    */
    fn task_names(&self) -> Vec<&str> {
        self.spec
            .otto
            .tasks
            .keys()
            .map(AsRef::as_ref)
            .collect::<Vec<&str>>()
    }
    fn tasks(&self) -> Vec<&Task> {
        self.spec.otto.tasks.values().collect()
    }

    pub fn parse(&self) -> Vec<ArgMatches> {
        let task_names = self.task_names();
        println!("task_names={:#?}", task_names);
        let pa = PartitionedArgs::new(&task_names);
        println!("pa={:#?}", pa);
        vec![]
    }
    fn tasks_to_commands(&self) -> Vec<Command> {
        fn param_to_arg(param: &Param) -> Arg {
            println!("param={:#?}", param);
            let mut arg = Arg::new(&*param.name);
            if let Some(help) = &param.help {
                println!("help={:?}", help);
                arg = arg.help(Some(&help[..]));
            }
            arg
        }
        fn task_to_command(task: &Task) -> Command {
            let args: Vec<Arg> = task.params.values().map(param_to_arg).collect();
            Command::new(task.name.to_owned()).args(args)
        }
        self.tasks().iter().map(|t| task_to_command(t)).collect()
    }
}
<|endoftext|>


<commit_before>pub mod error;

use config::Config;

use hyper::{Client, Url};
use hyper::header::{Authorization, Bearer};
use rustc_serialize::json;
use chrono::{Date, DateTime, UTC, Datelike};
use chrono::duration::Duration;
use itertools::Itertools;

use std::io::prelude::*; // Required for read_to_string use later.
use std::str::FromStr;

use self::error::TellerClientError;

#[derive(Debug)]
pub enum Interval {
    Monthly,
}

#[derive(Debug)]
pub enum Timeframe {
    Year,
    SixMonths,
    ThreeMonths,
}

pub type ApiServiceResult<T> = Result<T, TellerClientError>;

pub type Money = (String, String);

#[derive(Debug, RustcDecodable)]
struct AccountResponse {
    data: Account,
}

#[derive(Debug, RustcDecodable)]
struct AccountsResponse {
    data: Vec<Account>,
}

#[derive(Debug, RustcDecodable)]
struct TransactionsResponse {
    data: Vec<Transaction>,
}

#[derive(Debug, RustcDecodable)]
pub struct Account {
    pub updated_at: String,
    pub institution: String,
    pub id: String,
    pub currency: String,
    pub balance: String,
    pub account_number_last_4: String,
}

#[derive(Debug, RustcDecodable)]
pub struct Transaction {
    pub description: String,
    pub date: String,
    pub counterparty: String,
    pub amount: String,
}

#[derive(Debug)]
pub struct Balances {
    pub historical_amounts: Vec<(String, String)>,
    pub currency: String,
}

impl Balances {
    pub fn new(historical_amounts: Vec<(String, String)>, currency: String) -> Balances {
        Balances {
            historical_amounts: historical_amounts,
            currency: currency,
        }
    }
}

fn get_auth_header(auth_token: &String) -> Authorization<Bearer> {
    Authorization(
        Bearer {
            token: auth_token.to_owned()
        }
    )
}

pub fn get_accounts(config: &Config) -> ApiServiceResult<Vec<Account>> {
    let client = Client::new();

    let mut res = try!(
        client.get("https://api.teller.io/accounts")
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /accounts response: {}", body);

    let accounts_response: AccountsResponse = try!(json::decode(&body));

    Ok(accounts_response.data)
}

pub fn get_account(config: &Config, account_id: &str) -> ApiServiceResult<Account> {
    let client = Client::new();

    let mut res = try!(
        client.get(&format!("https://api.teller.io/accounts/{}", account_id))
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /account/:id response: {}", body);

    let account_response: AccountResponse = try!(json::decode(&body));

    Ok(account_response.data)
}

pub fn get_account_balance(config: &Config, account_id: String) -> ApiServiceResult<Money> {
    let to_balance_tuple = |a: Account| (a.balance, a.currency);
    get_account(&config, &account_id).map(to_balance_tuple)
}

pub fn raw_transactions(config: &Config, account_id: &str, count: u32, page: u32) -> ApiServiceResult<Vec<Transaction>> {
    let mut url = Url::parse(&format!("https://api.teller.io/accounts/{}/transactions", account_id)).unwrap();

    const COUNT: &'static str = "count";
    const PAGE: &'static str = "page";
    let query = vec![ (COUNT, count.to_string()), (PAGE, page.to_string()) ];
    url.set_query_from_pairs(query.into_iter());

    let client = Client::new();
    let mut res = try!(
        client.get(url)
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /account/:id/transactions response: {}", body);

    let transactions_response: TransactionsResponse = try!(json::decode(&body));

    Ok(transactions_response.data)
}

fn parse_utc_date_from_transaction(t: &Transaction) -> Date<UTC> {
    let full_date = &(t.date.to_owned() + "T00:00:00-00:00");
    let past_transaction_date_without_tz = DateTime::parse_from_rfc3339(full_date).unwrap().date();
    let past_transaction_date = past_transaction_date_without_tz.with_timezone(&UTC);
    past_transaction_date
}

pub fn get_transactions(config: &Config, account_id: &str, timeframe: &Timeframe) -> ApiServiceResult<Vec<Transaction>> {
    let page_through_transactions = |from| -> ApiServiceResult<Vec<Transaction>> {
        let mut all_transactions = vec![];

        let mut fetching = true;
        let mut page = 1;
        let count = 250;
        while fetching {
            let mut transactions = try!(raw_transactions(config, &account_id, count, page));
            match transactions.last() {
                None => {
                    // If there are no transactions left, do not fetch forever...
                    fetching = false
                },
                Some(past_transaction) => {
                    let past_transaction_date = parse_utc_date_from_transaction(&past_transaction);
                    if past_transaction_date < from {
                        fetching = false;
                    }
                },
            };

            all_transactions.append(&mut transactions);
            page = page + 1;
        }

        all_transactions = all_transactions.into_iter().filter(|t| {
            let transaction_date = parse_utc_date_from_transaction(&t);
            transaction_date > from
        }).collect();

        all_transactions.reverse();
        Ok(all_transactions)
    };

    match *timeframe {
        Timeframe::ThreeMonths => {
            let to = UTC::today();
            let from = to - Duration::days(91); // close enough... 😅

            page_through_transactions(from)
        },
        Timeframe::SixMonths => {
            let to = UTC::today();
            let from = to - Duration::days(183);

            page_through_transactions(from)
        },
        Timeframe::Year => {
            let to = UTC::today();
            let from = to - Duration::days(365);

            page_through_transactions(from)
        },
    }
}

pub fn get_balances(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Balances> {
    let transactions: Vec<Transaction> = get_transactions(&config, &account_id, &timeframe).unwrap_or(vec![]);

    let month_year_total_transactions: Vec<(String, i64)> = transactions.into_iter().group_by(|t| {
        let transaction_date = parse_utc_date_from_transaction(&t);
        match *interval {
            Interval::Monthly => {
                let group_name = transaction_date.format("%m-%Y").to_string();
                group_name
            }
        }
    }).map(|myt| {
        let group_name = myt.0;
        let amount = myt.1.into_iter().map(|t| {
            let v = (f64::from_str(&t.amount).unwrap() * 100f64).round() as i64;
            v
        }).fold(0i64, |sum, v| sum + v);
        (group_name, amount)
    }).collect();

    let account = try!(get_account(&config, &account_id));
    let current_balance = (f64::from_str(&account.balance).unwrap() * 100f64).round() as i64;
    let currency = account.currency;

    let mut historical_amounts: Vec<(String, String)> = vec![];

    let mut last_balance = current_balance;
    for mytt in month_year_total_transactions {
        last_balance = last_balance - mytt.1;
        historical_amounts.push((mytt.0.to_string(), format!("{:.2}", last_balance as f64 / 100f64)));
    }
    historical_amounts.push(("current".to_string(), format!("{:.2}", current_balance as f64 / 100f64)));

    Ok(Balances::new(historical_amounts, currency))
}
<commit_msg>wip(balances): numbers are more correct - still something off...<commit_after>pub mod error;

use config::Config;

use hyper::{Client, Url};
use hyper::header::{Authorization, Bearer};
use rustc_serialize::json;
use chrono::{Date, DateTime, UTC};
use chrono::duration::Duration;
use itertools::Itertools;

use std::io::prelude::*; // Required for read_to_string use later.
use std::str::FromStr;

use self::error::TellerClientError;

#[derive(Debug)]
pub enum Interval {
    Monthly,
}

#[derive(Debug)]
pub enum Timeframe {
    Year,
    SixMonths,
    ThreeMonths,
}

pub type ApiServiceResult<T> = Result<T, TellerClientError>;

pub type Money = (String, String);

#[derive(Debug, RustcDecodable)]
struct AccountResponse {
    data: Account,
}

#[derive(Debug, RustcDecodable)]
struct AccountsResponse {
    data: Vec<Account>,
}

#[derive(Debug, RustcDecodable)]
struct TransactionsResponse {
    data: Vec<Transaction>,
}

#[derive(Debug, RustcDecodable)]
pub struct Account {
    pub updated_at: String,
    pub institution: String,
    pub id: String,
    pub currency: String,
    pub balance: String,
    pub account_number_last_4: String,
}

#[derive(Debug, RustcDecodable)]
pub struct Transaction {
    pub description: String,
    pub date: String,
    pub counterparty: String,
    pub amount: String,
}

#[derive(Debug)]
pub struct Balances {
    pub historical_amounts: Vec<(String, String)>,
    pub currency: String,
}

impl Balances {
    pub fn new(historical_amounts: Vec<(String, String)>, currency: String) -> Balances {
        Balances {
            historical_amounts: historical_amounts,
            currency: currency,
        }
    }
}

fn get_auth_header(auth_token: &String) -> Authorization<Bearer> {
    Authorization(
        Bearer {
            token: auth_token.to_owned()
        }
    )
}

pub fn get_accounts(config: &Config) -> ApiServiceResult<Vec<Account>> {
    let client = Client::new();

    let mut res = try!(
        client.get("https://api.teller.io/accounts")
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /accounts response: {}", body);

    let accounts_response: AccountsResponse = try!(json::decode(&body));

    Ok(accounts_response.data)
}

pub fn get_account(config: &Config, account_id: &str) -> ApiServiceResult<Account> {
    let client = Client::new();

    let mut res = try!(
        client.get(&format!("https://api.teller.io/accounts/{}", account_id))
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /account/:id response: {}", body);

    let account_response: AccountResponse = try!(json::decode(&body));

    Ok(account_response.data)
}

pub fn get_account_balance(config: &Config, account_id: String) -> ApiServiceResult<Money> {
    let to_balance_tuple = |a: Account| (a.balance, a.currency);
    get_account(&config, &account_id).map(to_balance_tuple)
}

pub fn raw_transactions(config: &Config, account_id: &str, count: u32, page: u32) -> ApiServiceResult<Vec<Transaction>> {
    let mut url = Url::parse(&format!("https://api.teller.io/accounts/{}/transactions", account_id)).unwrap();

    const COUNT: &'static str = "count";
    const PAGE: &'static str = "page";
    let query = vec![ (COUNT, count.to_string()), (PAGE, page.to_string()) ];
    url.set_query_from_pairs(query.into_iter());

    let client = Client::new();
    let mut res = try!(
        client.get(url)
              .header(get_auth_header(&config.auth_token))
              .send()
    );
    if res.status.is_client_error() {
        return Err(TellerClientError::AuthenticationError);
    }

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    debug!("GET /account/:id/transactions response: {}", body);

    let transactions_response: TransactionsResponse = try!(json::decode(&body));

    Ok(transactions_response.data)
}

fn parse_utc_date_from_transaction(t: &Transaction) -> Date<UTC> {
    let full_date = &(t.date.to_owned() + "T00:00:00-00:00");
    let past_transaction_date_without_tz = DateTime::parse_from_rfc3339(full_date).unwrap().date();
    let past_transaction_date = past_transaction_date_without_tz.with_timezone(&UTC);
    past_transaction_date
}

pub fn get_transactions(config: &Config, account_id: &str, timeframe: &Timeframe) -> ApiServiceResult<Vec<Transaction>> {
    let page_through_transactions = |from| -> ApiServiceResult<Vec<Transaction>> {
        let mut all_transactions = vec![];

        let mut fetching = true;
        let mut page = 1;
        let count = 250;
        while fetching {
            let mut transactions = try!(raw_transactions(config, &account_id, count, page));
            match transactions.last() {
                None => {
                    // If there are no transactions left, do not fetch forever...
                    fetching = false
                },
                Some(past_transaction) => {
                    let past_transaction_date = parse_utc_date_from_transaction(&past_transaction);
                    if past_transaction_date < from {
                        fetching = false;
                    }
                },
            };

            all_transactions.append(&mut transactions);
            page = page + 1;
        }

        all_transactions = all_transactions.into_iter().filter(|t| {
            let transaction_date = parse_utc_date_from_transaction(&t);
            transaction_date > from
        }).collect();

        all_transactions.reverse();
        Ok(all_transactions)
    };

    match *timeframe {
        Timeframe::ThreeMonths => {
            let to = UTC::today();
            let from = to - Duration::days(91); // close enough... 😅

            page_through_transactions(from)
        },
        Timeframe::SixMonths => {
            let to = UTC::today();
            let from = to - Duration::days(183);

            page_through_transactions(from)
        },
        Timeframe::Year => {
            let to = UTC::today();
            let from = to - Duration::days(365);

            page_through_transactions(from)
        },
    }
}

pub fn get_balances(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Balances> {
    let transactions: Vec<Transaction> = get_transactions(&config, &account_id, &timeframe).unwrap_or(vec![]);

    let mut month_year_total_transactions: Vec<(String, i64)> = transactions.into_iter().group_by(|t| {
        let transaction_date = parse_utc_date_from_transaction(&t);
        match *interval {
            Interval::Monthly => {
                let group_name = transaction_date.format("%m-%Y").to_string();
                group_name
            }
        }
    }).map(|myt| {
        let group_name = myt.0;
        let amount = myt.1.into_iter().map(|t| {
            let v = (f64::from_str(&t.amount).unwrap() * 100f64).round() as i64;
            v
        }).fold(0i64, |sum, v| sum + v);
        (group_name, amount)
    }).collect();
    month_year_total_transactions.reverse();

    let account = try!(get_account(&config, &account_id));
    let current_balance = (f64::from_str(&account.balance).unwrap() * 100f64).round() as i64;
    let currency = account.currency;

    let mut historical_amounts: Vec<(String, String)> = vec![];
    historical_amounts.push(("current".to_string(), format!("{:.2}", current_balance as f64 / 100f64)));

    let mut last_balance = current_balance;
    for mytt in month_year_total_transactions {
        last_balance = last_balance - mytt.1;
        historical_amounts.push((mytt.0.to_string(), format!("{:.2}", last_balance as f64 / 100f64)));
    }
    historical_amounts.reverse();

    Ok(Balances::new(historical_amounts, currency))
}
<|endoftext|>


<commit_before>// base💯 - Copyright 2017 Adam Niederer

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#![allow(non_upper_case_globals)]
#![cfg_attr(test, feature(test))]
#![cfg_attr(feature = "simd", feature(target_feature))]
#![cfg_attr(feature = "simd", feature(cfg_target_feature))]

#[macro_use] extern crate clap;
#[cfg(feature = "simd")] extern crate stdsimd;

use std::io::{self, Read, Write, BufRead, BufReader, BufWriter};
use std::fs::File;
use std::iter::Iterator;
use clap::App;

fn main() {
    let cli_spec = load_yaml!("cli.yml");
    let cli_args = App::from_yaml(cli_spec).get_matches();

    let mut reader = {
        if let Some(path) = cli_args.value_of("input") {
            Box::new(BufReader::new(match File::open(path) {
                Ok(path) => path,
                _ => {
                    writeln!(io::stderr(), "base💯: no such file: {}", path).expect("base💯: stderr write error");
                    return;
                }
            })) as Box<BufRead>
        } else {
            Box::new(BufReader::new(io::stdin())) as Box<BufRead>
        }
    };

    let mut writer = BufWriter::new(io::stdout());

    if cli_args.is_present("decode") {
        let mut write_buf = [0u8; 0x10000];
        let mut buffer = [0u8; 0x10000];

        while let Ok(num_read) = reader.read(&mut buffer) {
            if num_read == 0 {
                break;
            }

            match writer.write_all(&emoji_to_char(&buffer[..num_read], &mut write_buf)[..num_read / 4]) {
                Ok(_) => (),
                _ => {
                    writeln!(io::stderr(), "base💯: write error").expect("base💯: stderr write error");
                    return;
                }
            }
        }
    } else {
        let mut write_buf = [0u8; 0x40000];
        let mut buffer = [0u8; 0x10000];

        while let Ok(num_read) = reader.read(&mut buffer) {
            if num_read == 0 {
                break;
            }

            match writer.write_all(&char_to_emoji(&buffer[..num_read], &mut write_buf)[..num_read * 4]) {
                Ok(_) => (),
                _ => {
                    writeln!(io::stderr(), "base💯: write error").expect("base💯: stderr write error");
                    return;
                }
            }
        }
    }
    writer.flush().expect("Write error");
}

#[cfg(any(not(feature = "simd"), not(target_arch = "x86_64")))]
fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    for (i, chunk) in buf.chunks(4).enumerate() {
        out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(target_feature = "avx2")]
pub fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    use stdsimd::simd::u8x32;
    use stdsimd::vendor::{_mm256_packus_epi32, _mm256_packus_epi16, _mm256_and_si256, _mm256_shuffle_pd};
    let mut i = 0;
    for chunk in buf.chunks(128) {
        if chunk.len() < 128 {
            // Non-SIMD implementation for the final <128 bytes
            for (i, chunk) in chunk.chunks(4).enumerate() {
                out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
            }
        } else {
            // AVX implementation of decoding algo

            // TODO: Use Get rid of these scalar loads
            let msbs = u8x32::new(chunk[2], chunk[6], chunk[10], chunk[14], chunk[18], chunk[22], chunk[26], chunk[30], chunk[34], chunk[38], chunk[42], chunk[46], chunk[50], chunk[54], chunk[58], chunk[62], chunk[66], chunk[70], chunk[74], chunk[78], chunk[82], chunk[86], chunk[90], chunk[94], chunk[98], chunk[102], chunk[106], chunk[110], chunk[114], chunk[118], chunk[122], chunk[126]);
            let lsbs = u8x32::new(chunk[3], chunk[7], chunk[11], chunk[15], chunk[19], chunk[23], chunk[27], chunk[31], chunk[35], chunk[39], chunk[43], chunk[47], chunk[51], chunk[55], chunk[59], chunk[63], chunk[67], chunk[71], chunk[75], chunk[79], chunk[83], chunk[87], chunk[91], chunk[95], chunk[99], chunk[103], chunk[107], chunk[111], chunk[115], chunk[119], chunk[123], chunk[127]);
            ((((msbs - u8x32::splat(143)) * u8x32::splat(64))
              + lsbs - u8x32::splat(128)) - u8x32::splat(55))
                .store(out, i);
            i += 64;
        }
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(all(not(target_feature = "avx2"), target_feature = "sse2"))]
pub fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    use stdsimd::simd::u8x16;
    let mut i = 0;
    for chunk in buf.chunks(64) {
        // Chunk data format: 0x00 0x00 0xhi 0xlo
        if chunk.len() < 64 {
            // Non-SIMD implementation for the final <128 bytes
            for (i, chunk) in chunk.chunks(4).enumerate() {
                out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
            }
        } else {

            // SSE2 implementation of decoding algo

            // TODO: Use Get rid of these scalar loads
            let msbs = u8x16::new(chunk[2], chunk[6], chunk[10], chunk[14], chunk[18], chunk[22], chunk[26], chunk[30], chunk[34], chunk[38], chunk[42], chunk[46], chunk[50], chunk[54], chunk[58], chunk[62]);
            let lsbs = u8x16::new(chunk[3], chunk[7], chunk[11], chunk[15], chunk[19], chunk[23], chunk[27], chunk[31], chunk[35], chunk[39], chunk[43], chunk[47], chunk[51], chunk[55], chunk[59], chunk[63]);
            ((((msbs - u8x16::splat(143)) * u8x16::splat(64))
              + lsbs - u8x16::splat(128)) - u8x16::splat(55))
                .store(out, i);
            i += 16;
        }
    }
    out
}

#[cfg(any(not(feature = "simd"), not(target_arch = "x86_64")))]
pub fn char_to_emoji<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b [u8] {
    for (i, ch) in buf.iter().enumerate() {
        out[4 * i + 0] = 0xf0;
        out[4 * i + 1] = 0x9f;
        out[4 * i + 2] = (((*ch as u16).wrapping_add(55)) / 64 + 143) as u8;
        out[4 * i + 3] = (ch.wrapping_add(55) % 64).wrapping_add(128);
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(target_feature = "sse2")]
pub fn char_to_emoji<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b [u8] {
    // TODO: SSE this up
    for (i, ch) in buf.iter().enumerate() {
        out[4 * i + 0] = 0xf0;
        out[4 * i + 1] = 0x9f;
        out[4 * i + 2] = (((*ch as u16).wrapping_add(55)) / 64 + 143) as u8;
        out[4 * i + 3] = (ch.wrapping_add(55) % 64).wrapping_add(128);
    }
    out
}
<commit_msg>Add partial implementation of vectorized loads on AVX2<commit_after>// base💯 - Copyright 2017 Adam Niederer

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#![allow(non_upper_case_globals)]
#![cfg_attr(test, feature(test))]
#![cfg_attr(feature = "simd", feature(target_feature))]
#![cfg_attr(feature = "simd", feature(cfg_target_feature))]

#[macro_use] extern crate clap;
#[cfg(feature = "simd")] extern crate stdsimd;

use std::io::{self, Read, Write, BufRead, BufReader, BufWriter};
use std::fs::File;
use std::iter::Iterator;
use clap::App;

fn main() {
    let cli_spec = load_yaml!("cli.yml");
    let cli_args = App::from_yaml(cli_spec).get_matches();

    let mut reader = {
        if let Some(path) = cli_args.value_of("input") {
            Box::new(BufReader::new(match File::open(path) {
                Ok(path) => path,
                _ => {
                    writeln!(io::stderr(), "base💯: no such file: {}", path).expect("base💯: stderr write error");
                    return;
                }
            })) as Box<BufRead>
        } else {
            Box::new(BufReader::new(io::stdin())) as Box<BufRead>
        }
    };

    let mut writer = BufWriter::new(io::stdout());

    if cli_args.is_present("decode") {
        let mut write_buf = [0u8; 0x10000];
        let mut buffer = [0u8; 0x10000];

        while let Ok(num_read) = reader.read(&mut buffer) {
            if num_read == 0 {
                break;
            }

            match writer.write_all(&emoji_to_char(&buffer[..num_read], &mut write_buf)[..num_read / 4]) {
                Ok(_) => (),
                _ => {
                    writeln!(io::stderr(), "base💯: write error").expect("base💯: stderr write error");
                    return;
                }
            }
        }
    } else {
        let mut write_buf = [0u8; 0x40000];
        let mut buffer = [0u8; 0x10000];

        while let Ok(num_read) = reader.read(&mut buffer) {
            if num_read == 0 {
                break;
            }

            match writer.write_all(&char_to_emoji(&buffer[..num_read], &mut write_buf)[..num_read * 4]) {
                Ok(_) => (),
                _ => {
                    writeln!(io::stderr(), "base💯: write error").expect("base💯: stderr write error");
                    return;
                }
            }
        }
    }
    writer.flush().expect("Write error");
}

#[cfg(any(not(feature = "simd"), not(target_arch = "x86_64")))]
fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    for (i, chunk) in buf.chunks(4).enumerate() {
        out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(target_feature = "avx2")]
pub fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    use stdsimd::simd::u8x32;
    use stdsimd::vendor::{_mm256_packus_epi32, _mm256_packus_epi16, _mm256_and_si256, _mm256_shuffle_pd};
    let mut i = 0;
    for chunk in buf.chunks(128) {
        if chunk.len() < 128 {
            // Non-SIMD implementation for the final <128 bytes
            for (i, chunk) in chunk.chunks(4).enumerate() {
                out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
            }
        } else {
            // AVX implementation of decoding algo
            // a, b, c, d contain one garbage word and one useful word
            let a_dirty = u8x32::load(chunk, i);
            let b_dirty = u8x32::load(chunk, i + 32);
            let c_dirty = u8x32::load(chunk, i + 64);
            let d_dirty = u8x32::load(chunk, i + 96);
            let dirty_mask = i8x32::new(0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF,
                                        0x00, 0x00, 0xFF, 0xFF);
            // Make a, b, c, d contain one 0x00 and one userful word
            let a_dirty_masked = _mm256_and_si256(a_dirty, dirty_mask);
            let b_dirty_masked = _mm256_and_si256(b_dirty, dirty_mask);
            let c_dirty_masked = _mm256_and_si256(c_dirty, dirty_mask);
            let d_dirty_masked = _mm256_and_si256(d_dirty, dirty_mask);

            // Pack useful words of a, b, c, d
            let a_interleaved = _mm256_packus_epi32(a_dirty_masked, b_dirty_masked) as u8x32;
            let b_interleaved = _mm256_packus_epi32(c_dirty_masked, d_dirty_masked) as u8x32;

            // Shuffle bytes in words and zero out the high bit
            let hi_mask = i8x32::new(0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00,
                                     0xFF, 0x00, 0xFF, 0x00);

            let lo_mask = i8x32::new(0x80, 0x00, 0x80, 0x02, 0x80, 0x04, 0x80, 0x06,
                                     0x80, 0x08, 0x80, 0x0A, 0x80, 0x0C, 0x80, 0x0E,
                                     0x80, 0x10, 0x80, 0x12, 0x80, 0x14, 0x80, 0x16,
                                     0x80, 0x18, 0x80, 0x1A, 0x80, 0x1C, 0x80, 0x1E);

            let a_hi_masked = _mm256_and_si256(a_interleaved, hi_mask);
            let b_hi_masked = _mm256_and_si256(b_interleaved, hi_mask);
            let a_lo_masked = _mm256_shuffle_epi8(a_interleaved, lo_mask);
            let b_lo_masked = _mm256_shuffle_epi8(b_interleaved, lo_mask);

            let hi = _mm256_packus_epi16(a_hi_masked, b_hi_masked);
            let lo = _mm256_packus_epi16(a_lo_masked, b_lo_masked);

            ((((hi - u8x32::splat(143)) * u8x32::splat(64))
              + lo - u8x32::splat(128)) - u8x32::splat(55))
                .store(out, i);

            // TODO: Use Get rid of these scalar loads
            let msbs = u8x32::new(chunk[2], chunk[6], chunk[10], chunk[14], chunk[18], chunk[22], chunk[26], chunk[30], chunk[34], chunk[38], chunk[42], chunk[46], chunk[50], chunk[54], chunk[58], chunk[62], chunk[66], chunk[70], chunk[74], chunk[78], chunk[82], chunk[86], chunk[90], chunk[94], chunk[98], chunk[102], chunk[106], chunk[110], chunk[114], chunk[118], chunk[122], chunk[126]);
            let lsbs = u8x32::new(chunk[3], chunk[7], chunk[11], chunk[15], chunk[19], chunk[23], chunk[27], chunk[31], chunk[35], chunk[39], chunk[43], chunk[47], chunk[51], chunk[55], chunk[59], chunk[63], chunk[67], chunk[71], chunk[75], chunk[79], chunk[83], chunk[87], chunk[91], chunk[95], chunk[99], chunk[103], chunk[107], chunk[111], chunk[115], chunk[119], chunk[123], chunk[127]);
            ((((msbs - u8x32::splat(143)) * u8x32::splat(64))
              + lsbs - u8x32::splat(128)) - u8x32::splat(55))
                .store(out, i);
            i += 64;
        }
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(all(not(target_feature = "avx2"), target_feature = "sse2"))]
pub fn emoji_to_char<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b[u8] {
    use stdsimd::simd::u8x16;
    let mut i = 0;
    for chunk in buf.chunks(64) {
        // Chunk data format: 0x00 0x00 0xhi 0xlo
        if chunk.len() < 64 {
            // Non-SIMD implementation for the final <128 bytes
            for (i, chunk) in chunk.chunks(4).enumerate() {
                out[i] = ((chunk[2].wrapping_sub(143)).wrapping_mul(64)).wrapping_add(chunk[3].wrapping_sub(128)).wrapping_sub(55)
            }
        } else {

            // SSE2 implementation of decoding algo

            // TODO: Use Get rid of these scalar loads
            let msbs = u8x16::new(chunk[2], chunk[6], chunk[10], chunk[14], chunk[18], chunk[22], chunk[26], chunk[30], chunk[34], chunk[38], chunk[42], chunk[46], chunk[50], chunk[54], chunk[58], chunk[62]);
            let lsbs = u8x16::new(chunk[3], chunk[7], chunk[11], chunk[15], chunk[19], chunk[23], chunk[27], chunk[31], chunk[35], chunk[39], chunk[43], chunk[47], chunk[51], chunk[55], chunk[59], chunk[63]);
            ((((msbs - u8x16::splat(143)) * u8x16::splat(64))
              + lsbs - u8x16::splat(128)) - u8x16::splat(55))
                .store(out, i);
            i += 16;
        }
    }
    out
}

#[cfg(any(not(feature = "simd"), not(target_arch = "x86_64")))]
pub fn char_to_emoji<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b [u8] {
    for (i, ch) in buf.iter().enumerate() {
        out[4 * i + 0] = 0xf0;
        out[4 * i + 1] = 0x9f;
        out[4 * i + 2] = (((*ch as u16).wrapping_add(55)) / 64 + 143) as u8;
        out[4 * i + 3] = (ch.wrapping_add(55) % 64).wrapping_add(128);
    }
    out
}

#[cfg(feature = "simd")]
#[cfg(target_feature = "sse2")]
pub fn char_to_emoji<'a, 'b>(buf: &'a[u8], out: &'b mut [u8]) -> &'b [u8] {
    // TODO: SSE this up
    for (i, ch) in buf.iter().enumerate() {
        out[4 * i + 0] = 0xf0;
        out[4 * i + 1] = 0x9f;
        out[4 * i + 2] = (((*ch as u16).wrapping_add(55)) / 64 + 143) as u8;
        out[4 * i + 3] = (ch.wrapping_add(55) % 64).wrapping_add(128);
    }
    out
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]
#![feature(question_mark)]

#[macro_use] extern crate log;
extern crate arc_cache;
extern crate bytes;
extern crate civet;
extern crate clap;
extern crate conduit_middleware;
extern crate conduit_router;
extern crate conduit;
extern crate env_logger;
extern crate mio;
extern crate nix;
extern crate rand;
extern crate rustc_serialize;
extern crate slab;

mod cache;
mod client_query;
mod client;
mod dns;
mod resolver;
mod tcp_listener;
mod udp_listener;
mod varz;
mod webservice;

use cache::Cache;
use clap::{Arg, App};
use resolver::*;
use std::net::UdpSocket;
use std::sync::Arc;
use std::str::FromStr;
use tcp_listener::*;
use udp_listener::*;
use varz::*;
use webservice::*;

const DNS_MAX_SIZE: usize = 65535;
const DNS_MAX_TCP_SIZE: usize = 65535;
const DNS_MAX_UDP_SIZE: usize = 4096;
const DNS_QUERY_MAX_SIZE: usize = 283;
const DNS_QUERY_MIN_SIZE: usize = 17;
const DNS_UDP_NOEDNS0_MAX_SIZE: usize = 512;
const HEALTH_CHECK_MS: u64 = 10 * 1000;
const MAX_ACTIVE_QUERIES: usize = 100_000;
const MAX_CLIENTS_WAITING_FOR_QUERY: usize = 1_000;
const MAX_TCP_CLIENTS: usize = 1_000;
const MAX_TCP_HASH_DISTANCE: usize = 10;
const MAX_TCP_IDLE_MS: u64 = 10 * 1000;
const MAX_WAITING_CLIENTS: usize = MAX_ACTIVE_QUERIES * 10;
const MIN_TTL: u32 = 60;
const MAX_TTL: u32 = 86400;
const FAILURE_TTL: u32 = 30;
const UDP_BUFFER_SIZE: usize = 16 * 1024 * 1024;
const UPSTREAM_INITIAL_TIMEOUT_MS: u64 = 1 * 1000;
const UPSTREAM_MAX_TIMEOUT_MS: u64 = 8 * 1000;
const UPSTREAM_TIMEOUT_MS: u64 = 10 * 1000;
const WEBSERVICE_PORT: u16 = 8888;
const WEBSERVICE_THREADS: u32 = 2;

pub struct RPDNSContext {
    pub udp_socket: UdpSocket,
    pub listen_addr: String,
    pub cache: Cache,
    pub varz: Arc<Varz>
}

struct RPDNS;

impl RPDNS {
    fn new(cache_size: usize, listen_addr: &str, upstream_servers_str: Vec<&str>, decrement_ttl: bool, failover: bool, ports: u16, max_failures: u32) -> RPDNS {
        let varz = Arc::new(Varz::default());
        let cache = Cache::new(cache_size, decrement_ttl);
        let udp_socket = socket_udp_bound(&listen_addr).expect("Unable to create a client socket");
        let rpdns_context = RPDNSContext {
            udp_socket: udp_socket,
            listen_addr: listen_addr.to_owned(),
            cache: cache,
            varz: varz
        };
        let resolver_tx = Resolver::spawn(&rpdns_context, upstream_servers_str, decrement_ttl, failover, ports, max_failures).expect("Unable to spawn the resolver");

        let _ = WebService::spawn(&rpdns_context).expect("Unable to spawn the web service");
        let udp_listener = UdpListener::spawn(&rpdns_context, resolver_tx.clone()).expect("Unable to spawn a UDP listener");
        let tcp_listener = TcpListener::spawn(&rpdns_context, resolver_tx.clone()).expect("Unable to spawn a TCP listener");
        let _ = udp_listener.join();
        let _ = tcp_listener.join();

        RPDNS
    }
}

fn main() {
    env_logger::init().expect("Failed to init logger");

    let matches = App::new("EdgeDNS").version("0.1").author("Frank Denis").about("A caching DNS reverse proxy").

    arg(Arg::with_name("upstream_servers_str").short("u").long("upstream").value_name("server:port,server:port...").help("Comma-delimited list of upstream servers").use_delimiter(true).default_value("8.8.8.8:53,8.8.4.4:53")).

    arg(Arg::with_name("listen_addr").short("l").long("listen").value_name("address:port").help("Listen address").takes_value(true).default_value("127.0.0.1:53")).

    arg(Arg::with_name("cache_size").short("c").long("cachesize").value_name("count").help("Max number of cached entries").takes_value(true).default_value("250000")).

    arg(Arg::with_name("decrement_ttl").short("r").long("resolver-mode").help("Resolver mode, decrements TTL").takes_value(false)).

    arg(Arg::with_name("failover").short("f").long("failover").help("Failover; try upstream servers sequentially instead of balancing the load").takes_value(false)).

    arg(Arg::with_name("ports_count").short("p").long("ports-count").value_name("count").help("Max number of UDP ports to use for outgoing connections, up to 64511").takes_value(true).default_value("8")).

    arg(Arg::with_name("upstream_max_failures").short("F").long("max-failures").value_name("count").help("Max failures before marking a server as temporarily unresponsive").takes_value(true).default_value("3")).

    get_matches();
    let upstream_servers_str: Vec<&str> = matches.values_of("upstream_servers_str").unwrap().collect();
    let listen_addr = matches.value_of("listen_addr").unwrap();
    let cache_size = FromStr::from_str(matches.value_of("cache_size").unwrap()).expect("Invalid number of cached entries");
    let decrement_ttl = matches.is_present("decrement_ttl");
    let failover = matches.is_present("failover");
    let ports = FromStr::from_str(matches.value_of("ports_count").unwrap()).expect("Invalid number of ports");
    let upstream_max_failures = FromStr::from_str(matches.value_of("upstream_max_failures").unwrap()).expect("Invalid value for the maximum number of failures");

    let _ = RPDNS::new(cache_size, listen_addr, upstream_servers_str, decrement_ttl, failover, ports, upstream_max_failures);
}
<commit_msg>Remove the rustc_private feature gate<commit_after>#![feature(question_mark)]

#[macro_use] extern crate log;
extern crate arc_cache;
extern crate bytes;
extern crate civet;
extern crate clap;
extern crate conduit_middleware;
extern crate conduit_router;
extern crate conduit;
extern crate env_logger;
extern crate mio;
extern crate nix;
extern crate rand;
extern crate rustc_serialize;
extern crate slab;

mod cache;
mod client_query;
mod client;
mod dns;
mod resolver;
mod tcp_listener;
mod udp_listener;
mod varz;
mod webservice;

use cache::Cache;
use clap::{Arg, App};
use resolver::*;
use std::net::UdpSocket;
use std::sync::Arc;
use std::str::FromStr;
use tcp_listener::*;
use udp_listener::*;
use varz::*;
use webservice::*;

const DNS_MAX_SIZE: usize = 65535;
const DNS_MAX_TCP_SIZE: usize = 65535;
const DNS_MAX_UDP_SIZE: usize = 4096;
const DNS_QUERY_MAX_SIZE: usize = 283;
const DNS_QUERY_MIN_SIZE: usize = 17;
const DNS_UDP_NOEDNS0_MAX_SIZE: usize = 512;
const HEALTH_CHECK_MS: u64 = 10 * 1000;
const MAX_ACTIVE_QUERIES: usize = 100_000;
const MAX_CLIENTS_WAITING_FOR_QUERY: usize = 1_000;
const MAX_TCP_CLIENTS: usize = 1_000;
const MAX_TCP_HASH_DISTANCE: usize = 10;
const MAX_TCP_IDLE_MS: u64 = 10 * 1000;
const MAX_WAITING_CLIENTS: usize = MAX_ACTIVE_QUERIES * 10;
const MIN_TTL: u32 = 60;
const MAX_TTL: u32 = 86400;
const FAILURE_TTL: u32 = 30;
const UDP_BUFFER_SIZE: usize = 16 * 1024 * 1024;
const UPSTREAM_INITIAL_TIMEOUT_MS: u64 = 1 * 1000;
const UPSTREAM_MAX_TIMEOUT_MS: u64 = 8 * 1000;
const UPSTREAM_TIMEOUT_MS: u64 = 10 * 1000;
const WEBSERVICE_PORT: u16 = 8888;
const WEBSERVICE_THREADS: u32 = 2;

pub struct RPDNSContext {
    pub udp_socket: UdpSocket,
    pub listen_addr: String,
    pub cache: Cache,
    pub varz: Arc<Varz>
}

struct RPDNS;

impl RPDNS {
    fn new(cache_size: usize, listen_addr: &str, upstream_servers_str: Vec<&str>, decrement_ttl: bool, failover: bool, ports: u16, max_failures: u32) -> RPDNS {
        let varz = Arc::new(Varz::default());
        let cache = Cache::new(cache_size, decrement_ttl);
        let udp_socket = socket_udp_bound(&listen_addr).expect("Unable to create a client socket");
        let rpdns_context = RPDNSContext {
            udp_socket: udp_socket,
            listen_addr: listen_addr.to_owned(),
            cache: cache,
            varz: varz
        };
        let resolver_tx = Resolver::spawn(&rpdns_context, upstream_servers_str, decrement_ttl, failover, ports, max_failures).expect("Unable to spawn the resolver");

        let _ = WebService::spawn(&rpdns_context).expect("Unable to spawn the web service");
        let udp_listener = UdpListener::spawn(&rpdns_context, resolver_tx.clone()).expect("Unable to spawn a UDP listener");
        let tcp_listener = TcpListener::spawn(&rpdns_context, resolver_tx.clone()).expect("Unable to spawn a TCP listener");
        let _ = udp_listener.join();
        let _ = tcp_listener.join();

        RPDNS
    }
}

fn main() {
    env_logger::init().expect("Failed to init logger");

    let matches = App::new("EdgeDNS").version("0.1").author("Frank Denis").about("A caching DNS reverse proxy").

    arg(Arg::with_name("upstream_servers_str").short("u").long("upstream").value_name("server:port,server:port...").help("Comma-delimited list of upstream servers").use_delimiter(true).default_value("8.8.8.8:53,8.8.4.4:53")).

    arg(Arg::with_name("listen_addr").short("l").long("listen").value_name("address:port").help("Listen address").takes_value(true).default_value("127.0.0.1:53")).

    arg(Arg::with_name("cache_size").short("c").long("cachesize").value_name("count").help("Max number of cached entries").takes_value(true).default_value("250000")).

    arg(Arg::with_name("decrement_ttl").short("r").long("resolver-mode").help("Resolver mode, decrements TTL").takes_value(false)).

    arg(Arg::with_name("failover").short("f").long("failover").help("Failover; try upstream servers sequentially instead of balancing the load").takes_value(false)).

    arg(Arg::with_name("ports_count").short("p").long("ports-count").value_name("count").help("Max number of UDP ports to use for outgoing connections, up to 64511").takes_value(true).default_value("8")).

    arg(Arg::with_name("upstream_max_failures").short("F").long("max-failures").value_name("count").help("Max failures before marking a server as temporarily unresponsive").takes_value(true).default_value("3")).

    get_matches();
    let upstream_servers_str: Vec<&str> = matches.values_of("upstream_servers_str").unwrap().collect();
    let listen_addr = matches.value_of("listen_addr").unwrap();
    let cache_size = FromStr::from_str(matches.value_of("cache_size").unwrap()).expect("Invalid number of cached entries");
    let decrement_ttl = matches.is_present("decrement_ttl");
    let failover = matches.is_present("failover");
    let ports = FromStr::from_str(matches.value_of("ports_count").unwrap()).expect("Invalid number of ports");
    let upstream_max_failures = FromStr::from_str(matches.value_of("upstream_max_failures").unwrap()).expect("Invalid value for the maximum number of failures");

    let _ = RPDNS::new(cache_size, listen_addr, upstream_servers_str, decrement_ttl, failover, ports, upstream_max_failures);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
#[macro_use] extern crate rustc_serialize;
extern crate env_logger;
extern crate regex;
extern crate win32_bindgen;

use win32_bindgen::{Architecture, ExpConfig, GenConfig, NativeCallConv};

pub const USE_MINGW_HEADERS: bool = false;
pub const USE_MSVC_HEADERS: bool = false;

fn main() {
    env_logger::init().unwrap();
    let result = if USE_MINGW_HEADERS {
        try_main_mingw()
    } else if USE_MSVC_HEADERS {
        try_main_msvc()
    } else {
        try_main_json()
    };
    result.unwrap();
}

const EXP_CONFIGS: &'static [ExpConfig] = &[
    ExpConfig {
        arch: Architecture::X86_32,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::Stdcall,
    },
    ExpConfig {
        arch: Architecture::X86_64,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::C,
    },
    ExpConfig {
        arch: Architecture::Arm,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::C,
    },
];

fn try_main_json() -> Result<(), String> {
    info!("Running with local\\config.json...");
    let json_config: Config = rustc_serialize::json::decode(&read_file("local/config.json")).unwrap();
    let header = json_config.header.clone();
    let gen_config = json_config.into_gen_config();
    win32_bindgen::process_header(&header, &gen_config);
    Ok(())
}

fn try_main_mingw() -> Result<(), String> {
    info!("Running with MinGW headers...");
    let gen_config = GenConfig {
        exp_configs: EXP_CONFIGS.iter().cloned().collect(),
        ignore_decl_spellings: vec![re("^_"), re("__")],
        ignore_file_paths: vec![
            re(r#"^$"#),
            re(r#"\\_mingw.h"#), re(r#"\\_mingw_secapi.h"#),
            re(r#"\\sdks\\_mingw_directx.h"#), re(r#"\\sdks\\_mingw_ddk.h"#),
            re(r#"\\psdk_inc\\intrin-impl.h"#),
            re(r#"\\ctype.h"#), re(r#"\\excpt.h"#), re(r#"\\string.h"#),
            re(r#"\\sec_api\\string_s.h"#),
            re(r#"\\winapifamily.h"#), re(r#"\\apiset.h"#),
            re(r#"\\sal.h"#), re(r#"\\specstrings.h"#),
        ],
        switches: vec![
        ],
    };

    win32_bindgen::process_header(
        // r#"F:\Programs\MSYS2-64\mingw32\i686-w64-mingw32\include\windows.h"#,
        r#"F:\Programs\MSYS2-64\mingw32\i686-w64-mingw32\include\winnt.h"#,
        &gen_config
    );
    Ok(())
}

fn try_main_msvc() -> Result<(), String> {
    info!("Running with Windows SDK headers...");
    let gen_config = GenConfig {
        exp_configs: EXP_CONFIGS.iter().cloned().collect(),
        ignore_decl_spellings: vec![re("^_"), re("__")],
        ignore_file_paths: vec![
            re(r#"^$"#),
            // The sanity checks are a pain to parse.
            re(r#"\\sdkddkver.h"#),
        ],
        switches: vec![
            r#"-fms-extensions"#.into(), r#"-fms-compatibility"#.into(),
            r#"-D_MSC_VER=1800"#.into(),
            r#"-D_STDCALL_SUPPORTED"#.into(),
            r#"-Ilocal/Include/shared"#.into(),
            r#"-Ilocal/Include/um"#.into(),
        ],
    };

    win32_bindgen::process_header(
        r#"local\Include\um\winnt.h"#,
        &gen_config
    );
    Ok(())
}

fn re(re: &str) -> regex::Regex {
    regex::Regex::new(re).unwrap()
}

#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Config {
    pub header: String,
    pub expansion_configs: Vec<ExpansionConfig>,
    pub ignore_decl_spellings: Vec<String>,
    pub ignore_file_paths: Vec<String>,
    pub switches: Vec<String>,
}

impl Config {
    pub fn into_gen_config(self) -> GenConfig {
        GenConfig {
            exp_configs: self.expansion_configs.into_iter().map(ExpansionConfig::into_exp_config).collect(),
            ignore_decl_spellings: self.ignore_decl_spellings.into_iter().map(|s| re(&s)).collect(),
            ignore_file_paths: self.ignore_file_paths.into_iter().map(|s| re(&s)).collect(),
            switches: self.switches,
        }
    }
}

#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct ExpansionConfig {
    pub architecture: ConfigArch,
    pub windows_version_short: String,
    pub windows_version_full: String,
    pub native_calling_conv: ConfigNCC,
}

impl ExpansionConfig {
    pub fn into_exp_config(self) -> ExpConfig {
        ExpConfig {
            arch: self.architecture.into_architecture(),
            winver: ((wv(&self.windows_version_short) >> 16) as u16, wv(&self.windows_version_full)),
            native_cc: self.native_calling_conv.into_native_call_conv(),
        }
    }
}

fn wv(s: &str) -> u32 {
    win32_bindgen::generated::winver::WinVersion::from_name(s).unwrap() as u32
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)]
pub enum ConfigArch {
    X86_32,
    X86_64,
    Arm,
}

impl ConfigArch {
    pub fn into_architecture(self) -> Architecture {
        use self::ConfigArch::*;
        match self {
            X86_32 => Architecture::X86_32,
            X86_64 => Architecture::X86_64,
            Arm => Architecture::Arm,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)]
pub enum ConfigNCC {
    C,
    Stdcall,
}

impl ConfigNCC {
    pub fn into_native_call_conv(self) -> NativeCallConv {
        use self::ConfigNCC::*;
        match self {
            C => NativeCallConv::C,
            Stdcall => NativeCallConv::Stdcall,
        }
    }
}

pub fn read_file(path: &str) -> String {
    use std::fs;
    use std::io::prelude::*;
    let mut s = String::new();
    let _ = fs::File::open(path).unwrap().read_to_string(&mut s).unwrap();
    s
}
<commit_msg>Fixed private path problem.<commit_after>#[macro_use] extern crate log;
#[macro_use] extern crate rustc_serialize;
extern crate env_logger;
extern crate regex;
extern crate win32_bindgen;

use win32_bindgen::{Architecture, ExpConfig, GenConfig, NativeCallConv};

pub const USE_MINGW_HEADERS: bool = false;
pub const USE_MSVC_HEADERS: bool = false;

fn main() {
    env_logger::init().unwrap();
    let result = if USE_MINGW_HEADERS {
        try_main_mingw()
    } else if USE_MSVC_HEADERS {
        try_main_msvc()
    } else {
        try_main_json()
    };
    result.unwrap();
}

const EXP_CONFIGS: &'static [ExpConfig] = &[
    ExpConfig {
        arch: Architecture::X86_32,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::Stdcall,
    },
    ExpConfig {
        arch: Architecture::X86_64,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::C,
    },
    ExpConfig {
        arch: Architecture::Arm,
        winver: ExpConfig::WINVER_WIN81,
        native_cc: NativeCallConv::C,
    },
];

fn try_main_json() -> Result<(), String> {
    info!("Running with local\\config.json...");
    let json_config: Config = rustc_serialize::json::decode(&read_file("local/config.json")).unwrap();
    let header = json_config.header.clone();
    let gen_config = json_config.into_gen_config();
    win32_bindgen::process_header(&header, &gen_config);
    Ok(())
}

fn try_main_mingw() -> Result<(), String> {
    info!("Running with MinGW headers...");
    let gen_config = GenConfig {
        exp_configs: EXP_CONFIGS.iter().cloned().collect(),
        ignore_decl_spellings: vec![re("^_"), re("__")],
        ignore_file_paths: vec![
            re(r#"^$"#),
            re(r#"\\_mingw.h"#), re(r#"\\_mingw_secapi.h"#),
            re(r#"\\sdks\\_mingw_directx.h"#), re(r#"\\sdks\\_mingw_ddk.h"#),
            re(r#"\\psdk_inc\\intrin-impl.h"#),
            re(r#"\\ctype.h"#), re(r#"\\excpt.h"#), re(r#"\\string.h"#),
            re(r#"\\sec_api\\string_s.h"#),
            re(r#"\\winapifamily.h"#), re(r#"\\apiset.h"#),
            re(r#"\\sal.h"#), re(r#"\\specstrings.h"#),
        ],
        switches: vec![
        ],
    };

    win32_bindgen::process_header(
        // r#"F:\Programs\MSYS2-64\mingw32\i686-w64-mingw32\include\windows.h"#,
        r#"F:\Programs\MSYS2-64\mingw32\i686-w64-mingw32\include\winnt.h"#,
        &gen_config
    );
    Ok(())
}

fn try_main_msvc() -> Result<(), String> {
    info!("Running with Windows SDK headers...");
    let gen_config = GenConfig {
        exp_configs: EXP_CONFIGS.iter().cloned().collect(),
        ignore_decl_spellings: vec![re("^_"), re("__")],
        ignore_file_paths: vec![
            re(r#"^$"#),
            // The sanity checks are a pain to parse.
            re(r#"\\sdkddkver.h"#),
        ],
        switches: vec![
            r#"-fms-extensions"#.into(), r#"-fms-compatibility"#.into(),
            r#"-D_MSC_VER=1800"#.into(),
            r#"-D_STDCALL_SUPPORTED"#.into(),
            r#"-Ilocal/Include/shared"#.into(),
            r#"-Ilocal/Include/um"#.into(),
        ],
    };

    win32_bindgen::process_header(
        r#"local\Include\um\winnt.h"#,
        &gen_config
    );
    Ok(())
}

fn re(re: &str) -> regex::Regex {
    regex::Regex::new(re).unwrap()
}

#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Config {
    pub header: String,
    pub expansion_configs: Vec<ExpansionConfig>,
    pub ignore_decl_spellings: Vec<String>,
    pub ignore_file_paths: Vec<String>,
    pub switches: Vec<String>,
}

impl Config {
    pub fn into_gen_config(self) -> GenConfig {
        GenConfig {
            exp_configs: self.expansion_configs.into_iter().map(ExpansionConfig::into_exp_config).collect(),
            ignore_decl_spellings: self.ignore_decl_spellings.into_iter().map(|s| re(&s)).collect(),
            ignore_file_paths: self.ignore_file_paths.into_iter().map(|s| re(&s)).collect(),
            switches: self.switches,
        }
    }
}

#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct ExpansionConfig {
    pub architecture: ConfigArch,
    pub windows_version_short: String,
    pub windows_version_full: String,
    pub native_calling_conv: ConfigNCC,
}

impl ExpansionConfig {
    pub fn into_exp_config(self) -> ExpConfig {
        ExpConfig {
            arch: self.architecture.into_architecture(),
            winver: ((wv(&self.windows_version_short) >> 16) as u16, wv(&self.windows_version_full)),
            native_cc: self.native_calling_conv.into_native_call_conv(),
        }
    }
}

fn wv(s: &str) -> u32 {
    win32_bindgen::WinVersion::from_name(s).unwrap() as u32
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)]
pub enum ConfigArch {
    X86_32,
    X86_64,
    Arm,
}

impl ConfigArch {
    pub fn into_architecture(self) -> Architecture {
        use self::ConfigArch::*;
        match self {
            X86_32 => Architecture::X86_32,
            X86_64 => Architecture::X86_64,
            Arm => Architecture::Arm,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)]
pub enum ConfigNCC {
    C,
    Stdcall,
}

impl ConfigNCC {
    pub fn into_native_call_conv(self) -> NativeCallConv {
        use self::ConfigNCC::*;
        match self {
            C => NativeCallConv::C,
            Stdcall => NativeCallConv::Stdcall,
        }
    }
}

pub fn read_file(path: &str) -> String {
    use std::fs;
    use std::io::prelude::*;
    let mut s = String::new();
    let _ = fs::File::open(path).unwrap().read_to_string(&mut s).unwrap();
    s
}
<|endoftext|>


<commit_before>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize * 3;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.low_x += (x as f64) * mdlbt.width / ww;
            mdlbt.low_y += (y as f64) * mdlbt.height / wh;
            mdlbt.width /= ww;
            mdlbt.height /= wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          Mouse::Right => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.width *= ww;
            mdlbt.height *= wh;
            mdlbt.low_x -= (x as f64) * mdlbt.width / ww;
            mdlbt.low_y -= (y as f64) * mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<commit_msg>VBO size was 3x too big.<commit_after>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.low_x += (x as f64) * mdlbt.width / ww;
            mdlbt.low_y += (y as f64) * mdlbt.height / wh;
            mdlbt.width /= ww;
            mdlbt.height /= wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          Mouse::Right => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.width *= ww;
            mdlbt.height *= wh;
            mdlbt.low_x -= (x as f64) * mdlbt.width / ww;
            mdlbt.low_y -= (y as f64) * mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate rusthub;
extern crate notify_rust;
extern crate rustc_serialize;
extern crate env_logger;

mod io;
mod notify;

use rusthub::notifications;
use rusthub::notifications::{NotificationResponse, Notifications};
use std::thread;
use std::time::Duration;

const TIMEOUT: i32 = 120;

fn filter_unseen(notifications: &Notifications) -> Notifications {
    let list = match io::get_saved_notifications() {
        Ok(saves) => notifications.list
            .clone()
            .into_iter()
            .filter(|n| !saves.list.iter().any(|sn| n.updated_at == sn.updated_at && n.subject.title == sn.subject.title))
            .collect(),
        Err(err) => {
            error!("{}", err);
            notifications.list.clone()
        }
    };

    Notifications { list: list }
}

fn main() {
    // INIT
    env_logger::init().unwrap();
    let token: String = io::retrieve_token(TIMEOUT).unwrap();
    debug!("Token: {}", &token);
    // TODO: Check if this token is stale before using it in the main loop

    // MAIN LOOP
    loop {
        // Get notifications
        let response: NotificationResponse = notifications::get_notifications_oauth(&token).unwrap();

        let unseen = filter_unseen(&response.notifications);
        debug!("Unseen Notifications: {} out of {}", unseen.list.len(), response.notifications.list.len());

        // Display notifications
        for notification in &unseen.list {
            notify::show_notification(&notification);
            thread::sleep(Duration::new(0, 500000000)); // Sleep for a half-second to give notify api a chance
        }

        // Cache Previous Notifications
        io::write_notifications(&response.notifications)
            .unwrap_or_else(|err| error!("While writing notifications: {}", err));

        // Sleep for requested time by GitHub
        let sleep_time: u64 = response.poll_interval as u64;
        thread::sleep(Duration::new(sleep_time, 0));
    }
}<commit_msg>re-added github poll debugging<commit_after>#[macro_use]
extern crate log;
extern crate rusthub;
extern crate notify_rust;
extern crate rustc_serialize;
extern crate env_logger;

mod io;
mod notify;

use rusthub::notifications;
use rusthub::notifications::{NotificationResponse, Notifications};
use std::thread;
use std::time::Duration;

const TIMEOUT: i32 = 120;

fn filter_unseen(notifications: &Notifications) -> Notifications {
    let list = match io::get_saved_notifications() {
        Ok(saves) => notifications.list
            .clone()
            .into_iter()
            .filter(|n| !saves.list.iter().any(|sn| n.updated_at == sn.updated_at && n.subject.title == sn.subject.title))
            .collect(),
        Err(err) => {
            error!("{}", err);
            notifications.list.clone()
        }
    };

    Notifications { list: list }
}

fn main() {
    // INIT
    env_logger::init().unwrap();
    let token: String = io::retrieve_token(TIMEOUT).unwrap();
    debug!("Token: {}", &token);
    // TODO: Check if this token is stale before using it in the main loop

    // MAIN LOOP
    loop {
        // Get notifications
        let response: NotificationResponse = notifications::get_notifications_oauth(&token).unwrap();

        let unseen = filter_unseen(&response.notifications);
        debug!("Unseen Notifications: {} out of {}", unseen.list.len(), response.notifications.list.len());

        // Display notifications
        for notification in &unseen.list {
            notify::show_notification(&notification);
            thread::sleep(Duration::new(0, 500000000)); // Sleep for a half-second to give notify api a chance
        }

        // Cache Previous Notifications
        io::write_notifications(&response.notifications)
            .unwrap_or_else(|err| error!("While writing notifications: {}", err));

        debug!("\nPoll Interval: {}\nRate Limit: {}\nRate Limit Remaining: {}",
               response.poll_interval, response.rate_limit, response.rate_limit_remaining);
        // Sleep for requested time by GitHub
        let sleep_time: u64 = response.poll_interval as u64;
        thread::sleep(Duration::new(sleep_time, 0));
    }
}<|endoftext|>


<commit_before>extern crate rand;

use rand::Rng;
use rand::distributions;
use individual::Individual;

mod individual;

fn select<'a, R: Rng>(population: &'a Vec<Individual>, rng: &mut R)
                      -> &'a Individual {
    let contestants = (0..4).map(|_| rng.choose(population));
    if let Some(selected) = contestants.min() {
        return selected.unwrap();
    }
    unimplemented!();
}

fn main() {
    let mut rng = rand::thread_rng();
    let range = distributions::Range::new(-512.03_f64, 511.97);

    // initialize population
    let mut population: Vec<_> = (0..128).map(|_| {
        Individual::new(&range, &mut rng)
    }).collect();

    for i in 0..10000 {
        // select and mutate individuals for next population
        population = (0..128).map(|_| {
            select(&population, &mut rng).mutate(&range, &mut rng)
        }).collect();

        if let Some(x) = population.iter().min() {
            if i % 100 == 0 {
                println!("{}th fitness: {}", i, x.fitness);
            }

            if x.fitness < 1000_f64 {
                println!("{}th solution converged at {}: {:?}",
                         i, x.fitness, x.solution);
                return;
            }
        } else { unimplemented!() }
    }
    println!("Failed to converge.");
}
<commit_msg>Clone Individual in select()<commit_after>extern crate rand;

use rand::Rng;
use rand::distributions;
use individual::Individual;

mod individual;

fn select<R: Rng>(population: &Vec<Individual>, rng: &mut R)
                  -> Individual {
    if let Some(selected) = (0..4).map(|_| rng.choose(population)).min() {
        selected.unwrap().clone()
    } else {
        unimplemented!();
    }
}

fn main() {
    let mut rng = rand::thread_rng();
    let range = distributions::Range::new(-512.03_f64, 511.97);

    // initialize population
    let mut population: Vec<_> = (0..128).map(|_| {
        Individual::new(&range, &mut rng)
    }).collect();

    for i in 0..10000 {
        // select and mutate individuals for next population
        population = (0..128).map(|_| {
            select(&population, &mut rng).mutate(&range, &mut rng)
        }).collect();

        if let Some(x) = population.iter().min() {
            if i % 100 == 0 {
                println!("{}th fitness: {}", i, x.fitness);
            }

            if x.fitness < 1000_f64 {
                println!("{}th solution converged at {}: {:?}",
                         i, x.fitness, x.solution);
                return;
            }
        } else { unimplemented!() }
    }
    println!("Failed to converge.");
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
extern crate getopts;

use std::env;

mod ast;
mod parser;
mod cli;

fn main() {
    let args: Vec<String> = env::args().collect();
    cli::run(args);
}
<commit_msg>Allowing non snake case function names.<commit_after>#![feature(plugin)]
#![plugin(oak)]
#![allow(non_snake_case)]

extern crate oak_runtime;
extern crate getopts;

use std::env;

mod ast;
mod parser;
mod cli;

fn main() {
    let args: Vec<String> = env::args().collect();
    cli::run(args);
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use]
extern crate clap;
extern crate serde;
extern crate serde_yaml;

use std::process::exit;

mod consts;
mod cli;
mod module;
mod error;
mod subcommands;

use cli::parse_cli_args;

fn main() {
    // Load config
    //let _ = Config::new();

    // Parse cli options
    let yml = load_yaml!("cli.yaml");
    let cli_args = clap::App::from_yaml(yml).get_matches();
    let command = parse_cli_args(cli_args);

    // Execute subcommand
    //let mod_name = cli_args.subcommand_matches(m).unwrap().value_of("module_name");
    command.run().unwrap_or_else(|e| {
        println!("{}", e);
        exit(1);
    });

    //println!("{} {}", command, module);
    /*
    let m = match ModuleData::load(module){
        Ok(m) => m,
        Err(e) => {
            println!("Error when parsing module config '{}':\n{}", module, e);
            exit(1);
        }
    };

    println!("{:?}", m);
    */
}
<commit_msg>Fixed yaml loading locaiton temporarily. Builds still won't work if executed outside of the root repo directory.<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use]
extern crate clap;
extern crate serde;
extern crate serde_yaml;

use std::process::exit;

mod consts;
mod cli;
mod module;
mod error;
mod subcommands;

use cli::parse_cli_args;

fn main() {
    // Load config
    //let _ = Config::new();

    // Parse cli options
    let yml = load_yaml!("src/cli.yaml");
    let cli_args = clap::App::from_yaml(yml).get_matches();
    let command = parse_cli_args(cli_args);

    // Execute subcommand
    //let mod_name = cli_args.subcommand_matches(m).unwrap().value_of("module_name");
    command.run().unwrap_or_else(|e| {
        println!("{}", e);
        exit(1);
    });

    //println!("{} {}", command, module);
    /*
    let m = match ModuleData::load(module){
        Ok(m) => m,
        Err(e) => {
            println!("Error when parsing module config '{}':\n{}", module, e);
            exit(1);
        }
    };

    println!("{:?}", m);
    */
}
<|endoftext|>