<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os, str};
use std::io::buffered::BufferedReader;
use std::path::posix::Path;
use std::io::fs::File;
use std::io::stdin;
use std::io::signal::{Listener, Interrupt};
use extra::getopts;

static exit_code : i32 = -999;
static nop_code : i32 = -1;

struct Shell {
    cmd_prompt : ~str,
    cmd_history : ~[~str],
}

impl Shell {

    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cmd_history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        let (port_func, chan_func) : (Port<i32>, Chan<i32>) = Chan::new();
        let (port_status, chan_status) : (Port<i32>, Chan<i32>) = Chan::new();
        chan_status.send(nop_code);
        spawn(proc() {
            let mut listener = Listener::new();
            listener.register(Interrupt);
            loop {
                match port_func.try_recv() {
                    Some(status) if status == exit_code => {
                        listener.unregister(Interrupt);
                        unsafe { std::libc::exit(1 as std::libc::c_int); }
                        // return;
                    }
                    Some(response) => { chan_status.send(response); }   // To complete process
                    None    => {}
                }
            }
        });

        loop {
            port_status.recv();   // Wait for op to finish.
            print(self.cmd_prompt); // Prints "gash >"
            io::stdio::flush();

            let mut line : ~str = stdin.read_line().unwrap().to_owned();
            let mut cmd_line: ~str = line.trim().to_owned();
            let mut background: bool = false;
            let mut i : uint = 0;

            // This block handles if there are no spaces around pipe.
            let lineClone = line.clone();
            for character in lineClone.chars() {
                if character == '<' {
                    line = line.slice(0, i).to_owned() + " < " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                } else if character == '>' {
                    line = line.slice(0, i).to_owned() + " > " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                } else if character == '|' {
                    line = line.slice(0, i).to_owned() + " | " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                }
                i = i + 1;
            }

            if cmd_line.char_len() > 0 {
                background = cmd_line.char_at(cmd_line.char_len() - 1) == '&';
                if background {
                    cmd_line = cmd_line.slice(0, cmd_line.char_len() - 1).trim().to_owned();
                }
            }

            let params = cmd_line.clone().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""          =>  { chan_func.send(nop_code);
                                  continue; }
                "exit"      =>  { chan_func.send(exit_code);
                                  return; }  // Exit
                "cd"        =>  { Shell::run_check_mode(background, Shell::run_cd(params), &chan_func); }
                "history"   =>  { Shell::run_check_mode(background, Shell::run_history(params, self.cmd_history), &chan_func); }
                _           =>  { Shell::run_check_mode(background, Shell::run_cmdline(params), &chan_func); }
            }

