<commit_before>//
extern crate termion;

//
use self::termion::event::{Event, Key, MouseEvent};
use self::termion::input::{TermRead, MouseTerminal};
use self::termion::raw::IntoRawMode;
use self::termion::terminal_size;

use self::termion::cursor::DetectCursorPos;

use std::io::{self, Write, stdin, Stdout};

//
use core::screen::Screen;
use core::codepointinfo::CodepointInfo;

use core::editor::Editor;

fn fill_screen(screen: &mut Screen, data: &[u8]) {

    screen.clear();

    let mut offset = 0;
    for c in data {

        let mut displayed_cp: char = *c as char;
        if *c as char == '\n' as char {
            displayed_cp = ' ';
        }

        let cpi = CodepointInfo {
            cp: *c as char,
            displayed_cp: displayed_cp,
            offset: offset,
        };

        let (ok, _) = screen.push(cpi);
        offset += 1;
        if ok == false {
            break;
        }
    }
}

fn draw_screen(screen: &Screen, stdout: &mut Stdout) {

    write!(stdout, "{}", termion::cursor::Goto(1, 1)).unwrap();

    for l in 0..screen.height {
        let line = &screen.line[l];

        for c in 0..line.width {
            let cpi = &line.chars[c];
            write!(stdout, "{}", cpi.displayed_cp).unwrap();
        }

        if l < screen.height - 1 {
            write!(stdout, "\r\n").unwrap();
        }
    }

    stdout.flush().unwrap();
}

fn draw_buffer(buf: &Option<&Box<::core::buffer::Buffer>>,
               mut scr: &mut Screen,
               mut stdout: &mut Stdout) {
    match *buf {
        Some(ref b) => {
            match b.byte_buffer {

                Some(ref byte_buf) => {
                    fill_screen(&mut scr, &byte_buf.data);
                    draw_screen(&scr, &mut stdout);
                }
                _ => {}
            }
        }
        _ => {}
    }
}

fn terminal_clear_current_line(mut stdout: &mut Stdout, line_width: u16) {
    for _ in 0..line_width {
        write!(stdout, " ").unwrap();
    }
}

fn terminal_goto_line(mut stdout: &mut Stdout, y: u16) {
    write!(stdout, "{}", termion::cursor::Goto(1, y)).unwrap();
}

fn terminal_cursor_to(mut stdout: &mut Stdout, x: u16, y: u16) {
    write!(stdout, "{}", termion::cursor::Goto(x, y)).unwrap();
}

fn terminal_clear_screen(stdout: &mut Stdout, clear_toggle_flag: &mut bool) {
    if *clear_toggle_flag == true {
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
    }
    *clear_toggle_flag = false;
}

