<commit_before>use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::{Machine, Log, Context,
                    Account, Storage, AccountCommitment,
                    BlockHeader};

use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;

pub struct JSONBlock {
    codes: HashMap<Address, Vec<u8>>,
    balances: HashMap<Address, U256>,
    storages: HashMap<Address, HashMap<M256, M256>>,
    nonces: HashMap<Address, M256>,

    coinbase: Address,
    timestamp: M256,
    number: M256,
    difficulty: M256,
    gas_limit: Gas,

    logs: Vec<Log>,
}

static EMPTY: [u8; 0] = [];

impl JSONBlock {
    pub fn block_header(&self) -> BlockHeader {
        BlockHeader {
            coinbase: self.coinbase,
            timestamp: self.timestamp,
            number: self.number,
            difficulty: self.difficulty,
            gas_limit: self.gas_limit,
        }
    }

    pub fn request_account(&self, address: Address) -> AccountCommitment {
        let balance = self.balance(address);
        let code = self.account_code(address);
        let nonce = self.account_nonce(address);

        AccountCommitment::Full {
            address: address,
            balance: balance,
            code: code.into(),
            nonce: nonce
        }
    }

    pub fn request_account_storage(&self, address: Address, index: M256) -> AccountCommitment {
        let hashmap_default = HashMap::new();
        let storage = self.storages.get(&address).unwrap_or(&hashmap_default);
        let value = match storage.get(&index) {
            Some(val) => *val,
            None => M256::zero(),
        };

        AccountCommitment::Storage {
            address: address,
            index: index,
            value: value,
        }
    }

    pub fn request_account_code(&self, address: Address) -> AccountCommitment {
        let default = Vec::new();
        let code = self.codes.get(&address).unwrap_or(&default);

        AccountCommitment::Code {
            address: address,
            code: code.clone(),
        }
    }

    pub fn apply_account(&mut self, account: Account) {
        match account {
            Account::Full {
                address: address,
                balance: balance,
                changing_storage: changing_storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                if !self.storages.contains_key(&address) {
                    self.storages.insert(address, HashMap::new());
                }
                let changing_storage: HashMap<M256, M256> = changing_storage.into();
                for (key, value) in changing_storage {
                    self.storages.get_mut(&address).unwrap().insert(key, value);
                }
                self.set_account_nonce(address, nonce);
            },
            Account::Create {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                self.storages.insert(address, storage.into());
                self.set_account_nonce(address, nonce);
            },
            Account::IncreaseBalance(address, topup) => {
                let balance = self.balance(address);
                self.set_balance(address, balance + topup);
            },
            Account::DecreaseBalance(address, withdraw) => {
                let balance = self.balance(address);
                self.set_balance(address, balance - withdraw);
            },
        }
    }

    pub fn apply_log(&mut self, log: Log) {
        self.logs.push(log);
    }

    pub fn coinbase(&self) -> Address {
        self.coinbase
    }

    pub fn timestamp(&self) -> M256 {
        self.timestamp
    }

    pub fn number(&self) -> M256 {
        self.number
    }

    pub fn difficulty(&self) -> M256 {
        self.difficulty
    }

    pub fn gas_limit(&self) -> Gas {
        self.gas_limit
    }

    pub fn account_nonce(&self, address: Address) -> M256 {
        self.nonces.get(&address).map_or(M256::zero(), |s| (*s).into())
    }

    pub fn set_account_nonce(&mut self, address: Address, nonce: M256) {
        self.nonces.insert(address, nonce);
    }

    pub fn account_code(&self, address: Address) -> &[u8] {
        self.codes.get(&address).map_or(EMPTY.as_ref(), |s| s.as_ref())
    }

    pub fn set_account_code(&mut self, address: Address, code: &[u8]) {
        self.codes.insert(address, code.into());
    }

    pub fn balance(&self, address: Address) -> U256 {
        self.balances.get(&address).map_or(U256::zero(), |s| (*s).into())
    }

    pub fn set_balance(&mut self, address: Address, balance: U256) {
        self.balances.insert(address, balance);
    }

    pub fn account_storage(&self, address: Address, index: M256) -> M256 {
        match self.storages.get(&address) {
            None => M256::zero(),
            Some(ref ve) => {
                match ve.get(&index) {
                    Some(&v) => v,
                    None => M256::zero()
                }
            }
        }
    }

    pub fn set_account_storage(&mut self, address: Address, index: M256, val: M256) {
        if self.storages.get(&address).is_none() {
            self.storages.insert(address, HashMap::new());
        }

        let v = self.storages.get_mut(&address).unwrap();
        v.insert(index, val);
    }

    pub fn find_log(&self, address: Address, data: &[u8], topics: &[M256]) -> bool {
        for log in &self.logs {
            if log.address == address && log.data.as_slice() == data && log.topics.as_slice() == topics {
                return true;
            }
        }
        return false;
    }
}

pub fn create_block(v: &Value) -> JSONBlock {
    let mut block = {
        let env = &v["env"];

        let current_coinbase = env["currentCoinbase"].as_str().unwrap();
        let current_difficulty = env["currentDifficulty"].as_str().unwrap();
        let current_gas_limit = env["currentGasLimit"].as_str().unwrap();
        let current_number = env["currentNumber"].as_str().unwrap();
        let current_timestamp = env["currentTimestamp"].as_str().unwrap();

        JSONBlock {
            balances: HashMap::new(),
            storages: HashMap::new(),
            codes: HashMap::new(),
            nonces: HashMap::new(),

            coinbase: Address::from_str(current_coinbase).unwrap(),
            difficulty: M256::from_str(current_difficulty).unwrap(),
            gas_limit: Gas::from_str(current_gas_limit).unwrap(),
            number: M256::from_str(current_number).unwrap(),
            timestamp: M256::from_str(current_timestamp).unwrap(),

            logs: Vec::new(),
        }
    };

    let ref pre_addresses = v["pre"];

    for (address, data) in pre_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();

        block.set_account_code(address, code.as_ref());
        block.set_balance(address, balance);

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            block.set_account_storage(address, index, value);
        }
    }

    block
}

pub fn create_context(v: &Value) -> Context {
    let address = Address::from_str(v["exec"]["address"].as_str().unwrap()).unwrap();
    let caller = Address::from_str(v["exec"]["caller"].as_str().unwrap()).unwrap();
    let code = read_hex(v["exec"]["code"].as_str().unwrap()).unwrap();
    let data = read_hex(v["exec"]["data"].as_str().unwrap()).unwrap();
    let gas = Gas::from_str(v["exec"]["gas"].as_str().unwrap()).unwrap();
    let gas_price = Gas::from_str(v["exec"]["gasPrice"].as_str().unwrap()).unwrap();
    let origin = Address::from_str(v["exec"]["origin"].as_str().unwrap()).unwrap();
    let value = U256::from_str(v["exec"]["value"].as_str().unwrap()).unwrap();

    Context {
        address: address,
        caller: caller,
        code: code,
        data: data,
        gas_limit: gas,
        gas_price: gas_price,
        origin: origin,
        value: value,
    }
}
<commit_msg>Problem: missing fields in Account::Create jsontests::blockchain<commit_after>use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::{Machine, Log, Context,
                    Account, Storage, AccountCommitment,
                    BlockHeader};

use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;

pub struct JSONBlock {
    codes: HashMap<Address, Vec<u8>>,
    balances: HashMap<Address, U256>,
    storages: HashMap<Address, HashMap<M256, M256>>,
    nonces: HashMap<Address, M256>,

    coinbase: Address,
    timestamp: M256,
    number: M256,
    difficulty: M256,
    gas_limit: Gas,

    logs: Vec<Log>,
}

static EMPTY: [u8; 0] = [];

impl JSONBlock {
    pub fn block_header(&self) -> BlockHeader {
        BlockHeader {
            coinbase: self.coinbase,
            timestamp: self.timestamp,
            number: self.number,
            difficulty: self.difficulty,
            gas_limit: self.gas_limit,
        }
    }

    pub fn request_account(&self, address: Address) -> AccountCommitment {
        let balance = self.balance(address);
        let code = self.account_code(address);
        let nonce = self.account_nonce(address);

        AccountCommitment::Full {
            address: address,
            balance: balance,
            code: code.into(),
            nonce: nonce
        }
    }

    pub fn request_account_storage(&self, address: Address, index: M256) -> AccountCommitment {
        let hashmap_default = HashMap::new();
        let storage = self.storages.get(&address).unwrap_or(&hashmap_default);
        let value = match storage.get(&index) {
            Some(val) => *val,
            None => M256::zero(),
        };

        AccountCommitment::Storage {
            address: address,
            index: index,
            value: value,
        }
    }

    pub fn request_account_code(&self, address: Address) -> AccountCommitment {
        let default = Vec::new();
        let code = self.codes.get(&address).unwrap_or(&default);

        AccountCommitment::Code {
            address: address,
            code: code.clone(),
        }
    }

    pub fn apply_account(&mut self, account: Account) {
        match account {
            Account::Full {
                address: address,
                balance: balance,
                changing_storage: changing_storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                if !self.storages.contains_key(&address) {
                    self.storages.insert(address, HashMap::new());
                }
                let changing_storage: HashMap<M256, M256> = changing_storage.into();
                for (key, value) in changing_storage {
                    self.storages.get_mut(&address).unwrap().insert(key, value);
                }
                self.set_account_nonce(address, nonce);
            },
            Account::Create {
                address, balance, storage, code, nonce, ..
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                self.storages.insert(address, storage.into());
                self.set_account_nonce(address, nonce);
            },
            Account::IncreaseBalance(address, topup) => {
                let balance = self.balance(address);
                self.set_balance(address, balance + topup);
            },
            Account::DecreaseBalance(address, withdraw) => {
                let balance = self.balance(address);
                self.set_balance(address, balance - withdraw);
            },
        }
    }

    pub fn apply_log(&mut self, log: Log) {
        self.logs.push(log);
    }

    pub fn coinbase(&self) -> Address {
        self.coinbase
    }

    pub fn timestamp(&self) -> M256 {
        self.timestamp
    }

    pub fn number(&self) -> M256 {
        self.number
    }

    pub fn difficulty(&self) -> M256 {
        self.difficulty
    }

    pub fn gas_limit(&self) -> Gas {
        self.gas_limit
    }

    pub fn account_nonce(&self, address: Address) -> M256 {
        self.nonces.get(&address).map_or(M256::zero(), |s| (*s).into())
    }

    pub fn set_account_nonce(&mut self, address: Address, nonce: M256) {
        self.nonces.insert(address, nonce);
    }

    pub fn account_code(&self, address: Address) -> &[u8] {
        self.codes.get(&address).map_or(EMPTY.as_ref(), |s| s.as_ref())
    }

    pub fn set_account_code(&mut self, address: Address, code: &[u8]) {
        self.codes.insert(address, code.into());
    }

