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

#![feature(core)]
#![feature(net)]

extern crate rand;
extern crate rusqlite;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

use rand::Rng;
use std::net::{SocketAddr, UdpSocket};
use std::thread::Thread;

use rusqlite::SqliteConnection;

use parse_packets::{parse_header, encode_connect_response, decode_client_announce};

mod parse_packets;

fn gen_uuid() -> u64 {
    let mut rng = rand::thread_rng();
    let mut uuid = time::precise_time_ns();
    uuid <<= 32;
    uuid | (rng.gen::<u32>() as u64)
}

fn init_db(path: &'static str) -> SqliteConnection {
    let conn = SqliteConnection::open(path).unwrap();
    conn.execute_batch(
        "BEGIN;
        CREATE TABLE IF NOT EXISTS users (
            uuid          INTEGER PRIMARY KEY,
            last_active   INTEGER
        );
        CREATE TABLE IF NOT EXISTS torrent (
            info_hash   TEXT,
            uuid        INTEGER,
            downloaded  INTEGER,
            uploaded    INTEGER,
            remaining   INTEGER,
            PRIMARY KEY (info_hash, uuid)
            FOREIGN KEY(uuid) REFERENCES users(uuid)
        );
        COMMIT;"
    ).unwrap();
    conn
}

fn add_new_connection(conn: &SqliteConnection) -> u64 {
    // Cool Story, we got a new connection.
    // We need to generate an unique id for this client.
    // 32bits of the current time in nanoseconds combined with 32bits of
    // random numbers
    let uuid = gen_uuid() as i64;
    conn.execute(
        "INSERT INTO users (uuid, last_active) VALUES ($1, strftime('%s', 'now'))",
        &[&uuid]
    ).unwrap();
    uuid as u64
}

fn handle_packet(tsock: UdpSocket, src: &SocketAddr, packet: Vec<u8>, conn: &SqliteConnection) {
    // Split the packet into header and body parts
    let mut packet_header = packet;
    let packet_body = packet_header.split_off(16);

    // parse the header to act on it
    let header = parse_header(&packet_header);

    println!("Connection ID: 0x{:x}", header.connection_id);
    match header.action {
        0 => {
            if header.connection_id == 0x41727101980 {
                let uuid = add_new_connection(conn);
                // Now they're in the db, let's say hi
                let encoded = encode_connect_response(uuid, header.transaction_id);
                tsock.send_to(&encoded, src).unwrap();
            } else {
                ()
            }
        },
        1 => {
            let decoded = decode_client_announce(&packet_body);
        },
        _ => {
            ()
        },
    }
}

fn main() {
    let database_path = "file::memory:?cache=shared";

    // Let's first initialize the database.
    let _ = init_db(database_path);
    let sock = UdpSocket::bind("127.0.0.1:6969").unwrap();

    loop {
        let mut buf = [0u8; 2048];
        let (amt, src) = sock.recv_from(&mut buf).unwrap();
        let tsock = sock.try_clone().unwrap();
        let mut b: Vec<u8> = buf.to_vec();
        b.truncate(amt);
        Thread::spawn(move|| {
            let conn = SqliteConnection::open(database_path).unwrap();
            handle_packet(tsock, &src, b, &conn);
            let _ = conn.close();
        });
    }
}
<commit_msg>sqelch warns, listen to everything<commit_after>// Copyright 2015 Justin Noah, All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(collections)]
#![feature(core)]
#![feature(net)]
#![feature(std_misc)]

extern crate rand;
extern crate rusqlite;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

use rand::Rng;
use std::net::{SocketAddr, UdpSocket};
use std::thread::Thread;

use rusqlite::SqliteConnection;

use parse_packets::{parse_header, encode_connect_response, decode_client_announce};

mod parse_packets;

fn gen_uuid() -> u64 {
    let mut rng = rand::thread_rng();
    let mut uuid = time::precise_time_ns();
    uuid <<= 32;
    uuid | (rng.gen::<u32>() as u64)
}

fn init_db(path: &'static str) -> SqliteConnection {
    let conn = SqliteConnection::open(path).unwrap();
    conn.execute_batch(
        "BEGIN;
        CREATE TABLE IF NOT EXISTS users (
            uuid          INTEGER PRIMARY KEY,
            last_active   INTEGER
        );
        CREATE TABLE IF NOT EXISTS torrent (
            info_hash   TEXT,
            uuid        INTEGER,
            downloaded  INTEGER,
            uploaded    INTEGER,
            remaining   INTEGER,
            PRIMARY KEY (info_hash, uuid)
            FOREIGN KEY(uuid) REFERENCES users(uuid)
        );
        COMMIT;"
    ).unwrap();
    conn
}

fn add_new_connection(conn: &SqliteConnection) -> u64 {
    // Cool Story, we got a new connection.
    // We need to generate an unique id for this client.
    // 32bits of the current time in nanoseconds combined with 32bits of
    // random numbers
    let uuid = gen_uuid() as i64;
    conn.execute(
        "INSERT INTO users (uuid, last_active) VALUES ($1, strftime('%s', 'now'))",
        &[&uuid]
    ).unwrap();
    uuid as u64
}

fn handle_packet(tsock: UdpSocket, src: &SocketAddr, packet: Vec<u8>, conn: &SqliteConnection) {
    // Split the packet into header and body parts
    let mut packet_header = packet;
    let packet_body = packet_header.split_off(16);

    // parse the header to act on it
    let header = parse_header(&packet_header);

    println!("Connection ID: 0x{:x}", header.connection_id);
    match header.action {
        0 => {
            if header.connection_id == 0x41727101980 {
                let uuid = add_new_connection(conn);
                // Now they're in the db, let's say hi
                let encoded = encode_connect_response(uuid, header.transaction_id);
                tsock.send_to(&encoded, src).unwrap();
            } else {
                ()
            }
        },
        1 => {
            let decoded = decode_client_announce(&packet_body);
        },
        _ => {
            ()
        },
    }
}