pub fn main_loop(editor: &mut Editor) {

    let mut stdout = MouseTerminal::from(io::stdout().into_raw_mode().unwrap());

    write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
    stdout.flush().unwrap();

    let mut keys: Vec<Event> = Vec::new();

    let mut quit = false;
    let mut clear_toggle_flag = true;

    //
    let display_status = true;

    // select file
    let mut bid = 2;
    let mut buf = editor.buffer_map.get(&bid);

    while !quit {
        let (width, height) = terminal_size().unwrap();
        let mut scr = Screen::new(width as usize, height as usize);

        terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
        write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
        stdout.flush().unwrap();

        draw_buffer(&buf, &mut scr, &mut stdout);
        if display_status == true {
            display_status_line(&buf, "", height, width, &mut stdout);
        }

        for evt in stdin().events() {

            keys.push(evt.unwrap());
            let evt = keys[keys.len() - 1].clone();

            terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
            write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
            stdout.flush().unwrap();

            draw_buffer(&buf, &mut scr, &mut stdout);

            // Print recieved Events...
            let mut status = String::new();
            match evt {

                Event::Key(k) => {
                    match k {
                        // Exit.
                        Key::Ctrl('r') => {
                            keys.clear();
                        }

                        Key::Ctrl('c') => {
                            if keys.len() > 1 {
                                if let Event::Key(prev_event) = keys[keys.len() - 2] {
                                    if let Key::Ctrl(prev_char) = prev_event {
                                        if prev_char == 'x' {
                                            quit = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        Key::Char(c) => {
                            if c == '\n' {
                                status = format!("'{}'", "<newline>");
                            } else {
                                status = format!("'{}'", c);
                            }
                        }
                        Key::Alt(c) => status = format!("Alt-{}", c),
                        Key::Ctrl(c) => status = format!("Ctrl-{}", c),

                        Key::F(1) => {
                            if bid > 0 {
                                bid -= 1;
                            }
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(2) => {
                            bid = ::std::cmp::min(bid + 1, (editor.buffer_map.len() - 1) as u64);
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(f) => status = format!("F{:?}", f),
                        Key::Left => status = format!("<left>"),
                        Key::Right => status = format!("<right>"),
                        Key::Up => status = format!("<up>"),
                        Key::Down => status = format!("<down>"),
                        Key::Backspace => status = format!("<backspace>"),
                        Key::Home => status = format!("<Home>"),
                        Key::End => status = format!("<End>"),
                        Key::PageUp => status = format!("<PageUp>"),
                        Key::PageDown => status = format!("<PageDown>"),
                        Key::Delete => status = format!("<Delete>"),
                        Key::Insert => status = format!("<Insert>"),
                        Key::Esc => status = format!("<Esc>"),
                        _ => status = format!("Other"),
                    }
                }

                Event::Mouse(m) => {
                    match m {
                        MouseEvent::Press(mb, x, y) => {
                            status = format!("MouseEvent::Press => MouseButton {:?} @ ({}, {})",
                                             mb,
                                             x,
                                             y);
                        }

                        MouseEvent::Release(x, y) => {
                            status = format!("MouseEvent::Release => @ ({}, {})", x, y);
                        }

                        MouseEvent::Hold(x, y) => {
                            status = format!("MouseEvent::Hold => @ ({}, {})", x, y);
                        }
                    };
                }

                Event::Unsupported(_) => {}
            }

            if display_status == true {
                display_status_line(&buf, &status, height, width, &mut stdout);
            }
        }
    }

    // quit
    // clear, restore cursor
    write!(stdout, "{}{}", termion::clear::All, termion::cursor::Show).unwrap();
    stdout.flush().unwrap();
}

fn display_status_line(buf: &Option<&Box<::core::buffer::Buffer>>,
                       status: &str,
                       line: u16,
                       width: u16,
                       mut stdout: &mut Stdout) {
    // select/clear last line
    let name = match *buf {
        Some(ref b) => b.name.as_str(),
        None => "",
    };

    let file_name = match *buf {
        Some(ref b) => {
            match b.byte_buffer {
                Some(ref bb) => bb.file_name.as_str(),
                None => "",
            }
        }
        None => "",
    };

    terminal_cursor_to(&mut stdout, 1, line);
    terminal_clear_current_line(&mut stdout, width);
    terminal_cursor_to(&mut stdout, 1, line);

    let status_str = format!("buffer_name '{}', file: '{}', event '{}'",
                             name,
                             file_name,
                             status);

    print!("{}", status_str);
    stdout.flush().unwrap();
}
<commit_msg>remove unused code/imports<commit_after>//
extern crate termion;

//
use self::termion::event::{Event, Key, MouseEvent};
use self::termion::input::{TermRead, MouseTerminal};
use self::termion::raw::IntoRawMode;
use self::termion::terminal_size;

use std::io::{self, Write, stdin, Stdout};

//
use core::screen::Screen;
use core::codepointinfo::CodepointInfo;

use core::editor::Editor;

fn fill_screen(screen: &mut Screen, data: &[u8]) {

    screen.clear();

    let mut offset = 0;
    for c in data {

        let mut displayed_cp: char = *c as char;
        if *c as char == '\n' as char {
            displayed_cp = ' ';
        }

        let cpi = CodepointInfo {
            cp: *c as char,
            displayed_cp: displayed_cp,
            offset: offset,
        };

        let (ok, _) = screen.push(cpi);
        offset += 1;
        if ok == false {
            break;
        }
    }
}

fn draw_screen(screen: &Screen, stdout: &mut Stdout) {

    write!(stdout, "{}", termion::cursor::Goto(1, 1)).unwrap();

    for l in 0..screen.height {
        let line = &screen.line[l];

        for c in 0..line.width {
            let cpi = &line.chars[c];
            write!(stdout, "{}", cpi.displayed_cp).unwrap();
        }

        if l < screen.height - 1 {
            write!(stdout, "\r\n").unwrap();
        }
    }

    stdout.flush().unwrap();
}

fn draw_buffer(buf: &Option<&Box<::core::buffer::Buffer>>,
               mut scr: &mut Screen,
               mut stdout: &mut Stdout) {
    match *buf {
        Some(ref b) => {
            match b.byte_buffer {

                Some(ref byte_buf) => {
                    fill_screen(&mut scr, &byte_buf.data);
                    draw_screen(&scr, &mut stdout);
                }
                _ => {}
            }
        }
        _ => {}
    }
}

fn terminal_clear_current_line(mut stdout: &mut Stdout, line_width: u16) {
    for _ in 0..line_width {
        write!(stdout, " ").unwrap();
    }
}

fn terminal_cursor_to(mut stdout: &mut Stdout, x: u16, y: u16) {
    write!(stdout, "{}", termion::cursor::Goto(x, y)).unwrap();
}

fn terminal_clear_screen(stdout: &mut Stdout, clear_toggle_flag: &mut bool) {
    if *clear_toggle_flag == true {
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
    }
    *clear_toggle_flag = false;
}

pub fn main_loop(editor: &mut Editor) {

    let mut stdout = MouseTerminal::from(io::stdout().into_raw_mode().unwrap());

    write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
    stdout.flush().unwrap();

    let mut keys: Vec<Event> = Vec::new();

    let mut quit = false;
    let mut clear_toggle_flag = true;

    //
    let display_status = true;

    // select file
    let mut bid = 2;
    let mut buf = editor.buffer_map.get(&bid);

    while !quit {
        let (width, height) = terminal_size().unwrap();
        let mut scr = Screen::new(width as usize, height as usize);

        terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
        write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
        stdout.flush().unwrap();

        draw_buffer(&buf, &mut scr, &mut stdout);
        if display_status == true {
            display_status_line(&buf, "", height, width, &mut stdout);
        }

        for evt in stdin().events() {

            keys.push(evt.unwrap());
            let evt = keys[keys.len() - 1].clone();

            terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
            write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
            stdout.flush().unwrap();

            draw_buffer(&buf, &mut scr, &mut stdout);

            // Print recieved Events...
            let mut status = String::new();
            match evt {

                Event::Key(k) => {
                    match k {
                        // Exit.
                        Key::Ctrl('r') => {
                            keys.clear();
                        }

                        Key::Ctrl('c') => {
                            if keys.len() > 1 {
                                if let Event::Key(prev_event) = keys[keys.len() - 2] {
                                    if let Key::Ctrl(prev_char) = prev_event {
                                        if prev_char == 'x' {
                                            quit = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        Key::Char(c) => {
                            if c == '\n' {
                                status = format!("'{}'", "<newline>");
                            } else {
                                status = format!("'{}'", c);
                            }
                        }
                        Key::Alt(c) => status = format!("Alt-{}", c),
                        Key::Ctrl(c) => status = format!("Ctrl-{}", c),

                        Key::F(1) => {
                            if bid > 0 {
                                bid -= 1;
                            }
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(2) => {
                            bid = ::std::cmp::min(bid + 1, (editor.buffer_map.len() - 1) as u64);
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(f) => status = format!("F{:?}", f),
                        Key::Left => status = format!("<left>"),
                        Key::Right => status = format!("<right>"),
                        Key::Up => status = format!("<up>"),
                        Key::Down => status = format!("<down>"),
                        Key::Backspace => status = format!("<backspace>"),
                        Key::Home => status = format!("<Home>"),
                        Key::End => status = format!("<End>"),
                        Key::PageUp => status = format!("<PageUp>"),
                        Key::PageDown => status = format!("<PageDown>"),
                        Key::Delete => status = format!("<Delete>"),
                        Key::Insert => status = format!("<Insert>"),
                        Key::Esc => status = format!("<Esc>"),
                        _ => status = format!("Other"),
                    }
                }

                Event::Mouse(m) => {
                    match m {
                        MouseEvent::Press(mb, x, y) => {
                            status = format!("MouseEvent::Press => MouseButton {:?} @ ({}, {})",
                                             mb,
                                             x,
                                             y);
                        }

                        MouseEvent::Release(x, y) => {
                            status = format!("MouseEvent::Release => @ ({}, {})", x, y);
                        }

                        MouseEvent::Hold(x, y) => {
                            status = format!("MouseEvent::Hold => @ ({}, {})", x, y);
                        }
                    };
                }

                Event::Unsupported(_) => {}
            }

            if display_status == true {
                display_status_line(&buf, &status, height, width, &mut stdout);
            }
        }
    }

    // quit
    // clear, restore cursor
    write!(stdout, "{}{}", termion::clear::All, termion::cursor::Show).unwrap();
    stdout.flush().unwrap();
}

fn display_status_line(buf: &Option<&Box<::core::buffer::Buffer>>,
                       status: &str,
                       line: u16,
                       width: u16,
                       mut stdout: &mut Stdout) {
    // select/clear last line
    let name = match *buf {
        Some(ref b) => b.name.as_str(),
        None => "",
    };

    let file_name = match *buf {
        Some(ref b) => {
            match b.byte_buffer {
                Some(ref bb) => bb.file_name.as_str(),
                None => "",
            }
        }
        None => "",
    };

    terminal_cursor_to(&mut stdout, 1, line);
    terminal_clear_current_line(&mut stdout, width);
    terminal_cursor_to(&mut stdout, 1, line);

    let status_str = format!("buffer_name '{}', file: '{}', event '{}'",
                             name,
                             file_name,
                             status);

    print!("{}", status_str);
    stdout.flush().unwrap();
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::Token;

#[derive(Debug, PartialEq)]
pub enum Symbol {
    Label(u16), // Label + its byte offset
    Constant(Token), // The constant value
}

pub struct AssemblerError {
    message: String,
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Symbol>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new(tokens);
        let tokens = parser.parse()?;

        Ok(self.assemble(tokens))
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new(tokens);
        let tokens = parser.parse()?;

        Ok(self.assemble(tokens))
    }

    fn assemble(&mut self, tokens: Vec<Vec<Token>>) -> Vec<u8> {
        // First, index the labels so we have addresses for them
        self.index_labels(&tokens);
        Vec::new()
    }

    /// Iterates over the tokens, counting the total byte counts as it
    /// goes, indexing the labels
    fn index_labels(&mut self, tokens: &[Vec<Token>]) {
        let mut addr: u16 = 0;
        for line in tokens {
            let mut peeker = line.iter().peekable();
            for token in line {
                peeker.next();
                if let &Token::OpCode(ref mnemonic) = token {
                    // Determine an addressing mode that was attempted,
                    let addressing_mode = if let None = peeker.peek() {
                        // if there was no token, then its implied
                        AddressingMode::Implied
                    } else {
                        // Otherwise, lets try and convert
                        // the next token to a mode
                        let next = *peeker.peek().unwrap();
                        next.to_addressing_mode()
                    };

                    if let Some(opcode) =
                           OpCode::from_mnemonic_and_addressing_mode(mnemonic.clone(),
                                                                     addressing_mode) {
                        addr += opcode.length as u16;
                    }
                }

                if let &Token::Label(ref name) = token {
                    // Check if the next thing is an assignment:
                    let next = *peeker.peek().unwrap();
                    if let &Token::Assignment = next {
                        peeker.next();
                        let ref val = *peeker.next().unwrap();
                        // Storethe token we're assigning
                        self.symbol_table.insert(name.clone(), Symbol::Constant(val.clone()));
                        peeker.next();
                    } else {
                        self.symbol_table.insert(name.clone(), Symbol::Label(addr));
                    }
                }
            }
        }
        for (key, ref value) in self.symbol_table.iter() {
            println!("{:?} -> {:?}", key, value);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assembler::token::Token;

    #[test]
    fn can_index_labels() {
        let mut assembler = Assembler::new();
        assembler.assemble_string("
            VARIABLE = $4400
            MAIN LDA $4400
            LOOP INX
        ");

        let var = assembler.symbol_table.get("VARIABLE").unwrap();
        assert_eq!(&Symbol::Constant(Token::Absolute("4400".into())), var);
    }
}
<commit_msg>Clean up assembler test<commit_after>use std::collections::HashMap;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::Token;

#[derive(Debug, PartialEq)]
pub enum Symbol {
    Label(u16), // Label + its byte offset
    Constant(Token), // The constant value
}

pub struct AssemblerError {
    message: String,
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Symbol>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new(tokens);
        let tokens = parser.parse()?;

        Ok(self.assemble(tokens))
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new(tokens);
        let tokens = parser.parse()?;

        Ok(self.assemble(tokens))
    }

    fn assemble(&mut self, tokens: Vec<Vec<Token>>) -> Vec<u8> {
        // First, index the labels so we have addresses for them
        self.index_labels(&tokens);
        Vec::new()
    }

    /// Iterates over the tokens, counting the total byte counts as it
    /// goes, indexing the labels
    fn index_labels(&mut self, tokens: &[Vec<Token>]) {
        let mut addr: u16 = 0;
        for line in tokens {
            let mut peeker = line.iter().peekable();
            for token in line {
                peeker.next();
                if let &Token::OpCode(ref mnemonic) = token {
                    // Determine an addressing mode that was attempted,
                    let addressing_mode = if let None = peeker.peek() {
                        // if there was no token, then its implied
                        AddressingMode::Implied
                    } else {
                        // Otherwise, lets try and convert
                        // the next token to a mode
                        let next = *peeker.peek().unwrap();
                        next.to_addressing_mode()
                    };

                    if let Some(opcode) =
                           OpCode::from_mnemonic_and_addressing_mode(mnemonic.clone(),
                                                                     addressing_mode) {
                        addr += opcode.length as u16;
                    }
                }

                if let &Token::Label(ref name) = token {
                    // Check if the next thing is an assignment:
                    let next = *peeker.peek().unwrap();
                    if let &Token::Assignment = next {
                        peeker.next();
                        let ref val = *peeker.next().unwrap();
                        // Storethe token we're assigning
                        self.symbol_table.insert(name.clone(), Symbol::Constant(val.clone()));
                        peeker.next();
                    } else {
                        self.symbol_table.insert(name.clone(), Symbol::Label(addr));
                    }
                }
            }
        }
        for (key, ref value) in self.symbol_table.iter() {
            println!("{:?} -> {:?}", key, value);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assembler::token::Token;

    #[test]
    fn can_index_labels() {
        let mut assembler = Assembler::new();
        assembler.assemble_string("
            VARIABLE = $4400
            MAIN LDA $4400
            LOOP INX
        ");

        assert_eq!(&Symbol::Constant(Token::Absolute("4400".into())),
                   assembler.symbol_table.get("VARIABLE").unwrap());
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::LexerToken;

#[derive(Debug, PartialEq)]
pub enum Symbol {
    Label(u16), // Label + its byte offset
    Constant(LexerToken), // The constant value
}

pub struct AssemblerError {
    message: String,
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Symbol>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = Vec::new(); // TODO: Fix.

        Ok(self.assemble(tokens))
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = Vec::new(); // TODO: Fix

        Ok(self.assemble(tokens))
    }

    fn assemble(&mut self, tokens: Vec<Vec<LexerToken>>) -> Vec<u8> {
        // First, index the labels so we have addresses for them
        Vec::new()
    }
}<commit_msg>Add basic Assembler functionality and test<commit_after>use std::collections::HashMap;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::{LexerToken, ParserToken};

#[derive(Debug, PartialEq)]
pub enum Symbol {
    Label(u16), // Label + its byte offset
    Constant(LexerToken), // The constant value
}

#[derive(Debug)]
pub struct AssemblerError {
    message: String,
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Symbol>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens))
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = Vec::new(); // TODO: Fix

        Ok(self.assemble(tokens))
    }

    fn assemble(&mut self, tokens: Vec<ParserToken>) -> Vec<u8> {
        // First, index the labels so we have addresses for them
        let mut result = Vec::new();

        for token in tokens {
            if let ParserToken::OpCode(opcode) = token {
                result.push(opcode.code);
            } else if let ParserToken::RawByte(byte) = token {
                result.push(byte);
            }
        }

        result
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_assemble_basic_code() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            LDA $4400
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44], &bytes[..]);
    }
}<|endoftext|>


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

//! Basic status view definition

use chrono::prelude::Utc;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;

use tui::constants::VIEW_BASIC_STATUS;
use tui::types::TUIStatusListener;

use servers::common::types::SyncStatus;
use servers::ServerStats;

const NANO_TO_MILLIS: f64 = 1.0 / 1_000_000.0;

pub struct TUIStatusView;

impl TUIStatusListener for TUIStatusView {
	/// Create basic status view
	fn create() -> Box<View> {
		let basic_status_view = BoxView::with_full_screen(
			LinearLayout::new(Orientation::Vertical)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Current Status: "))
						.child(TextView::new("Starting").with_id("basic_current_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Connected Peers: "))
						.child(TextView::new("0").with_id("connected_peers")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Chain Height: "))
						.child(TextView::new("  ").with_id("basic_header_chain_height")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_header_total_difficulty")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Height: "))
						.child(TextView::new("  ").with_id("chain_height")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_total_difficulty")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_config_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_network_info")),
				), //.child(logo_view)
		);
		Box::new(basic_status_view.with_id(VIEW_BASIC_STATUS))
	}

	/// update
	fn update(c: &mut Cursive, stats: &ServerStats) {
		//find and update here as needed
		let basic_status = {
			match stats.sync_status {
				SyncStatus::Initial => "Initializing".to_string(),
				SyncStatus::NoSync => "Running".to_string(),
				SyncStatus::AwaitingPeers(_) => "Waiting for peers".to_string(),
				SyncStatus::HeaderSync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading headers: {}%, step 1/4", percent)
				}
				SyncStatus::TxHashsetDownload {
					start_time,
					downloaded_size,
					total_size,
				} => {
					if total_size > 0 {
						let percent = if total_size > 0 {
							downloaded_size * 100 / total_size
						} else {
							0
						};
						let start = start_time.timestamp_nanos();
						let fin = Utc::now().timestamp_nanos();
						let dur_ms = (fin - start) as f64 * NANO_TO_MILLIS;

						format!("Downloading {}(MB) chain state for fast sync: {}% at {:.1?}(kB/s), step 2/4",
						total_size / 1_000_000,
						percent,
						if dur_ms > 1.0f64 { downloaded_size as f64 / dur_ms as f64 } else { 0f64 },
						)
					} else {
						let start = start_time.timestamp_millis();
						let fin = Utc::now().timestamp_millis();
						let dur_secs = (fin - start) / 1000;

						format!("Downloading chain state for fast sync. Waiting remote peer to start: {}s, step 2/4",
										dur_secs,
										)
					}
				}
				SyncStatus::TxHashsetSetup => {
					"Preparing chain state for validation, step 3/4".to_string()
				}
				SyncStatus::TxHashsetValidation {
					kernels,
					kernel_total,
					rproofs,
					rproof_total,
				} => {
					// 10% of overall progress is attributed to kernel validation
					// 90% to range proofs (which are much longer)
					let mut percent = if kernel_total > 0 {
						kernels * 10 / kernel_total
					} else {
						0
					};
					percent += if rproof_total > 0 {
						rproofs * 90 / rproof_total
					} else {
						0
					};
					format!("Validating chain state: {}%, step 3/4", percent)
				}
				SyncStatus::TxHashsetSave => {
					"Finalizing chain state for fast sync, step 3/4".to_string()
				}
				SyncStatus::BodySync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading blocks: {}%, step 4/4", percent)
				}
			}
		};
		/*let basic_mining_config_status = {
			if stats.mining_stats.is_enabled {
				"Configured as mining node"
			} else {
				"Configured as validating node only (not mining)"
			}
		};
		let (basic_mining_status, basic_network_info) = {
			if stats.mining_stats.is_enabled {
				if stats.is_syncing {
					(
						"Mining Status: Paused while syncing".to_string(),
						" ".to_string(),
					)
				} else if stats.mining_stats.combined_gps == 0.0 {
					(
						"Mining Status: Starting miner and awaiting first solution...".to_string(),
						" ".to_string(),
					)
				} else {
					(
						format!(
							"Mining Status: Mining at height {} at {:.*} GPS",
							stats.mining_stats.block_height, 4, stats.mining_stats.combined_gps
						),
						format!(
							"Cuckoo {} - Network Difficulty {}",
							stats.mining_stats.edge_bits,
							stats.mining_stats.network_difficulty.to_string()
						),
					)
				}
			} else {
				(" ".to_string(), " ".to_string())
			}
		};*/
		c.call_on_id("basic_current_status", |t: &mut TextView| {
			t.set_content(basic_status);
		});
		c.call_on_id("connected_peers", |t: &mut TextView| {
			t.set_content(stats.peer_count.to_string());
		});
		c.call_on_id("chain_height", |t: &mut TextView| {
			t.set_content(stats.head.height.to_string());
		});
		c.call_on_id("basic_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.head.total_difficulty.to_string());
		});
		c.call_on_id("basic_header_chain_height", |t: &mut TextView| {
			t.set_content(stats.header_head.height.to_string());
		});
		c.call_on_id("basic_header_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.header_head.total_difficulty.to_string());
		});
		/*c.call_on_id("basic_mining_config_status", |t: &mut TextView| {
			t.set_content(basic_mining_config_status);
		});
		c.call_on_id("basic_mining_status", |t: &mut TextView| {
			t.set_content(basic_mining_status);
		});
		c.call_on_id("basic_network_info", |t: &mut TextView| {
			t.set_content(basic_network_info);
		});*/
	}
}
<commit_msg>show header and chain tip hashes on status page in tui (#1951)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Basic status view definition

use chrono::prelude::Utc;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;

use tui::constants::VIEW_BASIC_STATUS;
use tui::types::TUIStatusListener;

use servers::common::types::SyncStatus;
use servers::ServerStats;

const NANO_TO_MILLIS: f64 = 1.0 / 1_000_000.0;

pub struct TUIStatusView;

impl TUIStatusListener for TUIStatusView {
	/// Create basic status view
	fn create() -> Box<View> {
		let basic_status_view = BoxView::with_full_screen(
			LinearLayout::new(Orientation::Vertical)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Current Status: "))
						.child(TextView::new("Starting").with_id("basic_current_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Connected Peers: "))
						.child(TextView::new("0").with_id("connected_peers")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Tip Hash: "))
						.child(TextView::new("  ").with_id("basic_header_tip_hash")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Chain Height: "))
						.child(TextView::new("  ").with_id("basic_header_chain_height")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_header_total_difficulty")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Tip Hash: "))
						.child(TextView::new("  ").with_id("tip_hash")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Height: "))
						.child(TextView::new("  ").with_id("chain_height")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_total_difficulty")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_config_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_status")),
				).child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_network_info")),
				), //.child(logo_view)
		);
		Box::new(basic_status_view.with_id(VIEW_BASIC_STATUS))
	}

	/// update
	fn update(c: &mut Cursive, stats: &ServerStats) {
		//find and update here as needed
		let basic_status = {
			match stats.sync_status {
				SyncStatus::Initial => "Initializing".to_string(),
				SyncStatus::NoSync => "Running".to_string(),
				SyncStatus::AwaitingPeers(_) => "Waiting for peers".to_string(),
				SyncStatus::HeaderSync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading headers: {}%, step 1/4", percent)
				}
				SyncStatus::TxHashsetDownload {
					start_time,
					downloaded_size,
					total_size,
				} => {
					if total_size > 0 {
						let percent = if total_size > 0 {
							downloaded_size * 100 / total_size
						} else {
							0
						};
						let start = start_time.timestamp_nanos();
						let fin = Utc::now().timestamp_nanos();
						let dur_ms = (fin - start) as f64 * NANO_TO_MILLIS;

						format!("Downloading {}(MB) chain state for fast sync: {}% at {:.1?}(kB/s), step 2/4",
						total_size / 1_000_000,
						percent,
						if dur_ms > 1.0f64 { downloaded_size as f64 / dur_ms as f64 } else { 0f64 },
						)
					} else {
						let start = start_time.timestamp_millis();
						let fin = Utc::now().timestamp_millis();
						let dur_secs = (fin - start) / 1000;

						format!("Downloading chain state for fast sync. Waiting remote peer to start: {}s, step 2/4",
										dur_secs,
										)
					}
				}
				SyncStatus::TxHashsetSetup => {
					"Preparing chain state for validation, step 3/4".to_string()
				}
				SyncStatus::TxHashsetValidation {
					kernels,
					kernel_total,
					rproofs,
					rproof_total,
				} => {
					// 10% of overall progress is attributed to kernel validation
					// 90% to range proofs (which are much longer)
					let mut percent = if kernel_total > 0 {
						kernels * 10 / kernel_total
					} else {
						0
					};
					percent += if rproof_total > 0 {
						rproofs * 90 / rproof_total
					} else {
						0
					};
					format!("Validating chain state: {}%, step 3/4", percent)
				}
				SyncStatus::TxHashsetSave => {
					"Finalizing chain state for fast sync, step 3/4".to_string()
				}
				SyncStatus::BodySync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading blocks: {}%, step 4/4", percent)
				}
			}
		};
		/*let basic_mining_config_status = {
			if stats.mining_stats.is_enabled {
				"Configured as mining node"
			} else {
				"Configured as validating node only (not mining)"
			}
		};
		let (basic_mining_status, basic_network_info) = {
			if stats.mining_stats.is_enabled {
				if stats.is_syncing {
					(
						"Mining Status: Paused while syncing".to_string(),
						" ".to_string(),
					)
				} else if stats.mining_stats.combined_gps == 0.0 {
					(
						"Mining Status: Starting miner and awaiting first solution...".to_string(),
						" ".to_string(),
					)
				} else {
					(
						format!(
							"Mining Status: Mining at height {} at {:.*} GPS",
							stats.mining_stats.block_height, 4, stats.mining_stats.combined_gps
						),
						format!(
							"Cuckoo {} - Network Difficulty {}",
							stats.mining_stats.edge_bits,
							stats.mining_stats.network_difficulty.to_string()
						),
					)
				}
			} else {
				(" ".to_string(), " ".to_string())
			}
		};*/
		c.call_on_id("basic_current_status", |t: &mut TextView| {
			t.set_content(basic_status);
		});
		c.call_on_id("connected_peers", |t: &mut TextView| {
			t.set_content(stats.peer_count.to_string());
		});
		c.call_on_id("tip_hash", |t: &mut TextView| {
			t.set_content(stats.head.last_block_h.to_string());
		});
		c.call_on_id("chain_height", |t: &mut TextView| {
			t.set_content(stats.head.height.to_string());
		});
		c.call_on_id("basic_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.head.total_difficulty.to_string());
		});
		c.call_on_id("basic_header_tip_hash", |t: &mut TextView| {
			t.set_content(stats.header_head.last_block_h.to_string());
		});
		c.call_on_id("basic_header_chain_height", |t: &mut TextView| {
			t.set_content(stats.header_head.height.to_string());
		});
		c.call_on_id("basic_header_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.header_head.total_difficulty.to_string());
		});
		/*c.call_on_id("basic_mining_config_status", |t: &mut TextView| {
			t.set_content(basic_mining_config_status);
		});
		c.call_on_id("basic_mining_status", |t: &mut TextView| {
			t.set_content(basic_mining_status);
		});
		c.call_on_id("basic_network_info", |t: &mut TextView| {
			t.set_content(basic_network_info);
		});*/
	}
}
<|endoftext|>


<commit_before>#![feature(convert)]
#![feature(buf_stream)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;

use std::net::{TcpListener, TcpStream, Ipv4Addr};
use std::thread;
use std::io::{self,Read,Write,BufStream,BufRead};
use std::str::FromStr;
use std::fmt;
use std::collections::HashMap;

use capnp::serialize_packed;
use capnp::{MessageBuilder, MessageReader, MallocMessageBuilder, ReaderOptions};

use yak_client::yak_capnp::*;

type Key = Vec<u8>;
type Values = Vec<Vec<u8>>;
struct MemStore (HashMap<Key, Values>);

trait Store {
  fn truncate(&mut self);
  fn read(&self, key: &[u8]) -> Values;
  fn write(&mut self, key: &[u8], val: &[u8]);
}

impl MemStore {
  fn new() -> MemStore {
    MemStore(HashMap::new())
  }
}

impl Store for MemStore {
  fn truncate(&mut self) {
    let MemStore(ref mut map) = *self;
    map.clear();
  }

  fn read(&self, key: &[u8]) -> Values {
    let MemStore(ref map) = *self;
    map.get(key).map(|x| x.clone()).unwrap_or(vec![])
  }
  fn write(&mut self, key: &[u8], val: &[u8]) {
    let MemStore(ref mut map) = *self;
    let entry = map.entry(key.into()).or_insert(vec![]);
    entry.push(val.into())
  }
}

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error)
}

pub fn main() {
  env_logger::init().unwrap();

  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next : Option<String> = a.next();

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  for stream in listener.incoming() {
    let next = next.clone();
    thread::spawn(move || {
	let mut sock = &stream.unwrap();
	let peer = sock.peer_addr().unwrap();
	info!("Accept stream from {:?}", peer);
        let mut strm = BufStream::new(sock);
        process_requests(peer, strm).unwrap()
      });
  }
}

fn process_requests<Id: fmt::Display, S: Read + Write>(id: Id, mut strm: BufStream<S>) -> Result<(), ServerError> {
  let mut store = MemStore::new();
  loop {
    debug!("{}: Waiting for message", id);
    let len = try!(strm.fill_buf()).len();
    if len == 0 {
        debug!("{}: End of client stream", id);
        return Ok(())
    }
    let message_reader = try!(serialize_packed::read_message(&mut strm, ReaderOptions::new()));
    let msg = try!(message_reader.get_root::<client_request::Reader>());
    debug!("{}: Read message", id);

    let mut message = MallocMessageBuilder::new_default();
    {
      let mut response = message.init_root::<client_response::Builder>();
      match try!(msg.which()) {
        client_request::Truncate(v) => truncate(&id, &mut store, try!(v), response),
          client_request::Read(v) => read(&id, &mut store, try!(v), response),
          client_request::Write(v) => write(&id, &mut store, try!(v), response),
      };
    }

    try!(serialize_packed::write_message(&mut strm, &mut message));
    try!(strm.flush())
  }
}

fn truncate<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, req: truncate_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(req.get_space());
  info!("{}/{:?}: truncate", id, space);
  store.truncate();
  response.set_ok(());
  Ok(())
}

fn read<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, req: read_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(req.get_space());
  let key = try!(req.get_key()).into();
  let val = store.read(key);
  info!("{}/{:?}: read:{:?}: -> {:?}", id, space, key, val);

  let mut data = response.init_ok_data(val.len() as u32);
  for i in 0..val.len() {
    let mut datum = data.borrow().get(i as u32);
    datum.set_value(&val[i])
  }
  Ok(())
}

fn write<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, v: write_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(v.get_space());
  let key = try!(v.get_key()).into();
  let val = try!(v.get_value()).into();
  info!("{}/{:?}: write:{:?} -> {:?}", id, space, key, val);

  store.write(key, val);
  response.set_ok(());
  Ok(())
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}
<commit_msg>Wrap the memory store in an Arc/Mutex lock.<commit_after>#![feature(convert)]
#![feature(buf_stream)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;