            self.cmd_history.push(program.to_owned());
        }
    }

    fn run_check_mode(background: bool, f: proc(), chan_func : &Chan<i32>) {
        let (port_temp, chan_temp) : (Port<i32>, Chan<i32>) = Chan::new();
        if background {
            spawn(proc() {
                f();
            });
            chan_func.send(nop_code);  // Don't wait til f returns.
        } else {
            spawn(proc() {
                f();
                chan_temp.send(nop_code); // Wait til f returns.
            });
            chan_func.send(port_temp.recv());
        }
    }

    fn run_cmdline_single(cmd_line: &str) {
        (Shell::run_cmdline(cmd_line))();
    }

    fn run_cmdline(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            if params.trim() != "" {
                let output = Shell::handle_pipes(params, false);
                // write output to file (if necessary and exists)
                match output {
                    Some(outString) => {
                        match Shell::get_output_file(params) {
                            Some(fileName) => {
                                let mut f = File::create(&Path::new(fileName));
                                f.write(outString.into_bytes());
                            }
                            None => { /* Shouldn't happen... */ }
                        }
                    }
                    None => { /*Do nothing*/ }
                }
            }
        };
    }

    fn handle_pipes(cmd_line: &str, out_pipe: bool) -> Option<~str> {
        let pipeSplit = Shell::split_on_last_pipe(cmd_line);
        let mut argv = Shell::get_args_no_redirects(pipeSplit[0]);
        let program = argv.remove(0);
        let hasOutRedirect = match Shell::get_output_file(cmd_line) {
            Some(_) => { true }
            None => {
                if out_pipe {
                    true
                } else {
                    false
                }
            }
        };

        if pipeSplit.len() == 2 {
            return Shell::run_cmd(program, argv, Shell::handle_pipes(pipeSplit[1], true), hasOutRedirect);
        } else {
            return Shell::run_cmd(program, argv, Shell::get_input_file_contents(cmd_line), hasOutRedirect);
        }
    }

    fn run_cmd(program: &str, argv: &[~str], inputStr: Option<~str>, hasOutRedirect: bool) -> Option<~str> {
        if Shell::cmd_exists(program) {
            let mut options = run::ProcessOptions::new();
            options.in_fd = match inputStr {
                Some(_) => { None }
                None => { Some(0) }
            };

            options.out_fd = if hasOutRedirect {
                None
            } else {
                Some(1)
            };

            let mut process = run::Process::new(program, argv, options).unwrap();
            match inputStr {
                Some(string) => {
                    let buf = string.into_bytes();
                    process.input().write(buf);
                }
                None => {}
            }

            process.close_input();

            if hasOutRedirect {
                let processOutput = process.finish_with_output();
                return Some(str::from_utf8(processOutput.output).to_owned());
            } else {
                process.finish();
                return None;
            };
        } else {
            println!("{:s}: command not found", program);
            return None;
        }
    }

    fn cmd_exists(cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_cd(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            let pathOpt: Option<Path> = match argv.len() {
                1   =>  { os::homedir() }
                0   =>  { os::homedir() }
                _   =>  { Some(Path::new(argv[1])) }
            };

            match pathOpt {
                Some(path)   =>  {
                    if path.is_dir() {
                        os::change_dir(&path);
                    } else {
                        println!("Error: {:s} is not a directory", path.as_str().unwrap());
                    }
                }
                None        =>  {
                    println!("Error: Invalid path");
                }
            };
        };
    }

    fn run_history(cmd_line: &str, cmd_history: &[~str]) -> proc() {
        let history = cmd_history.to_owned();
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            if (argv.len() > 1) {
                println!("Error: history does not take options (sadly).");
            }
            else {
                let mut i = 1;
                for entry in history.iter() {
                    println!("{:d} \t{:s}", i, entry.to_owned());
                    i = i + 1;
                }
            }
        };
    }

    fn split_on_last_pipe(cmd_line: &str) -> ~[~str] {
        return cmd_line.rsplitn('|', 1).filter_map(|x| Some(x.trim().to_owned())).to_owned_vec();
    }

    fn get_input_file_contents(cmd_line: &str) -> Option<~str> {
        return match cmd_line.splitn('<', 1).nth(1) {
            Some(inputFileCandidate) => {
                match inputFileCandidate.trim().splitn(' ', 1).nth(0) {
                    Some(inputFile) => {
                        match File::open(&Path::new(inputFile)) {
                            Some(mut file) => {
                                Some(file.read_to_str())
                            }
                            None => {
                                println!("File {:s} does not exist", inputFile);
                                None
                            }
                        }
                    }
                    None => { None }
                }
            }
            None => { None }
        };
    }

    fn get_output_file(cmd_line: &str) -> Option<~str> {
        return match cmd_line.splitn('>', 1).nth(1) {
            Some(inputFileCandidate) => {
                match inputFileCandidate.trim().splitn(' ', 1).nth(0) {
                    Some(inputFile) => { Some(inputFile.to_owned()) }
                    None => { None }
                }
            }
            None => { None }
        };
    }

    fn get_args_no_redirects(cmd_line: &str) -> ~[~str] {
        let mut activeRedirect = false;
        return cmd_line.split(' ').filter_map(|x| if x == ">" || x == "<" {
            activeRedirect = true;
            None
        } else if x == "" {
            None
        } else if activeRedirect {
            activeRedirect = false;
            None
        } else {
            Some(x.to_owned())
        }).to_owned_vec();
    }

    fn get_args(cmd_line: &str) -> ~[~str] {
        return cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::run_cmdline_single(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>added parsing of quoted strings and escape sequences in parameters (COMMITTED FROM WITHIN GASH)<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os, str};
use std::io::buffered::BufferedReader;
use std::path::posix::Path;
use std::io::fs::File;
use std::io::stdin;
use std::io::signal::{Listener, Interrupt};
use extra::getopts;

static exit_code : i32 = -999;
static nop_code : i32 = -1;

struct Shell {
    cmd_prompt : ~str,
    cmd_history : ~[~str],
}

impl Shell {

    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cmd_history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        let (port_func, chan_func) : (Port<i32>, Chan<i32>) = Chan::new();
        let (port_status, chan_status) : (Port<i32>, Chan<i32>) = Chan::new();
        chan_status.send(nop_code);
        spawn(proc() {
            let mut listener = Listener::new();
            listener.register(Interrupt);
            loop {
                match port_func.try_recv() {
                    Some(status) if status == exit_code => {
                        listener.unregister(Interrupt);
                        unsafe { std::libc::exit(1 as std::libc::c_int); }
                        // return;
                    }
                    Some(response) => { chan_status.send(response); }   // To complete process
                    None    => {}
                }
            }
        });

        loop {
            port_status.recv();   // Wait for op to finish.
            print(self.cmd_prompt); // Prints "gash >"
            io::stdio::flush();

            let mut line : ~str = stdin.read_line().unwrap().to_owned();
            let mut cmd_line: ~str = line.trim().to_owned();
            let mut background: bool = false;
            let mut i : uint = 0;

            // This block handles if there are no spaces around pipe.
            let lineClone = line.clone();
            for character in lineClone.chars() {
                if character == '<' {
                    line = line.slice(0, i).to_owned() + " < " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                } else if character == '>' {
                    line = line.slice(0, i).to_owned() + " > " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                } else if character == '|' {
                    line = line.slice(0, i).to_owned() + " | " + line.slice(i+1, line.char_len()).to_owned();
                    i = i + 2;
                }
                i = i + 1;
            }

            if cmd_line.char_len() > 0 {
                background = cmd_line.char_at(cmd_line.char_len() - 1) == '&';
                if background {
                    cmd_line = cmd_line.slice(0, cmd_line.char_len() - 1).trim().to_owned();
                }
            }

            let params = cmd_line.clone().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""          =>  { chan_func.send(nop_code);
                                  continue; }
                "exit"      =>  { chan_func.send(exit_code);
                                  return; }  // Exit
                "cd"        =>  { Shell::run_check_mode(background, Shell::run_cd(params), &chan_func); }
                "history"   =>  { Shell::run_check_mode(background, Shell::run_history(params, self.cmd_history), &chan_func); }
                _           =>  { Shell::run_check_mode(background, Shell::run_cmdline(params), &chan_func); }
            }

            self.cmd_history.push(program.to_owned());
        }
    }

    fn run_check_mode(background: bool, f: proc(), chan_func : &Chan<i32>) {
        let (port_temp, chan_temp) : (Port<i32>, Chan<i32>) = Chan::new();
        if background {
            spawn(proc() {
                f();
            });
            chan_func.send(nop_code);  // Don't wait til f returns.
        } else {
            spawn(proc() {
                f();
                chan_temp.send(nop_code); // Wait til f returns.
            });
            chan_func.send(port_temp.recv());
        }
    }

    fn run_cmdline_single(cmd_line: &str) {
        (Shell::run_cmdline(cmd_line))();
    }

    fn run_cmdline(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            if params.trim() != "" {
                let output = Shell::handle_pipes(params, false);
                // write output to file (if necessary and exists)
                match output {
                    Some(outString) => {
                        match Shell::get_output_file(params) {
                            Some(fileName) => {
                                let mut f = File::create(&Path::new(fileName));
                                f.write(outString.into_bytes());
                            }
                            None => { /* Shouldn't happen... */ }
                        }
                    }
                    None => { /*Do nothing*/ }
                }
            }
        };
    }

    fn handle_pipes(cmd_line: &str, out_pipe: bool) -> Option<~str> {
        let pipeSplit = Shell::split_on_last_pipe(cmd_line);
        let mut argv = Shell::get_args_no_redirects(pipeSplit[0]);
        let program = argv.remove(0);
        let hasOutRedirect = match Shell::get_output_file(cmd_line) {
            Some(_) => { true }
            None => {
                if out_pipe {
                    true
                } else {
                    false
                }
            }
        };

        if pipeSplit.len() == 2 {
            return Shell::run_cmd(program, argv, Shell::handle_pipes(pipeSplit[1], true), hasOutRedirect);
        } else {
            return Shell::run_cmd(program, argv, Shell::get_input_file_contents(cmd_line), hasOutRedirect);
        }
    }

    fn run_cmd(program: &str, argv: &[~str], inputStr: Option<~str>, hasOutRedirect: bool) -> Option<~str> {
        if Shell::cmd_exists(program) {
            let mut options = run::ProcessOptions::new();
            options.in_fd = match inputStr {
                Some(_) => { None }
                None => { Some(0) }
            };

            options.out_fd = if hasOutRedirect {
                None
            } else {
                Some(1)
            };

            let mut process = run::Process::new(program, argv, options).unwrap();
            match inputStr {
                Some(string) => {
                    let buf = string.into_bytes();
                    process.input().write(buf);
                }
                None => {}
            }

            process.close_input();

            if hasOutRedirect {
                let processOutput = process.finish_with_output();
                return Some(str::from_utf8(processOutput.output).to_owned());
            } else {
                process.finish();
                return None;
            };
        } else {
            println!("{:s}: command not found", program);
            return None;
        }
    }

    fn cmd_exists(cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_cd(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            let pathOpt: Option<Path> = match argv.len() {
                1   =>  { os::homedir() }
                0   =>  { os::homedir() }
                _   =>  { Some(Path::new(argv[1])) }
            };

            match pathOpt {
                Some(path)   =>  {
                    if path.is_dir() {
                        os::change_dir(&path);
                    } else {
                        println!("Error: {:s} is not a directory", path.as_str().unwrap());
                    }
                }
                None        =>  {
                    println!("Error: Invalid path");
                }
            };
        };
    }

    fn run_history(cmd_line: &str, cmd_history: &[~str]) -> proc() {
        let history = cmd_history.to_owned();
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            if (argv.len() > 1) {
                println!("Error: history does not take options (sadly).");
            }
            else {
                let mut i = 1;
                for entry in history.iter() {
                    println!("{:d} \t{:s}", i, entry.to_owned());
                    i = i + 1;
                }
            }
        };
    }

    fn split_on_last_pipe(cmd_line: &str) -> ~[~str] {
        return cmd_line.rsplitn('|', 1).filter_map(|x| Some(x.trim().to_owned())).to_owned_vec();
    }

    fn get_input_file_contents(cmd_line: &str) -> Option<~str> {
        return match cmd_line.splitn('<', 1).nth(1) {
            Some(inputFileCandidate) => {
                match inputFileCandidate.trim().splitn(' ', 1).nth(0) {
                    Some(inputFile) => {
                        match File::open(&Path::new(inputFile)) {
                            Some(mut file) => {
                                Some(file.read_to_str())
                            }
                            None => {
                                println!("File {:s} does not exist", inputFile);
                                None
                            }
                        }
                    }
                    None => { None }
                }
            }
            None => { None }
        };
    }

    fn get_output_file(cmd_line: &str) -> Option<~str> {
        return match cmd_line.splitn('>', 1).nth(1) {
            Some(inputFileCandidate) => {
                match inputFileCandidate.trim().splitn(' ', 1).nth(0) {
                    Some(inputFile) => { Some(inputFile.to_owned()) }
                    None => { None }
                }
            }
            None => { None }
        };
    }

    fn get_args_no_redirects(cmd_line: &str) -> ~[~str] {
        let mut activeRedirect: bool = false;
        let mut args: ~[~str] = ~[];
        let mut input: ~[~str] = Shell::get_args(cmd_line);
        for arg in input.mut_iter() {
            if *arg == ~">" || *arg == ~"<" {
                activeRedirect = true;
            } else if activeRedirect {
                activeRedirect = false;
            } else {
                let newArg = arg.to_owned();
                args.push(newArg);
            }
        }

        let result = args;
        return result;
    }

    fn get_args(cmd_line: &str) -> ~[~str] {
        let mut current: ~str = ~"";
        let mut escape: bool = false;
        let mut quoted: bool = false;
        let mut params: ~[~str] = ~[];

        for symbol in cmd_line.chars() {
            if escape {
                if symbol == 't' || symbol == 'n' || symbol == 'r' {
                    current = current + "\\";
                }
                current = current + str::from_char(symbol);
                escape = false;
            } else if symbol == ' ' || symbol == '\t' {
                if quoted {
                    current = current + str::from_char(symbol);
                } else if current.char_len() != 0 {
                    params.push(current.to_owned());
                    current = ~"";
                }
            } else if symbol == '\\' {
                escape = true;
            } else if symbol == '"' {
                quoted = !quoted;
            } else {
                current = current + str::from_char(symbol);
            }
        }

        if current.char_len() > 0 {
            params.push(current.to_owned());
        }

        let result = params;
        return result;
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::run_cmdline_single(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/* automatically generated by rust-bindgen */

use glut::bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutGet, glutGetWindow};
use glut::bindgen::{glutInit, glutInitDisplayMode, glutPostRedisplay, glutReshapeFunc};
use glut::bindgen::{glutReshapeWindow, glutSetWindow, glutSwapBuffers, glutTimerFunc};
use core::libc::*;
use core::ptr::{null, to_unsafe_ptr};
use core::str::to_bytes;
use core::task::local_data::{local_data_get, local_data_set};
use core::cast::reinterpret_cast;
use core::vec::raw::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

pub type GLenum = i32;
pub type GLint = i32;
pub type GLfloat = f32;
pub type GLdouble = f64;

pub struct Window(c_int);

pub static DOUBLE: c_uint = 2 as c_uint;

static WINDOW_WIDTH: GLenum = 102;
static WINDOW_HEIGHT: GLenum = 103;

pub enum State {
    WindowWidth,
    WindowHeight
}

pub fn destroy<T>(_value: ~[T]) {
    // let it drop
}

pub fn init() {
    unsafe {
        let argc = 0 as c_int;
        let command = to_bytes(~"glut");
        let argv: (*u8, *u8) = (to_ptr(command), null());
        let argv_p = reinterpret_cast(&to_unsafe_ptr(&argv));

        glutInit(to_unsafe_ptr(&argc), argv_p);

        destroy(command);
    }
}

pub fn create_window(name: ~str) -> Window {
    unsafe {
        let bytes = to_bytes(name);
        return Window(glutCreateWindow(to_ptr(bytes) as *c_char));
    }
}

pub fn destroy_window(window: Window) {
    unsafe {
        glutDestroyWindow(*window);
    }
}

pub fn reshape_window(window: Window, width: c_int, height: c_int) {
    unsafe {
        let current_window = glutGetWindow();
        glutSetWindow(*window);
        glutReshapeWindow(width, height);
        glutSetWindow(current_window);
    }
}

pub fn display_callback_tls_key(_callback: @@fn()) {
    // Empty.
}

pub extern fn display_callback() {
    unsafe {
        let callback = local_data_get(display_callback_tls_key).get();
        (*callback)();
    }
}

pub fn display_func(callback: @fn()) {
    unsafe {
        local_data_set(display_callback_tls_key, @callback);
        glutDisplayFunc(display_callback);
    }
}

pub fn timer_callback_tls_key(_callback: @~[@fn()]) {
    // Empty.
}

pub extern fn timer_callback(index: int) {
    unsafe {
        let callbacks = local_data_get(timer_callback_tls_key).get();
        ((*callbacks)[index as uint])();
    }
}

pub fn timer_func(msecs: u32, callback: @fn()) {
    unsafe {
        let mut callbacks;
        match local_data_get(timer_callback_tls_key) {
            None => {
                callbacks = @mut ~[];
                local_data_set(timer_callback_tls_key, cast::transmute(copy callbacks));
            }
            Some(existing_callbacks) => {
                callbacks = cast::transmute(existing_callbacks);
            }
        }

        callbacks.push(callback);
        let index = (callbacks.len() - 1) as c_int;
        glutTimerFunc(msecs, timer_callback, index);
    }
}

pub fn reshape_callback_tls_key(_callback: @@fn(x: c_int, y: c_int)) {
    // Empty.
}

pub extern fn reshape_callback(width: c_int, height: c_int) {
    unsafe {
        let callback = local_data_get(reshape_callback_tls_key).get();
        (*callback)(width, height);
    }
}

pub fn reshape_func(_window: Window, callback: @fn(x: c_int, y: c_int)) {
    unsafe {
        local_data_set(reshape_callback_tls_key, @callback);
        glutReshapeFunc(reshape_callback);
    }
}

#[cfg(target_os="macos")]
pub fn check_loop() {
    unsafe {
        ext::glutCheckLoop();
    }
}

#[cfg(target_os="linux")]
pub fn check_loop() {
    unsafe {
        ext::glutMainLoopEvent();
    }
}

pub fn init_display_mode(mode: c_uint) {
    unsafe {
        glutInitDisplayMode(mode);
    }
}

pub fn swap_buffers() {
    unsafe {
        glutSwapBuffers();
    }
}

pub fn post_redisplay() {
    unsafe {
        glutPostRedisplay();
    }
}

pub fn get(state: State) -> c_int {
    unsafe {
        let glut_state;
        match state {
            WindowWidth => glut_state = WINDOW_WIDTH,
            WindowHeight => glut_state = WINDOW_HEIGHT
        }
        glutGet(glut_state)
    }
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
pub extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
pub extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
pub extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
pub extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
pub extern mod bindgen {

pub fn glutInit(++argcp: *c_int, ++argv: **c_char);

pub fn glutInitDisplayMode(++mode: c_uint);

pub fn glutInitDisplayString(++string: *c_char);

pub fn glutInitWindowPosition(++x: c_int, ++y: c_int);

pub fn glutInitWindowSize(++width: c_int, ++height: c_int);

pub fn glutMainLoop();

pub fn glutCreateWindow(++title: *c_char) -> c_int;

pub fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

pub fn glutDestroyWindow(++win: c_int);

pub fn glutPostRedisplay();

pub fn glutPostWindowRedisplay(++win: c_int);

pub fn glutSwapBuffers();

pub fn glutGetWindow() -> c_int;

pub fn glutSetWindow(++win: c_int);

pub fn glutSetWindowTitle(++title: *c_char);

pub fn glutSetIconTitle(++title: *c_char);

pub fn glutPositionWindow(++x: c_int, ++y: c_int);

pub fn glutReshapeWindow(++width: c_int, ++height: c_int);

pub fn glutPopWindow();

pub fn glutPushWindow();

pub fn glutIconifyWindow();

pub fn glutShowWindow();

pub fn glutHideWindow();

pub fn glutFullScreen();

pub fn glutSetCursor(++cursor: c_int);

pub fn glutWarpPointer(++x: c_int, ++y: c_int);

pub fn glutEstablishOverlay();

pub fn glutRemoveOverlay();

pub fn glutUseLayer(++layer: GLenum);

pub fn glutPostOverlayRedisplay();

pub fn glutPostWindowOverlayRedisplay(++win: c_int);

pub fn glutShowOverlay();

pub fn glutHideOverlay();

pub fn glutCreateMenu(++arg1: *u8) -> c_int;

pub fn glutDestroyMenu(++menu: c_int);

pub fn glutGetMenu() -> c_int;

pub fn glutSetMenu(++menu: c_int);

pub fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

pub fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

pub fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

pub fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

pub fn glutRemoveMenuItem(++item: c_int);

pub fn glutAttachMenu(++button: c_int);

pub fn glutDetachMenu(++button: c_int);

pub fn glutDisplayFunc(++func: *u8);

pub fn glutReshapeFunc(++func: *u8);

pub fn glutKeyboardFunc(++func: *u8);

pub fn glutMouseFunc(++func: *u8);

pub fn glutMotionFunc(++func: *u8);

pub fn glutPassiveMotionFunc(++func: *u8);

pub fn glutEntryFunc(++func: *u8);

pub fn glutVisibilityFunc(++func: *u8);

pub fn glutIdleFunc(++func: *u8);

pub fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

pub fn glutMenuStateFunc(++func: *u8);

pub fn glutSpecialFunc(++func: *u8);

pub fn glutSpaceballMotionFunc(++func: *u8);

pub fn glutSpaceballRotateFunc(++func: *u8);

pub fn glutSpaceballButtonFunc(++func: *u8);

pub fn glutButtonBoxFunc(++func: *u8);

pub fn glutDialsFunc(++func: *u8);

pub fn glutTabletMotionFunc(++func: *u8);

pub fn glutTabletButtonFunc(++func: *u8);

pub fn glutMenuStatusFunc(++func: *u8);

pub fn glutOverlayDisplayFunc(++func: *u8);

pub fn glutWindowStatusFunc(++func: *u8);

pub fn glutKeyboardUpFunc(++func: *u8);

pub fn glutSpecialUpFunc(++func: *u8);

pub fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

pub fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

pub fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

pub fn glutCopyColormap(++win: c_int);

pub fn glutGet(++_type: GLenum) -> c_int;

pub fn glutDeviceGet(++_type: GLenum) -> c_int;

pub fn glutExtensionSupported(++name: *c_char) -> c_int;

pub fn glutGetModifiers() -> c_int;

pub fn glutLayerGet(++_type: GLenum) -> c_int;

pub fn glutGetProcAddress(++procName: *c_char) -> *c_void;

pub fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

pub fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

pub fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

pub fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

pub fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

pub fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

pub fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutWireCube(++size: GLdouble);

pub fn glutSolidCube(++size: GLdouble);

pub fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

pub fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

pub fn glutWireDodecahedron();

pub fn glutSolidDodecahedron();

pub fn glutWireTeapot(++size: GLdouble);

pub fn glutSolidTeapot(++size: GLdouble);

pub fn glutWireOctahedron();

pub fn glutSolidOctahedron();

pub fn glutWireTetrahedron();

pub fn glutSolidTetrahedron();

pub fn glutWireIcosahedron();

pub fn glutSolidIcosahedron();

pub fn glutVideoResizeGet(++param: GLenum) -> c_int;

pub fn glutSetupVideoResizing();

pub fn glutStopVideoResizing();

pub fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

pub fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

pub fn glutReportErrors();

pub fn glutIgnoreKeyRepeat(++ignore: c_int);

pub fn glutSetKeyRepeat(++repeatMode: c_int);

pub fn glutForceJoystickFunc();

pub fn glutGameModeString(++string: *c_char);

pub fn glutEnterGameMode() -> c_int;

pub fn glutLeaveGameMode();

pub fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<commit_msg>Wrap mouse functions<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/* automatically generated by rust-bindgen */

use glut::bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutMouseFunc, glutMotionFunc, glutPassiveMotionFunc, glutGet, glutGetWindow};
use glut::bindgen::{glutInit, glutInitDisplayMode, glutPostRedisplay, glutReshapeFunc};
use glut::bindgen::{glutReshapeWindow, glutSetWindow, glutSwapBuffers, glutTimerFunc};
use core::libc::*;
use core::ptr::{null, to_unsafe_ptr};
use core::str::to_bytes;
use core::task::local_data::{local_data_get, local_data_set};
use core::cast::reinterpret_cast;
use core::vec::raw::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

pub type GLenum = i32;
pub type GLint = i32;
pub type GLfloat = f32;
pub type GLdouble = f64;

pub struct Window(c_int);

pub static DOUBLE: c_uint = 2 as c_uint;

static WINDOW_WIDTH: GLenum = 102;
static WINDOW_HEIGHT: GLenum = 103;

pub enum State {
    WindowWidth,
    WindowHeight
}

pub fn destroy<T>(_value: ~[T]) {
    // let it drop
}

pub fn init() {
    unsafe {
        let argc = 0 as c_int;
        let command = to_bytes(~"glut");
        let argv: (*u8, *u8) = (to_ptr(command), null());
        let argv_p = reinterpret_cast(&to_unsafe_ptr(&argv));

        glutInit(to_unsafe_ptr(&argc), argv_p);

        destroy(command);
    }
}

pub fn create_window(name: ~str) -> Window {
    unsafe {
        let bytes = to_bytes(name);
        return Window(glutCreateWindow(to_ptr(bytes) as *c_char));
    }
}

pub fn destroy_window(window: Window) {
    unsafe {
        glutDestroyWindow(*window);
    }
}

pub fn reshape_window(window: Window, width: c_int, height: c_int) {
    unsafe {
        let current_window = glutGetWindow();
        glutSetWindow(*window);
        glutReshapeWindow(width, height);
        glutSetWindow(current_window);
    }
}

pub fn display_callback_tls_key(_callback: @@fn()) {
    // Empty.
}

pub extern fn display_callback() {
    unsafe {
        let callback = local_data_get(display_callback_tls_key).get();
        (*callback)();
    }
}

pub fn display_func(callback: @fn()) {
    unsafe {
        local_data_set(display_callback_tls_key, @callback);
        glutDisplayFunc(display_callback);
    }
}

pub fn mouse_callback_tls_key(_callback: @@fn(button: c_int, state: c_int, x: c_int, y: c_int)) {
    // Empty.
}

pub extern fn mouse_callback(button: c_int, state: c_int, x: c_int, y: c_int) {
    unsafe {
        let callback = local_data_get(mouse_callback_tls_key).get();
        (*callback)(button, state, x, y);
    }
}

pub fn mouse_func(callback: @fn(button: c_int, state: c_int, x: c_int, y: c_int)) {
    unsafe {
        local_data_set(mouse_callback_tls_key, @callback);
        glutMouseFunc(mouse_callback);
    }
}

pub fn motion_callback_tls_key(_callback: @@fn(x: c_int, y: c_int)) {
    // Empty.
}

pub extern fn motion_callback(x: c_int, y: c_int) {
    unsafe {
        let callback = local_data_get(motion_callback_tls_key).get();
        (*callback)(x, y);
    }
}

pub fn motion_func(callback: @fn(x: c_int, y: c_int)) {
    unsafe {
        local_data_set(motion_callback_tls_key, @callback);
        glutMotionFunc(motion_callback);
    }
}

pub fn passive_motion_callback_tls_key(_callback: @@fn(x: c_int, y: c_int)) {
    // Empty.
}

pub extern fn passive_motion_callback(x: c_int, y: c_int) {
    unsafe {
        let callback = local_data_get(passive_motion_callback_tls_key).get();
        (*callback)(x, y);
    }
}

pub fn passive_motion_func(callback: @fn(x: c_int, y: c_int)) {
    unsafe {
        local_data_set(passive_motion_callback_tls_key, @callback);
        glutPassiveMotionFunc(passive_motion_callback);
    }
}

pub fn timer_callback_tls_key(_callback: @~[@fn()]) {
    // Empty.
}

pub extern fn timer_callback(index: int) {
    unsafe {
        let callbacks = local_data_get(timer_callback_tls_key).get();
        ((*callbacks)[index as uint])();
    }
}

pub fn timer_func(msecs: u32, callback: @fn()) {
    unsafe {
        let mut callbacks;
        match local_data_get(timer_callback_tls_key) {
            None => {
                callbacks = @mut ~[];
                local_data_set(timer_callback_tls_key, cast::transmute(copy callbacks));
            }
            Some(existing_callbacks) => {
                callbacks = cast::transmute(existing_callbacks);
            }
        }

        callbacks.push(callback);
        let index = (callbacks.len() - 1) as c_int;
        glutTimerFunc(msecs, timer_callback, index);
    }
}

pub fn reshape_callback_tls_key(_callback: @@fn(x: c_int, y: c_int)) {
    // Empty.
}

pub extern fn reshape_callback(width: c_int, height: c_int) {
    unsafe {
        let callback = local_data_get(reshape_callback_tls_key).get();
        (*callback)(width, height);
    }
}

pub fn reshape_func(_window: Window, callback: @fn(x: c_int, y: c_int)) {
    unsafe {
        local_data_set(reshape_callback_tls_key, @callback);
        glutReshapeFunc(reshape_callback);
    }
}

#[cfg(target_os="macos")]
pub fn check_loop() {
    unsafe {
        ext::glutCheckLoop();
    }
}

#[cfg(target_os="linux")]
pub fn check_loop() {
    unsafe {
        ext::glutMainLoopEvent();
    }
}

pub fn init_display_mode(mode: c_uint) {
    unsafe {
        glutInitDisplayMode(mode);
    }
}

pub fn swap_buffers() {
    unsafe {
        glutSwapBuffers();
    }
}

pub fn post_redisplay() {
    unsafe {
        glutPostRedisplay();
    }
}

pub fn get(state: State) -> c_int {
    unsafe {
        let glut_state;
        match state {
            WindowWidth => glut_state = WINDOW_WIDTH,
            WindowHeight => glut_state = WINDOW_HEIGHT
        }
        glutGet(glut_state)
    }
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
pub extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
pub extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
pub extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
pub extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
pub extern mod bindgen {

pub fn glutInit(++argcp: *c_int, ++argv: **c_char);

pub fn glutInitDisplayMode(++mode: c_uint);

pub fn glutInitDisplayString(++string: *c_char);

pub fn glutInitWindowPosition(++x: c_int, ++y: c_int);

pub fn glutInitWindowSize(++width: c_int, ++height: c_int);

pub fn glutMainLoop();

pub fn glutCreateWindow(++title: *c_char) -> c_int;

pub fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

pub fn glutDestroyWindow(++win: c_int);

pub fn glutPostRedisplay();

pub fn glutPostWindowRedisplay(++win: c_int);

pub fn glutSwapBuffers();

pub fn glutGetWindow() -> c_int;

pub fn glutSetWindow(++win: c_int);

pub fn glutSetWindowTitle(++title: *c_char);

pub fn glutSetIconTitle(++title: *c_char);

pub fn glutPositionWindow(++x: c_int, ++y: c_int);

pub fn glutReshapeWindow(++width: c_int, ++height: c_int);

pub fn glutPopWindow();

pub fn glutPushWindow();

pub fn glutIconifyWindow();

pub fn glutShowWindow();

pub fn glutHideWindow();

pub fn glutFullScreen();

pub fn glutSetCursor(++cursor: c_int);

pub fn glutWarpPointer(++x: c_int, ++y: c_int);

pub fn glutEstablishOverlay();

pub fn glutRemoveOverlay();

pub fn glutUseLayer(++layer: GLenum);

pub fn glutPostOverlayRedisplay();

pub fn glutPostWindowOverlayRedisplay(++win: c_int);

pub fn glutShowOverlay();

pub fn glutHideOverlay();

pub fn glutCreateMenu(++arg1: *u8) -> c_int;

pub fn glutDestroyMenu(++menu: c_int);

pub fn glutGetMenu() -> c_int;

pub fn glutSetMenu(++menu: c_int);

pub fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

pub fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

pub fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

pub fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

pub fn glutRemoveMenuItem(++item: c_int);

pub fn glutAttachMenu(++button: c_int);

pub fn glutDetachMenu(++button: c_int);

pub fn glutDisplayFunc(++func: *u8);

pub fn glutReshapeFunc(++func: *u8);

pub fn glutKeyboardFunc(++func: *u8);

pub fn glutMouseFunc(++func: *u8);

pub fn glutMotionFunc(++func: *u8);

pub fn glutPassiveMotionFunc(++func: *u8);

pub fn glutEntryFunc(++func: *u8);

pub fn glutVisibilityFunc(++func: *u8);

pub fn glutIdleFunc(++func: *u8);

pub fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

pub fn glutMenuStateFunc(++func: *u8);

pub fn glutSpecialFunc(++func: *u8);

pub fn glutSpaceballMotionFunc(++func: *u8);

pub fn glutSpaceballRotateFunc(++func: *u8);

pub fn glutSpaceballButtonFunc(++func: *u8);

pub fn glutButtonBoxFunc(++func: *u8);

pub fn glutDialsFunc(++func: *u8);

pub fn glutTabletMotionFunc(++func: *u8);

pub fn glutTabletButtonFunc(++func: *u8);

pub fn glutMenuStatusFunc(++func: *u8);

pub fn glutOverlayDisplayFunc(++func: *u8);

pub fn glutWindowStatusFunc(++func: *u8);

pub fn glutKeyboardUpFunc(++func: *u8);

pub fn glutSpecialUpFunc(++func: *u8);

pub fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

pub fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

pub fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

pub fn glutCopyColormap(++win: c_int);

pub fn glutGet(++_type: GLenum) -> c_int;

pub fn glutDeviceGet(++_type: GLenum) -> c_int;

pub fn glutExtensionSupported(++name: *c_char) -> c_int;

pub fn glutGetModifiers() -> c_int;

pub fn glutLayerGet(++_type: GLenum) -> c_int;

pub fn glutGetProcAddress(++procName: *c_char) -> *c_void;

pub fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

pub fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

pub fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

pub fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

pub fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

pub fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

pub fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

pub fn glutWireCube(++size: GLdouble);

pub fn glutSolidCube(++size: GLdouble);

pub fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

pub fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

pub fn glutWireDodecahedron();

pub fn glutSolidDodecahedron();

pub fn glutWireTeapot(++size: GLdouble);

pub fn glutSolidTeapot(++size: GLdouble);

pub fn glutWireOctahedron();

pub fn glutSolidOctahedron();

pub fn glutWireTetrahedron();

pub fn glutSolidTetrahedron();

pub fn glutWireIcosahedron();

pub fn glutSolidIcosahedron();

pub fn glutVideoResizeGet(++param: GLenum) -> c_int;

pub fn glutSetupVideoResizing();

pub fn glutStopVideoResizing();

pub fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

pub fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

pub fn glutReportErrors();

pub fn glutIgnoreKeyRepeat(++ignore: c_int);

pub fn glutSetKeyRepeat(++repeatMode: c_int);

pub fn glutForceJoystickFunc();

pub fn glutGameModeString(++string: *c_char);

pub fn glutEnterGameMode() -> c_int;

pub fn glutLeaveGameMode();

pub fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<|endoftext|>


<commit_before>#![feature(convert)]
use std::io;
use std::io::prelude::*;

extern crate regex;
use regex::Regex;

struct Program { pc: u32, registers: (u32, u32), }
#[derive(Clone)]
enum InstructionType { Hlf, Tpl, Inc, Jmp, Jie, Jio, }
#[derive(Clone)]
struct Instruction {
    register: Option<String>,
    argument: Option<i32>,
    instr: InstructionType,
}

impl Instruction {
    fn eval(&self, program: Program) -> Program {
        match self.instr {
            InstructionType::Hlf => self.eval_hlf(program),
            InstructionType::Tpl => self.eval_tpl(program),
            InstructionType::Inc => self.eval_inc(program),
            InstructionType::Jmp => self.eval_jmp(program),
            InstructionType::Jie => self.eval_jie(program),
            InstructionType::Jio => self.eval_jio(program),
        }
    }

    fn eval_hlf(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 / 2, program.registers.1),
            "b" => (program.registers.0, program.registers.1 / 2),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_tpl(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 * 3, program.registers.1),
            "b" => (program.registers.0, program.registers.1 * 3),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_inc(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 + 1, program.registers.1),
            "b" => (program.registers.0, program.registers.1 + 1),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_jmp(&self, program: Program) -> Program {
        let jump = self.clone().argument.unwrap();
        let pc = self.compute_jump(program.pc, jump);
        Program { pc: pc, registers: program.registers, }
    }

    fn eval_jie(&self, program: Program) -> Program {
        let instr = self.clone();
        let (register, jump) = (instr.register.unwrap(), instr.argument.unwrap());
        let value = match register.as_str() {
            "a" => program.registers.0,
            "b" => program.registers.1,
            _   => panic!(""),
        };
        let pc = if value % 2 == 0 {
            self.compute_jump(program.pc, jump)
        } else {
            program.pc + 1
        };
        Program { pc: pc, registers: program.registers, }
    }

    fn eval_jio(&self, program: Program) -> Program {
        let instr = self.clone();
        let (register, jump) = (instr.register.unwrap(), instr.argument.unwrap());
        let value = match register.as_str() {
            "a" => program.registers.0,
            "b" => program.registers.1,
            _   => panic!(""),
        };
        let pc = if value == 1 {
            self.compute_jump(program.pc, jump)
        } else {
            program.pc + 1
        };
        Program { pc: pc, registers: program.registers, }
    }

    fn compute_jump(&self, pc: u32, jump: i32) -> u32 {
        if jump < 0 {
            pc - ((-jump) as u32)
        } else {
            pc + (jump as u32)
        }
    }
}

fn parse_jump(jump: String) -> i32 {
    let first = &jump[0..1];
    let rest = &jump[1..];
    let value = i32::from_str_radix(rest, 10).unwrap();
    if first == "-" {
        -value
    } else {
        value
    }
}

fn parse_input(line: &String) -> Instruction {
    let re = Regex::new(r"(\w+) ([^, ]+),? ?(.*)").unwrap();
    let caps = match re.captures(line) {
        Some(c) => c,
        None    => panic!("could not parse input"),
    };
    let instr_str = caps.at(1).unwrap();
    let (register, argument) = match instr_str {
        "hlf" | "tpl" | "inc" => (Some(caps.at(2).unwrap().to_string()), None),
        "jmp" => (None,
                  Some(parse_jump(caps.at(2).unwrap().to_string()))),
        "jie" | "jio" => (Some(caps.at(2).unwrap().to_string()),
                          Some(parse_jump(caps.at(3).unwrap().to_string()))),
        _ => panic!("could not parse input"),
    };
    let instr = match instr_str {
        "hlf" => InstructionType::Hlf,
        "tpl" => InstructionType::Tpl,
        "inc" => InstructionType::Inc,
        "jmp" => InstructionType::Jmp,
        "jie" => InstructionType::Jie,
        "jio" => InstructionType::Jio,
        _ => panic!("could not parse input"),
    };
    Instruction {
        register: register,
        argument: argument,
        instr: instr,
    }
}

fn main() {
    let stdin = io::stdin();
    let instructions: Vec<Instruction> =
        stdin
        .lock()
        .lines()
        .map(|l| parse_input(&l.unwrap()))
        .collect();
    let mut program = Program { pc: 0, registers: (0, 0), };
    loop {
        println!(
            "pc: {}, registers: ({}, {})",
            program.pc,
            program.registers.0,
            program.registers.1,
        );
        let pc = program.pc;
        if pc >= instructions.len() as u32 {
            break;
        }

        let instr = instructions.get(pc as usize).unwrap().clone();
        program = instr.eval(program);
    }
}
<commit_msg>day 23, part 2. well, that was pretty simple<commit_after>#![feature(convert)]
use std::io;
use std::io::prelude::*;

extern crate regex;
use regex::Regex;

struct Program { pc: u32, registers: (u32, u32), }
#[derive(Clone)]
enum InstructionType { Hlf, Tpl, Inc, Jmp, Jie, Jio, }
#[derive(Clone)]
struct Instruction {
    register: Option<String>,
    argument: Option<i32>,
    instr: InstructionType,
}

impl Instruction {
    fn eval(&self, program: Program) -> Program {
        match self.instr {
            InstructionType::Hlf => self.eval_hlf(program),
            InstructionType::Tpl => self.eval_tpl(program),
            InstructionType::Inc => self.eval_inc(program),
            InstructionType::Jmp => self.eval_jmp(program),
            InstructionType::Jie => self.eval_jie(program),
            InstructionType::Jio => self.eval_jio(program),
        }
    }

    fn eval_hlf(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 / 2, program.registers.1),
            "b" => (program.registers.0, program.registers.1 / 2),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_tpl(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 * 3, program.registers.1),
            "b" => (program.registers.0, program.registers.1 * 3),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_inc(&self, program: Program) -> Program {
        let register = self.clone().register.unwrap();
        let registers = match register.as_str() {
            "a" => (program.registers.0 + 1, program.registers.1),
            "b" => (program.registers.0, program.registers.1 + 1),
            _ => panic!(""),
        };
        let pc = program.pc + 1;
        Program { pc: pc, registers: registers }
    }

    fn eval_jmp(&self, program: Program) -> Program {
        let jump = self.clone().argument.unwrap();
        let pc = self.compute_jump(program.pc, jump);
        Program { pc: pc, registers: program.registers, }
    }

    fn eval_jie(&self, program: Program) -> Program {
        let instr = self.clone();
        let (register, jump) = (instr.register.unwrap(), instr.argument.unwrap());
        let value = match register.as_str() {
            "a" => program.registers.0,
            "b" => program.registers.1,
            _   => panic!(""),
        };
        let pc = if value % 2 == 0 {
            self.compute_jump(program.pc, jump)
        } else {
            program.pc + 1
        };
        Program { pc: pc, registers: program.registers, }
    }

    fn eval_jio(&self, program: Program) -> Program {
        let instr = self.clone();
        let (register, jump) = (instr.register.unwrap(), instr.argument.unwrap());
        let value = match register.as_str() {
            "a" => program.registers.0,
            "b" => program.registers.1,
            _   => panic!(""),
        };
        let pc = if value == 1 {
            self.compute_jump(program.pc, jump)
        } else {
            program.pc + 1
        };
        Program { pc: pc, registers: program.registers, }
    }

    fn compute_jump(&self, pc: u32, jump: i32) -> u32 {
        if jump < 0 {
            pc - ((-jump) as u32)
        } else {
            pc + (jump as u32)
        }
    }
}

fn parse_jump(jump: String) -> i32 {
    let first = &jump[0..1];
    let rest = &jump[1..];
    let value = i32::from_str_radix(rest, 10).unwrap();
    if first == "-" {
        -value
    } else {
        value
    }
}

fn parse_input(line: &String) -> Instruction {
    let re = Regex::new(r"(\w+) ([^, ]+),? ?(.*)").unwrap();
    let caps = match re.captures(line) {
        Some(c) => c,
        None    => panic!("could not parse input"),
    };
    let instr_str = caps.at(1).unwrap();
    let (register, argument) = match instr_str {
        "hlf" | "tpl" | "inc" => (Some(caps.at(2).unwrap().to_string()), None),
        "jmp" => (None,
                  Some(parse_jump(caps.at(2).unwrap().to_string()))),
        "jie" | "jio" => (Some(caps.at(2).unwrap().to_string()),
                          Some(parse_jump(caps.at(3).unwrap().to_string()))),
        _ => panic!("could not parse input"),
    };
    let instr = match instr_str {
        "hlf" => InstructionType::Hlf,
        "tpl" => InstructionType::Tpl,
        "inc" => InstructionType::Inc,
        "jmp" => InstructionType::Jmp,
        "jie" => InstructionType::Jie,
        "jio" => InstructionType::Jio,
        _ => panic!("could not parse input"),
    };
    Instruction {
        register: register,
        argument: argument,
        instr: instr,
    }
}

fn main() {
    let stdin = io::stdin();
    let instructions: Vec<Instruction> =
        stdin
        .lock()
        .lines()
        .map(|l| parse_input(&l.unwrap()))
        .collect();
    let mut program = Program { pc: 0, registers: (1, 0), };
    loop {
        println!(
            "pc: {}, registers: ({}, {})",
            program.pc,
            program.registers.0,
            program.registers.1,
        );
        let pc = program.pc;
        if pc >= instructions.len() as u32 {
            break;
        }

        let instr = instructions.get(pc as usize).unwrap().clone();
        program = instr.eval(program);
    }
}
<|endoftext|>


<commit_before>// xfail-boot
// -*- rust -*-

type compare[T] = fn(@T t1, @T t2) -> bool;

fn test_generic[T](@T expected, &compare[T] eq) {
  let @T actual = alt (true) {
    case (true) {
      expected
    }
  };
  check (eq(expected, actual));
}

fn test_box() {
  fn compare_box(@bool b1, @bool b2) -> bool {
    ret *b1 == b2;
  }
  auto eq = bind compare_box(_, _);
  test_generic[bool](@true, eq);
}

fn main() {
  test_box();
}
<commit_msg>Fix a typo in test expr-alt-generic-box1.rs<commit_after>// xfail-boot
// -*- rust -*-

type compare[T] = fn(@T t1, @T t2) -> bool;

fn test_generic[T](@T expected, &compare[T] eq) {
  let @T actual = alt (true) {
    case (true) {
      expected
    }
  };
  check (eq(expected, actual));
}

fn test_box() {
  fn compare_box(@bool b1, @bool b2) -> bool {
    ret *b1 == *b2;
  }
  auto eq = bind compare_box(_, _);
  test_generic[bool](@true, eq);
}

fn main() {
  test_box();
}
<|endoftext|>


<commit_before>extern crate rustogram;
const HIGHEST_TRACKABLE_VALUE: i64 = 3600 * 1000 * 1000;
const NUMBER_OF_SIGNIFICANT_VALUE_DIGITS: i32 = 3;

use rustogram::histogram::*;
use rustogram::iter::*;

#[test]
fn test_get_total_count() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();
    assert_eq!(10_001, raw_histogram.get_total_count());
    assert_eq!(20_000, histogram.get_total_count());
}

#[test]
fn test_get_max_value() {
    let histogram = get_histogram();
    assert!(histogram.values_are_equivalent(100_000_000, histogram.get_max_value()));
}

#[test]
fn test_get_min_value() {
    let histogram = get_histogram();
    assert!(histogram.values_are_equivalent(1_000, histogram.get_min_value()));
}

#[test]
fn test_get_mean_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    let expected_raw_mean = (10_000_000f64 + 100_000_000f64) / 10001f64;
    let expected_mean = (1_000f64 + 50_000_000f64) / 2f64;

    assert_float_eq(expected_raw_mean, raw_histogram.get_mean(), expected_raw_mean * 0.001);
    assert_float_eq(expected_mean, histogram.get_mean(), expected_mean * 0.001);
}

#[test]
fn test_get_std_deviation() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    let expected_raw_mean = (10_000_000f64 + 100_000_000f64) / 10001f64;
    let expected_raw_std_dev = (((10000.0 * (1000.0 - expected_raw_mean).powf(2f64)) +
                                (100000000.0 - expected_raw_mean).powf(2f64)) / 10001f64).sqrt();
    let expected_mean = (1_000f64 + 50_000_000f64) / 2f64;
    let mut expected_square_deviation_sum = 10_000f64 * (1_000f64 - expected_mean).powf(2f64);
    let mut value = 10_000;
    while value <= 100_000_000 {
        expected_square_deviation_sum += (value as f64 - expected_mean).powf(2f64);
        value += 10_000;
    }
    let expected_std_dev = (expected_square_deviation_sum as f64 / 20_000f64).sqrt();

    assert_float_eq(expected_raw_std_dev, raw_histogram.get_std_deviation(), expected_raw_std_dev * 0.001);
    assert_float_eq(expected_std_dev, histogram.get_std_deviation(), expected_std_dev * 0.001);
}

#[test]
fn test_get_value_at_percentile() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(30.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(99.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(99.99) as f64, 1000.0 * 0.001);
    assert_float_eq(100000000.0, raw_histogram.get_value_at_percentile(99.999) as f64, 100000000.0 * 0.001);
    assert_float_eq(100000000.0, raw_histogram.get_value_at_percentile(100.0) as f64, 100000000.0 * 0.001);

    assert_float_eq(1000.0, histogram.get_value_at_percentile(30.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, histogram.get_value_at_percentile(50.0) as f64, 1000.0 * 0.001);
    assert_float_eq(50000000.0, histogram.get_value_at_percentile(75.0) as f64, 50000000.0 * 0.001);
    assert_float_eq(80000000.0, histogram.get_value_at_percentile(90.0) as f64, 80000000.0 * 0.001);
    assert_float_eq(98000000.0, histogram.get_value_at_percentile(99.0) as f64, 98000000.0 * 0.001);
    assert_float_eq(100000000.0, histogram.get_value_at_percentile(99.999) as f64, 100000000.0 * 0.001);
    assert_float_eq(100000000.0, histogram.get_value_at_percentile(100.0) as f64, 100000000.0 * 0.001);

}

#[test]
fn test_get_value_at_percentile_for_large_histogram() {
    let largest_value = 1000000000000;
    let mut histogram = new_histogram(largest_value, 5);
    histogram.record_value(largest_value);

    assert!(histogram.get_value_at_percentile(100.0) > 0);
}

#[test]
fn test_get_percentile_at_or_below_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_float_eq(99.99, raw_histogram.get_percentile_at_or_below_value(5000), 0.0001);
    assert_float_eq(50.0, histogram.get_percentile_at_or_below_value(5000), 0.0001);
    assert_float_eq(100.0, histogram.get_percentile_at_or_below_value(100000000), 0.0001);
}

#[test]
fn test_get_count_between_values() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_eq!(10_000, raw_histogram.get_count_between_values(1000, 1000));
    assert_eq!(1, raw_histogram.get_count_between_values(5000, 150_000_000));
    assert_eq!(10_000, histogram.get_count_between_values(5000, 150_000_000));
}

