<commit_before>#![feature(unboxed_closures, fn_traits, rustc_private)]

#[macro_use]
extern crate log;
extern crate env_logger;

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;

// Lib
#[derive(Debug)]
struct Envelope<In, Out> {
    input: In,
    output: Sender<Out>,
}

trait Actor {
    type In;
    type Out;

    fn handle(&self, message: Envelope<Self::In, Self::Out>) -> ();
    fn inbox(&self) -> Sender<Self::In>;
}

#[derive(Debug)]
struct ActorHandle<A: Actor> {
    actor: A,
}

impl<A: Actor> ActorHandle<A> {
    fn call(&self, args: A::In) -> A::Out {
        unimplemented!();
    }
}

// Impl
#[derive(Debug)]
struct EchoActor {
    inbox: Sender<i32>,
}

impl Actor for EchoActor {
    type In = i32;
    type Out = i32;

    fn handle(&self, message: Envelope<Self::In, Self::Out>) -> () {
        message.output.send(message.input).unwrap();
    }

    fn inbox(&self) -> Sender<Self::In> {
        return self.inbox.clone();
    }
}

fn main() {
    let (tx, rx) = mpsc::channel();
    let a = EchoActor { inbox: tx };
    let h = ActorHandle { actor: a };
    info!("{:?}", h.call(42));
}
<commit_msg>rewrite it!<commit_after>#![feature(unboxed_closures, fn_traits, rustc_private)]

#[macro_use]
extern crate log;
extern crate env_logger;

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;

// Lib
#[derive(Debug)]
struct Envelope<In, Out> {
    input: In,
    output: Sender<Out>,
}

impl<In, Out> Envelope<In, Out> {
    fn new(input: In, output: Sender<Out>) -> Self {
        Envelope {
            input: input,
            output: output,
        }
    }
}

trait Actor {
    type In;
    type Out;

    fn handle(&self, message: Envelope<Self::In, Self::Out>) -> ();
}

#[derive(Debug)]
struct ActorHandle<In, Out> {
    outbox: Sender<Envelope<In, Out>>,
}

impl<In, Out> ActorHandle<In, Out> {
    fn new(outbox: Sender<Envelope<In, Out>>) -> Self {
        ActorHandle { outbox: outbox }
    }

    fn call(&self, args: In) -> Out {
        let (tx, rx) = mpsc::channel();
        let e = Envelope::new(args, tx);
        self.outbox.send(e).unwrap();
        rx.recv().unwrap()
    }
}

#[derive(Debug)]
struct ActorRunner<A: Actor> {
    actor: A,
    inbox: Receiver<Envelope<A::In, A::Out>>,
}

impl<A: Actor> ActorRunner<A> {
    fn new(actor: A, inbox: Receiver<Envelope<A::In, A::Out>>) -> Self {
        ActorRunner {
            actor: actor,
            inbox: inbox,
        }
    }
}

impl<A: Actor> FnOnce<()> for ActorRunner<A> {
    type Output = ();
    extern "rust-call" fn call_once(self, _: ()) -> () {
        // Forever...
        loop {
            // See if we have messages!
            match self.inbox.recv() {
                Ok(m) => self.actor.handle(m),
                // Exit on error
                Err(e) => {
                    error!("[Actor] Error: {:?}", e);
                    break;
                }
            }
        }
    }
}

// Impl
#[derive(Debug)]
struct EchoActor;

impl Actor for EchoActor {
    type In = i32;
    type Out = Self::In;

    fn handle(&self, message: Envelope<Self::In, Self::Out>) -> () {
        message.output.send(1 / message.input).unwrap();
    }
}