use std::net::{TcpListener, TcpStream, Ipv4Addr};
use std::thread;
use std::io::{self,Read,Write,BufStream,BufRead};
use std::str::FromStr;
use std::fmt;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

use capnp::serialize_packed;
use capnp::{MessageBuilder, MessageReader, MallocMessageBuilder, ReaderOptions};

use yak_client::yak_capnp::*;

type Key = Vec<u8>;
type Values = Vec<Vec<u8>>;
struct MemStore (Arc<Mutex<HashMap<Key, Values>>>);

trait Store {
  fn truncate(&self);
  fn read(&self, key: &[u8]) -> Values;
  fn write(&self, key: &[u8], val: &[u8]);
}

impl MemStore {
  fn new() -> MemStore {
    MemStore(Arc::new(Mutex::new(HashMap::new())))
  }
}

impl Store for MemStore {
  fn truncate(&self) {
    let mut guard = self.0.lock().unwrap();
    let ref mut map = guard;
    map.clear();
  }

  fn read(&self, key: &[u8]) -> Values {
    let map = self.0.lock().unwrap();
    map.get(key).map(|x| x.clone()).unwrap_or(vec![])
  }
  fn write(&self, key: &[u8], val: &[u8]) {
    let mut map = self.0.lock().unwrap();
    let entry = map.entry(key.into()).or_insert(vec![]);
    entry.push(val.into())
  }
}

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error)
}

