<commit_before>use token::{Token, TokenType};
use ast::*;
use pos::Pos;
use error::Error;
use types::Type;

pub struct Parser {
    tokens: Vec<Token>,
    index: usize,
    curr_id: u64,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            tokens: tokens,
            index: 0,
            curr_id: 0,
        }
    }

    fn next_id(&mut self) -> u64 {
        let x = self.curr_id;
        self.curr_id += 1;
        x
    }

    fn peek(&self, t: TokenType) -> bool {
        let token = &self.tokens[self.index];
        token.typ == t
    }

    fn curr_token(&self) -> Token {
        self.tokens[self.index].clone()
    }

    fn token_pos(&self) -> Pos {
        self.tokens[self.index].pos
    }

    fn eat(&mut self, t: TokenType) -> Result<(), Error> {
        let b = self.peek(t);
        if b {
            self.index += 1;
            Ok(())
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
        }
    }

    fn eat_lexeme(&mut self, t: TokenType) -> Result<String, Error> {
        let token = &self.tokens[self.index];
        if token.typ == t {
            match token.lexeme {
                Some(ref lexeme) => {
                    self.index += 1;
                    Ok(lexeme.clone())
                }
                None => Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
            }
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
        }
    }

    fn eat_type(&mut self) -> Result<Type, Error> {
        if self.peek(TokenType::TypeInt) {
            self.index += 1;
            Ok(Type::Int)
        } else if self.peek(TokenType::TypeFloat) {
            self.index += 1;
            Ok(Type::Float)
        } else if self.peek(TokenType::TypeString) {
            self.index += 1;
            Ok(Type::String)
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![TokenType::TypeInt, TokenType::TypeFloat]))
        }
    }

    pub fn parse_program(&mut self) -> Result<Program, Error> {
        let decls = try!(self.parse_decls());
        let stmts = try!(self.parse_stmts());
        try!(self.eat(TokenType::Eof));

        Ok(Program {
            decls: decls,
            stmts: stmts,
        })
    }

    fn parse_decls(&mut self) -> Result<Vec<Decl>, Error> {
        let mut decls: Vec<Decl> = Vec::new();
        while self.peek(TokenType::Var) {
            let decl = try!(self.parse_decl());
            decls.push(decl);
        }
        Ok(decls)
    }

    fn parse_decl(&mut self) -> Result<Decl, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Var));
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Colon));
        let ty = try!(self.eat_type());
        try!(self.eat(TokenType::Semicolon));
        Ok(Decl { pos: pos, id: id, ty: ty })
    }

    fn parse_stmts(&mut self) -> Result<Vec<Stmt>, Error> {
        let mut stmts: Vec<Stmt> = Vec::new();
        while self.is_stmt_start() {
            let stmt = try!(self.parse_stmt());
            stmts.push(stmt);
        }
        Ok(stmts)
    }

    fn parse_stmt(&mut self) -> Result<Stmt, Error> {
        if self.peek(TokenType::Read) {
            self.parse_read()
        } else if self.peek(TokenType::Print) {
            self.parse_print()
        } else if self.peek(TokenType::Id) {
            self.parse_assign()
        } else if self.peek(TokenType::If) {
            self.parse_if()
        } else if self.peek(TokenType::While) {
            self.parse_while()
        } else {
            Err(Error::UnexpectedToken(
                self.curr_token(),
                vec![TokenType::Read, TokenType::Print,
                     TokenType::Id, TokenType::If, TokenType::While]))
        }
    }

    fn parse_read(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Read));
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Read(StmtRead { pos: pos, id: id }))
    }

    fn parse_print(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Print));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Print(StmtPrint { pos: pos, expr: e }))
    }

    fn parse_assign(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Equal));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Assign(StmtAssign { pos: pos, id: id, expr: e }))
    }

    fn parse_if(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::If));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Then));
        let then_stmts = try!(self.parse_stmts());

        let else_stmts =
            if self.peek(TokenType::Else) {
                try!(self.eat(TokenType::Else));
                try!(self.parse_stmts())
            } else {
                vec![]
            };

        try!(self.eat(TokenType::EndIf));
        Ok(Stmt::If(StmtIf {
            pos: pos,
            expr: e,
            then_stmts: then_stmts,
            else_stmts: else_stmts,
        }))
    }

    fn parse_while(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::While));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Do));
        let stmts = try!(self.parse_stmts());
        try!(self.eat(TokenType::Done));
        Ok(Stmt::While(StmtWhile {
            pos: pos,
            expr: e,
            stmts: stmts,
        }))
    }

    fn parse_expr(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let mut term = try!(self.parse_term());
        while self.next_is_add() {
            let (tok, op) =
                if self.peek(TokenType::Plus) {
                    (TokenType::Plus, Binop::Add)
                } else if self.peek(TokenType::Minus) {
                    (TokenType::Minus, Binop::Sub)
                } else {
                    return Err(Error::UnexpectedToken(
                        self.curr_token(),
                        vec![TokenType::Plus, TokenType::Minus]));
                };
            try!(self.eat(tok));
            let t2 = try!(self.parse_term());
            term = Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Binop(ExprBinop {
                    op: op,
                    expr1: Box::new(term),
                    expr2: Box::new(t2)
                })
            };
        }
        Ok(term)
    }

    fn parse_term(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let mut fact = try!(self.parse_factor());
        while self.next_is_mul() {
            let (tok, op) =
                if self.peek(TokenType::Star) {
                    (TokenType::Star, Binop::Mul)
                } else if self.peek(TokenType::Slash) {
                    (TokenType::Slash, Binop::Div)
                } else {
                    return Err(Error::UnexpectedToken(
                        self.curr_token(),
                        vec![TokenType::Star, TokenType::Slash]));
                };
            try!(self.eat(tok));
            let f2 = try!(self.parse_factor());
            fact = Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Binop(ExprBinop {
                    op: op,
                    expr1: Box::new(fact),
                    expr2: Box::new(f2),
                })
            };
        }
        Ok(fact)
    }

    fn parse_factor(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        if self.peek(TokenType::Int) {
            self.parse_int()
        } else if self.peek(TokenType::Float) {
            self.parse_float()
        } else if self.peek(TokenType::String) {
            self.parse_string()
        } else if self.peek(TokenType::Id) {
            self.parse_id()
        } else if self.peek(TokenType::LParen) {
            try!(self.eat(TokenType::LParen));
            let e = try!(self.parse_expr());
            try!(self.eat(TokenType::RParen));
            Ok(e)
        } else if self.peek(TokenType::Minus) {
            try!(self.eat(TokenType::Minus));
            let e = try!(self.parse_expr());
            Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Negate(ExprNegate {
                    expr: Box::new(e)
                })
            })
        } else {
            Err(Error::UnexpectedToken(
                self.curr_token(),
                vec![TokenType::Int, TokenType::Float, TokenType::Id,
                     TokenType::Minus, TokenType::LParen]))
        }
    }

    fn parse_int(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Int));
        match lexeme.parse::<i64>() {
            Ok(n) => Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Int(ExprInt {
                    value: n
                })
            }),
            Err(_) => Err(Error::InvalidIntLiteral(pos, lexeme))
        }
    }

    fn parse_float(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Float));
        match lexeme.parse::<f64>() {
            Ok(n) => Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Float(ExprFloat {
                    value: n
                })
            }),
            Err(_) => Err(Error::InvalidFloatLiteral(pos, lexeme))
        }
    }

    fn parse_string(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::String));
        Ok(Expr {
            pos: pos,
            node_id: self.next_id(),
            expr: Expr_::String(ExprString {
                value: lexeme
            })
        })
    }

    fn parse_id(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Id));
        Ok(Expr {
            pos: pos,
            node_id: self.next_id(),
            expr: Expr_::Id(ExprId {
                id: lexeme
            })
        })
    }

    fn is_stmt_start(&self) -> bool {
        self.peek(TokenType::Id) ||
            self.peek(TokenType::If) ||
            self.peek(TokenType::While) ||
            self.peek(TokenType::Read) ||
            self.peek(TokenType::Print)
    }

    fn next_is_add(&self) -> bool {
        self.peek(TokenType::Plus) || self.peek(TokenType::Minus)
    }

    fn next_is_mul(&self) -> bool {
        self.peek(TokenType::Star) || self.peek(TokenType::Slash)
    }
}
<commit_msg>Rename eat_type to parse_type<commit_after>use token::{Token, TokenType};
use ast::*;
use pos::Pos;
use error::Error;
use types::Type;