#[test]
fn test_get_count_at_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_eq!(10000, raw_histogram.get_count_at_value(1000));
    assert_eq!(10000, histogram.get_count_at_value(1000));
}

struct AssertionCounter {
	count: i64
}

impl AssertionCounter {
	fn increment(&mut self) {
		self.count += 1;
	}

	fn increment_by(&mut self, increment: i64) {
		self.count += increment;
	}

	fn reset(&mut self) {
		self.count = 0;
	}
}

#[test]
fn test_get_recorded_values() {
	let histogram = get_histogram();
	let raw_histogram : Histogram = get_raw_histogram();

	let mut counter = AssertionCounter { count: 0 };

	let raw_histogram_asserter = |record: Option<(i64, &HistogramIterationValue, &mut AssertionCounter)>| {
		if record.is_some() {
			let index_and_value = record.unwrap();
			let (index, value, counter) = index_and_value;
			if index == 0 {
				assert_eq!(10_000, value.get_count_added_in_this_iteration_step());
				counter.increment();
			} else {
				assert_eq!(1, value.get_count_added_in_this_iteration_step());
				counter.increment();
			}
		}
	};
	raw_histogram.get_recorded_values(raw_histogram_asserter, &mut counter);

	assert_eq!(2, counter.count);

	counter.reset();

	let histogram_asserter = |record: Option<(i64, &HistogramIterationValue, &mut AssertionCounter)>| {
		if record.is_some() {
			let index_and_value = record.unwrap();
			let (index, value, counter) = index_and_value;
			if index == 0 {
				assert_eq!(10_000, value.get_count_added_in_this_iteration_step());
			}

			assert!(value.get_count_at_value_iterated_to() != 0);
			assert_eq!(value.get_count_at_value_iterated_to(), value.get_count_added_in_this_iteration_step());
			counter.increment_by(value.get_count_added_in_this_iteration_step());
		}
	};
	histogram.get_recorded_values(histogram_asserter, &mut counter);

	assert_eq!(20_000, counter.count);
}