pub fn main() {
  env_logger::init().unwrap();

  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next : Option<String> = a.next();

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  for stream in listener.incoming() {
    let next = next.clone();
    thread::spawn(move || {
	let mut sock = &stream.unwrap();
	let peer = sock.peer_addr().unwrap();
	info!("Accept stream from {:?}", peer);
        let mut strm = BufStream::new(sock);
        process_requests(peer, strm).unwrap()
      });
  }
}

fn process_requests<Id: fmt::Display, S: Read + Write>(id: Id, mut strm: BufStream<S>) -> Result<(), ServerError> {
  let mut store = MemStore::new();
  loop {
    debug!("{}: Waiting for message", id);
    let len = try!(strm.fill_buf()).len();
    if len == 0 {
        debug!("{}: End of client stream", id);
        return Ok(())
    }
    let message_reader = try!(serialize_packed::read_message(&mut strm, ReaderOptions::new()));
    let msg = try!(message_reader.get_root::<client_request::Reader>());
    debug!("{}: Read message", id);

    let mut message = MallocMessageBuilder::new_default();
    {
      let mut response = message.init_root::<client_response::Builder>();
      match try!(msg.which()) {
        client_request::Truncate(v) => truncate(&id, &mut store, try!(v), response),
          client_request::Read(v) => read(&id, &mut store, try!(v), response),
          client_request::Write(v) => write(&id, &mut store, try!(v), response),
      };
    }

    try!(serialize_packed::write_message(&mut strm, &mut message));
    try!(strm.flush())
  }
}