pub struct Parser {
    tokens: Vec<Token>,
    index: usize,
    curr_id: u64,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            tokens: tokens,
            index: 0,
            curr_id: 0,
        }
    }

    fn next_id(&mut self) -> u64 {
        let x = self.curr_id;
        self.curr_id += 1;
        x
    }

    fn peek(&self, t: TokenType) -> bool {
        let token = &self.tokens[self.index];
        token.typ == t
    }

    fn curr_token(&self) -> Token {
        self.tokens[self.index].clone()
    }

    fn token_pos(&self) -> Pos {
        self.tokens[self.index].pos
    }

    fn eat(&mut self, t: TokenType) -> Result<(), Error> {
        let b = self.peek(t);
        if b {
            self.index += 1;
            Ok(())
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
        }
    }

    fn eat_lexeme(&mut self, t: TokenType) -> Result<String, Error> {
        let token = &self.tokens[self.index];
        if token.typ == t {
            match token.lexeme {
                Some(ref lexeme) => {
                    self.index += 1;
                    Ok(lexeme.clone())
                }
                None => Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
            }
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![t]))
        }
    }

    pub fn parse_program(&mut self) -> Result<Program, Error> {
        let decls = try!(self.parse_decls());
        let stmts = try!(self.parse_stmts());
        try!(self.eat(TokenType::Eof));

        Ok(Program {
            decls: decls,
            stmts: stmts,
        })
    }

    fn parse_type(&mut self) -> Result<Type, Error> {
        if self.peek(TokenType::TypeInt) {
            let _ = try!(self.eat(TokenType::TypeInt));
            Ok(Type::Int)
        } else if self.peek(TokenType::TypeFloat) {
            let _ = try!(self.eat(TokenType::TypeFloat));
            Ok(Type::Float)
        } else if self.peek(TokenType::TypeString) {
            let _ = try!(self.eat(TokenType::TypeString));
            Ok(Type::String)
        } else {
            Err(Error::UnexpectedToken(self.curr_token(), vec![TokenType::TypeInt, TokenType::TypeFloat]))
        }
    }

    fn parse_decls(&mut self) -> Result<Vec<Decl>, Error> {
        let mut decls: Vec<Decl> = Vec::new();
        while self.peek(TokenType::Var) {
            let decl = try!(self.parse_decl());
            decls.push(decl);
        }
        Ok(decls)
    }

    fn parse_decl(&mut self) -> Result<Decl, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Var));
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Colon));
        let ty = try!(self.parse_type());
        try!(self.eat(TokenType::Semicolon));
        Ok(Decl { pos: pos, id: id, ty: ty })
    }

    fn parse_stmts(&mut self) -> Result<Vec<Stmt>, Error> {
        let mut stmts: Vec<Stmt> = Vec::new();
        while self.is_stmt_start() {
            let stmt = try!(self.parse_stmt());
            stmts.push(stmt);
        }
        Ok(stmts)
    }

    fn parse_stmt(&mut self) -> Result<Stmt, Error> {
        if self.peek(TokenType::Read) {
            self.parse_read()
        } else if self.peek(TokenType::Print) {
            self.parse_print()
        } else if self.peek(TokenType::Id) {
            self.parse_assign()
        } else if self.peek(TokenType::If) {
            self.parse_if()
        } else if self.peek(TokenType::While) {
            self.parse_while()
        } else {
            Err(Error::UnexpectedToken(
                self.curr_token(),
                vec![TokenType::Read, TokenType::Print,
                     TokenType::Id, TokenType::If, TokenType::While]))
        }
    }

    fn parse_read(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Read));
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Read(StmtRead { pos: pos, id: id }))
    }

    fn parse_print(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::Print));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Print(StmtPrint { pos: pos, expr: e }))
    }

    fn parse_assign(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        let id = try!(self.eat_lexeme(TokenType::Id));
        try!(self.eat(TokenType::Equal));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Semicolon));
        Ok(Stmt::Assign(StmtAssign { pos: pos, id: id, expr: e }))
    }

    fn parse_if(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::If));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Then));
        let then_stmts = try!(self.parse_stmts());

        let else_stmts =
            if self.peek(TokenType::Else) {
                try!(self.eat(TokenType::Else));
                try!(self.parse_stmts())
            } else {
                vec![]
            };

        try!(self.eat(TokenType::EndIf));
        Ok(Stmt::If(StmtIf {
            pos: pos,
            expr: e,
            then_stmts: then_stmts,
            else_stmts: else_stmts,
        }))
    }

    fn parse_while(&mut self) -> Result<Stmt, Error> {
        let pos = self.token_pos();
        try!(self.eat(TokenType::While));
        let e = try!(self.parse_expr());
        try!(self.eat(TokenType::Do));
        let stmts = try!(self.parse_stmts());
        try!(self.eat(TokenType::Done));
        Ok(Stmt::While(StmtWhile {
            pos: pos,
            expr: e,
            stmts: stmts,
        }))
    }

    fn parse_expr(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let mut term = try!(self.parse_term());
        while self.next_is_add() {
            let (tok, op) =
                if self.peek(TokenType::Plus) {
                    (TokenType::Plus, Binop::Add)
                } else if self.peek(TokenType::Minus) {
                    (TokenType::Minus, Binop::Sub)
                } else {
                    return Err(Error::UnexpectedToken(
                        self.curr_token(),
                        vec![TokenType::Plus, TokenType::Minus]));
                };
            try!(self.eat(tok));
            let t2 = try!(self.parse_term());
            term = Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Binop(ExprBinop {
                    op: op,
                    expr1: Box::new(term),
                    expr2: Box::new(t2)
                })
            };
        }
        Ok(term)
    }

    fn parse_term(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let mut fact = try!(self.parse_factor());
        while self.next_is_mul() {
            let (tok, op) =
                if self.peek(TokenType::Star) {
                    (TokenType::Star, Binop::Mul)
                } else if self.peek(TokenType::Slash) {
                    (TokenType::Slash, Binop::Div)
                } else {
                    return Err(Error::UnexpectedToken(
                        self.curr_token(),
                        vec![TokenType::Star, TokenType::Slash]));
                };
            try!(self.eat(tok));
            let f2 = try!(self.parse_factor());
            fact = Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Binop(ExprBinop {
                    op: op,
                    expr1: Box::new(fact),
                    expr2: Box::new(f2),
                })
            };
        }
        Ok(fact)
    }

    fn parse_factor(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        if self.peek(TokenType::Int) {
            self.parse_int()
        } else if self.peek(TokenType::Float) {
            self.parse_float()
        } else if self.peek(TokenType::String) {
            self.parse_string()
        } else if self.peek(TokenType::Id) {
            self.parse_id()
        } else if self.peek(TokenType::LParen) {
            try!(self.eat(TokenType::LParen));
            let e = try!(self.parse_expr());
            try!(self.eat(TokenType::RParen));
            Ok(e)
        } else if self.peek(TokenType::Minus) {
            try!(self.eat(TokenType::Minus));
            let e = try!(self.parse_expr());
            Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Negate(ExprNegate {
                    expr: Box::new(e)
                })
            })
        } else {
            Err(Error::UnexpectedToken(
                self.curr_token(),
                vec![TokenType::Int, TokenType::Float, TokenType::Id,
                     TokenType::Minus, TokenType::LParen]))
        }
    }

    fn parse_int(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Int));
        match lexeme.parse::<i64>() {
            Ok(n) => Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Int(ExprInt {
                    value: n
                })
            }),
            Err(_) => Err(Error::InvalidIntLiteral(pos, lexeme))
        }
    }

    fn parse_float(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Float));
        match lexeme.parse::<f64>() {
            Ok(n) => Ok(Expr {
                pos: pos,
                node_id: self.next_id(),
                expr: Expr_::Float(ExprFloat {
                    value: n
                })
            }),
            Err(_) => Err(Error::InvalidFloatLiteral(pos, lexeme))
        }
    }

    fn parse_string(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::String));
        Ok(Expr {
            pos: pos,
            node_id: self.next_id(),
            expr: Expr_::String(ExprString {
                value: lexeme
            })
        })
    }

    fn parse_id(&mut self) -> Result<Expr, Error> {
        let pos = self.token_pos();
        let lexeme = try!(self.eat_lexeme(TokenType::Id));
        Ok(Expr {
            pos: pos,
            node_id: self.next_id(),
            expr: Expr_::Id(ExprId {
                id: lexeme
            })
        })
    }

    fn is_stmt_start(&self) -> bool {
        self.peek(TokenType::Id) ||
            self.peek(TokenType::If) ||
            self.peek(TokenType::While) ||
            self.peek(TokenType::Read) ||
            self.peek(TokenType::Print)
    }

    fn next_is_add(&self) -> bool {
        self.peek(TokenType::Plus) || self.peek(TokenType::Minus)
    }

    fn next_is_mul(&self) -> bool {
        self.peek(TokenType::Star) || self.peek(TokenType::Slash)
    }
}
<|endoftext|>


<commit_before>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs, so I listed it here
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &'static str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner().flatten();

            panic!("Nth(0) {:?}", pairs.nth(0));
            panic!("Nth(1) {:?}", pairs.nth(1));
            panic!("Nth(2) {:?}", pairs.nth(2));

            Expression::FuncLiteral(
//                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
//               Box::new(parse_expression(pairs.nth(1).unwrap().into_span())),
//                Box::new(parse_expression(pairs.nth(2).unwrap().into_span()))
                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
                Box::new(parse_expression(pairs.nth(1).unwrap())),
                Box::new(parse_expression(pairs.nth(2).unwrap()))
            )
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

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

            Expression::FuncCall(
                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
                Some(Box::new(parse_expression(pairs.nth(2).unwrap())))
            )
        }

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(format!("{}", input.into_span().as_str())
            ),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just conver the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: String) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::main, &input) {
        Ok(mut pair) =>
            Ok(parse_expression(pair.nth(0).unwrap().into_inner().nth(0).unwrap())),

        Err(e) => Err(format!("{}", e))
    }
}<commit_msg>Move panic on to one line<commit_after>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs, so I listed it here
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &'static str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner().flatten();

            panic!("Nth(0): {:?}, Nth(1): {:?}, Nth(2): {:?}", pairs.nth(0), pairs.nth(1), pairs.nth(2));

            Expression::FuncLiteral(
//                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
//               Box::new(parse_expression(pairs.nth(1).unwrap().into_span())),
//                Box::new(parse_expression(pairs.nth(2).unwrap().into_span()))
                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
                Box::new(parse_expression(pairs.nth(1).unwrap())),
                Box::new(parse_expression(pairs.nth(2).unwrap()))
            )
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

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

            Expression::FuncCall(
                format!("{}", pairs.nth(0).unwrap().into_span().as_str()),
                Some(Box::new(parse_expression(pairs.nth(2).unwrap())))
            )
        }

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(format!("{}", input.into_span().as_str())
            ),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just conver the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: String) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::main, &input) {
        Ok(mut pair) =>
            Ok(parse_expression(pair.nth(0).unwrap().into_inner().nth(0).unwrap())),

        Err(e) => Err(format!("{}", e))
    }
}<|endoftext|>