fn main() {
    let (tx, rx) = mpsc::channel();
    let a = EchoActor;
    let h = ActorHandle::new(tx);
    let r = ActorRunner::new(a, rx);
    let t = thread::Builder::new()
        .name("actor".into())
        .spawn(r)
        .unwrap();

    info!("{:?}", h.call(1));
    info!("{:?}", h.call(0));
    t.join().unwrap();
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate reroute;

use std::fs::File;
use std::io::{BufReader, Result};
use std::io::prelude::*;
use std::env;

use hyper::Server;
use hyper::server::{Request, Response};
use reroute::{Captures, RouterBuilder};

fn not_found(req: Request, res: Response, _: Captures) {
    let uri = format!("{}", req.uri);
    let msg = format!("No service found behind '{}'.", uri);
    res.send(msg.as_bytes()).unwrap();
}

fn parse_capture(cap: &String) -> Vec<String> {
    let caps: Vec<&str> = cap.split(|c| c == ',' || c == '/').collect();
    let mut list: Vec<String> = Vec::new();
    // &caps[2..] is used to skip `/api/`
    for val in &caps[2..] {
        if val.is_empty() {
            continue;
        }
        list.push(val.to_string());
    }
    list
}

fn list_handler(_: Request, res: Response, c: Captures) {
    let cap = c.unwrap();
    let caps = parse_capture(&cap[0]);
    let mut re = "; Generated by editorconfig.me\n; EditorConfig helps developers define and maintain consistent\n; coding styles between different editors and IDEs\n; editorconfig.org\n\n".to_string();

    for target in caps {
        let content = match read_file(&get_file_name(&target)) {
            Ok(c) => c,
            Err(e) => {
                println!("Could not process '{}'. {:?}", target, e);
                format!("; Could not process '{}'\n", target)
            }
        };
        re.push_str(&content);
        re.push_str("\n");
    }
    res.send(re.as_bytes()).unwrap();
}

fn get_file_name(name: &String) -> String {
    let mut full_name = "./files/".to_string();
    full_name.push_str(&name);
    full_name.push_str(".editorconfig");
    full_name
}

fn read_file(name: &String) -> Result<String> {
    // let mut full_name = "./files/".to_string();
    // full_name.push_str(&name);
    let file = File::open(name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    Ok(contents)
}

// Look up the server port in PORT for heroku or use 8080 as fallback
fn get_server_port() -> String {
    env::var("PORT").unwrap_or("8080".to_string())
}

fn main() {
    let mut builder = RouterBuilder::new();

    builder.get(r"/api/(,?(\w)+)+", list_handler);

    builder.not_found(not_found);

    let router = builder.finalize().unwrap();

    let mut listen = "0.0.0.0:".to_string();
    listen.push_str(&get_server_port());
    Server::http(&listen).unwrap().handle(router).unwrap();
}

#[test]
fn test_parse_capture() {
    let actual = parse_capture(&"/api/,rust,,markdown,".to_string());
    let expected = vec!["rust".to_string(), "markdown".to_string()];
    assert_eq!(actual, expected);
}

#[test]
fn test_read_file() {
    let actual = read_file(&"test/testfile".to_string()).unwrap();
    let expected = "testtesttest\n".to_string();
    assert_eq!(actual, expected);
}

#[test]
fn test_get_file_name() {
    let actual = get_file_name(&"rust".to_string());
    let expected = "./files/rust.editorconfig".to_string();
    assert_eq!(actual, expected);
}
<commit_msg>Use HashSet instead of Vec for parameters<commit_after>extern crate hyper;
extern crate reroute;

use std::fs::File;
use std::io::{BufReader, Result};
use std::io::prelude::*;
use std::collections::HashSet;
use std::env;

use hyper::Server;
use hyper::server::{Request, Response};
use reroute::{Captures, RouterBuilder};

fn not_found(req: Request, res: Response, _: Captures) {
    let uri = format!("{}", req.uri);
    let msg = format!("No service found behind '{}'.", uri);
    res.send(msg.as_bytes()).unwrap();
}

fn parse_capture(cap: &String) -> HashSet<String> {
    let caps: Vec<&str> = cap.split(|c| c == ',' || c == '/').collect();
    // let mut list: Vec<String> = Vec::new();
    let mut list: HashSet<String> = HashSet::new();
    // &caps[2..] is used to skip `/api/`
    for val in &caps[2..] {
        if val.is_empty() {
            continue;
        }
        list.insert(val.to_string());
    }
    list
}

fn list_handler(_: Request, res: Response, c: Captures) {
    let cap = c.unwrap();
    let caps = parse_capture(&cap[0]);
    let mut re = "; Generated by editorconfig.me\n; EditorConfig helps developers define and maintain consistent\n; coding styles between different editors and IDEs\n; editorconfig.org\n\n".to_string();

    for target in caps {
        let content = match read_file(&get_file_name(&target)) {
            Ok(c) => c,
            Err(e) => {
                println!("Could not process '{}'. {:?}", target, e);
                format!("; Could not process '{}'\n", target)
            }
        };
        re.push_str(&content);
        re.push_str("\n");
    }
    res.send(re.as_bytes()).unwrap();
}

fn get_file_name(name: &String) -> String {
    let mut full_name = "./files/".to_string();
    full_name.push_str(&name);
    full_name.push_str(".editorconfig");
    full_name
}

fn read_file(name: &String) -> Result<String> {
    // let mut full_name = "./files/".to_string();
    // full_name.push_str(&name);
    let file = File::open(name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    Ok(contents)
}

// Look up the server port in PORT for heroku or use 8080 as fallback
fn get_server_port() -> String {
    env::var("PORT").unwrap_or("8080".to_string())
}

fn main() {
    let mut builder = RouterBuilder::new();

    builder.get(r"/api/(,?(\w)+)+", list_handler);

    builder.not_found(not_found);

    let router = builder.finalize().unwrap();

    let mut listen = "0.0.0.0:".to_string();
    listen.push_str(&get_server_port());
    Server::http(&listen).unwrap().handle(router).unwrap();
}

#[test]
fn test_parse_capture() {
    let actual = parse_capture(&"/api/,rust,,markdown,,,rust,".to_string());
    let expected: HashSet<String> = vec!["rust".to_string(), "markdown".to_string()]
        .into_iter()
        .collect();
    assert_eq!(actual, expected);
}

#[test]
fn test_read_file() {
    let actual = read_file(&"test/testfile".to_string()).unwrap();
    let expected = "testtesttest\n".to_string();
    assert_eq!(actual, expected);
}

#[test]
fn test_get_file_name() {
    let actual = get_file_name(&"rust".to_string());
    let expected = "./files/rust.editorconfig".to_string();
    assert_eq!(actual, expected);
}
<|endoftext|>


<commit_before>use std::env;
use std::process;

extern crate getopts;
use getopts::Options;

extern crate fish;

const NAME: &'static str = env!("CARGO_PKG_NAME");
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn print_version() {
    println!("{} version {}\nCopyright © 2016 - Marc Noirot", NAME, VERSION);
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("c", "code", "string of instructions to execute instead of FILE", "CODE");
    opts.optmulti("s", "string", "push strings onto the stack before execution starts", "STRING");
    opts.optmulti("v", "value", "push numbers onto the stack before execution starts", "NUMBER");
    opts.optopt("t", "tick", "define a delay between the execution of each instruction", "DELAY");
    opts.optflag("a", "always-tick", "make every instruction cause a tick, even whitespace and skipped instructions");
    opts.optflag("d", "debug", "dump interpreter state before executing an instruction");
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("V", "version", "print the program version and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            println!("Error: {}\n", e);
            print_usage(&program, opts);
            process::exit(1);
        },
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        process::exit(1);
    }

    if matches.opt_present("V") {
        print_version();
        process::exit(1);
    }

    let codebox = match matches.opt_str("c") {
        Some(c) => fish::CodeBox::load_from_string(&c),
        _ => {
            let input = if !matches.free.is_empty() {
                matches.free[0].clone()
            } else {
                print_usage(&program, opts);
                process::exit(1);
            };

            match fish::CodeBox::load_from_file(&input) {
                Ok(cb) => cb,
                Err(e) => {
                    println!("Error: {}", e);
                    process::exit(2);
                }
            }
        }
    };

    let input = std::io::stdin();
    let output = std::io::stdout();

    let mut fish = fish::Interpreter::new(input, output);

    if matches.opt_present("d") {
        fish.trace = true;
    }

    if fish.run(&codebox).is_err() {
        println!("something smells fishy...");
        process::exit(3);
    }

    println!("");
}
<commit_msg>Improve variable naming<commit_after>use std::env;
use std::process;

extern crate getopts;
use getopts::Options;

extern crate fish;

const NAME: &'static str = env!("CARGO_PKG_NAME");
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn print_version() {
    println!("{} version {}\nCopyright © 2016 - Marc Noirot", NAME, VERSION);
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("c", "code", "string of instructions to execute instead of FILE", "CODE");
    opts.optmulti("s", "string", "push strings onto the stack before execution starts", "STRING");
    opts.optmulti("v", "value", "push numbers onto the stack before execution starts", "NUMBER");
    opts.optopt("t", "tick", "define a delay between the execution of each instruction", "DELAY");
    opts.optflag("a", "always-tick", "make every instruction cause a tick, even whitespace and skipped instructions");
    opts.optflag("d", "debug", "dump interpreter state before executing an instruction");
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("V", "version", "print the program version and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            println!("Error: {}\n", e);
            print_usage(&program, opts);
            process::exit(1);
        },
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        process::exit(1);
    }

    if matches.opt_present("V") {
        print_version();
        process::exit(1);
    }

    let code_box = match matches.opt_str("c") {
        Some(c) => fish::CodeBox::load_from_string(&c),
        _ => {
            let input = if !matches.free.is_empty() {
                matches.free[0].clone()
            } else {
                print_usage(&program, opts);
                process::exit(1);
            };

            match fish::CodeBox::load_from_file(&input) {
                Ok(cb) => cb,
                Err(e) => {
                    println!("Error: {}", e);
                    process::exit(2);
                }
            }
        }
    };

    let input = std::io::stdin();
    let output = std::io::stdout();

    let mut fish = fish::Interpreter::new(input, output);

    if matches.opt_present("d") {
        fish.trace = true;
    }

    if fish.run(&code_box).is_err() {
        println!("something smells fishy...");
        process::exit(3);
    }

    println!("");
}
<|endoftext|>


<commit_before>extern crate libusb;
use std::time::Duration;
use std::thread;
use std::process;
use std::io::{self, Write};

fn main() {
    let context = libusb::Context::new().unwrap();
    let device = find_device(&context);

    match device {
        Ok(handle) => {
            run(handle).unwrap();
        },
        Err(libusb::Error::NotFound) => {
            println!("Device not found");
            process::exit(1);
        }
        Err(e) => {
            println!("{}", e);
            process::exit(1);
        }
    }
}

fn find_device<'a>(context: &'a libusb::Context) -> Result<libusb::DeviceHandle<'a>, libusb::Error> {
    let devices = try!(context.devices());
    devices.iter().find(|device| {
        device.device_descriptor().ok().map_or(false, |desc| desc.vendor_id() == 0x05c6)
    }).map_or(Err(libusb::Error::NotFound), |device| device.open())
}

fn run(mut handle: libusb::DeviceHandle) -> Result<(), libusb::Error> {
    let mut stdout = io::stdout();
    println!("Found device");
    try!(handle.claim_interface(0));

    let mut read_buf = [0; 4096];

    loop {
        println!("Connecting DMSS");

        try!(handle.write_bulk(0x01, &[0x0c, 0x00, 0x00, 0x00,  0x00, 0x47, 0xb8, 0x7e], Duration::from_secs(10)));
        let len = try!(handle.read_bulk(0x81, &mut read_buf, Duration::from_secs(10)));
        let rx = &read_buf[0..len];

        if rx == &[0x13, 0x0c, 0x00, 0x00,  0x00, 0x00, 0x72, 0xce, 0x7e] {
            break;
        } else {
            thread::sleep(Duration::from_millis(100));
        }
    }

    try!(handle.write_bulk(0x01, &[0x7d, 0x5d, 0x04, 0x34,  0x21, 0x34, 0x21, 0x00,  0x00, 0x1f, 0x00, 0x00,  0x00, 0xab, 0xdf, 0x7e], Duration::from_secs(1)));
    println!("DMSS is connected");

    loop {
        let len = try!(handle.read_bulk(0x81, &mut read_buf, Duration::from_secs(0)));

        for packet in Hdlc::new(read_buf[0..len].iter().map(|&x| x)) {
            if packet.len() > 0 {
                parse_packet(&mut stdout, packet).unwrap();
            }
        }
    }
}

fn split_byte(s: &[u8], sep: u8) -> (&[u8], &[u8]) {
    if let Some(pos) = s.iter().position(|&i| i == sep) {
        let (a, b) = s.split_at(pos);
        (a, &b[1..])
    } else {
        (s, &[])
    }
}

fn le32(s: &[u8]) -> u32 {
    (s[0] as u32) | (s[1] as u32) << 8 | (s[2] as u32) << 16 | (s[3] as u32) << 24
}

fn parse_packet(stdout: &mut Write, packet: Vec<u8>) -> io::Result<()> {
    if packet.len() < 24 || packet[0] != 0x79 || packet[2] != 0 {
        print!("[unknown packet: ");
        for b in &packet { print!("{:02x}", b); }
        println!("]");
        return Ok(());
    }

    let (header, rest) = packet.split_at(20);
    let timestamp = le32(&header[6..10]);
    let (msg, rest) = split_byte(rest, 0);
    let (file, _) = split_byte(rest, 0);

    //for b in &packet { print!("{:02x} ", b); }

    try!(write!(stdout, "{:10}: ", timestamp));
    try!(stdout.write_all(msg));
    try!(write!(stdout, " ("));
    try!(stdout.write_all(file));
    try!(write!(stdout, ")\n"));

    Ok(())
}

/// Iterator over packets in a HDLC-framed sequence of bytes
struct Hdlc<I> {
    input: I,
    end: bool,
}