fn main() {
    let database_path = "file::memory:?cache=shared";

    // Let's first initialize the database.
    let _ = init_db(database_path);
    let sock = UdpSocket::bind("0.0.0.0:6969").unwrap();

    loop {
        let mut buf = [0u8; 2048];
        let (amt, src) = sock.recv_from(&mut buf).unwrap();
        let tsock = sock.try_clone().unwrap();
        let mut b: Vec<u8> = buf.to_vec();
        b.truncate(amt);
        Thread::spawn(move|| {
            let conn = SqliteConnection::open(database_path).unwrap();
            handle_packet(tsock, &src, b, &conn);
            let _ = conn.close();
        });
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Write;

#[derive(Copy, Clone, Debug)]
struct Tile
{
    population : f64,
    fertility : f64,
    gold : f64,
}

#[derive(Debug)]
struct Producer
{
    name : String,
    population : f64,
    gold: f64,

    happiness : f64,

    products : [f64; 2], // 0 food, 1 goods
    product_usage: [f64; 2],

    production : Production,
}

#[derive(Debug)]
enum Production {
    None,
    Relative {product : usize, ratio : f64},
    Dimmishing {product : usize, multiple : f64, dimminish : f64}
}

impl Production {
    fn produce(&self, population: f64) -> (usize, f64) {
        match self {
            &Production::None => (0, 0.0),
            &Production::Relative { product, ratio } => (product, population * ratio),
            &Production::Dimmishing { product, multiple, dimminish } => (product, ((population+1.0).powf(1.0-dimminish) - 1.0)/(1.0-dimminish) * multiple),
        }
    }
}

// calculates diminishing return coeficient so that 0 population produces zero and at_one population produces 1
fn calc_diminish(product: usize, zero:f64, at_one:f64) -> Production {
    let mult = zero;
    let dimm = zero.log10()/(at_one + 1.0).log10();

    Production::Dimmishing {product:product, multiple:mult, dimminish : dimm }
}

fn main() {

    println!("TYPE;ID;A;B;C;D;E;F;G");

    let mut producers : Vec<Producer> = vec!();

    producers.push(Producer {name:"owners".to_string(),     population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: Production::None, product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"food high".to_string(),  population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(0, 2.0, 30.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"food low".to_string(),   population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(0, 1.5, 60.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"goods high".to_string(), population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(1, 3.0, 10.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"goods low".to_string(),  population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(1, 1.1, 20.0), product_usage: [1.0, 1.0], happiness: 0.0});

    let producer_count = producers.len();

    let mut prices : [f64; 2] = [1_f64, 1_f64];

    let mut prices_output : File = File::create("prices.csv").unwrap();
    writeln!(&mut prices_output, "Step;Price 1;Price 2").unwrap();

    let mut population_output : File = File::create("population.csv").unwrap();
    {
        let producers_names = producers.iter().map(|prod| prod.name.to_string()).collect::<Vec<_>>().join(";");
        writeln!(&mut population_output, "Step;{0}", producers_names).unwrap();
    }

    for step_id in 0..500
    {
        let mut total_product = [0_f64, 0_f64];
        let mut total_gold = 0_f64;

        // produce goods
        for x in 0..producer_count {
            let mut producer = &mut producers[x];

            let (item, amount) = producer.production.produce(producer.population);
            producer.products[item] += amount;
        }

        for _ in 0..4 {
            // calculate totals for trading
            for x in 0..producer_count {
                let producer = &producers[x];

                total_product[0] += producer.products[0];
                total_product[1] += producer.products[1];
                total_gold += producer.gold;
            }

            // trade between producers
            for product_id in 0..2 {

                let average_gold = total_gold / producer_count as f64;
                let needed_resources = total_product[product_id] / producer_count as f64;

                let (_, sellers_buyers) : (_, Vec<&mut Producer>) = producers.iter_mut().partition(|prod| prod.products[product_id] > needed_resources && prod.gold > average_gold);
                let (mut buyers, mut sellers) : (Vec<&mut Producer>, Vec<&mut Producer>) = sellers_buyers.into_iter().partition(|prod| prod.products[product_id] < needed_resources);

                if sellers.len() <= 0 || buyers.len() <= 0 {
                    continue;
                }

                let mut wanted_resources = 0_f64;
                let mut offered_gold = 0_f64;

                for buyer in &buyers {
                    wanted_resources += needed_resources - buyer.products[product_id];
                    offered_gold += buyer.gold;
                }

                let mut wanted_gold = 0_f64;
                let mut offered_resource = 0_f64;
                for seller in &sellers {
                    wanted_gold += average_gold - seller.gold;
                    offered_resource += seller.products[product_id] - needed_resources;
                }

                if offered_resource <= 0.1 { // if there is nothing to sell, no trading
                    continue;
                }

                let price = offered_gold / offered_resource;
                prices[product_id] = price;

                let mut total_bough = 0_f64;

                for buyer in &mut buyers {
                    let can_buy = buyer.gold / price;
                    let want = needed_resources - buyer.products[product_id];
                    let buys = can_buy.min(want);
                    buyer.products[product_id] += buys;
                    buyer.gold -= buys * price;
                    total_bough += buys;
                }

                let sold_ratio = total_bough / offered_resource;

                if sold_ratio > 1.0 {
                    println!("ERROR; sold more than is available");
                }

                for seller in &mut sellers {
                    let offered = seller.products[product_id] - needed_resources;
                    let seller_sold = offered * sold_ratio;

                    seller.products[product_id] -= seller_sold;
                    seller.gold += seller_sold * price;
                }

                println!("TRADING;{0:.10};{1:.10};{2:.10};{3:.10};{4:.10};{5:.10};{6:.10}", product_id, price, wanted_resources, offered_gold, offered_resource, wanted_gold, total_bough);
            }
        }
        println!("PRICES;0;{0:.10};{1:.10};", prices[0], prices[1]);

        // consume goods
        for x in 0..producer_count {
            let mut producer = &mut producers[x];

            println!("PRODUCERS_CONSUME_BEFORE;{3};{0:.3};{1:.3};{2:.3};{4:.3};{5:.3}", producer.population, producer.products[0], producer.products[1], x, producer.gold, producer.happiness);

            let needed_food = producer.population * producer.product_usage[0];
            let eaten_food = producer.products[0].min(needed_food);
            producer.products[0] -= eaten_food;

            let needed_goods = producer.population * producer.product_usage[1];
            let used_goods = producer.products[1].min(needed_goods);
            producer.products[1] -= used_goods;

            let food_ratio = eaten_food / needed_food;
            let goods_ratio = used_goods / needed_goods;

            producer.happiness = food_ratio + food_ratio * goods_ratio * 0.5;

            if x == 0 {
                producer.happiness *= 1.01;
            }

            println!("PRODUCERS_CONSUME_AFTER;{3};{0:.3};{1:.3};{2:.3};{4:.3};{5:.3};{6:.3};{7:.3}", producer.population, producer.products[0], producer.products[1], x, producer.gold, producer.happiness, eaten_food, used_goods);
        }

        // move people between producers
        {
            let mut producers_vec: Vec<&mut Producer> = producers.iter_mut().collect::<Vec<_>>();

            producers_vec.sort_by(|a, b| a.happiness.partial_cmp(&b.happiness).unwrap());

            for from in 0 .. producers_vec.len() {
                for to in from+1 .. producers_vec.len(){

                    let move_people = producers_vec[to].happiness - producers_vec[from].happiness;
                    let move_people = move_people * 0.1;
                    let target_population = 0.1_f64.max(producers_vec[from].population - move_people);
                    let move_people = producers_vec[from].population - target_population;

                    producers_vec[from].population -= move_people;
                    producers_vec[to].population += move_people;

                    println!("POPULATION_MOVE;{0:.3};{1:.3};{2:.3};{3:.3};{4:.3};{5:.3}", from, to, producers_vec[from].population, producers_vec[to].population, target_population, move_people);
                }
            }
        }

        // taxes (duh!)
        {
            let tax_rate = 0.2;

            let mut total_tax = 0.0;
            for x in 1..producer_count {
                let tax = producers[x].gold * tax_rate;
                producers[x].gold -= tax;
                total_tax += tax;
            }

            producers[0].gold += total_tax;
        }

        // sanity checks
        {
            for prod in &producers{
                for x in 0..2 {
                    if prod.products[x] < -0.0000001 {
                        println!("ERROR; product {0} is negative", x)
                    }
                }
                if prod.gold < -0.0000001 {
                    println!("ERROR; gold is negative:{0:.10}", prod.gold)
                }
            }
        }

        {
            let producers_population = producers.iter().map(|prod| prod.population.to_string()).collect::<Vec<_>>().join(";");
            writeln!(&mut population_output, "{0};{1}", step_id, producers_population).unwrap();
            writeln!(&mut prices_output, "{0};{1:.3};{2:.3}", step_id, prices[0], prices[1]).unwrap();
        }
    }
}
<commit_msg>Removed writing of simulation values into to standard output<commit_after>use std::fs::File;
use std::io::Write;

#[derive(Copy, Clone, Debug)]
struct Tile
{
    population : f64,
    fertility : f64,
    gold : f64,
}

#[derive(Debug)]
struct Producer
{
    name : String,
    population : f64,
    gold: f64,

    happiness : f64,

    products : [f64; 2], // 0 food, 1 goods
    product_usage: [f64; 2],

    production : Production,
}

#[derive(Debug)]
enum Production {
    None,
    Relative {product : usize, ratio : f64},
    Dimmishing {product : usize, multiple : f64, dimminish : f64}
}

impl Production {
    fn produce(&self, population: f64) -> (usize, f64) {
        match self {
            &Production::None => (0, 0.0),
            &Production::Relative { product, ratio } => (product, population * ratio),
            &Production::Dimmishing { product, multiple, dimminish } => (product, ((population+1.0).powf(1.0-dimminish) - 1.0)/(1.0-dimminish) * multiple),
        }
    }
}

// calculates diminishing return coeficient so that 0 population produces zero and at_one population produces 1
fn calc_diminish(product: usize, zero:f64, at_one:f64) -> Production {
    let mult = zero;
    let dimm = zero.log10()/(at_one + 1.0).log10();

    Production::Dimmishing {product:product, multiple:mult, dimminish : dimm }
}

fn main() {

    let mut producers : Vec<Producer> = vec!();

    producers.push(Producer {name:"owners".to_string(),     population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: Production::None, product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"food high".to_string(),  population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(0, 2.0, 30.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"food low".to_string(),   population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(0, 1.5, 60.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"goods high".to_string(), population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(1, 3.0, 10.0), product_usage: [1.0, 1.0], happiness: 0.0});
    producers.push(Producer {name:"goods low".to_string(),  population : 20_f64, gold: 1000_f64, products: [0_f64, 0_f64], production: calc_diminish(1, 1.1, 20.0), product_usage: [1.0, 1.0], happiness: 0.0});

    let producer_count = producers.len();

    let mut prices : [f64; 2] = [1_f64, 1_f64];

    let mut prices_output : File = File::create("prices.csv").unwrap();
    writeln!(&mut prices_output, "Step;Price 1;Price 2").unwrap();

    let mut population_output : File = File::create("population.csv").unwrap();
    {
        let producers_names = producers.iter().map(|prod| prod.name.to_string()).collect::<Vec<_>>().join(";");
        writeln!(&mut population_output, "Step;{0}", producers_names).unwrap();
    }

    for step_id in 0..500
    {
        let mut total_product = [0_f64, 0_f64];
        let mut total_gold = 0_f64;

        // produce goods
        for x in 0..producer_count {
            let mut producer = &mut producers[x];

            let (item, amount) = producer.production.produce(producer.population);
            producer.products[item] += amount;
        }

        for _ in 0..4 {
            // calculate totals for trading
            for x in 0..producer_count {
                let producer = &producers[x];

                total_product[0] += producer.products[0];
                total_product[1] += producer.products[1];
                total_gold += producer.gold;
            }

            // trade between producers
            for product_id in 0..2 {

                let average_gold = total_gold / producer_count as f64;
                let needed_resources = total_product[product_id] / producer_count as f64;

                let (_, sellers_buyers) : (_, Vec<&mut Producer>) = producers.iter_mut().partition(|prod| prod.products[product_id] > needed_resources && prod.gold > average_gold);
                let (mut buyers, mut sellers) : (Vec<&mut Producer>, Vec<&mut Producer>) = sellers_buyers.into_iter().partition(|prod| prod.products[product_id] < needed_resources);

                if sellers.len() <= 0 || buyers.len() <= 0 {
                    continue;
                }

                let mut wanted_resources = 0_f64;
                let mut offered_gold = 0_f64;

                for buyer in &buyers {
                    wanted_resources += needed_resources - buyer.products[product_id];
                    offered_gold += buyer.gold;
                }

                let mut wanted_gold = 0_f64;
                let mut offered_resource = 0_f64;
                for seller in &sellers {
                    wanted_gold += average_gold - seller.gold;
                    offered_resource += seller.products[product_id] - needed_resources;
                }

                if offered_resource <= 0.1 { // if there is nothing to sell, no trading
                    continue;
                }

                let price = offered_gold / offered_resource;
                prices[product_id] = price;

                let mut total_bough = 0_f64;

                for buyer in &mut buyers {
                    let can_buy = buyer.gold / price;
                    let want = needed_resources - buyer.products[product_id];
                    let buys = can_buy.min(want);
                    buyer.products[product_id] += buys;
                    buyer.gold -= buys * price;
                    total_bough += buys;
                }

                let sold_ratio = total_bough / offered_resource;

                if sold_ratio > 1.0 {
                    println!("ERROR; sold more than is available");
                }

                for seller in &mut sellers {
                    let offered = seller.products[product_id] - needed_resources;
                    let seller_sold = offered * sold_ratio;

                    seller.products[product_id] -= seller_sold;
                    seller.gold += seller_sold * price;
                }
            }
        }

        // consume goods
        for x in 0..producer_count {
            let mut producer = &mut producers[x];

            let needed_food = producer.population * producer.product_usage[0];
            let eaten_food = producer.products[0].min(needed_food);
            producer.products[0] -= eaten_food;

            let needed_goods = producer.population * producer.product_usage[1];
            let used_goods = producer.products[1].min(needed_goods);
            producer.products[1] -= used_goods;

            let food_ratio = eaten_food / needed_food;
            let goods_ratio = used_goods / needed_goods;

            producer.happiness = food_ratio + food_ratio * goods_ratio * 0.5;

            if x == 0 {
                producer.happiness *= 1.01;
            }
        }

        // move people between producers
        {
            let mut producers_vec: Vec<&mut Producer> = producers.iter_mut().collect::<Vec<_>>();

            producers_vec.sort_by(|a, b| a.happiness.partial_cmp(&b.happiness).unwrap());

            for from in 0 .. producers_vec.len() {
                for to in from+1 .. producers_vec.len(){

                    let move_people = producers_vec[to].happiness - producers_vec[from].happiness;
                    let move_people = move_people * 0.1;
                    let target_population = 0.1_f64.max(producers_vec[from].population - move_people);
                    let move_people = producers_vec[from].population - target_population;

                    producers_vec[from].population -= move_people;
                    producers_vec[to].population += move_people;
                }
            }
        }

        // taxes (duh!)
        {
            let tax_rate = 0.2;

            let mut total_tax = 0.0;
            for x in 1..producer_count {
                let tax = producers[x].gold * tax_rate;
                producers[x].gold -= tax;
                total_tax += tax;
            }

            producers[0].gold += total_tax;
        }

        // sanity checks
        {
            for prod in &producers{
                for x in 0..2 {
                    if prod.products[x] < -0.0000001 {
                        println!("ERROR; product {0} is negative", x)
                    }
                }
                if prod.gold < -0.0000001 {
                    println!("ERROR; gold is negative:{0:.10}", prod.gold)
                }
            }
        }

        {
            let producers_population = producers.iter().map(|prod| prod.population.to_string()).collect::<Vec<_>>().join(";");
            writeln!(&mut population_output, "{0};{1}", step_id, producers_population).unwrap();
            writeln!(&mut prices_output, "{0};{1:.3};{2:.3}", step_id, prices[0], prices[1]).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>//! **Wa** ve **f** unction Solv **er**: a parallelized, 3D, Schrödinger equation solver.
//!
//! Wafer exploits a Wick-rotated time-dependent Schrödinger equation to solve for
//! time-independent solutions in three dimensions.
//!
//! Inspired by [quantumfdtd](http://sourceforge.net/projects/quantumfdtd/),
//! which is a proof of concept tool and falls short of a general purpose utility.
//! Wafer attempts to remedy this issue.
//!
//! If you use Wafer in your research, please reference the following articles:
//!
//! M. Strickland and D. Yager-Elorriaga, “A parallel algorithm for solving the 3d
//! Schrödinger equation”,
//! [Journal of Computational Physics __229__, 6015–6026 (2010)](http://dx.doi.org/10.1016/j.jcp.2010.04.032).

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(missing_docs_in_private_items))]
#![cfg_attr(feature="clippy", warn(single_match_else))]

extern crate ansi_term;
extern crate chrono;
#[macro_use]
extern crate clap;
extern crate csv;
extern crate indicatif;
#[macro_use]
extern crate lazy_static;
#[macro_use(s)]
extern crate ndarray;
extern crate ndarray_parallel;
extern crate num;
extern crate num_cpus;
extern crate ordinal;
extern crate rand;
extern crate rayon;
extern crate rmp_serde as rmps;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate slog;
extern crate slog_async;
extern crate slog_term;
extern crate term_size;

use clap::{App, Arg};
use slog::{Drain, Duplicate, Logger, Fuse, LevelFilter, Level};
use std::fs::OpenOptions;
use std::process;
use std::time::Instant;
use config::Config;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

/// Config is a (mostly) public module which reads the configuration file `wafer.cfg`
/// and poplulates the `Config` struct with the information required to run the current
/// instance of the application.
pub mod config;
/// The meat of the caclulation is performed on a finite grid. Basically all of the computation
/// work is done within this module.
mod grid;
/// Any required file input (apart from configuration) is handled here. Plain text and binary formats.
mod input;
/// All file output is handled in this module. Plain text and binary options are both here.
mod output;
/// Handles the potential generation, binding energy offsets, callouts to files or scripts
/// if needed etc.
mod potential;

/// System entry point
fn main() {
    //Simulation timer.
    let start_time = Instant::now();

    //CLI options. For the moment, a custom configuration file and custom debug levels.
    let matches = App::new("Wafer")
                        .version(crate_version!())
                        .author(crate_authors!())
                        .about("Exploits a Wick-rotated time-dependent Schrödinger equation to solve for time-independent solutions in three dimensions.")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("The configuration file to use (default is \"wafer.cfg\")")
                                    .takes_value(true))
                        .arg(Arg::with_name("debug")
                                    .short("d")
                                    .multiple(true)
                                    .help("Raises screen debug level"))
                        .get_matches();

    //Load configuation parameters.
    let config_file = matches.value_of("config").unwrap_or("wafer.cfg");
    let config = match Config::load(config_file) {
        Ok(c) => c,
        Err(err) => {
            println!("Error processing configuration: {}", err);
            process::exit(1);
        }
    };
    if let Err(err) = output::check_output_dir(&config.project_name) {
        println!("Could not communicate with output directory: {}", err);
        process::exit(1);
    };

    //Setup logging.
    let log_file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(output::get_project_dir(&config.project_name) + "/simulation.log")
        .expect("Cannot connect to log file");
    let syslog = slog_term::PlainDecorator::new(log_file);
    let sys_drain = slog_term::FullFormat::new(syslog).build().fuse();
    let sys_drain = slog_async::Async::new(sys_drain).build().fuse();
    let screen = slog_term::TermDecorator::new().build();
    let screen_drain = slog_term::FullFormat::new(screen).build().fuse();
    let screen_drain = slog_async::Async::new(screen_drain).build().fuse();

    let screen_level = match matches.occurrences_of("debug") {
        0 => Level::Warning,
        1 => Level::Info,
        2 | _ => Level::Debug,
    };
    let log = Logger::root(Fuse::new(Duplicate::new(LevelFilter::new(screen_drain, screen_level), sys_drain)),
                           o!());

    info!(log, "Starting Wafer solver"; "version" => crate_version!(), "build-id" => short_sha());

    info!(log, "Checking/creating directories");
    if let Err(err) = input::check_input_dir() {
        crit!(log, "Could not communicate with input directory: {}", err);
        process::exit(1);
    };

    //Override rayon's defaults of threads (including HT cores) to physical cores
    if let Err(err) = rayon::initialize(rayon::Configuration::new()
                                            .num_threads(num_cpus::get_physical())) {
        crit!(log, "Failed to initialise thread pool: {}", err);
        process::exit(1);
    };

    let term_width = *output::TERMWIDTH;

    let sha = if term_width <= 97 { short_sha() } else { sha() };

    output::print_banner(sha);

    info!(log, "Loading Configuation from disk");
    config.print(term_width);
    if let Err(err) = output::copy_config(&config.project_name) {
        //TODO: Input from CLI if non-default config file
        warn!(log,
              "Configuration file not copied to output directory: {}",
              err);
    };

    if let Err(err) = grid::run(&config, &log) {
        crit!(log, "{}", err);
        process::exit(1);
    };

    let elapsed = start_time.elapsed();
    let time_taken = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
    match time_taken {
        0.0...60.0 => {
            println!("Simulation complete. Elapsed time: {:.3} seconds.",
                     time_taken)
        }
        60.0...3600.0 => {
            let minutes = (time_taken / 60.).floor();
            let seconds = time_taken - 60. * minutes;
            println!("Simulation complete. Elapsed time: {} minutes, {:.3} seconds.",
                     minutes,
                     seconds);
        }
        _ => {
            let hours = (time_taken / 3600.).floor();
            let minutes = ((time_taken - 3600. * hours) / 60.).floor();
            let seconds = time_taken - 3600. * hours - 60. * minutes;
            println!("Simulation complete. Elapsed time: {} hours, {} minutes, {:.3} seconds.",
                     hours,
                     minutes,
                     seconds);
        }
    }
    info!(log, "Simulation completed");
}

#[cfg(test)]
mod tests {
    #[test]
    fn placeholder() {
        let num = 5;
        assert_eq!(num, 5);
    }
}
<commit_msg>A small pause on error to let async logs catch up.<commit_after>//! **Wa** ve **f** unction Solv **er**: a parallelized, 3D, Schrödinger equation solver.
//!
//! Wafer exploits a Wick-rotated time-dependent Schrödinger equation to solve for
//! time-independent solutions in three dimensions.
//!
//! Inspired by [quantumfdtd](http://sourceforge.net/projects/quantumfdtd/),
//! which is a proof of concept tool and falls short of a general purpose utility.
//! Wafer attempts to remedy this issue.
//!
//! If you use Wafer in your research, please reference the following articles:
//!
//! M. Strickland and D. Yager-Elorriaga, “A parallel algorithm for solving the 3d
//! Schrödinger equation”,
//! [Journal of Computational Physics __229__, 6015–6026 (2010)](http://dx.doi.org/10.1016/j.jcp.2010.04.032).

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(missing_docs_in_private_items))]
#![cfg_attr(feature="clippy", warn(single_match_else))]

extern crate ansi_term;
extern crate chrono;
#[macro_use]
extern crate clap;
extern crate csv;
extern crate indicatif;
#[macro_use]
extern crate lazy_static;
#[macro_use(s)]
extern crate ndarray;
extern crate ndarray_parallel;
extern crate num;
extern crate num_cpus;
extern crate ordinal;
extern crate rand;
extern crate rayon;
extern crate rmp_serde as rmps;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate slog;
extern crate slog_async;
extern crate slog_term;
extern crate term_size;

use clap::{App, Arg};
use slog::{Drain, Duplicate, Logger, Fuse, LevelFilter, Level};
use std::fs::OpenOptions;
use std::process;
use std::thread;
use std::time::{Duration, Instant};
use config::Config;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

/// Config is a (mostly) public module which reads the configuration file `wafer.cfg`
/// and poplulates the `Config` struct with the information required to run the current
/// instance of the application.
pub mod config;
/// The meat of the caclulation is performed on a finite grid. Basically all of the computation
/// work is done within this module.
mod grid;
/// Any required file input (apart from configuration) is handled here. Plain text and binary formats.
mod input;
/// All file output is handled in this module. Plain text and binary options are both here.
mod output;
/// Handles the potential generation, binding energy offsets, callouts to files or scripts
/// if needed etc.
mod potential;

/// Exits (no error) after a short pause. Because we're using async logs, sometimes we dump before
/// the log system outputs information. We spool for a little first in these instances so we get the
/// logging info.
fn exit_with_pause() {
    thread::sleep(Duration::from_millis(10));
    process::exit(1);
}

/// System entry point
fn main() {
    //Simulation timer.
    let start_time = Instant::now();

    //CLI options. For the moment, a custom configuration file and custom debug levels.
    let matches = App::new("Wafer")
                        .version(crate_version!())
                        .author(crate_authors!())
                        .about("Exploits a Wick-rotated time-dependent Schrödinger equation to solve for time-independent solutions in three dimensions.")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("The configuration file to use (default is \"wafer.cfg\")")
                                    .takes_value(true))
                        .arg(Arg::with_name("debug")
                                    .short("d")
                                    .multiple(true)
                                    .help("Raises screen debug level"))
                        .get_matches();

    //Load configuation parameters.
    let config_file = matches.value_of("config").unwrap_or("wafer.cfg");
    let config = match Config::load(config_file) {
        Ok(c) => c,
        Err(err) => {
            println!("Error processing configuration: {}", err);
            //This match isn't happy using the `exit_with_pause` function, but fine with it explicit like this...
            thread::sleep(Duration::from_millis(10));
            process::exit(1);
        }
    };
    if let Err(err) = output::check_output_dir(&config.project_name) {
        println!("Could not communicate with output directory: {}", err);
        exit_with_pause();
    };

    //Setup logging.
    let log_file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(output::get_project_dir(&config.project_name) + "/simulation.log")
        .expect("Cannot connect to log file");
    let syslog = slog_term::PlainDecorator::new(log_file);
    let sys_drain = slog_term::FullFormat::new(syslog).build().fuse();
    let sys_drain = slog_async::Async::new(sys_drain).build().fuse();
    let screen = slog_term::TermDecorator::new().build();
    let screen_drain = slog_term::FullFormat::new(screen).build().fuse();
    let screen_drain = slog_async::Async::new(screen_drain).build().fuse();

    let screen_level = match matches.occurrences_of("debug") {
        0 => Level::Warning,
        1 => Level::Info,
        2 | _ => Level::Debug,
    };
    let log = Logger::root(Fuse::new(Duplicate::new(LevelFilter::new(screen_drain, screen_level), sys_drain)),
                           o!());

    info!(log, "Starting Wafer solver"; "version" => crate_version!(), "build-id" => short_sha());

    info!(log, "Checking/creating directories");
    if let Err(err) = input::check_input_dir() {
        crit!(log, "Could not communicate with input directory: {}", err);
        exit_with_pause();
    };

    //Override rayon's defaults of threads (including HT cores) to physical cores
    if let Err(err) = rayon::initialize(rayon::Configuration::new()
                                            .num_threads(num_cpus::get_physical())) {
        crit!(log, "Failed to initialise thread pool: {}", err);
        exit_with_pause();
    };

    let term_width = *output::TERMWIDTH;

    let sha = if term_width <= 97 { short_sha() } else { sha() };

    output::print_banner(sha);

    info!(log, "Loading Configuation from disk");
    config.print(term_width);
    if let Err(err) = output::copy_config(&config.project_name) {
        //TODO: Input from CLI if non-default config file
        warn!(log,
              "Configuration file not copied to output directory: {}",
              err);
    };

    if let Err(err) = grid::run(&config, &log) {
        crit!(log, "{}", err);
        exit_with_pause();
    };

    let elapsed = start_time.elapsed();
    let time_taken = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
    match time_taken {
        0.0...60.0 => {
            println!("Simulation complete. Elapsed time: {:.3} seconds.",
                     time_taken)
        }
        60.0...3600.0 => {
            let minutes = (time_taken / 60.).floor();
            let seconds = time_taken - 60. * minutes;
            println!("Simulation complete. Elapsed time: {} minutes, {:.3} seconds.",
                     minutes,
                     seconds);
        }
        _ => {
            let hours = (time_taken / 3600.).floor();
            let minutes = ((time_taken - 3600. * hours) / 60.).floor();
            let seconds = time_taken - 3600. * hours - 60. * minutes;
            println!("Simulation complete. Elapsed time: {} hours, {} minutes, {:.3} seconds.",
                     hours,
                     minutes,
                     seconds);
        }
    }
    info!(log, "Simulation completed");
}

#[cfg(test)]
mod tests {
    #[test]
    fn placeholder() {
        let num = 5;
        assert_eq!(num, 5);
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate libc;

use xlib::{XOpenDisplay, XDisplayName, XQueryExtension, XInitExtension, XSynchronize, XKeysymToString, XKeycodeToKeysym};
use libc::{c_int};
use std::ptr;
use xtst::{XRecordCreateContext, XRecordAllClients, XRecordAllocRange, XRecordRange, XRecordQueryVersion, XRecordEnableContext, XRecordEnableContextAsync,XRecordInterceptData, XRecordProcessReplies, XRecordFreeData};
use std::mem;
use std::c_str::CString;
mod xtst;
mod xlib;
mod xlibint;
mod xutil;

struct XRecordDatum {
  xtype: ::libc::c_uchar,
  event: ::xlib::XEvent,
  req:   ::xlibint::xResourceReq,
  reply: ::xlibint::xGenericReply,
  error: ::xlibint::xError,
  setup: ::xlibint::xConnSetupPrefix,
}

// let mut display_control: *mut xlib::Display  = std::mem::transmute(0);
// let mut display_data: *mut xlib::Display  = std::mem::transmute(0);
static mut display_control: *mut xlib::Display = 0 as *mut xlib::Struct__XDisplay;
// static mut display_data: *mut xlib::Display = 0 as *mut xlib::Struct__XDisplay;
static mut display_data: Display<'static> = Display {display: 0 as *mut xlib::Display};
static mut event_count:u32 = 0;
fn main() {
	unsafe {
		let mut a:  i8 = 0;
		display_control = XOpenDisplay(&a);
		display_data = Display::new();

		if display_control.is_null() {
			panic!("XOpenDisplay() failed!");
		}

		XSynchronize(display_control, 1);

		let display_name = unsafe {XDisplayName(&a)};
		let ext_name = "RECORD";
		// Check presence of Record extension
		let arg2:*mut c_int = &mut 1;
		let arg3:*mut c_int = &mut 1;
		let arg4:*mut c_int = &mut 1;
		let has_record = XQueryExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8,arg2,arg3,arg4);
		let extension = XInitExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8);
		if extension.is_null() {
			panic!("XInitExtension() failed!");
		}

		// Get version
		let mut versionMajor: c_int = 0;
		let mut versionMinor: c_int = 0;
		XRecordQueryVersion(display_control, &mut versionMajor, &mut versionMinor);
		println!("RECORD extension version {}.{}", versionMajor, versionMinor);

		// Prepare record range
		let mut recordRange: XRecordRange = *XRecordAllocRange();
		let mut recordRangePtr: *mut *mut XRecordRange = std::mem::transmute(&mut &mut recordRange);
		recordRange.device_events.first = 2; // KeyPress
		recordRange.device_events.last = 6; // MotionNotify

		// Create context
		let context = XRecordCreateContext(
			display_control,
			0,
			&mut XRecordAllClients,
			1,
			recordRangePtr,
			1
		);
		if context == 0 {
			panic!("Fail create Record context\n");
		}

		// Run
		let res = XRecordEnableContextAsync(display_data.display, context, Some(recordCallback), &mut 0);
		if res == 0 {
			panic!("Cound not enable the Record context!\n");
		}
		xtst::XRecordFreeContext(display_data.display, context);
		loop {
			XRecordProcessReplies(display_data.display);
		}
	}
}

extern "C" fn recordCallback(pointer:*mut i8, raw_data: *mut XRecordInterceptData) {

	unsafe {

		let data = &*raw_data;
		// println!("Category {}", data.category);
		if data.category != xtst::XRecordFromServer {
			return;
		}
		println!("Event count: {}", event_count);
		event_count += 1;
		println!("Time {}", data.server_time);
		println!("Datalen {}", data.data_len);
		let mut xdatum_ptr: *mut XRecordDatum = data.data as *mut XRecordDatum;
		let mut xdatum = &*xdatum_ptr;

		let mut event = xdatum.event;
		println!("Type {}", xdatum.xtype);

		// Catch key event
		if xdatum.xtype == xtst::KeyPress || xdatum.xtype == xtst::KeyRelease {
			// extract key code
			let raw_bytes: &mut [u8,..4] = std::mem::transmute(data.data);
			let c_char  = XKeysymToString(XKeycodeToKeysym(display_control, raw_bytes[1], 0));
			let c_string = CString::new(std::mem::transmute(c_char), false);
			let char: &str = c_string.as_str().unwrap();
			println!("Keycode: {}, Character {}", raw_bytes[1], char);

			// println!("nitems {}", (&*wm_name).nitems);
		}
		// get current focus window
		let current_window: *mut xlib::Window = &mut 0;
		let revert_to_return: *mut i32 = &mut 0;
		xlib::XGetInputFocus(display_control, current_window, revert_to_return);
		println!("revertToReturn {}", *revert_to_return);
		let mut j = 0u;
		let mut wm_name: *mut xutil::XTextProperty = std::mem::transmute(&mut j);
		let mut wm_name_true: &str = "";
		let mut tmp =0i8;
		let mut c_wm_name: CString = CString::new(&tmp,false);
		let mut res = 0;
		// res = xutil::XGetWMName(display_control, *current_window, wm_name);
		let mut i = 0u;
		while res == 0 && i < 2 {
			print!(".");
			println!("current_window {}", *current_window);
			if *current_window == 0 {
				break;
			}
			res = xutil::XGetWMName(display_control, *current_window, wm_name);

			if res == 0 {
				println!("Move to parent");
				let mut root: xlib::Window = 0;
				let mut parent: xlib::Window = 0;
				let mut childrens: *mut xlib::Window = &mut 0u64;
				let mut nchildren: u32 = 0;
				let r2 = xlib::XQueryTree(display_control, *current_window, &mut root, &mut parent, &mut childrens, &mut nchildren);
				if r2 == 0 {
					print!("*");
				} else {
					println!("parent {}", parent);
					*current_window = parent;
				}
			}
			// get parent window
			i += 1;
		}
		println!("---");
		if res == 0 {
			println!("no wmname");
		} else {
			// extract name from XTextProperty
			println!("wmname found!");
			println!("format: {}", (*wm_name).format);
			if (*wm_name).format != 8 {
				panic!("");
			}
			println!("encoding: {}", (*wm_name).encoding);
			let encoding_name = xlib::XGetAtomName(display_control, (*wm_name).encoding);
			let encoding_name_string = CString::new(std::mem::transmute(encoding_name), false);
			println!("encoding name: {}", encoding_name_string.as_str().unwrap());
			let mut tmp2 = 0i8;
			let mut list: *mut *mut ::libc::c_char = std::mem::transmute(&mut &mut tmp2);
			let mut list_count: i32 = 0;
			let res3 = xutil::XmbTextPropertyToTextList(display_control, std::mem::transmute(wm_name), &mut list, &mut list_count);
			println!("convert result: {}", res3);
			if res3 == 0 {
				println!("list count {}", list_count);
				c_wm_name = CString::new(std::mem::transmute(*list), false);
				wm_name_true = c_wm_name.as_str().unwrap();
				println!("wm_name: {}", wm_name_true);
				xlib::XFreeStringList(list);
			} else {
				c_wm_name = CString::new(std::mem::transmute((*wm_name).value), false);
				// wm_name_true = c_wm_name.as_str().unwrap();
				println!("wm_name bytes: {}", c_wm_name.as_bytes());
				// ая -      27 45 76 208 239 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// бв -      27 45 76 209 210 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// zx -      122 120 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// длодлод - 27 45 76 212 219 222 212 219 222 212 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// zx • - Sublime Text (UNREGISTERED)

				println!("wm_name: {}", c_wm_name);
				println!("wm_name len w/o null: {}", c_wm_name.len());
			}

		}

		XRecordFreeData(raw_data);
	}
	println!("\n");
}

// ============================================================================
// Simple naive wrappers around X stuff
// ============================================================================
struct Display<'a> {
    display: *mut xlib::Display,
}

impl<'a> Display<'a> {
	fn new() -> Display<'a> {
		Display {display: unsafe {
			let mut a:  i8 = 0;
			let dpy = XOpenDisplay(&a);
			if dpy.is_null() {
				panic!("XOpenDisplay() failed!");
			}
			dpy
		}}
	}
	fn get_input_focus(&self) -> Window{
		let current_window: *mut xlib::Window = &mut 0;
		let revert_to_return: *mut i32 = &mut 0;
		unsafe{xlib::XGetInputFocus(self.display, current_window, revert_to_return)};
		Window {id: 0, display: self}
	}
}

struct Window<'a> {
    id: u64, // XID
    display: &'a Display<'a>
}

impl<'a> Window<'a> {
	fn get_wm_name(&self) {
		let mut prop: *mut xutil::XTextProperty = 0 as *mut xutil::XTextProperty;
		let res = unsafe{xutil::XGetWMName(self.display.display, self.id, prop)};
	}
}<commit_msg>wapper another display +<commit_after>#![feature(globs)]
extern crate libc;

use xlib::{XOpenDisplay, XDisplayName, XQueryExtension, XInitExtension, XSynchronize, XKeysymToString, XKeycodeToKeysym};
use libc::{c_int};
use std::ptr;
use xtst::{XRecordCreateContext, XRecordAllClients, XRecordAllocRange, XRecordRange, XRecordQueryVersion, XRecordEnableContext, XRecordEnableContextAsync,XRecordInterceptData, XRecordProcessReplies, XRecordFreeData};
use std::mem;
use std::c_str::CString;
mod xtst;
mod xlib;
mod xlibint;
mod xutil;

struct XRecordDatum {
  xtype: ::libc::c_uchar,
  event: ::xlib::XEvent,
  req:   ::xlibint::xResourceReq,
  reply: ::xlibint::xGenericReply,
  error: ::xlibint::xError,
  setup: ::xlibint::xConnSetupPrefix,
}

// let mut display_control: *mut xlib::Display  = std::mem::transmute(0);
// let mut display_data: *mut xlib::Display  = std::mem::transmute(0);
// static mut display_control: *mut xlib::Display = 0 as *mut xlib::Struct__XDisplay;
// static mut display_data: *mut xlib::Display = 0 as *mut xlib::Struct__XDisplay;
static mut display_control: Display<'static> = Display {display: 0 as *mut xlib::Display};
static mut display_data: Display<'static> = Display {display: 0 as *mut xlib::Display};
static mut event_count:u32 = 0;
fn main() {
	unsafe {
		let mut a:  i8 = 0;
		display_control = Display::new();
		display_data = Display::new();

		XSynchronize(display_control.display, 1);

		let display_name = unsafe {XDisplayName(&a)};
		let ext_name = "RECORD";
		// Check presence of Record extension
		let arg2:*mut c_int = &mut 1;
		let arg3:*mut c_int = &mut 1;
		let arg4:*mut c_int = &mut 1;
		let has_record = XQueryExtension(display_control.display, ext_name.to_c_str().as_ptr() as *const i8,arg2,arg3,arg4);
		let extension = XInitExtension(display_control.display, ext_name.to_c_str().as_ptr() as *const i8);
		if extension.is_null() {
			panic!("XInitExtension() failed!");
		}

		// Get version
		let mut versionMajor: c_int = 0;
		let mut versionMinor: c_int = 0;
		XRecordQueryVersion(display_control.display, &mut versionMajor, &mut versionMinor);
		println!("RECORD extension version {}.{}", versionMajor, versionMinor);

		// Prepare record range
		let mut recordRange: XRecordRange = *XRecordAllocRange();
		let mut recordRangePtr: *mut *mut XRecordRange = std::mem::transmute(&mut &mut recordRange);
		recordRange.device_events.first = 2; // KeyPress
		recordRange.device_events.last = 6; // MotionNotify

		// Create context
		let context = XRecordCreateContext(
			display_control.display,
			0,
			&mut XRecordAllClients,
			1,
			recordRangePtr,
			1
		);
		if context == 0 {
			panic!("Fail create Record context\n");
		}

		// Run
		let res = XRecordEnableContextAsync(display_data.display, context, Some(recordCallback), &mut 0);
		if res == 0 {
			panic!("Cound not enable the Record context!\n");
		}
		xtst::XRecordFreeContext(display_data.display, context);
		loop {
			XRecordProcessReplies(display_data.display);
		}
	}
}

extern "C" fn recordCallback(pointer:*mut i8, raw_data: *mut XRecordInterceptData) {

	unsafe {

		let data = &*raw_data;
		// println!("Category {}", data.category);
		if data.category != xtst::XRecordFromServer {
			return;
		}
		println!("Event count: {}", event_count);
		event_count += 1;
		println!("Time {}", data.server_time);
		println!("Datalen {}", data.data_len);
		let mut xdatum_ptr: *mut XRecordDatum = data.data as *mut XRecordDatum;
		let mut xdatum = &*xdatum_ptr;

		let mut event = xdatum.event;
		println!("Type {}", xdatum.xtype);

		// Catch key event
		if xdatum.xtype == xtst::KeyPress || xdatum.xtype == xtst::KeyRelease {
			// extract key code
			let raw_bytes: &mut [u8,..4] = std::mem::transmute(data.data);
			let c_char  = XKeysymToString(XKeycodeToKeysym(display_control.display, raw_bytes[1], 0));
			let c_string = CString::new(std::mem::transmute(c_char), false);
			let char: &str = c_string.as_str().unwrap();
			println!("Keycode: {}, Character {}", raw_bytes[1], char);

			// println!("nitems {}", (&*wm_name).nitems);
		}
		// get current focus window
		let current_window: *mut xlib::Window = &mut 0;
		let revert_to_return: *mut i32 = &mut 0;
		xlib::XGetInputFocus(display_control.display, current_window, revert_to_return);
		println!("revertToReturn {}", *revert_to_return);
		let mut j = 0u;
		let mut wm_name: *mut xutil::XTextProperty = std::mem::transmute(&mut j);
		let mut wm_name_true: &str = "";
		let mut tmp =0i8;
		let mut c_wm_name: CString = CString::new(&tmp,false);
		let mut res = 0;
		// res = xutil::XGetWMName(display_control.display, *current_window, wm_name);
		let mut i = 0u;
		while res == 0 && i < 2 {
			print!(".");
			println!("current_window {}", *current_window);
			if *current_window == 0 {
				break;
			}
			res = xutil::XGetWMName(display_control.display, *current_window, wm_name);

			if res == 0 {
				println!("Move to parent");
				let mut root: xlib::Window = 0;
				let mut parent: xlib::Window = 0;
				let mut childrens: *mut xlib::Window = &mut 0u64;
				let mut nchildren: u32 = 0;
				let r2 = xlib::XQueryTree(display_control.display, *current_window, &mut root, &mut parent, &mut childrens, &mut nchildren);
				if r2 == 0 {
					print!("*");
				} else {
					println!("parent {}", parent);
					*current_window = parent;
				}
			}
			// get parent window
			i += 1;
		}
		println!("---");
		if res == 0 {
			println!("no wmname");
		} else {
			// extract name from XTextProperty
			println!("wmname found!");
			println!("format: {}", (*wm_name).format);
			if (*wm_name).format != 8 {
				panic!("");
			}
			println!("encoding: {}", (*wm_name).encoding);
			let encoding_name = xlib::XGetAtomName(display_control.display, (*wm_name).encoding);
			let encoding_name_string = CString::new(std::mem::transmute(encoding_name), false);
			println!("encoding name: {}", encoding_name_string.as_str().unwrap());
			let mut tmp2 = 0i8;
			let mut list: *mut *mut ::libc::c_char = std::mem::transmute(&mut &mut tmp2);
			let mut list_count: i32 = 0;
			let res3 = xutil::XmbTextPropertyToTextList(display_control.display, std::mem::transmute(wm_name), &mut list, &mut list_count);
			println!("convert result: {}", res3);
			if res3 == 0 {
				println!("list count {}", list_count);
				c_wm_name = CString::new(std::mem::transmute(*list), false);
				wm_name_true = c_wm_name.as_str().unwrap();
				println!("wm_name: {}", wm_name_true);
				xlib::XFreeStringList(list);
			} else {
				c_wm_name = CString::new(std::mem::transmute((*wm_name).value), false);
				// wm_name_true = c_wm_name.as_str().unwrap();
				println!("wm_name bytes: {}", c_wm_name.as_bytes());
				// ая -      27 45 76 208 239 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// бв -      27 45 76 209 210 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// zx -      122 120 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// длодлод - 27 45 76 212 219 222 212 219 222 212 32 27 37 71 226 128 162 27 37 64 32 45 32 83 117 98 108 105 109 101 32 84 101 120 116 32 40 85 78 82 69 71 73 83 84 69 82 69 68 41 0
				// zx • - Sublime Text (UNREGISTERED)

				println!("wm_name: {}", c_wm_name);
				println!("wm_name len w/o null: {}", c_wm_name.len());
			}

		}

		XRecordFreeData(raw_data);
	}
	println!("\n");
}

// ============================================================================
// Simple naive wrappers around X stuff
// ============================================================================
struct Display<'a> {
    display: *mut xlib::Display,
}

