<commit_before>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_int, c_uchar, c_void};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let selection = project_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&project_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    project_tree.append_column(&column);

    let mut project_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_buttons.set_size_request(-1, -1);
    build_buttons.add(&run_button);
    build_buttons.add(&build_button);
    build_buttons.add(&test_button);
    build_buttons.add(&clean_button);
    build_buttons.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_buttons, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut project_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::new_project(&mut state, &mut project_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::import_project(&mut state, &mut project_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(|| {
        ::projects::save_selection(&mut state);
    }));
    project_tree.connect(gtk::signals::RowCollapsed::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    project_tree.connect(gtk::signals::RowExpanded::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::io::fs::mkdir_recursive(&res_path.dir_path(), ::std::io::USER_DIR).ok();
                    ::std::io::File::create(&res_path).write(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::os::getenv("VIM").is_none() {
        ::std::os::setenv("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::io::File::create(&config_file).write(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_from_gui : [ffi::c_int, ..2] = [0, ..2];
    let mut gui_from_nvim : [ffi::c_int, ..2] = [0, ..2];
    unsafe {
        ffi::pipe(nvim_from_gui.as_mut_ptr());
        ffi::pipe(gui_from_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // send attach_ui message
            {
                let mut arr = neovim::Array::new();
                arr.add_integer(80);
                arr.add_integer(24);
                let msg = neovim::serialize_message(1, "attach_ui", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
            }

            // listen for messages
            let mut buf : [ffi::c_uchar, ..1024] = [0, ..1024];
            unsafe {
                loop {
                    let n = ffi::read(gui_from_nvim[0], buf.as_mut_ptr() as *mut ffi::c_void, 1024);
                    if n < 0 {
                        break;
                    } else if n > 0 {
                        let msg = ::std::string::String::from_raw_buf_len(buf.as_ptr(), n as uint);
                        let arr = neovim::deserialize_message(&msg);
                        println!("Received: {}", arr);
                    }
                }
            }
        }).detach();

        // start the gui
        gui_main(&mut pty, gui_from_nvim[0], gui_from_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // start nvim
        let mut args = ::std::os::args().clone();
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::run_with_fds(args, nvim_from_gui[0], gui_from_nvim[1]);
    }
}
<commit_msg>Separate the setup from the main loop and break receive code to separate function<commit_after>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_int, c_uchar, c_void};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut project_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    project_buttons.set_size_request(-1, -1);
    project_buttons.add(&new_button);
    project_buttons.add(&import_button);
    project_buttons.add(&rename_button);
    project_buttons.add(&remove_button);

    let mut project_tree = gtk::TreeView::new().unwrap();
    let selection = project_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    project_tree.set_model(&model);
    project_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&project_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    project_tree.append_column(&column);

    let mut project_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    project_pane.set_size_request(-1, -1);
    project_pane.pack_start(&project_buttons, false, true, 0);
    project_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_buttons = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_buttons.set_size_request(-1, -1);
    build_buttons.add(&run_button);
    build_buttons.add(&build_button);
    build_buttons.add(&test_button);
    build_buttons.add(&clean_button);
    build_buttons.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_buttons, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&project_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut project_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::new_project(&mut state, &mut project_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::import_project(&mut state, &mut project_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(|| {
        ::projects::save_selection(&mut state);
    }));
    project_tree.connect(gtk::signals::RowCollapsed::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    project_tree.connect(gtk::signals::RowExpanded::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn receive_message (fd: ffi::c_int) -> bool {
    let mut buf : [ffi::c_uchar, ..1024] = [0, ..1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return false;
    } else if n > 0 {
        let msg = unsafe { ::std::string::String::from_raw_buf_len(buf.as_ptr(), n as uint) };
        let arr = neovim::deserialize_message(&msg);
        println!("Received: {}", arr);
    }

    true
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::io::fs::mkdir_recursive(&res_path.dir_path(), ::std::io::USER_DIR).ok();
                    ::std::io::File::create(&res_path).write(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::os::getenv("VIM").is_none() {
        ::std::os::setenv("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::io::File::create(&config_file).write(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_from_gui : [ffi::c_int, ..2] = [0, ..2];
    let mut gui_from_nvim : [ffi::c_int, ..2] = [0, ..2];
    unsafe {
        ffi::pipe(nvim_from_gui.as_mut_ptr());
        ffi::pipe(gui_from_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // send attach_ui message
            {
                let mut arr = neovim::Array::new();
                arr.add_integer(80);
                arr.add_integer(24);
                let msg = neovim::serialize_message(1, "attach_ui", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
            }
            receive_message(gui_from_nvim[0]);

            // send vim_command message
/*
            {
                let mut arr = neovim::Array::new();
                arr.add_string("");
                let msg = neovim::serialize_message(1, "vim_command", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
            }
            receive_message(gui_from_nvim[0]);
*/

            // listen for messages
            loop {
                if !receive_message(gui_from_nvim[0]) {
                    break;
                }
            }
        }).detach();

        // start the gui
        gui_main(&mut pty, gui_from_nvim[0], gui_from_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // start nvim
        let mut args = ::std::os::args().clone();
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::main_setup(args);
        neovim::channel_from_fds(nvim_from_gui[0], gui_from_nvim[1]);
        neovim::main_loop();
    }
}
<|endoftext|>


<commit_before>#![feature(box_syntax)]

extern crate lindenmayer_system;
extern crate turtle;

use lindenmayer_system::{Symbol, SymbolString, Expr, Rule, System};

use std::fs::File;
use turtle::{Canvas, Turtle};

fn draw(symstr: &SymbolString<char, f32>,
        init_direction: f32,
        angle: f32,
        distance: f32,
        filename: &str) {
    let mut t = Canvas::new();
    t.right(init_direction);
    for sym in symstr.0.iter() {
        match sym.symbol {
            'F' => t.forward(distance),
            'f' => t.move_forward(distance),
            '+' => t.left(angle),
            '-' => t.right(angle),
            '[' => t.push(),
            ']' => t.pop(),
            _ => {}
        }
    }
    t.save_svg(&mut File::create(filename.to_string() + ".svg").unwrap()).unwrap();
    t.save_eps(&mut File::create(filename.to_string() + ".eps").unwrap()).unwrap();
}

fn draw_parametric(symstr: &SymbolString<char, f32>, default_angle: f32, filename: &str) {
    let mut t = Canvas::new();
    for sym in symstr.0.iter() {
        match (sym.symbol, sym.args.get(0)) {
            ('F', Some(&Expr::Const(d))) => t.forward(d),
            ('f', Some(&Expr::Const(d))) => t.move_forward(d),
            ('+', Some(&Expr::Const(a))) => t.rotate(a),
            ('+', None) => t.rotate(default_angle),
            ('-', Some(&Expr::Const(a))) => t.rotate(-a),
            ('-', None) => t.rotate(-default_angle),
            ('[', None) => t.push(),
            (']', None) => t.pop(),
            _ => {}
        }
    }
    t.save_svg(&mut File::create(filename.to_string() + ".svg").unwrap()).unwrap();
    t.save_eps(&mut File::create(filename.to_string() + ".eps").unwrap()).unwrap();
}

fn symstr(s: &str) -> SymbolString<char, f32> {
    SymbolString(s.chars()
                  .filter(|&c| !c.is_whitespace())
                  .map(|c| Symbol::new(c))
                  .collect())
}

fn rule(sym: char, successor: &str) -> Rule<char, f32> {
    Rule::new(sym, symstr(successor))
}

fn koch_curve(maxiter: usize) {
    let axiom = symstr("F++F++F");

    let mut system: System<char, f32> = System::new();
    system.add_rule(rule('F', "F-F++F-F"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, -90.0, 60.0, 10.0, &format!("koch_{:02}", iters));
}

fn dragon_curve(maxiter: usize) {
    let axiom = symstr("FX");

    let mut system = System::new();
    system.add_rule(rule('X', "X+YF+"));
    system.add_rule(rule('Y', "-FX-Y"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, 0.0, 90.0, 10.0, &format!("dragon_{:02}", iters));
}

fn sierpinski_triangle(maxiter: usize) {
    let axiom = symstr("A");

    let mut system = System::new();
    system.add_rule(rule('A', "+B-A-B+"));
    system.add_rule(rule('B', "-A+B+A-"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    // replace A and B with F
    let mut system = System::new();
    system.add_rule(rule('A', "F"));
    system.add_rule(rule('B', "F"));
    let (after, _iters) = system.develop_step(&after);

    draw(&after,
         -90.0,
         60.0,
         10.0,
         &format!("sierpinski_{:02}", iters));
}

fn fractal_plant(maxiter: usize) {
    let axiom = symstr("X");

    let mut system = System::new();
    system.add_rule(rule('X', "F-[[X]+X]+F[+FX]-X"));
    system.add_rule(rule('F', "FF"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, 0.0, 25.0, 10.0, &format!("plant_{:02}", iters));
}

fn branching_pattern_abop_1_9(maxiter: usize) {
    const R: f32 = 1.456;
    let axiom = SymbolString(vec![Symbol::new_parametric('A', vec![Expr::Const(300.0)])]);

    let mut system = System::new();
    system.add_rule(Rule::new('A',
                              SymbolString(vec![
            Symbol::new_parametric('F', vec![Expr::Arg(0)]),
            Symbol::new('['),
            Symbol::new('+'),
            Symbol::new_parametric('A', vec![Expr::Div(box Expr::Arg(0), box Expr::Const(R))]),
            Symbol::new(']'),
            Symbol::new('['),
            Symbol::new('-'),
            Symbol::new_parametric('A', vec![Expr::Div(box Expr::Arg(0), box Expr::Const(R))]),
            Symbol::new(']'),
        ])));

    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw_parametric(&after, 85.0, &format!("branching_abop_1_9_{:02}", iters));
}

fn main() {
    for i in 0..7 {
        koch_curve(i);
    }
    for i in 0..16 {
        dragon_curve(i);
    }
    for i in 0..10 {
        sierpinski_triangle(i);
    }
    for i in 4..8 {
        fractal_plant(i);
    }
    branching_pattern_abop_1_9(15);
}
<commit_msg>Refactor<commit_after>#![feature(box_syntax)]

extern crate lindenmayer_system;
extern crate turtle;

use lindenmayer_system::{Symbol, SymbolString, Expr, Rule, System};

use std::fs::File;
use turtle::{Canvas, Turtle};

fn draw(symstr: &SymbolString<char, f32>,
        init_direction: f32,
        default_angle: f32,
        default_distance: f32,
        filename: &str) {
    let mut t = Canvas::new();
    t.right(init_direction);
    for sym in symstr.0.iter() {
        match (sym.symbol, sym.args.get(0)) {
            ('F', Some(&Expr::Const(d))) => t.forward(d),
            ('F', None) => t.forward(default_distance),

            ('f', Some(&Expr::Const(d))) => t.move_forward(d),
            ('f', None) => t.move_forward(default_distance),

            ('+', Some(&Expr::Const(a))) => t.rotate(a),
            ('+', None) => t.rotate(default_angle),

            ('-', Some(&Expr::Const(a))) => t.rotate(-a),
            ('-', None) => t.rotate(-default_angle),

            ('[', None) => t.push(),
            (']', None) => t.pop(),
            _ => {}
        }
    }
    t.save_svg(&mut File::create(filename.to_string() + ".svg").unwrap()).unwrap();
    t.save_eps(&mut File::create(filename.to_string() + ".eps").unwrap()).unwrap();
}

fn symstr(s: &str) -> SymbolString<char, f32> {
    SymbolString(s.chars()
                  .filter(|&c| !c.is_whitespace())
                  .map(|c| Symbol::new(c))
                  .collect())
}

fn rule(sym: char, successor: &str) -> Rule<char, f32> {
    Rule::new(sym, symstr(successor))
}

fn koch_curve(maxiter: usize) {
    let axiom = symstr("F++F++F");

    let mut system: System<char, f32> = System::new();
    system.add_rule(rule('F', "F-F++F-F"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, -90.0, 60.0, 10.0, &format!("koch_{:02}", iters));
}

fn dragon_curve(maxiter: usize) {
    let axiom = symstr("FX");

    let mut system = System::new();
    system.add_rule(rule('X', "X+YF+"));
    system.add_rule(rule('Y', "-FX-Y"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, 0.0, 90.0, 10.0, &format!("dragon_{:02}", iters));
}

fn sierpinski_triangle(maxiter: usize) {
    let axiom = symstr("A");

    let mut system = System::new();
    system.add_rule(rule('A', "+B-A-B+"));
    system.add_rule(rule('B', "-A+B+A-"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    // replace A and B with F
    let mut system = System::new();
    system.add_rule(rule('A', "F"));
    system.add_rule(rule('B', "F"));
    let (after, _iters) = system.develop_step(&after);

    draw(&after,
         -90.0,
         60.0,
         10.0,
         &format!("sierpinski_{:02}", iters));
}

fn fractal_plant(maxiter: usize) {
    let axiom = symstr("X");

    let mut system = System::new();
    system.add_rule(rule('X', "F-[[X]+X]+F[+FX]-X"));
    system.add_rule(rule('F', "FF"));
    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after, 0.0, 25.0, 10.0, &format!("plant_{:02}", iters));
}

fn branching_pattern_abop_1_9(maxiter: usize) {
    const R: f32 = 1.456;
    let axiom = SymbolString(vec![Symbol::new_parametric('A', vec![Expr::Const(300.0)])]);

    let mut system = System::new();
    system.add_rule(Rule::new('A',
                              SymbolString(vec![
            Symbol::new_parametric('F', vec![Expr::Arg(0)]),
            Symbol::new('['),
            Symbol::new('+'),
            Symbol::new_parametric('A', vec![Expr::Div(box Expr::Arg(0), box Expr::Const(R))]),
            Symbol::new(']'),
            Symbol::new('['),
            Symbol::new('-'),
            Symbol::new_parametric('A', vec![Expr::Div(box Expr::Arg(0), box Expr::Const(R))]),
            Symbol::new(']'),
        ])));

    println!("{:?}", system);

    let (after, iters) = system.develop(axiom, maxiter);

    draw(&after,
         0.0,
         85.0,
         0.0,
         &format!("branching_abop_1_9_{:02}", iters));
}

fn main() {
    for i in 0..7 {
        koch_curve(i);
    }
    for i in 0..16 {
        dragon_curve(i);
    }
    for i in 0..10 {
        sierpinski_triangle(i);
    }
    for i in 4..8 {
        fractal_plant(i);
    }
    branching_pattern_abop_1_9(15);
}
<|endoftext|>


<commit_before>extern crate lancelot;
extern crate log;

use failure::{Error, Fail};
use log::{error, info, trace};
use std::env;
use std::process;

use lancelot::arch::*;
use lancelot::workspace::Workspace;

#[derive(Debug, Fail)]
pub enum MainError {
    #[fail(display = "foo")]
    Foo,
}

pub struct Config {
    pub mode: u8,
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 3 {
            return Err("not enough arguments: provide `lancelot.exe 32|64 /path/to/input`");
        }

        let mode = match args[1].as_ref() {
            "32" => 32,
            "64" => 64,
            _ => return Err("invalid mode, pick one of `32` or `64`"),
        };

        let filename = args[2].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { mode, filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

pub fn run(args: &Config) -> Result<(), Error> {
    info!("filename: {:?}", args.filename);

    if args.mode == 32 {
        let ws = Workspace::<Arch32>::from_file(&args.filename)?.load()?;

        info!("found {} functions", ws.get_functions().collect::<Vec<_>>().len());
        for rva in ws.get_functions() {
            println!("{:#x}", ws.module.base_address + *rva as u32);
        }
    } else if args.mode == 64 {
        let ws = Workspace::<Arch64>::from_file(&args.filename)?.load()?;

        info!("found {} functions", ws.get_functions().collect::<Vec<_>>().len());
        for rva in ws.get_functions() {
            println!("{:#x}", ws.module.base_address + *rva as u64);
        }
    }

    Ok(())
}

fn main() {
    let args = Config::from_args(env::args()).unwrap_or_else(|err| {
        eprintln!("error parsing arguments: {}", err);
        process::exit(1);
    });

    setup_logging(&args);

    if let Err(e) = run(&args) {
        error!("{:?}", e)
    }
}
<commit_msg>main: emit functions in sorted order<commit_after>extern crate lancelot;
extern crate log;

use failure::{Error, Fail};
use log::{error, info, trace};
use std::env;
use std::process;

use lancelot::arch::*;
use lancelot::workspace::Workspace;

#[derive(Debug, Fail)]
pub enum MainError {
    #[fail(display = "foo")]
    Foo,
}

pub struct Config {
    pub mode: u8,
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 3 {
            return Err("not enough arguments: provide `lancelot.exe 32|64 /path/to/input`");
        }

        let mode = match args[1].as_ref() {
            "32" => 32,
            "64" => 64,
            _ => return Err("invalid mode, pick one of `32` or `64`"),
        };

        let filename = args[2].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { mode, filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

pub fn run(args: &Config) -> Result<(), Error> {
    info!("filename: {:?}", args.filename);

    if args.mode == 32 {
        let ws = Workspace::<Arch32>::from_file(&args.filename)?.load()?;

        let mut functions = ws.get_functions().collect::<Vec<_>>();
        functions.sort();

        info!("found {} functions", functions.len());
        for rva in functions.iter() {
            println!("{:#x}", ws.module.base_address + **rva as u32);
        }
    } else if args.mode == 64 {
        let ws = Workspace::<Arch64>::from_file(&args.filename)?.load()?;

        let mut functions = ws.get_functions().collect::<Vec<_>>();
        functions.sort();

        info!("found {} functions", functions.len());
        for rva in functions.iter() {
            println!("{:#x}", ws.module.base_address + **rva as u64);
        }
    }

    Ok(())
}

fn main() {
    let args = Config::from_args(env::args()).unwrap_or_else(|err| {
        eprintln!("error parsing arguments: {}", err);
        process::exit(1);
    });

    setup_logging(&args);

    if let Err(e) = run(&args) {
        error!("{:?}", e)
    }
}
<|endoftext|>


<commit_before> #![feature(std_misc)]
extern crate time;

mod models;
mod parser;
mod mayberef;

use std::fs::{File, read_dir};
use std::io::{BufReader, BufRead, Read, Write, stdin};
use std::path::{Path};
use std::collections::HashMap;
use std::collections::hash_map::Entry::*;
use std::ascii::OwnedAsciiExt;
use models::*;

fn get_line() -> String {
    let mut stdin = stdin();
    let mut buffer = String::new();
    stdin.read_line(&mut buffer).unwrap();
    buffer
}

fn find_most_common_words(corpus_loc: &str, outfile: &str) {
    let path = Path::new(corpus_loc);
    let mut word_counts = HashMap::new();
    let words = files(path).flat_map(|file| read_words(file));

    for word in words {
        match word_counts.entry(word) {
            Vacant(e) => { e.insert(1); },
            Occupied(mut e) => { *e.get_mut() += 1; },
        }
    }

    let mut counts: Vec<_> = word_counts.into_iter().collect();
    counts.sort_by(|a, b| b.1.cmp(&a.1));

    let mut out = File::create(&Path::new(outfile)).unwrap();
    for (word, count) in counts {
        out.write_all(format!("{}, {}\n", word, count).as_bytes()).unwrap();
    }

}

fn load_most_common_words(filename: &str, num: usize) -> Vec<String> {
    let file = File::open(&Path::new(filename)).unwrap();
    let reader = BufReader::new(file);
    reader.lines().map(|line|
        line.unwrap().split(',').next().unwrap().to_string()
    )
    .take(num)
    .collect()
}

fn sentences<T: Read + 'static>(reader: BufReader<T>) -> Box<Iterator<Item = String>> {
    Box::new(reader.split('.' as u8)
                   .filter_map(|v| {
                        let lowercase = v.unwrap().into_ascii_lowercase();
                        String::from_utf8(lowercase).ok()
                    }))
}

fn read_words<R: BufRead + 'static>(reader: R) -> Box<Iterator<Item = String>> {
    Box::new(reader.lines()
                   .filter_map(|line| line.ok())
                   .flat_map(|line| {
                       line.split(|c| match c {
                                'a'...'z' | 'A'...'Z' => false,
                                _ => true,
                            })
                           .filter(|word| !word.is_empty())
                           .map(|word| word.to_string().into_ascii_lowercase())
                           .collect::<Vec<_>>()
                           .into_iter()
                   }))
}

fn files(path: &Path) -> Box<Iterator<Item = BufReader<File>>> {
    Box::new(read_dir(path)
            .unwrap()
            .map(|path| path.unwrap().path())
            .filter(|path| path.to_str().unwrap().ends_with(".txt"))
            .map(|path| {
                let file = File::open(&path).unwrap();
                BufReader::new(file)
            }))
}

fn create_model(path: &Path) {
    const CORPUS_DIR: &'static str = "/home/jamougha/corpus/pg";
    const WORDS: &'static str = "/home/jamougha/corpus/pg/word_counts.csv";
    let start_time = time::get_time();
    // find_most_common_words(CORPUS_DIR, WORDS);
    let words = load_most_common_words(WORDS, 30000);
    let mut builder = LanguageModelBuilder::new(10, words);

    let corpus_path = Path::new(CORPUS_DIR);

    let mut num_words = 0;

    for sentence in files(corpus_path).flat_map(sentences) {
        let mut acc = builder.new_sentence();
        for word in sentence.split(|c| match c {
            'a'...'z' => false,
            _ => true,
        }).filter(|w| !w.is_empty())
        {
            num_words += 1;
            acc.add_word(word);
            if num_words % 10_000_000 == 0 {
                println!("Loaded {} million words in {} seconds",
                         num_words / 1_000_000,
                         time::get_time().sec - start_time.sec);
            }
        }
    }

    builder.save(path);
    let end_time = time::get_time();
    println!("Model built in {}s", end_time.sec - start_time.sec);
}

fn main() {
    let path = Path::new("/home/jamougha/corpus/pg/model.data");
    create_model(&path);
    let start_time = time::get_time();
    let builder = LanguageModelBuilder::load(&path);
    let model = builder.build();
    let end_time = time::get_time();
    println!("Model loaded in {}s", start_time.sec - end_time.sec);

    loop {
        println!("");
        let input = get_line();
        if input.starts_with(":q") {
            break;
        }

        match parser::parse(input.trim_matches(|c: char| c.is_whitespace()), &model) {
            Ok(word_vec) => {
                let nearest = model.nearest_words(&word_vec);
                println!(" = {:?}", word_vec);
                println!("-------------");
                for word in nearest.iter().take(20) {
                    println!("{:?}, {}", word, word_vec.distance(word));
                }
            }
            Err(e) => println!("{:?}", e)
        }

    }

}
<commit_msg>Fix model load time and don't scan the model now we can load the builder data directly<commit_after> #![feature(std_misc)]
extern crate time;

mod models;
mod parser;
mod mayberef;

use std::fs::{File, read_dir};
use std::io::{BufReader, BufRead, Read, Write, stdin};
use std::path::{Path};
use std::collections::HashMap;
use std::collections::hash_map::Entry::*;
use std::ascii::OwnedAsciiExt;
use models::*;

fn get_line() -> String {
    let mut stdin = stdin();
    let mut buffer = String::new();
    stdin.read_line(&mut buffer).unwrap();
    buffer
}

fn find_most_common_words(corpus_loc: &str, outfile: &str) {
    let path = Path::new(corpus_loc);
    let mut word_counts = HashMap::new();
    let words = files(path).flat_map(|file| read_words(file));

    for word in words {
        match word_counts.entry(word) {
            Vacant(e) => { e.insert(1); },
            Occupied(mut e) => { *e.get_mut() += 1; },
        }
    }

    let mut counts: Vec<_> = word_counts.into_iter().collect();
    counts.sort_by(|a, b| b.1.cmp(&a.1));

    let mut out = File::create(&Path::new(outfile)).unwrap();
    for (word, count) in counts {
        out.write_all(format!("{}, {}\n", word, count).as_bytes()).unwrap();
    }

}

fn load_most_common_words(filename: &str, num: usize) -> Vec<String> {
    let file = File::open(&Path::new(filename)).unwrap();
    let reader = BufReader::new(file);
    reader.lines().map(|line|
        line.unwrap().split(',').next().unwrap().to_string()
    )
    .take(num)
    .collect()
}

fn sentences<T: Read + 'static>(reader: BufReader<T>) -> Box<Iterator<Item = String>> {
    Box::new(reader.split('.' as u8)
                   .filter_map(|v| {
                        let lowercase = v.unwrap().into_ascii_lowercase();
                        String::from_utf8(lowercase).ok()
                    }))
}

fn read_words<R: BufRead + 'static>(reader: R) -> Box<Iterator<Item = String>> {
    Box::new(reader.lines()
                   .filter_map(|line| line.ok())
                   .flat_map(|line| {
                       line.split(|c| match c {
                                'a'...'z' | 'A'...'Z' => false,
                                _ => true,
                            })
                           .filter(|word| !word.is_empty())
                           .map(|word| word.to_string().into_ascii_lowercase())
                           .collect::<Vec<_>>()
                           .into_iter()
                   }))
}

fn files(path: &Path) -> Box<Iterator<Item = BufReader<File>>> {
    Box::new(read_dir(path)
            .unwrap()
            .map(|path| path.unwrap().path())
            .filter(|path| path.to_str().unwrap().ends_with(".txt"))
            .map(|path| {
                let file = File::open(&path).unwrap();
                BufReader::new(file)
            }))
}

fn create_model(path: &Path) {
    const CORPUS_DIR: &'static str = "/home/jamougha/corpus/pg";
    const WORDS: &'static str = "/home/jamougha/corpus/pg/word_counts.csv";
    let start_time = time::get_time();
    // find_most_common_words(CORPUS_DIR, WORDS);
    let words = load_most_common_words(WORDS, 30000);
    let mut builder = LanguageModelBuilder::new(10, words);

    let corpus_path = Path::new(CORPUS_DIR);

    let mut num_words = 0;

    for sentence in files(corpus_path).flat_map(sentences) {
        let mut acc = builder.new_sentence();
        for word in sentence.split(|c| match c {
            'a'...'z' => false,
            _ => true,
        }).filter(|w| !w.is_empty())
        {
            num_words += 1;
            acc.add_word(word);
            if num_words % 10_000_000 == 0 {
                println!("Loaded {} million words in {} seconds",
                         num_words / 1_000_000,
                         time::get_time().sec - start_time.sec);
            }
        }
    }

    builder.save(path);
    let end_time = time::get_time();
    println!("Model built in {}s", end_time.sec - start_time.sec);
}

fn main() {
    let path = Path::new("/home/jamougha/corpus/pg/model.data");
    // create_model(&path);
    let start_time = time::get_time();
    let builder = LanguageModelBuilder::load(&path);
    let model = builder.build();
    println!("Model loaded in {}s", time::get_time().sec - start_time.sec);

    loop {
        println!("");
        let input = get_line();
        if input.starts_with(":q") {
            break;
        }

        match parser::parse(input.trim_matches(|c: char| c.is_whitespace()), &model) {
            Ok(word_vec) => {
                let nearest = model.nearest_words(&word_vec);
                println!(" = {:?}", word_vec);
                println!("-------------");
                for word in nearest.iter().take(20) {
                    println!("{:?}, {}", word, word_vec.distance(word));
                }
            }
            Err(e) => println!("{:?}", e)
        }

    }

}
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;
use std::str;
use tokio_core::io::{Codec, EasyBuf};
use tokio_core::io::{Io, Framed};
use tokio_proto::pipeline::ServerProto;
use tokio_service::Service;
use futures::{future, Future, BoxFuture};

#[derive(Default)]
pub struct CliCodec {
    /// Offset within the incoming EasyBuf at which newline search last ended
    search_offset: usize,
}

impl Codec for CliCodec {
    /// Input type is a tuple with the command name and an optional argument string
    type In = (String, Option<String>);

    /// Response type is just a string
    type Out = String;

    /// Find a newline, decode to a tuple of command name and argument string
    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
        // Find newline
        let m = buf
            .as_slice()
            .iter()
            .skip(self.search_offset)
            .position(|&b| b == b'\n');

        match m {
            // Process the line if a newline was found
            Some(idx) => {
                println!("Found newline at position {}, started at {}", idx, self.search_offset); // XXX

                let line = buf.drain_to(self.search_offset + idx);
                buf.drain_to(1);

                self.search_offset = 0;

                match str::from_utf8(line.as_slice()) {
                    // Return the string on successful UTF-8 decode
                    // (TODO: split on the first space, ignore blank lines)
                    Ok(s) => Ok(Some(
                            ("Received".to_string(), Some(s.trim().to_string()))
                            )),

                    // Return an error if invalid UTF-8 is received
                    Err(e) => Err(io::Error::new(io::ErrorKind::Other, format!("invalid UTF-8: {:?}", e))),
                }
            },

            // Save our position if a newline wasn't found
            _ => {
                println!("Haven't received newline yet!  We started at offset {}, now at {}", self.search_offset, buf.len()); // XXX

                self.search_offset = buf.len();

                Ok(None)
            }
        }
    }

    /// Append the String to the outgoing buffer
    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        buf.extend(msg.as_bytes());
        buf.push(b'\n');
        Ok(())
    }
}

pub struct CliProto;

impl<T: Io + 'static> ServerProto<T> for CliProto {
    type Request = (String, Option<String>);
    type Response = String;

    type Transport = Framed<T, CliCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CliCodec::default()))
    }
}

pub struct CliServer;

impl Service for CliServer {
    type Request = (String, Option<String>);
    type Response = String;

    type Error = io::Error;

    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        future::ok(format!("Received: {:?}", req)).boxed()
    }
}

fn main() {
    // TODO
    println!("Hello, world!");
}
<commit_msg>Start the CliServer service.<commit_after>extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;
use std::str;
use tokio_core::io::{Codec, EasyBuf};
use tokio_core::io::{Io, Framed};
use tokio_proto::pipeline::ServerProto;
use tokio_proto::TcpServer;
use tokio_service::Service;
use futures::{future, Future, BoxFuture};

#[derive(Default)]
pub struct CliCodec {
    /// Offset within the incoming EasyBuf at which newline search last ended
    search_offset: usize,
}

impl Codec for CliCodec {
    /// Input type is a tuple with the command name and an optional argument string
    type In = (String, Option<String>);

    /// Response type is just a string
    type Out = String;

    /// Find a newline, decode to a tuple of command name and argument string
    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
        // Find newline
        let m = buf
            .as_slice()
            .iter()
            .skip(self.search_offset)
            .position(|&b| b == b'\n');

        match m {
            // Process the line if a newline was found
            Some(idx) => {
                println!("Found newline at position {}, started at {}", idx, self.search_offset); // XXX

                let line = buf.drain_to(self.search_offset + idx);
                buf.drain_to(1);

                self.search_offset = 0;

                match str::from_utf8(line.as_slice()) {
                    // Return the string on successful UTF-8 decode
                    // (TODO: split on the first space, ignore blank lines)
                    Ok(s) => Ok(Some(
                            ("Received".to_string(), Some(s.trim().to_string()))
                            )),

                    // Return an error if invalid UTF-8 is received
                    Err(e) => Err(io::Error::new(io::ErrorKind::Other, format!("invalid UTF-8: {:?}", e))),
                }
            },

            // Save our position if a newline wasn't found
            _ => {
                println!("Haven't received newline yet!  We started at offset {}, now at {}", self.search_offset, buf.len()); // XXX

                self.search_offset = buf.len();

                Ok(None)
            }
        }
    }

    /// Append the String to the outgoing buffer
    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        buf.extend(msg.as_bytes());
        buf.push(b'\n');
        Ok(())
    }
}

pub struct CliProto;

impl<T: Io + 'static> ServerProto<T> for CliProto {
    type Request = (String, Option<String>);
    type Response = String;

    type Transport = Framed<T, CliCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CliCodec::default()))
    }
}

pub struct CliServer;

impl Service for CliServer {
    type Request = (String, Option<String>);
    type Response = String;

    type Error = io::Error;

    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        future::ok(format!("Received: {:?}", req)).boxed()
    }
}

fn main() {
    let addr = "0.0.0.0:14311".parse().unwrap();
    let server = TcpServer::new(CliProto, addr);

    println!("Serving on {}", addr);
    server.serve(|| Ok(CliServer));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) || c == '.' || c == ':' // TODO: use is_plx
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_u(c) || c == ':' // TODO: use is_plx
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':' // TODO: use is_plx
            } else {
                is_pn_chars(c) || c == ':' || c == '.' // TODO: use is_plx
            }
        })
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<commit_msg>pn_local allow plx<commit_after>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) ||
    c == '.'  || c == ':'              ||
    c == '%'  || is_hex_digit(c as u8) ||
    c == '\\' || is_pn_local_esc(c)
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        let mut percent_count = 0;
        let mut pn_local_esc_count = 0;
        val.char_indices().all(|(idx, c)| {
            if percent_count > 0 {
                percent_count = percent_count - 1;
                is_hex_digit(c as u8)
            } else if c == '%' {
                percent_count = 2;
                true
            } else if pn_local_esc_count > 0 {
                pn_local_esc_count = pn_local_esc_count - 1;
                is_pn_local_esc(c)
            } else if c == '\\' {
                pn_local_esc_count = 1;
                true
            } else if idx == 0 {
                is_pn_chars_u(c) || c == ':'
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':'
            } else {
                is_pn_chars(c) || c == ':' || c == '.'
            }
        }) && percent_count == 0 && pn_local_esc_count == 0
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(pn_local("hoge:%28 piyo") , IResult::Done(" piyo", "hoge:%28") );
    assert_eq!(pn_local("hoge:%2 piyo")  , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:%__ piyo") , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:\\* piyo") , IResult::Done(" piyo", "hoge:\\*") );
    assert_eq!(pn_local("%28\\* piyo")   , IResult::Done(" piyo", "%28\\*")   );
    assert_eq!(pn_local("%28\\ piyo")    , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<|endoftext|>


<commit_before>#[macro_use(accepts, to_sql_checked)]
extern crate postgres;
extern crate chrono;
extern crate byteorder;
extern crate num;
#[macro_use(value_t)]
extern crate clap;

mod currency;

use postgres::{Connection, SslMode};
use chrono::{NaiveDateTime, UTC};
use currency::Currency;
use clap::{App, SubCommand, ArgMatches, Arg};

const ACCOUNT_ID_ARG_NAME: &'static str = "ACCOUNT_ID";
const BALANCE_ARG_NAME:    &'static str = "BALANCE";

// Define the data in the database.
struct Account {
    id: i32,
    name: String,
    kind: String,
}

struct Balance {
    id: i32,
    account: i32,
    as_of: chrono::NaiveDateTime,
    balance: Currency
}

struct Deposit {
    id: i32,
    account: i32,
    at: chrono::NaiveDateTime,
    amount: Currency
}

fn prepare_interface<'a, 'b>() -> ArgMatches<'a, 'b> {
    // Top level command.
    let mut app = App::new("investments")
                      .about("Keeps track of investments");

    // Subcommands for the 'account' subcommand.
    let mut accounts_sub = SubCommand::with_name("account")
                                  .about("manage accounts");
    let accounts_list = SubCommand::with_name("list")
                                   .about("list accounts");
    accounts_sub = accounts_sub.subcommand(accounts_list);

    // Subcommands for the 'balance' subcommand.
    let mut balances_sub = SubCommand::with_name("balance")
                                  .about("manage balances");
    let balances_list = SubCommand::with_name("list")
                                   .about("list balances by account");
    let balances_update = SubCommand::with_name("update")
                                     .about("add a new balance for an account")
                                     .arg(
                                          Arg::with_name(ACCOUNT_ID_ARG_NAME)
                                              .help("The account to update")
                                              .required(true)
                                              .index(1)
                                     )
                                     .arg(
                                          Arg::with_name(BALANCE_ARG_NAME)
                                              .help("The current balance of the account, e.g. £1234.56")
                                              .required(true)
                                              .index(2)
                                     );
    balances_sub = balances_sub.subcommand(balances_list)
                               .subcommand(balances_update);

    // Register top-level subcommands.
    app = app.subcommand(accounts_sub);
    app = app.subcommand(balances_sub);

    return app.get_matches();
}

// List the accounts stored and their balances.
fn list_balances() {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let stmt = conn.prepare("
        SELECT DISTINCT ON (balance.account) accounts.id, accounts.name, balance.balance
        FROM balance
        INNER JOIN accounts ON balance.account=accounts.id
        ORDER BY balance.account, balance.as_of DESC"
    ).unwrap();

    println!("Balances:");

    for row in stmt.query(&[]).unwrap() {
        let account_id: i32 = row.get(0);
        let name: String = row.get(1);
        let balance: Currency = row.get(2);
        println!("\t({}) {}: {}", account_id, name, balance);
    }
}

fn update_balances(matches: &ArgMatches) {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let balance = Balance {
        id: 0,
        account: value_t!(matches.value_of(ACCOUNT_ID_ARG_NAME), i32).unwrap(),
        as_of: UTC::now().naive_utc(),
        balance: value_t!(matches.value_of(BALANCE_ARG_NAME), Currency).unwrap(),
    };

    let stmt = conn.prepare("
        INSERT INTO balance (account, as_of, balance) VALUES
            ($1, $2, $3)
    ").unwrap();
    let updates = stmt.execute(&[&balance.account, &balance.as_of, &balance.balance]).unwrap();
}

// Show the accounts in the system.
fn list_accounts() {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let stmt = conn.prepare("
        SELECT accounts.id, accounts.name
        FROM accounts
        ORDER BY accounts.id"
    ).unwrap();

    println!("Accounts:");

    for row in stmt.query(&[]).unwrap() {
        let account_id: i32 = row.get(0);
        let name: String = row.get(1);
        println!("\t{}: {}", account_id, name);
    }

}

// Handle the account subcommand.
fn handle_accounts(matches: &ArgMatches) {
    match matches.subcommand() {
        ("list", Some(matches)) => {list_accounts()},
        _                       => {},
    }
}

// Handle the balance subcommand.
fn handle_balances(matches: &ArgMatches) {
    match matches.subcommand() {
        ("list", Some(matches))   => {list_balances()},
        ("update", Some(matches)) => {update_balances(matches)},
        _                         => {},
    }
}

fn main() {
    let matches = prepare_interface();

    match matches.subcommand() {
        ("account", Some(matches)) => {handle_accounts(matches)},
        ("balance", Some(matches)) => {handle_balances(matches)},
        _                          => {},
    }
}
<commit_msg>Add new accounts.<commit_after>#[macro_use(accepts, to_sql_checked)]
extern crate postgres;
extern crate chrono;
extern crate byteorder;
extern crate num;
#[macro_use(value_t)]
extern crate clap;

mod currency;

use postgres::{Connection, SslMode};
use chrono::{NaiveDateTime, UTC};
use currency::Currency;
use clap::{App, SubCommand, ArgMatches, Arg};

const ACCOUNT_ID_ARG_NAME:   &'static str = "ACCOUNT_ID";
const BALANCE_ARG_NAME:      &'static str = "BALANCE";
const ACCOUNT_NAME_ARG_NAME: &'static str = "ACCOUNT_NAME";
const ACCOUNT_TYPE_ARG_NAME: &'static str = "ACCOUNT_TYPE";

// Define the data in the database.
struct Account {
    id: i32,
    name: String,
    kind: String,
}

struct Balance {
    id: i32,
    account: i32,
    as_of: chrono::NaiveDateTime,
    balance: Currency
}

struct Deposit {
    id: i32,
    account: i32,
    at: chrono::NaiveDateTime,
    amount: Currency
}

fn prepare_interface<'a, 'b>() -> ArgMatches<'a, 'b> {
    // Top level command.
    let mut app = App::new("investments")
                      .about("Keeps track of investments");

    // Subcommands for the 'account' subcommand.
    let mut accounts_sub = SubCommand::with_name("account")
                                  .about("manage accounts");
    let accounts_list = SubCommand::with_name("list")
                                   .about("list accounts");
    let accounts_add = SubCommand::with_name("add")
                                  .about("add new account")
                                  .arg(
                                      Arg::with_name(ACCOUNT_NAME_ARG_NAME)
                                          .help("The name of the new account")
                                          .required(true)
                                          .index(1)
                                  )
                                  .arg(
                                      Arg::with_name(ACCOUNT_TYPE_ARG_NAME)
                                          .help("The type of the new account")
                                          .required(true)
                                          .index(2)
                                  );
    accounts_sub = accounts_sub.subcommand(accounts_list)
                               .subcommand(accounts_add);

    // Subcommands for the 'balance' subcommand.
    let mut balances_sub = SubCommand::with_name("balance")
                                  .about("manage balances");
    let balances_list = SubCommand::with_name("list")
                                   .about("list balances by account");
    let balances_update = SubCommand::with_name("update")
                                     .about("add a new balance for an account")
                                     .arg(
                                          Arg::with_name(ACCOUNT_ID_ARG_NAME)
                                              .help("The account to update")
                                              .required(true)
                                              .index(1)
                                     )
                                     .arg(
                                          Arg::with_name(BALANCE_ARG_NAME)
                                              .help("The current balance of the account, e.g. £1234.56")
                                              .required(true)
                                              .index(2)
                                     );
    balances_sub = balances_sub.subcommand(balances_list)
                               .subcommand(balances_update);

    // Register top-level subcommands.
    app = app.subcommand(accounts_sub);
    app = app.subcommand(balances_sub);

    return app.get_matches();
}

// List the accounts stored and their balances.
fn list_balances() {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let stmt = conn.prepare("
        SELECT DISTINCT ON (balance.account) accounts.id, accounts.name, balance.balance
        FROM balance
        INNER JOIN accounts ON balance.account=accounts.id
        ORDER BY balance.account, balance.as_of DESC"
    ).unwrap();

    println!("Balances:");

    for row in stmt.query(&[]).unwrap() {
        let account_id: i32 = row.get(0);
        let name: String = row.get(1);
        let balance: Currency = row.get(2);
        println!("\t({}) {}: {}", account_id, name, balance);
    }
}

fn update_balances(matches: &ArgMatches) {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let balance = Balance {
        id: 0,
        account: value_t!(matches.value_of(ACCOUNT_ID_ARG_NAME), i32).unwrap(),
        as_of: UTC::now().naive_utc(),
        balance: value_t!(matches.value_of(BALANCE_ARG_NAME), Currency).unwrap(),
    };

    let stmt = conn.prepare("
        INSERT INTO balance (account, as_of, balance) VALUES
            ($1, $2, $3)
    ").unwrap();
    let updates = stmt.execute(&[&balance.account, &balance.as_of, &balance.balance]).unwrap();
}

fn add_account(matches: &ArgMatches) {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let account = Account {
        id: 0,
        name: matches.value_of(ACCOUNT_NAME_ARG_NAME).unwrap().to_string(),
        kind: matches.value_of(ACCOUNT_TYPE_ARG_NAME).unwrap().to_string(),
    };

    let stmt = conn.prepare("
        INSERT INTO accounts (name, kind) VALUES ($1, $2)
    ").unwrap();
    let updates = stmt.execute(&[&account.name, &account.kind]).unwrap();

    if updates == 0 {println!("Failed to add new account.")}
}

// Show the accounts in the system.
fn list_accounts() {
    let conn = Connection::connect("postgres://cory@localhost:5432/finances", &SslMode::None).unwrap();

    let stmt = conn.prepare("
        SELECT accounts.id, accounts.name
        FROM accounts
        ORDER BY accounts.id"
    ).unwrap();

    println!("Accounts:");

    for row in stmt.query(&[]).unwrap() {
        let account_id: i32 = row.get(0);
        let name: String = row.get(1);
        println!("\t{}: {}", account_id, name);
    }
}

// Handle the account subcommand.
fn handle_accounts(matches: &ArgMatches) {
    match matches.subcommand() {
        ("list", Some(matches)) => {list_accounts()},
        ("add", Some(matches))  => {add_account(matches)},
        _                       => {},
    }
}

// Handle the balance subcommand.
fn handle_balances(matches: &ArgMatches) {
    match matches.subcommand() {
        ("list", Some(matches))   => {list_balances()},
        ("update", Some(matches)) => {update_balances(matches)},
        _                         => {},
    }
}

fn main() {
    let matches = prepare_interface();

    match matches.subcommand() {
        ("account", Some(matches)) => {handle_accounts(matches)},
        ("balance", Some(matches)) => {handle_balances(matches)},
        _                          => {},
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use game::entity;
use game::entity::Entity;
use game::entity::PhysicalProperties;
use game::map::Map;
use game::sprite::{Sprite, Animation};

use gmath::vectors::Vec2;
use gmath::shapes::Rect;

use keyboard::KeyboardState;

use sdl2::keycode;
use sdl2::render::Renderer;
use sdl2::render::Texture;

pub struct Player {
    accel      : Vec2<f32>,
    vel        : Vec2<f32>,
    pos        : Vec2<f32>,
    base_bounds: Rect,
    base_hitbox: Rect,
    keyboard   : Rc<RefCell<KeyboardState>>,
    on_ground  : bool,
    properties : PhysicalProperties,
    animation  : Animation,
}

impl Entity for Player {
    fn acceleration(&self) -> Vec2<f32> { self.accel }
    fn set_acceleration(&mut self, new_accel: Vec2<f32>) { self.accel = new_accel; }
    fn velocity(&self) -> Vec2<f32> { self.vel }
    fn set_velocity(&mut self, new_vel: Vec2<f32>) { self.vel = new_vel; }
    fn position(&self) -> Vec2<f32> { self.pos }
    fn set_position(&mut self, new_pos: Vec2<f32>) { self.pos = new_pos }
    fn physical_properties(&self) -> PhysicalProperties { self.properties }
    fn bounds(&self) -> Rect { self.base_bounds.move_vec(self.pos) }
    fn is_on_ground(&self) -> bool { self.on_ground }
    fn hit_y(&mut self, value: bool) { self.on_ground = value }
}

impl Player {
    pub fn new(position: Vec2<f32>, spritesheet: Rc<~Texture>,
            keyboard: Rc<RefCell<KeyboardState>>) -> Player {

        let sprite = Sprite {
            spritesheet: spritesheet,
            offset: Vec2::new(32*2, 0),
            frame_width: 32*2,
            frame_height: 64*2,
            num_frames_x: 6,
            num_frames_y: 1,
        };

        Player {
            accel: Vec2::new(0.0, 9.8),
            vel: Vec2::zero(),
            pos: position,
            base_bounds: Rect::new(0.0, 0.0, 32.0, 90.0),
            base_hitbox: Rect::new(0.0, 0.0, 32.0, 32.0),
            keyboard: keyboard,
            on_ground: false,
            properties: PhysicalProperties {
                c_drag        : 0.470,
                mass          : 70.00, // (kg)
                acting_area   : 0.760, // (m^2)
                movement_accel: 5.000,
                max_velocity  : 7.000, // (m/s)
                jump_accel    : 5.000, // (m/s)
                jump_time     : 0.000, // (secs)
                stopping_bonus: 1.000,
            },
            animation: Animation::new(sprite, 0.2),
        }
    }

    pub fn update(&mut self, map: &Map, secs: f32) {
        self.handle_input();
        entity::physics(self, map, secs);
        self.animation.update(secs);
    }

    fn handle_input(&mut self) {
        let keyboard = self.keyboard.borrow().borrow();

        self.accel.x =
            if keyboard.get().is_keydown(keycode::LeftKey) {
                -self.properties.movement_accel * if self.on_ground { 1.0 } else { 0.6 }
            }
            else if keyboard.get().is_keydown(keycode::RightKey) {
                self.properties.movement_accel * if self.on_ground { 1.0 } else { 0.6 }
            }
            else {
                0.0
            };

        if keyboard.get().is_new_keypress(keycode::UpKey) {
            self.vel = self.vel + Vec2::new(0.0, -self.properties.jump_accel);
        }
    }

    pub fn draw(&self, renderer: &Renderer) {
        let pos = Vec2::new(self.pos.x as i32, self.pos.y as i32);
        self.animation.draw(pos, renderer);
    }
}
<commit_msg>Add multiple sprites to player<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::num::abs;

use game::entity;
use game::entity::Entity;
use game::entity::PhysicalProperties;
use game::map::Map;
use game::sprite::{Sprite, Animation};

use gmath::vectors::Vec2;
use gmath::shapes::Rect;

use keyboard::KeyboardState;

use sdl2::keycode;
use sdl2::render::Renderer;
use sdl2::render::Texture;

pub struct Player {
    accel      : Vec2<f32>,
    vel        : Vec2<f32>,
    pos        : Vec2<f32>,
    base_bounds: Rect,
    base_hitbox: Rect,
    keyboard   : Rc<RefCell<KeyboardState>>,
    on_ground  : bool,
    properties : PhysicalProperties,
    animations : ~[Animation],
    animation_state: AnimationState
}

enum AnimationState {
    Standing = 0u,
    Walking  = 1u,
}

impl Entity for Player {
    fn acceleration(&self) -> Vec2<f32> { self.accel }
    fn set_acceleration(&mut self, new_accel: Vec2<f32>) { self.accel = new_accel; }
    fn velocity(&self) -> Vec2<f32> { self.vel }
    fn set_velocity(&mut self, new_vel: Vec2<f32>) { self.vel = new_vel; }
    fn position(&self) -> Vec2<f32> { self.pos }
    fn set_position(&mut self, new_pos: Vec2<f32>) { self.pos = new_pos }
    fn physical_properties(&self) -> PhysicalProperties { self.properties }
    fn bounds(&self) -> Rect { self.base_bounds.move_vec(self.pos) }
    fn is_on_ground(&self) -> bool { self.on_ground }
    fn hit_y(&mut self, value: bool) { self.on_ground = value }
}

impl Player {
    pub fn new(position: Vec2<f32>, spritesheet: Rc<~Texture>,
            keyboard: Rc<RefCell<KeyboardState>>) -> Player {
        let stand_sprite = Sprite {
            spritesheet: spritesheet.clone(),
            offset: Vec2::new(0, 0),
            frame_width: 64,
            frame_height: 128,
            num_frames_x: 1,
            num_frames_y: 1,
        };
        let stand_animation = Animation::new(stand_sprite, 0.0);

        let walk_sprite = Sprite {
            spritesheet: spritesheet.clone(),
            offset: Vec2::new(64, 0),
            frame_width: 64,
            frame_height: 128,
            num_frames_x: 6,
            num_frames_y: 1,
        };
        let walk_animation = Animation::new(walk_sprite, 0.2);

        Player {
            accel: Vec2::new(0.0, 9.8),
            vel: Vec2::zero(),
            pos: position,
            base_bounds: Rect::new(0.0, 0.0, 32.0, 90.0),
            base_hitbox: Rect::new(0.0, 0.0, 32.0, 32.0),
            keyboard: keyboard,
            on_ground: false,
            properties: PhysicalProperties {
                c_drag        : 0.470,
                mass          : 70.00, // (kg)
                acting_area   : 0.760, // (m^2)
                movement_accel: 3.000,
                max_velocity  : 6.000, // (m/s)
                jump_accel    : 5.000, // (m/s)
                jump_time     : 0.000, // (secs)
                stopping_bonus: 1.000,
            },
            animations: box [stand_animation, walk_animation],
            animation_state: Standing,
        }
    }

    pub fn update(&mut self, map: &Map, secs: f32) {
        self.handle_input();
        entity::physics(self, map, secs);

        if abs(self.velocity().x) < 0.1 {
            self.animation_state = Standing;
        }
        else {
            self.animation_state = Walking;
            self.animations[Walking as uint].frame_time = 0.7 / abs(self.velocity().x)
        }

        self.animations[self.animation_state as uint].update(secs);
    }

    fn handle_input(&mut self) {
        let keyboard = self.keyboard.borrow().borrow();

        self.accel.x =
            if keyboard.get().is_keydown(keycode::LeftKey) {
                -self.properties.movement_accel * if self.on_ground { 1.0 } else { 0.6 }
            }
            else if keyboard.get().is_keydown(keycode::RightKey) {
                self.properties.movement_accel * if self.on_ground { 1.0 } else { 0.6 }
            }
            else {
                0.0
            };

        if keyboard.get().is_new_keypress(keycode::UpKey) {
            self.vel = self.vel + Vec2::new(0.0, -self.properties.jump_accel);
        }
    }

    pub fn draw(&self, renderer: &Renderer) {
        let pos = Vec2::new(self.pos.x as i32, self.pos.y as i32);
        self.animations[self.animation_state as uint].draw(pos, renderer);
    }
}
<|endoftext|>


<commit_before>extern crate ndarray;

use ndarray_ext::NdArray;
use tensor::Tensor;

#[allow(mutable_transmutes)]
/// Checks the validity of `gradients` with finite difference trick.
/// For this test only, `variables` must be "shared" variables.
pub fn gradient_check<'a, 'b, T>(
    objective: &Tensor,
    gradients: &[T],
    variables: &[&Tensor],
    feeds: &[(&Tensor, &NdArray)],
    eps: f32,
    tol: f32,
) where
    T: AsRef<Tensor>,
{
    // backprop
    let theoretical_grads = ::eval::eval(gradients, feeds);

    // for each variable nodes
    for (var_node, th_grad) in variables.iter().zip(theoretical_grads) {
        // Sorry for unwrap
        let v_arr = var_node.get_persistent_array().unwrap();

        let head_ptr: *mut f32 = v_arr.as_mut_ptr();

        // for each values
        for i in 0..v_arr.len() as isize {
            let evacuated;

            // perturbation (+)
            unsafe {
                evacuated = *head_ptr.offset(i);
                *head_ptr.offset(i) = evacuated + eps;
            }

            // eval
            let ref obj_pos = ::eval::eval(&[objective], feeds)[0];

            // perturbation (-)
            unsafe {
                *head_ptr.offset(i) = evacuated - eps;
            }

            // eval
            let ref obj_neg = ::eval::eval(&[objective], feeds)[0];

            // restore
            unsafe {
                *head_ptr.offset(i) = evacuated;
            }

            let g_num = (obj_pos - obj_neg).scalar_sum() / (2. * eps);
            let g_th = unsafe { *th_grad.as_ptr().offset(i) };

            // compare
            let diff = (g_num - g_th).abs();
            if diff > tol {
                panic!(
                    "Gradient checking failed with too large error: num={}, bp={}",
                    g_num,
                    g_th
                );
            }
        }
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! eval_with_time {
  ( $x:expr) => {
    {
      use std::time::{Duration, Instant};
      let start = Instant::now();
      let result = $x;
      let end = start.elapsed();
      println!("{}.{:03} sec", end.as_secs(), end.subsec_nanos() / 1_000_000);
      result
    }
  };
}
<commit_msg>Remove unnecessary annotation<commit_after>extern crate ndarray;

use ndarray_ext::NdArray;
use tensor::Tensor;

/// Checks the validity of `gradients` with finite difference trick.
/// For this test only, `variables` must be "shared" variables.
pub fn gradient_check<'a, 'b, T>(
    objective: &Tensor,
    gradients: &[T],
    variables: &[&Tensor],
    feeds: &[(&Tensor, &NdArray)],
    eps: f32,
    tol: f32,
) where
    T: AsRef<Tensor>,
{
    // backprop
    let theoretical_grads = ::eval::eval(gradients, feeds);

    // for each variable nodes
    for (var_node, th_grad) in variables.iter().zip(theoretical_grads) {
        // Sorry for unwrap
        let v_arr = var_node.get_persistent_array().unwrap();

        let head_ptr: *mut f32 = v_arr.as_mut_ptr();

        // for each values
        for i in 0..v_arr.len() as isize {
            let evacuated;

            // perturbation (+)
            unsafe {
                evacuated = *head_ptr.offset(i);
                *head_ptr.offset(i) = evacuated + eps;
            }

            // eval
            let ref obj_pos = ::eval::eval(&[objective], feeds)[0];

            // perturbation (-)
            unsafe {
                *head_ptr.offset(i) = evacuated - eps;
            }

            // eval
            let ref obj_neg = ::eval::eval(&[objective], feeds)[0];

            // restore
            unsafe {
                *head_ptr.offset(i) = evacuated;
            }

            let g_num = (obj_pos - obj_neg).scalar_sum() / (2. * eps);
            let g_th = unsafe { *th_grad.as_ptr().offset(i) };

            // compare
            let diff = (g_num - g_th).abs();
            if diff > tol {
                panic!(
                    "Gradient checking failed with too large error: num={}, bp={}",
                    g_num,
                    g_th
                );
            }
        }
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! eval_with_time {
  ( $x:expr) => {
    {
      use std::time::{Duration, Instant};
      let start = Instant::now();
      let result = $x;
      let end = start.elapsed();
      println!("{}.{:03} sec", end.as_secs(), end.subsec_nanos() / 1_000_000);
      result
    }
  };
}
<|endoftext|>


<commit_before>
extern crate love2d;
use love2d::{Window, Event};
use love2d::{ElementState, VirtualKeyCode};

use std::collections::HashMap;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            // let delta = frame.delta();

            frame.set_color_html("312");
            frame.draw_rect((-0.5, -0.5), (0.5, 0.5));

            frame.set_color_html("#033112");
            frame.draw_rect((0.0, 0.0), (-1.0, -1.0));

            frame.set_color(1.0, 0.0, 0.0, 1.0);
            frame.draw_line(0.0, 0.0, 1.0, 1.0);

            frame.set_color(0.0, 0.0, 1.0, 0.3);
            frame.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

            frame.set_color(0.0, 1.0, 0.0, 0.3);
            frame.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

            frame.set_color(1.0, 0.0, 0.0, 0.3);
            frame.draw_circle(0.25, -0.25, 0.75, 0.25, 10);

            frame.finish();
        }

        for ev in app.poll_events() {
            use Event::*;
            use VirtualKeyCode::*;
            match ev {
                Closed => break 'main,
                KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        Space => println!("Space!"),
                        Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<commit_msg>Added simple animation of circle<commit_after>
extern crate love2d;
use love2d::{Window, Event};
use love2d::{ElementState, VirtualKeyCode};

use std::collections::HashMap;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();

    let mut time = 0.0;

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            let delta = frame.delta() as f32;
            time += delta;

            frame.set_color_html("312");
            frame.draw_rect((-0.5, -0.5), (0.5, 0.5));

            frame.set_color_html("#033112");
            frame.draw_rect((0.0, 0.0), (-1.0, -1.0));

            frame.set_color(1.0, 0.0, 0.0, 1.0);
            frame.draw_line(0.0, 0.0, 1.0, 1.0);

            frame.set_color(0.0, 0.0, 1.0, 0.3);
            frame.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

            frame.set_color(0.0, 1.0, 0.0, 0.3);
            frame.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

            frame.set_color(1.0, 0.0, 0.0, 0.3);
            frame.draw_circle(0.25 * time.sin(), -0.25 * time.cos(), 0.75, 0.25, 10);

            frame.finish();
        }

        for ev in app.poll_events() {
            use Event::*;
            use VirtualKeyCode::*;

            match ev {
                Closed => break 'main,
                KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        Space => println!("Space!"),
                        Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>//#![feature(convert)]

//extern crate std;
extern crate libc;

use std::process::Command;
use std::str;
use std::option::Option;
use std::collections::BTreeSet;
use libc::{execvp, perror};
use std::ptr;
use std::env;
use std::ffi::CString;

fn detached_session_number(line: &str) -> Option<usize> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| s.parse().ok() )
    }
}

fn detached_sessions(output: &str) -> BTreeSet<usize> {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

// XXX: Conversion convenience function until rust allows
//   #![feature(convert)] and
//   .to_cstring
fn c_string_or_bust(arg: &str, error: &str) -> CString {
    let bytes: Vec<u8> = arg.bytes().collect();
    CString::new(bytes).ok().expect(error)
}

fn exec_program(program: &str, args: &[&str]) {
    let c_program = c_string_or_bust(program, "Program name isn't unicode").as_ptr();
    // I don't much care about the ownership of the strings here
    // at this point, so let's just fail if execvp isn't working.
    unsafe {
        let mut c_args = vec![];
        for &arg in args.iter() {
            c_args.push(c_string_or_bust(arg, "Can't with string that aren't valid Unicode").as_ptr());
        }
        c_args.push(ptr::null());
        execvp(c_program, c_args.as_mut_ptr());
        perror(c_string_or_bust("Running tmux failed:", "Invalid text").as_ptr());
    }
    panic!("Oh noes, couldn't exec.");
}

fn prepare_environment() {
    let path = match env::var("PATH") {
        Ok(path) => path + ":/usr/local/bin",
        _ => "/bin:/usr/bin:/usr/local/bin".to_string()
    };
    env::set_var("PATH", path.as_str());
}

fn start_server() {
    Command::new("tmux").arg("start-server").status().ok()
        .expect("Could not start tmux server: it exited with an error status.");
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output().ok()
        .expect("Running list-sessions command exited with an error status");

    let output = str::from_utf8(session_output.stdout.as_slice()).ok()
        .expect("Could not read the (expected) utf-8 from tmux");
    let sessions = detached_sessions(output);

    match sessions.iter().next() {
        Some(n) => {
            let my_str = n.to_string();
            let session = my_str.as_ref();
            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
            args.push(session);
            exec_program("tmux", args.as_slice());
        }
        _ => { exec_program("tmux", ["tmux"].as_ref()); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(11) => (),
        Some(n) => panic!(format!("Should have returned 11, got {}!", n)),
        None => panic!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>Get rid of .as_slice() and use & conversion<commit_after>//#![feature(convert)]

//extern crate std;
extern crate libc;

use std::process::Command;
use std::str;
use std::option::Option;
use std::collections::BTreeSet;
use libc::{execvp, perror};
use std::ptr;
use std::env;
use std::ffi::CString;

fn detached_session_number(line: &str) -> Option<usize> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| s.parse().ok() )
    }
}

fn detached_sessions(output: &str) -> BTreeSet<usize> {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

// XXX: Conversion convenience function until rust allows
//   #![feature(convert)] and
//   .to_cstring
fn c_string_or_bust(arg: &str, error: &str) -> CString {
    let bytes: Vec<u8> = arg.bytes().collect();
    CString::new(bytes).ok().expect(error)
}

fn exec_program(program: &str, args: &[&str]) {
    let c_program = c_string_or_bust(program, "Program name isn't unicode").as_ptr();
    // I don't much care about the ownership of the strings here
    // at this point, so let's just fail if execvp isn't working.
    unsafe {
        let mut c_args = vec![];
        for &arg in args.iter() {
            c_args.push(c_string_or_bust(arg, "Can't with string that aren't valid Unicode").as_ptr());
        }
        c_args.push(ptr::null());
        execvp(c_program, c_args.as_mut_ptr());
        perror(c_string_or_bust("Running tmux failed:", "Invalid text").as_ptr());
    }
    panic!("Oh noes, couldn't exec.");
}

fn prepare_environment() {
    let path = match env::var("PATH") {
        Ok(path) => path + ":/usr/local/bin",
        _ => "/bin:/usr/bin:/usr/local/bin".to_string()
    };
    env::set_var("PATH", &path);
}

fn start_server() {
    Command::new("tmux").arg("start-server").status().ok()
        .expect("Could not start tmux server: it exited with an error status.");
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output().ok()
        .expect("Running list-sessions command exited with an error status");

    let output = str::from_utf8(&session_output.stdout).ok()
        .expect("Could not read the (expected) utf-8 from tmux");
    let sessions = detached_sessions(output);

    match sessions.iter().next() {
        Some(n) => {
            let my_str = n.to_string();
            let session = my_str.as_ref();
            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
            args.push(session);
            exec_program("tmux", args.as_slice());
        }
        _ => { exec_program("tmux", ["tmux"].as_ref()); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(11) => (),
        Some(n) => panic!(format!("Should have returned 11, got {}!", n)),
        None => panic!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>