<commit_before>#![feature(lang_items)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(unique)]
#![no_std]

#[macro_use]
extern crate system;
extern crate spin;

#[macro_use]
mod vga_buffer;

use core::ops::{Deref};
use system::{CAddr, ChannelMessage};

/// Decode a code in the PS/2 scan code set 1 (legacy set).
///
/// Difference between set 1 and sets 2 & 3:
///   http://wiki.osdev.org/%228042%22_PS/2_Controller#Translation
///
/// Reference table:
///   http://www.computer-engineering.org/ps2keyboard/scancodes1.html
pub fn from_scancode_printable(code: usize) -> Option<char> {
    let printable = match code {
        0x1e => 'a',
        0x30 => 'b',
        0x2e => 'c',
        0x20 => 'd',
        0x12 => 'e',
        0x21 => 'f',
        0x22 => 'g',
        0x23 => 'h',
        0x17 => 'i',
        0x24 => 'j',
        0x25 => 'k',
        0x26 => 'l',
        0x32 => 'm',
        0x31 => 'n',
        0x18 => 'o',
        0x19 => 'p',
        0x10 => 'q',
        0x13 => 'r',
        0x1f => 's',
        0x14 => 't',
        0x16 => 'u',
        0x2f => 'v',
        0x11 => 'w',
        0x2d => 'x',
        0x15 => 'y',
        0x2c => 'z',
        0x0b => '0',
        0x02 => '1',
        0x03 => '2',
        0x04 => '3',
        0x05 => '4',
        0x06 => '5',
        0x07 => '6',
        0x08 => '7',
        0x09 => '8',
        0x0a => '9',
        0x29 => '`',
        0x0c => '-',
        0x0d => '=',
        0x2b => '\\',
        0x39 => ' ',
        0x1a => '[',
        0x1b => ']',
        0x27 => ';',
        0x28 => '\'',
        0x33 => ',',
        0x34 => '.',
        0x35 => '/',
        0x37 => '*', // Keypad
        0x4a => '-', // Keypad
        0x4e => '+', // Keypad
        _ => return None,
    };

    Some(printable)
}

