<commit_before>extern crate feroxide_gui;
use feroxide_gui::*;

extern crate feroxide;
use feroxide::*;
<<<<<<< HEAD
use feroxide::data_atoms::*;

extern crate gtk;
use gtk::prelude::*;
use gtk::*;

use std::rc::Rc;
use std::cell::RefCell;

macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

fn main() {
    #![allow(unused)]

    println!("Hello World!");

    // Testing feroxide
    println!("Water has {} g/mol",
             Molecule::from_string("H2O".to_owned()).unwrap().mass());

    // Get reaction
    let reaction_water =
        ElemReaction::<Molecule>::molecule_from_string("2H2 + O2 → 2H2O".to_owned()).unwrap();

    // Create container
    let mut fo_container = Rc::new(RefCell::new(feroxide::Container::<Molecule> {
                                                    contents: vec![],
                                                    available_energy: Energy::from(0.0),
                                                }));

    // Initialise GTK
    if gtk::init().is_err() {
        panic!("Failed to initialise GTK.");
    }

    // Create window
    let window = Window::new(WindowType::Toplevel);
    window.set_title("feroxide");
    window.set_position(WindowPosition::Center);
    window.set_size_request(400, 400);

    window.connect_delete_event(|_, _| {
                                    gtk::main_quit();
                                    Inhibit(false)
                                });

    //////// Menu bar
    let menu_bar = MenuBar::new();
=======
>>>>>>> 714ddde (Convert to Piston library)

extern crate piston_window;
use piston_window::*;
use piston_window::types::*;

use std::process;

// You could specify another OpenGL version here,
// None will use the default one
const OPENGL: Option<OpenGL> = None;

const TITLE: &str = "Feroxide";
const DIMENSIONS: (u32, u32) = (1000, 200);
const FONT_PATH: &str = "/usr/share/fonts/TTF/VeraMono.ttf";
const FONT_SIZE: FontSize = 20;

const CTRL_C: &str = "\u{3}";

fn set_up_window() -> PistonWindow {
    let window_settings = WindowSettings::new(TITLE, DIMENSIONS)
        .decorated(true)
        .exit_on_esc(true)
        .maybe_opengl(OPENGL)
        .resizable(true)
        .vsync(false);

    let mut window: PistonWindow = window_settings.build().unwrap();

    window.set_lazy(false);
    window.set_max_fps(60);

    window
}

fn get_glyphs(window: &PistonWindow) -> Glyphs {
    let factory = window.factory.clone();
    let texture_settings = TextureSettings::new();

    Glyphs::new(FONT_PATH, factory, texture_settings).unwrap()
}

fn main() {
    let mut window = set_up_window();
    let mut glyphs = get_glyphs(&window);

<<<<<<< HEAD
        fo_container.add_elements(&[
            ContainerCompound {
                element: molecule_from_atom!(HYDROGEN),
                moles: Moles::from(10.0)
            }
        ]);

        println!("{}", fo_container.stringify());
    }));

    item_add_atoms_oxygen.connect_activate(clone!(fo_container => move |_| {
        let mut fo_container = fo_container.borrow_mut();

        fo_container.add_elements(&[
            ContainerCompound {
                element: molecule_from_atom!(OXYGEN),
                moles: Moles::from(10.0)
            }
        ]);

        println!("{}", fo_container.stringify());
    }));

    item_add_energy.connect_activate(clone!(fo_container => move |_| {
        let mut fo_container = fo_container.borrow_mut();

        fo_container.available_energy += Energy::from(100.0);

        println!("{}", fo_container.stringify());
    }));
=======
    let mut container = Container {
        contents: vec! {
            ContainerCompound {
                element: Ion::from_string("H2".to_owned()).unwrap(),
                moles: Moles::from(2000.0)
            },
            ContainerCompound {
                element: Ion::from_string("O2".to_owned()).unwrap(),
                moles: Moles::from(1000.0)
            },
            ContainerCompound {
                element: Ion::from_string("H2O".to_owned()).unwrap(),
                moles: Moles::from(1000.0)
            },
        },
        available_energy: Energy::from(10_000.0),
    };
>>>>>>> 714ddde (Convert to Piston library)

    let water_reaction_right = ElemReaction::<Ion>::ion_from_string("2H2 + O2 > 2H2O".to_owned()).unwrap();
    let water_reaction_left  = ElemReaction::<Ion>::ion_from_string("2 H2O < 2H2 + O2".to_owned()).unwrap();

    while let Some(event) = window.next() {

        /*
        if let Some(button_args) = event.button_args() {
            if button_args.button == Button::Mouse(MouseButton::Left) && button_args.state == ButtonState::Press {
                container.react(&water_reaction);
            }
        }
        */

        if let Some(string) = event.text_args() {
            if string == ">" {
                container.react(&water_reaction_right);
            }
            else if string == "<" {
                container.react(&water_reaction_left);
            }
            else if string == CTRL_C {
                process::exit(0);
            }
        }

        window.draw_2d(&event, |ctx, g2d| {
            // Clear screen
            clear(colors::WHITE, g2d);

            let mut line_nr = 1;
            let mut print_line = |string: String, color: Color| {
                text::Text::new_color(color, FONT_SIZE)
                    .draw(
                        &string,
                        &mut glyphs,
                        &ctx.draw_state,
                        ctx.transform.trans(10.0, (line_nr * FONT_SIZE * 2) as Scalar),
                        g2d,
                    );

                line_nr += 1;
            };

            // Write reactions
            print_line(format!(">: {}", water_reaction_right), colors::BLACK);
            print_line(format!("<: {}", water_reaction_left), colors::BLACK);

            // Write contents
            let content_string = container.contents.iter().map(|x| { x.name() + "; " }).collect::<String>();
            print_line(content_string, colors::BLACK);

            // Write energy
            let energy_color =
                if container.available_energy <= water_reaction_left.energy_cost() {
                    colors::RED
                } else {
                    colors::BLACK
                };

            print_line(format!("{} J", container.available_energy), energy_color);
        });
    }
}
<commit_msg>Fix clippy issues<commit_after>extern crate feroxide_gui;
use feroxide_gui::*;

extern crate feroxide;
use feroxide::*;
<<<<<<< HEAD
use feroxide::data_atoms::*;

extern crate gtk;
use gtk::prelude::*;
use gtk::*;

use std::rc::Rc;
use std::cell::RefCell;

macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

fn main() {
    #![allow(unused)]

    println!("Hello World!");

    // Testing feroxide
    println!("Water has {} g/mol",
             Molecule::from_string("H2O".to_owned()).unwrap().mass());

    // Get reaction
    let reaction_water =
        ElemReaction::<Molecule>::molecule_from_string("2H2 + O2 → 2H2O".to_owned()).unwrap();

    // Create container
    let mut fo_container = Rc::new(RefCell::new(feroxide::Container::<Molecule> {
                                                    contents: vec![],
                                                    available_energy: Energy::from(0.0),
                                                }));

    // Initialise GTK
    if gtk::init().is_err() {
        panic!("Failed to initialise GTK.");
    }

    // Create window
    let window = Window::new(WindowType::Toplevel);
    window.set_title("feroxide");
    window.set_position(WindowPosition::Center);
    window.set_size_request(400, 400);

    window.connect_delete_event(|_, _| {
                                    gtk::main_quit();
                                    Inhibit(false)
                                });

    //////// Menu bar
    let menu_bar = MenuBar::new();
=======
>>>>>>> 714ddde (Convert to Piston library)

extern crate piston_window;
use piston_window::*;
use piston_window::types::*;

use std::process;

// You could specify another OpenGL version here,
// None will use the default one
const OPENGL: Option<OpenGL> = None;

const TITLE: &str = "Feroxide";
const DIMENSIONS: (u32, u32) = (1000, 200);
const FONT_PATH: &str = "/usr/share/fonts/TTF/VeraMono.ttf";
const FONT_SIZE: FontSize = 20;

const CTRL_C: &str = "\u{3}";

fn set_up_window() -> PistonWindow {
    let window_settings = WindowSettings::new(TITLE, DIMENSIONS)
        .decorated(true)
        .exit_on_esc(true)
        .maybe_opengl(OPENGL)
        .resizable(true)
        .vsync(false);

    let mut window: PistonWindow = window_settings.build().unwrap();

    window.set_lazy(false);
    window.set_max_fps(60);

    window
}

fn get_glyphs(window: &PistonWindow) -> Glyphs {
    let factory = window.factory.clone();
    let texture_settings = TextureSettings::new();

    Glyphs::new(FONT_PATH, factory, texture_settings).unwrap()
}

fn main() {
    let mut window = set_up_window();
    let mut glyphs = get_glyphs(&window);

<<<<<<< HEAD
        fo_container.add_elements(&[
            ContainerCompound {
                element: molecule_from_atom!(HYDROGEN),
                moles: Moles::from(10.0)
            }
        ]);

        println!("{}", fo_container.stringify());
    }));

    item_add_atoms_oxygen.connect_activate(clone!(fo_container => move |_| {
        let mut fo_container = fo_container.borrow_mut();

        fo_container.add_elements(&[
            ContainerCompound {
                element: molecule_from_atom!(OXYGEN),
                moles: Moles::from(10.0)
            }
        ]);

        println!("{}", fo_container.stringify());
    }));

    item_add_energy.connect_activate(clone!(fo_container => move |_| {
        let mut fo_container = fo_container.borrow_mut();

        fo_container.available_energy += Energy::from(100.0);

        println!("{}", fo_container.stringify());
    }));
=======
    let mut container = Container {
        contents: vec! {
            ContainerCompound {
                element: Ion::from_string("H2".to_owned()).unwrap(),
                moles: Moles::from(2000.0)
            },
            ContainerCompound {
                element: Ion::from_string("O2".to_owned()).unwrap(),
                moles: Moles::from(1000.0)
            },
            ContainerCompound {
                element: Ion::from_string("H2O".to_owned()).unwrap(),
                moles: Moles::from(1000.0)
            },
        },
        available_energy: Energy::from(10_000.0),
    };
>>>>>>> 714ddde (Convert to Piston library)

    let water_reaction_right = ElemReaction::<Ion>::ion_from_string("2H2 + O2 > 2H2O".to_owned()).unwrap();
    let water_reaction_left  = ElemReaction::<Ion>::ion_from_string("2 H2O < 2H2 + O2".to_owned()).unwrap();

    while let Some(event) = window.next() {

        /*
        if let Some(button_args) = event.button_args() {
            if button_args.button == Button::Mouse(MouseButton::Left) && button_args.state == ButtonState::Press {
                container.react(&water_reaction);
            }
        }
        */

        if let Some(string) = event.text_args() {
            if string == ">" {
                container.react(&water_reaction_right);
            }
            else if string == "<" {
                container.react(&water_reaction_left);
            }
            else if string == CTRL_C {
                process::exit(0);
            }
        }

        window.draw_2d(&event, |ctx, g2d| {
            // Clear screen
            clear(colors::WHITE, g2d);

            let mut line_nr = 1;
            let mut print_line = |string: String, color: Color| {
                text::Text::new_color(color, FONT_SIZE)
                    .draw(
                        &string,
                        &mut glyphs,
                        &ctx.draw_state,
                        ctx.transform.trans(10.0, Scalar::from(line_nr * FONT_SIZE * 2)),
                        g2d,
                    );

                line_nr += 1;
            };

            // Write reactions
            print_line(format!(">: {}", water_reaction_right), colors::BLACK);
            print_line(format!("<: {}", water_reaction_left), colors::BLACK);

            // Write contents
            let content_string = container.contents.iter().map(|x| { x.name() + "; " }).collect::<String>();
            print_line(content_string, colors::BLACK);

            // Write energy
            let energy_color =
                if container.available_energy <= water_reaction_left.energy_cost() {
                    colors::RED
                } else {
                    colors::BLACK
                };

            print_line(format!("{} J", container.available_energy), energy_color);
        });
    }
}
<|endoftext|>