impl<'a> Display<'a> {
	fn new() -> Display<'a> {
		Display {display: unsafe {
			let mut a:  i8 = 0;
			let dpy = XOpenDisplay(&a);
			if dpy.is_null() {
				panic!("XOpenDisplay() failed!");
			}
			dpy
		}}
	}
	fn get_input_focus(&self) -> Window{
		let current_window: *mut xlib::Window = &mut 0;
		let revert_to_return: *mut i32 = &mut 0;
		unsafe{xlib::XGetInputFocus(self.display, current_window, revert_to_return)};
		Window {id: 0, display: self}
	}
}

struct Window<'a> {
    id: u64, // XID
    display: &'a Display<'a>
}

impl<'a> Window<'a> {
	fn get_wm_name(&self) {
		let mut prop: *mut xutil::XTextProperty = 0 as *mut xutil::XTextProperty;
		let res = unsafe{xutil::XGetWMName(self.display.display, self.id, prop)};
	}
}<|endoftext|>


<commit_before>extern crate argparse;
use argparse::{ArgumentParser, StoreTrue, Store};

fn main() {
    let mut size: usize = 20;
    let mut reverse: bool = false;
    let mut skin = "███".to_string();
    let padding = vec!["  ", " ", "", " ", "  ", "   ", "    ", "   "];

    {
        // this block limits scope of borrows by ap.refer() method
        let mut ap = ArgumentParser::new();

        ap.set_description("Print a beautiful millipede (written in rust)");
        ap.refer(&mut size)
          .add_option(&["-w", "--width"], Store, "millipede width");
        ap.refer(&mut skin)
          .add_option(&["-s", "--skin"], Store, "millipede skin");
        ap.refer(&mut reverse)
          .add_option(&["-r", "--reverse"], StoreTrue, "reverse the millipede");
        ap.parse_args_or_exit();
    }
    if reverse == false {
        let mut i: usize = 0;

        println!("    ╚⊙ ⊙╝");
        while i < size {
            println!("{}╚═({})═╝", padding[i % 8], skin);
            i = i + 1;
        }
    } else {
        let mut i: usize = size;

        while i > 0 {
            println!("{}╔═({})═╗", padding[i % 8], skin);
            i = i - 1;
        }
        println!("   ╔⊙ ⊙╗");
    }
}
<commit_msg>Add http server<commit_after>extern crate argparse;
extern crate iron;