    pub fn balance(&self, address: Address) -> U256 {
        self.balances.get(&address).map_or(U256::zero(), |s| (*s).into())
    }

    pub fn set_balance(&mut self, address: Address, balance: U256) {
        self.balances.insert(address, balance);
    }

    pub fn account_storage(&self, address: Address, index: M256) -> M256 {
        match self.storages.get(&address) {
            None => M256::zero(),
            Some(ref ve) => {
                match ve.get(&index) {
                    Some(&v) => v,
                    None => M256::zero()
                }
            }
        }
    }

    pub fn set_account_storage(&mut self, address: Address, index: M256, val: M256) {
        if self.storages.get(&address).is_none() {
            self.storages.insert(address, HashMap::new());
        }

        let v = self.storages.get_mut(&address).unwrap();
        v.insert(index, val);
    }

    pub fn find_log(&self, address: Address, data: &[u8], topics: &[M256]) -> bool {
        for log in &self.logs {
            if log.address == address && log.data.as_slice() == data && log.topics.as_slice() == topics {
                return true;
            }
        }
        return false;
    }
}

pub fn create_block(v: &Value) -> JSONBlock {
    let mut block = {
        let env = &v["env"];

        let current_coinbase = env["currentCoinbase"].as_str().unwrap();
        let current_difficulty = env["currentDifficulty"].as_str().unwrap();
        let current_gas_limit = env["currentGasLimit"].as_str().unwrap();
        let current_number = env["currentNumber"].as_str().unwrap();
        let current_timestamp = env["currentTimestamp"].as_str().unwrap();

        JSONBlock {
            balances: HashMap::new(),
            storages: HashMap::new(),
            codes: HashMap::new(),
            nonces: HashMap::new(),

            coinbase: Address::from_str(current_coinbase).unwrap(),
            difficulty: M256::from_str(current_difficulty).unwrap(),
            gas_limit: Gas::from_str(current_gas_limit).unwrap(),
            number: M256::from_str(current_number).unwrap(),
            timestamp: M256::from_str(current_timestamp).unwrap(),

            logs: Vec::new(),
        }
    };

    let ref pre_addresses = v["pre"];

    for (address, data) in pre_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();

        block.set_account_code(address, code.as_ref());
        block.set_balance(address, balance);

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            block.set_account_storage(address, index, value);
        }
    }

    block
}

pub fn create_context(v: &Value) -> Context {
    let address = Address::from_str(v["exec"]["address"].as_str().unwrap()).unwrap();
    let caller = Address::from_str(v["exec"]["caller"].as_str().unwrap()).unwrap();
    let code = read_hex(v["exec"]["code"].as_str().unwrap()).unwrap();
    let data = read_hex(v["exec"]["data"].as_str().unwrap()).unwrap();
    let gas = Gas::from_str(v["exec"]["gas"].as_str().unwrap()).unwrap();
    let gas_price = Gas::from_str(v["exec"]["gasPrice"].as_str().unwrap()).unwrap();
    let origin = Address::from_str(v["exec"]["origin"].as_str().unwrap()).unwrap();
    let value = U256::from_str(v["exec"]["value"].as_str().unwrap()).unwrap();

    Context {
        address: address,
        caller: caller,
        code: code,
        data: data,
        gas_limit: gas,
        gas_price: gas_price,
        origin: origin,
        value: value,
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

pub use visualizer::visualizer::{Visualizer};

pub mod mesh;
pub mod geom;
pub mod camera;
pub mod visualizer;
pub mod types;
pub mod shader;
pub mod zgl; // TODO: not pub
pub mod picker;
pub mod texture;
pub mod obj;
pub mod font_stash;

// vim: set tabstop=5 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualizer mod: Export only 'Visualizer' class<commit_after>// See LICENSE file for copyright and license details.

pub use visualizer::visualizer::{Visualizer};

mod mesh;
mod geom;
mod camera;
mod visualizer;
mod types;
mod shader;
mod zgl;
mod picker;
mod texture;
mod obj;
mod font_stash;

// vim: set tabstop=5 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>
extern crate clap;
extern crate intcode;

// Time Start: Fri, 13 Dec 2019 09:13:42 -0500
// Time Finish 1: Fri, 13 Dec 2019 09:38:12 -0500 (24 minutes, 30 seconds)
// Time Finish 2:
// Time Total:

use clap::{Arg, App};

use intcode::Intcode;
use intcode::Val;

use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt;
use std::{thread, time};

#[derive(Copy, Clone)]
struct BBox(i64,i64,i64,i64);// xmin, xmax, ymin, ymax
impl BBox {
    pub fn new() -> BBox {
        BBox(0,0,0,0)
    }

    pub fn xmin(&self) -> i64 { self.0 }
    pub fn xmax(&self) -> i64 { self.1 }
    pub fn ymin(&self) -> i64 { self.2 }
    pub fn ymax(&self) -> i64 { self.3 }

    pub fn update(&mut self, x: i64, y: i64) {
        if x < self.0 { self.0 = x; }
        if x > self.1 { self.1 = x; }
        if y < self.2 { self.2 = y; }
        if y > self.3 { self.3 = y; }
    }
}
impl fmt::Display for BBox {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "BBox: {}, {}, {}, {}", self.0, self.1, self.2, self.3)
    }
}

struct Screen {
    pub screen: HashMap<(i64, i64), u8>,
    pub bbox: BBox,
}
impl Screen {
    pub fn new() -> Screen {
        Screen {
            screen: HashMap::new(),
            bbox: BBox::new(),
        }
    }

    pub fn item_at(&self, x: i64, y: i64) -> u8 {
        match self.screen.get(&(x,y)) {
            Some(x) => *x,
            None    => 0,
        }
    }

    pub fn put(&mut self, x: i64, y: i64, obj: u8) {
        self.bbox.update(x, y);
        self.screen.insert((x, y), obj);
    }
}
impl fmt::Display for Screen {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for y in (self.bbox.ymin()..=self.bbox.ymax()).rev() {
            for x in self.bbox.xmin()..=self.bbox.xmax() {
                if let Err(err) = match self.item_at(x, y) {
                    0 => write!(f, "{}", " "), // empty
                    1 => write!(f, "{}", "#"), // wall
                    2 => write!(f, "{}", "@"), // block
                    3 => write!(f, "{}", "-"), // paddle
                    4 => write!(f, "{}", "*"), // ball
                    x => panic!("Unexpected object: {}", x),
                } {
                    return Err(err);
                }
            }
            if let Err(err) = write!(f, "{}", "\n") {
                return Err(err);
            }
        }
        Ok(())
    }
}

struct Pong {
    paddle: i64,
    ball_x: i64,
    ball_dx: i64,
    pub score: i64,
    blocks: HashSet<(i64, i64)>,
}
impl Pong {
    pub fn new() -> Pong {
        Pong {
            paddle:  0,
            ball_x:  9999,
            ball_dx: 0,
            score:   0,
            blocks: HashSet::new(),
        }
    }

    fn draw(&self, screen: &Screen) {
        println!("\x1B[H\x1B[2J{}\n\n Score: {}", screen, self.score);
        thread::sleep(time::Duration::from_millis(10));
    }

    fn run_code(&mut self, ic: &mut Intcode) {
        let mut screen = Screen::new();
        ic.set_input(0);
        loop {
            while ic.output_len() < 3 && ic.step() { }

            if ic.is_halted() { break; }

            let x = ic.shift_output().expect("x output disappeared!");
            let y = ic.shift_output().expect("y output disappeared!");
            let obj = ic.shift_output().expect("object output disappeared!");

            if x == -1 && y == 0 {
                self.score = obj;
                continue;
            }

            screen.put(x, y, obj as u8);

            match obj {
                0 => { self.blocks.remove(&(x,y)); },                                         // empty
                1 => (),                                                                      // wall
                2 => { self.blocks.insert((x,y)); },                                          // block
                3 => { self.paddle = x; self.draw(&screen); },                                // paddle
                4 => { self.ball_dx = x - self.ball_x; self.ball_x = x; self.draw(&screen); } // ball
                x => unreachable!("Unexpected object {}", x),
            }

            if self.ball_dx < 1000 { self.ball_dx = 0; } // ugly handling of initial conditions

            if self.paddle < self.ball_x + self.ball_dx {
                ic.set_input(1);
            }
            else if self.paddle > self.ball_x + self.ball_dx {
                ic.set_input(-1);
            }
            else {
                ic.set_input(0);
            }
        }
        self.draw(&screen);
    }
}

fn run_code(ic: &mut Intcode, screen: &mut Screen) {
    loop {
        while ic.output_len() < 3 && ic.step() { }

        if ic.is_halted() { break; }

        let x = ic.shift_output().expect("x output disappeared!");
        let y = ic.shift_output().expect("y output disappeared!");
        let obj = ic.shift_output().expect("object output disappeared!") as u8;
        screen.put(x, y, obj);
    }
}

fn main() {
    let matches = App::new("Advent of Code 2019, Day 13")
        .arg(Arg::with_name("FILE")
             .help("Input file to process")
             .index(1))
        .get_matches();
    let fname = String::from(matches.value_of("FILE").unwrap_or("13.in"));

    let mut ic = Intcode::load(&fname);
    let mut pong = Pong::new();
    ic.set(&Val::Address(0), 2); // Insert quarter

    pong.run_code(&mut ic);

    println!("Step 2: final score {}", pong.score);

    let mut ic = Intcode::load(&fname);
    let mut screen = Screen::new();
    run_code(&mut ic, &mut screen);

    let num_blocks: u32 = screen.screen.values().map(|v| match v { 2 => 1, _ => 0 }).sum();
    println!("Step 1: {} block tiles after running", num_blocks);
}
<commit_msg>Add finish time<commit_after>
extern crate clap;
extern crate intcode;

// Time Start: Fri, 13 Dec 2019 09:13:42 -0500
// Time Finish 1: Fri, 13 Dec 2019 09:38:12 -0500 (24 minutes, 30 seconds)
// Time Finish 2: Fri, 13 Dec 2019 10:41:59 -0500 (1 hour, 3 minutes, 47 seconds)
// Time Total: 1 hour, 28 minutes, 17 seconds

use clap::{Arg, App};

use intcode::Intcode;
use intcode::Val;

use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt;
use std::{thread, time};

#[derive(Copy, Clone)]
struct BBox(i64,i64,i64,i64);// xmin, xmax, ymin, ymax
impl BBox {
    pub fn new() -> BBox {
        BBox(0,0,0,0)
    }

    pub fn xmin(&self) -> i64 { self.0 }
    pub fn xmax(&self) -> i64 { self.1 }
    pub fn ymin(&self) -> i64 { self.2 }
    pub fn ymax(&self) -> i64 { self.3 }

    pub fn update(&mut self, x: i64, y: i64) {
        if x < self.0 { self.0 = x; }
        if x > self.1 { self.1 = x; }
        if y < self.2 { self.2 = y; }
        if y > self.3 { self.3 = y; }
    }
}
impl fmt::Display for BBox {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "BBox: {}, {}, {}, {}", self.0, self.1, self.2, self.3)
    }
}