impl<I> Hdlc<I> where I:Iterator<Item=u8> {
    fn new(input: I) -> Hdlc<I> {
        Hdlc {
            input: input,
            end: false,
        }
    }

    fn input_byte(&mut self) -> Option<u8> {
        let x = self.input.next();
        self.end |= x.is_none();
        x
    }
}

impl<I> Iterator for Hdlc<I> where I:Iterator<Item=u8> {
    type Item = Vec<u8>;
    fn next(&mut self) -> Option<Vec<u8>> {
        if self.end {
            return None;
        }

        let mut out = vec![];

        loop {
            match self.input_byte() {
                Some(0x7e) | None => break,
                Some(0x7d) => {
                    match self.input_byte() {
                        Some(c) => out.push(c ^ 0x20),
                        None => break,
                    }
                }
                Some(c) => out.push(c),
            };
        }

        Some(out)
    }
}<commit_msg>Display line number from logs<commit_after>extern crate libusb;
use std::time::Duration;
use std::thread;
use std::process;
use std::io::{self, Write};

fn main() {
    let context = libusb::Context::new().unwrap();
    let device = find_device(&context);

    match device {
        Ok(handle) => {
            run(handle).unwrap();
        },
        Err(libusb::Error::NotFound) => {
            println!("Device not found");
            process::exit(1);
        }
        Err(e) => {
            println!("{}", e);
            process::exit(1);
        }
    }
}

fn find_device<'a>(context: &'a libusb::Context) -> Result<libusb::DeviceHandle<'a>, libusb::Error> {
    let devices = try!(context.devices());
    devices.iter().find(|device| {
        device.device_descriptor().ok().map_or(false, |desc| desc.vendor_id() == 0x05c6)
    }).map_or(Err(libusb::Error::NotFound), |device| device.open())
}

fn run(mut handle: libusb::DeviceHandle) -> Result<(), libusb::Error> {
    let mut stdout = io::stdout();
    println!("Found device");
    try!(handle.claim_interface(0));

    let mut read_buf = [0; 4096];

    loop {
        println!("Connecting DMSS");

        try!(handle.write_bulk(0x01, &[0x0c, 0x00, 0x00, 0x00,  0x00, 0x47, 0xb8, 0x7e], Duration::from_secs(10)));
        let len = try!(handle.read_bulk(0x81, &mut read_buf, Duration::from_secs(10)));
        let rx = &read_buf[0..len];

        if rx == &[0x13, 0x0c, 0x00, 0x00,  0x00, 0x00, 0x72, 0xce, 0x7e] {
            break;
        } else {
            thread::sleep(Duration::from_millis(100));
        }
    }

    try!(handle.write_bulk(0x01, &[0x7d, 0x5d, 0x04, 0x34,  0x21, 0x34, 0x21, 0x00,  0x00, 0x1f, 0x00, 0x00,  0x00, 0xab, 0xdf, 0x7e], Duration::from_secs(1)));
    println!("DMSS is connected");

    loop {
        let len = try!(handle.read_bulk(0x81, &mut read_buf, Duration::from_secs(0)));

        for packet in Hdlc::new(read_buf[0..len].iter().map(|&x| x)) {
            if packet.len() > 0 {
                parse_packet(&mut stdout, packet).unwrap();
            }
        }
    }
}

fn split_byte(s: &[u8], sep: u8) -> (&[u8], &[u8]) {
    if let Some(pos) = s.iter().position(|&i| i == sep) {
        let (a, b) = s.split_at(pos);
        (a, &b[1..])
    } else {
        (s, &[])
    }
}

fn le32(s: &[u8]) -> u32 {
    (s[0] as u32) | (s[1] as u32) << 8 | (s[2] as u32) << 16 | (s[3] as u32) << 24
}

fn le16(s: &[u8]) -> u16 {
    (s[0] as u16) | (s[1] as u16) << 8
}

fn parse_packet(stdout: &mut Write, packet: Vec<u8>) -> io::Result<()> {
    if packet.len() < 24 || packet[0] != 0x79 || packet[2] != 0 {
        print!("[unknown packet: ");
        for b in &packet { print!("{:02x}", b); }
        println!("]");
        return Ok(());
    }

    let (header, rest) = packet.split_at(20);
    let timestamp = le32(&header[6..10]);
    let lineno = le16(&header[12..14]);
    let (msg, rest) = split_byte(rest, 0);
    let (file, _) = split_byte(rest, 0);

    //for b in &packet { print!("{:02x} ", b); }

    try!(write!(stdout, "{:10}: ", timestamp));
    try!(stdout.write_all(msg));
    try!(write!(stdout, " ("));
    try!(stdout.write_all(file));
    try!(write!(stdout, ":{})\n", lineno));

    Ok(())
}

/// Iterator over packets in a HDLC-framed sequence of bytes
struct Hdlc<I> {
    input: I,
    end: bool,
}

impl<I> Hdlc<I> where I:Iterator<Item=u8> {
    fn new(input: I) -> Hdlc<I> {
        Hdlc {
            input: input,
            end: false,
        }
    }

    fn input_byte(&mut self) -> Option<u8> {
        let x = self.input.next();
        self.end |= x.is_none();
        x
    }
}

impl<I> Iterator for Hdlc<I> where I:Iterator<Item=u8> {
    type Item = Vec<u8>;
    fn next(&mut self) -> Option<Vec<u8>> {
        if self.end {
            return None;
        }

        let mut out = vec![];

        loop {
            match self.input_byte() {
                Some(0x7e) | None => break,
                Some(0x7d) => {
                    match self.input_byte() {
                        Some(c) => out.push(c ^ 0x20),
                        None => break,
                    }
                }
                Some(c) => out.push(c),
            };
        }

        Some(out)
    }
}<|endoftext|>


<commit_before>#![feature(core)]
#![feature(collections)]

#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex;
extern crate git2;
extern crate core;
extern crate rustc_serialize;
extern crate docopt;

use git2::{Repository, Commit, Diff, DiffFormat, Oid};
use docopt::Docopt;
use std::collections::HashMap;
// use std::old_io::BufferedReader;
// use std::old_io::File;
use std::str;
// use regex::Regex;
use rustc_serialize::json;
use std::fmt::Display;
use std::path::Path;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest. Output is ing JSON.
";

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

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(&args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old_id = Oid::from_str(&old_string[..])
            .ok().expect("Couldn't parse old ID");
        let old = repo.find_commit(old_id);
        let new_id = Oid::from_str(&new_string[..])
            .ok().expect("Couldn't parse new ID");
        let new = repo.find_commit(new_id);
        if old.is_ok() && new.is_ok() {
            let (old_commit, new_commit) = (old.unwrap(), new.unwrap());
            let output = find_moves(&repo, &old_commit, &new_commit).unwrap();
            make_json(vec![OutputSet {
                old: TransitOid(old_id),
                old_time: old_commit.time().seconds(), // Seconds from Epoch
                new: TransitOid(new_id),
                new_time: new_commit.time().seconds(), // Seconds from Epoch
                outputs: output,
            }]);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.collect::<Vec<Oid>>();
        let mut output = Vec::with_capacity(history.len());
        // Walk through each pair of commits.
        for pair in history.windows(2) {
            let (old_id, new_id) = (pair[0], pair[1]);
            if let (Ok(old), Ok(new)) = (repo.find_commit(old_id), repo.find_commit(new_id)) {
                let detected = find_moves(&repo, &old, &new).unwrap();
                output.push(OutputSet {
                    old: TransitOid(old_id),
                    old_time: old.time().seconds(), // Seconds from Epoch
                    new: TransitOid(new_id),
                    new_time: new.time().seconds(), // Seconds from Epoch
                    outputs: detected,
                });
            } else {
                continue;
            }
        }
        make_json(output);
    }
}

fn make_json(output: Vec<OutputSet>) {
    let out = json::as_pretty_json(&output).indent(4);
    println!("{}", out);
}

#[derive(Debug, PartialEq, Eq)]
enum FoundState {
    Added, Deleted
}

fn format_key(key: String) -> String {
    let remove_whitespace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    let trim = regex!(r"^[\s]+|[\s]+$");
    let result = remove_whitespace.replace_all(&key[..], "");
    trim.replace_all(&result[..], "")
}

#[derive(Debug)]
struct Found {
    filename: String,
    key: String,
    state: FoundState,
    start_position: u32,
    line_count: u32,
}