use argparse::{ArgumentParser, StoreTrue, Store};
use iron::prelude::*;

fn http_server(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((iron::status::Ok, "Rust server")))
}

static HTTP_ADDR: &'static str = "localhost:4242";

fn main() {
    let mut size: usize = 20;
    let mut reverse: bool = false;
    let mut server_mode: bool = false;
    let mut skin = "███".to_string();
    let padding = vec!["  ", " ", "", " ", "  ", "   ", "    ", "   "];

    {
        // this block limits scope of borrows by ap.refer() method
        let mut ap = ArgumentParser::new();

        ap.set_description("Print a beautiful millipede (written in rust)");
        ap.refer(&mut size)
          .add_option(&["-w", "--width"], Store, "millipede width");
        ap.refer(&mut skin)
          .add_option(&["-s", "--skin"], Store, "millipede skin");
        ap.refer(&mut reverse)
          .add_option(&["-r", "--reverse"], StoreTrue, "reverse the millipede");
        ap.refer(&mut server_mode)
          .add_option(&["--server"], StoreTrue, "Spawn http server");
        ap.parse_args_or_exit();
    }
    if server_mode == true {
        let chain = Chain::new(http_server);

        println!("Listening on {}", HTTP_ADDR);
        Iron::new(chain).http(HTTP_ADDR).unwrap();
    }

    if reverse == false {
        let mut i: usize = 0;

        println!("    ╚⊙ ⊙╝");
        while i < size {
            println!("{}╚═({})═╝", padding[i % 8], skin);
            i = i + 1;
        }
    } else {
        let mut i: usize = size;

        while i > 0 {
            println!("{}╔═({})═╗", padding[i % 8], skin);
            i = i - 1;
        }
        println!("   ╔⊙ ⊙╗");
    }
}
<|endoftext|>