fn truncate<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, req: truncate_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(req.get_space());
  info!("{}/{:?}: truncate", id, space);
  store.truncate();
  response.set_ok(());
  Ok(())
}

fn read<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, req: read_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(req.get_space());
  let key = try!(req.get_key()).into();
  let val = store.read(key);
  info!("{}/{:?}: read:{:?}: -> {:?}", id, space, key, val);

  let mut data = response.init_ok_data(val.len() as u32);
  for i in 0..val.len() {
    let mut datum = data.borrow().get(i as u32);
    datum.set_value(&val[i])
  }
  Ok(())
}

fn write<Id: fmt::Display, S: Store>(id: &Id, store: &mut S, v: write_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let space = try!(v.get_space());
  let key = try!(v.get_key()).into();
  let val = try!(v.get_value()).into();
  info!("{}/{:?}: write:{:?} -> {:?}", id, space, key, val);

  store.write(key, val);
  response.set_ok(());
  Ok(())
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::Cow;
use std::str::FromStr;

/// The type of identifier to be renamed.
#[derive(Debug, Clone, Copy)]
pub enum IdentifierType<'a> {
    StructMember,
    EnumVariant { prefix: &'a str },
    FunctionArg,
    Type,
    Enum,
}

impl<'a> IdentifierType<'a> {
    fn to_str(&'a self) -> &'static str {
        match *self {
            IdentifierType::StructMember => "m",
            IdentifierType::EnumVariant { .. } => "",
            IdentifierType::FunctionArg => "a",
            IdentifierType::Type => "",
            IdentifierType::Enum => "",
        }
    }
}

/// A rule to apply to an identifier when generating bindings.
#[derive(Debug, Clone, Copy)]
pub enum RenameRule {
    /// Do not apply any renaming. The default.
    None,
    /// Converts the identifier to PascalCase and adds a context dependent prefix
    GeckoCase,
    /// Converts the identifier to lower case.
    LowerCase,
    /// Converts the identifier to upper case.
    UpperCase,
    /// Converts the identifier to PascalCase.
    PascalCase,
    /// Converts the identifier to camelCase.
    CamelCase,
    /// Converts the identifier to snake_case.
    SnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE.
    ScreamingSnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
    /// with the enum name.
    QualifiedScreamingSnakeCase,
}

impl RenameRule {
    pub(crate) fn not_none(self) -> Option<Self> {
        match self {
            RenameRule::None => None,
            other => Some(other),
        }
    }

    /// Applies the rename rule to a string
    pub fn apply<'a>(self, text: &'a str, context: IdentifierType) -> Cow<'a, str> {
        use heck::*;

        if text.is_empty() {
            return Cow::Borrowed(text);
        }

        Cow::Owned(match self {
            RenameRule::None => return Cow::Borrowed(text),
            RenameRule::GeckoCase => context.to_str().to_owned() + &text.to_camel_case(),
            RenameRule::LowerCase => text.to_lowercase(),
            RenameRule::UpperCase => text.to_uppercase(),
            RenameRule::PascalCase => text.to_camel_case(),
            RenameRule::CamelCase => text.to_mixed_case(),
            RenameRule::SnakeCase => text.to_snake_case(),
            RenameRule::ScreamingSnakeCase => text.to_shouty_snake_case(),
            RenameRule::QualifiedScreamingSnakeCase => {
                let mut result = String::new();

                if let IdentifierType::EnumVariant { prefix } = context {
                    result.push_str(
                        &RenameRule::ScreamingSnakeCase.apply(prefix, IdentifierType::Enum),
                    );
                    result.push('_');
                }

                result.push_str(&RenameRule::ScreamingSnakeCase.apply(&text, context));
                result
            }
        })
    }
}

impl Default for RenameRule {
    fn default() -> RenameRule {
        RenameRule::None
    }
}

impl FromStr for RenameRule {
    type Err = String;

    fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
        match s {
            "none" => Ok(RenameRule::None),
            "None" => Ok(RenameRule::None),

            "mGeckoCase" => Ok(RenameRule::GeckoCase),
            "GeckoCase" => Ok(RenameRule::GeckoCase),
            "gecko_case" => Ok(RenameRule::GeckoCase),

            "lowercase" => Ok(RenameRule::LowerCase),
            "LowerCase" => Ok(RenameRule::LowerCase),
            "lower_case" => Ok(RenameRule::LowerCase),

            "UPPERCASE" => Ok(RenameRule::UpperCase),
            "UpperCase" => Ok(RenameRule::UpperCase),
            "upper_case" => Ok(RenameRule::UpperCase),

            "PascalCase" => Ok(RenameRule::PascalCase),
            "pascal_case" => Ok(RenameRule::PascalCase),

            "camelCase" => Ok(RenameRule::CamelCase),
            "CamelCase" => Ok(RenameRule::CamelCase),
            "camel_case" => Ok(RenameRule::CamelCase),

            "snake_case" => Ok(RenameRule::SnakeCase),
            "SnakeCase" => Ok(RenameRule::SnakeCase),

            "SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
            "ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
            "screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),

            "QUALIFIED_SCREAMING_SNAKE_CASE" => Ok(RenameRule::QualifiedScreamingSnakeCase),
            "QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase),
            "qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase),

            _ => Err(format!("Unrecognized RenameRule: '{}'.", s)),
        }
    }
}