fn find_additions_and_deletions(diff: Diff) -> Vec<Found> {

    #[derive(Debug)]
    enum State {
        Other, Addition, Deletion
    }

    let mut founds: Vec<Found> = Vec::new();

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();
    let mut old_path = String::new();
    let mut new_path = String::new();

    let mut line_count: u32 = 0;
    let mut start_position: u32 = 0;

    // Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
    // It's a bit weird, but I think it will provide the necessary information.
    diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

        // if delta.nfiles() != 2 {
        //     // This is diff with only one side, and thus can't have a move.
        //     return true;
        // }
        // assert!(delta.nfiles() == 2, "This only works on diffs between exactly 2 files. Found {} files.", delta.nfiles());

        // Thinking:
        //  * If is not a hunk, keep going.
        //  * If it's a hunk, do regex magic.
        //  * Stick regex output into a hashmap as a hash.
        //  * Later, we will iterate through and output pased on the values.
        // Filter out all the boring context lines.
        // If we're not interested in this line just return since it will iterate to the next.
        if maybe_hunk.is_none() { return true }; // Return early.

        //dump_diffline(&line);
        //dump_diffdelta(&delta);
        //dump_diffhunk(&maybe_hunk.unwrap());

        old_path = match delta.old_file().path()
        .and_then(|x| x.to_str()) {
            Some(path) => String::from_str(path),
            None => return false,
        };
        new_path = match delta.new_file().path()
        .and_then(|x| x.to_str()) {
            Some(path) => String::from_str(path),
            None => return false,
        };

        match line.origin() {
            // Additions
            '+' | '>' => {
                // If we attempt to unwrap and get `InvalidBytes(_)` it's probably just junk.
                // TODO: Is it?
                let line_str = str::from_utf8(line.content()).unwrap_or("");
                added.push_str(line_str);

                match state {
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                        line_count = 0;
                        start_position = match line.new_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                    State::Addition => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = match line.new_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                }

                state = State::Addition;
                true
            },
            // Deletions
            '-' | '<' => {
                // If we attempt to unwrap and get `InvalidBytes(_)` it's probably just junk.
                // TODO: Is it?
                let line_str = str::from_utf8(line.content()).unwrap_or("");
                deleted.push_str(line_str);

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                        line_count = 0;
                        start_position = match line.old_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                    State::Deletion => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = match line.old_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                }

                state = State::Deletion;
                true
            },
            // Other
            _         => {
                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                    },
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                    },
                    _ => (),
                }

                state = State::Other;
                true
            }
        }
    }).ok(); // We don't care if we exit early. That's fine.

    // Grab last one.
    match state {
        State::Addition => {
            if added.len() > 0 {
                founds.push(Found {
                    filename: new_path.clone(),
                    key: format_key(added.clone()),
                    state: FoundState::Added,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        State::Deletion => {
            if deleted.len() > 0 {
                founds.push(Found {
                    filename: old_path.clone(),
                    key: format_key(deleted.clone()),
                    state: FoundState::Deleted,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        _ => (),
    }

    return founds;
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, git2::Error> {
    let old_tree = try!(old.tree());
    let new_tree = try!(new.tree());
    // Build up a diff of the two trees.
    let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    let founds: Vec<Found> = find_additions_and_deletions(diff);

    let mut moves: Vec<Output> = Vec::new();
    let mut map: HashMap<String, Found> = HashMap::new();

    for f in founds {
        if f.key.len() == 0 { continue; }

        if map.contains_key(&f.key) {
            let q = map.get(&f.key).unwrap();

            // If both states are added, there are no moves.
            // assert!(f.state != q.state, format!("States {:?}, {:?}. Should be Addition/Deletion ", f.state, q.state));
            if f.state == q.state {
                return Ok(Vec::<Output>::new())
            }

            let output: Output;

            match f.state {
                FoundState::Added => {
                    output = Output {
                        old_filename: q.filename.clone(),
                        new_filename: f.filename.clone(),
                        origin_line: q.start_position,
                        destination_line: f.start_position,
                        num_lines: f.line_count,
                    };
                },
                FoundState::Deleted => {
                    output = Output {
                        old_filename: f.filename.clone(),
                        new_filename: q.filename.clone(),
                        origin_line: f.start_position,
                        destination_line: q.start_position,
                        num_lines: f.line_count,
                    };
                },
            }

            moves.push(output);
        } else {
            map.insert(f.key.clone(), f);
        }
    }

    return Ok(moves);
}

#[derive(Debug, RustcEncodable)]
struct OutputSet {
    old: TransitOid,
    old_time: i64, // Seconds from Epoch
    new: TransitOid,
    new_time: i64, // Seconds from Epoch
    outputs: Vec<Output>,
}

#[derive(Debug, RustcEncodable)]
struct Output {
    old_filename: String,
    new_filename: String,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}

#[derive(Debug, Hash, PartialEq, Eq)]
struct TransitOid(Oid);
impl Display for TransitOid {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        Display::fmt(&self.0, f)
    }
}

impl rustc_serialize::Encodable for TransitOid {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&format!("{}", self)[..])
    }
}
<commit_msg>Prep for web<commit_after>#![feature(core)]
#![feature(collections)]

#![feature(plugin)]
#![plugin(regex_macros)] extern crate regex;
extern crate git2;
extern crate core;
extern crate rustc_serialize;
extern crate docopt;

use git2::{Repository, Commit, Diff, DiffFormat, Oid};
use docopt::Docopt;
use std::collections::HashMap;
// use std::old_io::BufferedReader;
// use std::old_io::File;
use std::str;
// use regex::Regex;
use rustc_serialize::json;
use std::fmt::Display;
use std::path::Path;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit [--web | <repo> [<old> <new>] | --help]

Examples:
  transit --web             Spawn a web service.
  transit $REPO             Output the results of a revwalk through a repo.
  transit $REPO $ID1 $ID2   Output the data for a pair of commits.
  transit --help            Display this message.

Output is in JSON.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_web: bool,
    arg_repo: Option<String>,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    print!("{:?}", args);

    if args.flag_web {
        unimplemented!();
    } else if let Some(path_string) = args.arg_repo {
        // Pull up the revwalk.
        let path = Path::new(&path_string);
        let repo = Repository::discover(&path)
            .ok().expect("Unable to find repo.");
        // If we can destructures the two optional args into real things.
        if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
            // Compare a specific commit pair.
            // Fist, get the commits. (Error checked)
            let old_id = Oid::from_str(&old_string[..])
                .ok().expect("Couldn't parse old ID");
            let old = repo.find_commit(old_id);
            let new_id = Oid::from_str(&new_string[..])
                .ok().expect("Couldn't parse new ID");
            let new = repo.find_commit(new_id);
            if old.is_ok() && new.is_ok() {
                let (old_commit, new_commit) = (old.unwrap(), new.unwrap());
                let output = find_moves(&repo, &old_commit, &new_commit).unwrap();
                make_json(vec![OutputSet {
                    old: TransitOid(old_id),
                    old_time: old_commit.time().seconds(), // Seconds from Epoch
                    new: TransitOid(new_id),
                    new_time: new_commit.time().seconds(), // Seconds from Epoch
                    outputs: output,
                }]);
            } else {
                panic!("Commit ids were not valid.");
            }
        } else {
            // Revwalk.
            let mut revwalk = repo.revwalk()
                .ok().expect("Unable to get revwalk.");
            // Setup some options.
            revwalk.simplify_first_parent(); // TODO: Maybe remove?
            let mut flags = git2::Sort::empty();
            flags.insert(git2::SORT_TIME);
            flags.insert(git2::SORT_TOPOLOGICAL);
            revwalk.set_sorting(flags);
            // Push HEAD to the revwalk.
            revwalk.push_head()
                .ok().expect("Unable to push HEAD.");
            // We sadly must collect here to use `.windows()`
            let history = revwalk.collect::<Vec<Oid>>();
            let mut output = Vec::with_capacity(history.len());
            // Walk through each pair of commits.
            for pair in history.windows(2) {
                let (old_id, new_id) = (pair[0], pair[1]);
                if let (Ok(old), Ok(new)) = (repo.find_commit(old_id), repo.find_commit(new_id)) {
                    let detected = find_moves(&repo, &old, &new).unwrap();
                    output.push(OutputSet {
                        old: TransitOid(old_id),
                        old_time: old.time().seconds(), // Seconds from Epoch
                        new: TransitOid(new_id),
                        new_time: new.time().seconds(), // Seconds from Epoch
                        outputs: detected,
                    });
                } else {
                    continue;
                }
            }
            make_json(output);
        }
    } else {
        unreachable!();
    }
}

fn make_json(output: Vec<OutputSet>) {
    let out = json::as_pretty_json(&output).indent(4);
    println!("{}", out);
}

#[derive(Debug, PartialEq, Eq)]
enum FoundState {
    Added, Deleted
}

fn format_key(key: String) -> String {
    let remove_whitespace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    let trim = regex!(r"^[\s]+|[\s]+$");
    let result = remove_whitespace.replace_all(&key[..], "");
    trim.replace_all(&result[..], "")
}

#[derive(Debug)]
struct Found {
    filename: String,
    key: String,
    state: FoundState,
    start_position: u32,
    line_count: u32,
}

fn find_additions_and_deletions(diff: Diff) -> Vec<Found> {

    #[derive(Debug)]
    enum State {
        Other, Addition, Deletion
    }

    let mut founds: Vec<Found> = Vec::new();

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();
    let mut old_path = String::new();
    let mut new_path = String::new();

    let mut line_count: u32 = 0;
    let mut start_position: u32 = 0;

    // Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
    // It's a bit weird, but I think it will provide the necessary information.
    diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

        // if delta.nfiles() != 2 {
        //     // This is diff with only one side, and thus can't have a move.
        //     return true;
        // }
        // assert!(delta.nfiles() == 2, "This only works on diffs between exactly 2 files. Found {} files.", delta.nfiles());

        // Thinking:
        //  * If is not a hunk, keep going.
        //  * If it's a hunk, do regex magic.
        //  * Stick regex output into a hashmap as a hash.
        //  * Later, we will iterate through and output pased on the values.
        // Filter out all the boring context lines.
        // If we're not interested in this line just return since it will iterate to the next.
        if maybe_hunk.is_none() { return true }; // Return early.

        //dump_diffline(&line);
        //dump_diffdelta(&delta);
        //dump_diffhunk(&maybe_hunk.unwrap());

        old_path = match delta.old_file().path()
        .and_then(|x| x.to_str()) {
            Some(path) => String::from_str(path),
            None => return false,
        };
        new_path = match delta.new_file().path()
        .and_then(|x| x.to_str()) {
            Some(path) => String::from_str(path),
            None => return false,
        };

        match line.origin() {
            // Additions
            '+' | '>' => {
                // If we attempt to unwrap and get `InvalidBytes(_)` it's probably just junk.
                // TODO: Is it?
                let line_str = str::from_utf8(line.content()).unwrap_or("");
                added.push_str(line_str);

                match state {
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                        line_count = 0;
                        start_position = match line.new_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                    State::Addition => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = match line.new_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                }

                state = State::Addition;
                true
            },
            // Deletions
            '-' | '<' => {
                // If we attempt to unwrap and get `InvalidBytes(_)` it's probably just junk.
                // TODO: Is it?
                let line_str = str::from_utf8(line.content()).unwrap_or("");
                deleted.push_str(line_str);

                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                        line_count = 0;
                        start_position = match line.old_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                    State::Deletion => {
                        line_count += 1;
                    },
                    State::Other => {
                        line_count = 1;
                        start_position = match line.old_lineno() {
                            Some(lineno) => lineno,
                            None => return false, // Can't be a move if deleted.
                        }
                    },
                }

                state = State::Deletion;
                true
            },
            // Other
            _         => {
                match state {
                    State::Addition => {
                        founds.push(Found {
                            filename: new_path.clone(),
                            key: format_key(added.clone()),
                            state: FoundState::Added,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        added = String::new();
                    },
                    State::Deletion => {
                        founds.push(Found {
                            filename: old_path.clone(),
                            key: format_key(deleted.clone()),
                            state: FoundState::Deleted,
                            start_position: start_position,
                            line_count: line_count,
                        });
                        deleted = String::new();
                    },
                    _ => (),
                }

                state = State::Other;
                true
            }
        }
    }).ok(); // We don't care if we exit early. That's fine.

    // Grab last one.
    match state {
        State::Addition => {
            if added.len() > 0 {
                founds.push(Found {
                    filename: new_path.clone(),
                    key: format_key(added.clone()),
                    state: FoundState::Added,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        State::Deletion => {
            if deleted.len() > 0 {
                founds.push(Found {
                    filename: old_path.clone(),
                    key: format_key(deleted.clone()),
                    state: FoundState::Deleted,
                    start_position: start_position,
                    line_count: line_count,
                });
            }
        },
        _ => (),
    }

    return founds;
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, git2::Error> {
    let old_tree = try!(old.tree());
    let new_tree = try!(new.tree());
    // Build up a diff of the two trees.
    let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    let founds: Vec<Found> = find_additions_and_deletions(diff);

    let mut moves: Vec<Output> = Vec::new();
    let mut map: HashMap<String, Found> = HashMap::new();

    for f in founds {
        if f.key.len() == 0 { continue; }

        if map.contains_key(&f.key) {
            let q = map.get(&f.key).unwrap();

            // If both states are added, there are no moves.
            // assert!(f.state != q.state, format!("States {:?}, {:?}. Should be Addition/Deletion ", f.state, q.state));
            if f.state == q.state {
                return Ok(Vec::<Output>::new())
            }

            let output: Output;

            match f.state {
                FoundState::Added => {
                    output = Output {
                        old_filename: q.filename.clone(),
                        new_filename: f.filename.clone(),
                        origin_line: q.start_position,
                        destination_line: f.start_position,
                        num_lines: f.line_count,
                    };
                },
                FoundState::Deleted => {
                    output = Output {
                        old_filename: f.filename.clone(),
                        new_filename: q.filename.clone(),
                        origin_line: f.start_position,
                        destination_line: q.start_position,
                        num_lines: f.line_count,
                    };
                },
            }

            moves.push(output);
        } else {
            map.insert(f.key.clone(), f);
        }
    }

    return Ok(moves);
}

#[derive(Debug, RustcEncodable)]
struct OutputSet {
    old: TransitOid,
    old_time: i64, // Seconds from Epoch
    new: TransitOid,
    new_time: i64, // Seconds from Epoch
    outputs: Vec<Output>,
}

#[derive(Debug, RustcEncodable)]
struct Output {
    old_filename: String,
    new_filename: String,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}

#[derive(Debug, Hash, PartialEq, Eq)]
struct TransitOid(Oid);
impl Display for TransitOid {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        Display::fmt(&self.0, f)
    }
}

impl rustc_serialize::Encodable for TransitOid {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&format!("{}", self)[..])
    }
}
<|endoftext|>


<commit_before>use instr::Instr;
use cpu::Cpu;
use cpu::CpuInterrupt;
use time::precise_time_ns;
use std::fs::File;
use std::cmp::Ordering;
use std::collections::BinaryHeap;

use glium::DisplayBuild;
use glium::Surface;
use glium::SwapBuffersError;
use glium::glutin::Api;
use glium::glutin::GlRequest;
use glium::glutin::Event;

extern crate time;
extern crate getopts;
#[macro_use]
extern crate glium;
extern crate cgmath;

mod instr;
mod cpu;
mod mem;
mod render;

#[derive(Copy, Clone)]
pub enum IntType {
    Vblank,
    Hblank,
    IoTimer,
}

struct ClockInt {
    pub int_target: u64,
    pub int_type: IntType,
}

impl PartialEq for ClockInt {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.int_target == other.int_target
    }
}

impl Eq for ClockInt {}

impl PartialOrd for ClockInt {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.int_target.partial_cmp(&other.int_target) {
            Some(Ordering::Less) => Some(Ordering::Greater),
            Some(Ordering::Greater) => Some(Ordering::Less),
            ord => ord,
        }
    }
}

impl Ord for ClockInt {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        match self.int_target.cmp(&other.int_target) {
            Ordering::Less => Ordering::Greater,
            Ordering::Greater => Ordering::Less,
            ord => ord,
        }
    }
}

const NS_PER_S: u64 = 1_000_000_000;
const MS_PER_NS: u64 = 1_000_000;

// 10ms
const BUSY_WAIT_THRESHOLD: u64 = 10_000_000;

pub struct Clock {
    freq:       u32,
    period:     u64,
    int_heap:   BinaryHeap<ClockInt>,
}

impl Clock {

    pub fn new(freq: u32) -> Clock {
        Clock {
            freq: freq,
            period: NS_PER_S / (freq as u64),
            int_heap: BinaryHeap::new(),
        }
    }

    pub fn set_interrupt(&mut self, itype: IntType, period: u64) {
        let start = precise_time_ns();
        let int = ClockInt {
            int_type: itype,
            int_target: start + period,
        };
        self.int_heap.push(int);
    }

    pub fn wait_cycles(&mut self, n: u32) -> Option<IntType> {
        let start = precise_time_ns();
        let real_wait = self.period * (n as u64);
        let real_target = real_wait + start;
        let (target, result) = if let Some(interrupt) = self.int_heap.pop() {
            if real_target > interrupt.int_target {
                (interrupt.int_target, Some(interrupt.int_type))
            } else {
                self.int_heap.push(interrupt);
                (real_target, None)
            }
        } else {
            (real_target, None)
        };
        let mut curtime = start;
        if target > start && target - start > BUSY_WAIT_THRESHOLD {
            std::thread::sleep_ms(((target - start) * MS_PER_NS) as u32);
            return result;
        } else {
            loop {
                if curtime >= target {
                    return result;
                }
                curtime = precise_time_ns();
            }
        }
    }

}

fn main() {
    //  Gather command line args
    let args: Vec<String> = std::env::args().collect();
    let mut opts = getopts::Options::new();
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(e) => panic!("Error: {}", e),
    };
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("No input ROM");
        return;
    };

    // Build graphics context and window
    let display = glium::glutin::WindowBuilder::new()
        .with_title("Gameboy Rust".to_string())
        .with_gl(GlRequest::Specific(Api::OpenGl, (3, 2)))
        .build_glium()
        .unwrap();

    // Do machine initialization
    let mut cpu = Cpu::new();
    cpu.init();
    {
        let mut ram = cpu.get_ram();
        let mut biosfile = match File::open(std::path::Path::new("rom/bios.bin")) {
            Ok(f) => { f },
            Err(e) => {
                println!("Error opening bios file");
                return;
            },
        };
        let mut romfile = match File::open(std::path::Path::new(&input)) {
            Ok(f) => { f },
            Err(e) => {
                println!("Error opening file: {}", e);
                return;
            }
        };
        if let Err(e) = ram.load_bios(&mut biosfile) {
            println!("Error loading bios data: {}", e);
            return;
        }
        if let Err(e) = ram.load_rom(&mut romfile) {
            println!("Error loading rom data: {}", e);
            return;
        }
    }

    // Initialize virtual LCD
    let mut lcd = render::GbDisplay::new(&display);

    let mut viewport = {
        let window = display.get_window();
        let (width, height) = window.unwrap().get_inner_size_pixels().unwrap();
        render::calculate_viewport(width, height)
    };

    // Initialize virtual hardware clocks
    let mut clock = Clock::new(cpu::GB_FREQUENCY);
    clock.set_interrupt(IntType::Vblank, render::VBLANK_PERIOD);
    clock.set_interrupt(IntType::Hblank, render::HBLANK_PERIOD);
    clock.set_interrupt(IntType::IoTimer, cpu::TIMER_BASE_PERIOD_NS);

    // Simulate CPU
    'main: loop {
        // Collect user input
        for ev in display.poll_events() {
            match ev {
                Event::Closed => {
                    break 'main;
                },
                Event::Resized(..) => {
                    let window = display.get_window();
                    let (width, height) = window.unwrap().get_inner_size_pixels().unwrap();
                    viewport = render::calculate_viewport(width, height);
                },
                _ => (),
            }
        }

        // Simulate CPU and hardware timers
        'sim: loop  {
            if let Some(int) = clock.wait_cycles(cpu.do_instr()) {
                // Handle timer interrupt
                match int {
                    // Interrupt at the start of the vblank period
                    IntType::Vblank => {
                        clock.set_interrupt(IntType::Vblank, render::VBLANK_PERIOD);
                        cpu.interrupt(CpuInterrupt::Vblank);
                        let ly = lcd.set_ly_vblank();
                        let ram = cpu.get_ram();
                        ram[mem::IOREG_LY] = ly;
                    }
                    // ~10 H-Blanks occur after the V-Blank starts
                    IntType::Hblank => {
                        clock.set_interrupt(IntType::Hblank, render::HBLANK_PERIOD);
                        let ly = lcd.inc_ly_counter();
                        let ram = cpu.get_ram();
                        ram[mem::IOREG_LY] = ly;
                        // At the end, collect data from VRAM and render it
                        if ly == 0 {
                            break 'sim;
                        }
                    }
                    // Do timer computations
                    IntType::IoTimer => {
                        clock.set_interrupt(IntType::IoTimer, cpu::TIMER_BASE_PERIOD_NS);
                        cpu.inc_io_timer();
                    }
                }
            }
        }

        // Redraw screen
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        lcd.clear_viewport(&mut target, viewport, (1.0, 1.0, 1.0, 1.0));
        lcd.draw(&display, &mut target, viewport, cpu.get_ram());
        match target.finish().err() {
            Some(SwapBuffersError::ContextLost) => {
                panic!("OpenGL contetxt lost!");
            },
            Some(SwapBuffersError::AlreadySwapped) => {
                println!("Warning: OpenGL buffer already swapped");
            },
            None => (),
        }
    }
}
<commit_msg>Flush command buffer at end of render step<commit_after>use instr::Instr;
use cpu::Cpu;
use cpu::CpuInterrupt;
use time::precise_time_ns;
use std::fs::File;
use std::cmp::Ordering;
use std::collections::BinaryHeap;