<commit_before>//! gb-rs: Game Boy emulator
//! Ressources:
//!
//! Opcode map: http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html
//! JS emulator: http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-The-CPU
//! Lots of info about GC quircks: http://www.devrs.com/gb/files/faqs.html
//! Accuracy tests: http://tasvideos.org/EmulatorResources/GBAccuracyTests.html

#![feature(io,core,os,path,std_misc,collections)]
#![warn(missing_docs)]

#[macro_use]
extern crate log;
extern crate sdl2;
extern crate ascii;

#[cfg(test)]
extern crate test;

use std::old_io::Timer;
use std::time::Duration;
use ui::{Controller, Audio};

mod cpu;
mod io;
mod gpu;
mod ui;
mod cartridge;
mod spu;
mod resampler;

#[allow(dead_code)]
fn main() {
    let argv = std::os::args();

    if argv.len() < 2 {
        println!("Usage: {} <rom-file>", argv[0]);
        return;
    }

    let rompath = Path::new(&argv[1]);

    let cart = match cartridge::Cartridge::from_path(&rompath) {
        Ok(r)  => r,
        Err(e) => panic!("Failed to load ROM: {}", e),
    };

    println!("Loaded ROM {:?}", cart);

    let mut display = ui::sdl2::Display::new(1);
    let controller = ui::sdl2::Controller::new();

    let gpu = gpu::Gpu::new(&mut display);

    let (spu, audio_channel) = spu::Spu::new();

    let mut audio = ui::sdl2::Audio::new(audio_channel);

    audio.start();

    let inter = io::Interconnect::new(cart, gpu, spu, controller.buttons());

    let mut cpu = cpu::Cpu::new(inter);

    // In order to synchronize the emulation speed with the wall clock
    // we need to wait at some point so that we don't go too
    // fast. Waiting between each cycle would mean a storm of syscalls
    // back and forth between the kernel and us, so instead we execute
    // instructions in batches of GRANULARITY cycles and then sleep
    // for a while. If the GRANULARITY value is too low we'll go to
    // sleep very often which will have poor performance. If it's too
    // high it might look like the emulation is stuttering.
    let mut timer = match Timer::new() {
        Ok(t)  => t,
        Err(e) => panic!("Couldn't create timer: {}", e),
    };

    let batch_duration = Duration::nanoseconds(GRANULARITY * (1_000_000_000 /
                                                              SYSCLK_FREQ));

    let tick = timer.periodic(batch_duration);

    let mut audio_adjust_count = 0;

    let mut cycles = 0;

    loop {
        while cycles < GRANULARITY {
            // The actual emulator takes place here!
            cycles += cpu.run_next_instruction() as i64;
        }

        cycles -= GRANULARITY;

        // Update controller status
        match controller.update() {
            ui::Event::PowerOff => break,
            ui::Event::None     => (),
        }

        // Sleep until next batch cycle
        if let Err(e) = tick.recv() {
            panic!("Timer died: {:?}", e);
        }

        audio_adjust_count += GRANULARITY;

        if audio_adjust_count >= SYSCLK_FREQ * AUDIO_ADJUST_SEC {
            // Retrieve the number of samples generated since the last
            // adjustment
            let s = spu::samples_per_steps(audio_adjust_count as u32);

            audio.adjust_resampling(s);

            audio_adjust_count = 0;
        }
    }
}

/// Number of instructions executed between sleeps (i.e. giving the
/// hand back to the scheduler). Low values increase CPU usage and can
/// result in poor performance, high values will cause stuttering.
const GRANULARITY:      i64 = 0x10000;

/// Gameboy sysclk frequency: 4.19Mhz
const SYSCLK_FREQ:      i64 = 0x400000;

/// How often should we adjust the audio resampling rate. In seconds.
const AUDIO_ADJUST_SEC: i64 = 1;

#[cfg(test)]
mod benchmark {
    use test::Bencher;
    use ui::Controller;

    use std::thread::Thread;

    #[bench]
    fn bench_rom(b: &mut Bencher) {
        let mut display = ::ui::dummy::DummyDisplay;
        let controller  = ::ui::dummy::DummyController::new();

        let rom = ::std::iter::repeat(0).take(0x4000).collect();
        let cart = ::cartridge::Cartridge::from_vec(rom);

        let (spu, audio_channel) = ::spu::Spu::new();

        Thread::spawn(move|| {
            // Dummy consumer
            audio_channel.recv().unwrap();
        });

        let gpu = ::gpu::Gpu::new(&mut display);

        let inter = ::io::Interconnect::new(cart,
                                            gpu,
                                            spu,
                                            controller.buttons());

        let mut cpu = ::cpu::Cpu::new(inter);

        b.iter(|| {
            cpu.reset();

            // Simulate 100ms of emulated time so that the benchmark
            // doesn't run for too long.
            let mut cycle = 0;

            while cycle < super::SYSCLK_FREQ / 10 {
                cycle += cpu.run_next_instruction() as i64;
            }
        });
    }
}
<commit_msg>Fix warnings about unstable feature "test" in test builds<commit_after>//! gb-rs: Game Boy emulator
//! Ressources:
//!
//! Opcode map: http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html
//! JS emulator: http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-The-CPU
//! Lots of info about GC quircks: http://www.devrs.com/gb/files/faqs.html
//! Accuracy tests: http://tasvideos.org/EmulatorResources/GBAccuracyTests.html

#![feature(io,core,os,path,std_misc,collections)]
#![cfg_attr(test, feature(test))]

#![warn(missing_docs)]

#[macro_use]
extern crate log;
extern crate sdl2;
extern crate ascii;

#[cfg(test)]
extern crate test;

use std::old_io::Timer;
use std::time::Duration;
use ui::{Controller, Audio};

mod cpu;
mod io;
mod gpu;
mod ui;
mod cartridge;
mod spu;
mod resampler;

#[allow(dead_code)]
fn main() {
    let argv = std::os::args();

    if argv.len() < 2 {
        println!("Usage: {} <rom-file>", argv[0]);
        return;
    }

    let rompath = Path::new(&argv[1]);

    let cart = match cartridge::Cartridge::from_path(&rompath) {
        Ok(r)  => r,
        Err(e) => panic!("Failed to load ROM: {}", e),
    };

    println!("Loaded ROM {:?}", cart);

    let mut display = ui::sdl2::Display::new(1);
    let controller = ui::sdl2::Controller::new();

    let gpu = gpu::Gpu::new(&mut display);

    let (spu, audio_channel) = spu::Spu::new();

    let mut audio = ui::sdl2::Audio::new(audio_channel);

    audio.start();

    let inter = io::Interconnect::new(cart, gpu, spu, controller.buttons());

    let mut cpu = cpu::Cpu::new(inter);

    // In order to synchronize the emulation speed with the wall clock
    // we need to wait at some point so that we don't go too
    // fast. Waiting between each cycle would mean a storm of syscalls
    // back and forth between the kernel and us, so instead we execute
    // instructions in batches of GRANULARITY cycles and then sleep
    // for a while. If the GRANULARITY value is too low we'll go to
    // sleep very often which will have poor performance. If it's too
    // high it might look like the emulation is stuttering.
    let mut timer = match Timer::new() {
        Ok(t)  => t,
        Err(e) => panic!("Couldn't create timer: {}", e),
    };

    let batch_duration = Duration::nanoseconds(GRANULARITY * (1_000_000_000 /
                                                              SYSCLK_FREQ));

    let tick = timer.periodic(batch_duration);

    let mut audio_adjust_count = 0;

    let mut cycles = 0;

    loop {
        while cycles < GRANULARITY {
            // The actual emulator takes place here!
            cycles += cpu.run_next_instruction() as i64;
        }

        cycles -= GRANULARITY;

        // Update controller status
        match controller.update() {
            ui::Event::PowerOff => break,
            ui::Event::None     => (),
        }

        // Sleep until next batch cycle
        if let Err(e) = tick.recv() {
            panic!("Timer died: {:?}", e);
        }

        audio_adjust_count += GRANULARITY;

        if audio_adjust_count >= SYSCLK_FREQ * AUDIO_ADJUST_SEC {
            // Retrieve the number of samples generated since the last
            // adjustment
            let s = spu::samples_per_steps(audio_adjust_count as u32);

            audio.adjust_resampling(s);

            audio_adjust_count = 0;
        }
    }
}

/// Number of instructions executed between sleeps (i.e. giving the
/// hand back to the scheduler). Low values increase CPU usage and can
/// result in poor performance, high values will cause stuttering.
const GRANULARITY:      i64 = 0x10000;

/// Gameboy sysclk frequency: 4.19Mhz
const SYSCLK_FREQ:      i64 = 0x400000;

/// How often should we adjust the audio resampling rate. In seconds.
const AUDIO_ADJUST_SEC: i64 = 1;

#[cfg(test)]
mod benchmark {
    use test::Bencher;
    use ui::Controller;

    use std::thread::Thread;