deserialize_enum_str!(RenameRule);
<commit_msg>Fix new clippy lint clippy::wrong-self-convention<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::Cow;
use std::str::FromStr;

/// The type of identifier to be renamed.
#[derive(Debug, Clone, Copy)]
pub enum IdentifierType<'a> {
    StructMember,
    EnumVariant { prefix: &'a str },
    FunctionArg,
    Type,
    Enum,
}

impl<'a> IdentifierType<'a> {
    fn to_str(self) -> &'static str {
        match self {
            IdentifierType::StructMember => "m",
            IdentifierType::EnumVariant { .. } => "",
            IdentifierType::FunctionArg => "a",
            IdentifierType::Type => "",
            IdentifierType::Enum => "",
        }
    }
}

/// A rule to apply to an identifier when generating bindings.
#[derive(Debug, Clone, Copy)]
pub enum RenameRule {
    /// Do not apply any renaming. The default.
    None,
    /// Converts the identifier to PascalCase and adds a context dependent prefix
    GeckoCase,
    /// Converts the identifier to lower case.
    LowerCase,
    /// Converts the identifier to upper case.
    UpperCase,
    /// Converts the identifier to PascalCase.
    PascalCase,
    /// Converts the identifier to camelCase.
    CamelCase,
    /// Converts the identifier to snake_case.
    SnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE.
    ScreamingSnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
    /// with the enum name.
    QualifiedScreamingSnakeCase,
}

impl RenameRule {
    pub(crate) fn not_none(self) -> Option<Self> {
        match self {
            RenameRule::None => None,
            other => Some(other),
        }
    }

    /// Applies the rename rule to a string
    pub fn apply<'a>(self, text: &'a str, context: IdentifierType) -> Cow<'a, str> {
        use heck::*;

        if text.is_empty() {
            return Cow::Borrowed(text);
        }

        Cow::Owned(match self {
            RenameRule::None => return Cow::Borrowed(text),
            RenameRule::GeckoCase => context.to_str().to_owned() + &text.to_camel_case(),
            RenameRule::LowerCase => text.to_lowercase(),
            RenameRule::UpperCase => text.to_uppercase(),
            RenameRule::PascalCase => text.to_camel_case(),
            RenameRule::CamelCase => text.to_mixed_case(),
            RenameRule::SnakeCase => text.to_snake_case(),
            RenameRule::ScreamingSnakeCase => text.to_shouty_snake_case(),
            RenameRule::QualifiedScreamingSnakeCase => {
                let mut result = String::new();

                if let IdentifierType::EnumVariant { prefix } = context {
                    result.push_str(
                        &RenameRule::ScreamingSnakeCase.apply(prefix, IdentifierType::Enum),
                    );
                    result.push('_');
                }

                result.push_str(&RenameRule::ScreamingSnakeCase.apply(&text, context));
                result
            }
        })
    }
}

impl Default for RenameRule {
    fn default() -> RenameRule {
        RenameRule::None
    }
}

impl FromStr for RenameRule {
    type Err = String;

    fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
        match s {
            "none" => Ok(RenameRule::None),
            "None" => Ok(RenameRule::None),

            "mGeckoCase" => Ok(RenameRule::GeckoCase),
            "GeckoCase" => Ok(RenameRule::GeckoCase),
            "gecko_case" => Ok(RenameRule::GeckoCase),

            "lowercase" => Ok(RenameRule::LowerCase),
            "LowerCase" => Ok(RenameRule::LowerCase),
            "lower_case" => Ok(RenameRule::LowerCase),

            "UPPERCASE" => Ok(RenameRule::UpperCase),
            "UpperCase" => Ok(RenameRule::UpperCase),
            "upper_case" => Ok(RenameRule::UpperCase),

            "PascalCase" => Ok(RenameRule::PascalCase),
            "pascal_case" => Ok(RenameRule::PascalCase),

            "camelCase" => Ok(RenameRule::CamelCase),
            "CamelCase" => Ok(RenameRule::CamelCase),
            "camel_case" => Ok(RenameRule::CamelCase),

            "snake_case" => Ok(RenameRule::SnakeCase),
            "SnakeCase" => Ok(RenameRule::SnakeCase),

            "SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
            "ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
            "screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),

            "QUALIFIED_SCREAMING_SNAKE_CASE" => Ok(RenameRule::QualifiedScreamingSnakeCase),
            "QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase),
            "qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase),

            _ => Err(format!("Unrecognized RenameRule: '{}'.", s)),
        }
    }
}

deserialize_enum_str!(RenameRule);
<|endoftext|>


<commit_before>//! Default runtime
//!
//! By default, hyper includes the [tokio](https://tokio.rs) runtime. To ease
//! using it, several types are re-exported here.
//!
//! The inclusion of a default runtime can be disabled by turning off hyper's
//! `runtime` Cargo feature.

pub use futures::{Future, Stream};
pub use futures::future::{lazy, poll_fn};
pub use tokio::{run, spawn};
<commit_msg>refactor(rt): replace spawn and run with wrapped functions<commit_after>//! Default runtime
//!
//! By default, hyper includes the [tokio](https://tokio.rs) runtime. To ease
//! using it, several types are re-exported here.
//!
//! The inclusion of a default runtime can be disabled by turning off hyper's
//! `runtime` Cargo feature.

pub use futures::{Future, Stream};
pub use futures::future::{lazy, poll_fn};
use tokio;

use self::inner::Spawn;

/// Spawns a future on the default executor.
///
/// # Panics
///
/// This function will panic if the default executor is not set.
///
/// # Note
///
/// The `Spawn` return type is not currently meant for anything other than
/// to reserve adding new trait implementations to it later. It can be
/// ignored for now.
pub fn spawn<F>(f: F) -> Spawn
where
    F: Future<Item=(), Error=()> + Send + 'static,
{
    tokio::spawn(f);
    Spawn {
        _inner: (),
    }
}

/// Start the Tokio runtime using the supplied future to bootstrap execution.
///
/// # Example
///
/// See the [server documentation](::server) for an example of its usage.
pub fn run<F>(f: F)
where
    F: Future<Item=(), Error=()> + Send + 'static
{
    tokio::run(f);
}

// Make the `Spawn` type an unnameable, so we can add
// methods or trait impls to it later without a breaking change.
mod inner {
    #[allow(missing_debug_implementations)]
    pub struct Spawn {
        pub(super) _inner: (),
    }
}
<|endoftext|>


<commit_before>/// A rectangle defined by its top-left corner and dimensions
#[derive(Copy, Clone, Debug)]
pub struct Rectangle {
    /// horizontal position of the top-left corner of the rectangle, in surface coordinates
    pub x: i32,
    /// vertical position of the top-left corner of the rectangle, in surface coordinates
    pub y: i32,
    /// width of the rectangle
    pub width: i32,
    /// height of the rectangle
    pub height: i32,
}

impl Rectangle {
    /// Checks whether given point is inside a rectangle
    pub fn contains(&self, point: (i32, i32)) -> bool {
        let (x, y) = point;
        (x >= self.x) && (x < self.x + self.width) && (y >= self.y) && (y < self.y + self.height)
    }
}
<commit_msg>rectangle: derive Default<commit_after>/// A rectangle defined by its top-left corner and dimensions
#[derive(Copy, Clone, Debug, Default)]
pub struct Rectangle {
    /// horizontal position of the top-left corner of the rectangle, in surface coordinates
    pub x: i32,
    /// vertical position of the top-left corner of the rectangle, in surface coordinates
    pub y: i32,
    /// width of the rectangle
    pub width: i32,
    /// height of the rectangle
    pub height: i32,
}

impl Rectangle {
    /// Checks whether given point is inside a rectangle
    pub fn contains(&self, point: (i32, i32)) -> bool {
        let (x, y) = point;
        (x >= self.x) && (x < self.x + self.width) && (y >= self.y) && (y < self.y + self.height)
    }
}
<|endoftext|>


<commit_before>#![feature(step_by)]
#![feature(inclusive_range_syntax)]

extern crate sdl2;
extern crate sdl2_gfx;

use sdl2_gfx::primitives::DrawRenderer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use std::time::Duration;

mod primitives;
mod circle;

use circle::*;
use primitives::*;

const WIDTH: u32 = 1280;
const HEIGHT: u32 = 720;