struct Screen {
    pub screen: HashMap<(i64, i64), u8>,
    pub bbox: BBox,
}
impl Screen {
    pub fn new() -> Screen {
        Screen {
            screen: HashMap::new(),
            bbox: BBox::new(),
        }
    }

    pub fn item_at(&self, x: i64, y: i64) -> u8 {
        match self.screen.get(&(x,y)) {
            Some(x) => *x,
            None    => 0,
        }
    }

    pub fn put(&mut self, x: i64, y: i64, obj: u8) {
        self.bbox.update(x, y);
        self.screen.insert((x, y), obj);
    }
}
impl fmt::Display for Screen {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for y in (self.bbox.ymin()..=self.bbox.ymax()).rev() {
            for x in self.bbox.xmin()..=self.bbox.xmax() {
                if let Err(err) = match self.item_at(x, y) {
                    0 => write!(f, "{}", " "), // empty
                    1 => write!(f, "{}", "#"), // wall
                    2 => write!(f, "{}", "@"), // block
                    3 => write!(f, "{}", "-"), // paddle
                    4 => write!(f, "{}", "*"), // ball
                    x => panic!("Unexpected object: {}", x),
                } {
                    return Err(err);
                }
            }
            if let Err(err) = write!(f, "{}", "\n") {
                return Err(err);
            }
        }
        Ok(())
    }
}

struct Pong {
    paddle: i64,
    ball_x: i64,
    ball_dx: i64,
    pub score: i64,
    blocks: HashSet<(i64, i64)>,
}
impl Pong {
    pub fn new() -> Pong {
        Pong {
            paddle:  0,
            ball_x:  9999,
            ball_dx: 0,
            score:   0,
            blocks: HashSet::new(),
        }
    }

    fn draw(&self, screen: &Screen) {
        println!("\x1B[H\x1B[2J{}\n\n Score: {}", screen, self.score);
        thread::sleep(time::Duration::from_millis(10));
    }

    fn run_code(&mut self, ic: &mut Intcode) {
        let mut screen = Screen::new();
        ic.set_input(0);
        loop {
            while ic.output_len() < 3 && ic.step() { }

            if ic.is_halted() { break; }

            let x = ic.shift_output().expect("x output disappeared!");
            let y = ic.shift_output().expect("y output disappeared!");
            let obj = ic.shift_output().expect("object output disappeared!");

            if x == -1 && y == 0 {
                self.score = obj;
                continue;
            }

            screen.put(x, y, obj as u8);

            match obj {
                0 => { self.blocks.remove(&(x,y)); },                                         // empty
                1 => (),                                                                      // wall
                2 => { self.blocks.insert((x,y)); },                                          // block
                3 => { self.paddle = x; self.draw(&screen); },                                // paddle
                4 => { self.ball_dx = x - self.ball_x; self.ball_x = x; self.draw(&screen); } // ball
                x => unreachable!("Unexpected object {}", x),
            }

            if self.ball_dx < 1000 { self.ball_dx = 0; } // ugly handling of initial conditions

            if self.paddle < self.ball_x + self.ball_dx {
                ic.set_input(1);
            }
            else if self.paddle > self.ball_x + self.ball_dx {
                ic.set_input(-1);
            }
            else {
                ic.set_input(0);
            }
        }
        self.draw(&screen);
    }
}

fn run_code(ic: &mut Intcode, screen: &mut Screen) {
    loop {
        while ic.output_len() < 3 && ic.step() { }

        if ic.is_halted() { break; }

        let x = ic.shift_output().expect("x output disappeared!");
        let y = ic.shift_output().expect("y output disappeared!");
        let obj = ic.shift_output().expect("object output disappeared!") as u8;
        screen.put(x, y, obj);
    }
}

fn main() {
    let matches = App::new("Advent of Code 2019, Day 13")
        .arg(Arg::with_name("FILE")
             .help("Input file to process")
             .index(1))
        .get_matches();
    let fname = String::from(matches.value_of("FILE").unwrap_or("13.in"));

    let mut ic = Intcode::load(&fname);
    let mut pong = Pong::new();
    ic.set(&Val::Address(0), 2); // Insert quarter

    pong.run_code(&mut ic);

    println!("Step 2: final score {}", pong.score);

    let mut ic = Intcode::load(&fname);
    let mut screen = Screen::new();
    run_code(&mut ic, &mut screen);

    let num_blocks: u32 = screen.screen.values().map(|v| match v { 2 => 1, _ => 0 }).sum();
    println!("Step 1: {} block tiles after running", num_blocks);
}
<|endoftext|>


<commit_before>
use {Parcel, Error, Settings};

use std::io::prelude::*;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Unimplemented;

impl Parcel for Unimplemented
{
    const TYPE_NAME: &'static str = "Unimplemented";

    fn read(_: &mut Read,
            _: &Settings) -> Result<Self, Error> {
        unimplemented!();
    }

    fn write(&self, _: &mut Write,
             _: &Settings) -> Result<(), Error> {
        unimplemented!();
    }
}

<commit_msg>Document the unimplemented type<commit_after>
use {Parcel, Error, Settings};

use std::io::prelude::*;

/// A type that does not have any protocol serialization implemented.
///
/// Panics whenever a read or write of this value is attempted.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Unimplemented;

impl Parcel for Unimplemented
{
    const TYPE_NAME: &'static str = "Unimplemented";

    fn read(_: &mut Read,
            _: &Settings) -> Result<Self, Error> {
        unimplemented!();
    }

    fn write(&self, _: &mut Write,
             _: &Settings) -> Result<(), Error> {
        unimplemented!();
    }
}

<|endoftext|>


<commit_before>use std::{error, fmt, result};

use persistent_log::Log;
use LogIndex;
use ServerId;
use Term;

/// This is a `Log` implementation that stores entries in a simple in-memory vector. Other data
/// is stored in a struct. It is chiefly intended for testing.
///
/// # Panic
///
/// No bounds checking is performed and attempted access to non-existing log
/// indexes will panic.
#[derive(Clone, Debug)]
pub struct MemLog {
    current_term: Term,
    voted_for: Option<ServerId>,
    entries: Vec<(Term, Vec<u8>)>,
}

/// Non-instantiable error type for MemLog
pub enum Error { }

impl fmt::Display for Error {
    fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result {
        unreachable!()
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result {
        unreachable!()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        unreachable!()
    }
}

impl MemLog {
    pub fn new() -> MemLog {
        MemLog {
            current_term: Term(0),
            voted_for: None,
            entries: Vec::new(),
        }
    }
}

impl Log for MemLog {
    type Error = Error;

    fn current_term(&self) -> result::Result<Term, Error> {
        Ok(self.current_term)
    }

    fn set_current_term(&mut self, term: Term) -> result::Result<(), Error> {
        self.voted_for = None;
        Ok(self.current_term = term)
    }

    fn inc_current_term(&mut self) -> result::Result<Term, Error> {
        self.voted_for = None;
        self.current_term = self.current_term + 1;
        self.current_term()
    }

    fn voted_for(&self) -> result::Result<Option<ServerId>, Error> {
        Ok(self.voted_for)
    }

    fn set_voted_for(&mut self, address: ServerId) -> result::Result<(), Error> {
        Ok(self.voted_for = Some(address))
    }

    fn latest_log_index(&self) -> result::Result<LogIndex, Error> {
        Ok(LogIndex(self.entries.len() as u64))
    }

    fn latest_log_term(&self) -> result::Result<Term, Error> {
        let len = self.entries.len();
        if len == 0 {
            Ok(Term::from(0))
        } else {
            Ok(self.entries[len - 1].0)
        }
    }

    fn entry(&self, index: LogIndex) -> result::Result<(Term, &[u8]), Error> {
        let (term, ref bytes) = self.entries[(index - 1).as_u64() as usize];
        Ok((term, &bytes))
    }

    fn append_entries(&mut self,
                      from: LogIndex,
                      entries: &[(Term, &[u8])])
                      -> result::Result<(), Error> {
        assert!(self.latest_log_index().unwrap() + 1 >= from);
        self.entries.truncate((from - 1).as_u64() as usize);
        Ok(self.entries.extend(entries.iter().map(|&(term, command)| (term, command.to_vec()))))
    }
}

#[cfg(test)]
mod test {

    use super::*;
    use LogIndex;
    use ServerId;
    use Term;
    use persistent_log::Log;

    #[test]
    fn test_current_term() {
        let mut store = MemLog::new();
        assert_eq!(Term(0), store.current_term().unwrap());
        store.set_voted_for(ServerId::from(0)).unwrap();
        store.set_current_term(Term(42)).unwrap();
        assert_eq!(None, store.voted_for().unwrap());
        assert_eq!(Term(42), store.current_term().unwrap());
        store.inc_current_term().unwrap();
        assert_eq!(Term(43), store.current_term().unwrap());
    }

    #[test]
    fn test_voted_for() {
        let mut store = MemLog::new();
        assert_eq!(None, store.voted_for().unwrap());
        let id = ServerId::from(0);
        store.set_voted_for(id).unwrap();
        assert_eq!(Some(id), store.voted_for().unwrap());
    }

    #[test]
    fn test_append_entries() {
        let mut store = MemLog::new();
        assert_eq!(LogIndex::from(0), store.latest_log_index().unwrap());
        assert_eq!(Term::from(0), store.latest_log_term().unwrap());

        // [0.1, 0.2, 0.3, 1.4]
        store.append_entries(LogIndex(1),
                             &[(Term::from(0), &[1]),
                               (Term::from(0), &[2]),
                               (Term::from(0), &[3]),
                               (Term::from(1), &[4])])
             .unwrap();
        assert_eq!(LogIndex::from(4), store.latest_log_index().unwrap());
        assert_eq!(Term::from(1), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(0), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());
        assert_eq!((Term::from(1), &*vec![4u8]),
                   store.entry(LogIndex::from(4)).unwrap());

        // [0.1, 0.2, 0.3]
        store.append_entries(LogIndex::from(4), &[]).unwrap();
        assert_eq!(LogIndex(3), store.latest_log_index().unwrap());
        assert_eq!(Term::from(0), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(0), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());

        // [0.1, 0.2, 2.3, 3.4]
        store.append_entries(LogIndex::from(3), &[(Term(2), &[3]), (Term(3), &[4])]).unwrap();
        assert_eq!(LogIndex(4), store.latest_log_index().unwrap());
        assert_eq!(Term::from(3), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(2), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());
        assert_eq!((Term::from(3), &*vec![4u8]),
                   store.entry(LogIndex::from(4)).unwrap());
    }
}
<commit_msg>Remove unnecessary deref.<commit_after>use std::{error, fmt, result};

use persistent_log::Log;
use LogIndex;
use ServerId;
use Term;

/// This is a `Log` implementation that stores entries in a simple in-memory vector. Other data
/// is stored in a struct. It is chiefly intended for testing.
///
/// # Panic
///
/// No bounds checking is performed and attempted access to non-existing log
/// indexes will panic.
#[derive(Clone, Debug)]
pub struct MemLog {
    current_term: Term,
    voted_for: Option<ServerId>,
    entries: Vec<(Term, Vec<u8>)>,
}

/// Non-instantiable error type for MemLog
pub enum Error { }

impl fmt::Display for Error {
    fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result {
        unreachable!()
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result {
        unreachable!()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        unreachable!()
    }
}

impl MemLog {
    pub fn new() -> MemLog {
        MemLog {
            current_term: Term(0),
            voted_for: None,
            entries: Vec::new(),
        }
    }
}

impl Log for MemLog {
    type Error = Error;