pub fn from_scancode(code: usize) -> Key {
    if code == 0x1C {
        Key::Enter
    } else {
        let printable = from_scancode_printable(code);
        if printable.is_some() {
            Key::Printable(printable.unwrap())
        } else {
            Key::Nonprintable
        }
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum Key {
    Printable(char),
    Enter,
    Nonprintable
}

static mut IS_PARENT: bool = true;

#[lang="start"]
#[no_mangle]
fn start(_argc: isize, _argv: *const *const u8) {
    if unsafe { IS_PARENT } {
        unsafe { IS_PARENT = false; }
        parent_main();
    } else {
        child_main();
    }
    loop {};
}

fn parent_main() {
    let task_buffer = 0x90001000;

    system_print!(task_buffer, "parent rinit started.");
    print!("Child entry should be at: 0x{:x} ({})\nChild stack pointer should be at: 0x{:x} ({})\n",
           start as *const () as usize, start as *const () as usize,
           0x70000000 + (0x1000 * 4 - 4), 0x70000000 + (0x1000 * 4 - 4));
    print!(">>> ");
    let mut lastkey = Key::Nonprintable;
    let mut command = [0u8; 32];
    let mut command_size = 0;
    while true {
        let key = from_scancode(match system::channel_take(task_buffer, CAddr::from(254)) {
            ChannelMessage::Raw(i) => i,
            _ => panic!(),
        } as usize);
        if key == lastkey {
            continue;
        } else {
            lastkey = key.clone();
        }
        match key {
            Key::Printable(c) => {
                print!("{}", c);
                if command_size < 32 {
                    command[command_size] = c as u8;
                    command_size += 1;
                }
            }
            Key::Enter => {
                print!("\n");
                execute_command(task_buffer, ::core::str::from_utf8(&command[0..command_size]).unwrap());
                command = [0u8; 32];
                command_size = 0;
            }
            _ => (),
        }
    }
}

fn start_child(task_buffer: usize) {
    system::retype_task(task_buffer, CAddr::from(2), CAddr::from(249));
    system::task_set_stack_pointer(task_buffer, CAddr::from(249), 0x70000000 + (0x1000 * 4 - 4));
    system::task_set_instruction_pointer(task_buffer, CAddr::from(249), start as *const () as u64);
    system::task_set_cpool(task_buffer, CAddr::from(249), CAddr::from(0));
    system::task_set_top_page_table(task_buffer, CAddr::from(249), CAddr::from(3));
    system::task_set_buffer(task_buffer, CAddr::from(249), CAddr::from(250));
    system::task_set_active(task_buffer, CAddr::from(249));
}

fn child_main() {
    let task_buffer = 0x90003000;

    system_print!(task_buffer, "child rinit started.");
    while true {
        let value = system::channel_take(task_buffer, CAddr::from(255));
        system_print!(task_buffer, "Received from master: {:?}", value);
    }
}

fn parse_usize(s: &str, prefix: &str) -> Option<(usize, usize)> {
    if s.len() >= prefix.len() + 4 && &s[0..prefix.len()] == prefix {
        let st = &s[(prefix.len()+1)..s.len()];
        let mut split = st.split(' ');
        let o1: usize = split.next().unwrap().parse().unwrap();
        let o2: usize = split.next().unwrap().parse().unwrap();
        return Some((o1, o2));
    } else {
        return None;
    }
}

fn execute_command(task_buffer: usize, s: &str) {
    if s == "list" {
        print!("Listing task cpool ...\n");
        system::cpool_list_debug(task_buffer);
    } else if s == "start child" {
        start_child(task_buffer);
        print!("Child started.\n");
    } else if s.len() >= 6 && &s[0..4] == "echo" {
        print!("{}\n", &s[5..s.len()]);
    } else if s.len() >= 6 && &s[0..4] == "send" {
        let value: u64 = (&s[5..s.len()]).parse().unwrap();
        system::channel_put(task_buffer, CAddr::from(255), ChannelMessage::Raw(value));
        print!("Sent to child through channel 255\n");
    } else if let Some((source, target)) = parse_usize(s, "retype cpool") {
        system::retype_cpool(task_buffer, CAddr::from(source as u8), CAddr::from(target as u8));
        print!("Operation finished.\n");
    } else if let Some((source, target)) = parse_usize(s, "retype task") {
        system::retype_task(task_buffer, CAddr::from(source as u8), CAddr::from(target as u8));
        print!("Operation finished.\n");
    } else if let Some((target, ptr)) = parse_usize(s, "set stack") {
        system::task_set_stack_pointer(task_buffer, CAddr::from(target as u8), ptr as u64);
        print!("Operation finished.\n");
    } else if let Some((target, ptr)) = parse_usize(s, "set instruction") {
        system::task_set_instruction_pointer(task_buffer, CAddr::from(target as u8), ptr as u64);
        print!("Operation finished.\n");
    } else if let Some((target, cpool)) = parse_usize(s, "set cpool") {
        system::task_set_cpool(task_buffer, CAddr::from(target as u8), CAddr::from(cpool as u8));
        print!("Operation finished.\n");
    } else if let Some((target, table)) = parse_usize(s, "set table") {
        system::task_set_top_page_table(task_buffer, CAddr::from(target as u8), CAddr::from(table as u8));
        print!("Operation finished.\n");
    } else if let Some((target, buffer)) = parse_usize(s, "set buffer") {
        system::task_set_buffer(task_buffer, CAddr::from(target as u8), CAddr::from(buffer as u8));
        print!("Operation finished.\n");
    } else if let Some((target, status)) = parse_usize(s, "set active") {
        if status == 0 {
            system::task_set_inactive(task_buffer, CAddr::from(target as u8));
        } else {
            system::task_set_active(task_buffer, CAddr::from(target as u8));
        }
        print!("Operation finished.\n");
    } else {
        print!("Unknown command.\n");
    }
    print!(">>> ");
}

fn divide_by_zero() {
    unsafe {
        asm!("mov dx, 0; div dx" ::: "ax", "dx" : "volatile", "intel")
    }
}
<commit_msg>Add a command for sending capability over channels<commit_after>#![feature(lang_items)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(unique)]
#![no_std]

#[macro_use]
extern crate system;
extern crate spin;

#[macro_use]
mod vga_buffer;

use core::ops::{Deref};
use system::{CAddr, ChannelMessage};

/// Decode a code in the PS/2 scan code set 1 (legacy set).
///
/// Difference between set 1 and sets 2 & 3:
///   http://wiki.osdev.org/%228042%22_PS/2_Controller#Translation
///
/// Reference table:
///   http://www.computer-engineering.org/ps2keyboard/scancodes1.html
pub fn from_scancode_printable(code: usize) -> Option<char> {
    let printable = match code {
        0x1e => 'a',
        0x30 => 'b',
        0x2e => 'c',
        0x20 => 'd',
        0x12 => 'e',
        0x21 => 'f',
        0x22 => 'g',
        0x23 => 'h',
        0x17 => 'i',
        0x24 => 'j',
        0x25 => 'k',
        0x26 => 'l',
        0x32 => 'm',
        0x31 => 'n',
        0x18 => 'o',
        0x19 => 'p',
        0x10 => 'q',
        0x13 => 'r',
        0x1f => 's',
        0x14 => 't',
        0x16 => 'u',
        0x2f => 'v',
        0x11 => 'w',
        0x2d => 'x',
        0x15 => 'y',
        0x2c => 'z',
        0x0b => '0',
        0x02 => '1',
        0x03 => '2',
        0x04 => '3',
        0x05 => '4',
        0x06 => '5',
        0x07 => '6',
        0x08 => '7',
        0x09 => '8',
        0x0a => '9',
        0x29 => '`',
        0x0c => '-',
        0x0d => '=',
        0x2b => '\\',
        0x39 => ' ',
        0x1a => '[',
        0x1b => ']',
        0x27 => ';',
        0x28 => '\'',
        0x33 => ',',
        0x34 => '.',
        0x35 => '/',
        0x37 => '*', // Keypad
        0x4a => '-', // Keypad
        0x4e => '+', // Keypad
        _ => return None,
    };

    Some(printable)
}

pub fn from_scancode(code: usize) -> Key {
    if code == 0x1C {
        Key::Enter
    } else {
        let printable = from_scancode_printable(code);
        if printable.is_some() {
            Key::Printable(printable.unwrap())
        } else {
            Key::Nonprintable
        }
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum Key {
    Printable(char),
    Enter,
    Nonprintable
}

static mut IS_PARENT: bool = true;

#[lang="start"]
#[no_mangle]
fn start(_argc: isize, _argv: *const *const u8) {
    if unsafe { IS_PARENT } {
        unsafe { IS_PARENT = false; }
        parent_main();
    } else {
        child_main();
    }
    loop {};
}

fn parent_main() {
    let task_buffer = 0x90001000;

    system_print!(task_buffer, "parent rinit started.");
    print!("Child entry should be at: 0x{:x} ({})\nChild stack pointer should be at: 0x{:x} ({})\n",
           start as *const () as usize, start as *const () as usize,
           0x70000000 + (0x1000 * 4 - 4), 0x70000000 + (0x1000 * 4 - 4));
    print!(">>> ");
    let mut lastkey = Key::Nonprintable;
    let mut command = [0u8; 32];
    let mut command_size = 0;
    while true {
        let key = from_scancode(match system::channel_take(task_buffer, CAddr::from(254)) {
            ChannelMessage::Raw(i) => i,
            _ => panic!(),
        } as usize);
        if key == lastkey {
            continue;
        } else {
            lastkey = key.clone();
        }
        match key {
            Key::Printable(c) => {
                print!("{}", c);
                if command_size < 32 {
                    command[command_size] = c as u8;
                    command_size += 1;
                }
            }
            Key::Enter => {
                print!("\n");
                execute_command(task_buffer, ::core::str::from_utf8(&command[0..command_size]).unwrap());
                command = [0u8; 32];
                command_size = 0;
            }
            _ => (),
        }
    }
}

fn start_child(task_buffer: usize) {
    system::retype_task(task_buffer, CAddr::from(2), CAddr::from(249));
    system::task_set_stack_pointer(task_buffer, CAddr::from(249), 0x70000000 + (0x1000 * 4 - 4));
    system::task_set_instruction_pointer(task_buffer, CAddr::from(249), start as *const () as u64);
    system::task_set_cpool(task_buffer, CAddr::from(249), CAddr::from(0));
    system::task_set_top_page_table(task_buffer, CAddr::from(249), CAddr::from(3));
    system::task_set_buffer(task_buffer, CAddr::from(249), CAddr::from(250));
    system::task_set_active(task_buffer, CAddr::from(249));
}

fn child_main() {
    let task_buffer = 0x90003000;

    system_print!(task_buffer, "child rinit started.");
    while true {
        let value = system::channel_take(task_buffer, CAddr::from(255));
        system_print!(task_buffer, "Received from master: {:?}", value);
    }
}

fn parse_usize(s: &str, prefix: &str) -> Option<(usize, usize)> {
    if s.len() >= prefix.len() + 4 && &s[0..prefix.len()] == prefix {
        let st = &s[(prefix.len()+1)..s.len()];
        let mut split = st.split(' ');
        let o1: usize = split.next().unwrap().parse().unwrap();
        let o2: usize = split.next().unwrap().parse().unwrap();
        return Some((o1, o2));
    } else {
        return None;
    }
}

fn execute_command(task_buffer: usize, s: &str) {
    if s == "list" {
        print!("Listing task cpool ...\n");
        system::cpool_list_debug(task_buffer);
    } else if s == "start child" {
        start_child(task_buffer);
        print!("Child started.\n");
    } else if s.len() >= 6 && &s[0..4] == "echo" {
        print!("{}\n", &s[5..s.len()]);
    } else if s.len() >= 6 && &s[0..8] == "send raw" {
        let value: u64 = (&s[9..s.len()]).parse().unwrap();
        system::channel_put(task_buffer, CAddr::from(255), ChannelMessage::Raw(value));
        print!("Sent raw to child through channel 255\n");
    } else if s.len() >= 6 && &s[0..8] == "send cap" {
        let value: u64 = (&s[9..s.len()]).parse().unwrap();
        system::channel_put(task_buffer, CAddr::from(255), ChannelMessage::Cap(Some(CAddr::from(value as u8))));
        print!("Sent cap to child through channel 255\n");
    } else if let Some((source, target)) = parse_usize(s, "retype cpool") {
        system::retype_cpool(task_buffer, CAddr::from(source as u8), CAddr::from(target as u8));
        print!("Operation finished.\n");
    } else if let Some((source, target)) = parse_usize(s, "retype task") {
        system::retype_task(task_buffer, CAddr::from(source as u8), CAddr::from(target as u8));
        print!("Operation finished.\n");
    } else if let Some((target, ptr)) = parse_usize(s, "set stack") {
        system::task_set_stack_pointer(task_buffer, CAddr::from(target as u8), ptr as u64);
        print!("Operation finished.\n");
    } else if let Some((target, ptr)) = parse_usize(s, "set instruction") {
        system::task_set_instruction_pointer(task_buffer, CAddr::from(target as u8), ptr as u64);
        print!("Operation finished.\n");
    } else if let Some((target, cpool)) = parse_usize(s, "set cpool") {
        system::task_set_cpool(task_buffer, CAddr::from(target as u8), CAddr::from(cpool as u8));
        print!("Operation finished.\n");
    } else if let Some((target, table)) = parse_usize(s, "set table") {
        system::task_set_top_page_table(task_buffer, CAddr::from(target as u8), CAddr::from(table as u8));
        print!("Operation finished.\n");
    } else if let Some((target, buffer)) = parse_usize(s, "set buffer") {
        system::task_set_buffer(task_buffer, CAddr::from(target as u8), CAddr::from(buffer as u8));
        print!("Operation finished.\n");
    } else if let Some((target, status)) = parse_usize(s, "set active") {
        if status == 0 {
            system::task_set_inactive(task_buffer, CAddr::from(target as u8));
        } else {
            system::task_set_active(task_buffer, CAddr::from(target as u8));
        }
        print!("Operation finished.\n");
    } else {
        print!("Unknown command.\n");
    }
    print!(">>> ");
}

fn divide_by_zero() {
    unsafe {
        asm!("mov dx, 0; div dx" ::: "ax", "dx" : "volatile", "intel")
    }
}
<|endoftext|>


<commit_before>use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
use bigint::H512;
use std::io;
use std::net::SocketAddr;
use ecies::ECIESStream;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use secp256k1::key::{PublicKey, SecretKey};
use hash::SECP256K1;
use util::pk2id;
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use rlp;

#[derive(Clone, Debug, Copy, PartialEq, Eq)]
/// Capability information
pub struct CapabilityInfo {
    pub name: &'static str,
    pub version: usize,
    pub length: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CapabilityMessage {
    pub name: String,
    pub version: usize,
}

impl Encodable for CapabilityMessage {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(2);
        s.append(&self.name);
        s.append(&self.version);
    }
}

impl Decodable for CapabilityMessage {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        Ok(Self {
            name: rlp.val_at(0)?,
            version: rlp.val_at(1)?,
        })
    }
}

#[derive(Clone, Debug)]
pub struct HelloMessage {
    pub protocol_version: usize,
    pub client_version: String,
    pub capabilities: Vec<CapabilityMessage>,
    pub port: usize,
    pub id: H512,
}

impl Encodable for HelloMessage {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(5);
        s.append(&self.protocol_version);
        s.append(&self.client_version);
        s.append_list(&self.capabilities);
        s.append(&self.port);
        s.append(&self.id);
    }
}

impl Decodable for HelloMessage {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        Ok(Self {
            protocol_version: rlp.val_at(0)?,
            client_version: rlp.val_at(1)?,
            capabilities: rlp.list_at(2)?,
            port: rlp.val_at(3)?,
            id: rlp.val_at(4)?,
        })
    }
}

/// Peer stream of a RLPx
pub struct PeerStream {
    stream: ECIESStream,
    protocol_version: usize,
    client_version: String,
    shared_capabilities: Vec<CapabilityInfo>,
    port: usize,
    id: H512,
    remote_id: H512,
}

impl PeerStream {
    /// Remote public id of this peer
    pub fn remote_id(&self) -> H512 {
        self.remote_id
    }

    /// Connect to a peer over TCP
    pub fn connect(
        addr: &SocketAddr, handle: &Handle,
        secret_key: SecretKey, remote_id: H512,
        protocol_version: usize, client_version: String,
        capabilities: Vec<CapabilityInfo>, port: usize
    ) -> Box<Future<Item = PeerStream, Error = io::Error>> {
        let public_key = match PublicKey::from_secret_key(&SECP256K1, &secret_key) {
            Ok(key) => key,
            Err(_) => return Box::new(future::err(
                io::Error::new(io::ErrorKind::Other, "SECP256K1 public key error")))
                as Box<Future<Item = PeerStream, Error = io::Error>>,
        };
        let id = pk2id(&public_key);
        let nonhello_capabilities = capabilities.clone();
        let nonhello_client_version = client_version.clone();

        let stream = ECIESStream::connect(addr, handle, secret_key.clone(), remote_id)
            .and_then(move |socket| {
                let hello = rlp::encode(&HelloMessage {
                    port, id, protocol_version, client_version,
                    capabilities: {
                        let mut caps = Vec::new();
                        for cap in capabilities {
                            caps.push(CapabilityMessage {
                                name: cap.name.to_string(),
                                version: cap.version
                            });
                        }
                        caps
                    }
                }).to_vec();
                let message_id: Vec<u8> = rlp::encode(&0usize).to_vec();
                assert!(message_id.len() == 1);
                let mut ret: Vec<u8> = Vec::new();
                ret.push(message_id[0]);
                for d in &hello {
                    ret.push(*d);
                }
                socket.send(ret)
            })
            .and_then(|transport| transport.into_future().map_err(|(e, _)| e))
            .and_then(move |(hello, transport)| {
                if hello.is_none() {
                    return Err(io::Error::new(io::ErrorKind::Other, "hello failed (no value)"));
                }
                let hello = hello.unwrap();

                let message_id_rlp = UntrustedRlp::new(&hello[0..1]);
                let message_id: Result<usize, rlp::DecoderError> = message_id_rlp.as_val();
                match message_id {
                    Ok(message_id) => {
                        if message_id != 0 {
                            return Err(io::Error::new(io::ErrorKind::Other,
                                                      "hello failed (message id)"));
                        }
                    },
                    Err(_) => {
                        return Err(io::Error::new(io::ErrorKind::Other,
                                                  "hello failed (message id parsing)"));
                    }
                }

                let rlp: Result<HelloMessage, rlp::DecoderError> =
                    UntrustedRlp::new(&hello[1..]).as_val();
                match rlp {
                    Ok(val) => {
                        println!("hello message: {:?}", val);
                        let mut shared_capabilities: Vec<CapabilityInfo> = Vec::new();

                        for cap_info in nonhello_capabilities {
                            if val.capabilities.iter().find(
                                |v| v.name == cap_info.name && v.version == cap_info.version)
                                .is_some()
                            {
                                shared_capabilities.push(cap_info.clone());
                            }
                        }

                        let mut shared_caps_original = shared_capabilities.clone();

                        for cap_info in shared_caps_original {
                            shared_capabilities.retain(|v| {
                                if v.name != cap_info.name { true }
                                else if v.version < cap_info.version { false }
                                else { true }
                            });
                        }

                        shared_capabilities.sort_by_key(|v| v.name.clone());

                        Ok(PeerStream {
                            stream: transport,
                            client_version: nonhello_client_version,
                            protocol_version, port, id, remote_id,
                            shared_capabilities
                        })
                    },
                    Err(_) => Err(io::Error::new(io::ErrorKind::Other, "hello failed (rlp error)"))
                }
            });

        Box::new(stream)
    }
}

impl Stream for PeerStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match try_ready!(self.stream.poll()) {
            Some(val) => {
                let message_id_rlp = UntrustedRlp::new(&val[0..1]);
                let message_id: Result<usize, rlp::DecoderError> = message_id_rlp.as_val();

                let (cap, id) = match message_id {
                    Ok(message_id) => {
                        if message_id < 0x10 {
                            println!("got reserved message: {}, {:?}", message_id, &val[1..]);
                            return Ok(Async::NotReady);
                        }

                        let mut message_id = message_id - 0x10;
                        let mut index = 0;
                        for cap in &self.shared_capabilities {
                            if message_id > cap.length {
                                message_id = message_id - cap.length;
                                index = index + 1;
                            }
                        }
                        if index >= self.shared_capabilities.len() {
                            return Err(io::Error::new(io::ErrorKind::Other,
                                                      "message id parsing failed (too big)"));
                        }
                        (self.shared_capabilities[index].clone(), message_id)
                    },
                    Err(_) => {
                        return Err(io::Error::new(io::ErrorKind::Other,
                                                  "message id parsing failed (invalid)"));
                    }
                };

                Ok(Async::Ready(Some((cap, id, (&val[1..]).into()))))
            },
            None => Ok(Async::Ready(None)),
        }
    }
}