use glium::DisplayBuild;
use glium::Surface;
use glium::SwapBuffersError;
use glium::glutin::Api;
use glium::glutin::GlRequest;
use glium::glutin::Event;

extern crate time;
extern crate getopts;
#[macro_use]
extern crate glium;
extern crate cgmath;

mod instr;
mod cpu;
mod mem;
mod render;

#[derive(Copy, Clone)]
pub enum IntType {
    Vblank,
    Hblank,
    IoTimer,
}

struct ClockInt {
    pub int_target: u64,
    pub int_type: IntType,
}

impl PartialEq for ClockInt {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.int_target == other.int_target
    }
}

impl Eq for ClockInt {}

impl PartialOrd for ClockInt {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.int_target.partial_cmp(&other.int_target) {
            Some(Ordering::Less) => Some(Ordering::Greater),
            Some(Ordering::Greater) => Some(Ordering::Less),
            ord => ord,
        }
    }
}

impl Ord for ClockInt {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        match self.int_target.cmp(&other.int_target) {
            Ordering::Less => Ordering::Greater,
            Ordering::Greater => Ordering::Less,
            ord => ord,
        }
    }
}

const NS_PER_S: u64 = 1_000_000_000;
const MS_PER_NS: u64 = 1_000_000;

// 10ms
const BUSY_WAIT_THRESHOLD: u64 = 10_000_000;