    fn current_term(&self) -> result::Result<Term, Error> {
        Ok(self.current_term)
    }

    fn set_current_term(&mut self, term: Term) -> result::Result<(), Error> {
        self.voted_for = None;
        Ok(self.current_term = term)
    }

    fn inc_current_term(&mut self) -> result::Result<Term, Error> {
        self.voted_for = None;
        self.current_term = self.current_term + 1;
        self.current_term()
    }

    fn voted_for(&self) -> result::Result<Option<ServerId>, Error> {
        Ok(self.voted_for)
    }

    fn set_voted_for(&mut self, address: ServerId) -> result::Result<(), Error> {
        Ok(self.voted_for = Some(address))
    }

    fn latest_log_index(&self) -> result::Result<LogIndex, Error> {
        Ok(LogIndex(self.entries.len() as u64))
    }

    fn latest_log_term(&self) -> result::Result<Term, Error> {
        let len = self.entries.len();
        if len == 0 {
            Ok(Term::from(0))
        } else {
            Ok(self.entries[len - 1].0)
        }
    }

    fn entry(&self, index: LogIndex) -> result::Result<(Term, &[u8]), Error> {
        let (term, ref bytes) = self.entries[(index - 1).as_u64() as usize];
        Ok((term, bytes))
    }

    fn append_entries(&mut self,
                      from: LogIndex,
                      entries: &[(Term, &[u8])])
                      -> result::Result<(), Error> {
        assert!(self.latest_log_index().unwrap() + 1 >= from);
        self.entries.truncate((from - 1).as_u64() as usize);
        Ok(self.entries.extend(entries.iter().map(|&(term, command)| (term, command.to_vec()))))
    }
}

#[cfg(test)]
mod test {

    use super::*;
    use LogIndex;
    use ServerId;
    use Term;
    use persistent_log::Log;

    #[test]
    fn test_current_term() {
        let mut store = MemLog::new();
        assert_eq!(Term(0), store.current_term().unwrap());
        store.set_voted_for(ServerId::from(0)).unwrap();
        store.set_current_term(Term(42)).unwrap();
        assert_eq!(None, store.voted_for().unwrap());
        assert_eq!(Term(42), store.current_term().unwrap());
        store.inc_current_term().unwrap();
        assert_eq!(Term(43), store.current_term().unwrap());
    }

    #[test]
    fn test_voted_for() {
        let mut store = MemLog::new();
        assert_eq!(None, store.voted_for().unwrap());
        let id = ServerId::from(0);
        store.set_voted_for(id).unwrap();
        assert_eq!(Some(id), store.voted_for().unwrap());
    }