impl Sink for PeerStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        if !self.shared_capabilities.contains(&cap) {
            return Ok(AsyncSink::Ready);
        }

        let mut message_id = 0x10;
        for scap in &self.shared_capabilities {
            if scap != &cap {
                message_id = message_id + scap.length;
            } else {
                break;
            }
        }
        message_id = message_id + id;
        let first = rlp::encode(&message_id);
        assert!(first.len() == 1);

        let mut ret: Vec<u8> = Vec::new();
        ret.push(first[0]);
        for d in &data {
            ret.push(*d);
        }

        match self.stream.start_send(ret)? {
            AsyncSink::Ready => Ok(AsyncSink::Ready),
            AsyncSink::NotReady(_) => Ok(AsyncSink::NotReady((cap, id, data))),
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.stream.poll_complete()
    }
}
<commit_msg>rlpx: handle reserved messages<commit_after>use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
use bigint::H512;
use std::io;
use std::net::SocketAddr;
use ecies::ECIESStream;
use tokio_core::reactor::Handle;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use secp256k1::key::{PublicKey, SecretKey};
use hash::SECP256K1;
use util::pk2id;
use futures::future;
use futures::{Poll, Async, StartSend, AsyncSink, Future, Stream, Sink};
use rlp;

#[derive(Clone, Debug, Copy, PartialEq, Eq)]
/// Capability information
pub struct CapabilityInfo {
    pub name: &'static str,
    pub version: usize,
    pub length: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CapabilityMessage {
    pub name: String,
    pub version: usize,
}

impl Encodable for CapabilityMessage {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(2);
        s.append(&self.name);
        s.append(&self.version);
    }
}

impl Decodable for CapabilityMessage {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        Ok(Self {
            name: rlp.val_at(0)?,
            version: rlp.val_at(1)?,
        })
    }
}

#[derive(Clone, Debug)]
pub struct HelloMessage {
    pub protocol_version: usize,
    pub client_version: String,
    pub capabilities: Vec<CapabilityMessage>,
    pub port: usize,
    pub id: H512,
}

impl Encodable for HelloMessage {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(5);
        s.append(&self.protocol_version);
        s.append(&self.client_version);
        s.append_list(&self.capabilities);
        s.append(&self.port);
        s.append(&self.id);
    }
}

impl Decodable for HelloMessage {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        Ok(Self {
            protocol_version: rlp.val_at(0)?,
            client_version: rlp.val_at(1)?,
            capabilities: rlp.list_at(2)?,
            port: rlp.val_at(3)?,
            id: rlp.val_at(4)?,
        })
    }
}

/// Peer stream of a RLPx
pub struct PeerStream {
    stream: ECIESStream,
    protocol_version: usize,
    client_version: String,
    shared_capabilities: Vec<CapabilityInfo>,
    port: usize,
    id: H512,
    remote_id: H512,
}

impl PeerStream {
    /// Remote public id of this peer
    pub fn remote_id(&self) -> H512 {
        self.remote_id
    }