#[test]
fn test_get_recorded_values_with_null_pass_through_argument() {
	let histogram = get_histogram();
	let histogram_asserter = |record: Option<(i64, &HistogramIterationValue, &mut AssertionCounter)>| {

	}
	histogram.get_recorded_values(histogram_asserter, None);
}

fn assert_float_eq(expected: f64, actual: f64, delta: f64) {
    if !(actual > expected - delta && actual < expected + delta) {
        panic!(format!("Expected {} to be equal to {} +/-{}", actual, expected, delta));
    }
}

fn get_histogram() -> Histogram {
    let mut h = new_histogram(HIGHEST_TRACKABLE_VALUE, NUMBER_OF_SIGNIFICANT_VALUE_DIGITS);

    let mut i = 10_000;
    while i != 0 {
        h.record_value_with_expected_interval(1_000, 10_000);
        i -= 1;
    }
    h.record_value_with_expected_interval(100_000_000, 10_000);
    h
}

fn get_raw_histogram() -> Histogram {
    let mut h = new_histogram(HIGHEST_TRACKABLE_VALUE, NUMBER_OF_SIGNIFICANT_VALUE_DIGITS);

    let mut i = 10_000;
    while i != 0 {
        h.record_value(1_000);
        i -= 1;
    }
    h.record_value(100_000_000);
    h
}
<commit_msg>remove test<commit_after>extern crate rustogram;
const HIGHEST_TRACKABLE_VALUE: i64 = 3600 * 1000 * 1000;
const NUMBER_OF_SIGNIFICANT_VALUE_DIGITS: i32 = 3;