    #[test]
    fn test_append_entries() {
        let mut store = MemLog::new();
        assert_eq!(LogIndex::from(0), store.latest_log_index().unwrap());
        assert_eq!(Term::from(0), store.latest_log_term().unwrap());

        // [0.1, 0.2, 0.3, 1.4]
        store.append_entries(LogIndex(1),
                             &[(Term::from(0), &[1]),
                               (Term::from(0), &[2]),
                               (Term::from(0), &[3]),
                               (Term::from(1), &[4])])
             .unwrap();
        assert_eq!(LogIndex::from(4), store.latest_log_index().unwrap());
        assert_eq!(Term::from(1), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(0), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());
        assert_eq!((Term::from(1), &*vec![4u8]),
                   store.entry(LogIndex::from(4)).unwrap());

        // [0.1, 0.2, 0.3]
        store.append_entries(LogIndex::from(4), &[]).unwrap();
        assert_eq!(LogIndex(3), store.latest_log_index().unwrap());
        assert_eq!(Term::from(0), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(0), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());

        // [0.1, 0.2, 2.3, 3.4]
        store.append_entries(LogIndex::from(3), &[(Term(2), &[3]), (Term(3), &[4])]).unwrap();
        assert_eq!(LogIndex(4), store.latest_log_index().unwrap());
        assert_eq!(Term::from(3), store.latest_log_term().unwrap());
        assert_eq!((Term::from(0), &*vec![1u8]),
                   store.entry(LogIndex::from(1)).unwrap());
        assert_eq!((Term::from(0), &*vec![2u8]),
                   store.entry(LogIndex::from(2)).unwrap());
        assert_eq!((Term::from(2), &*vec![3u8]),
                   store.entry(LogIndex::from(3)).unwrap());
        assert_eq!((Term::from(3), &*vec![4u8]),
                   store.entry(LogIndex::from(4)).unwrap());
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: 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 Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate docopt;
extern crate csv;
extern crate rustc_serialize;
extern crate curl;
extern crate mimir;
#[macro_use]
extern crate log;

use std::path::Path;
use mimir::rubber::Rubber;
use std::fs;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Bano {
    pub id: String,
    pub nb: String,
    pub street: String,
    pub zip: String,
    pub city: String,
    pub src: String,
    pub lat: f64,
    pub lon: f64,
}

impl Bano {
    pub fn insee(&self) -> &str {
        assert!(self.id.len() >= 5);
        self.id[..5].trim_left_matches('0')
    }
    pub fn fantoir(&self) -> &str {
        assert!(self.id.len() >= 10);
        &self.id[..10]
    }
    pub fn into_addr(self) -> mimir::Addr {
        let street_name = format!("{}, {} {}", self.street, self.zip, self.city);
        let addr_name = format!("{} {}", self.nb, street_name);
        let street_id = format!("street:{}", self.fantoir().to_string());
        let admin = mimir::Admin {
            id: format!("admin:fr:{}", self.insee()),
            level: 8,
            name: self.city,
            zip_code: self.zip,
            weight: 1,
            coord: Some(mimir::Coord {
                lat: 0.0,
                lon: 0.0,
            }),
            boundary: None,
        };
        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            name: street_name,
            administrative_region: Some(admin),
            weight: 1,
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lat, self.lon),
            house_number: self.nb,
            street: street,
            name: addr_name,
            coord: mimir::Coord {
                lat: self.lat,
                lon: self.lon,
            },
            weight: 1,
        }
    }
}

fn index_bano<I>(cnx_string: &str, files: I)
    where I: Iterator<Item = std::path::PathBuf>
{
    let mut rubber = Rubber::new(cnx_string);
    rubber.create_index();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::Reader::from_file(&f).unwrap().has_headers(false);

        let iter = rdr.decode().map(|r| {
            let b: Bano = r.unwrap();
            b.into_addr()
        });
        match rubber.index(iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_connection_string: String,
}

static USAGE: &'static str = "
Usage:
    bano2mimir --input=<input> [--connection-string=<connection-string>]

    -i, --input=<input>           Bano files. Can be either a directory or a file.
    -c, --connection-string=<connection-string>
                                  Elasticsearch parameters, [default: http://localhost:9200/munin]
";

fn main() {
    mimir::logger_init().unwrap();
    info!("importing bano into Mimir");

    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let file_path = Path::new(&args.flag_input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.flag_input).unwrap();
        index_bano(&args.flag_connection_string,
                   paths.map(|p| p.unwrap().path()));
    } else {
        index_bano(&args.flag_connection_string,
                   std::iter::once(std::path::PathBuf::from(&args.flag_input)));
    }
}
<commit_msg>id of addr was in the wrong order kraken use lon;lat<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: 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 Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate docopt;
extern crate csv;
extern crate rustc_serialize;
extern crate curl;
extern crate mimir;
#[macro_use]
extern crate log;

use std::path::Path;
use mimir::rubber::Rubber;
use std::fs;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Bano {
    pub id: String,
    pub nb: String,
    pub street: String,
    pub zip: String,
    pub city: String,
    pub src: String,
    pub lat: f64,
    pub lon: f64,
}

impl Bano {
    pub fn insee(&self) -> &str {
        assert!(self.id.len() >= 5);
        self.id[..5].trim_left_matches('0')
    }
    pub fn fantoir(&self) -> &str {
        assert!(self.id.len() >= 10);
        &self.id[..10]
    }
    pub fn into_addr(self) -> mimir::Addr {
        let street_name = format!("{}, {} {}", self.street, self.zip, self.city);
        let addr_name = format!("{} {}", self.nb, street_name);
        let street_id = format!("street:{}", self.fantoir().to_string());
        let admin = mimir::Admin {
            id: format!("admin:fr:{}", self.insee()),
            level: 8,
            name: self.city,
            zip_code: self.zip,
            weight: 1,
            coord: Some(mimir::Coord {
                lat: 0.0,
                lon: 0.0,
            }),
            boundary: None,
        };
        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            name: street_name,
            administrative_region: Some(admin),
            weight: 1,
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            house_number: self.nb,
            street: street,
            name: addr_name,
            coord: mimir::Coord {
                lat: self.lat,
                lon: self.lon,
            },
            weight: 1,
        }
    }
}

fn index_bano<I>(cnx_string: &str, files: I)
    where I: Iterator<Item = std::path::PathBuf>
{
    let mut rubber = Rubber::new(cnx_string);
    rubber.create_index();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::Reader::from_file(&f).unwrap().has_headers(false);

        let iter = rdr.decode().map(|r| {
            let b: Bano = r.unwrap();
            b.into_addr()
        });
        match rubber.index(iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_connection_string: String,
}

static USAGE: &'static str = "
Usage:
    bano2mimir --input=<input> [--connection-string=<connection-string>]

    -i, --input=<input>           Bano files. Can be either a directory or a file.
    -c, --connection-string=<connection-string>
                                  Elasticsearch parameters, [default: http://localhost:9200/munin]
";

fn main() {
    mimir::logger_init().unwrap();
    info!("importing bano into Mimir");

    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let file_path = Path::new(&args.flag_input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.flag_input).unwrap();
        index_bano(&args.flag_connection_string,
                   paths.map(|p| p.unwrap().path()));
    } else {
        index_bano(&args.flag_connection_string,
                   std::iter::once(std::path::PathBuf::from(&args.flag_input)));
    }
}
<|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/. */

use bindgen::ir::{Path, Type};

pub fn mangle_path(path: &Path, generic_values: &[Type]) -> Path {
    internal_mangle_path(path, generic_values, true)
}

pub fn mangle_name(name: &str, generic_values: &[Type]) -> String {
    internal_mangle_name(name, generic_values, true)
}

fn internal_mangle_path(path: &Path, generic_values: &[Type], last_in_parent: bool) -> Path {
    let name = path.name();
    let mangled_name = internal_mangle_name(name, generic_values, last_in_parent);
    Path::new(mangled_name)
}

fn internal_mangle_name(name: &str, generic_values: &[Type], last_in_parent: bool) -> String {
    if generic_values.is_empty() {
        return name.to_owned();
    }

    let mut mangled = name.to_owned();

    mangled.push_str("_"); // <
    for (i, ty) in generic_values.iter().enumerate() {
        if i != 0 {
            mangled.push_str("__"); // ,
        }

        let is_last = i == generic_values.len() - 1;
        match ty {
            &Type::Path(ref generic) => {
                mangled.push_str(&internal_mangle_name(
                    generic.export_name(),
                    generic.generics(),
                    last_in_parent && is_last,
                ));
            }
            &Type::Primitive(ref primitive) => {
                mangled.push_str(primitive.to_repr_rust());
            }
            &Type::MutRef(..)
            | &Type::Ref(..)
            | &Type::ConstPtr(..)
            | &Type::Ptr(..)
            | &Type::Array(..)
            | &Type::FuncPtr(..) => unimplemented!(),
        }

        // Skip writing the trailing '>' mangling when possible
        if is_last && !last_in_parent {
            mangled.push_str("___"); // >
        }
    }

    mangled
}

#[test]
fn generics() {
    use bindgen::ir::{GenericPath, PrimitiveType};

    fn float() -> Type {
        Type::Primitive(PrimitiveType::Float)
    }

    fn path(path: &str) -> Type {
        generic_path(path, &vec![])
    }

    fn generic_path(path: &str, generics: &[Type]) -> Type {
        let path = Path::new(path);
        let generic_path = GenericPath::new(path, generics.to_owned());
        Type::Path(generic_path)
    }

    // Foo<f32> => Foo_f32
    assert_eq!(
        mangle_path(&Path::new("Foo"), &vec![float()]),
        Path::new("Foo_f32")
    );

    // Foo<Bar<f32>> => Foo_Bar_f32
    assert_eq!(
        mangle_path(&Path::new("Foo"), &vec![generic_path("Bar", &[float()])]),
        Path::new("Foo_Bar_f32")
    );

    // Foo<Bar> => Foo_Bar
    assert_eq!(
        mangle_path(&Path::new("Foo"), &[path("Bar")]),
        Path::new("Foo_Bar")
    );

    // Foo<Bar<T>> => Foo_Bar_T
    assert_eq!(
        mangle_path(&Path::new("Foo"), &[generic_path("Bar", &[path("T")])]),
        Path::new("Foo_Bar_T")
    );

    // Foo<Bar<T>, E> => Foo_Bar_T_____E
    assert_eq!(
        mangle_path(
            &Path::new("Foo"),
            &[generic_path("Bar", &[path("T")]), path("E")]
        ),
        Path::new("Foo_Bar_T_____E")
    );

    // Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E
    assert_eq!(
        mangle_path(
            &Path::new("Foo"),
            &[
                generic_path("Bar", &[path("T")]),
                generic_path("Bar", &[path("E")]),
            ]
        ),
        Path::new("Foo_Bar_T_____Bar_E")
    );
}
<commit_msg>Improve mangling error message<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/. */

use bindgen::ir::{Path, Type};

pub fn mangle_path(path: &Path, generic_values: &[Type]) -> Path {
    internal_mangle_path(path, generic_values, true)
}

pub fn mangle_name(name: &str, generic_values: &[Type]) -> String {
    internal_mangle_name(name, generic_values, true)
}

fn internal_mangle_path(path: &Path, generic_values: &[Type], last_in_parent: bool) -> Path {
    let name = path.name();
    let mangled_name = internal_mangle_name(name, generic_values, last_in_parent);
    Path::new(mangled_name)
}

fn internal_mangle_name(name: &str, generic_values: &[Type], last_in_parent: bool) -> String {
    if generic_values.is_empty() {
        return name.to_owned();
    }

    let mut mangled = name.to_owned();

    mangled.push_str("_"); // <
    for (i, ty) in generic_values.iter().enumerate() {
        if i != 0 {
            mangled.push_str("__"); // ,
        }

        let is_last = i == generic_values.len() - 1;
        match *ty {
            Type::Path(ref generic) => {
                mangled.push_str(&internal_mangle_name(
                    generic.export_name(),
                    generic.generics(),
                    last_in_parent && is_last,
                ));
            }
            Type::Primitive(ref primitive) => {
                mangled.push_str(primitive.to_repr_rust());
            }
            Type::MutRef(..)
            | Type::Ref(..)
            | Type::ConstPtr(..)
            | Type::Ptr(..)
            | Type::Array(..)
            | Type::FuncPtr(..) => {
                panic!("Unable to mangle generic parameter {:?} for '{}'", ty, name);
            }
        }

        // Skip writing the trailing '>' mangling when possible
        if is_last && !last_in_parent {
            mangled.push_str("___"); // >
        }
    }

    mangled
}

#[test]
fn generics() {
    use bindgen::ir::{GenericPath, PrimitiveType};

    fn float() -> Type {
        Type::Primitive(PrimitiveType::Float)
    }

    fn path(path: &str) -> Type {
        generic_path(path, &vec![])
    }

    fn generic_path(path: &str, generics: &[Type]) -> Type {
        let path = Path::new(path);
        let generic_path = GenericPath::new(path, generics.to_owned());
        Type::Path(generic_path)
    }

    // Foo<f32> => Foo_f32
    assert_eq!(
        mangle_path(&Path::new("Foo"), &vec![float()]),
        Path::new("Foo_f32")
    );

    // Foo<Bar<f32>> => Foo_Bar_f32
    assert_eq!(
        mangle_path(&Path::new("Foo"), &vec![generic_path("Bar", &[float()])]),
        Path::new("Foo_Bar_f32")
    );

    // Foo<Bar> => Foo_Bar
    assert_eq!(
        mangle_path(&Path::new("Foo"), &[path("Bar")]),
        Path::new("Foo_Bar")
    );

    // Foo<Bar<T>> => Foo_Bar_T
    assert_eq!(
        mangle_path(&Path::new("Foo"), &[generic_path("Bar", &[path("T")])]),
        Path::new("Foo_Bar_T")
    );

    // Foo<Bar<T>, E> => Foo_Bar_T_____E
    assert_eq!(
        mangle_path(
            &Path::new("Foo"),
            &[generic_path("Bar", &[path("T")]), path("E")]
        ),
        Path::new("Foo_Bar_T_____E")
    );

    // Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E
    assert_eq!(
        mangle_path(
            &Path::new("Foo"),
            &[
                generic_path("Bar", &[path("T")]),
                generic_path("Bar", &[path("E")]),
            ]
        ),
        Path::new("Foo_Bar_T_____Bar_E")
    );
}
<|endoftext|>


<commit_before>use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
use std::fmt::{Debug, Formatter, Result};
use bit_reverse::ParallelReverse;

/// Represents a 64-bit bitboard.
#[derive(PartialEq, Clone, Copy)]
pub struct BitBoard(pub u64);

impl BitBoard {
    pub fn flip(&self) -> Self {
        BitBoard(self.0.swap_bits())
    }
}

// ---------------------------------------------------------------------------
// Operations
impl BitAnd for BitBoard {
    type Output = Self;

    fn bitand(self, rhs: Self) -> Self {
        BitBoard(self.0 & rhs.0)
    }
}

impl BitAndAssign for BitBoard {
    fn bitand_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 & rhs.0)
    }
}

impl BitOr for BitBoard {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        BitBoard(self.0 | rhs.0)
    }
}

impl BitOrAssign for BitBoard {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 | rhs.0)
    }
}

impl BitXor for BitBoard {
    type Output = Self;

    fn bitxor(self, rhs: Self) -> Self {
        BitBoard(self.0 ^ rhs.0)
    }
}

impl BitXorAssign for BitBoard {
    fn bitxor_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 ^ rhs.0)
    }
}

impl Not for BitBoard {
    type Output = Self;

    fn not(self) -> Self {
        BitBoard(!self.0)
    }
}

// ---------------------------------------------------------------------------
// Debug
impl Debug for BitBoard {
    #[allow(unused_must_use)]
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "\n{}:\n+-+-+-+-+-+-+-+-+-+\n", self.0);
        for rank in 0..8 {
            write!(f, "| ");
            for file in 0..8 {
                write!(f, "{} ", if self.0 & (1 << ((7 - rank) * 8 + file)) > 0 { "X" } else { "-" });
            }
            write!(f, "|\n");
        }
        write!(f, "+-+-+-+-+-+-+-+-+-+")
    }
}
<commit_msg>Manually implement display intead of debug<commit_after>use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
use std::fmt::{Formatter, Result, Display};
use bit_reverse::ParallelReverse;

/// Represents a 64-bit bitboard.
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct BitBoard(pub u64);

impl BitBoard {
    pub fn flip(&self) -> Self {
        BitBoard(self.0.swap_bits())
    }
}

// ---------------------------------------------------------------------------
// Operations
impl BitAnd for BitBoard {
    type Output = Self;

    fn bitand(self, rhs: Self) -> Self {
        BitBoard(self.0 & rhs.0)
    }
}

impl BitAndAssign for BitBoard {
    fn bitand_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 & rhs.0)
    }
}

impl BitOr for BitBoard {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        BitBoard(self.0 | rhs.0)
    }
}

impl BitOrAssign for BitBoard {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 | rhs.0)
    }
}

impl BitXor for BitBoard {
    type Output = Self;

    fn bitxor(self, rhs: Self) -> Self {
        BitBoard(self.0 ^ rhs.0)
    }
}

impl BitXorAssign for BitBoard {
    fn bitxor_assign(&mut self, rhs: Self) {
        *self = BitBoard(self.0 ^ rhs.0)
    }
}

impl Not for BitBoard {
    type Output = Self;

    fn not(self) -> Self {
        BitBoard(!self.0)
    }
}

// ---------------------------------------------------------------------------
// Display
impl Display for BitBoard {
    #[allow(unused_must_use)]
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "\n{}:\n+-+-+-+-+-+-+-+-+-+\n", self.0);
        for rank in 0..8 {
            write!(f, "| ");
            for file in 0..8 {
                write!(f, "{} ", if self.0 & (1 << ((7 - rank) * 8 + file)) > 0 { "X" } else { "-" });
            }
            write!(f, "|\n");
        }
        write!(f, "+-+-+-+-+-+-+-+-+-+")
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cmp::{max, min, Ordering};

use interpreter::{TreeInterpreter, InterpretResult};
use variable::Variable;