pub struct Clock {
    freq:       u32,
    period:     u64,
    int_heap:   BinaryHeap<ClockInt>,
}

impl Clock {

    pub fn new(freq: u32) -> Clock {
        Clock {
            freq: freq,
            period: NS_PER_S / (freq as u64),
            int_heap: BinaryHeap::new(),
        }
    }

    pub fn set_interrupt(&mut self, itype: IntType, period: u64) {
        let start = precise_time_ns();
        let int = ClockInt {
            int_type: itype,
            int_target: start + period,
        };
        self.int_heap.push(int);
    }

    pub fn wait_cycles(&mut self, n: u32) -> Option<IntType> {
        let start = precise_time_ns();
        let real_wait = self.period * (n as u64);
        let real_target = real_wait + start;
        let (target, result) = if let Some(interrupt) = self.int_heap.pop() {
            if real_target > interrupt.int_target {
                (interrupt.int_target, Some(interrupt.int_type))
            } else {
                self.int_heap.push(interrupt);
                (real_target, None)
            }
        } else {
            (real_target, None)
        };
        let mut curtime = start;
        if target > start && target - start > BUSY_WAIT_THRESHOLD {
            std::thread::sleep_ms(((target - start) * MS_PER_NS) as u32);
            return result;
        } else {
            loop {
                if curtime >= target {
                    return result;
                }
                curtime = precise_time_ns();
            }
        }
    }

}