use rustogram::histogram::*;
use rustogram::iter::*;

#[test]
fn test_get_total_count() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();
    assert_eq!(10_001, raw_histogram.get_total_count());
    assert_eq!(20_000, histogram.get_total_count());
}

#[test]
fn test_get_max_value() {
    let histogram = get_histogram();
    assert!(histogram.values_are_equivalent(100_000_000, histogram.get_max_value()));
}

#[test]
fn test_get_min_value() {
    let histogram = get_histogram();
    assert!(histogram.values_are_equivalent(1_000, histogram.get_min_value()));
}

#[test]
fn test_get_mean_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    let expected_raw_mean = (10_000_000f64 + 100_000_000f64) / 10001f64;
    let expected_mean = (1_000f64 + 50_000_000f64) / 2f64;

    assert_float_eq(expected_raw_mean, raw_histogram.get_mean(), expected_raw_mean * 0.001);
    assert_float_eq(expected_mean, histogram.get_mean(), expected_mean * 0.001);
}

#[test]
fn test_get_std_deviation() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    let expected_raw_mean = (10_000_000f64 + 100_000_000f64) / 10001f64;
    let expected_raw_std_dev = (((10000.0 * (1000.0 - expected_raw_mean).powf(2f64)) +
                                (100000000.0 - expected_raw_mean).powf(2f64)) / 10001f64).sqrt();
    let expected_mean = (1_000f64 + 50_000_000f64) / 2f64;
    let mut expected_square_deviation_sum = 10_000f64 * (1_000f64 - expected_mean).powf(2f64);
    let mut value = 10_000;
    while value <= 100_000_000 {
        expected_square_deviation_sum += (value as f64 - expected_mean).powf(2f64);
        value += 10_000;
    }
    let expected_std_dev = (expected_square_deviation_sum as f64 / 20_000f64).sqrt();

    assert_float_eq(expected_raw_std_dev, raw_histogram.get_std_deviation(), expected_raw_std_dev * 0.001);
    assert_float_eq(expected_std_dev, histogram.get_std_deviation(), expected_std_dev * 0.001);
}