<commit_before>extern crate discord;
extern crate reqwest;
extern crate select;

use discord::Discord;
use discord::model::Event;

use std::vec;

use select::document::Document;
use select::predicate::Class;

// For file reading
use std::io::Read;
use std::fs::File;

#[derive(Debug)]
struct UMassEvent {
    title: String,
    description: String,
    date: String,
    location: Option<String>,
}

impl UMassEvent {
    fn format(&self) -> String {
        match self.location {
            Some(ref location) => format!("{} at {}:\n{}", self.title, location, self.description),
            None => format!("{}:\n{}", self.title, self.description),
        }
    }
}

fn get_events() -> Vec<UMassEvent> {

    let mut resp = reqwest::get("http://www.umass.edu/events/")
        .expect("Couldn't get the events page");

    println!("Status: {}", resp.status());

    let mut content = String::new();
    let _ = resp.read_to_string(&mut content);

    let document = Document::from(&*content);

    let mut events: vec::Vec<UMassEvent> = vec![];

    for node in document.find(Class("views-row")) {

        // This is really janky and relies on UMass not changing the event page html...

        let title = node.find(Class("views-field-title"))
            .next()
            .unwrap()
            .children()
            .nth(1)
            .unwrap()
            .first_child()
            .unwrap()
            .first_child()
            .unwrap()
            .text();
        let description = node.find(Class("views-field-field-short-desc"))
            .next()
            .unwrap()
            .children()
            .nth(1)
            .unwrap()
            .first_child()
            .unwrap()
            .text();
        let date = node.find(Class("event-date")).next().unwrap().text();
        let location = node.find(Class("event-location"))
            .next()
            .unwrap()
            .children()
            .nth(1)
            .map(|node| node.first_child().unwrap().text());
        events.push(UMassEvent {
            title: title,
            description: description,
            date: date,
            location: location,
        })

    }
    events
}