    /// Connect to a peer over TCP
    pub fn connect(
        addr: &SocketAddr, handle: &Handle,
        secret_key: SecretKey, remote_id: H512,
        protocol_version: usize, client_version: String,
        capabilities: Vec<CapabilityInfo>, port: usize
    ) -> Box<Future<Item = PeerStream, Error = io::Error>> {
        let public_key = match PublicKey::from_secret_key(&SECP256K1, &secret_key) {
            Ok(key) => key,
            Err(_) => return Box::new(future::err(
                io::Error::new(io::ErrorKind::Other, "SECP256K1 public key error")))
                as Box<Future<Item = PeerStream, Error = io::Error>>,
        };
        let id = pk2id(&public_key);
        let nonhello_capabilities = capabilities.clone();
        let nonhello_client_version = client_version.clone();

        let stream = ECIESStream::connect(addr, handle, secret_key.clone(), remote_id)
            .and_then(move |socket| {
                let hello = rlp::encode(&HelloMessage {
                    port, id, protocol_version, client_version,
                    capabilities: {
                        let mut caps = Vec::new();
                        for cap in capabilities {
                            caps.push(CapabilityMessage {
                                name: cap.name.to_string(),
                                version: cap.version
                            });
                        }
                        caps
                    }
                }).to_vec();
                let message_id: Vec<u8> = rlp::encode(&0usize).to_vec();
                assert!(message_id.len() == 1);
                let mut ret: Vec<u8> = Vec::new();
                ret.push(message_id[0]);
                for d in &hello {
                    ret.push(*d);
                }
                socket.send(ret)
            })
            .and_then(|transport| transport.into_future().map_err(|(e, _)| e))
            .and_then(move |(hello, transport)| {
                if hello.is_none() {
                    return Err(io::Error::new(io::ErrorKind::Other, "hello failed (no value)"));
                }
                let hello = hello.unwrap();

                let message_id_rlp = UntrustedRlp::new(&hello[0..1]);
                let message_id: Result<usize, rlp::DecoderError> = message_id_rlp.as_val();
                match message_id {
                    Ok(message_id) => {
                        if message_id != 0 {
                            return Err(io::Error::new(io::ErrorKind::Other,
                                                      "hello failed (message id)"));
                        }
                    },
                    Err(_) => {
                        return Err(io::Error::new(io::ErrorKind::Other,
                                                  "hello failed (message id parsing)"));
                    }
                }

                let rlp: Result<HelloMessage, rlp::DecoderError> =
                    UntrustedRlp::new(&hello[1..]).as_val();
                match rlp {
                    Ok(val) => {
                        println!("hello message: {:?}", val);
                        let mut shared_capabilities: Vec<CapabilityInfo> = Vec::new();

                        for cap_info in nonhello_capabilities {
                            if val.capabilities.iter().find(
                                |v| v.name == cap_info.name && v.version == cap_info.version)
                                .is_some()
                            {
                                shared_capabilities.push(cap_info.clone());
                            }
                        }

                        let mut shared_caps_original = shared_capabilities.clone();

                        for cap_info in shared_caps_original {
                            shared_capabilities.retain(|v| {
                                if v.name != cap_info.name { true }
                                else if v.version < cap_info.version { false }
                                else { true }
                            });
                        }

                        shared_capabilities.sort_by_key(|v| v.name.clone());

                        Ok(PeerStream {
                            stream: transport,
                            client_version: nonhello_client_version,
                            protocol_version, port, id, remote_id,
                            shared_capabilities
                        })
                    },
                    Err(_) => Err(io::Error::new(io::ErrorKind::Other, "hello failed (rlp error)"))
                }
            });

        Box::new(stream)
    }

    fn handle_reserved_message(
        &mut self, message_id: usize, data: Vec<u8>
    ) -> Result<(), io::Error> {
        match message_id {
            0x01 /* disconnect */ => {
                let reason: Result<usize, rlp::DecoderError> = UntrustedRlp::new(&data).val_at(0);
                return Err(io::Error::new(io::ErrorKind::Other,
                                          "explicit disconnect"));
            },
            0x02 /* ping */ => {
                let mut payload: Vec<u8> = rlp::encode(&0x03usize /* pong */).to_vec();
                payload.append(&mut rlp::EMPTY_LIST_RLP.to_vec());
                self.stream.start_send(payload)?;
            },
            0x03 /* pong */ => (),
            _ => return Err(io::Error::new(io::ErrorKind::Other,
                                           "unhandled reserved message")),
        }
        Ok(())
    }
}

impl Stream for PeerStream {
    type Item = (CapabilityInfo, usize, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match try_ready!(self.stream.poll()) {
            Some(val) => {
                let message_id_rlp = UntrustedRlp::new(&val[0..1]);
                let message_id: Result<usize, rlp::DecoderError> = message_id_rlp.as_val();

                let (cap, id) = match message_id {
                    Ok(message_id) => {
                        if message_id < 0x10 {
                            self.handle_reserved_message(message_id, (&val[1..]).into())?;
                            return Ok(Async::NotReady);
                        }

                        let mut message_id = message_id - 0x10;
                        let mut index = 0;
                        for cap in &self.shared_capabilities {
                            if message_id > cap.length {
                                message_id = message_id - cap.length;
                                index = index + 1;
                            }
                        }
                        if index >= self.shared_capabilities.len() {
                            return Err(io::Error::new(io::ErrorKind::Other,
                                                      "message id parsing failed (too big)"));
                        }
                        (self.shared_capabilities[index].clone(), message_id)
                    },
                    Err(_) => {
                        return Err(io::Error::new(io::ErrorKind::Other,
                                                  "message id parsing failed (invalid)"));
                    }
                };

                Ok(Async::Ready(Some((cap, id, (&val[1..]).into()))))
            },
            None => Ok(Async::Ready(None)),
        }
    }
}

impl Sink for PeerStream {
    type SinkItem = (CapabilityInfo, usize, Vec<u8>);
    type SinkError = io::Error;

    fn start_send(&mut self, (cap, id, data): (CapabilityInfo, usize, Vec<u8>)) -> StartSend<Self::SinkItem, Self::SinkError> {
        if !self.shared_capabilities.contains(&cap) {
            return Ok(AsyncSink::Ready);
        }

        let mut message_id = 0x10;
        for scap in &self.shared_capabilities {
            if scap != &cap {
                message_id = message_id + scap.length;
            } else {
                break;
            }
        }
        message_id = message_id + id;
        let first = rlp::encode(&message_id);
        assert!(first.len() == 1);

        let mut ret: Vec<u8> = Vec::new();
        ret.push(first[0]);
        for d in &data {
            ret.push(*d);
        }

        match self.stream.start_send(ret)? {
            AsyncSink::Ready => Ok(AsyncSink::Ready),
            AsyncSink::NotReady(_) => Ok(AsyncSink::NotReady((cap, id, data))),
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.stream.poll_complete()
    }
}
<|endoftext|>


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

//! The Rust core library

#![crate_id = "core#0.11-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes)]
#![deny(missing_doc)]

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* Core modules for ownership management */

pub mod cast;
pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

pub mod cmp;
pub mod kinds;
pub mod ops;
pub mod ty;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
mod unit;
pub mod any;
pub mod bool;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod char;
pub mod slice;
pub mod str;
pub mod tuple;

// FIXME: this module should not exist
mod should_not_exist;
<commit_msg>core: Allow some #[deriving] in libcore<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust core library

#![crate_id = "core#0.11-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![no_std]
#![feature(globs, macro_rules, managed_boxes)]
#![deny(missing_doc)]

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod num;

/* Core modules for ownership management */

pub mod cast;
pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

pub mod cmp;
pub mod kinds;
pub mod ops;
pub mod ty;
pub mod clone;
pub mod default;
pub mod container;

/* Core types and methods on primitives */

mod unicode;
mod unit;
pub mod any;
pub mod bool;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;
pub mod char;
pub mod result;
pub mod slice;
pub mod str;
pub mod tuple;

// FIXME: this module should not exist
mod should_not_exist;

mod std {
    pub use clone;
    pub use cmp;
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_real,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn cheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_complex,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_complex,
            lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Spev trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_real,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn cheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_complex,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_complex,
            lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, ap: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_doublereal, w: CLPK_doublereal,
            z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


<commit_before>use camera;
use cube_shell::cube_diff;
use id_allocator::IdAllocator;
use lod::{LOD, LODIndex, OwnerId};
use nalgebra::{Pnt3, Vec3};
use ncollide_entities::bounding_volume::AABB;
use ncollide_queries::ray::{Ray, Ray3};
use opencl_context::CL;
use physics::Physics;
use server::EntityId;
use std::f32::consts::PI;
use std::iter::range_inclusive;
use std::num;
use stopwatch::TimerSet;
use surroundings_loader::{SurroundingsLoader, LODChange};
use terrain::terrain;
use terrain::terrain_block::BlockPosition;
use terrain::terrain_game_loader::TerrainGameLoader;
use update;

pub const LOD_THRESHOLDS: [i32; 3] = [1, 8, 32];

const MAX_JUMP_FUEL: u32 = 4;
const MAX_STEP_HEIGHT: f32 = 1.0;

pub struct Player<'a> {
  pub position: Pnt3<f32>,
  // speed; units are world coordinates
  pub speed: Vec3<f32>,
  // acceleration; units are world coordinates
  pub accel: Vec3<f32>,
  // acceleration; x/z units are relative to player facing
  pub walk_accel: Vec3<f32>,
  // this is depleted as we jump and replenished as we stand.
  pub jump_fuel: u32,
  // are we currently trying to jump? (e.g. holding the key).
  pub is_jumping: bool,
  pub id: EntityId,

  // rotation around the y-axis, in radians
  pub lateral_rotation: f32,
  // "pitch", in radians
  pub vertical_rotation: f32,