#[test]
fn test_get_value_at_percentile() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(30.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(99.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, raw_histogram.get_value_at_percentile(99.99) as f64, 1000.0 * 0.001);
    assert_float_eq(100000000.0, raw_histogram.get_value_at_percentile(99.999) as f64, 100000000.0 * 0.001);
    assert_float_eq(100000000.0, raw_histogram.get_value_at_percentile(100.0) as f64, 100000000.0 * 0.001);

    assert_float_eq(1000.0, histogram.get_value_at_percentile(30.0) as f64, 1000.0 * 0.001);
    assert_float_eq(1000.0, histogram.get_value_at_percentile(50.0) as f64, 1000.0 * 0.001);
    assert_float_eq(50000000.0, histogram.get_value_at_percentile(75.0) as f64, 50000000.0 * 0.001);
    assert_float_eq(80000000.0, histogram.get_value_at_percentile(90.0) as f64, 80000000.0 * 0.001);
    assert_float_eq(98000000.0, histogram.get_value_at_percentile(99.0) as f64, 98000000.0 * 0.001);
    assert_float_eq(100000000.0, histogram.get_value_at_percentile(99.999) as f64, 100000000.0 * 0.001);
    assert_float_eq(100000000.0, histogram.get_value_at_percentile(100.0) as f64, 100000000.0 * 0.001);

}

#[test]
fn test_get_value_at_percentile_for_large_histogram() {
    let largest_value = 1000000000000;
    let mut histogram = new_histogram(largest_value, 5);
    histogram.record_value(largest_value);

    assert!(histogram.get_value_at_percentile(100.0) > 0);
}

#[test]
fn test_get_percentile_at_or_below_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_float_eq(99.99, raw_histogram.get_percentile_at_or_below_value(5000), 0.0001);
    assert_float_eq(50.0, histogram.get_percentile_at_or_below_value(5000), 0.0001);
    assert_float_eq(100.0, histogram.get_percentile_at_or_below_value(100000000), 0.0001);
}

#[test]
fn test_get_count_between_values() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_eq!(10_000, raw_histogram.get_count_between_values(1000, 1000));
    assert_eq!(1, raw_histogram.get_count_between_values(5000, 150_000_000));
    assert_eq!(10_000, histogram.get_count_between_values(5000, 150_000_000));
}

#[test]
fn test_get_count_at_value() {
    let histogram = get_histogram();
    let raw_histogram = get_raw_histogram();

    assert_eq!(10000, raw_histogram.get_count_at_value(1000));
    assert_eq!(10000, histogram.get_count_at_value(1000));
}

struct AssertionCounter {
	count: i64
}

impl AssertionCounter {
	fn increment(&mut self) {
		self.count += 1;
	}

	fn increment_by(&mut self, increment: i64) {
		self.count += increment;
	}

	fn reset(&mut self) {
		self.count = 0;
	}
}

#[test]
fn test_get_recorded_values() {
	let histogram = get_histogram();
	let raw_histogram : Histogram = get_raw_histogram();

	let mut counter = AssertionCounter { count: 0 };

	let raw_histogram_asserter = |record: Option<(i64, &HistogramIterationValue, &mut AssertionCounter)>| {
		if record.is_some() {
			let index_and_value = record.unwrap();
			let (index, value, counter) = index_and_value;
			if index == 0 {
				assert_eq!(10_000, value.get_count_added_in_this_iteration_step());
				counter.increment();
			} else {
				assert_eq!(1, value.get_count_added_in_this_iteration_step());
				counter.increment();
			}
		}
	};
	raw_histogram.get_recorded_values(raw_histogram_asserter, &mut counter);

	assert_eq!(2, counter.count);

	counter.reset();

	let histogram_asserter = |record: Option<(i64, &HistogramIterationValue, &mut AssertionCounter)>| {
		if record.is_some() {
			let index_and_value = record.unwrap();
			let (index, value, counter) = index_and_value;
			if index == 0 {
				assert_eq!(10_000, value.get_count_added_in_this_iteration_step());
			}

			assert!(value.get_count_at_value_iterated_to() != 0);
			assert_eq!(value.get_count_at_value_iterated_to(), value.get_count_added_in_this_iteration_step());
			counter.increment_by(value.get_count_added_in_this_iteration_step());
		}
	};
	histogram.get_recorded_values(histogram_asserter, &mut counter);

	assert_eq!(20_000, counter.count);
}