fn main() {
    // Initialize SDL2
    let sdl_context   = sdl2::init().unwrap();
    let video_context = sdl_context.video().unwrap();

    // Create window
    let window = video_context.window("Graphics Task 1", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    // Get renderer binded to window
    let mut renderer = window.renderer().build().unwrap();

    // Create FPS manager to precisely control inter-frames delays
    let mut fps_manager = sdl2_gfx::framerate::FPSManager::new();
    fps_manager.set_framerate(10).unwrap();

    // Set draw color and clear the screen
    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();
    renderer.present();

    // Get event pump
    let mut events = sdl_context.event_pump().unwrap();

    // Set first circle center and radius
    let startx1 = (WIDTH / 100 * 27) as i16;
    let startx2 = (WIDTH / 100 * 80) as i16;
    let starty  = (HEIGHT / 2)       as i16;

    // Set result text coordinates
    let textx = (WIDTH - 200) as i16;
    let texty = 10;
    // Create circles
    let mut bresenham_circles = Vec::with_capacity(80);
    let mut builtin_circles   = Vec::with_capacity(80);

    for r in (4..320).step_by(4) {
        bresenham_circles.push(
            Circle::new(
                Point2D::new(startx1, starty),
                r,
                Color::RGB(0, 255, 0)
            )
        );

        builtin_circles.push(
            Circle::new(
                Point2D::new(startx2, starty),
                r,
                Color::RGB(255, 0, 0)
            )
        );
    }

    // Start main loop
    'main:
    loop {
        // If exit event passed, break the loop
        for event in events.poll_iter() {
            match event {
                Event::Quit {..} => break 'main,
                _ => ()
            }
        }

        // Clear render buffer
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();

        // Plot circles
        let builtin_duration = stopwatch(|| {
            for c in &builtin_circles {
                c.draw_builtin_circle(&renderer);
            }
        });

        let bresenham_duration = stopwatch(|| {
            for c in &bresenham_circles {
                c.draw(&renderer);
            }
        });

        let faster = if bresenham_duration.subsec_nanos() > builtin_duration.subsec_nanos() {
            "BUILTIN"
        } else {
            "MY IMPLEMENTATION"
        };

        // Draw results
        renderer.string(
            textx,
            texty,
            &format!("Bresenham: {} ms", bresenham_duration.subsec_nanos() / 1000_000),
            Color::RGB(255, 255, 255)
        ).unwrap();

        renderer.string(
            textx,
            texty + 15,
            &format!("Builtin:   {} ms", builtin_duration.subsec_nanos() / 1000_000),
            Color::RGB(255, 255, 255)
        ).unwrap();

        renderer.string(
            textx,
            texty + 30,
            &format!("Faster: {}", faster),
            Color::RGB(255, 255, 255)
        ).unwrap();

        // Present render buffer
        renderer.present();

        // Sleep until the next frame should be rendered
        fps_manager.delay();
    }
}

fn stopwatch<F>(mut closure: F) -> Duration
    where F: FnMut() {
    use std::time::SystemTime;
    let before_time = SystemTime::now();
    closure();
    let after_time  = SystemTime::now();
    after_time.duration_since(before_time).unwrap()
}
<commit_msg>Removed unnecessary #![feature]<commit_after>#![feature(step_by)]

extern crate sdl2;
extern crate sdl2_gfx;

use sdl2_gfx::primitives::DrawRenderer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use std::time::Duration;

mod primitives;
mod circle;

use circle::*;
use primitives::*;

const WIDTH: u32 = 1280;
const HEIGHT: u32 = 720;

fn main() {
    // Initialize SDL2
    let sdl_context   = sdl2::init().unwrap();
    let video_context = sdl_context.video().unwrap();

    // Create window
    let window = video_context.window("Graphics Task 1", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    // Get renderer binded to window
    let mut renderer = window.renderer().build().unwrap();

    // Create FPS manager to precisely control inter-frames delays
    let mut fps_manager = sdl2_gfx::framerate::FPSManager::new();
    fps_manager.set_framerate(10).unwrap();

    // Set draw color and clear the screen
    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();
    renderer.present();

    // Get event pump
    let mut events = sdl_context.event_pump().unwrap();

    // Set first circle center and radius
    let startx1 = (WIDTH / 100 * 27) as i16;
    let startx2 = (WIDTH / 100 * 80) as i16;
    let starty  = (HEIGHT / 2)       as i16;

    // Set result text coordinates
    let textx = (WIDTH - 200) as i16;
    let texty = 10;
    // Create circles
    let mut bresenham_circles = Vec::with_capacity(80);
    let mut builtin_circles   = Vec::with_capacity(80);

    for r in (4..320).step_by(4) {
        bresenham_circles.push(
            Circle::new(
                Point2D::new(startx1, starty),
                r,
                Color::RGB(0, 255, 0)
            )
        );

        builtin_circles.push(
            Circle::new(
                Point2D::new(startx2, starty),
                r,
                Color::RGB(255, 0, 0)
            )
        );
    }

    // Start main loop
    'main:
    loop {
        // If exit event passed, break the loop
        for event in events.poll_iter() {
            match event {
                Event::Quit {..} => break 'main,
                _ => ()
            }
        }

        // Clear render buffer
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();

        // Plot circles
        let builtin_duration = stopwatch(|| {
            for c in &builtin_circles {
                c.draw_builtin_circle(&renderer);
            }
        });

        let bresenham_duration = stopwatch(|| {
            for c in &bresenham_circles {
                c.draw(&renderer);
            }
        });

        let faster = if bresenham_duration.subsec_nanos() > builtin_duration.subsec_nanos() {
            "BUILTIN"
        } else {
            "MY IMPLEMENTATION"
        };

        // Draw results
        renderer.string(
            textx,
            texty,
            &format!("Bresenham: {} ms", bresenham_duration.subsec_nanos() / 1000_000),
            Color::RGB(255, 255, 255)
        ).unwrap();

        renderer.string(
            textx,
            texty + 15,
            &format!("Builtin:   {} ms", builtin_duration.subsec_nanos() / 1000_000),
            Color::RGB(255, 255, 255)
        ).unwrap();

        renderer.string(
            textx,
            texty + 30,
            &format!("Faster: {}", faster),
            Color::RGB(255, 255, 255)
        ).unwrap();

        // Present render buffer
        renderer.present();

        // Sleep until the next frame should be rendered
        fps_manager.delay();
    }
}

fn stopwatch<F>(mut closure: F) -> Duration
    where F: FnMut() {
    use std::time::SystemTime;
    let before_time = SystemTime::now();
    closure();
    let after_time  = SystemTime::now();
    after_time.duration_since(before_time).unwrap()
}
<|endoftext|>


<commit_before>//! Support Vector Machine Module
//!
//! Contains implementation of Support Vector Machine
//! using the [Pegasos training algorithm](http://ttic.uchicago.edu/~nati/Publications/PegasosMPB.pdf).
//!
//! The SVM model currently only support binary classification.
//! The model inputs should be a matrix and the training targets are
//! in the form of a vector of `-1`s and `1`s.
//!
//! # Examples
//!
//! ```
//! use rusty_machine::learning::svm::SVM;
//! use rusty_machine::learning::SupModel;
//!
//! use rusty_machine::linalg::matrix::Matrix;
//! use rusty_machine::linalg::vector::Vector;
//!
//! let inputs = Matrix::new(4,1,vec![1.0,3.0,5.0,7.0]);
//! let targets = Vector::new(vec![-1.,-1.,1.,1.]);
//!
//! let mut svm_mod = SVM::default();
//!
//! // Train the model
//! svm_mod.train(&inputs, &targets);
//!
//! // Now we'll predict a new point
//! let new_point = Matrix::new(1,1,vec![10.]);
//! let output = svm_mod.predict(&new_point);
//!
//! // Hopefully we classified our new point correctly!
//! assert!(output[0] == 1f64, "Our classifier isn't very good!");
//! ```

use linalg::matrix::Matrix;
use linalg::vector::Vector;

use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;

use rand;
use rand::Rng;

/// Support Vector Machine
pub struct SVM<K: Kernel> {
    ker: K,
    alpha: Option<Vector<f64>>,
    train_inputs: Option<Matrix<f64>>,
    train_targets: Option<Vector<f64>>,
    lambda: f64,
}

impl Default for SVM<SquaredExp> {
    fn default() -> SVM<SquaredExp> {
        SVM {
            ker: SquaredExp::default(),
            alpha: None,
            train_inputs: None,
            train_targets: None,
            lambda: 0.3f64,
        }
    }
}

impl<K: Kernel> SVM<K> {
	/// Constructs an untrained SVM with specified
	/// kernel and lambda which determins the hardness
	/// of the margin.
	///
	/// # Examples
	///
	/// ```
	/// use rusty_machine::learning::svm::SVM;
	/// use rusty_machine::learning::toolkit::kernel::SquaredExp;
	///
	/// let _ = SVM::new(SquaredExp::default(), 0.3);
	/// ```
	pub fn new(ker: K, lambda: f64) -> SVM<K> {
		SVM {
			ker: ker,
			alpha: None,
			train_inputs: None,
			train_targets: None,
			lambda: lambda,
		}
	}
}

impl<K: Kernel> SVM<K> {

    /// Construct a kernel matrix
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let cols = m1.cols();

        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data()[i * cols..(i + 1) * cols],
                                              &m2.data()[j * cols..(j + 1) * cols]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<K: Kernel> SupModel<Matrix<f64>, Vector<f64>> for SVM<K> {
    fn predict(&self, inputs: &Matrix<f64>) -> Vector<f64> {
    	let ones = Matrix::<f64>::ones(inputs.rows(), 1);
        let full_inputs = ones.hcat(inputs);

        if let (&Some(ref alpha),
                &Some(ref train_inputs),
                &Some(ref train_targets)) = (&self.alpha, &self.train_inputs, &self.train_targets) {
            let ker_mat = self.ker_mat(&full_inputs, train_inputs);
            let weight_vec = alpha.elemul(train_targets) / self.lambda;

            let plane_dist = ker_mat * weight_vec;

            plane_dist.apply(&|d| d.signum())
        }
        else {
        	panic!("Model has not been trained.");
        }
    }

    fn train(&mut self, inputs: &Matrix<f64>, targets: &Vector<f64>) {
        let n = inputs.rows();

        let mut rng = rand::thread_rng();

        let mut alpha = vec![0f64; n];

        let ones = Matrix::<f64>::ones(inputs.rows(), 1);
        let full_inputs = ones.hcat(inputs);
        let m = full_inputs.cols();

        // TODO: Make T a variable instead of 1000 constant.
        for t in 0..1000 {
            let i = rng.gen_range(0, n);
            let mut sum = 0f64;
            for j in 0..n {
                sum += alpha[j] * targets[j] *
                       self.ker.kernel(&full_inputs.data()[i * m..(i + 1) * m],
                                       &full_inputs.data()[j * m..(j + 1) * m]);
            }
            sum *= targets[i] / (self.lambda * (t as f64));

            if sum < 1f64 {
                alpha[i] = alpha[i] + 1f64;
            }
        }

        self.alpha = Some(Vector::new(alpha) / 1000f64);
        self.train_inputs = Some(full_inputs);
        self.train_targets = Some(targets.clone());
    }
}
<commit_msg>Adding optimization iterations to SVM<commit_after>//! Support Vector Machine Module
//!
//! Contains implementation of Support Vector Machine
//! using the [Pegasos training algorithm](http://ttic.uchicago.edu/~nati/Publications/PegasosMPB.pdf).
//!
//! The SVM models currently only support binary classification.
//! The model inputs should be a matrix and the training targets are
//! in the form of a vector of `-1`s and `1`s.
//!
//! # Examples
//!
//! ```
//! use rusty_machine::learning::svm::SVM;
//! use rusty_machine::learning::SupModel;
//!
//! use rusty_machine::linalg::matrix::Matrix;
//! use rusty_machine::linalg::vector::Vector;
//!
//! let inputs = Matrix::new(4,1,vec![1.0,3.0,5.0,7.0]);
//! let targets = Vector::new(vec![-1.,-1.,1.,1.]);
//!
//! let mut svm_mod = SVM::default();
//!
//! // Train the model
//! svm_mod.train(&inputs, &targets);
//!
//! // Now we'll predict a new point
//! let new_point = Matrix::new(1,1,vec![10.]);
//! let output = svm_mod.predict(&new_point);
//!
//! // Hopefully we classified our new point correctly!
//! assert!(output[0] == 1f64, "Our classifier isn't very good!");
//! ```

use linalg::matrix::Matrix;
use linalg::vector::Vector;

use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;

use rand;
use rand::Rng;

/// Support Vector Machine
pub struct SVM<K: Kernel> {
    ker: K,
    alpha: Option<Vector<f64>>,
    train_inputs: Option<Matrix<f64>>,
    train_targets: Option<Vector<f64>>,
    lambda: f64,
    /// Number of iterations for training. Defaults to 100.
    pub optim_iters: usize,
}

impl Default for SVM<SquaredExp> {
    fn default() -> SVM<SquaredExp> {
        SVM {
            ker: SquaredExp::default(),
            alpha: None,
            train_inputs: None,
            train_targets: None,
            lambda: 0.3f64,
            optim_iters: 100,
        }
    }
}

impl<K: Kernel> SVM<K> {
	/// Constructs an untrained SVM with specified
	/// kernel and lambda which determins the hardness
	/// of the margin.
	///
	/// # Examples
	///
	/// ```
	/// use rusty_machine::learning::svm::SVM;
	/// use rusty_machine::learning::toolkit::kernel::SquaredExp;
	///
	/// let _ = SVM::new(SquaredExp::default(), 0.3);
	/// ```
	pub fn new(ker: K, lambda: f64) -> SVM<K> {
		SVM {
			ker: ker,
			alpha: None,
			train_inputs: None,
			train_targets: None,
			lambda: lambda,
			optim_iters: 100,
		}
	}
}

impl<K: Kernel> SVM<K> {

    /// Construct a kernel matrix
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let cols = m1.cols();

        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data()[i * cols..(i + 1) * cols],
                                              &m2.data()[j * cols..(j + 1) * cols]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<K: Kernel> SupModel<Matrix<f64>, Vector<f64>> for SVM<K> {
    fn predict(&self, inputs: &Matrix<f64>) -> Vector<f64> {
    	let ones = Matrix::<f64>::ones(inputs.rows(), 1);
        let full_inputs = ones.hcat(inputs);

        if let (&Some(ref alpha),
                &Some(ref train_inputs),
                &Some(ref train_targets)) = (&self.alpha, &self.train_inputs, &self.train_targets) {
            let ker_mat = self.ker_mat(&full_inputs, train_inputs);
            let weight_vec = alpha.elemul(train_targets) / self.lambda;

            let plane_dist = ker_mat * weight_vec;

            plane_dist.apply(&|d| d.signum())
        }
        else {
        	panic!("Model has not been trained.");
        }
    }

    fn train(&mut self, inputs: &Matrix<f64>, targets: &Vector<f64>) {
        let n = inputs.rows();

        let mut rng = rand::thread_rng();

        let mut alpha = vec![0f64; n];

        let ones = Matrix::<f64>::ones(inputs.rows(), 1);
        let full_inputs = ones.hcat(inputs);
        let m = full_inputs.cols();

        for t in 0..self.optim_iters {
            let i = rng.gen_range(0, n);
            let mut sum = 0f64;
            for j in 0..n {
                sum += alpha[j] * targets[j] *
                       self.ker.kernel(&full_inputs.data()[i * m..(i + 1) * m],
                                       &full_inputs.data()[j * m..(j + 1) * m]);
            }
            sum *= targets[i] / (self.lambda * (t as f64));

            if sum < 1f64 {
                alpha[i] = alpha[i] + 1f64;
            }
        }

        self.alpha = Some(Vector::new(alpha) / (self.optim_iters as f64));
        self.train_inputs = Some(full_inputs);
        self.train_targets = Some(targets.clone());
    }
}
<|endoftext|>


<commit_before>extern crate libc;

pub mod anoncreds;
pub mod crypto;
pub mod sovrin;
pub mod wallet;

use self::libc::{c_char, c_uchar};

#[no_mangle]
pub extern fn init_client(host_and_port: *const c_char) -> i32 {
    unimplemented!();
}

#[no_mangle]
pub extern fn release_client(client_id: i32) -> i32 {
    unimplemented!();
}

#[no_mangle]
pub extern fn free_str(c_ptr: *mut c_char) {
    unimplemented!();
}<commit_msg>Create simple storage for active clients in C API.<commit_after>extern crate libc;

pub mod anoncreds;
pub mod crypto;
pub mod sovrin;
pub mod wallet;

use std::collections::HashMap;
use std::mem;
use std::sync::{Arc, Mutex, Once, ONCE_INIT};

use self::libc::{c_char, c_uchar};
use super::SovrinClient;

#[derive(Clone)]
pub struct SingletonClients {
    inner: Arc<Mutex<(HashMap<i32, SovrinClient>, i32)>>
}

pub fn get_active_clients() -> SingletonClients {
    static mut SINGLETON: *const SingletonClients = 0 as *const SingletonClients;
    static ONCE: Once = ONCE_INIT;

    unsafe {
        ONCE.call_once(|| {
            let singleton = SingletonClients {
                inner: Arc::new(Mutex::new((HashMap::new(), 1)))
            };
            SINGLETON = mem::transmute(Box::new(singleton));
        });
        (*SINGLETON).clone()
    }
}

#[no_mangle]
pub extern fn init_client(host_and_port: *const c_char) -> i32 {
    unimplemented!();
}

#[no_mangle]
pub extern fn release_client(client_id: i32) -> i32 {
    unimplemented!();
}

#[no_mangle]
pub extern fn free_str(c_ptr: *mut c_char) {
    unimplemented!();
}<|endoftext|>