    #[bench]
    fn bench_rom(b: &mut Bencher) {
        let mut display = ::ui::dummy::DummyDisplay;
        let controller  = ::ui::dummy::DummyController::new();

        let rom = ::std::iter::repeat(0).take(0x4000).collect();
        let cart = ::cartridge::Cartridge::from_vec(rom);

        let (spu, audio_channel) = ::spu::Spu::new();

        Thread::spawn(move|| {
            // Dummy consumer
            audio_channel.recv().unwrap();
        });

        let gpu = ::gpu::Gpu::new(&mut display);

        let inter = ::io::Interconnect::new(cart,
                                            gpu,
                                            spu,
                                            controller.buttons());

        let mut cpu = ::cpu::Cpu::new(inter);

        b.iter(|| {
            cpu.reset();

            // Simulate 100ms of emulated time so that the benchmark
            // doesn't run for too long.
            let mut cycle = 0;

            while cycle < super::SYSCLK_FREQ / 10 {
                cycle += cpu.run_next_instruction() as i64;
            }
        });
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate futures;
extern crate tokio_minihttp;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;

use futures::future;
use tokio_minihttp::{Request, Response, Http};
use tokio_proto::TcpServer;
use tokio_service::Service;

struct StatusService;

impl Service for StatusService {
    type Request = Request;
    type Response = Response;
    type Error = io::Error;
    type Future = future::Ok<Response, io::Error>;

    fn call(&self, _request: Request) -> Self::Future {
        let (code, message) = match _request.path() {
            "/200" => (200, "OK"),
            "/400" => (400, "Bad Request"),
            "/500" => (500, "Internal Server Error"),
            _ => (404, "Not Found")
        };

        let mut resp = Response::new();
        resp.status_code(code, message);
        resp.body(message);
        future::ok(resp)
    }
}

fn main() {
    drop(env_logger::init());
    let addr = "0.0.0.0:8080".parse().unwrap();
    TcpServer::new(Http, addr)
        .serve(|| Ok(StatusService));
}
<commit_msg>Add handler for all requests.<commit_after>extern crate env_logger;
extern crate futures;
extern crate tokio_minihttp;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;

use futures::future;
use tokio_minihttp::{Request, Response, Http};
use tokio_proto::TcpServer;
use tokio_service::Service;

struct StatusService;

impl Service for StatusService {
    type Request = Request;
    type Response = Response;
    type Error = io::Error;
    type Future = future::Ok<Response, io::Error>;

    fn call(&self, _request: Request) -> Self::Future {
        println!("Request debug: {:?}", _request);
        let method = _request.method();
        // let path = _request.path();
        let mut resp = Response::new();
        // let mut body = format!("{}{}", method, path);
        resp.status_code(200, "OK");
        resp.body(method);
        println!("+ debug: {:?}", _request);
        future::ok(resp)
    }
}

fn main() {
    drop(env_logger::init());
    let addr = "0.0.0.0:8080".parse().unwrap();
    TcpServer::new(Http, addr)
        .serve(|| Ok(StatusService));
}
<|endoftext|>


<commit_before>use std::sync::{Arc, Mutex};
use std::collections::{HashMap, VecDeque};

enum Message<T> {
    Command(String),
    Data(T),
}

struct ActorRef<T: Send + Sized> {
    name: Arc<String>,
    message_queue: Arc<Mutex<VecDeque<Message<T>>>>,
}

impl<T: Send + Sized> ActorRef<T> {
    fn new(name: Arc<String>) -> ActorRef<T> {
        ActorRef {
            name: name,
            message_queue: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn receive(&self, message: Message<T>) {
        self.message_queue.lock().unwrap().push_back(message);
    }

    fn handle(&self) {
        let message;
        {
            message = self.message_queue.lock().unwrap().pop_front();
        }
        let message = message.unwrap();
        match message {
            Message::Command(_) => println!("aya captain"),
            Message::Data(_) => println!("interesting data that you have"),
        }
    }

}

struct ActorSystem<T: Send + Sized> {
    actors_table: Arc<Mutex<HashMap<Arc<String>, ActorRef<T>>>>,
}

impl<T: Send + Sized> ActorSystem<T> {
    fn new() -> ActorSystem<T> {
        ActorSystem {
            actors_table: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    fn create_actor_ref(&self, handle: String) {
        let handle = Arc::new(handle);
        let actor_ref: ActorRef<T> = ActorRef::new(handle.clone());
        {
            let mut actors_table = self.actors_table.lock().unwrap();
            actors_table.insert(handle.clone(), actor_ref);
        }
    }

    fn send_message_to_actor(&self, dont_judge_me: Arc<String>, message: Message<T>) {
        let actors_table = self.actors_table.lock().unwrap();
        // Here this is very bad as get gives a ref, and thus we need to keep the lock for a long
        // time (and we also need the actor's message queue lock).
        let actor_ref = actors_table.get(&dont_judge_me.clone());
        match actor_ref {
            Some(actor_ref) => {
                println!("yay");
                actor_ref.receive(message);
                actor_ref.handle();
            }
            None => println!("oh noes"),
        }
    }
}

fn main() {
    let actor_system: ActorSystem<i32> = ActorSystem::new();
    actor_system.create_actor_ref("actor1".to_string());
    actor_system.create_actor_ref("actor2".to_string());
    actor_system.send_message_to_actor(Arc::new("actor1".to_string()), Message::Data(1i32));
    actor_system.send_message_to_actor(Arc::new("actor2".to_string()), Message::Data("ay ay"));

    println!("Hello world");
}
<commit_msg>Proper ActorRef, with trait ojects, also removed genericity from the Message using Any<commit_after>use std::any::Any;
use std::collections::{HashSet, VecDeque};
use std::sync::{Arc, Mutex};

enum Message {
    Command(String),
    Data(Box<Any + Send>),
}

type ActorRef = Arc<Mutex<Actor>>;

trait Actor {
    fn receive(&mut self, Message);
    fn handle_message(&mut self);
}

struct Printer {
    name: String,
    message_queue: VecDeque<Message>,
}

impl Printer {
    fn new(name: String) -> Printer {
        Printer {
            name: name,
            message_queue: VecDeque::new(),
        }
    }
}

impl Actor for Printer {
    fn receive(&mut self, message: Message) {
        self.message_queue.push_back(message);
    }

    fn handle_message(&mut self) {
        let message = self.message_queue.pop_front().unwrap();

        match message {
            Message::Command(command) => {
                println!("Received Command: ({})", command)
            },
            Message::Data(truc) => {
                match truc.downcast_ref::<String>() {
                    Some(s) => println!("Received data: ({})", s),
                    None => println!("Message is dropped"),
                }
            }
        }
    }
}

struct ActorSystem {
    // TODO(gamazeps): Use an unordered container instead.
    // There is currently an issue with having an ActorRef as a Arc<Mutex<Actor + Eq + Hash>>.
    actors_table: Mutex<Vec<ActorRef>>,
    actors_queue: Arc<Mutex<VecDeque<ActorRef>>>,
}

impl ActorSystem {
    fn new() -> ActorSystem {
        ActorSystem {
            actors_table: Mutex::new(Vec::new()),
            actors_queue: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn spawn_actor(&self, name: String) -> ActorRef {
        let actor_ref = Arc::new(Mutex::new(Printer::new(name)));
        {
            let mut actors_table = self.actors_table.lock().unwrap();
            actors_table.push(actor_ref.clone());
        }
        actor_ref
    }

    fn send_to_actor(&self, actor_ref: ActorRef, message: Message) {
        {
            let mut actor = actor_ref.lock().unwrap();
            actor.receive(message);
        }
        {
            let mut actors_queue = self.actors_queue.lock().unwrap();
            actors_queue.push_back(actor_ref);
        }
    }
}

fn main() {
    let message = "This is a message".to_string();
    let command = "This is a command".to_string();

    let mut actor = Printer::new("actor_1".to_string());

    actor.receive(Message::Command(command));
    actor.receive(Message::Data(Box::new(message)));
    actor.receive(Message::Data(Box::new(3i32)));

    actor.handle_message();
    actor.handle_message();
    actor.handle_message();
}
<|endoftext|>


<commit_before>extern crate sendgrid;
extern crate time;

use sendgrid::mail::Mail;
use sendgrid::sg_client::SGClient;

fn main() {
    let mut env_vars = std::env::vars();
    let api_key_check = env_vars.find(|var| var.0 == "SENDGRID_API_KEY");
    let api_key: String;
    match api_key_check {
        Some(key) => api_key = key.1,
        None => panic!("Must supply API key in environment variables to use!"),
    }

    let sg = SGClient::new(api_key);

    let mut mail_info = Mail::new();
    mail_info.add_to("garrettsquire@gmail.com");
    mail_info.add_from("garrett.squire@sendgrid.net");
    mail_info.add_subject("Rust is rad");
    mail_info.add_text("What's up?");

    let mut x_smtpapi = String::new();
    x_smtpapi.push_str("{\"unique_args\":{\"test\":7}}");
    mail_info.add_x_smtpapi(x_smtpapi);

    sg.send(mail_info);
}
<commit_msg>just use the examples folder<commit_after>fn main() {
    println!("See the examples folder!");
}
<|endoftext|>


<commit_before>// This needs to be here
#![allow(dead_code)]

extern crate libc;
extern crate term;

use libc::{c_uint, c_uchar, c_int, c_short, c_long, c_ulong};
use libc::{clock_t, pid_t, uid_t, size_t};
use std::io;
use std::mem;
use std::ptr;

// used in Termios struct
const NCCS:uint = 32;

// stdin, stdout, stderr have standard file descriptors
const STDIN:c_int = 0;

// constants for control sequences is useful
const EOF:char = '\u{4}';
const DEL:char = '\u{7f}';
const NL:char  = '\n';
const ESC:char = '\u{1b}';

// select termios constants that we use
const ICANON:c_uint   = 2;
const ECHO:c_uint     = 8;
const TCSANOW:c_int   = 0;
const TCSADRAIN:c_int = 1;
const TCSAFLUSH:c_int = 2;

// signal values
const SIGHUP:c_int    = 1;       /* Hangup (POSIX).  */
const SIGINT:c_int    = 2;       /* Interrupt (ANSI).  */
const SIGQUIT:c_int   = 3;       /* Quit (POSIX).  */
const SIGILL:c_int    = 4;       /* Illegal instruction (ANSI).  */
const SIGTRAP:c_int   = 5;       /* Trace trap (POSIX).  */
const SIGABRT:c_int   = 6;       /* Abort (ANSI).  */
const SIGIOT:c_int    = 6;       /* IOT trap (4.2 BSD).  */
const SIGBUS:c_int    = 7;       /* BUS error (4.2 BSD).  */
const SIGFPE:c_int    = 8;       /* Floating-point exception (ANSI).  */
const SIGKILL:c_int   = 9;       /* Kill, unblockable (POSIX).  */
const SIGUSR1:c_int   = 10;      /* User-defined signal 1 (POSIX).  */
const SIGSEGV:c_int   = 11;      /* Segmentation violation (ANSI).  */
const SIGUSR2:c_int   = 12;      /* User-defined signal 2 (POSIX).  */
const SIGPIPE:c_int   = 13;      /* Broken pipe (POSIX).  */
const SIGALRM:c_int   = 14;      /* Alarm clock (POSIX).  */
const SIGTERM:c_int   = 15;      /* Termination (ANSI).  */
const SIGSTKFLT:c_int = 16;      /* Stack fault.  */
const SIGCLD:c_int    = SIGCHLD; /* Same as SIGCHLD (System V).  */
const SIGCHLD:c_int   = 17;      /* Child status has changed (POSIX).  */
const SIGCONT:c_int   = 18;      /* Continue (POSIX).  */
const SIGSTOP:c_int   = 19;      /* Stop, unblockable (POSIX).  */
const SIGTSTP:c_int   = 20;      /* Keyboard stop (POSIX).  */
const SIGTTIN:c_int   = 21;      /* Background read from tty (POSIX).  */
const SIGTTOU:c_int   = 22;      /* Background write to tty (POSIX).  */
const SIGURG:c_int    = 23;      /* Urgent condition on socket (4.2 BSD).  */
const SIGXCPU:c_int   = 24;      /* CPU limit exceeded (4.2 BSD).  */
const SIGXFSZ:c_int   = 25;      /* File size limit exceeded (4.2 BSD).  */
const SIGVTALRM:c_int = 26;      /* Virtual alarm clock (4.2 BSD).  */
const SIGPROF:c_int   = 27;      /* Profiling alarm clock (4.2 BSD).  */
const SIGWINCH:c_int  = 28;      /* Window size change (4.3 BSD, Sun).  */
const SIGPOLL:c_int   = SIGIO;   /* Pollable event occurred (System V).  */
const SIGIO:c_int     = 29;      /* I/O now possible (4.2 BSD).  */
const SIGPWR:c_int    = 30;      /* Power failure restart (System V).  */
const SIGSYS:c_int    = 31;      /* Bad system call.  */
const SIGUNUSED:c_int = 31;

// sizeof(int) = 4
// sizeof(unsigned long int) = 8
const SI_MAX_SIZE:uint = 128;
const SI_PAD_SIZE:uint = (SI_MAX_SIZE / 4)  - 4;
const SIGSET_NWORDS:uint = (1024 / (8 * 8));

const SA_NOCLDSTOP:c_int = 1;
const SA_NOCLDWAIT:c_int = 2;
const SA_SIGINFO:c_int   = 4;
const SA_RESTART:c_int   = 0x10000000;

// types used in Termios struct
type CCType = c_uchar;
type SpeedType = c_uint;
type TCFlag = c_uint;

#[repr(C)]
#[deriving(Copy)]
#[deriving(Clone)]
struct Termios {
    iflag: TCFlag,
    oflag: TCFlag,
    cflag: TCFlag,
    lflag: TCFlag,
    line: CCType,
    cc: [c_uchar, ..NCCS],
    ispeed: SpeedType,
    ospeed: SpeedType,
}

impl Termios {
    fn new() -> Termios {
        Termios {
            cc: [0, ..NCCS],
            cflag: 0,
            iflag: 0,
            ispeed: 0,
            lflag: 0,
            line: 0,
            oflag: 0,
            ospeed: 0,
        }
    }

    fn get_from(&mut self, fd:c_int) -> bool {
        unsafe {
            return tcgetattr(fd, self) == 0;
        }
    }

    fn get(&mut self) -> bool {
        self.get_from(STDIN)
    }

    fn set_to(&self, fd:c_int) -> bool {
        unsafe {
            return tcsetattr(fd, TCSANOW, self) == 0;
        }
    }

    fn set(&self) -> bool {
        self.set_to(STDIN)
    }

    fn lenable(&mut self, flag:c_uint) {
        self.lflag |= flag;
    }

    fn ldisable(&mut self, flag:c_uint) {
        self.lflag &= !flag;
    }
}

#[link(name = "c")]
extern {
    fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
    fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const Termios) -> c_int;
}

// This could also be a pointer,
// but it probably isn't
type SigVal = c_int;

// _pad is needed to make all these types the same size
// this is the case because rust doesn't have an equivalent to C unions
// it's really a bitch
// at least let me transmute between different sized types I mean jesus christ

struct KillFields {
    pid: pid_t,
    uid: uid_t,
    _pad: [c_int, ..(SI_PAD_SIZE - 2)]
}

struct PTimerFields {
    tid: c_int,
    overrun: c_int,
    sigval: SigVal,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct PSignalFields {
    pid: pid_t,
    uid: uid_t,
    sigval: SigVal,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigChldFields {
    pid: pid_t,
    uid: uid_t,
    status: c_int,
    utime: clock_t,
    stime: clock_t,
    _pad: [c_int, ..(SI_PAD_SIZE - 8)]
}

struct SigFaultFields {
    addr: size_t, // pointer
    addr_lsb: c_short,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigPollFields {
    band: c_long,
    fd: c_int,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigSysFields {
    _call_addr: size_t, // pointer
    _syscall: c_int,
    _arch: c_uint,
    _pad: [c_int, ..(SI_PAD_SIZE - 4)]
}

// If only Rust had a C union equivalent...
enum SigFields {
    Kill(KillFields),
    PTimer(PTimerFields),
    PSignal(PSignalFields),
    SigChld(SigChldFields),
    SigFault(SigFaultFields),
    SigPoll(SigPollFields),
    SigSys(SigSysFields)
}

#[repr(C)]
struct SigInfo {
    signo: c_int,
    errno: c_int,
    code: c_int,

    // Rust doesn't currently support unions for FFI's
    // the best option is to have a generic pad and use
    // transmute to change between types
    // No, you can't just use enums, that would be too easy
    pad: [c_int, ..SI_PAD_SIZE]
}

// The size_t at the end is a pointer to a ucontext_t
// do I want to implement that type? Lol no
// Protip: we're calling sigaction with SA_SIGINFO
// In part because I didn't realize I didn't have to implement
// all of SigInfo, so I did, and now I want to use that code dammit!
type SigHandler = extern fn(c_int, *const SigInfo, size_t);
type SigSet = [c_ulong, ..SIGSET_NWORDS];

#[repr(C)]
struct SigAction {
    handler: SigHandler,
    mask: SigSet,
    flags: c_int
}

impl SigInfo {
    fn determine_sigfields(&self) -> SigFields {
        use SigFields::{Kill, PTimer, PSignal, SigChld, SigFault, SigPoll, SigSys};
        unsafe {
            match self.signo {
                SIGKILL => return Kill(mem::transmute(self.pad)),
                SIGALRM | SIGVTALRM | SIGPROF => return PTimer(mem::transmute(self.pad)),
                SIGCHLD => return SigChld(mem::transmute(self.pad)),
                SIGILL | SIGFPE | SIGSEGV | SIGBUS => return SigFault(mem::transmute(self.pad)),
                SIGPOLL => return SigPoll(mem::transmute(self.pad)),
                SIGSYS => return SigSys(mem::transmute(self.pad)),
                _ => return PSignal(mem::transmute(self.pad))
            }
        }
    }
}

#[link(name="c")]
extern {
    fn sigaction(signum:c_int, act:&SigAction, oldact:*mut SigAction) -> c_int;
    fn sigfillset(mask:*mut SigSet);
}

fn empty_escape(esc:&mut Iterator<char>) -> String {
    let mut out = String::new();
    loop {
        match esc.next() {
            Some(c) => out.push(c),
            None => break
        }
    }
    return out;
}

#[allow(unused_variables)]
extern fn handle_sigint(signum:c_int, siginfo:*const SigInfo, context:size_t) {
    println!("Caught SIGINT");
}

fn prepare_terminal() -> Termios {
    // new terminal mode info
    let mut tios = Termios::new();
    // populate terminal info
    tios.get();
    let tios_clone = tios.clone();
    // turn off canonical mode
    tios.ldisable(ICANON);
    // turn off echo mode
    tios.ldisable(ECHO);
    // set the terminal mode
    update_terminal(tios);
    // return the old terminal mode
    return tios_clone;
}

fn update_terminal(tios:Termios) -> bool {
    if !tios.set() {
        io::stderr().write_line("Warning: Could not set terminal mode").unwrap();
        return false;
    }
    return true;
}

fn handle_escape(stdin:io::stdio::StdinReader) {
    // Handle an ANSI escape sequence
}

fn main() {
    let mut sa = SigAction {
        handler: handle_sigint,
        mask: [0, ..SIGSET_NWORDS],
        flags: SA_RESTART | SA_SIGINFO
    };
    unsafe {
        sigfillset(&mut sa.mask);
        assert!(sigaction(SIGINT, &sa, ptr::null_mut::<SigAction>()) == 0);
    }
    let old_tios = prepare_terminal();
    let mut stdin = io::stdin();
    loop {
        // Note: in non-canonical mode
        match stdin.read_char() {
            Ok(EOF) => break,
            Ok(NL) => {
                print!("\n");
            },
            Ok(DEL) => {
                print!("{} {}", DEL, DEL);
            },
            Ok(c) => {
                print!("{}", c);
            },
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        }
    }
    // print so we know we've reached this code
    println!("Exiting");
    // restore old term state
    update_terminal(old_tios);
}
<commit_msg>Implement a line buffer editor<commit_after>// This needs to be here
#![allow(dead_code)]

extern crate libc;
extern crate term;

use libc::{c_uint, c_uchar, c_int, c_short, c_long, c_ulong};
use libc::{clock_t, pid_t, uid_t, size_t};
use std::io;
use std::mem;
use std::ptr;

// used in Termios struct
const NCCS:uint = 32;

// stdin, stdout, stderr have standard file descriptors
const STDIN:c_int = 0;

// constants for control sequences is useful
const EOF:char = '\u{4}';
const DEL:char = '\u{7f}';
const NL:char  = '\n';
const ESC:char = '\u{1b}';
const ANSI:char = '\u{5b}';
const BS:char = '\u{8}';

// select termios constants that we use
const ICANON:c_uint   = 2;
const ECHO:c_uint     = 8;
const TCSANOW:c_int   = 0;
const TCSADRAIN:c_int = 1;
const TCSAFLUSH:c_int = 2;

// signal values
const SIGHUP:c_int    = 1;       /* Hangup (POSIX).  */
const SIGINT:c_int    = 2;       /* Interrupt (ANSI).  */
const SIGQUIT:c_int   = 3;       /* Quit (POSIX).  */
const SIGILL:c_int    = 4;       /* Illegal instruction (ANSI).  */
const SIGTRAP:c_int   = 5;       /* Trace trap (POSIX).  */
const SIGABRT:c_int   = 6;       /* Abort (ANSI).  */
const SIGIOT:c_int    = 6;       /* IOT trap (4.2 BSD).  */
const SIGBUS:c_int    = 7;       /* BUS error (4.2 BSD).  */
const SIGFPE:c_int    = 8;       /* Floating-point exception (ANSI).  */
const SIGKILL:c_int   = 9;       /* Kill, unblockable (POSIX).  */
const SIGUSR1:c_int   = 10;      /* User-defined signal 1 (POSIX).  */
const SIGSEGV:c_int   = 11;      /* Segmentation violation (ANSI).  */
const SIGUSR2:c_int   = 12;      /* User-defined signal 2 (POSIX).  */
const SIGPIPE:c_int   = 13;      /* Broken pipe (POSIX).  */
const SIGALRM:c_int   = 14;      /* Alarm clock (POSIX).  */
const SIGTERM:c_int   = 15;      /* Termination (ANSI).  */
const SIGSTKFLT:c_int = 16;      /* Stack fault.  */
const SIGCLD:c_int    = SIGCHLD; /* Same as SIGCHLD (System V).  */
const SIGCHLD:c_int   = 17;      /* Child status has changed (POSIX).  */
const SIGCONT:c_int   = 18;      /* Continue (POSIX).  */
const SIGSTOP:c_int   = 19;      /* Stop, unblockable (POSIX).  */
const SIGTSTP:c_int   = 20;      /* Keyboard stop (POSIX).  */
const SIGTTIN:c_int   = 21;      /* Background read from tty (POSIX).  */
const SIGTTOU:c_int   = 22;      /* Background write to tty (POSIX).  */
const SIGURG:c_int    = 23;      /* Urgent condition on socket (4.2 BSD).  */
const SIGXCPU:c_int   = 24;      /* CPU limit exceeded (4.2 BSD).  */
const SIGXFSZ:c_int   = 25;      /* File size limit exceeded (4.2 BSD).  */
const SIGVTALRM:c_int = 26;      /* Virtual alarm clock (4.2 BSD).  */
const SIGPROF:c_int   = 27;      /* Profiling alarm clock (4.2 BSD).  */
const SIGWINCH:c_int  = 28;      /* Window size change (4.3 BSD, Sun).  */
const SIGPOLL:c_int   = SIGIO;   /* Pollable event occurred (System V).  */
const SIGIO:c_int     = 29;      /* I/O now possible (4.2 BSD).  */
const SIGPWR:c_int    = 30;      /* Power failure restart (System V).  */
const SIGSYS:c_int    = 31;      /* Bad system call.  */
const SIGUNUSED:c_int = 31;

// sizeof(int) = 4
// sizeof(unsigned long int) = 8
const SI_MAX_SIZE:uint = 128;
const SI_PAD_SIZE:uint = (SI_MAX_SIZE / 4)  - 4;
const SIGSET_NWORDS:uint = (1024 / (8 * 8));

const SA_NOCLDSTOP:c_int = 1;
const SA_NOCLDWAIT:c_int = 2;
const SA_SIGINFO:c_int   = 4;
const SA_RESTART:c_int   = 0x10000000;

// types used in Termios struct
type CCType = c_uchar;
type SpeedType = c_uint;
type TCFlag = c_uint;

#[repr(C)]
#[deriving(Copy)]
#[deriving(Clone)]
struct Termios {
    iflag: TCFlag,
    oflag: TCFlag,
    cflag: TCFlag,
    lflag: TCFlag,
    line: CCType,
    cc: [c_uchar, ..NCCS],
    ispeed: SpeedType,
    ospeed: SpeedType,
}

impl Termios {
    fn new() -> Termios {
        Termios {
            cc: [0, ..NCCS],
            cflag: 0,
            iflag: 0,
            ispeed: 0,
            lflag: 0,
            line: 0,
            oflag: 0,
            ospeed: 0,
        }
    }

    fn get_from(&mut self, fd:c_int) -> bool {
        unsafe {
            return tcgetattr(fd, self) == 0;
        }
    }

    fn get(&mut self) -> bool {
        self.get_from(STDIN)
    }

    fn set_to(&self, fd:c_int) -> bool {
        unsafe {
            return tcsetattr(fd, TCSANOW, self) == 0;
        }
    }

    fn set(&self) -> bool {
        self.set_to(STDIN)
    }

    fn lenable(&mut self, flag:c_uint) {
        self.lflag |= flag;
    }

    fn ldisable(&mut self, flag:c_uint) {
        self.lflag &= !flag;
    }
}

#[link(name = "c")]
extern {
    fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
    fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const Termios) -> c_int;
}

// This could also be a pointer,
// but it probably isn't
type SigVal = c_int;

// _pad is needed to make all these types the same size
// this is the case because rust doesn't have an equivalent to C unions
// it's really a bitch
// at least let me transmute between different sized types I mean jesus christ

struct KillFields {
    pid: pid_t,
    uid: uid_t,
    _pad: [c_int, ..(SI_PAD_SIZE - 2)]
}

struct PTimerFields {
    tid: c_int,
    overrun: c_int,
    sigval: SigVal,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct PSignalFields {
    pid: pid_t,
    uid: uid_t,
    sigval: SigVal,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigChldFields {
    pid: pid_t,
    uid: uid_t,
    status: c_int,
    utime: clock_t,
    stime: clock_t,
    _pad: [c_int, ..(SI_PAD_SIZE - 8)]
}

struct SigFaultFields {
    addr: size_t, // pointer
    addr_lsb: c_short,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigPollFields {
    band: c_long,
    fd: c_int,
    _pad: [c_int, ..(SI_PAD_SIZE - 3)]
}

struct SigSysFields {
    _call_addr: size_t, // pointer
    _syscall: c_int,
    _arch: c_uint,
    _pad: [c_int, ..(SI_PAD_SIZE - 4)]
}

// If only Rust had a C union equivalent...
enum SigFields {
    Kill(KillFields),
    PTimer(PTimerFields),
    PSignal(PSignalFields),
    SigChld(SigChldFields),
    SigFault(SigFaultFields),
    SigPoll(SigPollFields),
    SigSys(SigSysFields)
}

#[repr(C)]
struct SigInfo {
    signo: c_int,
    errno: c_int,
    code: c_int,

    // Rust doesn't currently support unions for FFI's
    // the best option is to have a generic pad and use
    // transmute to change between types
    // No, you can't just use enums, that would be too easy
    pad: [c_int, ..SI_PAD_SIZE]
}

// The size_t at the end is a pointer to a ucontext_t
// do I want to implement that type? Lol no
// Protip: we're calling sigaction with SA_SIGINFO
// In part because I didn't realize I didn't have to implement
// all of SigInfo, so I did, and now I want to use that code dammit!
type SigHandler = extern fn(c_int, *const SigInfo, size_t);
type SigSet = [c_ulong, ..SIGSET_NWORDS];

#[repr(C)]
struct SigAction {
    handler: SigHandler,
    mask: SigSet,
    flags: c_int
}

impl SigInfo {
    fn determine_sigfields(&self) -> SigFields {
        use SigFields::{Kill, PTimer, PSignal, SigChld, SigFault, SigPoll, SigSys};
        unsafe {
            match self.signo {
                SIGKILL => return Kill(mem::transmute(self.pad)),
                SIGALRM | SIGVTALRM | SIGPROF => return PTimer(mem::transmute(self.pad)),
                SIGCHLD => return SigChld(mem::transmute(self.pad)),
                SIGILL | SIGFPE | SIGSEGV | SIGBUS => return SigFault(mem::transmute(self.pad)),
                SIGPOLL => return SigPoll(mem::transmute(self.pad)),
                SIGSYS => return SigSys(mem::transmute(self.pad)),
                _ => return PSignal(mem::transmute(self.pad))
            }
        }
    }
}

#[link(name="c")]
extern {
    fn sigaction(signum:c_int, act:&SigAction, oldact:*mut SigAction) -> c_int;
    fn sigfillset(mask:*mut SigSet);
}

fn empty_escape(esc:&mut Iterator<char>) -> String {
    let mut out = String::new();
    loop {
        match esc.next() {
            Some(c) => out.push(c),
            None => break
        }
    }
    return out;
}

#[allow(unused_variables)]
extern fn handle_sigint(signum:c_int, siginfo:*const SigInfo, context:size_t) {
    println!("Caught SIGINT");
}

fn prepare_terminal() -> Termios {
    // new terminal mode info
    let mut tios = Termios::new();
    // populate terminal info
    tios.get();
    let tios_clone = tios.clone();
    // turn off canonical mode
    tios.ldisable(ICANON);
    // turn off echo mode
    tios.ldisable(ECHO);
    // set the terminal mode
    update_terminal(tios);
    // return the old terminal mode
    return tios_clone;
}

fn update_terminal(tios:Termios) -> bool {
    if !tios.set() {
        io::stderr().write_line("Warning: Could not set terminal mode").unwrap();
        return false;
    }
    return true;
}

fn handle_escape(stdin:&mut io::stdio::StdinReader,
                 line:&mut String, part:&mut String) {
    // Handle an ANSI escape sequence
    if stdin.read_char() != Ok(ANSI) {
        return;
    }
    match stdin.read_char() {
        Err(_) => return,
        Ok('D') => {
            match line.pop() {
                Some(c) => {
                    part.push(c);
                    cursor_left();
                },
                None => return
            }
        },
        Ok('C') => {
            match part.pop() {
                Some(c) => {
                    line.push(c);
                    cursor_right();
                },
                None => return
            }
        },
        Ok(_) => return
    }
}

fn redraw_line(line:&String, pad_to:uint) {
    // TODO: make this more optimized
    print!("\r{}", line);
    if pad_to > line.len() {
        let pad_amount = pad_to - line.len();
        print!("{}", String::from_char(pad_amount, ' '));
    }

}

fn cursor_left() {
    print!("{}", DEL);
}

fn cursor_right() {
    print!("{}{}C", ESC, ANSI);
}

fn draw_part(part:&String) {
    // quick out if part is empty
    if part.is_empty() {
        return;
    }
    let mut cpart = part.clone();
    let mut rpart = String::new();
    loop {
        match cpart.pop() {
            Some(c) => rpart.push(c),
            None => break
        }
    }
    print!("{}", rpart);
}

fn cursors_left(by:uint) {
    // move back by a given number of characters
    print!("{}", String::from_char(by, DEL));
}

fn idraw_part(part:&String) {
    // in-place draw of the line part
    draw_part(part);
    cursors_left(part.len());
}

fn main() {
    let mut sa = SigAction {
        handler: handle_sigint,
        mask: [0, ..SIGSET_NWORDS],
        flags: SA_RESTART | SA_SIGINFO
    };
    unsafe {
        sigfillset(&mut sa.mask);
        assert!(sigaction(SIGINT, &sa, ptr::null_mut::<SigAction>()) == 0);
    }
    let old_tios = prepare_terminal();
    let mut stdin = io::stdin();
    let mut line = String::new();
    let mut part = String::new();
    loop {
        // Note: in non-canonical mode
        match stdin.read_char() {
            Ok(EOF) => break,
            Ok(NL) => {
                line.clear();
                part.clear();
                print!("\n");
            },
            Ok(DEL) => {
                if line.is_empty() {
                    continue;
                }
                line.pop();
                cursor_left();
                draw_part(&part);
                print!(" ");
                cursors_left(part.len() + 1);
            },
            Ok(ESC) => handle_escape(&mut stdin, &mut line, &mut part),
            Ok(c) => {
                line.push(c);
                print!("{}", c);
                idraw_part(&part);
            },
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        }
    }
    // print so we know we've reached this code
    println!("Exiting");
    // restore old term state
    update_terminal(old_tios);
}
<|endoftext|>


<commit_before>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

macro_rules! exit_with_exception {
	($error:ident, $extra:tt) => {
		let _ = write!(&mut std::io::stderr(), "{}\n", $extra);
		let _ = write!(&mut std::io::stderr(), "{}\n", $error);
		std::process::exit(-1);
	};
}

fn print_usage(program: &str, opts: Options, include_info: bool, include_copyright: bool) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let copyright = "rewrite 0.2 by NeoSmart Technologies. Written by Mahmoud Al-Qudsi <mqudsi@neosmart.net>";
    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even where FILE is being read by \
                upstream command";

    if include_copyright {
        println!("{}", copyright);
    }
    if include_info {
        println!("{}", info);
    }
    print!("{}", opts.usage(&brief));
}

fn redirect_to_file(outfile: &str) -> Result<(), &str> {
    // create the temporary file in the same directory as outfile
    // this lets us guarantee a rename (instead of a move) on completion
    let mut tempfile = PathBuf::from(outfile);
    tempfile.pop(); //now refers to parent, which might be nothing
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create temporary output file!");
        });

        loop {
            let read_bytes = stdin.read(&mut buffer).unwrap_or_else(|e| {
                exit_with_exception!(e, "Error reading from stdin!");
            });
            if read_bytes == 0 {
                break;
            }

            let write_bytes = f.write(&buffer[0..read_bytes]).unwrap_or_else(|e| {
                exit_with_exception!(e, "Failed to write to temporary output file!");
            });

            assert!(write_bytes == read_bytes);
        }
    }

    std::fs::rename(&tempfile, &outfile).unwrap_or_else(|_x| {
        // fs::rename does not support cross-device linking
        // copy and delete instead
        std::fs::copy(&tempfile, &outfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create output file!");
        });
        std::fs::remove_file(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to delete temporary output file!");
        });
    });

    return Ok(());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            print!("{}\n", e);
            print_usage(&program, opts, false, false);
            return;
        }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts, true, true);
        return;
    }
    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, true, false);
        return;
    };

    assert!(redirect_to_file(&infile).is_ok());
}
<commit_msg>Clean up error handling<commit_after>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

macro_rules! exit_with_exception {
	($error:ident, $extra:tt) => {
		let _ = write!(&mut std::io::stderr(), "{}\n", $extra);
		let _ = write!(&mut std::io::stderr(), "{}\n", $error);
		std::process::exit(-1);
	};
}

fn print_usage(program: &str, opts: Options, include_info: bool, include_copyright: bool) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let copyright = "rewrite 0.2 by NeoSmart Technologies. Written by Mahmoud Al-Qudsi <mqudsi@neosmart.net>";
    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even where FILE is being read by \
                upstream command";

    if include_copyright {
        println!("{}", copyright);
    }
    if include_info {
        println!("{}", info);
    }
    print!("{}", opts.usage(&brief));
}

fn redirect_to_file(outfile: &str) {
    // Create the temporary file in the same directory as outfile this lets us guarantee a rename
    // (instead of a move) on completion
    let mut tempfile = PathBuf::from(outfile);
    tempfile.pop(); // Now refers to parent, which might be nothing
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create temporary output file!");
        });

        loop {
            let read_bytes = stdin.read(&mut buffer).unwrap_or_else(|e| {
                exit_with_exception!(e, "Error reading from stdin!");
            });
            if read_bytes == 0 {
                break;
            }

            let write_bytes = f.write(&buffer[0..read_bytes]).unwrap_or_else(|e| {
                exit_with_exception!(e, "Failed to write to temporary output file!");
            });

            debug_assert!(write_bytes == read_bytes);
        }
    }

    std::fs::rename(&tempfile, &outfile).unwrap_or_else(|_x| {
        // fs::rename() does not support cross-device linking.
        // Copy and delete instead.
        std::fs::copy(&tempfile, &outfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create output file!");
        });
        std::fs::remove_file(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to delete temporary output file!");
        });
    });
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            println!("{}", e);
            print_usage(&program, opts, false, false);
            return;
        }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts, true, true);
        return;
    }
    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, true, false);
        return;
    };

    redirect_to_file(&infile);
}
<|endoftext|>