/// Handles the dispatching of named functions using an array of arguments.
pub trait FnDispatcher {
    /// Dispatches and interprets a function by name.
    fn call(&self, fn_name: &str, args: &Vec<Rc<Variable>>, intr: &TreeInterpreter)
        -> InterpretResult;
}

/// Validates the arity of a function.
#[inline]
fn arity(fn_name: &str, arity: usize, args: &Vec<Rc<Variable>>) -> Result<(), String> {
    if args.len() != arity {
        Err(format!("{} arity error: expected {} args, found {}", fn_name, arity, args.len()))
    } else {
        Ok(())
    }
}

/// Validates that an array contains only a single allowed type.
#[inline]
fn homogeneous_array(valid_types: Vec<&str>, array: &Vec<Rc<Variable>>) -> bool {
    let matched_type = array[0].get_type();
    if !valid_types.contains(&matched_type) {
        return false;
    }
    for a in array {
        if a.get_type() != matched_type {
            return false;
        }
    }
    return true;
}

/// Macro used to variadically validate validate Variable and argument arity.
macro_rules! validate {
    // Validate positional arguments only.
    ($name:expr, $args:expr, $($x:expr),*) => (
        {
            let validators: Vec<Box<Fn(&Rc<Variable>) -> Result<(), String>>> = vec![$($x), *];
            try!(arity($name, validators.len(), $args));
            for (k, v) in $args.iter().enumerate() {
                if let Err(e) = validators[k](v) {
                    return Err(format!("{} error at argument {}: {}", $name, k, e));
                }
            }
        }
    );
    // Validate positional arguments with a variadic validator.
    ($name:expr, $args:expr, $($x:expr),* ...$variadic:expr ) => (
        {
            let validators: Vec<Box<Fn(&Rc<Variable>) -> Result<(), String>>> = vec![$($x), *];
            if $args.len() < validators.len() {
                return Err(format!("{} arity error: expected at least {} args, found {}",
                                   $name, validators.len(), $args.len()));
            }
            for (k, v) in $args.iter().enumerate() {
                try!((match validators.get(k) {
                    Some(validator) => validator(v),
                    None => $variadic(v)
                }).or_else(|e| Err(format!("{} error at argument {}: {}", $name, k, e))));
            }
        }
    );
}

/// Validates that a vector contains a homogeneous array of a specific type(s).
macro_rules! array {
    ($($x:ident)|*) => [
        Box::new(move |arg: &Rc<Variable>| -> Result<(), String> {
            let valid_types = vec![$(stringify!($x)), *];
            match **arg {
                Variable::Array(ref array) if array.is_empty() => Ok(()),
                Variable::Array(ref array) if homogeneous_array(valid_types, array) => Ok(()),
                _ => Err(format!("type array[{}]", valid_types.join("|")))
            }
        })
    ];
}

/// Creates a closure used to validate the type of the given variable.
macro_rules! types {
    ($($x:ident)|*) => [
        {
            Box::new(move |arg: &Rc<Variable>| -> Result<(), String> {
                let valid_types = vec![$(stringify!($x)), *];
                let arg_type = arg.get_type();
                if arg_type == "any" || valid_types.contains(&arg_type) {
                    Ok(())
                } else {
                    Err(format!("type {}", valid_types.join("|")))
                }
            })
        }
    ];
}

/// Macro used to implement min and max functions.
macro_rules! min_max {
    ($operator:ident, $args:expr) => (
        {
            validate!(stringify!($operator), $args, array![string|number]);
            match *$args[0] {
                Variable::Array(ref array) if array.is_empty() => Ok(Rc::new(Variable::Null)),
                Variable::Array(ref array) => {
                    if array[0].is_string() {
                        Ok(Rc::new(Variable::String(array.iter().fold(
                            array[0].as_string().unwrap().clone(),
                            |acc, item| $operator(acc, item.as_string().unwrap().clone())))))
                    } else {
                        Ok(Rc::new(Variable::F64(array.iter().fold(
                            array[0].as_f64().unwrap(),
                            |acc, item| acc.$operator(item.as_f64().unwrap())))))
                    }
                },
                _ => unreachable!()
            }
        }
    )
}

/// Macro used to implement max_by and min_by functions.
macro_rules! max_by_min_by {
    ($operator:ident, $args:expr, $interpreter:expr) => (
        {
            validate!(stringify!($operator), $args, types![array], types![expref]);
            let vals = $args[0].as_array().expect("Expected array");
            let ast = $args[1].as_expref().expect("Expected expref");
            let initial = try!($interpreter.interpret(vals[0].clone(), ast));
            let entered_type = initial.get_type();
            if entered_type != "string" && entered_type != "number" {
                return Err(format!("{}_by expref expects string|number, found {}",
                                   stringify!($operator), entered_type));
            }
            vals.iter().skip(1).map(|v| $interpreter.interpret(v.clone(), ast))
                .fold(Ok(initial.clone()), |a, b| {
                    let (a_val, b_val) = (try!(a), try!(b));
                    if b_val.get_type() != entered_type {
                        Err(format!("{}_by expref expects {}, found {:?}",
                                    stringify!($operator), entered_type, b_val))
                    } else {
                        Ok($operator(a_val, b_val))
                    }
                })
        }
    )
}

/// Built-in function implementations.
#[derive(Clone)]
pub struct BuiltinFunctions;

impl BuiltinFunctions {
    /// Creates a new Builtins function dispatcher.
    pub fn new() -> BuiltinFunctions {
        BuiltinFunctions
    }
}

impl FnDispatcher for BuiltinFunctions {
    fn call(&self, fn_name: &str, args: &Vec<Rc<Variable>>, intr: &TreeInterpreter)
        -> InterpretResult
    {
        match fn_name {
            "abs" => {
                validate!("abs", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().abs())))
            },
            "avg" => {
                validate!("avg", args, array!(number));
                let array = args[0].as_array().unwrap();
                let sum = array.iter().fold(0f64, |a, ref b| a + b.as_f64().unwrap());
                Ok(Rc::new(Variable::F64(sum / (array.len() as f64))))
            },
            "ceil" => {
                validate!("ceil", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().ceil())))
            },
            "contains" => {
                validate!("contains", args, types![array|string], types![any]);
                match *args[0] {
                    Variable::Array(ref a) => Ok(Rc::new(Variable::Boolean(a.contains(&args[1])))),
                    Variable::String(ref subj) => {
                        match args[1].as_string() {
                            None => Ok(Rc::new(Variable::Boolean(false))),
                            Some(s) => Ok(Rc::new(Variable::Boolean(subj.contains(s))))
                        }
                    },
                    _ => unreachable!()
                }
            },
            "ends_with" => {
                validate!("ends_with", args, types![string], types![string]);
                let subject = args[0].as_string().unwrap();
                let search = args[1].as_string().unwrap();
                Ok(Rc::new(Variable::Boolean(subject.ends_with(search))))
            },
            "floor" => {
                validate!("floor", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().floor())))
            },
            "join" => {
                validate!("join", args, types![string], array![string]);
                Ok(Rc::new(Variable::String(args.iter().skip(1)
                    .map(|ref v| v.as_string().unwrap().clone())
                    .collect::<Vec<String>>()
                    .join(args[0].as_string().unwrap()))))
            },
            "keys" => {
                validate!("keys", args, types![object]);
                Ok(Rc::new(args[0].object_keys_to_array().unwrap()))
            },
            "length" => {
                validate!("length", args, types![array|object|string]);
                match *args[0] {
                    Variable::Array(ref a) => Ok(Rc::new(Variable::U64(a.len() as u64))),
                    Variable::Object(ref m) => Ok(Rc::new(Variable::U64(m.len() as u64))),
                    Variable::String(ref s) => Ok(Rc::new(Variable::U64(s.len() as u64))),
                    _ => unreachable!()
                }
            },
            "max" => min_max!(max, args),
            "min" => min_max!(min, args),
            "max_by" => max_by_min_by!(max, args, intr),
            "min_by" => max_by_min_by!(min, args, intr),
            "merge" => {
                validate!("merge", args, types![object] ...types![object]);
                let mut result = args[0].as_object().unwrap().clone();
                for arg in args.iter().skip(1) {
                    result.extend(arg.as_object().unwrap().clone());
                }
                Ok(Rc::new(Variable::Object(result)))
            },
            "not_null" => {
                validate!("not_null", args, types![any] ...types![any]);
                for arg in args {
                    if **arg != Variable::Null {
                        return Ok(arg.clone());
                    }
                }
                Ok(Rc::new(Variable::Null))
            },
            "reverse" => {
                validate!("reverse", args, types![array]);
                let mut values = args.clone();
                values.reverse();
                Ok(Rc::new(Variable::Array(values)))
            },
            "sort" => {
                validate!("sort", args, array![string|number]);
                let mut values: Vec<Rc<Variable>> = args[0].as_array().unwrap().clone();
                if values[0].is_string() {
                    values.sort_by(|a, b| a.as_string().unwrap().cmp(b.as_string().unwrap()));
                } else {
                    values.sort_by(|a, b| a.as_f64().unwrap()
                        .partial_cmp(&b.as_f64().unwrap())
                        .unwrap_or(Ordering::Equal));
                }
                Ok(Rc::new(Variable::Array(values)))
            },
            "starts_with" => {
                validate!("starts_with", args, types![string], types![string]);
                let subject = args[0].as_string().unwrap();
                let search = args[1].as_string().unwrap();
                Ok(Rc::new(Variable::Boolean(subject.starts_with(search))))
            },
            "sum" => {
                validate!("sum", args, array![number]);
                let array = args[0].as_array().unwrap();
                Ok(Rc::new(Variable::F64(array.iter().fold(
                    array[0].as_f64().unwrap().clone(),
                    |acc, item| acc.max(item.as_f64().unwrap())))))
            },
            "to_array" => {
                try!(arity("to_array", 1, args));
                match *args[0] {
                    Variable::Array(_) => Ok(args[0].clone()),
                    _ => Ok(Rc::new(Variable::Array(vec![args[0].clone()])))
                }
            },
            "to_number" => {
                try!(arity("to_number", 1, args));
                match *args[0] {
                    Variable::I64(_) | Variable::F64(_) | Variable::U64(_) => Ok(args[0].clone()),
                    Variable::String(ref s) => {
                        match s.parse::<f64>() {
                            Ok(f)  => Ok(Rc::new(Variable::F64(f))),
                            Err(_) => Ok(Rc::new(Variable::Null))
                        }
                    },
                    _ => Ok(Rc::new(Variable::Null))
                }
            },
            "to_string" => {
                validate!("to_string", args, types![object|array|boolean|number|string|null]);
                Ok(Rc::new(Variable::String(args[0].to_string().unwrap())))
            },
            "type" => {
                try!(arity("type", 1, args));
                Ok(Rc::new(Variable::String(args[0].get_type().to_string())))
            },
            "values" => {
                validate!("values", args, types![object]);
                Ok(Rc::new(args[0].object_values_to_array().unwrap()))
            },
            _ => Err(format!("Unknown function: {}", fn_name))
        }
    }
}
<commit_msg>Adding sort_by<commit_after>use std::rc::Rc;
use std::cmp::{max, min, Ordering};