fn assert_float_eq(expected: f64, actual: f64, delta: f64) {
    if !(actual > expected - delta && actual < expected + delta) {
        panic!(format!("Expected {} to be equal to {} +/-{}", actual, expected, delta));
    }
}

fn get_histogram() -> Histogram {
    let mut h = new_histogram(HIGHEST_TRACKABLE_VALUE, NUMBER_OF_SIGNIFICANT_VALUE_DIGITS);

    let mut i = 10_000;
    while i != 0 {
        h.record_value_with_expected_interval(1_000, 10_000);
        i -= 1;
    }
    h.record_value_with_expected_interval(100_000_000, 10_000);
    h
}

fn get_raw_histogram() -> Histogram {
    let mut h = new_histogram(HIGHEST_TRACKABLE_VALUE, NUMBER_OF_SIGNIFICANT_VALUE_DIGITS);

    let mut i = 10_000;
    while i != 0 {
        h.record_value(1_000);
        i -= 1;
    }
    h.record_value(100_000_000);
    h
}
<|endoftext|>


<commit_before>extern crate httpd = "tiny-http";

use std::io::net::tcp::TcpStream;

#[test]
#[ignore]   // failing
fn input_basic_string() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();

    {
        let mut stream = std::io::net::tcp::TcpStream::connect("127.0.0.1", port).unwrap();
        write!(stream, "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Type: text/plain; charset=utf8\r\nContent-Length: 5\r\n\r\nhello");
    }

    let mut request = server.recv().unwrap();

    assert_eq!(request.as_reader().read_to_string().unwrap().as_slice(), "hello");
}
<commit_msg>Input tests now passing<commit_after>extern crate httpd = "tiny-http";

use std::io::net::tcp::TcpStream;

#[test]
fn input_basic_string() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();

    {
        let mut stream = std::io::net::tcp::TcpStream::connect("127.0.0.1", port).unwrap();
        write!(stream, "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Type: text/plain; charset=utf8\r\nContent-Length: 5\r\n\r\nhello");
    }

    let mut request = server.recv().unwrap();

    assert_eq!(request.as_reader().read_to_string().unwrap().as_slice(), "hello");
}
<|endoftext|>


<commit_before>use calx_grid::{Dir6, Prefab};
use display;
use euclid::{Point2D, Rect, Vector2D, vec2};
use scancode::Scancode;
use std::collections::HashSet;
use std::fs::File;
use std::io::prelude::*;
use std::num::Wrapping;
use vitral::{self, ButtonAction, Align, FracPoint2D};
use vitral::Context;
use world::{self, Form, Location, Mutate, Portal, Query, Terraform, World, Terrain};
use world::errors::*;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum PaintMode {
    Terrain,
    Entity,
    Portal,
}

/// Top-level application state for gameplay.
pub struct View {
    pub world: World,

    fore_terrain: Terrain,
    back_terrain: Terrain,
    entity: String,
    mode: PaintMode,

    /// Camera and second camera (for portaling)
    camera: (Location, Location),
    /// Do the two cameras move together?
    camera_lock: bool,

    console: display::Console,
    console_is_large: bool,
}

impl View {
    pub fn new(world: World) -> View {
        View {
            world: world,
            fore_terrain: Terrain::Rock,
            back_terrain: Terrain::Ground,
            entity: "player".to_string(),
            mode: PaintMode::Terrain,
            camera: (Location::new(0, 0, 0), Location::new(0, 8, 0)),
            camera_lock: false,
            console: display::Console::default(),
            console_is_large: false,
        }
    }

    fn spawn_at(&mut self, loc: Location, form: Option<&str>) {
        for e in self.world.entities_at(loc) {
            self.world.remove_entity(e);
        }

        if let Some(name) = form {
            let form = Form::named(name).expect(&format!("Form '{}' not found!", name));
            self.world.spawn(&form.loadout, loc);
        }
    }

    pub fn draw(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {
        let camera_loc = self.camera.0;
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;
        view.highlight_offscreen_tiles = true;

        {
            let mut context = context.bound_clipped_r(*screen_area);

            view.draw(&self.world, &mut context);

            if let Some(loc) = view.cursor_loc {
                match self.mode {
                    PaintMode::Terrain => {
                        if context.is_mouse_pressed(vitral::MouseButton::Left) {
                            self.world.set_terrain(loc, self.fore_terrain);
                        }

                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.world.set_terrain(loc, self.back_terrain);
                        }
                    }

                    PaintMode::Entity => {
                        if context.is_mouse_pressed(vitral::MouseButton::Left) {
                            // XXX: Cloning to evade borrow checker...
                            let e = self.entity.clone();
                            self.spawn_at(loc, Some(&e[..]));
                        }

                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.spawn_at(loc, None);
                        }
                    }

                    PaintMode::Portal => {
                        let (a, b) = self.camera;
                        if a != b && context.is_mouse_pressed(vitral::MouseButton::Left) {
                            self.world.set_portal(loc, Portal::new(a, b));
                        }
                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.world.remove_portal(loc);
                        }
                    }
                }
            }
        }

        {
            let mut context = context.bound(0, 360, 640, 120);

            match context.bound(10, 10, 100, 10).button(&format!(
                "left: {:?}",
                self.fore_terrain
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Terrain;
                    self.fore_terrain = prev_terrain(self.fore_terrain);
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Terrain;
                    self.fore_terrain = next_terrain(self.fore_terrain);
                }
                _ => {}
            };

            match context.bound(112, 10, 100, 10).button(&format!(
                "right: {:?}",
                self.back_terrain
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Terrain;
                    self.back_terrain = prev_terrain(self.back_terrain);
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Terrain;
                    self.back_terrain = next_terrain(self.back_terrain);
                }
                _ => {}
            };

            match context.bound(10, 22, 100, 10).button(&format!(
                "entity: {}",
                self.entity
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Entity;

                    let names: Vec<&str> = world::FORMS.iter().filter_map(|x| x.name()).collect();
                    let idx = names.iter().position(|x| *x == &self.entity[..]).expect(
                        &format!(
                            "Invalid current entity '{}'",
                            self.entity
                        ),
                    );

                    self.entity = names[(idx + (names.len() - 1)) % names.len()].to_string();
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Entity;

                    let names: Vec<&str> = world::FORMS.iter().filter_map(|x| x.name()).collect();
                    let idx = names.iter().position(|x| *x == &self.entity[..]).expect(
                        &format!(
                            "Invalid current entity '{}'",
                            self.entity
                        ),
                    );

                    self.entity = names[(idx + 1) % names.len()].to_string();
                }
                _ => {}
            };

            let mut pos = FracPoint2D::new(1.0, 0.05);
            for loc in view.cursor_loc.iter() {
                pos = context.draw_text(
                    pos,
                    Align::Right,
                    [1.0, 1.0, 1.0, 1.0],
                    &format!("{:?}", loc),
                );
            }

        }

        if self.console_is_large {
            let mut console_area = *screen_area;
            console_area.size.height /= 2.0;
            self.console.draw_large(context, &console_area);
        } else {
            self.console.draw_small(context, screen_area);
        }

        if let Some(scancode) = context.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            if self.console_is_large {
                self.console_input(context, scancode);
            } else {
                self.editor_input(context, scancode);
            }
        }
    }

    command_parser!{
        fn load(&mut self, path: String);
        fn save(&mut self, path: String);
    }

    fn load(&mut self, path: String) {
        fn loader(path: String) -> Result<Prefab<(Terrain, Vec<String>)>> {
            let mut file = File::open(path)?;
            world::load_prefab(&mut file)
        }

        let prefab = match loader(path) {
            Ok(prefab) => prefab,
            Err(e) => {
                let _ = writeln!(&mut self.console, "Load error: {}", e);
                return;
            }
        };

        // Apply map.
        self.world = World::new(1);
        // Prefabs do not contain positioning data. The standard fullscreen prefab which includes a
        // one-cell wide offscreen boundary goes in a bounding box with origin at (-21, -22).
        self.world.deploy_prefab(
            Location::new(-21, -22, 0),
            &prefab,
        );

        // We don't want mapedit to have an active player entity.
        self.world.set_player(None);
    }

    fn save(&mut self, path: String) {
        let mut locs = HashSet::new();
        for x in world::onscreen_locations().iter() {
            locs.insert(Location::origin() + *x);
            // Get the immediate border around the actual screen cells, these will also affect the
            // visual look of the map.
            for d in Dir6::iter() {
                locs.insert(Location::origin() + *x + d.to_v2());
            }
        }

        let prefab = self.world.extract_prefab(locs.iter().cloned());

        match File::create(&path) {
            Ok(mut file) => {
                if let Err(e) = world::save_prefab(&mut file, &prefab) {
                    let _ = writeln!(&mut self.console, "Save failed: {}", e);
                } else {
                    let _ = writeln!(&mut self.console, "Saved '{}'", path);
                }
            }
            Err(e) => {
                let _ = writeln!(&mut self.console, "Couldn't open file {}: {:?}", path, e);
            }
        }
    }

    fn console_input(&mut self, context: &mut display::Backend, scancode: Scancode) {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.console_is_large = !self.console_is_large;
            }
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
            }
            F12 => context.save_screenshot("mapedit"),
            _ => {}
        }
    }

    fn editor_input(&mut self, context: &mut display::Backend, scancode: Scancode) {
        use scancode::Scancode::*;
        match scancode {
            Q => self.move_camera(vec2(-1, 0), 0),
            W => self.move_camera(vec2(-1, -1), 0),
            E => self.move_camera(vec2(0, -1), 0),
            A => self.move_camera(vec2(0, 1), 0),
            S => self.move_camera(vec2(1, 1), 0),
            D => self.move_camera(vec2(1, 0), 0),
            F1 => self.switch_camera(),
            F12 => context.save_screenshot("mapedit"),
            Tab => self.console_is_large = !self.console_is_large,
            RightBracket => self.move_camera(vec2(0, 0), 1),
            LeftBracket => self.move_camera(vec2(0, 0), -1),
            _ => {}
        }
    }

    fn move_camera(&mut self, delta: Vector2D<i32>, dz: i8) {
        let second_delta = if self.camera_lock { delta } else { vec2(0, 0) };

        let (a, b) = self.camera;
        self.camera = (a + delta, b + second_delta);

        let z0 = Wrapping(self.camera.0.z) + Wrapping(dz);
        let z1 = Wrapping(self.camera.1.z) + Wrapping(if self.camera_lock { dz } else { 0 });

        self.camera.0.z = z0.0;
        self.camera.1.z = z1.0;
    }

    fn switch_camera(&mut self) {
        let (a, b) = self.camera;
        self.camera = (b, a);
    }
}