<commit_before>extern crate time;
use time::{Timespec, Duration};
use std::thread;

macro_rules! printfl {
    ($($tt:tt)*) => {{
        use std::io::{self, Write};
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

pub struct ProgressBar {
    start_time: Timespec,
    total: i64,
    current: i64,
    is_finish: bool,
}

impl ProgressBar {
    pub fn new(total: i64) -> ProgressBar {
            ProgressBar {
                total: total,
                current: 0,
                start_time: time::get_time(),
                is_finish: false,
            }
    }

    fn add(&mut self, i: i64) -> i64 {
        self.current += i;
        if self.current <= self.total {
            self.write()
        };
        self.current
    }

    fn write(&self) {
        let width = 143;    // replace to -> get_tty_size()
        let percent_box;
        let counter_box;
        let mut time_left_box = format!("");
        let speed_box;
        let mut bar_box = "[".to_string();
        let mut out;
        // precent box
        let percent = self.current as f64 / (self.total as f64 / 100f64);
        percent_box = format!(" {:.*} % ", 2, percent);
        // counter box
        counter_box = format!("{} / {} ", self.current, self.total);
        // time left box
        let from_start = time::get_time() - self.start_time;
        let per_entry = from_start / self.current as i32; // Why the hack
        let mut left = per_entry * (self.total - self.current) as i32;
        let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
        left = (left / sec_nano) * sec_nano;
        if left.num_seconds() > 0 {
            time_left_box = format!("{}s", left.num_seconds());
        }
        // NOT WORKING: speed box
        let speed = (from_start / sec_nano) / self.current as i32;
        speed_box = format!("{}/s", speed.num_nanoseconds().unwrap() as f64);
        // bar_box - Add prefix & suffix(2)
        let size = width -
                   (percent_box.to_string() + &counter_box + &time_left_box + &speed_box).len();
        // Test if size > 0
        let curr_count = ((self.current as f64 / self.total as f64) * size as f64).ceil();
        let err_count = size as f64 - curr_count;
        bar_box = bar_box + &std::iter::repeat("=").take(curr_count as usize).collect::<String>();
        if self.current < self.total {
            bar_box = bar_box + ">";
        } else {
            bar_box = bar_box + "=";
        }
        bar_box = bar_box + &std::iter::repeat("-").take(err_count as usize).collect::<String>() +
                  "]";
        out = counter_box.to_string() + &bar_box + &percent_box + &time_left_box;
        // Print
        if out.len() < width {
            let gap = width - out.len();
            out = out + &std::iter::repeat(" ").take(gap as usize).collect::<String>();
        }
        printfl!("\r{}", out);
    }

    fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.write();
        }
        println!("");
        self.is_finish = true;
    }
}

fn main() {
    let mut pb = ProgressBar::new(1000);
    for _ in 0..1000 {
        pb.add(1);
        thread::sleep_ms(2);
    }
    pb.finish();
    print!("The end!");
}
<commit_msg>support usize<commit_after>extern crate time;
use time::{Timespec, Duration};
use std::thread;
use std::ops::Add;
use std::io::{self, Write, Read};

macro_rules! printfl {
    ($($tt:tt)*) => {{
        use std::io::{self, Write};
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

pub struct ProgressBar {
    start_time: Timespec,
    total: usize,
    current: usize,
    is_finish: bool,
}

impl ProgressBar {
    pub fn new(total: usize) -> ProgressBar {
            ProgressBar {
                total: total,
                current: 0,
                start_time: time::get_time(),
                is_finish: false,
            }
    }

    fn add(&mut self, i: usize) -> usize {
        self.current += i;
        if self.current <= self.total {
            self.draw()
        };
        self.current
    }

    fn draw(&self) {
        let width = 143;    // replace to -> get_tty_size()
        let percent_box;
        let counter_box;
        let mut time_left_box = format!("");
        let speed_box;
        let mut bar_box = "[".to_string();
        let mut out;
        // precent box
        let percent = self.current as f64 / (self.total as f64 / 100f64);
        percent_box = format!(" {:.*} % ", 2, percent);
        // counter box
        counter_box = format!("{} / {} ", self.current, self.total);
        // time left box
        let from_start = time::get_time() - self.start_time;
        let per_entry = from_start / self.current as i32; // Why the hack
        let mut left = per_entry * (self.total - self.current) as i32;
        let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
        left = (left / sec_nano) * sec_nano;
        if left.num_seconds() > 0 {
            time_left_box = format!("{}s", left.num_seconds());
        }
        // NOT WORKING: speed box
        let speed = (from_start / sec_nano) / self.current as i32;
        speed_box = format!("{}/s", speed.num_nanoseconds().unwrap() as f64);
        // bar_box - Add prefix & suffix(2)
        let size = width -
                   (percent_box.to_string() + &counter_box + &time_left_box + &speed_box).len();
        // Test if size > 0
        let curr_count = ((self.current as f64 / self.total as f64) * size as f64).ceil();
        let err_count = size as f64 - curr_count;
        bar_box = bar_box + &std::iter::repeat("=").take(curr_count as usize).collect::<String>();
        if self.current < self.total {
            bar_box = bar_box + ">";
        } else {
            bar_box = bar_box + "=";
        }
        bar_box = bar_box + &std::iter::repeat("-").take(err_count as usize).collect::<String>() +
                  "]";
        out = counter_box.to_string() + &bar_box + &percent_box + &time_left_box;
        // Print
        if out.len() < width {
            let gap = width - out.len();
            out = out + &std::iter::repeat(" ").take(gap as usize).collect::<String>();
        }
        printfl!("\r{}", out);
    }

    fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.draw();
        }
        println!("");
        self.is_finish = true;
    }
}

// Implement io::Writer
impl Write for ProgressBar {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.add(n);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

// TODO: Implement io::Reader

fn main() {
    let mut pb = ProgressBar::new(1000);
    for _ in 0..1000 {
        pb.add(1);
        thread::sleep_ms(2);
    }
    pb.finish();
    print!("The end!");

    /*let name = "/usr/share/dict/words";
    let mut file = std::fs::File::open(name).unwrap();
    let bytes = std::fs::metadata(name).unwrap().len() as i64;
    let mut pb = ProgressBar::new(bytes);
    std::io::copy(&mut file, &mut pb).unwrap();
    println!("Done");
    // Create example that use multiWriter and decorateWriter example too
    */
}
<|endoftext|>


<commit_before>#![feature(phase)]
#[phase(plugin, link)] extern crate log;

const U4_LOW:  u8 = 0b00001111;
const U4_HIGH: u8 = 0b11110000;

enum CpuState {
	Continue,
	Halt,
}

struct P150Cpu {
	ip:  u8,
	ir: u16,

	reg: [u8, ..16],
	mem: [u8, ..256],
}

impl P150Cpu {
	fn new() -> P150Cpu {
		P150Cpu {
			ip:  0x0,
			ir:  0x00,

			reg: [0u8, ..16],
			mem: [0u8, ..256],
		}
	}

	fn dump(&self) {
		println!("IP: {}, IR: {}", self.ip, self.ir);

		println!("Registers")
		for (addr, cell) in self.reg.iter().enumerate() {
			println!("{}: {}", addr, cell)
		}
	}

	// Read an array of instructions into memory
	fn init_mem(&mut self, memory: &[u16]) {
		let mut next_cell = 0x00;

		for op in memory.iter() {
			let byte_1 = (*op >> 8) as u8;
			let byte_2 = *op as u8;

			self.mem[next_cell]     = byte_1;
			self.mem[next_cell + 1] = byte_2;
			next_cell += 2
		}
	}

	fn tick(&mut self) -> CpuState {
		self.fetch();

		// decode
		let op = (self.ir >> 12) as u8;
		match op {
			0x0   => { // ADDB
				let rloc_i0 = ((self.ir >> 8) as u8) & U4_LOW;   // first input: lower nibble of first byte
				let rloc_i1 = ((self.ir as u8) & U4_HIGH) >> 4;  // second input: upper nibble of second byte
				let rloc_o0 = (self.ir as u8) & U4_LOW;          // output: lower nibble of second byte

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] + self.reg[rloc_i1 as uint];
				Continue
			},

			0x9   => { // RSET
				let rloc = ((self.ir >> 8) as u8) & U4_MASK; // lower 4 bytes of first byte
				let rval = self.ir as u8;                    // value is entire second byte
				self.reg[rloc as uint] = rval;               // store value in register

				Continue
			},

			0xB   => { // HALT
				Halt
			},
			_     => { debug!("read opcode: {}", op); Continue },
		}
	}

	fn fetch(&mut self) {
		// load PC -> IR
		let byte_1 = self.mem[(self.ip+0) as uint];
		let byte_2 = self.mem[(self.ip+1) as uint];

		self.ir  = (byte_1 as u16 << 8) | (byte_2 as u16);
		self.ip += 2;

		debug!("IR set to {} ({},{})", self.ir, byte_1, byte_2)
	}
}

fn main() {
	let mut cpu = P150Cpu::new();
	let program = [0x911E, 0x920C, 0x0123, 0xB000];
	cpu.init_mem(program);

	// 0x911E => 0x9 (rset), 0x1 (reg), 0x1E (val: 30)
	// 0x920C => 0x9 (rset), 0x2 (reg), 0x0C (val: 12)
	// 0x0123 => 0x0 (addb), 0x1 (in1), 0x2 (in2), 0x3 (out1)

	loop {
		match cpu.tick() {
			Continue => { continue; },
			Halt => { println!("CPU halted."); cpu.dump(); break; },
		}
	}
}

<commit_msg>Allow taking upper or lower nibble<commit_after>#![feature(phase)]
#[phase(plugin, link)] extern crate log;

const U4_LOW:  u8 = 0b00001111;
const U4_HIGH: u8 = 0b11110000;

enum CpuState {
	Continue,
	Halt,
}

struct P150Cpu {
	ip:  u8,
	ir: u16,

	reg: [u8, ..16],
	mem: [u8, ..256],
}

impl P150Cpu {
	fn new() -> P150Cpu {
		P150Cpu {
			ip:  0x0,
			ir:  0x00,

			reg: [0u8, ..16],
			mem: [0u8, ..256],
		}
	}

	fn dump(&self) {
		println!("IP: {}, IR: {}", self.ip, self.ir);

		println!("Registers")
		for (addr, cell) in self.reg.iter().enumerate() {
			println!("{}: {}", addr, cell)
		}
	}

	// Read an array of instructions into memory
	fn init_mem(&mut self, memory: &[u16]) {
		let mut next_cell = 0x00;

		for op in memory.iter() {
			let byte_1 = (*op >> 8) as u8;
			let byte_2 = *op as u8;

			self.mem[next_cell]     = byte_1;
			self.mem[next_cell + 1] = byte_2;
			next_cell += 2
		}
	}

	fn tick(&mut self) -> CpuState {
		self.fetch();

		// decode
		let op = (self.ir >> 12) as u8;
		match op {
			0x0   => { // ADDB
				let rloc_i0 = ((self.ir >> 8) as u8) & U4_LOW;   // first input: lower nibble of first byte
				let rloc_i1 = ((self.ir as u8) & U4_HIGH) >> 4;  // second input: upper nibble of second byte
				let rloc_o0 = (self.ir as u8) & U4_LOW;          // output: lower nibble of second byte

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] + self.reg[rloc_i1 as uint];
				Continue
			},

			0x9   => { // RSET
				let rloc = ((self.ir >> 8) as u8) & U4_LOW;  // lower nibble of first byte
				let rval = self.ir as u8;                    // value is entire second byte
				self.reg[rloc as uint] = rval;               // store value in register

				Continue
			},

			0xB   => { Halt },
			_     => { debug!("read opcode: {}", op); Continue },
		}
	}

	fn fetch(&mut self) {
		// load PC -> IR
		let byte_1 = self.mem[(self.ip+0) as uint];
		let byte_2 = self.mem[(self.ip+1) as uint];

		self.ir  = (byte_1 as u16 << 8) | (byte_2 as u16);
		self.ip += 2;

		debug!("IR set to {} ({},{})", self.ir, byte_1, byte_2)
	}
}

fn main() {
	let mut cpu = P150Cpu::new();
	let program = [0x911E, 0x920C, 0x0123, 0xB000];
	cpu.init_mem(program);

	// 0x911E => 0x9 (rset), 0x1 (reg), 0x1E (val: 30)
	// 0x920C => 0x9 (rset), 0x2 (reg), 0x0C (val: 12)
	// 0x0123 => 0x0 (addb), 0x1 (in1), 0x2 (in2), 0x3 (out1)

	loop {
		match cpu.tick() {
			Continue => { continue; },
			Halt => { println!("CPU halted."); cpu.dump(); break; },
		}
	}
}

<|endoftext|>


<commit_before>extern crate getopts;

use std::process::{Command, Stdio};
use std::io;
use std::io::{Read, Write};
use std::env;

use getopts::{Options, Matches};

#[derive(Debug)]
enum DeleteOption {
    Local,
    Remote,
    Both
}

impl DeleteOption {
    fn new(opts: Matches) -> DeleteOption {
        return if opts.opt_present("l") {
            DeleteOption::Local
        } else if opts.opt_present("r") {
            DeleteOption::Remote
        } else {
            DeleteOption::Both
        };
    }

    fn warning_message(&self) -> String {
        let source = match self {
            &DeleteOption::Local => "locally:",
            &DeleteOption::Remote => "remotely:",
            &DeleteOption::Both => "locally and remotely:",
        };
        "The following branches will be deleted ".to_owned() + source
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("l", "local", "only delete local branches");
    opts.optflag("r", "remote", "only delete remote branches");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(e) => {
            println!("{}", e);
            print_usage(opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return;
    }

    let branches = merged_branches();

    // Early return if there's nothing to delete
    if branches.len() == 0 {
        println!("No branches to delete, you're clean!");
        return;
    }

    let del_opt = DeleteOption::new(matches);

    print_warning(&branches, &del_opt);

    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();

    match input.to_lowercase().as_ref() {
        "y\n" => (),
        "yes\n" => (),
        _ => return,
    }

    match delete_branches(&branches, del_opt) {
        Ok(ref msg) => println!("\n{}", msg),
        Err(ref msg) => println!("\n{}", msg),
    }
}

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

fn print_warning(branches: &String, del_opt: &DeleteOption) {
    println!("{}", del_opt.warning_message());
    println!("{}", format_columns(branches));
    print!("Continue? (yN) ");
    io::stdout().flush().unwrap();
}

fn format_columns(branches: &String) -> String {
    let split = branches.split("\n");
    let vec: Vec<&str> = split.collect();

    if vec.len() < 51 {
        return branches.to_owned();
    }

    let col_count = vec.len() / 50 + 1;
    let mut spacer = String::new();
    for _ in (1..35) {
        spacer = spacer + " "
    }

    // let rows = vec.iter().slice(3).map(|b1, b2, b3| b1 + spacer + b2 + spacer + b3).collect();
    // rows.join("\n")
    String::new()
}

fn merged_branches() -> String {
    let grep = Command::new("grep")
        .args(&["-vE", "(\\* master|\\smaster)"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    let gbranch = Command::new("git")
        .args(&["branch", "--merged", "master"])
        .output()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    {
        grep.stdin.unwrap().write_all(&gbranch.stdout).unwrap();
    }

    let mut s = String::new();
    grep.stdout.unwrap().read_to_string(&mut s).unwrap();
    trim_entries(s)
}

fn delete_branches(branches: &String, options: DeleteOption) -> Result<String, String> {
    ensure_master();

    let output = match options {
        DeleteOption::Local => delete_local_branches(branches).unwrap(),
        DeleteOption::Remote => delete_remote_branches(branches).unwrap(),
        DeleteOption::Both => {
            let out1 = delete_remote_branches(branches).unwrap();
            let out2 = delete_local_branches(branches).unwrap();
            ["Remote:".to_owned(), out1, "Local:".to_owned(), out2].join("\n")
        },
    };

    Ok(output)
}

fn delete_local_branches(branches: &String) -> Result<String, String> {
    let xargs = Command::new("xargs")
        .args(&["git", "branch", "-d"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    {
        xargs.stdin.unwrap().write_all(branches.as_bytes()).unwrap()
    }

    let mut s = String::new();
    xargs.stdout.unwrap().read_to_string(&mut s).unwrap();
    Ok(s)
}

fn delete_remote_branches(branches: &String) -> Result<String, String> {
    let xargs = Command::new("xargs")
        .args(&["git", "push", "origin", "--delete"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    {
        xargs.stdin.unwrap().write_all(branches.as_bytes()).unwrap()
    }

    let mut stdout = String::new();
    xargs.stdout.unwrap().read_to_string(&mut stdout).unwrap();

    let mut stderr = String::new();
    xargs.stderr.unwrap().read_to_string(&mut stderr).unwrap();

    let split = stderr.split("\n");
    let vec: Vec<&str> = split.collect();
    let mut failed_remotes = vec![];
    for s in vec {
        if s.contains("error: unable to delete '") {
            let branch = s.trim_left_matches("error: unable to delete '")
                .trim_right_matches("': remote ref does not exist");

            failed_remotes.push(branch.to_owned() + " was already deleted in the remote.");
        }
    };
    let output = failed_remotes.join("\n") + &stdout;

    Ok(output)
}

fn ensure_master() {
    let current_branch_command = Command::new("git")
        .args(&["rev-parse", "--abbrev-ref", "HEAD"])
        .output()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    let current_branch = String::from_utf8(current_branch_command.stdout).unwrap();

    if current_branch.trim() != "master" {
        panic!("Please run this command from the master branch");
    }
}

fn trim_entries(entries: String) -> String {
    let split = entries.split("\n");
    let vec: Vec<&str> = split.collect();
    let trimmed_vec: Vec<&str> = vec.iter().map(|s| s.trim()).collect();
    trimmed_vec.join("\n").trim_right_matches("\n").to_owned()
}

#[cfg(test)]
mod test {
    use super::trim_entries;
    use super::format_columns;
    use super::print_warning;
    use super::DeleteOption;

    use getopts::{Options};

    #[test]
    fn test_trim_entries() {
        assert_eq!("branch", trim_entries(" branch ".to_owned()));
        assert_eq!("branch", trim_entries(" branch\n".to_owned()));
        assert_eq!("branch1\nbranch2\nbranch3", trim_entries(" branch1 \n branch2 \n branch3 ".to_owned()));
    }

    #[test]
    fn test_format_columns() {
        let mut input = String::new();
        for _ in (1..51) {
            input = input + "branch\n"
        }

        let expected = "branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch";

        assert_eq!(expected, format_columns(&input));
    }

    #[test]
    fn test_print_warning() {
        print_warning(&"branch".to_owned(), &DeleteOption::Both);
    }

    #[test]
    fn test_delete_option_new() {
        let mut opts = Options::new();
        opts.optflag("l", "local", "only delete local branches");
        opts.optflag("r", "remote", "only delete remote branches");
        opts.optflag("h", "help", "print this help menu");

        // opts throws away the first elem, because it expects it to be the
        // path of the executable
        let args = vec!["./target/debug/git-clean", "-l"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Local => (),
            other @ _ => panic!("Expected a DeleteOption::Local, but found: {:?}", other),
        };

        let args = vec!["./target/debug/git-clean", "-r"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Remote => (),
            other @ _ => panic!("Expected a DeleteOption::Remote, but found: {:?}", other),
        };

        let args = vec!["./target/debug/git-clean"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Both => (),
            other @ _ => panic!("Expected a DeleteOption::Both, but found: {:?}", other),
        };
    }

    #[test]
    fn test_warning_message() {
        assert_eq!("The following branches will be deleted locally:", DeleteOption::Local.warning_message());
        assert_eq!("The following branches will be deleted remotely:", DeleteOption::Remote.warning_message());
        assert_eq!("The following branches will be deleted locally and remotely:", DeleteOption::Both.warning_message());
    }
}
<commit_msg>spawn_piped()<commit_after>extern crate getopts;

use std::process::{Command, Stdio, Child};
use std::io;
use std::io::{Read, Write};
use std::env;

use getopts::{Options, Matches};

#[derive(Debug)]
enum DeleteOption {
    Local,
    Remote,
    Both
}

impl DeleteOption {
    fn new(opts: Matches) -> DeleteOption {
        return if opts.opt_present("l") {
            DeleteOption::Local
        } else if opts.opt_present("r") {
            DeleteOption::Remote
        } else {
            DeleteOption::Both
        };
    }

    fn warning_message(&self) -> String {
        let source = match self {
            &DeleteOption::Local => "locally:",
            &DeleteOption::Remote => "remotely:",
            &DeleteOption::Both => "locally and remotely:",
        };
        "The following branches will be deleted ".to_owned() + source
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("l", "local", "only delete local branches");
    opts.optflag("r", "remote", "only delete remote branches");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(e) => {
            println!("{}", e);
            print_usage(opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return;
    }

    let branches = merged_branches();

    // Early return if there's nothing to delete
    if branches.len() == 0 {
        println!("No branches to delete, you're clean!");
        return;
    }

    let del_opt = DeleteOption::new(matches);

    print_warning(&branches, &del_opt);

    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();

    match input.to_lowercase().as_ref() {
        "y\n" => (),
        "yes\n" => (),
        _ => return,
    }

    match delete_branches(&branches, del_opt) {
        Ok(ref msg) => println!("\n{}", msg),
        Err(ref msg) => println!("\n{}", msg),
    }
}

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

fn print_warning(branches: &String, del_opt: &DeleteOption) {
    println!("{}", del_opt.warning_message());
    println!("{}", format_columns(branches));
    print!("Continue? (yN) ");
    io::stdout().flush().unwrap();
}

fn format_columns(branches: &String) -> String {
    let split = branches.split("\n");
    let vec: Vec<&str> = split.collect();

    if vec.len() < 51 {
        return branches.to_owned();
    }

    let col_count = vec.len() / 50 + 1;
    let mut spacer = String::new();
    for _ in (1..35) {
        spacer = spacer + " "
    }

    // let rows = vec.iter().slice(3).map(|b1, b2, b3| b1 + spacer + b2 + spacer + b3).collect();
    // rows.join("\n")
    String::new()
}

fn merged_branches() -> String {
    let grep = spawn_piped(vec!["grep", "-vE", "(\\* master|\\smaster)"]);

    let gbranch = Command::new("git")
        .args(&["branch", "--merged", "master"])
        .output()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    {
        grep.stdin.unwrap().write_all(&gbranch.stdout).unwrap();
    }

    let mut s = String::new();
    grep.stdout.unwrap().read_to_string(&mut s).unwrap();
    trim_entries(s)
}

fn delete_branches(branches: &String, options: DeleteOption) -> Result<String, String> {
    ensure_master();

    let output = match options {
        DeleteOption::Local => delete_local_branches(branches).unwrap(),
        DeleteOption::Remote => delete_remote_branches(branches).unwrap(),
        DeleteOption::Both => {
            let out1 = delete_remote_branches(branches).unwrap();
            let out2 = delete_local_branches(branches).unwrap();
            ["Remote:".to_owned(), out1, "Local:".to_owned(), out2].join("\n")
        },
    };

    Ok(output)
}

fn delete_local_branches(branches: &String) -> Result<String, String> {
    let xargs = spawn_piped(vec!["xargs", "git", "branch", "-d"]);

    {
        xargs.stdin.unwrap().write_all(branches.as_bytes()).unwrap()
    }

    let mut s = String::new();
    xargs.stdout.unwrap().read_to_string(&mut s).unwrap();
    Ok(s)
}

fn delete_remote_branches(branches: &String) -> Result<String, String> {
    let xargs = spawn_piped(vec!["xargs", "git", "push", "origin", "--delete"]);

    {
        xargs.stdin.unwrap().write_all(branches.as_bytes()).unwrap()
    }

    let mut stdout = String::new();
    xargs.stdout.unwrap().read_to_string(&mut stdout).unwrap();

    let mut stderr = String::new();
    xargs.stderr.unwrap().read_to_string(&mut stderr).unwrap();

    let split = stderr.split("\n");
    let vec: Vec<&str> = split.collect();
    let mut failed_remotes = vec![];
    for s in vec {
        if s.contains("error: unable to delete '") {
            let branch = s.trim_left_matches("error: unable to delete '")
                .trim_right_matches("': remote ref does not exist");

            failed_remotes.push(branch.to_owned() + " was already deleted in the remote.");
        }
    };
    let output = failed_remotes.join("\n") + &stdout;

    Ok(output)
}

fn ensure_master() {
    let current_branch_command = Command::new("git")
        .args(&["rev-parse", "--abbrev-ref", "HEAD"])
        .output()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) });

    let current_branch = String::from_utf8(current_branch_command.stdout).unwrap();

    if current_branch.trim() != "master" {
        panic!("Please run this command from the master branch");
    }
}

fn trim_entries(entries: String) -> String {
    let split = entries.split("\n");
    let vec: Vec<&str> = split.collect();
    let trimmed_vec: Vec<&str> = vec.iter().map(|s| s.trim()).collect();
    trimmed_vec.join("\n").trim_right_matches("\n").to_owned()
}

fn spawn_piped(args: Vec<&'static str>) -> Child {
    let cmd = args[0];
    Command::new(cmd)
        .args(&args[1..])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap_or_else(|e| { panic!("ERR: {}", e) })
}

#[cfg(test)]
mod test {
    use super::trim_entries;
    use super::format_columns;
    use super::print_warning;
    use super::DeleteOption;
    use super::spawn_piped;

    use std::io::{Read, Write};

    use getopts::{Options};

    #[test]
    fn test_trim_entries() {
        assert_eq!("branch", trim_entries(" branch ".to_owned()));
        assert_eq!("branch", trim_entries(" branch\n".to_owned()));
        assert_eq!("branch1\nbranch2\nbranch3", trim_entries(" branch1 \n branch2 \n branch3 ".to_owned()));
    }

    #[test]
    fn test_format_columns() {
        let mut input = String::new();
        for _ in (1..51) {
            input = input + "branch\n"
        }

        let expected = "branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch                                   branch\
                        branch";

        assert_eq!(expected, format_columns(&input));
    }

    #[test]
    fn test_print_warning() {
        print_warning(&"branch".to_owned(), &DeleteOption::Both);
    }

    #[test]
    fn test_delete_option_new() {
        let mut opts = Options::new();
        opts.optflag("l", "local", "only delete local branches");
        opts.optflag("r", "remote", "only delete remote branches");
        opts.optflag("h", "help", "print this help menu");

        // opts throws away the first elem, because it expects it to be the
        // path of the executable
        let args = vec!["./target/debug/git-clean", "-l"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Local => (),
            other @ _ => panic!("Expected a DeleteOption::Local, but found: {:?}", other),
        };

        let args = vec!["./target/debug/git-clean", "-r"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Remote => (),
            other @ _ => panic!("Expected a DeleteOption::Remote, but found: {:?}", other),
        };

        let args = vec!["./target/debug/git-clean"];

        let matches = match opts.parse(&args[1..]) {
            Ok(m) => { m }
            Err(_) => { return }
        };

        match DeleteOption::new(matches) {
            DeleteOption::Both => (),
            other @ _ => panic!("Expected a DeleteOption::Both, but found: {:?}", other),
        };
    }

    #[test]
    fn test_spawn_piped() {
        let echo = spawn_piped(vec!["grep", "foo"]);

        {
            echo.stdin.unwrap().write_all("foo\nbar\nbaz".as_bytes()).unwrap()
        }

        let mut stdout = String::new();
        echo.stdout.unwrap().read_to_string(&mut stdout).unwrap();

        assert_eq!(stdout, "foo\n");
    }

    #[test]
    fn test_warning_message() {
        assert_eq!("The following branches will be deleted locally:", DeleteOption::Local.warning_message());
        assert_eq!("The following branches will be deleted remotely:", DeleteOption::Remote.warning_message());
        assert_eq!("The following branches will be deleted locally and remotely:", DeleteOption::Both.warning_message());
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate rand;
extern crate sdl2;
extern crate time;

use std::env;
use std::fs;
use std::io::Read;
use std::path::Path;

mod cpu;
mod graphics;
mod input;
mod interconnect;
mod memory;
mod sound;
mod vm;

fn main() {
    // TODO: Use an actual argument parser when adding options in the future.
    if let Some(rom_file_name) = env::args().nth(1) {
        let rom = read_bin(rom_file_name);

        let mut vm = vm::VirtualMachine::new(rom);
        vm.run();
    } else {
        print_usage();
        std::process::exit(1);
    }
}

/// Prints the application name alongside the cargo version.
fn print_version() {
    println!("notch {}", env!("CARGO_PKG_VERSION"));
}

/// Prints usage information.
fn print_usage() {
    println!("Notch is a CHIP-8 virtual machine written in Rust.");
    println!("");
    println!("Usage: notch [ROM]");
    println!("");
    println!("To contribute or report bugs, please see:");
    println!("<https://github.com/Reshurum/notch>");
}

/// Reads a file into a vector of unsigned bytes.
fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut file = fs::File::open(path).unwrap();
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer).unwrap();
    buffer
}
<commit_msg>Improved file loading<commit_after>extern crate byteorder;
extern crate rand;
extern crate sdl2;
extern crate time;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;

mod cpu;
mod graphics;
mod input;
mod interconnect;
mod memory;
mod sound;
mod vm;

fn main() {
    // TODO: Use an actual argument parser when adding options in the future.
    if let Some(rom_file_name) = env::args().nth(1) {
        let rom = read_bin(rom_file_name);

        let mut vm = vm::VirtualMachine::new(rom);
        vm.run();
    } else {
        print_usage();
        std::process::exit(1);
    }
}

/// Prints the application name alongside the cargo version.
fn print_version() {
    println!("notch {}", env!("CARGO_PKG_VERSION"));
}

/// Prints usage information.
fn print_usage() {
    println!("Notch is a CHIP-8 virtual machine written in Rust.");
    println!("");
    println!("Usage: notch [ROM]");
    println!("");
    println!("To contribute or report bugs, please see:");
    println!("<https://github.com/Reshurum/notch>");
}

/// Reads a file into a vector of unsigned bytes.
fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut buffer: Vec<u8> = Vec::new();
    let filename = format!("{}", path.as_ref().display());

    // Open and read the file if it exists.
    let mut file = match File::open(path) {
        Ok(ref mut file) => {
            file.read_to_end(&mut buffer).unwrap();
        },
        Err(why) => {
            println!("notch: cannot open '{}': {}", filename, why);
            std::process::exit(2);
        },
    };

    buffer
}
<|endoftext|>