use interpreter::{TreeInterpreter, InterpretResult};
use variable::Variable;

/// Handles the dispatching of named functions using an array of arguments.
pub trait FnDispatcher {
    /// Dispatches and interprets a function by name.
    fn call(&self, fn_name: &str, args: &Vec<Rc<Variable>>, intr: &TreeInterpreter)
        -> InterpretResult;
}

/// Validates the arity of a function.
#[inline]
fn arity(fn_name: &str, arity: usize, args: &Vec<Rc<Variable>>) -> Result<(), String> {
    if args.len() != arity {
        Err(format!("{} arity error: expected {} args, found {}", fn_name, arity, args.len()))
    } else {
        Ok(())
    }
}

/// Validates that an array contains only a single allowed type.
#[inline]
fn homogeneous_array(valid_types: Vec<&str>, array: &Vec<Rc<Variable>>) -> bool {
    let matched_type = array[0].get_type();
    if !valid_types.contains(&matched_type) {
        return false;
    }
    for a in array {
        if a.get_type() != matched_type {
            return false;
        }
    }
    return true;
}

/// Macro used to variadically validate validate Variable and argument arity.
macro_rules! validate {
    // Validate positional arguments only.
    ($name:expr, $args:expr, $($x:expr),*) => (
        {
            let validators: Vec<Box<Fn(&Rc<Variable>) -> Result<(), String>>> = vec![$($x), *];
            try!(arity($name, validators.len(), $args));
            for (k, v) in $args.iter().enumerate() {
                if let Err(e) = validators[k](v) {
                    return Err(format!("{} error at argument {}: {}", $name, k, e));
                }
            }
        }
    );
    // Validate positional arguments with a variadic validator.
    ($name:expr, $args:expr, $($x:expr),* ...$variadic:expr ) => (
        {
            let validators: Vec<Box<Fn(&Rc<Variable>) -> Result<(), String>>> = vec![$($x), *];
            if $args.len() < validators.len() {
                return Err(format!("{} arity error: expected at least {} args, found {}",
                                   $name, validators.len(), $args.len()));
            }
            for (k, v) in $args.iter().enumerate() {
                try!((match validators.get(k) {
                    Some(validator) => validator(v),
                    None => $variadic(v)
                }).or_else(|e| Err(format!("{} error at argument {}: {}", $name, k, e))));
            }
        }
    );
}

/// Validates that a vector contains a homogeneous array of a specific type(s).
macro_rules! array {
    ($($x:ident)|*) => [
        Box::new(move |arg: &Rc<Variable>| -> Result<(), String> {
            let valid_types = vec![$(stringify!($x)), *];
            match **arg {
                Variable::Array(ref array) if array.is_empty() => Ok(()),
                Variable::Array(ref array) if homogeneous_array(valid_types, array) => Ok(()),
                _ => Err(format!("type array[{}]", valid_types.join("|")))
            }
        })
    ];
}

/// Creates a closure used to validate the type of the given variable.
macro_rules! types {
    ($($x:ident)|*) => [
        {
            Box::new(move |arg: &Rc<Variable>| -> Result<(), String> {
                let valid_types = vec![$(stringify!($x)), *];
                let arg_type = arg.get_type();
                if arg_type == "any" || valid_types.contains(&arg_type) {
                    Ok(())
                } else {
                    Err(format!("type {}", valid_types.join("|")))
                }
            })
        }
    ];
}

/// Macro used to implement min and max functions.
macro_rules! min_max {
    ($operator:ident, $args:expr) => (
        {
            validate!(stringify!($operator), $args, array![string|number]);
            match *$args[0] {
                Variable::Array(ref array) if array.is_empty() => Ok(Rc::new(Variable::Null)),
                Variable::Array(ref array) => {
                    if array[0].is_string() {
                        Ok(Rc::new(Variable::String(array.iter().fold(
                            array[0].as_string().unwrap().clone(),
                            |acc, item| $operator(acc, item.as_string().unwrap().clone())))))
                    } else {
                        Ok(Rc::new(Variable::F64(array.iter().fold(
                            array[0].as_f64().unwrap(),
                            |acc, item| acc.$operator(item.as_f64().unwrap())))))
                    }
                },
                _ => unreachable!()
            }
        }
    )
}

/// Macro used to implement max_by and min_by functions.
macro_rules! max_by_min_by {
    ($operator:ident, $args:expr, $interpreter:expr) => (
        {
            validate!(stringify!($operator), $args, types![array], types![expref]);
            let vals = $args[0].as_array().expect("Expected array");
            let ast = $args[1].as_expref().expect("Expected expref");
            let initial = try!($interpreter.interpret(vals[0].clone(), ast));
            let entered_type = initial.get_type();
            if entered_type != "string" && entered_type != "number" {
                return Err(format!("{}_by expref expects string|number, found {}",
                                   stringify!($operator), entered_type));
            }
            vals.iter().skip(1).map(|v| $interpreter.interpret(v.clone(), ast))
                .fold(Ok(initial.clone()), |a, b| {
                    let (a_val, b_val) = (try!(a), try!(b));
                    if b_val.get_type() != entered_type {
                        Err(format!("{}_by expref expects {}, found {:?}",
                                    stringify!($operator), entered_type, b_val))
                    } else {
                        Ok($operator(a_val, b_val))
                    }
                })
        }
    )
}

/// Built-in function implementations.
#[derive(Clone)]
pub struct BuiltinFunctions;

impl BuiltinFunctions {
    /// Creates a new Builtins function dispatcher.
    pub fn new() -> BuiltinFunctions {
        BuiltinFunctions
    }
}

impl FnDispatcher for BuiltinFunctions {
    fn call(&self, fn_name: &str, args: &Vec<Rc<Variable>>, intr: &TreeInterpreter)
        -> InterpretResult
    {
        match fn_name {
            "abs" => {
                validate!("abs", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().abs())))
            },
            "avg" => {
                validate!("avg", args, array!(number));
                let array = args[0].as_array().unwrap();
                let sum = array.iter().fold(0f64, |a, ref b| a + b.as_f64().unwrap());
                Ok(Rc::new(Variable::F64(sum / (array.len() as f64))))
            },
            "ceil" => {
                validate!("ceil", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().ceil())))
            },
            "contains" => {
                validate!("contains", args, types![array|string], types![any]);
                match *args[0] {
                    Variable::Array(ref a) => Ok(Rc::new(Variable::Boolean(a.contains(&args[1])))),
                    Variable::String(ref subj) => {
                        match args[1].as_string() {
                            None => Ok(Rc::new(Variable::Boolean(false))),
                            Some(s) => Ok(Rc::new(Variable::Boolean(subj.contains(s))))
                        }
                    },
                    _ => unreachable!()
                }
            },
            "ends_with" => {
                validate!("ends_with", args, types![string], types![string]);
                let subject = args[0].as_string().unwrap();
                let search = args[1].as_string().unwrap();
                Ok(Rc::new(Variable::Boolean(subject.ends_with(search))))
            },
            "floor" => {
                validate!("floor", args, types![number]);
                Ok(Rc::new(Variable::F64(args[0].as_f64().unwrap().floor())))
            },
            "join" => {
                validate!("join", args, types![string], array![string]);
                Ok(Rc::new(Variable::String(args.iter().skip(1)
                    .map(|ref v| v.as_string().unwrap().clone())
                    .collect::<Vec<String>>()
                    .join(args[0].as_string().unwrap()))))
            },
            "keys" => {
                validate!("keys", args, types![object]);
                Ok(Rc::new(args[0].object_keys_to_array().unwrap()))
            },
            "length" => {
                validate!("length", args, types![array|object|string]);
                match *args[0] {
                    Variable::Array(ref a) => Ok(Rc::new(Variable::U64(a.len() as u64))),
                    Variable::Object(ref m) => Ok(Rc::new(Variable::U64(m.len() as u64))),
                    Variable::String(ref s) => Ok(Rc::new(Variable::U64(s.len() as u64))),
                    _ => unreachable!()
                }
            },
            "max" => min_max!(max, args),
            "min" => min_max!(min, args),
            "max_by" => max_by_min_by!(max, args, intr),
            "min_by" => max_by_min_by!(min, args, intr),
            "merge" => {
                validate!("merge", args, types![object] ...types![object]);
                let mut result = args[0].as_object().unwrap().clone();
                for arg in args.iter().skip(1) {
                    result.extend(arg.as_object().unwrap().clone());
                }
                Ok(Rc::new(Variable::Object(result)))
            },
            "not_null" => {
                validate!("not_null", args, types![any] ...types![any]);
                for arg in args {
                    if **arg != Variable::Null {
                        return Ok(arg.clone());
                    }
                }
                Ok(Rc::new(Variable::Null))
            },
            "reverse" => {
                validate!("reverse", args, types![array]);
                let mut values = args.clone();
                values.reverse();
                Ok(Rc::new(Variable::Array(values)))
            },
            "sort" => {
                validate!("sort", args, array![string|number]);
                let mut values: Vec<Rc<Variable>> = args[0].as_array().unwrap().clone();
                if values[0].is_string() {
                    values.sort_by(|a, b| a.as_string().unwrap().cmp(b.as_string().unwrap()));
                } else {
                    values.sort_by(|a, b| a.as_f64().unwrap()
                        .partial_cmp(&b.as_f64().unwrap())
                        .unwrap_or(Ordering::Equal));
                }
                Ok(Rc::new(Variable::Array(values)))
            },
            "sort_by" => sort_by(args, intr),
            "starts_with" => {
                validate!("starts_with", args, types![string], types![string]);
                let subject = args[0].as_string().unwrap();
                let search = args[1].as_string().unwrap();
                Ok(Rc::new(Variable::Boolean(subject.starts_with(search))))
            },
            "sum" => {
                validate!("sum", args, array![number]);
                let array = args[0].as_array().unwrap();
                Ok(Rc::new(Variable::F64(array.iter().fold(
                    array[0].as_f64().unwrap().clone(),
                    |acc, item| acc.max(item.as_f64().unwrap())))))
            },
            "to_array" => {
                try!(arity("to_array", 1, args));
                match *args[0] {
                    Variable::Array(_) => Ok(args[0].clone()),
                    _ => Ok(Rc::new(Variable::Array(vec![args[0].clone()])))
                }
            },
            "to_number" => {
                try!(arity("to_number", 1, args));
                match *args[0] {
                    Variable::I64(_) | Variable::F64(_) | Variable::U64(_) => Ok(args[0].clone()),
                    Variable::String(ref s) => {
                        match s.parse::<f64>() {
                            Ok(f)  => Ok(Rc::new(Variable::F64(f))),
                            Err(_) => Ok(Rc::new(Variable::Null))
                        }
                    },
                    _ => Ok(Rc::new(Variable::Null))
                }
            },
            "to_string" => {
                validate!("to_string", args, types![object|array|boolean|number|string|null]);
                Ok(Rc::new(Variable::String(args[0].to_string().unwrap())))
            },
            "type" => {
                try!(arity("type", 1, args));
                Ok(Rc::new(Variable::String(args[0].get_type().to_string())))
            },
            "values" => {
                validate!("values", args, types![object]);
                Ok(Rc::new(args[0].object_values_to_array().unwrap()))
            },
            _ => Err(format!("Unknown function: {}", fn_name))
        }
    }
}