fn main() {
    let mut token_file = File::open("token").expect("No token file");
    let mut token = String::new();
    let _ = token_file.read_to_string(&mut token);

    let discord = Discord::from_bot_token(token.trim()).expect("Login failed");

    let (mut connection, _) = discord.connect().expect("Connect failed");

    println!("Connected to Discord");
    println!("Connected to servers: {:?}", discord.get_servers());

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {
                println!("{} says: {}", message.author.name, message.content);
                if message.content == "!events" {

                    let events = get_events();

                    // Intro
                    let _ =
                        discord.send_message(message.channel_id, "Today's events are:", "", false);

                    for event in events {
                        let _ =
                            discord.send_message(message.channel_id, &event.format(), "", false);
                    }

                } else if message.content == "!quit" {
                    println!("Quitting.");
                    break;
                }
            }
            Ok(_) => {}
            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed on us with code {:?}: {}", code, body);
                break;
            }
            Err(err) => println!("Receive error: {:?}", err),
        }
    }
}
<commit_msg>Clean up<commit_after>extern crate discord;
extern crate reqwest;
extern crate select;

use discord::Discord;
use discord::model::Event;

use select::document::Document;
use select::predicate::Class;

// For file reading
use std::io::Read;
use std::fs::File;

#[derive(Debug)]
struct UMassEvent {
    title: String,
    description: String,
    date: String,
    location: Option<String>,
}