fn next_terrain(t: Terrain) -> Terrain {
    let mut i = Terrain::iter().cycle().filter(|t| !t.is_irregular());
    loop {
        if i.next() == Some(&t) {
            return *i.next().unwrap();
        }
    }
}

fn prev_terrain(t: Terrain) -> Terrain {
    let mut i = Terrain::iter().rev().cycle().filter(|t| !t.is_irregular());
    loop {
        if i.next() == Some(&t) {
            return *i.next().unwrap();
        }
    }
}
<commit_msg>Don't directly call remove_entity in mapedit<commit_after>use calx_grid::{Dir6, Prefab};
use display;
use euclid::{Point2D, Rect, Vector2D, vec2};
use scancode::Scancode;
use std::collections::HashSet;
use std::fs::File;
use std::io::prelude::*;
use std::num::Wrapping;
use vitral::{self, ButtonAction, Align, FracPoint2D};
use vitral::Context;
use world::{self, Form, Location, Mutate, Portal, Query, Terraform, World, Terrain};
use world::errors::*;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum PaintMode {
    Terrain,
    Entity,
    Portal,
}

/// Top-level application state for gameplay.
pub struct View {
    pub world: World,

    fore_terrain: Terrain,
    back_terrain: Terrain,
    entity: String,
    mode: PaintMode,

    /// Camera and second camera (for portaling)
    camera: (Location, Location),
    /// Do the two cameras move together?
    camera_lock: bool,

    console: display::Console,
    console_is_large: bool,
}

impl View {
    pub fn new(world: World) -> View {
        View {
            world: world,
            fore_terrain: Terrain::Rock,
            back_terrain: Terrain::Ground,
            entity: "player".to_string(),
            mode: PaintMode::Terrain,
            camera: (Location::new(0, 0, 0), Location::new(0, 8, 0)),
            camera_lock: false,
            console: display::Console::default(),
            console_is_large: false,
        }
    }

    fn spawn_at(&mut self, loc: Location, form: Option<&str>) {
        for e in self.world.entities_at(loc) {
            self.world.kill_entity(e);
        }

        if let Some(name) = form {
            let form = Form::named(name).expect(&format!("Form '{}' not found!", name));
            self.world.spawn(&form.loadout, loc);
        }
    }

    pub fn draw(&mut self, context: &mut display::Backend, screen_area: &Rect<f32>) {
        let camera_loc = self.camera.0;
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;
        view.highlight_offscreen_tiles = true;

        {
            let mut context = context.bound_clipped_r(*screen_area);

            view.draw(&self.world, &mut context);

            if let Some(loc) = view.cursor_loc {
                match self.mode {
                    PaintMode::Terrain => {
                        if context.is_mouse_pressed(vitral::MouseButton::Left) {
                            self.world.set_terrain(loc, self.fore_terrain);
                        }

                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.world.set_terrain(loc, self.back_terrain);
                        }
                    }

                    PaintMode::Entity => {
                        if context.is_mouse_pressed(vitral::MouseButton::Left) {
                            // XXX: Cloning to evade borrow checker...
                            let e = self.entity.clone();
                            self.spawn_at(loc, Some(&e[..]));
                        }

                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.spawn_at(loc, None);
                        }
                    }

                    PaintMode::Portal => {
                        let (a, b) = self.camera;
                        if a != b && context.is_mouse_pressed(vitral::MouseButton::Left) {
                            self.world.set_portal(loc, Portal::new(a, b));
                        }
                        if context.is_mouse_pressed(vitral::MouseButton::Right) {
                            self.world.remove_portal(loc);
                        }
                    }
                }
            }
        }

        {
            let mut context = context.bound(0, 360, 640, 120);

            match context.bound(10, 10, 100, 10).button(&format!(
                "left: {:?}",
                self.fore_terrain
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Terrain;
                    self.fore_terrain = prev_terrain(self.fore_terrain);
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Terrain;
                    self.fore_terrain = next_terrain(self.fore_terrain);
                }
                _ => {}
            };

            match context.bound(112, 10, 100, 10).button(&format!(
                "right: {:?}",
                self.back_terrain
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Terrain;
                    self.back_terrain = prev_terrain(self.back_terrain);
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Terrain;
                    self.back_terrain = next_terrain(self.back_terrain);
                }
                _ => {}
            };

            match context.bound(10, 22, 100, 10).button(&format!(
                "entity: {}",
                self.entity
            )) {
                ButtonAction::LeftClicked => {
                    self.mode = PaintMode::Entity;

                    let names: Vec<&str> = world::FORMS.iter().filter_map(|x| x.name()).collect();
                    let idx = names.iter().position(|x| *x == &self.entity[..]).expect(
                        &format!(
                            "Invalid current entity '{}'",
                            self.entity
                        ),
                    );

                    self.entity = names[(idx + (names.len() - 1)) % names.len()].to_string();
                }
                ButtonAction::RightClicked => {
                    self.mode = PaintMode::Entity;

                    let names: Vec<&str> = world::FORMS.iter().filter_map(|x| x.name()).collect();
                    let idx = names.iter().position(|x| *x == &self.entity[..]).expect(
                        &format!(
                            "Invalid current entity '{}'",
                            self.entity
                        ),
                    );

                    self.entity = names[(idx + 1) % names.len()].to_string();
                }
                _ => {}
            };

            let mut pos = FracPoint2D::new(1.0, 0.05);
            for loc in view.cursor_loc.iter() {
                pos = context.draw_text(
                    pos,
                    Align::Right,
                    [1.0, 1.0, 1.0, 1.0],
                    &format!("{:?}", loc),
                );
            }

        }

        if self.console_is_large {
            let mut console_area = *screen_area;
            console_area.size.height /= 2.0;
            self.console.draw_large(context, &console_area);
        } else {
            self.console.draw_small(context, screen_area);
        }

        if let Some(scancode) = context.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            if self.console_is_large {
                self.console_input(context, scancode);
            } else {
                self.editor_input(context, scancode);
            }
        }

        self.world.clean_dead();
    }

    command_parser!{
        fn load(&mut self, path: String);
        fn save(&mut self, path: String);
    }

    fn load(&mut self, path: String) {
        fn loader(path: String) -> Result<Prefab<(Terrain, Vec<String>)>> {
            let mut file = File::open(path)?;
            world::load_prefab(&mut file)
        }

        let prefab = match loader(path) {
            Ok(prefab) => prefab,
            Err(e) => {
                let _ = writeln!(&mut self.console, "Load error: {}", e);
                return;
            }
        };

        // Apply map.
        self.world = World::new(1);
        // Prefabs do not contain positioning data. The standard fullscreen prefab which includes a
        // one-cell wide offscreen boundary goes in a bounding box with origin at (-21, -22).
        self.world.deploy_prefab(
            Location::new(-21, -22, 0),
            &prefab,
        );

        // We don't want mapedit to have an active player entity.
        self.world.set_player(None);
    }

    fn save(&mut self, path: String) {
        let mut locs = HashSet::new();
        for x in world::onscreen_locations().iter() {
            locs.insert(Location::origin() + *x);
            // Get the immediate border around the actual screen cells, these will also affect the
            // visual look of the map.
            for d in Dir6::iter() {
                locs.insert(Location::origin() + *x + d.to_v2());
            }
        }

        let prefab = self.world.extract_prefab(locs.iter().cloned());

        match File::create(&path) {
            Ok(mut file) => {
                if let Err(e) = world::save_prefab(&mut file, &prefab) {
                    let _ = writeln!(&mut self.console, "Save failed: {}", e);
                } else {
                    let _ = writeln!(&mut self.console, "Saved '{}'", path);
                }
            }
            Err(e) => {
                let _ = writeln!(&mut self.console, "Couldn't open file {}: {:?}", path, e);
            }
        }
    }

    fn console_input(&mut self, context: &mut display::Backend, scancode: Scancode) {
        use scancode::Scancode::*;
        match scancode {
            Tab => {
                self.console_is_large = !self.console_is_large;
            }
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
            }
            F12 => context.save_screenshot("mapedit"),
            _ => {}
        }
    }

    fn editor_input(&mut self, context: &mut display::Backend, scancode: Scancode) {
        use scancode::Scancode::*;
        match scancode {
            Q => self.move_camera(vec2(-1, 0), 0),
            W => self.move_camera(vec2(-1, -1), 0),
            E => self.move_camera(vec2(0, -1), 0),
            A => self.move_camera(vec2(0, 1), 0),
            S => self.move_camera(vec2(1, 1), 0),
            D => self.move_camera(vec2(1, 0), 0),
            F1 => self.switch_camera(),
            F12 => context.save_screenshot("mapedit"),
            Tab => self.console_is_large = !self.console_is_large,
            RightBracket => self.move_camera(vec2(0, 0), 1),
            LeftBracket => self.move_camera(vec2(0, 0), -1),
            _ => {}
        }
    }

    fn move_camera(&mut self, delta: Vector2D<i32>, dz: i8) {
        let second_delta = if self.camera_lock { delta } else { vec2(0, 0) };

        let (a, b) = self.camera;
        self.camera = (a + delta, b + second_delta);

        let z0 = Wrapping(self.camera.0.z) + Wrapping(dz);
        let z1 = Wrapping(self.camera.1.z) + Wrapping(if self.camera_lock { dz } else { 0 });

        self.camera.0.z = z0.0;
        self.camera.1.z = z1.0;
    }

    fn switch_camera(&mut self) {
        let (a, b) = self.camera;
        self.camera = (b, a);
    }
}

fn next_terrain(t: Terrain) -> Terrain {
    let mut i = Terrain::iter().cycle().filter(|t| !t.is_irregular());
    loop {
        if i.next() == Some(&t) {
            return *i.next().unwrap();
        }
    }
}

fn prev_terrain(t: Terrain) -> Terrain {
    let mut i = Terrain::iter().rev().cycle().filter(|t| !t.is_irregular());
    loop {
        if i.next() == Some(&t) {
            return *i.next().unwrap();
        }
    }
}
<|endoftext|>