enum SortByState {
    Initial,
    FoundString,
    FoundNumber,
    Error(String)
}

fn sort_by(args: &Vec<Rc<Variable>>, intr: &TreeInterpreter) -> InterpretResult {
    validate!("sort_by", args, types![array], types![expref]);
    let mut state = SortByState::Initial;
    let mut vals = args[0].as_array().expect("Expected array").clone();
    let ast = args[1].as_expref().expect("Expected expref");

    vals.sort_by(|ref lhs, ref rhs| {
        if let SortByState::Error(_) = state {
            return Ordering::Equal;
        }
        let a = match intr.interpret((*lhs).clone(), ast) {
            Ok(result) => result,
            Err(e) => {
                state = SortByState::Error(e);
                return Ordering::Equal
            }
        };
        let b = match intr.interpret((*rhs).clone(), ast) {
            Ok(result) => result,
            Err(e) => {
                state = SortByState::Error(e);
                return Ordering::Equal
            }
        };
        let a_type = a.get_type();
        let b_type = b.get_type();
        match state {
            SortByState::Initial if a_type == "string" && b_type == a_type => {
                state = SortByState::FoundString;
                a.as_string().unwrap().cmp(b.as_string().unwrap())
            },
            SortByState::Initial if a_type == "number" && b_type == a_type => {
                state = SortByState::FoundNumber;
                a.as_f64().unwrap().partial_cmp(&b.as_f64().unwrap()).unwrap()
            },
            SortByState::FoundString if a_type == "string" && b_type == "string" =>
                a.as_string().unwrap().cmp(b.as_string().unwrap()),
            SortByState::FoundNumber if a_type == "number" && b_type == "number" =>
                a.as_f64().unwrap().partial_cmp(&b.as_f64().unwrap()).unwrap(),
            _ => {
                state = SortByState::Error("sort_by expref is expected to return all strings \
                                           or all numbers".to_string());
                Ordering::Equal
            }
        }
    });

    match state {
        SortByState::Initial => Ok(Rc::new(Variable::Array(vec![]))),
        SortByState::Error(e) => Err(e),
        _ => Ok(Rc::new(Variable::Array(vals)))
    }
}
<|endoftext|>


<commit_before>fn main() {
    // testing(5, vec![(3, 1)]);
    // testing(20, vec![(6, 2)]);
    // testing(9001, vec![(4501, 2250)]);
    // testing(9004, vec![(2252, 1125)]);
    // testing(9005, vec![(4503, 2251), (903, 449)]);
    // testing(90005, vec![(45003, 22501), (9003, 4499), (981, 467), (309, 37)]);
    // testing(90002, vec![]);

    println!(" {} -- {:?}", 9000, solequa(9000));
    println!(" {} -- {:?}", 9001, solequa(9001));
    println!(" {} -- {:?}", 9002, solequa(9002));
    println!(" {} -- {:?}", 9003, solequa(9003));
    println!(" {} -- {:?}", 9004, solequa(9004));
    println!(" {} -- {:?}", 9005, solequa(9005));
    println!(" {} -- {:?}", 9006, solequa(9006));
    println!(" {} -- {:?}", 9007, solequa(9007));
    println!(" {} -- {:?}", 9008, solequa(9008));
    println!(" {} -- {:?}", 9009, solequa(9009));

}

fn solequa(n: u64) -> Vec<(u64, u64)> {
    let mut ret = Vec::new();
    let mut x: u64;
    let mut y: u64;

    x = (n as f64).sqrt() as u64;

    let xlimit = n / 2 + 1;

    if n % 2 == 0 {
        if x % 2 != 0 {
            x += 1;
        }
    } else {
        if x % 2 == 0 {
            x += 1;
        }
    }

    while x <= xlimit {
        let fx = x as f64;

        y = (( fx * fx - n as f64 ).sqrt() as f64 / 2.0) as u64;

        let res = (fx - 2.0 * y as f64) * (fx + 2.0 * y as f64);

        if res as u64 == n {
            ret.insert(0, (x, y));
        }

        x += 2;
    }

    ret
}

fn testing(n: u64, exp: Vec<(u64, u64)>) -> () {
    assert_eq!(solequa(n), exp)
}

#[test]
fn basics_solequa() {
    testing(20, vec![(6, 2)]);
    testing(900000, vec![(112502, 56249), (56254, 28123), (37506, 18747), (22510, 11245), (18762, 9369),
    (12518, 6241), (11270, 5615), (7530, 3735), (6286, 3107), (4550, 2225), (3810, 1845), (2590, 1205),
    (2350, 1075), (1650, 675), (1430, 535), (1150, 325), (1050, 225), (950, 25)]);

    testing(9001, vec![(4501, 2250)]);
    testing(9000001, vec![(4500001, 2250000), (73801, 36870)]);
    testing(90000001, vec![(45000001, 22500000), (6428575, 3214284), (3461545, 1730766), (494551, 247230)]);

    testing(90002, vec![]);

    testing(9004, vec![(2252, 1125)]);
    testing(9000004, vec![(2250002, 1125000), (173090, 86532), (132370, 66168), (10402, 4980)]);
    testing(90000004, vec![(22500002, 11250000), (252898, 126360), (93602, 46560), (22498, 10200)]);

    testing(9005, vec![(4503, 2251), (903, 449)]);
    testing(90005, vec![(45003, 22501), (9003, 4499), (981, 467), (309, 37)]);
    testing(5, vec![(3, 1)]);
    testing(9000005, vec![(4500003, 2250001), (900003, 449999), (642861, 321427), (155187, 77579),
    (128589, 64277), (31107, 15481), (22269, 11033), (4941, 1963)]);

    testing(9009, vec![(4505, 2252), (1503, 750), (647, 320), (505, 248), (415, 202), (353, 170), (225, 102),
    (153, 60), (135, 48), (103, 20), (97, 10), (95, 2)]);

    testing(900000009, vec![(450000005, 225000002), (150000003, 75000000), (50000005, 24999998), (26470597, 13235290), (8823555, 4411752), (2941253, 1470550)]);
}

<commit_msg>hacking at sqrt<commit_after>fn main() {
    // testing(5, vec![(3, 1)]);
    // testing(20, vec![(6, 2)]);
    // testing(9001, vec![(4501, 2250)]);
    // testing(9004, vec![(2252, 1125)]);
    // testing(9005, vec![(4503, 2251), (903, 449)]);
    // testing(90005, vec![(45003, 22501), (9003, 4499), (981, 467), (309, 37)]);
    // testing(90002, vec![]);

    println!(" {} -- {:?}", 9000, solequa(9000));
    println!(" {} -- {:?}", 9001, solequa(9001));
    println!(" {} -- {:?}", 9002, solequa(9002));
    println!(" {} -- {:?}", 9003, solequa(9003));
    println!(" {} -- {:?}", 9004, solequa(9004));
    println!(" {} -- {:?}", 9005, solequa(9005));
    println!(" {} -- {:?}", 9006, solequa(9006));
    println!(" {} -- {:?}", 9007, solequa(9007));
    println!(" {} -- {:?}", 9008, solequa(9008));
    println!(" {} -- {:?}", 9009, solequa(9009));

}

fn q_sqrt( n:f64 ) -> u64 {
	let mut i: u64;
	let mut x2: f64;
    let mut y: f64;
	let threehalfs: f64 = 1.5;

	x2 = n * 0.5;
	y  = n;
	i  = y as u64;                       // evil floating point bit level hacking
	i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
	y  = i as f64;
	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

	y as u64
}

fn solequa(n: u64) -> Vec<(u64, u64)> {
    let mut ret = Vec::new();
    let mut x: u64;
    let mut y: u64;

    x = (n as f64).sqrt() as u64;

    println!("?{} -- x{}", 1/q_sqrt(n as f64), x);
    let xlimit = n / 2 + 1;

    if n % 2 == 0 {
        if x % 2 != 0 {
            x += 1;
        }
    } else {
        if x % 2 == 0 {
            x += 1;
        }
    }

    while x <= xlimit {
        let fx = x as f64;

        y = (( fx * fx - n as f64 ).sqrt() as f64 / 2.0) as u64;

        let res = (fx - 2.0 * y as f64) * (fx + 2.0 * y as f64);

        if res as u64 == n {
            ret.insert(0, (x, y));
        }

        x += 2;
    }

    ret
}

fn testing(n: u64, exp: Vec<(u64, u64)>) -> () {
    assert_eq!(solequa(n), exp)
}

#[test]
fn basics_solequa() {
    testing(20, vec![(6, 2)]);
    testing(900000, vec![(112502, 56249), (56254, 28123), (37506, 18747), (22510, 11245), (18762, 9369),
    (12518, 6241), (11270, 5615), (7530, 3735), (6286, 3107), (4550, 2225), (3810, 1845), (2590, 1205),
    (2350, 1075), (1650, 675), (1430, 535), (1150, 325), (1050, 225), (950, 25)]);

    testing(9001, vec![(4501, 2250)]);
    testing(9000001, vec![(4500001, 2250000), (73801, 36870)]);
    testing(90000001, vec![(45000001, 22500000), (6428575, 3214284), (3461545, 1730766), (494551, 247230)]);

    testing(90002, vec![]);

    testing(9004, vec![(2252, 1125)]);
    testing(9000004, vec![(2250002, 1125000), (173090, 86532), (132370, 66168), (10402, 4980)]);
    testing(90000004, vec![(22500002, 11250000), (252898, 126360), (93602, 46560), (22498, 10200)]);

    testing(9005, vec![(4503, 2251), (903, 449)]);
    testing(90005, vec![(45003, 22501), (9003, 4499), (981, 467), (309, 37)]);
    testing(5, vec![(3, 1)]);
    testing(9000005, vec![(4500003, 2250001), (900003, 449999), (642861, 321427), (155187, 77579),
    (128589, 64277), (31107, 15481), (22269, 11033), (4941, 1963)]);

    testing(9009, vec![(4505, 2252), (1503, 750), (647, 320), (505, 248), (415, 202), (353, 170), (225, 102),
    (153, 60), (135, 48), (103, 20), (97, 10), (95, 2)]);

    testing(900000009, vec![(450000005, 225000002), (150000003, 75000000), (50000005, 24999998), (26470597, 13235290), (8823555, 4411752), (2941253, 1470550)]);
}

<|endoftext|>