impl UMassEvent {
    fn format(&self) -> String {
        match self.location {
            // "Event_Name at Event_location: Long Description"
            Some(ref location) => format!("{} at {}:\n{}", self.title, location, self.description),
            // "Event_Name: Long Description"
            None => format!("{}:\n{}", self.title, self.description),
        }
    }
}

fn get_document() -> Result<select::document::Document, reqwest::Error> {
    reqwest::get("http://www.umass.edu/events/").map(|mut response| {
        // Extract the data from the http request
        let mut content = String::new();
        let _ = response.read_to_string(&mut content);
        Document::from(&*content)
    })
}

fn get_events() -> Vec<UMassEvent> {
    let document = get_document().expect("Couldn't get the events page");

    // Parse the data into a list of events
    let events = document.find(Class("views-row"))
        .map(|node| {

            // This is really janky and relies on UMass not changing the event page html...

            let title = node.find(Class("views-field-title"))
                .next()
                .unwrap()
                .children()
                .nth(1)
                .unwrap()
                .first_child()
                .unwrap()
                .first_child()
                .unwrap()
                .text();
            let description = node.find(Class("views-field-field-short-desc"))
                .next()
                .unwrap()
                .children()
                .nth(1)
                .unwrap()
                .first_child()
                .unwrap()
                .text();
            let date = node.find(Class("event-date")).next().unwrap().text();
            let location = node.find(Class("event-location"))
                .next()
                .unwrap()
                .children()
                .nth(1)
                .map(|node| node.first_child().unwrap().text());

            // Return the event, which will then be collected into the events vector
            UMassEvent {
                title: title,
                description: description,
                date: date,
                location: location,
            }
        })
        .collect();

    events
}