fn main() {
    //  Gather command line args
    let args: Vec<String> = std::env::args().collect();
    let mut opts = getopts::Options::new();
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(e) => panic!("Error: {}", e),
    };
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("No input ROM");
        return;
    };

    // Build graphics context and window
    let display = glium::glutin::WindowBuilder::new()
        .with_title("Gameboy Rust".to_string())
        .with_gl(GlRequest::Specific(Api::OpenGl, (3, 2)))
        .build_glium()
        .unwrap();

    // Do machine initialization
    let mut cpu = Cpu::new();
    cpu.init();
    {
        let mut ram = cpu.get_ram();
        let mut biosfile = match File::open(std::path::Path::new("rom/bios.bin")) {
            Ok(f) => { f },
            Err(e) => {
                println!("Error opening bios file");
                return;
            },
        };
        let mut romfile = match File::open(std::path::Path::new(&input)) {
            Ok(f) => { f },
            Err(e) => {
                println!("Error opening file: {}", e);
                return;
            }
        };
        if let Err(e) = ram.load_bios(&mut biosfile) {
            println!("Error loading bios data: {}", e);
            return;
        }
        if let Err(e) = ram.load_rom(&mut romfile) {
            println!("Error loading rom data: {}", e);
            return;
        }
    }

    // Initialize virtual LCD
    let mut lcd = render::GbDisplay::new(&display);

    let mut viewport = {
        let window = display.get_window();
        let (width, height) = window.unwrap().get_inner_size_pixels().unwrap();
        render::calculate_viewport(width, height)
    };

    // Initialize virtual hardware clocks
    let mut clock = Clock::new(cpu::GB_FREQUENCY);
    clock.set_interrupt(IntType::Vblank, render::VBLANK_PERIOD);
    clock.set_interrupt(IntType::Hblank, render::HBLANK_PERIOD);
    clock.set_interrupt(IntType::IoTimer, cpu::TIMER_BASE_PERIOD_NS);

    // Simulate CPU
    'main: loop {
        // Collect user input
        for ev in display.poll_events() {
            match ev {
                Event::Closed => {
                    break 'main;
                },
                Event::Resized(..) => {
                    let window = display.get_window();
                    let (width, height) = window.unwrap().get_inner_size_pixels().unwrap();
                    viewport = render::calculate_viewport(width, height);
                },
                _ => (),
            }
        }

        // Simulate CPU and hardware timers
        'sim: loop  {
            if let Some(int) = clock.wait_cycles(cpu.do_instr()) {
                // Handle timer interrupt
                match int {
                    // Interrupt at the start of the vblank period
                    IntType::Vblank => {
                        clock.set_interrupt(IntType::Vblank, render::VBLANK_PERIOD);
                        cpu.interrupt(CpuInterrupt::Vblank);
                        let ly = lcd.set_ly_vblank();
                        let ram = cpu.get_ram();
                        ram[mem::IOREG_LY] = ly;
                    }
                    // ~10 H-Blanks occur after the V-Blank starts
                    IntType::Hblank => {
                        clock.set_interrupt(IntType::Hblank, render::HBLANK_PERIOD);
                        let ly = lcd.inc_ly_counter();
                        let ram = cpu.get_ram();
                        ram[mem::IOREG_LY] = ly;
                        // At the end, collect data from VRAM and render it
                        if ly == 0 {
                            break 'sim;
                        }
                    }
                    // Do timer computations
                    IntType::IoTimer => {
                        clock.set_interrupt(IntType::IoTimer, cpu::TIMER_BASE_PERIOD_NS);
                        cpu.inc_io_timer();
                    }
                }
            }
        }

        // Redraw screen
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        lcd.clear_viewport(&mut target, viewport, (1.0, 1.0, 1.0, 1.0));
        lcd.draw(&display, &mut target, viewport, cpu.get_ram());
        match target.finish().err() {
            Some(SwapBuffersError::ContextLost) => {
                panic!("OpenGL contetxt lost!");
            },
            Some(SwapBuffersError::AlreadySwapped) => {
                println!("Warning: OpenGL buffer already swapped");
            },
            None => (),
        }
        display.flush();
    }
}
<|endoftext|>


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

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

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

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

use rusqlite::SqliteConnection;

use parse_packets::{parse_header, encode_connect_response};

mod parse_packets;

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

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

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

fn handle_packet(tsock: UdpSocket, src: &SocketAddr, amt: usize, packet: [u8; 2048], conn: &SqliteConnection) {
    let header = parse_header(&packet[0..16]);

    if header.connection_id == 0x41727101980 {
        let uuid = add_new_connection(conn);
        // Now they're in the db, let's say hi
        let encoded = encode_connect_response(uuid, header.transaction_id);
        tsock.send_to(&encoded, src).unwrap();
    }
}

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

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

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

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

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

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

use rusqlite::SqliteConnection;

use parse_packets::{parse_header, encode_connect_response};

mod parse_packets;

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

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

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

fn handle_packet(tsock: UdpSocket, src: &SocketAddr, amt: usize, packet: [u8; 2048], conn: &SqliteConnection) {
    let header = parse_header(&packet[0..16]);

    if header.connection_id == 0x41727101980 {
        let uuid = add_new_connection(conn);
        // Now they're in the db, let's say hi
        let encoded = encode_connect_response(uuid, header.transaction_id);
        tsock.send_to(&encoded, src).unwrap();
    }
}

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

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

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


<commit_before>use std::os;
use std::io;

#[allow(dead_code)]

use ast::Ast;
use parser::Parser;

use ast::ExprAst;
use ast::SymbolNode;

use eval::Evaler;
use std::collections::HashMap;

mod ast;
mod parser;
mod env;
mod eval;
mod test;

fn help() {
    println!("rust-scm: prog");
}

fn add(val: int) -> int {
    return val + 1;
}

#[allow(dead_code)]
fn main() {
    let mut env = HashMap::new();
    env.insert("Haha", add);
    println!("env: {}", env.capacity());

    let mut evaler = Evaler::new();
    let res = evaler.eval("11".to_string());
    res.print();

    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    //assert!(res.as_int() == 11);
    res.print();

    let args = os::args();

    if args.len() < 2 {
        help();
        os::set_exit_status(1);
        return;
    }

    let program = args[0].as_slice();
    println!("args: {} program: {}", args, program);
    let code = match io::File::open(&Path::new(args[1].as_slice())) {
        Ok(mut file) => file.read_to_string().unwrap(),
        Err(_) => {
            os::set_exit_status(1);
            return
        }
    };
    let parser = parser::Parser::new();
    let res = UnicodeChar::is_numeric('a');
    println!("res: {}", res);
    println!("parser: {}", parser);
    println!("code: {}", code);
}
<commit_msg>cleanup<commit_after>use std::os;
use std::io;

#[allow(dead_code)]

use ast::Ast;
use parser::Parser;

use ast::ExprAst;
use ast::SymbolNode;

use eval::Evaler;
use std::collections::HashMap;

mod ast;
mod parser;
mod env;
mod eval;
mod test;

fn help() {
    println!("rust-scm: prog");
}

fn add(val: int) -> int {
    return val + 1;
}

#[allow(dead_code)]
fn main() {
    let mut evaler = Evaler::new();
    let res = evaler.eval("11".to_string());
    res.print();

    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    //assert!(res.as_int() == 11);
    res.print();

    let args = os::args();

    if args.len() < 2 {
        help();
        os::set_exit_status(1);
        return;
    }

    let program = args[0].as_slice();
    println!("args: {} program: {}", args, program);
    let code = match io::File::open(&Path::new(args[1].as_slice())) {
        Ok(mut file) => file.read_to_string().unwrap(),
        Err(_) => {
            os::set_exit_status(1);
            return
        }
    };
    let parser = parser::Parser::new();
    let res = UnicodeChar::is_numeric('a');
    println!("res: {}", res);
    println!("parser: {}", parser);
    println!("code: {}", code);

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

use std::io;
use std::io::prelude::*;
use std::fs::File;

use glium::{DisplayBuild, Surface, Program};
use glium::backend::Facade;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Point {
    position: (f32, f32)
}

implement_vertex!(Point, position);

/// The four corners of OpenGL screen space.
const VERTICES: [Point; 4] = [
    Point { position: (  1.0,  1.0 ) },
    Point { position: ( -1.0,  1.0 ) },
    Point { position: ( -1.0, -1.0 ) },
    Point { position: (  1.0, -1.0 ) },
];

/// Two triangles arranged as a rectangle covering OpenGL screen space.
/// All the real work happens in the fragment shader, so we just want to
/// run the shader on every pixel.
const INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3
];

fn main() {
    let mut builder = glium::glutin::WindowBuilder::new();
    builder.opengl.vsync = true;

    let display = builder.build_glium()
        .expect("failed to build glium window");

    let positions = glium::VertexBuffer::new(&display, &VERTICES)
        .expect("building positions");
    let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &INDICES)
        .expect("building indices");

    let mut dimensions = display.get_framebuffer_dimensions();
    let mut aspect = dimensions.0 as f32 / dimensions.1 as f32;
    let mut c = [ 0.0, 0.0f32 ];

    let mut program = load_shader_program(&display).unwrap();

    loop {
        if let Ok(p) = load_shader_program(&display) {
            program = p;
        }

        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);

        let params = Default::default();
        target.draw(&positions, &indices, &program,
                    &uniform! {
                        screen_to_complex: if aspect < 1.0 {
                            [ 2.0, 2.0 / aspect ]
                        } else {
                            [ 2.0 * aspect, 2.0 ]
                        },
                        c: c },
                    &params)
            .expect("target.draw");
        target.finish().expect("target.finish");

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::Resized(w, h) => {
                    dimensions = (w, h);
                    aspect = dimensions.0 as f32 / dimensions.1 as f32;
                }
                glium::glutin::Event::MouseMoved(x,y) => {
                    // Map pixels to complex coordinates, keeping the circle of radius
                    // two centered at the origin in the middle of the image.
                    if dimensions.0 > dimensions.1 {
                        // Window is wider than it is high.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0 * aspect;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0;
                    } else {
                        // Window is higher than it is wide.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0 / aspect;
                    }
                },
                _ => ()
            }
        }
    }
}

#[derive(Debug)]
struct ShaderError;

impl From<std::io::Error> for ShaderError {
    fn from(e: io::Error) -> ShaderError {
        ShaderError
    }
}

fn read_file(path: &str) -> io::Result<String> {
    let mut s = String::new();
    let mut f = try!(File::open(path));
    try!(f.read_to_string(&mut s));
    Ok(s)
}

fn load_shader_program<F: Facade>(display: &F) -> Result<Program, ShaderError> {
    let vert_shader = try!(read_file("src/julia.vert"));
    let frag_shader = try!(read_file("src/julia.frag"));
    if let Ok(p) = glium::Program::from_source(display, &vert_shader, &frag_shader, None) {
        Ok(p)
    } else {
        Err(ShaderError)
    }
}
<commit_msg>Use include_str! for initial shader loads<commit_after>#[macro_use]
extern crate glium;