  pub surroundings_loader: SurroundingsLoader<'a>,
  // Nearby blocks should be made solid if they aren't loaded yet.
  pub solid_boundary: SurroundingsLoader<'a>,
}

impl<'a> Player<'a> {
  pub fn new(
    id_allocator: &mut IdAllocator<EntityId>,
    owner_allocator: &mut IdAllocator<OwnerId>,
  ) -> Player<'a> {
    Player {
      position: Pnt3::new(0.0, 0.0, 0.0),
      speed: Vec3::new(0.0, 0.0, 0.0),
      accel: Vec3::new(0.0, -0.1, 0.0),
      walk_accel: Vec3::new(0.0, 0.0, 0.0),
      jump_fuel: 0,
      is_jumping: false,
      id: id_allocator.allocate(),
      lateral_rotation: 0.0,
      vertical_rotation: 0.0,
      surroundings_loader:
        SurroundingsLoader::new(
          owner_allocator.allocate(),
          1,
          Box::new(|&: last, cur| cube_diff(last, cur, 1)),
        ),
      solid_boundary:
        SurroundingsLoader::new(
          owner_allocator.allocate(),
          1,
          Box::new(|&: last, cur| cube_diff(last, cur, 1)),
        ),
    }
  }

  /// Translates the player/camera by a vector.
  /// If the player collides with something with a small height jump, the player will shift upward.
  /// Returns the actual amount moved by.
  pub fn translate(
    &mut self,
    physics: &mut Physics,
    v: Vec3<f32>,
  ) {
    let bounds = physics.bounds.get_mut(&self.id).unwrap();
    let init_bounds =
      AABB::new(
        *bounds.mins() + v,
        *bounds.maxs() + v,
      );
    let mut new_bounds = init_bounds.clone();
    // The height of the player's "step".
    let mut step_height = 0.0;
    let mut collided = false;
    loop {
      match physics.terrain_octree.intersect(&new_bounds, None) {
        None => {
          Physics::reinsert(&mut physics.misc_octree, self.id, bounds, new_bounds);
          self.position = self.position + v + Vec3::new(0.0, step_height, 0.0);
          break;
        },
        Some((collision_bounds, _)) => {
          collided = true;
          // Step to the top of whatever we hit.
          step_height = collision_bounds.maxs().y - init_bounds.mins().y;
          assert!(step_height > 0.0);

          if step_height > MAX_STEP_HEIGHT {
            // Step is too big; we just ran into something.
            break;
          }

          new_bounds =
            AABB::new(
              *init_bounds.mins() + Vec3::new(0.0, step_height, 0.0),
              *init_bounds.maxs() + Vec3::new(0.0, step_height, 0.0),
            );
        },
      }
    }

    if collided {
      if v.y < 0.0 {
        self.jump_fuel = MAX_JUMP_FUEL;
      }

      self.speed = self.speed - v;
    } else {
      if v.y < 0.0 {
        self.jump_fuel = 0;
      }
    }
  }

  pub fn update(
    &mut self,
    timers: &TimerSet,
    cl: &CL,
    terrain_game_loader: &mut TerrainGameLoader,
    id_allocator: &mut IdAllocator<EntityId>,
    physics: &mut Physics,
  ) {
    let block_position = BlockPosition::from_world_position(&self.position);

    timers.time("update.player.surroundings", || {
      self.surroundings_loader.update(
        block_position,
        |lod_change| {
          match lod_change {
            LODChange::Load(pos, _, id) => {
              terrain_game_loader.load(
                timers,
                cl,
                id_allocator,
                physics,
                &pos,
                LOD::LodIndex(LODIndex(0)),
                id,
              );
            },
            LODChange::Unload(pos, id) => {
              terrain_game_loader.unload(
                timers,
                physics,
                &pos,
                id,
              );
            },
          }
        },
      );

      self.solid_boundary.update(
        block_position,
        |lod_change|
          update::load_placeholders(
            timers,
            cl,
            id_allocator,
            physics,
            terrain_game_loader,
            lod_change,
          )
      );
    });

    if self.is_jumping {
      if self.jump_fuel > 0 {
        self.jump_fuel -= 1;
      } else {
        // this code is duplicated in a few places
        self.is_jumping = false;
        self.accel.y = self.accel.y - 0.3;
      }
    }

    let delta_p = self.speed;
    if delta_p.x != 0.0 {
      self.translate(physics, Vec3::new(delta_p.x, 0.0, 0.0));
    }
    if delta_p.y != 0.0 {
      self.translate(physics, Vec3::new(0.0, delta_p.y, 0.0));
    }
    if delta_p.z != 0.0 {
      self.translate(physics, Vec3::new(0.0, 0.0, delta_p.z));
    }

    let y_axis = Vec3::new(0.0, 1.0, 0.0);
    let walk_v =
        camera::from_axis_angle3(y_axis, self.lateral_rotation) * self.walk_accel;
    self.speed = self.speed + walk_v + self.accel;
    // friction
    self.speed = self.speed * Vec3::new(0.7, 0.99, 0.7 as f32);
  }

  /// Changes the camera's acceleration by the given `da`.
  pub fn walk(&mut self, da: Vec3<f32>) {
    self.walk_accel = self.walk_accel + da * 0.2 as f32;
  }

  /// Rotate the camera around the y axis, by `r` radians. Positive is counterclockwise.
  pub fn rotate_lateral(&mut self, r: f32) {
    self.lateral_rotation = self.lateral_rotation + r;
  }

  /// Changes the camera pitch by `r` radians. Positive is up.
  /// Angles that "flip around" (i.e. looking too far up or down)
  /// are sliently rejected.
  pub fn rotate_vertical(&mut self, r: f32) {
    let new_rotation = self.vertical_rotation + r;

    if new_rotation < -PI / 2.0
    || new_rotation >  PI / 2.0 {
      return
    }

    self.vertical_rotation = new_rotation;
  }

  // axes

  /// Return the "right" axis (i.e. the x-axis rotated to match you).
  pub fn right(&self) -> Vec3<f32> {
    return
      camera::from_axis_angle3(Vec3::new(0.0, 1.0, 0.0), self.lateral_rotation) *
      Vec3::new(1.0, 0.0, 0.0)
  }

  /// Return the "Ray axis (i.e. the z-axis rotated to match you).
  pub fn forward(&self) -> Vec3<f32> {
    let y_axis = Vec3::new(0.0, 1.0, 0.0);
    let transform =
      camera::from_axis_angle3(self.right(), self.vertical_rotation) *
      camera::from_axis_angle3(y_axis, self.lateral_rotation);
    let forward_orig = Vec3::new(0.0, 0.0, -1.0);

    transform * forward_orig
  }

  #[allow(dead_code)]
  pub fn forward_ray(&self) -> Ray3<f32> {
    Ray::new(self.position, self.forward())
  }

  pub fn lod_index(distance: i32) -> LODIndex {
    assert!(distance >= 0);
    let mut lod = 0;
    while
      lod < LOD_THRESHOLDS.len()
      && LOD_THRESHOLDS[lod] < distance
    {
      lod += 1;
    }
    LODIndex(num::cast(lod).unwrap())
  }

  pub fn load_distance(mut polygon_budget: i32) -> i32 {
    // TODO: This should try to account for VRAM not used on a per-poly basis.

    let mut load_distance = 0;
    let mut prev_threshold = 0;
    let mut prev_square = 0;
    for (&threshold, &quality) in
      LOD_THRESHOLDS.iter()
        .zip(terrain::LOD_QUALITY.iter()) {
      let polygons_per_block = (quality * quality * 4) as i32;
      for i in range_inclusive(prev_threshold, threshold) {
        let i = 2 * i + 1;
        let square = i * i;
        let polygons_in_layer = (square - prev_square) * polygons_per_block;
        polygon_budget -= polygons_in_layer;
        if polygon_budget < 0 {
          break;
        }

        load_distance += 1;
        prev_square = square;
      }
      prev_threshold = threshold + 1;
    }

    let mut width = 2 * prev_threshold + 1;
    loop {
      let square = width * width;
      // The "to infinity and beyond" quality.
      let quality = terrain::LOD_QUALITY[LOD_THRESHOLDS.len()];
      let polygons_per_block = (quality * quality * 4) as i32;
      let polygons_in_layer = (square - prev_square) * polygons_per_block;
      polygon_budget -= polygons_in_layer;

      if polygon_budget < 0 {
        break;
      }

      width += 2;
      load_distance += 1;
      prev_square = square;
    }

    load_distance
  }
}
<commit_msg>Fix player not collision checking with misc_octree.<commit_after>use camera;
use cube_shell::cube_diff;
use id_allocator::IdAllocator;
use lod::{LOD, LODIndex, OwnerId};
use nalgebra::{Pnt3, Vec3};
use ncollide_entities::bounding_volume::AABB;
use ncollide_queries::ray::{Ray, Ray3};
use opencl_context::CL;
use physics::Physics;
use server::EntityId;
use std::f32::consts::PI;
use std::iter::range_inclusive;
use std::num;
use stopwatch::TimerSet;
use surroundings_loader::{SurroundingsLoader, LODChange};
use terrain::terrain;
use terrain::terrain_block::BlockPosition;
use terrain::terrain_game_loader::TerrainGameLoader;
use update;

pub const LOD_THRESHOLDS: [i32; 3] = [1, 8, 32];

