<commit_before>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip.
//!
//! The Advanced "mode" is enabled by writing 87 87 to PORT 1. It is later disabled by writing AA
//! to that same port. `07 12` then selects the bank 12h. This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | EE XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `EE` – firstly sets RGB to enabled.
//!
//! Purpose of following three most significant bits in `EE` is known:
//!
//! `0b10000000` - unknown
//! `0b01000000` - unknown
//! `0b00100000` - unknown
//!
//!
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write, Read};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const RGB_BANK: u8 = 0x12;
const NCT6795D_MASK: u16 = 0xD350;

const REG_DEVID_MSB: u8 = 0x20;
const REG_DEVID_LSB: u8 = 0x21;
const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn inb(f: &mut fs::File, port: u16) -> io::Result<u8> {
    let mut d = [0u8];
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.read(&mut d)?;
    Ok(d[0])
}

fn outb(f: &mut fs::File, port: u16, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, base_port: u16, cell: u8, data: u8) -> io::Result<()> {
    outb(f, base_port, cell)?;
    outb(f, base_port + 1, data)
}

fn write_colour(f: &mut fs::File, base_port: u16, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, base_port, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 3, data as u8)
}

fn run<'a>(f: &mut fs::File, base_port: u16, matches: ArgMatches<'a>) -> Result<()> {
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let ignore = matches.is_present("IGNORECHECK");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    // Check if indeed a NCT6795D
    if !ignore {
        outb(f, base_port, REG_DEVID_MSB)?;
        let msb = inb(f, base_port + 1)?;
        outb(f, base_port, REG_DEVID_LSB)?;
        let ident = (msb as u16) << 8 | inb(f, base_port + 1)? as u16;
        if ident & 0xFFF0 != NCT6795D_MASK {
            let err: Result<()> = Err("`--ignore-check` flag, which would skip the check, \
                                       is not specified (may be dangerous); \
                                       also try `--base-port`".into());
            return err.chain_err(|| format!("The sI/O chip identifies as {:x}, which does not \
                                            seem to be NCT6795D", ident));
        }
    }

    // Without this pulsing does not work
    outb(&mut f, base_port, 0x07)?;
    outb(&mut f, base_port + 1, 0x09)?;
    outb(&mut f, base_port, 0x2c)?;
    let c = inb(&mut f, base_port + 1)?;
    if c & 0x10 != 0x10 {
        outb(&mut f, base_port + 1, c | 0x10)?;
    }

    // Select the 0x12th bank.
    outb(f, base_port, 0x07)?;
    outb(f, base_port + 1, RGB_BANK)?;

    // Check if RGB control enabled?
    outb(f, base_port, 0xe0)?;
    let d = inb(f, base_port + 1)?;
    if d & 0xe0 != 0xe0 {
        outb(f, base_port + 1, 0xe0 | (d & !0xe0))?;
    }

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(f, base_port, 0xe4, e4_val)?;

    write_byte_to_cell(f, base_port, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(f, base_port, 0xff, ff_val)?;

    write_colour(f, base_port, REDCELL, red)?;
    write_colour(f, base_port, GREENCELL, green)?;
    write_colour(f, base_port, BLUECELL, blue)?;

    Ok(())
}

/// Wrapper which enables and disables the advanced mode
fn run_wrap<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let base_port = u16::from_str_radix(matches.value_of("BASEPORT")
                                               .expect("bug: BASEPORT argument"), 16)?;

    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    // Enable the advanced mode.
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;

    // These are something the built-in app does during initialization…
    // Purpose unclear
    // outb(&mut f, base_port, 0x07)?;
    // outb(&mut f, base_port + 1, 0x0B)?;
    // outb(&mut f, base_port, 0x60)?;
    // let a = inb(&mut f, base_port + 1)?;
    // outb(&mut f, base_port, 0x61)?;
    // let b = inb(&mut f, base_port + 1)?;
    // println!("{:x} {:x}", a, b);

    let r = run(&mut f, base_port, matches);
    // Disable the advanced mode.
    outb(&mut f, base_port, 0xAA).chain_err(|| "could not disable advanced mode")?;
    r.chain_err(|| "could not set the colour")
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .arg(Arg::with_name("IGNORECHECK").long("ignore-check")
             .help("ignore the result of sI/O identification check"))
        .arg(Arg::with_name("BASEPORT").long("base-port").default_value("4e")
             .help("base port to use. Values known to be in use are 4e and 2e"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run_wrap(matches) {
        let _ = writeln!(::std::io::stderr(), "error: {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<commit_msg>Fix compilation failures<commit_after>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip.
//!
//! The Advanced "mode" is enabled by writing 87 87 to PORT 1. It is later disabled by writing AA
//! to that same port. `07 12` then selects the bank 12h. This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | EE XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `EE` – firstly sets RGB to enabled.
//!
//! Purpose of following three most significant bits in `EE` is known:
//!
//! `0b10000000` - unknown
//! `0b01000000` - unknown
//! `0b00100000` - unknown
//!
//!
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write, Read};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const RGB_BANK: u8 = 0x12;
const NCT6795D_MASK: u16 = 0xD350;

const REG_DEVID_MSB: u8 = 0x20;
const REG_DEVID_LSB: u8 = 0x21;
const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn inb(f: &mut fs::File, port: u16) -> io::Result<u8> {
    let mut d = [0u8];
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.read(&mut d)?;
    Ok(d[0])
}

fn outb(f: &mut fs::File, port: u16, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, base_port: u16, cell: u8, data: u8) -> io::Result<()> {
    outb(f, base_port, cell)?;
    outb(f, base_port + 1, data)
}

fn write_colour(f: &mut fs::File, base_port: u16, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, base_port, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 3, data as u8)
}

fn run<'a>(f: &mut fs::File, base_port: u16, matches: ArgMatches<'a>) -> Result<()> {
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let ignore = matches.is_present("IGNORECHECK");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    // Check if indeed a NCT6795D
    if !ignore {
        outb(f, base_port, REG_DEVID_MSB)?;
        let msb = inb(f, base_port + 1)?;
        outb(f, base_port, REG_DEVID_LSB)?;
        let ident = (msb as u16) << 8 | inb(f, base_port + 1)? as u16;
        if ident & 0xFFF0 != NCT6795D_MASK {
            let err: Result<()> = Err("`--ignore-check` flag, which would skip the check, \
                                       is not specified (may be dangerous); \
                                       also try `--base-port`".into());
            return err.chain_err(|| format!("The sI/O chip identifies as {:x}, which does not \
                                            seem to be NCT6795D", ident));
        }
    }

    // Without this pulsing does not work
    outb(f, base_port, 0x07)?;
    outb(f, base_port + 1, 0x09)?;
    outb(f, base_port, 0x2c)?;
    let c = inb(f, base_port + 1)?;
    if c & 0x10 != 0x10 {
        outb(f, base_port + 1, c | 0x10)?;
    }

    // Select the 0x12th bank.
    outb(f, base_port, 0x07)?;
    outb(f, base_port + 1, RGB_BANK)?;

    // Check if RGB control enabled?
    outb(f, base_port, 0xe0)?;
    let d = inb(f, base_port + 1)?;
    if d & 0xe0 != 0xe0 {
        outb(f, base_port + 1, 0xe0 | (d & !0xe0))?;
    }

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(f, base_port, 0xe4, e4_val)?;

    write_byte_to_cell(f, base_port, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(f, base_port, 0xff, ff_val)?;

    write_colour(f, base_port, REDCELL, red)?;
    write_colour(f, base_port, GREENCELL, green)?;
    write_colour(f, base_port, BLUECELL, blue)?;

    Ok(())
}

/// Wrapper which enables and disables the advanced mode
fn run_wrap<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let base_port = u16::from_str_radix(matches.value_of("BASEPORT")
                                               .expect("bug: BASEPORT argument"), 16)?;

    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    // Enable the advanced mode.
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;

    // These are something the built-in app does during initialization…
    // Purpose unclear
    // outb(&mut f, base_port, 0x07)?;
    // outb(&mut f, base_port + 1, 0x0B)?;
    // outb(&mut f, base_port, 0x60)?;
    // let a = inb(&mut f, base_port + 1)?;
    // outb(&mut f, base_port, 0x61)?;
    // let b = inb(&mut f, base_port + 1)?;
    // println!("{:x} {:x}", a, b);

    let r = run(&mut f, base_port, matches);
    // Disable the advanced mode.
    outb(&mut f, base_port, 0xAA).chain_err(|| "could not disable advanced mode")?;
    r.chain_err(|| "could not set the colour")
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .arg(Arg::with_name("IGNORECHECK").long("ignore-check")
             .help("ignore the result of sI/O identification check"))
        .arg(Arg::with_name("BASEPORT").long("base-port").default_value("4e")
             .help("base port to use. Values known to be in use are 4e and 2e"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run_wrap(matches) {
        let _ = writeln!(::std::io::stderr(), "error: {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<|endoftext|>


<commit_before>// TODO
// when sending too much data, size gets printed. it is not beeing sent a u8, it is being sent as a string i think
// add nickname
// modularize
// print list of peers (exclude myself or print myself and state it is me)
// add /help
//     Help:          -h --help
//    Host IP:       -H --host {host IP}
//    Broadcast IP:  -B --broadcast {broadcast IP}
//    RPC Port:      -P --port {port}
// add encryption
// add rooms, by default join lobby

use std::net::UdpSocket;
use std::io;
use std::io::Write;
use std::thread;
use std::time::Duration;
use std::process;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use std::time::SystemTime;

fn main () {
    let peers = Arc::new(Mutex::new(HashMap::new()));

    let peers_sender = peers.clone();
    let sender = thread::spawn(move || {
        let socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");
        socket.set_broadcast(true).expect("set_broadcast call failed");

        print!("> ");
        io::stdout().flush().unwrap();

        loop {
            let mut input = String::new();
            match io::stdin().read_line(&mut input) {
                Ok(_) => {
                    input.pop();

                    process(&socket, input);
                    io::stdout().flush().unwrap();
                   // println!("peers {:?}", *peers_sender.lock().unwrap()); //TODO move this to the process of the sender when writting /peers
                }
                Err(error) =>
                    println!("error: {}", error),
            }
        }
    });

    let prober = thread::spawn(|| {
        let socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");
        socket.set_broadcast(true).expect("set_broadcast call failed");
        loop {
            let message = format!("P");
            socket.send_to(&message.into_bytes(), "255.255.255.255:4041").expect("couldn't send data");
            thread::sleep(Duration::from_millis(5000)); //TODO put in seconds
        }
    });

    let peers_rec = peers.clone();
    let receiver = thread::spawn(move || {
        let socket = UdpSocket::bind("0.0.0.0:4041").expect("couldn't bind to address");

        loop {
            let mut buffer = [0; 512];
            let (received_bytes, source) = socket.recv_from(&mut buffer)
                .expect("Didn't receive data");

            match std::str::from_utf8(&buffer[0..1]).unwrap() {
                "M" => {
                    println!("{}: {}", source, std::str::from_utf8(&buffer[2..received_bytes]).unwrap());
                    io::stdout().flush().unwrap();
                    print!("> ");
                    io::stdout().flush().unwrap();
                }

                "P" => {
                    //println!("probe with source {}", source);
                    peers_rec.lock().unwrap().insert(source, SystemTime::now()); //TODO insert only seconds and IP
                    // clean hosts that have not received content for more than x seconds
                }

                _ =>  {
                }
            }

        }
    });

    receiver.join().unwrap();
    sender.join().unwrap();
    prober.join().unwrap();
}

fn process(socket: &UdpSocket, input: String) {
    match input.as_ref() {
        "" => {

        },

        "/quit" => {
            process::exit(0x0f00);
        },

        "/peers" => {
            //TODO print list of
        },

        "/rooms" => {
        },

        "/help" => {
        },

        _ => {
            let size = input.len();
            let message = format!("M{}{}", size, input);
            socket.send_to(&message.into_bytes(), "255.255.255.255:4041").expect("couldn't send data");
        }
    }
    ()
}
<commit_msg>Add more ><commit_after>// TODO
// when sending too much data, size gets printed. it is not beeing sent a u8, it is being sent as a string i think
// add nickname
// modularize
// print list of peers (exclude myself or print myself and state it is me)
// add /help
//     Help:          -h --help
//    Host IP:       -H --host {host IP}
//    Broadcast IP:  -B --broadcast {broadcast IP}
//    RPC Port:      -P --port {port}
// add encryption
// add rooms, by default join lobby

use std::net::UdpSocket;
use std::io;
use std::io::Write;
use std::thread;
use std::time::Duration;
use std::process;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use std::time::SystemTime;

fn main () {
    let peers = Arc::new(Mutex::new(HashMap::new()));

    let peers_sender = peers.clone();
    let sender = thread::spawn(move || {
        let socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");
        socket.set_broadcast(true).expect("set_broadcast call failed");

        print!(">>> ");
        io::stdout().flush().unwrap();

        loop {
            let mut input = String::new();
            match io::stdin().read_line(&mut input) {
                Ok(_) => {
                    input.pop();

                    process(&socket, input);
                    io::stdout().flush().unwrap();
                   // println!("peers {:?}", *peers_sender.lock().unwrap()); //TODO move this to the process of the sender when writting /peers
                }
                Err(error) =>
                    println!("error: {}", error),
            }
        }
    });

    let prober = thread::spawn(|| {
        let socket = UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");
        socket.set_broadcast(true).expect("set_broadcast call failed");
        loop {
            let message = format!("P");
            socket.send_to(&message.into_bytes(), "255.255.255.255:4041").expect("couldn't send data");
            thread::sleep(Duration::from_millis(5000)); //TODO put in seconds
        }
    });

    let peers_rec = peers.clone();
    let receiver = thread::spawn(move || {
        let socket = UdpSocket::bind("0.0.0.0:4041").expect("couldn't bind to address");

        loop {
            let mut buffer = [0; 512];
            let (received_bytes, source) = socket.recv_from(&mut buffer)
                .expect("Didn't receive data");

            match std::str::from_utf8(&buffer[0..1]).unwrap() {
                "M" => {
                    println!("{}: {}", source, std::str::from_utf8(&buffer[2..received_bytes]).unwrap());
                    io::stdout().flush().unwrap();
                    print!(">>> ");
                    io::stdout().flush().unwrap();
                }

                "P" => {
                    //println!("probe with source {}", source);
                    peers_rec.lock().unwrap().insert(source, SystemTime::now()); //TODO insert only seconds and IP
                    // clean hosts that have not received content for more than x seconds
                }

                _ =>  {
                }
            }

        }
    });

    receiver.join().unwrap();
    sender.join().unwrap();
    prober.join().unwrap();
}

fn process(socket: &UdpSocket, input: String) {
    match input.as_ref() {
        "" => {

        },

        "/quit" => {
            process::exit(0x0f00);
        },

        "/peers" => {
            //TODO print list of
        },

        "/rooms" => {
        },

        "/help" => {
        },

        _ => {
            let size = input.len();
            let message = format!("M{}{}", size, input);
            socket.send_to(&message.into_bytes(), "255.255.255.255:4041").expect("couldn't send data");
        }
    }
    ()
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

extern crate catchit;

use catchit::{Engine, Object, CollisionShape, ObstacleKind, State, Extent};
use catchit::Scalar as CatchitScalar;

use piston::window::WindowSettings;
use piston::event::{ RenderArgs, UpdateArgs, Events, RenderEvent, UpdateEvent, MouseCursorEvent,
                     EventLoop, PressEvent, ReleaseEvent };
use piston::input::{Button, Key, MouseButton};
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::character::CharacterCache;
use graphics::math::Scalar;

pub struct App {
    gl: GlGraphics,
    engine: Engine,
    last_state: Option<State>,
    field_border_y: Scalar,
    max_score: u32,
    text_height: f64,
    tries: u32,
    font_fira_bold: GlyphCache<'static>
}

const WIDTH: u16 = 1024;
const HEIGHT: u16 = 768;
const UPDATES_PER_SECOND: u64 = 30;
const FONT_SIZE: u32 = 22;
const HUD_SPACE: Scalar = 1.0 / 8.0;
const NEW_GAME_TEXT: &'static str = "Press SPACE for new game";

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::{ rectangle, ellipse, clear , Transformed, Text, Line };
        use graphics::math::Matrix2d;
        use graphics::types::Color;

        const BG:    Color = [1.0, 204.0 / 255.0, 0.0, 1.0];
        const BLACK: Color = [0.2, 0.2, 0.2, 1.0];
        const WHITE: Color = [0.8, 0.8, 0.8, 1.0];
        const BLUE:  Color = [0.0, 0.0, 0.8, 1.0];
        const RED:   Color = [204.0 / 255.0, 0.0, 0.0, 1.0];

        let square = rectangle::square(0.0, 0.0, 1.0);
        let s = self.engine.state();
        let game_over = self.game_over();
        let font_fira_bold = &mut self.font_fira_bold;
        let text_height = self.text_height;
        let max_score = self.max_score;
        let tries = self.tries;
        let field_border_y = self.field_border_y;
        let last_state = &self.last_state;

        self.gl.draw(args.viewport(), |c, gl| {
            let draw_object = |obj: &Object, gl: &mut GlGraphics, color: Color| {
                let transform = c.transform.trans(obj.pos[0] - obj.half_size,
                                                  obj.pos[1] - obj.half_size)
                                           .scale(obj.half_size * 2.0, obj.half_size * 2.0);
                match obj.shape {
                    CollisionShape::Square => rectangle(color, square, transform, gl),
                    CollisionShape::Circle => ellipse(color, square, transform, gl),
                }
            };

            fn blend_color(c1: Color, c2: Color, blend: CatchitScalar) -> Color {
                let mut c = c1;
                for i in (0..3) {
                    c[i] = blend as f32 * c1[i] + (1.0 - blend as f32) * c2[i];
                }
                c
            }

            clear(BG, gl);

            let text = Text::colored(BLACK, FONT_SIZE);
            let text_matrix = |x: Scalar| -> Matrix2d {
                c.transform.trans(x, HEIGHT as Scalar - text_height / 2.0)
            };

            if let Some(ref s) = s.as_ref().or(last_state.as_ref()) {
                let deadly_color = blend_color(BLACK, BG, s.obstacle_opacity.current);
                let hunter_color = blend_color(RED, BLUE, 1.0 - s.attracting_force.current
                                                                / s.attracting_force.v2);

                for obstacle in &s.obstacles {
                    let color = match obstacle.kind {
                        ObstacleKind::Deadly => deadly_color,
                        ObstacleKind::AttractiveForceSwitch => BLUE,
                        ObstacleKind::InvisibiltySwitch => WHITE,
                    };
                    draw_object(&obstacle.object, gl, color);
                }

                draw_object(&s.prey, gl, RED);
                draw_object(&s.hunter.object, gl, hunter_color);

                text.draw(&format!("Score: {}", s.score), font_fira_bold,
                                                          &c.draw_state,
                                                          text_matrix(WIDTH as Scalar
                                                                      * HUD_SPACE * 4.5),
                                                          gl);

                text.draw(&format!("Multiplier: {:.2}", s.score_coeff), font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 6.0),
                                                         gl);
            }

            if game_over {
                let w = text_width(font_fira_bold, NEW_GAME_TEXT) / 2.0;
                text.draw(NEW_GAME_TEXT, font_fira_bold, &c.draw_state,
                                          c.transform.trans(WIDTH as Scalar / 2.0 - w,
                                                           HEIGHT as Scalar / 2.0),
                                          gl);
                text.draw("Use LMB for repelling force", font_fira_bold, &c.draw_state,
                                          c.transform.trans(WIDTH as Scalar / 2.0 - w,
                                                           HEIGHT as Scalar / 2.0
                                                           + text_height
                                                           + text_height * 0.4),
                                          gl);
            }

            // Draw HUD
            ////////////
            let line = Line::new(BLACK, 1.0);

            line.draw([0.0, 0.0, WIDTH as Scalar, 0.0], &c.draw_state,
                                                         c.transform.trans(0.0, field_border_y),
                                                         gl);

            text.draw(&format!("Best Score: {}", max_score), font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 1.0),
                                                         gl);

            text.draw(&format!("Tries: {}", tries),      font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 3.0),
                                                         gl);

        });
    }

    fn game_over(&self) -> bool {
        self.last_state.is_some()
    }

    fn update(&mut self, args: &UpdateArgs) {
        if let Err(state) = self.engine.update(args.dt) {
            if state.score > self.max_score {
                self.max_score += state.score;
            }
            self.tries += 1;
            self.last_state = Some(state);
        }
    }
}

fn compute_field(width: u16, height: u16, text_height: Scalar) -> Extent {
    [width as CatchitScalar, height as CatchitScalar
                                    - (text_height * 2.0)]
}

fn text_width(cache: &mut GlyphCache<'static>, text: &str) -> Scalar {
    let mut w = 0.0;
    for c in text.chars() {
        w += cache.character(FONT_SIZE, c).width();
    }
    w
}

fn main() {
    // Create an Glutin window.
    let window = Window::new(
        WindowSettings::new(
            "catchit",
            [WIDTH as u32, HEIGHT as u32]
        )
        .exit_on_esc(true)
        .vsync(true)
        .samples(1)
    );

    let mut app = {
        let gl = GlGraphics::new(OpenGL::_3_2);
        let mut glyphs = GlyphCache::from_bytes(include_bytes!("../res/FiraMono-Bold.ttf"))
                                                              .unwrap();
        let text_height = glyphs.character(FONT_SIZE, 'S').top();
        let field = compute_field(WIDTH, HEIGHT, text_height);

        // Create a new game and run it.
        App {
            gl: gl,
            engine: Engine::from_field(field),
            last_state: None,
            field_border_y: field[1],
            text_height: text_height,
            tries: 0,
            max_score: 0,
            font_fira_bold: glyphs,
        }
    };

    for e in window.events()
                   .max_fps(UPDATES_PER_SECOND)
                   .ups(UPDATES_PER_SECOND) {
        if let Some(pos) = e.mouse_cursor_args() {
            app.engine.set_hunter_pos(pos);
        }

        match e.press_args() {
            Some(Button::Keyboard(Key::Space)) if app.game_over() => {
                app.last_state = None;
                app.engine.reset(compute_field(WIDTH, HEIGHT, app.text_height))
            },
            Some(Button::Mouse(MouseButton::Left)) => {
                app.engine.set_hunter_force(true);
            }
            _ => {},
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.release_args() {
            app.engine.set_hunter_force(false);
        }

        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<commit_msg>chore(main): run at 60fps with oversampling<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

extern crate catchit;

use catchit::{Engine, Object, CollisionShape, ObstacleKind, State, Extent};
use catchit::Scalar as CatchitScalar;

use piston::window::WindowSettings;
use piston::event::{ RenderArgs, UpdateArgs, Events, RenderEvent, UpdateEvent, MouseCursorEvent,
                     EventLoop, PressEvent, ReleaseEvent };
use piston::input::{Button, Key, MouseButton};
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::character::CharacterCache;
use graphics::math::Scalar;

pub struct App {
    gl: GlGraphics,
    engine: Engine,
    last_state: Option<State>,
    field_border_y: Scalar,
    max_score: u32,
    text_height: f64,
    tries: u32,
    font_fira_bold: GlyphCache<'static>
}

const WIDTH: u16 = 1024;
const HEIGHT: u16 = 768;
const UPDATES_PER_SECOND: u64 = 60;
const FONT_SIZE: u32 = 22;
const HUD_SPACE: Scalar = 1.0 / 8.0;
const NEW_GAME_TEXT: &'static str = "Press SPACE for new game";

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::{ rectangle, ellipse, clear , Transformed, Text, Line };
        use graphics::math::Matrix2d;
        use graphics::types::Color;

        const BG:    Color = [1.0, 204.0 / 255.0, 0.0, 1.0];
        const BLACK: Color = [0.2, 0.2, 0.2, 1.0];
        const WHITE: Color = [0.8, 0.8, 0.8, 1.0];
        const BLUE:  Color = [0.0, 0.0, 0.8, 1.0];
        const RED:   Color = [204.0 / 255.0, 0.0, 0.0, 1.0];

        let square = rectangle::square(0.0, 0.0, 1.0);
        let s = self.engine.state();
        let game_over = self.game_over();
        let font_fira_bold = &mut self.font_fira_bold;
        let text_height = self.text_height;
        let max_score = self.max_score;
        let tries = self.tries;
        let field_border_y = self.field_border_y;
        let last_state = &self.last_state;

        self.gl.draw(args.viewport(), |c, gl| {
            let draw_object = |obj: &Object, gl: &mut GlGraphics, color: Color| {
                let transform = c.transform.trans(obj.pos[0] - obj.half_size,
                                                  obj.pos[1] - obj.half_size)
                                           .scale(obj.half_size * 2.0, obj.half_size * 2.0);
                match obj.shape {
                    CollisionShape::Square => rectangle(color, square, transform, gl),
                    CollisionShape::Circle => ellipse(color, square, transform, gl),
                }
            };

            fn blend_color(c1: Color, c2: Color, blend: CatchitScalar) -> Color {
                let mut c = c1;
                for i in (0..3) {
                    c[i] = blend as f32 * c1[i] + (1.0 - blend as f32) * c2[i];
                }
                c
            }

            clear(BG, gl);

            let text = Text::colored(BLACK, FONT_SIZE);
            let text_matrix = |x: Scalar| -> Matrix2d {
                c.transform.trans(x, HEIGHT as Scalar - text_height / 2.0)
            };

            if let Some(ref s) = s.as_ref().or(last_state.as_ref()) {
                let deadly_color = blend_color(BLACK, BG, s.obstacle_opacity.current);
                let hunter_color = blend_color(RED, BLUE, 1.0 - s.attracting_force.current
                                                                / s.attracting_force.v2);

                for obstacle in &s.obstacles {
                    let color = match obstacle.kind {
                        ObstacleKind::Deadly => deadly_color,
                        ObstacleKind::AttractiveForceSwitch => BLUE,
                        ObstacleKind::InvisibiltySwitch => WHITE,
                    };
                    draw_object(&obstacle.object, gl, color);
                }

                draw_object(&s.prey, gl, RED);
                draw_object(&s.hunter.object, gl, hunter_color);

                text.draw(&format!("Score: {}", s.score), font_fira_bold,
                                                          &c.draw_state,
                                                          text_matrix(WIDTH as Scalar
                                                                      * HUD_SPACE * 4.5),
                                                          gl);

                text.draw(&format!("Multiplier: {:.2}", s.score_coeff), font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 6.0),
                                                         gl);
            }

            if game_over {
                let w = text_width(font_fira_bold, NEW_GAME_TEXT) / 2.0;
                text.draw(NEW_GAME_TEXT, font_fira_bold, &c.draw_state,
                                          c.transform.trans(WIDTH as Scalar / 2.0 - w,
                                                           HEIGHT as Scalar / 2.0),
                                          gl);
                text.draw("Use LMB for repelling force", font_fira_bold, &c.draw_state,
                                          c.transform.trans(WIDTH as Scalar / 2.0 - w,
                                                           HEIGHT as Scalar / 2.0
                                                           + text_height
                                                           + text_height * 0.4),
                                          gl);
            }

            // Draw HUD
            ////////////
            let line = Line::new(BLACK, 1.0);

            line.draw([0.0, 0.0, WIDTH as Scalar, 0.0], &c.draw_state,
                                                         c.transform.trans(0.0, field_border_y),
                                                         gl);

            text.draw(&format!("Best Score: {}", max_score), font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 1.0),
                                                         gl);

            text.draw(&format!("Tries: {}", tries),      font_fira_bold,
                                                         &c.draw_state,
                                                         text_matrix(WIDTH as Scalar
                                                                     * HUD_SPACE * 3.0),
                                                         gl);

        });
    }

    fn game_over(&self) -> bool {
        self.last_state.is_some()
    }

    fn update(&mut self, args: &UpdateArgs) {
        if let Err(state) = self.engine.update(args.dt) {
            if state.score > self.max_score {
                self.max_score += state.score;
            }
            self.tries += 1;
            self.last_state = Some(state);
        }
    }
}

fn compute_field(width: u16, height: u16, text_height: Scalar) -> Extent {
    [width as CatchitScalar, height as CatchitScalar
                                    - (text_height * 2.0)]
}

fn text_width(cache: &mut GlyphCache<'static>, text: &str) -> Scalar {
    let mut w = 0.0;
    for c in text.chars() {
        w += cache.character(FONT_SIZE, c).width();
    }
    w
}

fn main() {
    // Create an Glutin window.
    let window = Window::new(
        WindowSettings::new(
            "catchit",
            [WIDTH as u32, HEIGHT as u32]
        )
        .exit_on_esc(true)
        .vsync(true)
        .samples(16)
    );

    let mut app = {
        let gl = GlGraphics::new(OpenGL::_3_2);
        let mut glyphs = GlyphCache::from_bytes(include_bytes!("../res/FiraMono-Bold.ttf"))
                                                              .unwrap();
        let text_height = glyphs.character(FONT_SIZE, 'S').top();
        let field = compute_field(WIDTH, HEIGHT, text_height);

        // Create a new game and run it.
        App {
            gl: gl,
            engine: Engine::from_field(field),
            last_state: None,
            field_border_y: field[1],
            text_height: text_height,
            tries: 0,
            max_score: 0,
            font_fira_bold: glyphs,
        }
    };

    for e in window.events()
                   .max_fps(UPDATES_PER_SECOND)
                   .ups(UPDATES_PER_SECOND) {
        if let Some(pos) = e.mouse_cursor_args() {
            app.engine.set_hunter_pos(pos);
        }

        match e.press_args() {
            Some(Button::Keyboard(Key::Space)) if app.game_over() => {
                app.last_state = None;
                app.engine.reset(compute_field(WIDTH, HEIGHT, app.text_height))
            },
            Some(Button::Mouse(MouseButton::Left)) => {
                app.engine.set_hunter_force(true);
            }
            _ => {},
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.release_args() {
            app.engine.set_hunter_force(false);
        }

        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<|endoftext|>


<commit_before>extern crate base64;

extern crate byteorder;

extern crate hyper;
extern crate hyper_native_tls;

extern crate rayon;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

extern crate pem;

#[macro_use]
extern crate prettytable;

use std::{env, process};
use std::fs::File;
use std::io::{Read, Write};

use byteorder::{BigEndian, WriteBytesExt};

use rayon::iter::{IntoParallelRefIterator, ParallelIterator};

#[derive(Deserialize)]
struct LogsResponseLogs {
    description: String,
    url: String,
    operated_by: Vec<u32>,
    disqualified_at: Option<u64>,
}

#[derive(Deserialize)]
struct LogsResponseOperators {
    name: String,
    id: u32,
}

#[derive(Deserialize)]
struct LogsResponse {
    logs: Vec<LogsResponseLogs>,
    operators: Vec<LogsResponseOperators>,
}

#[derive(Debug, Clone)]
struct Log {
    description: String,
    url: String,
    is_google: bool,
}

const LOG_LIST_URL: &'static str = "https://www.gstatic.com/ct/log_list/log_list.json";

fn fetch_trusted_ct_logs(http_client: &hyper::Client) -> Vec<Log> {
    let response = http_client.get(LOG_LIST_URL).send().unwrap();
    let logs_response: LogsResponse = serde_json::from_reader(response).unwrap();

    let mut google_id = None;
    for operator in logs_response.operators {
        if operator.name == "Google" {
            google_id = Some(operator.id);
            break;
        }
    }

    let mut logs = vec![];
    for log in logs_response.logs {
        if log.disqualified_at.is_some() {
            continue;
        }
        logs.push(Log {
            url: log.url,
            description: log.description,
            is_google: log.operated_by.contains(&google_id.unwrap()),
        });
    }

    return logs;
}

#[derive(Debug, Deserialize)]
struct SignedCertificateTimestamp {
    sct_version: u8,
    id: String,
    timestamp: u64,
    extensions: String,
    signature: String,
}

impl SignedCertificateTimestamp {
    fn to_raw_bytes(&self) -> Vec<u8> {
        let mut b = Vec::new();
        b.write_u8(self.sct_version).unwrap();

        let log_id = base64::decode(&self.id).unwrap();
        b.write(&log_id).unwrap();

        b.write_u64::<BigEndian>(self.timestamp).unwrap();

        let extensions = base64::decode(&self.extensions).unwrap();
        assert!(extensions.len() <= 65535);
        b.write_u16::<BigEndian>(extensions.len() as u16).unwrap();
        b.write(&extensions).unwrap();

        let signature = base64::decode(&self.signature).unwrap();
        b.write(&signature).unwrap();

        return b;
    }
}

fn submit_to_log(http_client: &hyper::Client,
                 url: &str,
                 payload: &[u8])
                 -> Option<SignedCertificateTimestamp> {
    let mut url = "https://".to_string() + url;
    if !url.ends_with("/") {
        url += "/";
    }
    url += "ct/v1/add-chain";
    let response = http_client.post(&url)
        .body(hyper::client::Body::BufBody(payload, payload.len()))
        .header(hyper::header::ContentType::json())
        .send();
    let response = match response {
        Ok(r) => r,
        // TODO: maybe not all of these should be silently ignored.
        Err(_) => return None,
    };

    // 400, 403, and probably some others generally indicate a log doesn't accept certs from this
    // root, or that the log isn't accepting new submissions.
    if response.status.is_client_error() {
        return None;
    }

    let parsed_response: SignedCertificateTimestamp = serde_json::from_reader(response).unwrap();

    return Some(parsed_response);
}

#[derive(Serialize)]
struct AddChainRequest {
    chain: Vec<String>,
}

fn submit_cert_to_logs(http_client: &hyper::Client,
                       logs: &[Log],
                       cert: Vec<Vec<u8>>)
                       -> Vec<(Log, SignedCertificateTimestamp)> {
    let payload = serde_json::to_vec(&AddChainRequest {
            chain: cert.iter().map(|r| base64::encode(r)).collect(),
        })
        .unwrap();

    // TODO: At least some of this cloning and filtering has got to be nonsense...
    let scts: Vec<(&Log, SignedCertificateTimestamp)> = logs.par_iter()
        .map(|ref log| {
            let sct = submit_to_log(http_client, &log.url, &payload);
            return (log.clone(), sct);
        })
        .filter(|&(_, ref sct)| sct.is_some())
        .map(|(log, sct)| (log, sct.unwrap()))
        .collect();
    return scts.into_iter().map(|(log, sct)| (log.clone(), sct)).collect();
}

fn main() {
    let path = match env::args().skip(1).next() {
        Some(p) => p,
        None => {
            println!("Usage: {} <path/to/chain.pem>", env::args().next().unwrap());
            process::exit(1);
        }
    };

    let mut contents = String::new();
    File::open(path).unwrap().read_to_string(&mut contents).unwrap();

    let chain = pem::parse_many(contents)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect();

    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    let logs = fetch_trusted_ct_logs(&http_client);

    let scts = submit_cert_to_logs(&http_client, &logs, chain);

    let mut table = prettytable::Table::new();
    table.add_row(row!["Log", "SCT"]);
    for (log, sct) in scts {
        table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
    }
    table.printstd();
}
<commit_msg>cleanups<commit_after>extern crate base64;

extern crate byteorder;

extern crate hyper;
extern crate hyper_native_tls;

extern crate rayon;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

extern crate pem;

#[macro_use]
extern crate prettytable;

use std::{env, process};
use std::fs::File;
use std::io::{Read, Write};

use byteorder::{BigEndian, WriteBytesExt};

use rayon::iter::{IntoParallelRefIterator, ParallelIterator};

#[derive(Deserialize)]
struct LogsResponseLogs {
    description: String,
    url: String,
    operated_by: Vec<u32>,
    disqualified_at: Option<u64>,
}

#[derive(Deserialize)]
struct LogsResponseOperators {
    name: String,
    id: u32,
}

#[derive(Deserialize)]
struct LogsResponse {
    logs: Vec<LogsResponseLogs>,
    operators: Vec<LogsResponseOperators>,
}

#[derive(Debug, Clone)]
struct Log {
    description: String,
    url: String,
    is_google: bool,
}

const LOG_LIST_URL: &'static str = "https://www.gstatic.com/ct/log_list/log_list.json";

fn fetch_trusted_ct_logs(http_client: &hyper::Client) -> Vec<Log> {
    let response = http_client.get(LOG_LIST_URL).send().unwrap();
    let logs_response: LogsResponse = serde_json::from_reader(response).unwrap();

    let mut google_id = None;
    for operator in logs_response.operators {
        if operator.name == "Google" {
            google_id = Some(operator.id);
            break;
        }
    }

    let mut logs = vec![];
    for log in logs_response.logs {
        if log.disqualified_at.is_some() {
            continue;
        }
        logs.push(Log {
            url: log.url,
            description: log.description,
            is_google: log.operated_by.contains(&google_id.unwrap()),
        });
    }

    return logs;
}

#[derive(Debug, Deserialize)]
struct SignedCertificateTimestamp {
    sct_version: u8,
    id: String,
    timestamp: u64,
    extensions: String,
    signature: String,
}

impl SignedCertificateTimestamp {
    fn to_raw_bytes(&self) -> Vec<u8> {
        let mut b = Vec::new();
        b.write_u8(self.sct_version).unwrap();

        let log_id = base64::decode(&self.id).unwrap();
        b.write(&log_id).unwrap();

        b.write_u64::<BigEndian>(self.timestamp).unwrap();

        let extensions = base64::decode(&self.extensions).unwrap();
        assert!(extensions.len() <= 65535);
        b.write_u16::<BigEndian>(extensions.len() as u16).unwrap();
        b.write(&extensions).unwrap();

        let signature = base64::decode(&self.signature).unwrap();
        b.write(&signature).unwrap();

        return b;
    }
}

fn submit_to_log(http_client: &hyper::Client,
                 url: &str,
                 payload: &[u8])
                 -> Option<SignedCertificateTimestamp> {
    let mut url = "https://".to_string() + url;
    if !url.ends_with("/") {
        url += "/";
    }
    url += "ct/v1/add-chain";
    let response = http_client.post(&url)
        .body(hyper::client::Body::BufBody(payload, payload.len()))
        .header(hyper::header::ContentType::json())
        .send();
    let response = match response {
        Ok(r) => r,
        // TODO: maybe not all of these should be silently ignored.
        Err(_) => return None,
    };

    // 400, 403, and probably some others generally indicate a log doesn't accept certs from this
    // root, or that the log isn't accepting new submissions.
    if response.status.is_client_error() {
        return None;
    }

    let parsed_response: SignedCertificateTimestamp = serde_json::from_reader(response).unwrap();

    return Some(parsed_response);
}

#[derive(Serialize)]
struct AddChainRequest {
    chain: Vec<String>,
}

fn submit_cert_to_logs<'a>(http_client: &hyper::Client,
                           logs: &'a [Log],
                           cert: Vec<Vec<u8>>)
                           -> Vec<(&'a Log, SignedCertificateTimestamp)> {
    let payload = serde_json::to_vec(&AddChainRequest {
            chain: cert.iter().map(|r| base64::encode(r)).collect(),
        })
        .unwrap();

    return logs.par_iter()
        .map(|ref log| {
            let sct = submit_to_log(http_client, &log.url, &payload);
            return (log.clone(), sct);
        })
        .filter(|&(_, ref sct)| sct.is_some())
        .map(|(log, sct)| (log, sct.unwrap()))
        .collect();
}

fn main() {
    let path = match env::args().skip(1).next() {
        Some(p) => p,
        None => {
            println!("Usage: {} <path/to/chain.pem>", env::args().next().unwrap());
            process::exit(1);
        }
    };

    let mut contents = String::new();
    File::open(path).unwrap().read_to_string(&mut contents).unwrap();

    let chain = pem::parse_many(contents)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect();

    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    let logs = fetch_trusted_ct_logs(&http_client);

    let scts = submit_cert_to_logs(&http_client, &logs, chain);

    let mut table = prettytable::Table::new();
    table.add_row(row!["Log", "SCT"]);
    for (log, sct) in scts {
        table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
    }
    table.printstd();
}
<|endoftext|>


<commit_before>extern crate image;
extern crate rand;
extern crate docopt;
extern crate "rustc-serialize" as rustc_serialize;
extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;
use rand::StdRng;
use docopt::Docopt;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: usize = 800;
static HEIGHT: usize = 600;
static USAGE: &'static str = "
Usage: tray_rust [options]

Options:
    -o <file>   Specify the output file to save the image. Supported formats are
                PNG, JPG, PPM and BMP (although the BMP won't currently be picked up with the flag).
                Default is 'out.png'.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_o: Option<String>,
}

/// Threads are each sent a sender end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the render target
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::LowDiscrepancy::new(queue.block_dim(), 64);
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    let mut rng = match StdRng::new() {
        Ok(r) => r,
        Err(e) => { println!("Failed to get StdRng, {}", e); return }
    };
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos, &mut rng);
            for s in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(s);
                if let Some(hit) = scene.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit, &mut sampler, &mut rng);
                    samples.push((s.0, s.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {:?}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Spawn `n` worker threads to render the scene in parallel. Returns the receive end
/// of the channel where the threads will write their samples so that the receiver
/// can write these samples to the render target
fn spawn_workers(pool: &TaskPool, n: usize, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    for _ in 0..n {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render the scene in parallel to the render target
fn render_parallel(rt: &mut film::RenderTarget){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

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

    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let d = Duration::span(|| render_parallel(&mut rt));
    println!("Rendering took {}ms", d.num_milliseconds());
    let img = rt.get_render();
    let out_file = match args.flag_o {
        Some(f) => f,
        None => "out.png".to_string(),
    };
    match image::save_buffer(&Path::new(out_file), &img[..], WIDTH as u32, HEIGHT as u32, image::RGB(8)) {
        Ok(_) => {},
        Err(e) => println!("Error saving image, {}", e),
    };
}

<commit_msg>Add option to specify number of threads to use<commit_after>extern crate image;
extern crate rand;
extern crate docopt;
extern crate "rustc-serialize" as rustc_serialize;
extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;
use std::os;
use rand::StdRng;
use docopt::Docopt;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: usize = 800;
static HEIGHT: usize = 600;
static USAGE: &'static str = "
Usage: tray_rust [options]

Options:
  -o <file>     Specify the output file to save the image. Supported formats are
                PNG, JPG, PPM and BMP (although the BMP won't currently be picked up with the flag).
                Default is 'out.png'.
  -n <number>   Specify the number of threads to use for rendering. Defaults to the number of cores
                on the system.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_o: Option<String>,
    flag_n: Option<usize>,
}

/// Threads are each sent a sender end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the render target
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::LowDiscrepancy::new(queue.block_dim(), 64);
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    let mut rng = match StdRng::new() {
        Ok(r) => r,
        Err(e) => { println!("Failed to get StdRng, {}", e); return }
    };
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos, &mut rng);
            for s in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(s);
                if let Some(hit) = scene.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit, &mut sampler, &mut rng);
                    samples.push((s.0, s.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {:?}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Spawn `n` worker threads to render the scene in parallel. Returns the receive end
/// of the channel where the threads will write their samples so that the receiver
/// can write these samples to the render target
fn spawn_workers(pool: &TaskPool, n: usize, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    for _ in 0..n {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render the scene in parallel to the render target
fn render_parallel(rt: &mut film::RenderTarget, n: usize){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

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

    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let n = match args.flag_n {
        Some(n) => n,
        None => os::num_cpus(),
    };
    let d = Duration::span(|| render_parallel(&mut rt, n));
    println!("Rendering took {}ms", d.num_milliseconds());
    let img = rt.get_render();
    let out_file = match args.flag_o {
        Some(f) => f,
        None => "out.png".to_string(),
    };
    match image::save_buffer(&Path::new(out_file), &img[..], WIDTH as u32, HEIGHT as u32, image::RGB(8)) {
        Ok(_) => {},
        Err(e) => println!("Error saving image, {}", e),
    };
}

<|endoftext|>


<commit_before>#[macro_use] extern crate nickel;

// use nickel::Nickel;

use std::collections::HashMap;
use nickel::{Nickel, HttpRouter, StaticFilesHandler};

fn main() {
    let mut server = Nickel::new();

     /*
     server.utilize(router! {
         get "**" => |_req, _res| {
             "Hello world! Good bye!"
         }
     });
     */

    server.utilize(StaticFilesHandler::new("assets/"));

    server.get("/", middleware! {|_, response|
        let mut data = HashMap::new();
        data.insert("color", "Green");
        data.insert("name", "California Apple");
        data.insert("price", "2.50");
        return response.render("assets/hello.tpl", &data);
    });

     let _ = server.listen("127.0.0.1:6767");
 }
<commit_msg>add 'Piq' and 'Omino'<commit_after>#[macro_use] extern crate nickel;

// use nickel::Nickel;

use std::collections::HashMap;
use nickel::{Nickel, HttpRouter, StaticFilesHandler};

/*
BriqsDBでの'Briq'という概念は、最初はコンスセルの別名に過ぎなかったのだが、
文字列や任意のバイト列をそれで表現したいと思った時に、'128bitの塊'という役割も背負うことになった。
そのせいで、自分の中で混乱が生じているのだ。

果たして、上記のどちらの概念が、よりプリミティブなのか？
*/
trait Piq {
    fn p(&self);
    fn q(&self);
}

/*
ということで、基本はポインタとなる64bitの塊ということにしました。
上記のどちらの概念の間に、あるもの。dominoにこだわるのは、少しやめる感じでしょうか。
*/
struct Omino {
    bytes: [u8; 8]
}

fn main() {
    let mut server = Nickel::new();

    let o = Omino { bytes:[0; 8] };

     /*
     server.utilize(router! {
         get "**" => |_req, _res| {
             "Hello world! Good bye!"
         }
     });
     */

    server.utilize(StaticFilesHandler::new("assets/"));

    server.get("/", middleware! {|_, response|
        let mut data = HashMap::new();
        data.insert("color", "Green");
        data.insert("name", "California Apple");
        data.insert("price", "2.50");
        return response.render("assets/hello.tpl", &data);
    });

     let _ = server.listen("127.0.0.1:6767");
 }
<|endoftext|>


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(clippy::missing_docs_in_private_items)]

use rustc_tools_util::*;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(std::env::args().skip(2)) {
        std::process::exit(code);
    }
}

fn process<I>(mut old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["check".to_owned()];

    let mut found_dashes = false;
    for arg in old_args.by_ref() {
        found_dashes |= arg == "--";
        if found_dashes {
            break;
        }
        args.push(arg);
    }

    let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

    let mut path = std::env::current_exe()
        .expect("current executable path invalid")
        .with_file_name("clippy-driver");
    if cfg!(windows) {
        path.set_extension("exe");
    }

    let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
        .map(|_| {
            std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                || {
                    let mut fallback = std::ffi::OsString::new();
                    fallback.push("clippy_dogfood");
                    fallback
                },
                |d| {
                    std::path::PathBuf::from(d)
                        .join("target")
                        .join("dogfood")
                        .into_os_string()
                },
            )
        })
        .map(|p| ("CARGO_TARGET_DIR", p));

    // Run the dogfood tests directly on nightly cargo. This is required due
    // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
    if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
        args.insert(0, "+nightly".to_string());
    }

    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WRAPPER", path)
        .env("CLIPPY_ARGS", clippy_args)
        .envs(target_dir)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<commit_msg>Drive-by cleanups to cargo-clippy. No functional change.<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(clippy::missing_docs_in_private_items)]

use rustc_tools_util::*;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(std::env::args().skip(2)) {
        std::process::exit(code);
    }
}

fn process<I>(mut old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["check".to_owned()];

    for arg in old_args.by_ref() {
        if arg == "--" {
            break;
        }
        args.push(arg);
    }

    let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

    let mut path = std::env::current_exe()
        .expect("current executable path invalid")
        .with_file_name("clippy-driver");
    if cfg!(windows) {
        path.set_extension("exe");
    }

    let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
        .map(|_| {
            std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                || std::ffi::OsString::from("clippy_dogfood"),
                |d| {
                    std::path::PathBuf::from(d)
                        .join("target")
                        .join("dogfood")
                        .into_os_string()
                },
            )
        })
        .map(|p| ("CARGO_TARGET_DIR", p));

    // Run the dogfood tests directly on nightly cargo. This is required due
    // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
    if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
        args.insert(0, "+nightly".to_string());
    }

    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WRAPPER", path)
        .env("CLIPPY_ARGS", clippy_args)
        .envs(target_dir)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<|endoftext|>


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

#[macro_use]
extern crate ecs;
use ecs::*;

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

use window::WindowSettings;

use std::collections::HashMap;
use std::default::Default;
use std::rand::Rng;
use event::{Event, ReleaseEvent, UpdateEvent, PressEvent, RenderEvent};
use quack::Set;

use opengl_graphics::{
    Gl,
};
use sdl2_window::Sdl2Window;

static WINDOW_W: f64 = 800.0;
static WINDOW_H: f64 = 600.0;
static WINDOW_PADDING: i32 = 20;

//fn draw_system(event: &Event,
//              gl: &mut Gl,
//              positions: &mut Components<Position>,
//              shapes: &mut Components<Shape>,
//              colors: &mut Components<Color>) {
//    use graphics::*;
//    if let Some(args) = event.update_args() {
//        let w = args.width as f64;
//        let h = args.height as f64;
//
//        let pad = WINDOW_PADDING;
//        gl.viewport(pad, pad, w as i32 - 2 * pad, h as i32 - 2 * pad);
//
//        gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
//            graphics::clear([0.2, 0.2, 0.0, 1.0], gl);
//            let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
//            r.draw([0.0, 0.0, WINDOW_W, WINDOW_H], &c, gl);
//        });
//
////        c.rgb(0.7, 0.7, 0.7).rect(0.0, 0.0, WINDOW_W, WINDOW_H).border_radius(1.0).draw(gl);
////
////        for (eid, pos) in positions.iter_mut() {
////          let mut shape = Point;
////          let mut border = None;
////          if shapes.contains_key(eid) {
////            shape = shapes.get_mut(eid).varient;
////            border = shapes.get_mut(eid).border;
////          }
////          let (r, g, b) = if colors.contains_key(eid) {
////              (colors.get_mut(eid).r, colors.get_mut(eid).g, colors.get_mut(eid).b)
////          } else {
////              (1.0, 1.0, 1.0)
////          };
////          let drawing = c.rgb(r, g, b);
////          match (shape, border) {
////              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
////              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),
////
////              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
////              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),
////
////              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
////              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
////          };
////        }
//    }
//}

//fn shimmer_system(shimmers: &mut Components<Shimmer>,
//                 colors: &mut Components<Color>) {
//    for (eid, _) in shimmers.iter_mut() {
//        if !colors.contains_key(eid) {
//            continue;
//        }
//        let color = colors.get_mut(eid);
//        let ref mut rng = rand::thread_rng();
//        color.r = rng.gen_range(0.5, 1.0);
//        color.g = rng.gen_range(0.5, 1.0);
//        color.b = rng.gen_range(0.5, 1.0);
//    }
//}
//
//fn move_system(event: &Event,
//               to_delete: &mut Vec<u32>,
//              positions: &mut Components<Position>,
//              shapes: &mut Components<Shape>,
//              clamps: &mut Components<WindowClamp>,
//              velocities: &mut Components<Velocity>) {
//    if let Some(args) = event.update_args {
//        let dt = args.dt;
////
////        for (eid, position) in positions.iter_mut() {
////            if !velocities.contains_key(eid) {
////                continue;
////            }
////
////            // If we have both a position and a velocity, integrate.
////            let velocity = velocities.get_mut(eid);
////            position.x += velocity.x * dt;
////            position.y += velocity.y * dt;
////
////            if !clamps.contains_key(eid) {
////              continue;
////            }
////            let (w, h) = match shapes.find(eid) {
////                Some(&s) =>
////                  match s.varient {
////                    Circle(r) => (r, r),
////                    Square(w,h) => (w, h),
////                    Point => (0.0, 0.0)
////                  },
////                None => (0.0, 0.0)
////            };
////
////            let clamp = clamps.get_mut(eid);
////            let velocity_mult = match clamp.varient {
////              Bounce => -1.0,
////              Stop => 0.0,
////              _ => 1.0
////            };
////            match clamp.varient {
////              Bounce | Stop => {
////                if position.x + w > WINDOW_W {
////                  position.x = WINDOW_W - w;
////                  velocity.x *= velocity_mult;
////                } else if position.x < 0.0 {
////                  position.x = 0.0;
////                  velocity.x *= velocity_mult;
////                }
////                if position.y + h > WINDOW_H {
////                  position.y = WINDOW_H - h;
////                  velocity.y *= velocity_mult;
////                } else if position.y < 0.0 {
////                  position.y = 0.0;
////                  velocity.y *= velocity_mult;
////                }
////              },
////              Remove => {
////                if position.x > WINDOW_W
////                || position.x + w < 0.0 {
////                  to_delete.push(*eid);
////                }
////                if position.y > WINDOW_H
////                || position.y + h < 0.0 {
////                  to_delete.push(*eid);
////                }
////              }
////            }
////        }
//    }
//}
//
//fn control_system(event: &Event,
//              controllers: &mut Components<PlayerController>,
//              velocities: &mut Components<Velocity>) {
//
//    const PADDLE_V: f64 = 800.0;
//
////    for (eid, controller) in controllers.iter_mut() {
////        event.press(|button| {
////            if button == Keyboard(controller.up) {
////                velocities.get_mut(eid).y = -PADDLE_V;
////            } else if button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = PADDLE_V;
////            }
////        });
////        event.release(|button| {
////            if button == Keyboard(controller.up)
////            || button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = 0.0;
////            }
////        });
////    }
//}

#[derive(Clone, PartialEq, Debug)]
pub enum ClampVarient {
    Bounce,
    Stop,
    Remove // Acts when item leaves window.
}

#[derive(Clone, PartialEq, Debug)]
pub struct WindowClamp {
    varient: ClampVarient
}

#[derive(Clone, PartialEq, Debug)]
pub struct PlayerController {
    up: input::Button,
    down: input::Button
}

#[derive(Clone, PartialEq, Debug)]
pub struct Position {
    x: f64,
    y: f64
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shimmer;

#[derive(Clone, PartialEq, Debug)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[derive(Clone, PartialEq, Debug)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { ShapeVarient::Point }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shape {
    varient: ShapeVarient,
    border: Option<f64>
}

#[derive(Clone, PartialEq, Debug)]
pub struct Velocity {
    x: f64,
    y: f64
}

components! {
    Components {
        #[hot] position: Position,
        #[hot] shape: Shape,
        #[hot] velocity: Velocity,
        #[hot] color: Color,
        #[hot] shimmer: Shimmer,
        #[hot] player_controller: PlayerController,
        #[hot] window_clamp: WindowClamp
    }
}

systems! {
    Systems<Components>;
}

fn make_ball(world: &mut World<Components, Systems>) {
    const BALL_R: f64 = 20.0;
    let x = (WINDOW_W - BALL_R) / 2.0;
    let y = (WINDOW_H - BALL_R) / 2.0;

    let entity = world.create_entity(Box::new(
        |entity: BuildData, data: &mut Components| {
        data.position.add(&entity,
            Position{
                x: x,
                y: y
            });
        data.shimmer.add(&entity, Shimmer);
        data.shape.add(&entity,
            Shape {
                varient: ShapeVarient::Circle(BALL_R)
                border: None
            });
        }
    ));

//    let e = world.create_entity(Box::new(
//            |entity: BuildData, data: &mut Components| {
//        data.color.add(&entity,
//            Color{
//                r: 1.0,
//                g: 0.5,
//                b: 0.2
//            });
//        data.window_clamp.add(&entity,
//            WindowClamp {
//               varient: ClampVarient::Bounce
//            });
//    }) as Box<EntityBuilder<Components>>);
}

//fn make_player(ents: &mut Entities, p1: bool) -> u32 {
//    const FROM_WALL: f64 = 20.0;
//    const PADDLE_W: f64 = 20.0;
//    const PADDLE_H: f64 = 150.0;
//    let x = if p1 {
//        FROM_WALL
//    } else {
//        WINDOW_W - FROM_WALL - PADDLE_W
//    };
//    let y = (WINDOW_H - PADDLE_H) / 2.0;
//    let e = Entity::new()
//        .with_player_controller(
//            PlayerController {
//                up: if p1 { keyboard::W } else { keyboard::I },
//                down: if p1 { keyboard::S } else { keyboard::K }
//            })
//        .with_velocity(Velocity { x: 0.0, y: 0.0 } )
//        .with_position(
//            Position{
//                x: x,
//                y: y
//            })
//        .with_shape(
//            Shape {
//                varient: Square(PADDLE_W, PADDLE_H),
//                border: None
//            })
//        .with_color(
//            Color{
//                r: 0.5,
//                g: 0.2,
//                b: 0.8
//            })
//        .with_window_clamp(
//            WindowClamp {
//               varient: Stop
//            });
//    ents.add(e)
//}

fn main() {
    let opengl = shader_version::OpenGL::_3_2;
    let mut window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::<Components, Systems>::new();
    make_ball(&mut world);

    for e in event::events(window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            //(args.dt as f32);
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
//            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
//                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
//                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
//                let off = Color([0.0, 0.0, 0.0, 1.0]);
//                let on = Color([1.0, 1.0, 1.0, 1.0]);
//
//                let w = args.width as f64 / 64.0;
//                let h = args.height as f64 / 32.0;
//
//                for (y,row) in vm.screen_rows().enumerate() {
//                    for (x,byte) in row.iter().enumerate() {
//                        let x = x as f64 * w;
//                        let y = y as f64 * h;
//                        r.set(match *byte { 0 => off, _ => on })
//                        .draw([x, y, w, h], &c, gl);
//                    }
//                }
//            });
        }
    }
}
<commit_msg>Weird lifetime, closure issue, maybe a bug<commit_after>#![allow(unused_variables, unused_imports)]

#[macro_use]
extern crate ecs;
use ecs::*;

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

use window::WindowSettings;

use std::collections::HashMap;
use std::default::Default;
use std::rand::Rng;
use event::{Event, ReleaseEvent, UpdateEvent, PressEvent, RenderEvent};
use quack::Set;

use opengl_graphics::{
    Gl,
};
use sdl2_window::Sdl2Window;

static WINDOW_W: f64 = 800.0;
static WINDOW_H: f64 = 600.0;
static WINDOW_PADDING: i32 = 20;

//fn draw_system(event: &Event,
//              gl: &mut Gl,
//              positions: &mut Components<Position>,
//              shapes: &mut Components<Shape>,
//              colors: &mut Components<Color>) {
//    use graphics::*;
//    if let Some(args) = event.update_args() {
//        let w = args.width as f64;
//        let h = args.height as f64;
//
//        let pad = WINDOW_PADDING;
//        gl.viewport(pad, pad, w as i32 - 2 * pad, h as i32 - 2 * pad);
//
//        gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
//            graphics::clear([0.2, 0.2, 0.0, 1.0], gl);
//            let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
//            r.draw([0.0, 0.0, WINDOW_W, WINDOW_H], &c, gl);
//        });
//
////        c.rgb(0.7, 0.7, 0.7).rect(0.0, 0.0, WINDOW_W, WINDOW_H).border_radius(1.0).draw(gl);
////
////        for (eid, pos) in positions.iter_mut() {
////          let mut shape = Point;
////          let mut border = None;
////          if shapes.contains_key(eid) {
////            shape = shapes.get_mut(eid).varient;
////            border = shapes.get_mut(eid).border;
////          }
////          let (r, g, b) = if colors.contains_key(eid) {
////              (colors.get_mut(eid).r, colors.get_mut(eid).g, colors.get_mut(eid).b)
////          } else {
////              (1.0, 1.0, 1.0)
////          };
////          let drawing = c.rgb(r, g, b);
////          match (shape, border) {
////              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
////              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),
////
////              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
////              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),
////
////              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
////              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
////          };
////        }
//    }
//}

//fn shimmer_system(shimmers: &mut Components<Shimmer>,
//                 colors: &mut Components<Color>) {
//    for (eid, _) in shimmers.iter_mut() {
//        if !colors.contains_key(eid) {
//            continue;
//        }
//        let color = colors.get_mut(eid);
//        let ref mut rng = rand::thread_rng();
//        color.r = rng.gen_range(0.5, 1.0);
//        color.g = rng.gen_range(0.5, 1.0);
//        color.b = rng.gen_range(0.5, 1.0);
//    }
//}
//
//fn move_system(event: &Event,
//               to_delete: &mut Vec<u32>,
//              positions: &mut Components<Position>,
//              shapes: &mut Components<Shape>,
//              clamps: &mut Components<WindowClamp>,
//              velocities: &mut Components<Velocity>) {
//    if let Some(args) = event.update_args {
//        let dt = args.dt;
////
////        for (eid, position) in positions.iter_mut() {
////            if !velocities.contains_key(eid) {
////                continue;
////            }
////
////            // If we have both a position and a velocity, integrate.
////            let velocity = velocities.get_mut(eid);
////            position.x += velocity.x * dt;
////            position.y += velocity.y * dt;
////
////            if !clamps.contains_key(eid) {
////              continue;
////            }
////            let (w, h) = match shapes.find(eid) {
////                Some(&s) =>
////                  match s.varient {
////                    Circle(r) => (r, r),
////                    Square(w,h) => (w, h),
////                    Point => (0.0, 0.0)
////                  },
////                None => (0.0, 0.0)
////            };
////
////            let clamp = clamps.get_mut(eid);
////            let velocity_mult = match clamp.varient {
////              Bounce => -1.0,
////              Stop => 0.0,
////              _ => 1.0
////            };
////            match clamp.varient {
////              Bounce | Stop => {
////                if position.x + w > WINDOW_W {
////                  position.x = WINDOW_W - w;
////                  velocity.x *= velocity_mult;
////                } else if position.x < 0.0 {
////                  position.x = 0.0;
////                  velocity.x *= velocity_mult;
////                }
////                if position.y + h > WINDOW_H {
////                  position.y = WINDOW_H - h;
////                  velocity.y *= velocity_mult;
////                } else if position.y < 0.0 {
////                  position.y = 0.0;
////                  velocity.y *= velocity_mult;
////                }
////              },
////              Remove => {
////                if position.x > WINDOW_W
////                || position.x + w < 0.0 {
////                  to_delete.push(*eid);
////                }
////                if position.y > WINDOW_H
////                || position.y + h < 0.0 {
////                  to_delete.push(*eid);
////                }
////              }
////            }
////        }
//    }
//}
//
//fn control_system(event: &Event,
//              controllers: &mut Components<PlayerController>,
//              velocities: &mut Components<Velocity>) {
//
//    const PADDLE_V: f64 = 800.0;
//
////    for (eid, controller) in controllers.iter_mut() {
////        event.press(|button| {
////            if button == Keyboard(controller.up) {
////                velocities.get_mut(eid).y = -PADDLE_V;
////            } else if button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = PADDLE_V;
////            }
////        });
////        event.release(|button| {
////            if button == Keyboard(controller.up)
////            || button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = 0.0;
////            }
////        });
////    }
//}

#[derive(Clone, PartialEq, Debug)]
pub enum ClampVarient {
    Bounce,
    Stop,
    Remove // Acts when item leaves window.
}

#[derive(Clone, PartialEq, Debug)]
pub struct WindowClamp {
    varient: ClampVarient
}

#[derive(Clone, PartialEq, Debug)]
pub struct PlayerController {
    up: input::Button,
    down: input::Button
}

#[derive(Clone, PartialEq, Debug)]
pub struct Position {
    x: f64,
    y: f64
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shimmer;

#[derive(Clone, PartialEq, Debug)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[derive(Clone, PartialEq, Debug)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { ShapeVarient::Point }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shape {
    varient: ShapeVarient,
    border: Option<f64>
}

#[derive(Clone, PartialEq, Debug)]
pub struct Velocity {
    x: f64,
    y: f64
}

components! {
    Components {
        #[hot] position: Position,
        #[hot] shape: Shape,
        #[hot] velocity: Velocity,
        #[hot] color: Color,
        #[hot] shimmer: Shimmer,
        #[hot] player_controller: PlayerController,
        #[hot] window_clamp: WindowClamp
    }
}

systems! {
    Systems<Components>;
}

fn make_ball(world: &mut World<Components, Systems>) {
    const BALL_R: f64 = 20.0;
    let shape = ShapeVarient::Circle(BALL_R);
    let x = (WINDOW_W - BALL_R) / 2.0;
    let y = (WINDOW_H - BALL_R) / 2.0;

    let entity = world.create_entity(Box::new(
        |entity: BuildData, data: &mut Components| {
        data.position.add(&entity,
            Position{
                x: x,
                y: y
            });
        data.shimmer.add(&entity, Shimmer);
        data.shape.add(&entity,
            Shape {
                varient: shape,
                border: None
            });
        }
    ));

//    let e = world.create_entity(Box::new(
//            |entity: BuildData, data: &mut Components| {
//        data.color.add(&entity,
//            Color{
//                r: 1.0,
//                g: 0.5,
//                b: 0.2
//            });
//        data.window_clamp.add(&entity,
//            WindowClamp {
//               varient: ClampVarient::Bounce
//            });
//    }) as Box<EntityBuilder<Components>>);
}

//fn make_player(ents: &mut Entities, p1: bool) -> u32 {
//    const FROM_WALL: f64 = 20.0;
//    const PADDLE_W: f64 = 20.0;
//    const PADDLE_H: f64 = 150.0;
//    let x = if p1 {
//        FROM_WALL
//    } else {
//        WINDOW_W - FROM_WALL - PADDLE_W
//    };
//    let y = (WINDOW_H - PADDLE_H) / 2.0;
//    let e = Entity::new()
//        .with_player_controller(
//            PlayerController {
//                up: if p1 { keyboard::W } else { keyboard::I },
//                down: if p1 { keyboard::S } else { keyboard::K }
//            })
//        .with_velocity(Velocity { x: 0.0, y: 0.0 } )
//        .with_position(
//            Position{
//                x: x,
//                y: y
//            })
//        .with_shape(
//            Shape {
//                varient: Square(PADDLE_W, PADDLE_H),
//                border: None
//            })
//        .with_color(
//            Color{
//                r: 0.5,
//                g: 0.2,
//                b: 0.8
//            })
//        .with_window_clamp(
//            WindowClamp {
//               varient: Stop
//            });
//    ents.add(e)
//}

fn main() {
    let opengl = shader_version::OpenGL::_3_2;
    let mut window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::<Components, Systems>::new();
    make_ball(&mut world);

    for e in event::events(window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            //(args.dt as f32);
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
//            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
//                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
//                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
//                let off = Color([0.0, 0.0, 0.0, 1.0]);
//                let on = Color([1.0, 1.0, 1.0, 1.0]);
//
//                let w = args.width as f64 / 64.0;
//                let h = args.height as f64 / 32.0;
//
//                for (y,row) in vm.screen_rows().enumerate() {
//                    for (x,byte) in row.iter().enumerate() {
//                        let x = x as f64 * w;
//                        let y = y as f64 * h;
//                        r.set(match *byte { 0 => off, _ => on })
//                        .draw([x, y, w, h], &c, gl);
//                    }
//                }
//            });
        }
    }
}
<|endoftext|>