// Get the token file from memory
fn load_token() -> String {
    let mut token = String::new();
    let _ = File::open("token").expect("No token file").read_to_string(&mut token);
    token
}

// Login to Discord and connect
fn login() -> (discord::Discord, discord::Connection) {
    let discord = Discord::from_bot_token(load_token().trim()).expect("Login failed");
    let connection = discord.connect().expect("Connect failed").0;
    (discord, connection)
}

fn main() {
    let (discord, mut connection) = login();
    println!("Connected to Discord");
    println!("Connected to servers: {:?}", discord.get_servers());

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {
                println!("{} says: {}", message.author.name, message.content);
                if message.content == "!events" {

                    let events = get_events();

                    // Intro
                    let _ =
                        discord.send_message(message.channel_id, "Today's events are:", "", false);

                    let _ = events.iter().map(|event| {
                        discord.send_message(message.channel_id, &event.format(), "", false)
                    });

                } else if message.content == "!quit" {
                    println!("Quitting.");
                    break;
                }
            }
            Ok(_) => {}
            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed on us with code {:?}: {}", code, body);
                break;
            }
            Err(err) => println!("Receive error: {:?}", err),
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate rustc_serialize;

use std::io::Read;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::Json;

#[derive(Debug)]
struct Document {
    data: Json,
}

impl Document {
    fn from_json(data: Json) -> Document {
        Document{
            data: data,
        }
    }
}

#[derive(Debug)]
struct Mapping {
    pub docs: HashMap<String, Document>,
}

impl Mapping {
    fn new() -> Mapping {
        Mapping{
            docs: HashMap::new(),
        }
    }
}

#[derive(Debug)]
struct Index {
    pub mappings: HashMap<&'static str, Mapping>,
}

impl Index {
    fn new() -> Index {
        Index{
            mappings: HashMap::new(),
        }
    }
}

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

fn main() {
    let mut indices = Arc::new(Mutex::new(HashMap::new()));
    let mut wagtail_index = Index::new();
    wagtail_index.mappings.insert("wagtaildocs_document", Mapping::new());
    indices.lock().unwrap().insert("wagtail", wagtail_index);

    let mut router = Router::new();

    router.get("/", |_: &mut Request| -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    });

    {
        let indices = indices.clone();

        router.get("/:index/_count", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Load query from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // TODO: Run query

            let mut response = Response::with((status::Ok, "{\"count\": 0}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.get("/:index/_search", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Load query from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // TODO: Run query

            let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.put("/:index/:mapping/:doc", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
            let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get_mut(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Find mapping
            let mut mapping = match index.mappings.get_mut(mapping_name) {
                Some(mapping) => mapping,
                None => {
                    let mut response = Response::with((status::NotFound, "{\"message\": \"Mapping not found\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // Load data from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // Create and insert document
            let doc = Document::from_json(data);
            mapping.docs.insert(doc_id.clone().to_owned(), doc);

            let mut response = Response::with((status::Ok, "{}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    Iron::new(router).http("localhost:9200").unwrap();
}
<commit_msg>Temporary implementation of count<commit_after>extern crate iron;
extern crate router;
extern crate rustc_serialize;

use std::io::Read;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::Json;

#[derive(Debug)]
struct Document {
    data: Json,
}

impl Document {
    fn from_json(data: Json) -> Document {
        Document{
            data: data,
        }
    }
}

#[derive(Debug)]
struct Mapping {
    pub docs: HashMap<String, Document>,
}

impl Mapping {
    fn new() -> Mapping {
        Mapping{
            docs: HashMap::new(),
        }
    }
}

#[derive(Debug)]
struct Index {
    pub mappings: HashMap<&'static str, Mapping>,
}

impl Index {
    fn new() -> Index {
        Index{
            mappings: HashMap::new(),
        }
    }
}

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

fn main() {
    let mut indices = Arc::new(Mutex::new(HashMap::new()));
    let mut wagtail_index = Index::new();
    wagtail_index.mappings.insert("wagtaildocs_document", Mapping::new());
    indices.lock().unwrap().insert("wagtail", wagtail_index);

    let mut router = Router::new();

    router.get("/", |_: &mut Request| -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    });

    {
        let indices = indices.clone();

        router.get("/:index/_count", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Load query from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // TODO: Run query

            // Temporary count and return numbers
            let mut count = 0;
            for mapping in index.mappings.values() {
                count += mapping.docs.len();
            }

            let mut response = Response::with((status::Ok, format!("{{\"count\": {}}}", count)));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.get("/:index/_search", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Load query from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // TODO: Run query

            let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.put("/:index/:mapping/:doc", move |req: &mut Request| -> IronResult<Response> {
            // URL parameters
            let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
            let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

            // Lock index array
            let mut indices = indices.lock().unwrap();

            // Find index
            let mut index = match indices.get_mut(index_name) {
                Some(index) => index,
                None => {
                    return Ok(index_not_found_response());
                }
            };

            // Find mapping
            let mut mapping = match index.mappings.get_mut(mapping_name) {
                Some(mapping) => mapping,
                None => {
                    let mut response = Response::with((status::NotFound, "{\"message\": \"Mapping not found\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // Load data from body
            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            let data = match Json::from_str(&payload) {
                Ok(data) => data,
                Err(error) => {
                    // TODO: What specifically is bad about the JSON?
                    let mut response = Response::with((status::BadRequest, "{\"message\": \"Couldn't parse JSON\"}"));
                    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                    return Ok(response);
                }
            };

            // Create and insert document
            let doc = Document::from_json(data);
            mapping.docs.insert(doc_id.clone().to_owned(), doc);

            let mut response = Response::with((status::Ok, "{}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    Iron::new(router).http("localhost:9200").unwrap();
}
<|endoftext|>