const MAX_JUMP_FUEL: u32 = 4;
const MAX_STEP_HEIGHT: f32 = 1.0;

pub struct Player<'a> {
  pub position: Pnt3<f32>,
  // speed; units are world coordinates
  pub speed: Vec3<f32>,
  // acceleration; units are world coordinates
  pub accel: Vec3<f32>,
  // acceleration; x/z units are relative to player facing
  pub walk_accel: Vec3<f32>,
  // this is depleted as we jump and replenished as we stand.
  pub jump_fuel: u32,
  // are we currently trying to jump? (e.g. holding the key).
  pub is_jumping: bool,
  pub id: EntityId,

  // rotation around the y-axis, in radians
  pub lateral_rotation: f32,
  // "pitch", in radians
  pub vertical_rotation: f32,

  pub surroundings_loader: SurroundingsLoader<'a>,
  // Nearby blocks should be made solid if they aren't loaded yet.
  pub solid_boundary: SurroundingsLoader<'a>,
}

impl<'a> Player<'a> {
  pub fn new(
    id_allocator: &mut IdAllocator<EntityId>,
    owner_allocator: &mut IdAllocator<OwnerId>,
  ) -> Player<'a> {
    Player {
      position: Pnt3::new(0.0, 0.0, 0.0),
      speed: Vec3::new(0.0, 0.0, 0.0),
      accel: Vec3::new(0.0, -0.1, 0.0),
      walk_accel: Vec3::new(0.0, 0.0, 0.0),
      jump_fuel: 0,
      is_jumping: false,
      id: id_allocator.allocate(),
      lateral_rotation: 0.0,
      vertical_rotation: 0.0,
      surroundings_loader:
        SurroundingsLoader::new(
          owner_allocator.allocate(),
          1,
          Box::new(|&: last, cur| cube_diff(last, cur, 1)),
        ),
      solid_boundary:
        SurroundingsLoader::new(
          owner_allocator.allocate(),
          1,
          Box::new(|&: last, cur| cube_diff(last, cur, 1)),
        ),
    }
  }

  /// Translates the player/camera by a vector.
  /// If the player collides with something with a small height jump, the player will shift upward.
  /// Returns the actual amount moved by.
  pub fn translate(
    &mut self,
    physics: &mut Physics,
    v: Vec3<f32>,
  ) {
    let bounds = physics.bounds.get_mut(&self.id).unwrap();
    let init_bounds =
      AABB::new(
        *bounds.mins() + v,
        *bounds.maxs() + v,
      );
    let mut new_bounds = init_bounds.clone();
    // The height of the player's "step".
    let mut step_height = 0.0;
    let mut collided = false;
    loop {
      match physics.terrain_octree.intersect(&new_bounds, None) {
        None => {
          if Physics::reinsert(&mut physics.misc_octree, self.id, bounds, new_bounds).is_some() {
            collided = true;
          } else {
            self.position = self.position + v + Vec3::new(0.0, step_height, 0.0);
          }
          break;
        },
        Some((collision_bounds, _)) => {
          collided = true;
          // Step to the top of whatever we hit.
          step_height = collision_bounds.maxs().y - init_bounds.mins().y;
          assert!(step_height > 0.0);

          if step_height > MAX_STEP_HEIGHT {
            // Step is too big; we just ran into something.
            break;
          }

          new_bounds =
            AABB::new(
              *init_bounds.mins() + Vec3::new(0.0, step_height, 0.0),
              *init_bounds.maxs() + Vec3::new(0.0, step_height, 0.0),
            );
        },
      }
    }

    if collided {
      if v.y < 0.0 {
        self.jump_fuel = MAX_JUMP_FUEL;
      }

      self.speed = self.speed - v;
    } else {
      if v.y < 0.0 {
        self.jump_fuel = 0;
      }
    }
  }

  pub fn update(
    &mut self,
    timers: &TimerSet,
    cl: &CL,
    terrain_game_loader: &mut TerrainGameLoader,
    id_allocator: &mut IdAllocator<EntityId>,
    physics: &mut Physics,
  ) {
    let block_position = BlockPosition::from_world_position(&self.position);

    timers.time("update.player.surroundings", || {
      self.surroundings_loader.update(
        block_position,
        |lod_change| {
          match lod_change {
            LODChange::Load(pos, _, id) => {
              terrain_game_loader.load(
                timers,
                cl,
                id_allocator,
                physics,
                &pos,
                LOD::LodIndex(LODIndex(0)),
                id,
              );
            },
            LODChange::Unload(pos, id) => {
              terrain_game_loader.unload(
                timers,
                physics,
                &pos,
                id,
              );
            },
          }
        },
      );

      self.solid_boundary.update(
        block_position,
        |lod_change|
          update::load_placeholders(
            timers,
            cl,
            id_allocator,
            physics,
            terrain_game_loader,
            lod_change,
          )
      );
    });

    if self.is_jumping {
      if self.jump_fuel > 0 {
        self.jump_fuel -= 1;
      } else {
        // this code is duplicated in a few places
        self.is_jumping = false;
        self.accel.y = self.accel.y - 0.3;
      }
    }

    let delta_p = self.speed;
    if delta_p.x != 0.0 {
      self.translate(physics, Vec3::new(delta_p.x, 0.0, 0.0));
    }
    if delta_p.y != 0.0 {
      self.translate(physics, Vec3::new(0.0, delta_p.y, 0.0));
    }
    if delta_p.z != 0.0 {
      self.translate(physics, Vec3::new(0.0, 0.0, delta_p.z));
    }

    let y_axis = Vec3::new(0.0, 1.0, 0.0);
    let walk_v =
        camera::from_axis_angle3(y_axis, self.lateral_rotation) * self.walk_accel;
    self.speed = self.speed + walk_v + self.accel;
    // friction
    self.speed = self.speed * Vec3::new(0.7, 0.99, 0.7 as f32);
  }

  /// Changes the camera's acceleration by the given `da`.
  pub fn walk(&mut self, da: Vec3<f32>) {
    self.walk_accel = self.walk_accel + da * 0.2 as f32;
  }

  /// Rotate the camera around the y axis, by `r` radians. Positive is counterclockwise.
  pub fn rotate_lateral(&mut self, r: f32) {
    self.lateral_rotation = self.lateral_rotation + r;
  }

  /// Changes the camera pitch by `r` radians. Positive is up.
  /// Angles that "flip around" (i.e. looking too far up or down)
  /// are sliently rejected.
  pub fn rotate_vertical(&mut self, r: f32) {
    let new_rotation = self.vertical_rotation + r;

    if new_rotation < -PI / 2.0
    || new_rotation >  PI / 2.0 {
      return
    }

    self.vertical_rotation = new_rotation;
  }

  // axes

  /// Return the "right" axis (i.e. the x-axis rotated to match you).
  pub fn right(&self) -> Vec3<f32> {
    return
      camera::from_axis_angle3(Vec3::new(0.0, 1.0, 0.0), self.lateral_rotation) *
      Vec3::new(1.0, 0.0, 0.0)
  }

  /// Return the "Ray axis (i.e. the z-axis rotated to match you).
  pub fn forward(&self) -> Vec3<f32> {
    let y_axis = Vec3::new(0.0, 1.0, 0.0);
    let transform =
      camera::from_axis_angle3(self.right(), self.vertical_rotation) *
      camera::from_axis_angle3(y_axis, self.lateral_rotation);
    let forward_orig = Vec3::new(0.0, 0.0, -1.0);

    transform * forward_orig
  }

  #[allow(dead_code)]
  pub fn forward_ray(&self) -> Ray3<f32> {
    Ray::new(self.position, self.forward())
  }

  pub fn lod_index(distance: i32) -> LODIndex {
    assert!(distance >= 0);
    let mut lod = 0;
    while
      lod < LOD_THRESHOLDS.len()
      && LOD_THRESHOLDS[lod] < distance
    {
      lod += 1;
    }
    LODIndex(num::cast(lod).unwrap())
  }

  pub fn load_distance(mut polygon_budget: i32) -> i32 {
    // TODO: This should try to account for VRAM not used on a per-poly basis.

    let mut load_distance = 0;
    let mut prev_threshold = 0;
    let mut prev_square = 0;
    for (&threshold, &quality) in
      LOD_THRESHOLDS.iter()
        .zip(terrain::LOD_QUALITY.iter()) {
      let polygons_per_block = (quality * quality * 4) as i32;
      for i in range_inclusive(prev_threshold, threshold) {
        let i = 2 * i + 1;
        let square = i * i;
        let polygons_in_layer = (square - prev_square) * polygons_per_block;
        polygon_budget -= polygons_in_layer;
        if polygon_budget < 0 {
          break;
        }

        load_distance += 1;
        prev_square = square;
      }
      prev_threshold = threshold + 1;
    }

    let mut width = 2 * prev_threshold + 1;
    loop {
      let square = width * width;
      // The "to infinity and beyond" quality.
      let quality = terrain::LOD_QUALITY[LOD_THRESHOLDS.len()];
      let polygons_per_block = (quality * quality * 4) as i32;
      let polygons_in_layer = (square - prev_square) * polygons_per_block;
      polygon_budget -= polygons_in_layer;

      if polygon_budget < 0 {
        break;
      }

      width += 2;
      load_distance += 1;
      prev_square = square;
    }

    load_distance
  }
}
<|endoftext|>