use std::io;
use std::io::prelude::*;
use std::fs::File;

use glium::{DisplayBuild, Surface, Program};
use glium::backend::Facade;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Point {
    position: (f32, f32)
}

implement_vertex!(Point, position);

/// The four corners of OpenGL screen space.
const VERTICES: [Point; 4] = [
    Point { position: (  1.0,  1.0 ) },
    Point { position: ( -1.0,  1.0 ) },
    Point { position: ( -1.0, -1.0 ) },
    Point { position: (  1.0, -1.0 ) },
];

/// Two triangles arranged as a rectangle covering OpenGL screen space.
/// All the real work happens in the fragment shader, so we just want to
/// run the shader on every pixel.
const INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3
];

fn main() {
    let mut builder = glium::glutin::WindowBuilder::new();
    builder.opengl.vsync = true;

    let display = builder.build_glium()
        .expect("failed to build glium window");

    let positions = glium::VertexBuffer::new(&display, &VERTICES)
        .expect("building positions");
    let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &INDICES)
        .expect("building indices");

    let mut program = Program::from_source(&display,
                                           &include_str!("julia.vert"),
                                           &include_str!("julia.frag"),
                                           None)
        .expect("building program");

    let mut dimensions = display.get_framebuffer_dimensions();
    let mut aspect = dimensions.0 as f32 / dimensions.1 as f32;
    let mut c = [ 0.0, 0.0f32 ];

    loop {
        if let Ok(p) = load_shader_program(&display) {
            program = p;
        }

        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);

        let params = Default::default();
        target.draw(&positions, &indices, &program,
                    &uniform! {
                        screen_to_complex: if aspect < 1.0 {
                            [ 2.0, 2.0 / aspect ]
                        } else {
                            [ 2.0 * aspect, 2.0 ]
                        },
                        c: c },
                    &params)
            .expect("target.draw");
        target.finish().expect("target.finish");

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::Resized(w, h) => {
                    dimensions = (w, h);
                    aspect = dimensions.0 as f32 / dimensions.1 as f32;
                }
                glium::glutin::Event::MouseMoved(x,y) => {
                    // Map pixels to complex coordinates, keeping the circle of radius
                    // two centered at the origin in the middle of the image.
                    if dimensions.0 > dimensions.1 {
                        // Window is wider than it is high.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0 * aspect;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0;
                    } else {
                        // Window is higher than it is wide.
                        c[0] = (x as f32 / dimensions.0 as f32 - 0.5) * 2.0;
                        c[1] = (y as f32 / dimensions.1 as f32 - 0.5) * 2.0 / aspect;
                    }
                },
                _ => ()
            }
        }
    }
}

#[derive(Debug)]
struct ShaderError;

impl From<std::io::Error> for ShaderError {
    fn from(e: io::Error) -> ShaderError {
        ShaderError
    }
}

fn read_file(path: &str) -> io::Result<String> {
    let mut s = String::new();
    let mut f = try!(File::open(path));
    try!(f.read_to_string(&mut s));
    Ok(s)
}

fn load_shader_program<F: Facade>(display: &F) -> Result<Program, ShaderError> {
    let vert_shader = try!(read_file("src/julia.vert"));
    let frag_shader = try!(read_file("src/julia.frag"));
    if let Ok(p) = glium::Program::from_source(display, &vert_shader, &frag_shader, None) {
        Ok(p)
    } else {
        Err(ShaderError)
    }
}
<|endoftext|>


<commit_before>//! A very simple HTTP server which responds with the plain text "Hello, World!" to every request.

#![crate_id = "floor#0.0.1"]
#![comment = "A expressjs inspired web framework for Rust"]
#![license = "MIT"]
#![crate_type = "rlib"]

extern crate time;
extern crate http;
extern crate collections;

use collections::hashmap::HashMap;

use std::io::net::ip::{SocketAddr, Ipv4Addr, Port};

use http::server::request::{AbsolutePath};
use http::server::{Config, Server, Request, ResponseWriter};
use http::headers::content_type::MediaType;

#[deriving(Clone)]
pub struct Floor{
    route_store: RouteStore,
    server: Option<Server>
}

#[deriving(Clone)]
struct RouteStore{
    routes: HashMap<String, fn(request: &Request, response: &mut ResponseWriter)>,
}

impl RouteStore {
    fn new () -> RouteStore {
        RouteStore {
            routes: HashMap::new()
        }
    }
}

#[deriving(Clone)]
pub struct Server {
    route_store: RouteStore,
    port: Port
}

impl http::server::Server for Server {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: self.port } }
    }

    fn handle_request(&self, _r: &Request, w: &mut ResponseWriter) {

        //println!("{:?}", _r.request_uri)

        fn set_headers(_r: &Request, w: &mut ResponseWriter) {
            w.headers.date = Some(time::now_utc());

            // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
            w.headers.content_length = None;
            w.headers.content_type = Some(MediaType {
                type_: String::from_str("text"),
                subtype: String::from_str("plain"),
                parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
            });
            w.headers.server = Some(String::from_str("Example"));
        }

        match &_r.request_uri {
            &AbsolutePath(ref url) => {
                match self.route_store.routes.find(url) {
                    Some(item) => {
                        set_headers(_r, w);
                        (*item)(_r, w);
                    },
                    None => {}
                }
            },
            _ => set_headers(_r, w)
        }
    }
}

impl Server {
    fn new(route_store: RouteStore, port: Port) -> Server {
        Server {
            route_store: route_store,
            port: port
        }
    }
}

impl Floor {
    pub fn get(&mut self, uri: &str, handler: fn(request: &Request, response: &mut ResponseWriter)){
        self.route_store.routes.insert(String::from_str(uri), handler);
    }

    pub fn new() -> Floor {
        let routes = RouteStore::new();
        Floor {
            route_store: routes,
            server: None,
        }
    }

    //why do we need this. Is serve_forever like a protected method in C# terms?
    pub fn listen(mut self, port: Port) {
        self.server = Some(Server::new(self.route_store.clone(), port));
        self.server.unwrap().serve_forever();
    }
}<commit_msg>chore(main.rs): remove dated comment<commit_after>//! A very simple HTTP server which responds with the plain text "Hello, World!" to every request.

#![crate_id = "floor#0.0.1"]
#![comment = "A expressjs inspired web framework for Rust"]
#![license = "MIT"]
#![crate_type = "rlib"]

extern crate time;
extern crate http;
extern crate collections;

use collections::hashmap::HashMap;

use std::io::net::ip::{SocketAddr, Ipv4Addr, Port};

use http::server::request::{AbsolutePath};
use http::server::{Config, Server, Request, ResponseWriter};
use http::headers::content_type::MediaType;

#[deriving(Clone)]
pub struct Floor{
    route_store: RouteStore,
    server: Option<Server>
}

#[deriving(Clone)]
struct RouteStore{
    routes: HashMap<String, fn(request: &Request, response: &mut ResponseWriter)>,
}

impl RouteStore {
    fn new () -> RouteStore {
        RouteStore {
            routes: HashMap::new()
        }
    }
}

#[deriving(Clone)]
pub struct Server {
    route_store: RouteStore,
    port: Port
}

impl http::server::Server for Server {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: self.port } }
    }

    fn handle_request(&self, _r: &Request, w: &mut ResponseWriter) {

        //println!("{:?}", _r.request_uri)

        fn set_headers(_r: &Request, w: &mut ResponseWriter) {
            w.headers.date = Some(time::now_utc());

            // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
            w.headers.content_length = None;
            w.headers.content_type = Some(MediaType {
                type_: String::from_str("text"),
                subtype: String::from_str("plain"),
                parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
            });
            w.headers.server = Some(String::from_str("Example"));
        }

        match &_r.request_uri {
            &AbsolutePath(ref url) => {
                match self.route_store.routes.find(url) {
                    Some(item) => {
                        set_headers(_r, w);
                        (*item)(_r, w);
                    },
                    None => {}
                }
            },
            _ => set_headers(_r, w)
        }
    }
}

impl Server {
    fn new(route_store: RouteStore, port: Port) -> Server {
        Server {
            route_store: route_store,
            port: port
        }
    }
}

impl Floor {
    pub fn get(&mut self, uri: &str, handler: fn(request: &Request, response: &mut ResponseWriter)){
        self.route_store.routes.insert(String::from_str(uri), handler);
    }

    pub fn new() -> Floor {
        let routes = RouteStore::new();
        Floor {
            route_store: routes,
            server: None,
        }
    }

    pub fn listen(mut self, port: Port) {
        self.server = Some(Server::new(self.route_store.clone(), port));
        self.server.unwrap().serve_forever();
    }
}<|endoftext|>