<commit_before>use Query;
use Token;
use std::str::Chars;

// consts for character representing tokens
const TOKEN_VAR_START: char = '%';
const TOKEN_VAR_END: char = '%';
const TOKEN_FUNC_NAME_START: char = '$';
const TOKEN_FUNC_PARAM_START: char = '(';
const TOKEN_FUNC_PARAM_END: char = ')';
const TOKEN_FUNC_PARAM_SEP: char = ',';
const TOKEN_ESCAPE: char = '\\';

// TODO: Proper error type instead of String
pub type ParseResult<T> = Result<T, ParseError>;

/// Errors found in parsing query
#[derive(Debug)]
pub enum ParseError {
    /// Unknown escape sequence.
    /// String contains the sequece
    UnknownEscape(String),

    /// Escape squence at end of query
    EscapeAtEndOfQuery,

    /// Variable is missing closing character
    VariableMissingClosing,

    /// Function is missing start of parameters
    FuncMissingParameter,

    /// Function parameters is missing closing character
    FuncParameterNotClosed,

    /// End of Query
    EndOfQuery,
}

impl Query {
    pub fn parse(src: String) -> ParseResult<Query> {
        let mut iter = src.chars();
        match parse_scope(&mut iter) {
            Ok(t) => Ok(Query { tokens: t }),
            Err(e) => return Err(e),
        }
    }
}

fn parse_scope(iter: &mut Chars) -> ParseResult<Token> {
    let mut tokens = Vec::new();
    loop {
        let token = parse_expr(iter);
        tokens.push(match token {
            Ok(t) => t,
            Err(e) => {
                match e {
                    ParseError::EndOfQuery => break,
                    _ => return Err(e),
                }
            }
        });
    }
    Ok(Token::Scope(tokens))
}

fn parse_expr(iter: &mut Chars) -> ParseResult<Token> {
    match iter.clone().peekable().peek() {
        Some(c) => {
            return match *c {
                TOKEN_VAR_START => return parse_variable(iter),
                TOKEN_FUNC_NAME_START => return parse_function(iter),
                _ => return parse_text(iter),
            }
        }
        None => return Err(ParseError::EndOfQuery),
    }
}

fn parse_text(iter: &mut Chars) -> ParseResult<Token> {
    let mut text = String::new();

    loop {
        // Peek to check for next expression
        if let Some(peek) = iter.clone().peekable().peek() {
            match *peek {
                TOKEN_VAR_START => break,
                TOKEN_FUNC_PARAM_SEP => break,
                TOKEN_FUNC_NAME_START => break,
                TOKEN_FUNC_PARAM_START => break,
                TOKEN_FUNC_PARAM_END => break,
                _ => (),
            }
        }

        if let Some(next) = iter.next() {
            match next {
                TOKEN_ESCAPE => {
                    text.push(match parse_escape(iter) {
                        Ok(esc) => esc,
                        Err(err) => return Err(err),
                    })
                }
                _ => text.push(next),
            }
        } else {
            // Made it to the end of the string
            break;
        }
    }
    Ok(Token::Text(text))
}

fn parse_escape(iter: &mut Chars) -> ParseResult<char> {
    if let Some(next) = iter.next() {
        Ok(match next {
            'n' => '\n',
            't' => '\t',
            TOKEN_ESCAPE => TOKEN_ESCAPE,
            TOKEN_VAR_START => TOKEN_VAR_START,
            TOKEN_FUNC_NAME_START => TOKEN_FUNC_NAME_START,
            TOKEN_FUNC_PARAM_SEP => TOKEN_FUNC_PARAM_SEP,
            _ => return Err(ParseError::UnknownEscape(format!("\\{}", next))),
        })
    } else {
        Err(ParseError::EscapeAtEndOfQuery)
    }
}

fn parse_variable(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_VAR_START

    let mut name = String::new();
    while let Some(c) = iter.next() {
        match c {
            TOKEN_VAR_END => return Ok(Token::Variable(name)),
            _ => name.push(c),
        };
    }
    Err(ParseError::VariableMissingClosing)
}

fn parse_function(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_FUNC_NAME_START
    let mut name = String::new();
    let mut args = Vec::<Token>::new();

    // get the name of the function
    loop {
        if let Some(c) = iter.next() {
            match c { // TODO: enforce name limits here
                TOKEN_FUNC_PARAM_START => break,
                _ => name.push(c),
            };
        } else {
            return Err(ParseError::FuncMissingParameter);
        }
    }

    // get the parameters of the function
    while let Some(c) = iter.clone().peekable().peek() {
        match *c { // TODO: parse tokens seperated by commas
            TOKEN_FUNC_PARAM_END => {
                let _ = iter.next();
                return Ok(Token::Function(name, args));
            }
            TOKEN_FUNC_PARAM_SEP => {
                let _ = iter.next();
                continue;
            }
            _ => {
                args.push(match parse_expr(iter) {
                    Ok(t) => t,
                    Err(e) => return Err(e),
                })
            }
        }
    }

    Err(ParseError::FuncParameterNotClosed)
}

#[cfg(test)]
mod tests {
    use ::Token::*;
    use ParseError;
    use Query;

    macro_rules! parse_test {
        ($name: ident, $input: expr, $out: expr) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out]));
            }
        };
        ($name: ident, $input: expr, $out: expr, $($more: expr),*) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out $(, $more)*]));
            }
        };
    }

    macro_rules! parse_fail_test {
        ($name: ident, $input: expr, $expt: pat) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned());
                assert!(out.is_err());
                match out {
                    Ok(_) => unreachable!(),
                    Err(e) => match e {
                        $expt => (),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }

    #[test]
    fn parse_empty() {
        let out = Query::parse("".to_owned()).unwrap();
        assert_eq!(out.tokens, Scope(vec![]));
    }

    // Single tokens tests
    parse_test!(parse_variable, "%hello%", Variable("hello".to_owned()));
    parse_test!(parse_text, "hello", Text("hello".to_owned()));
    parse_test!(parse_escape, "\\t", Text("\t".to_owned()));
    parse_test!(parse_func, "$func()", Function("func".to_owned(), vec![]));
    parse_test!(parse_func_param,
                "$func(expr, expr)",
                Function("func".to_owned(),
                         vec![Text("expr".to_owned()), Text(" expr".to_owned())]));

    parse_test!(parse_func_rec_params,
                "$i($f())",
                Function("i".to_owned(), vec![Function("f".to_owned(), vec![])]));

    // Multi token tests
    parse_test!(parse_text_and_variable,
                "Hello %name%",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()));
    parse_test!(parse_text_var_func,
                "Hello %name% $f()",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()),
                Text(" ".to_owned()),
                Function("f".to_owned(), vec![]));

    parse_fail_test!(parse_fail_miss_matched_variable,
                     "%hello",
                     ParseError::VariableMissingClosing);
    parse_fail_test!(parse_fail_unknown_escape, "\\?", ParseError::UnknownEscape(_));

    parse_fail_test!(parse_fail_end_with_escape,
                     "\\",
                     ParseError::EscapeAtEndOfQuery);
    parse_fail_test!(parse_fail_func_no_para,
                     "$func",
                     ParseError::FuncMissingParameter);
    parse_fail_test!(parse_fail_func_no_close_para,
                     "$func(",
                     ParseError::FuncParameterNotClosed);

}
<commit_msg>feat: scope function arguments<commit_after>use Query;
use Token;
use std::str::Chars;

// consts for character representing tokens
const TOKEN_VAR_START: char = '%';
const TOKEN_VAR_END: char = '%';
const TOKEN_FUNC_NAME_START: char = '$';
const TOKEN_FUNC_PARAM_START: char = '(';
const TOKEN_FUNC_PARAM_END: char = ')';
const TOKEN_FUNC_PARAM_SEP: char = ',';
const TOKEN_ESCAPE: char = '\\';

// TODO: Proper error type instead of String
pub type ParseResult<T> = Result<T, ParseError>;

/// Errors found in parsing query
#[derive(Debug)]
pub enum ParseError {
    /// Unknown escape sequence.
    /// String contains the sequece
    UnknownEscape(String),

    /// Escape squence at end of query
    EscapeAtEndOfQuery,

    /// Variable is missing closing character
    VariableMissingClosing,

    /// Function is missing start of parameters
    FuncMissingParameter,

    /// Function parameters is missing closing character
    FuncParameterNotClosed,

    /// End of Query
    EndOfQuery,
}

impl Query {
    pub fn parse(src: String) -> ParseResult<Query> {
        let mut iter = src.chars();
        match parse_scope(&mut iter) {
            Ok(t) => Ok(Query { tokens: t }),
            Err(e) => return Err(e),
        }
    }
}

fn parse_scope(iter: &mut Chars) -> ParseResult<Token> {
    let mut tokens = Vec::new();
    loop {
        let token = match iter.clone().peekable().peek() {
            Some(c) => {
                match *c {
                    TOKEN_VAR_START => parse_variable(iter),
                    TOKEN_FUNC_NAME_START => parse_function(iter),
                    TOKEN_FUNC_PARAM_END | TOKEN_FUNC_PARAM_SEP => break,
                    _ => parse_text(iter),
                }
            }
            None => Err(ParseError::EndOfQuery),
        };

        tokens.push(match token {
            Ok(t) => t,
            Err(e) => {
                match e {
                    ParseError::EndOfQuery => break,
                    _ => return Err(e),
                }
            }
        });
    }
    Ok(Token::Scope(tokens))
}

fn parse_text(iter: &mut Chars) -> ParseResult<Token> {
    let mut text = String::new();

    loop {
        // Peek to check for next expression
        if let Some(peek) = iter.clone().peekable().peek() {
            match *peek {
                TOKEN_VAR_START => break,
                TOKEN_FUNC_PARAM_SEP => break,
                TOKEN_FUNC_NAME_START => break,
                TOKEN_FUNC_PARAM_START => break,
                TOKEN_FUNC_PARAM_END => break,
                _ => (),
            }
        }

        if let Some(next) = iter.next() {
            match next {
                TOKEN_ESCAPE => {
                    text.push(match parse_escape(iter) {
                        Ok(esc) => esc,
                        Err(err) => return Err(err),
                    })
                }
                _ => text.push(next),
            }
        } else {
            // Made it to the end of the string
            break;
        }
    }
    Ok(Token::Text(text))
}

fn parse_escape(iter: &mut Chars) -> ParseResult<char> {
    if let Some(next) = iter.next() {
        Ok(match next {
            'n' => '\n',
            't' => '\t',
            TOKEN_ESCAPE => TOKEN_ESCAPE,
            TOKEN_VAR_START => TOKEN_VAR_START,
            TOKEN_FUNC_NAME_START => TOKEN_FUNC_NAME_START,
            TOKEN_FUNC_PARAM_SEP => TOKEN_FUNC_PARAM_SEP,
            _ => return Err(ParseError::UnknownEscape(format!("\\{}", next))),
        })
    } else {
        Err(ParseError::EscapeAtEndOfQuery)
    }
}

fn parse_variable(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_VAR_START

    let mut name = String::new();
    while let Some(c) = iter.next() {
        match c {
            TOKEN_VAR_END => return Ok(Token::Variable(name)),
            _ => name.push(c),
        };
    }
    Err(ParseError::VariableMissingClosing)
}

fn parse_function(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_FUNC_NAME_START
    let mut name = String::new();
    let mut args = Vec::<Token>::new();

    // get the name of the function
    loop {
        if let Some(c) = iter.next() {
            match c { // TODO: enforce name limits here
                TOKEN_FUNC_PARAM_START => break,
                _ => name.push(c),
            };
        } else {
            return Err(ParseError::FuncMissingParameter);
        }
    }

    // get the parameters of the function
    while let Some(c) = iter.clone().peekable().peek() {
        match *c { // TODO: parse tokens seperated by commas
            TOKEN_FUNC_PARAM_END => {
                let _ = iter.next();
                return Ok(Token::Function(name, args));
            }
            TOKEN_FUNC_PARAM_SEP => {
                let _ = iter.next();
                continue;
            }
            _ => {
                args.push(match parse_scope(iter) {
                    Ok(t) => t,
                    Err(e) => return Err(e),
                })
            }
        }
    }

    Err(ParseError::FuncParameterNotClosed)
}

#[cfg(test)]
mod tests {
    use ::Token::*;
    use ParseError;
    use Query;

    macro_rules! parse_test {
        ($name: ident, $input: expr, $out: expr) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out]));
            }
        };

        ($name: ident, $input: expr, $out: expr, $($more: expr),*) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out $(, $more)*]));
            }
        };
    }

    macro_rules! parse_fail_test {
        ($name: ident, $input: expr, $expt: pat) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned());
                assert!(out.is_err());
                match out {
                    Ok(_) => unreachable!(),
                    Err(e) => match e {
                        $expt => (),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }

    #[test]
    fn parse_empty() {
        let out = Query::parse("".to_owned()).unwrap();
        assert_eq!(out.tokens, Scope(vec![]));
    }

    // Single tokens tests
    parse_test!(parse_variable, "%hello%", Variable("hello".to_owned()));
    parse_test!(parse_text, "hello", Text("hello".to_owned()));
    parse_test!(parse_escape, "\\t", Text("\t".to_owned()));
    parse_test!(parse_func, "$func()", Function("func".to_owned(), vec![]));
    parse_test!(parse_func_param,
                "$func(expr, expr)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())])]));

    parse_test!(parse_func_param_var,
                "$func(expr, expr, %name%)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())]),
                              Scope(vec![Text(" ".to_owned()), Variable("name".to_owned())])]));

    parse_test!(parse_func_rec_params,
                "$i($f())",
                Function("i".to_owned(),
                         vec![Scope(vec![Function("f".to_owned(), vec![])])]));

    // Multi token tests
    parse_test!(parse_text_and_variable,
                "Hello %name%",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()));

    parse_test!(parse_text_var_func,
                "Hello %name% $f()",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()),
                Text(" ".to_owned()),
                Function("f".to_owned(), vec![]));

    parse_fail_test!(parse_fail_miss_matched_variable,
                     "%hello",
                     ParseError::VariableMissingClosing);
    parse_fail_test!(parse_fail_unknown_escape, "\\?", ParseError::UnknownEscape(_));

    parse_fail_test!(parse_fail_end_with_escape,
                     "\\",
                     ParseError::EscapeAtEndOfQuery);
    parse_fail_test!(parse_fail_func_no_para,
                     "$func",
                     ParseError::FuncMissingParameter);
    parse_fail_test!(parse_fail_func_no_close_para,
                     "$func(",
                     ParseError::FuncParameterNotClosed);

}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use regex::Regex;
use std::collections::HashMap;
use lexer;

pub type Token = lexer::Token;
pub type Lexer = lexer::Lexer;

pub struct Parser {
    lexer: Lexer,
    variables: HashMap<String, f64>,
    variable_regex: Regex,
}

impl Parser {
    pub fn new() -> Self {
        Parser{lexer: Lexer::new(), variables: HashMap::new(), variable_regex: Regex::new(r"\A(\w+)=").unwrap()}
    }
    pub fn parse(&mut self, input: String) -> Result<f64, String> {
        let temp = &(input.clone())[..];
        let mut variable: String = String::default();
        if self.variable_regex.is_match(temp) {
            // Unwrapping is safe because the match is known to exist
            // The second element `at(1)`, is the variable name captured by the parenthesis in the regex
            variable = String::from(self.variable_regex.captures(temp).unwrap().at(1).unwrap());
            self.lexer.set_input(self.variable_regex.replace(temp, ""));
        } else {
            self.lexer.set_input(input);
        }
        let expression_value: f64 = match self.expression() {
            Ok(v) => v,
            Err(msg) => return Err(msg)
        };
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        match token.get_kind() {
            lexer::SubToken::End => {
                if variable != String::default() {
                    self.variables.insert(variable, expression_value);
                }
                return Ok(expression_value);
            }
            _ => {
                return Err(String::from("End expected"));
            }
        }
    }
    pub fn expression(&mut self) -> Result<f64, String> {
        let mut component1: f64 = match self.factor() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Plus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 += component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Minus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 -= component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(component1)
    }
    pub fn factor(&mut self) -> Result<f64, String> {
        let mut factor1: f64 = match self.number() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Multiply => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 *= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Divide => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 /= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Power => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1.powf(factor2);
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Modulo => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1 % factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(factor1)
    }
    pub fn number(&mut self) -> Result<f64, String> {
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        let value: f64;
        match token.get_kind() {
            lexer::SubToken::LParen => {
                value = match self.expression() {
                    Ok(v) => v,
                    Err(msg) => return Err(msg)
                };
                match self.lexer.get_next_token() {
                    Err(msg) => return Err(msg),
                    _ => ()
                };
            }
            lexer::SubToken::Number => {
                value = match token.get_value() {
                    Some(v) => v,
                    None => return Err(String::from("No value"))
                };
            }
            lexer::SubToken::Minus => {
                value = match self.factor() {
                    Ok(x) => x*-1.0,
                    Err(msg) => return Err(msg)
                };
            }
            _ => {
                return Err(String::from("Not a number"));
            }
        }
        Ok(value)
    }
}<commit_msg>Support for assigning variables<commit_after>#![allow(dead_code)]

use regex::Regex;
use std::collections::HashMap;
use lexer;

pub type Token = lexer::Token;
pub type Lexer = lexer::Lexer;

pub struct Parser {
    lexer: Lexer,
    variables: HashMap<String, f64>,
}

impl Parser {
    pub fn new() -> Self {
        Parser{lexer: Lexer::new(), variables: HashMap::new()}
    }
    pub fn parse(&mut self, input: String) -> Result<f64, String> {
        lazy_static! {
            static ref VAR_ASSIGN_RE: Regex = Regex::new(r"\A(\w+)=").unwrap();
        }
        let temp = &(input.clone())[..];
        let mut variable: String = String::default();
        if VAR_ASSIGN_RE.is_match(temp) {
            // Unwrapping is safe because the match is known to exist
            // The second element `at(1)`, is the variable name captured by the parenthesis in the regex
            variable = String::from(VAR_ASSIGN_RE.captures(temp).unwrap().at(1).unwrap());
            self.lexer.set_input(VAR_ASSIGN_RE.replace(temp, ""));
        } else {
            self.lexer.set_input(input);
        }
        let expression_value: f64 = match self.expression() {
            Ok(v) => v,
            Err(msg) => return Err(msg)
        };
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        match token.get_kind() {
            lexer::SubToken::End => {
                if variable != String::default() {
                    self.variables.insert(variable, expression_value);
                }
                return Ok(expression_value);
            }
            _ => {
                return Err(String::from("End expected"));
            }
        }
    }
    pub fn expression(&mut self) -> Result<f64, String> {
        let mut component1: f64 = match self.factor() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Plus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 += component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Minus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 -= component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(component1)
    }
    pub fn factor(&mut self) -> Result<f64, String> {
        let mut factor1: f64 = match self.number() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Multiply => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 *= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Divide => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 /= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Power => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1.powf(factor2);
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Modulo => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1 % factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(factor1)
    }
    pub fn number(&mut self) -> Result<f64, String> {
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        let value: f64;
        match token.get_kind() {
            lexer::SubToken::LParen => {
                value = match self.expression() {
                    Ok(v) => v,
                    Err(msg) => return Err(msg)
                };
                match self.lexer.get_next_token() {
                    Err(msg) => return Err(msg),
                    _ => ()
                };
            }
            lexer::SubToken::Number => {
                value = match token.get_value() {
                    Some(v) => v,
                    None => return Err(String::from("No value"))
                };
            }
            lexer::SubToken::Minus => {
                value = match self.factor() {
                    Ok(x) => x*-1.0,
                    Err(msg) => return Err(msg)
                };
            }
            _ => {
                return Err(String::from("Not a number"));
            }
        }
        Ok(value)
    }
}<|endoftext|>


<commit_before>//! The parser is based on the following grammar
//!
//! Expression ==> "let" Name "=" Equation
//!             |  Equation
//!
//! Equation   ==> Product { "+" Product }
//!             |  Product { "-" Product }
//!
//! Product    ==> Factor { "*" Factor }
//!             |  Factor { "/" Factor }
//!
//! Factor     ==> "-" Factor
//!             |  Exponent { "^" Factor }
//!
//! Exponent   ==> Number { "!" }
//!
//! Number     ==> Function "(" Equation ")"
//!             |  Constant
//!             |  Name
//!             |  "ans"
//!             |  "(" Equation ")"
//!             |  "|" Equation "|"
//!             |  NumLiteral
//!
//! Function   ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "abs" | "exp"
//!             |  "ln" | "log"
//!
//! Constant   ==> "pi" | "e" | "phi"

use std::vec::IntoIter;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use ast::Ast;
use ast::AstVal;
use ast::AstBranch::*;
use ast::FuncKind::*;
use ast::ConstKind::*;
use ast::OpKind::*;
use token::Token;
use token::TokVal;
use token::TokVal::*;
use token::KeywordKind::*;

pub fn parse_tokens(tokens: Vec<Token>) -> CalcrResult<Ast> {
    let end_pos = tokens.last().and_then(|tok| Some(tok.span.1)).unwrap_or(0);
    let mut parser = Parser {
        iter: tokens.into_iter().peekable(),
        paren_level: 0,
        abs_level: 0,
        end_pos: end_pos,
    };
    parser.parse_expression()
}

fn get_builtin_name(name: &String) -> Option<AstVal> {
    match name.as_ref() {
        "ans" => Some(AstVal::LastResult),
        "pi" | "π" => Some(AstVal::Const(Pi)),
        "e" => Some(AstVal::Const(E)),
        "phi" | "ϕ" => Some(AstVal::Const(Phi)),
        "cos" => Some(AstVal::Func(Cos)),
        "sin" => Some(AstVal::Func(Sin)),
        "tan" => Some(AstVal::Func(Tan)),
        "asin" => Some(AstVal::Func(Asin)),
        "acos" => Some(AstVal::Func(Acos)),
        "atan" => Some(AstVal::Func(Atan)),
        "sqrt" | "√" => Some(AstVal::Func(Sqrt)),
        "abs" => Some(AstVal::Func(Abs)),
        "exp" => Some(AstVal::Func(Exp)),
        "ln" => Some(AstVal::Func(Ln)),
        "log" => Some(AstVal::Func(Log)),
        _ => None
    }
}

pub struct Parser {
    iter: Peekable<IntoIter<Token>>,
    paren_level: u32,
    abs_level: u32,
    end_pos: usize,
}

impl Parser {
    fn parse_expression(&mut self) -> CalcrResult<Ast> {
        if self.next_tok_is(Keyword(Let)) {
            self.consume_tok();
            if !self.toks_empty() {
                let Token { val: tok_val, span: tok_span } = self.consume_tok();
                match tok_val {
                    Name(ref name) if get_builtin_name(name).is_none() => {
                        if self.next_tok_is(Op(Assign)) {
                            let assign_tok = self.consume_tok();
                            let eq = try!(self.parse_equation());
                            let name_ast = Ast {
                                val: AstVal::Name(name.clone()),
                                span: tok_span,
                                branches: Leaf,
                            };
                            Ok(Ast {
                                val: AstVal::Op(Assign),
                                span: assign_tok.span,
                                branches: Binary(Box::new(name_ast), Box::new(eq)),
                            })
                        } else {
                            Err(CalcrError {
                                desc: "Expected assignment operator '=' after name".to_string(),
                                span: Some(tok_span),
                            })
                        }
                    },
                    Name(ref name) => Err(CalcrError {
                        desc: format!("Cannot assign to builtin name '{}'", name),
                        span: Some(tok_span),
                    }),
                    _ => Err(CalcrError {
                        desc: "Expected name to assign to".to_string(),
                        span: Some(tok_span),
                    }),
                }
            } else {
                Err(CalcrError {
                    desc: "Expected name to assign to".to_string(),
                    span: Some((self.end_pos, self.end_pos)),
                })
            }

        } else {
            self.parse_equation()
        }
    }

    fn parse_equation(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_product());
        while self.next_tok_matches(|val| *val == Op(Plus) || *val == Op(Minus)) {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            let rhs = try!(self.parse_product());
            lhs = Ast {
                val: AstVal::Op(tok_val.op().unwrap()),
                span: tok_span,
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            }
        }
        if self.next_tok_is(ParenClose) && self.paren_level < 1 {
            let Token { val: _, span: tok_span } = self.consume_tok();
            Err(CalcrError {
                desc: format!("Missing opening parentheses"),
                span: Some(tok_span),
            })
        } else if self.next_tok_is(AbsDelim) && self.abs_level < 1 {
            let Token { val: _, span: tok_span } = self.consume_tok();
            Err(CalcrError {
                desc: format!("Missing opening abs delimiter"),
                span: Some(tok_span),
            })
        } else {
            Ok(lhs)
        }
    }

    fn parse_product(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        while self.next_tok_matches(|val| *val == Op(Mult) || *val == Op(Div)) {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: AstVal::Op(tok_val.op().unwrap()),
                span: tok_span,
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CalcrResult<Ast> {
        // when we lex we only store `Minus`s since we do not have any context there,
        // however we know if we see a `Minus` now, then it is a `Neg`.
        if self.next_tok_is(Op(Minus)) {
            let tok_span = self.consume_tok().span;
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: AstVal::Op(Neg),
                span: tok_span,
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.next_tok_is(Op(Pow)) {
                let tok_span = self.consume_tok().span;
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: AstVal::Op(Pow),
                    span: tok_span,
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CalcrResult<Ast> {
        let mut out = try!(self.parse_number());

        while self.next_tok_is(Op(Fact)) {
            let tok_span = self.consume_tok().span;
            out = Ast {
                val: AstVal::Op(Fact),
                span: tok_span,
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CalcrResult<Ast> {
        if self.toks_empty() {
            Err(CalcrError {
                desc: format!("Expected number or constant"),
                span: Some((self.end_pos, self.end_pos)),
            })
        } else {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            match tok_val {
                Name(ref name) => {
                    let val = match get_builtin_name(name) {
                        Some(val) => val,
                        None => AstVal::Name(name.clone()),
                    };
                    if let AstVal::Func(_) = val {
                        // it's a function so we need to grab its argument
                        if self.next_tok_is(ParenOpen) {
                            // since we know the next token is an open paren, we use
                            // this function to get its AST
                            let arg = try!(self.parse_equation());
                            Ok(Ast {
                                val: val,
                                span: tok_span,
                                branches: Unary(Box::new(arg)),
                            })
                        } else {
                            Err(CalcrError {
                                desc: "Missing opening parentheses after function".to_string(),
                                span: Some(tok_span),
                            })
                        }
                    } else {
                        Ok(Ast {
                            val: val,
                            span: tok_span,
                            branches: Leaf,
                        })
                    }
                },
                ParenOpen => {
                    self.paren_level += 1;
                    let eq = try!(self.parse_equation());
                    if !self.next_tok_is(ParenClose) {
                        Err(CalcrError {
                            desc: "Missing closing parentheses".to_string(),
                            span: Some(tok_span),
                        })
                    } else {
                        self.paren_level -= 1;
                        let close_paren_span = self.consume_tok().span;
                        Ok(Ast {
                            val: AstVal::Paren,
                            span: (tok_span.0, close_paren_span.1),
                            branches: Unary(Box::new(eq)),
                        })
                    }
                },
                AbsDelim => {
                    self.abs_level += 1;
                    let eq = try!(self.parse_equation());
                    if !self.next_tok_is(AbsDelim) {
                        Err(CalcrError {
                            desc: "Missing closing abs delimiter".to_string(),
                            span: Some(tok_span),
                        })
                    } else {
                        self.abs_level -= 1;
                        let close_delim_span = self.consume_tok().span;
                        Ok(Ast {
                            val: AstVal::Func(Abs),
                            span: (tok_span.0, close_delim_span.1),
                            branches: Unary(Box::new(eq)),
                        })
                    }
                },
                Num(num) => {
                    Ok(Ast {
                        val: AstVal::Num(num),
                        span: tok_span,
                        branches: Leaf,
                    })
                },
                _ => Err(CalcrError {
                    desc: format!("Expected number or constant"),
                    span: Some(tok_span),
                }),
            }
        }
    }

    /// Peeks at the next token and check whether its values is equal to `val`
    fn next_tok_is(&mut self, val: TokVal) -> bool {
        self.next_tok_matches(|v| *v == val)
    }

    /// Peeks at the next token and checks whether its value makes `pred` true
    fn next_tok_matches<F>(&mut self, pred: F) -> bool where F: FnOnce(&TokVal) -> bool {
        self.iter.peek().map_or(false, |ref tok| pred(&tok.val))
    }

    /// Checks if we have run out of `Token`s to parse
    fn toks_empty(&mut self) -> bool {
        self.iter.peek().is_none()
    }

    /// Consumes a `Token` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more `Token`s to consume
    fn consume_tok(&mut self) -> Token {
        let tok = self.iter.next();
        tok.unwrap()
    }
}<commit_msg>Add some tests to the parser<commit_after>//! The parser is based on the following grammar
//!
//! Expression ==> "let" Name "=" Equation
//!             |  Equation
//!
//! Equation   ==> Product { "+" Product }
//!             |  Product { "-" Product }
//!
//! Product    ==> Factor { "*" Factor }
//!             |  Factor { "/" Factor }
//!
//! Factor     ==> "-" Factor
//!             |  Exponent { "^" Factor }
//!
//! Exponent   ==> Number { "!" }
//!
//! Number     ==> Function "(" Equation ")"
//!             |  Constant
//!             |  Name
//!             |  "ans"
//!             |  "(" Equation ")"
//!             |  "|" Equation "|"
//!             |  NumLiteral
//!
//! Function   ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "abs" | "exp"
//!             |  "ln" | "log"
//!
//! Constant   ==> "pi" | "e" | "phi"

use std::vec::IntoIter;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use ast::Ast;
use ast::AstVal;
use ast::AstBranch::*;
use ast::FuncKind::*;
use ast::ConstKind::*;
use ast::OpKind::*;
use token::Token;
use token::TokVal;
use token::TokVal::*;
use token::KeywordKind::*;

pub fn parse_tokens(tokens: Vec<Token>) -> CalcrResult<Ast> {
    let end_pos = tokens.last().and_then(|tok| Some(tok.span.1)).unwrap_or(0);
    let mut parser = Parser {
        iter: tokens.into_iter().peekable(),
        paren_level: 0,
        abs_level: 0,
        end_pos: end_pos,
    };
    parser.parse_expression()
}

fn get_builtin_name(name: &String) -> Option<AstVal> {
    match name.as_ref() {
        "ans" => Some(AstVal::LastResult),
        "pi" | "π" => Some(AstVal::Const(Pi)),
        "e" => Some(AstVal::Const(E)),
        "phi" | "ϕ" => Some(AstVal::Const(Phi)),
        "cos" => Some(AstVal::Func(Cos)),
        "sin" => Some(AstVal::Func(Sin)),
        "tan" => Some(AstVal::Func(Tan)),
        "asin" => Some(AstVal::Func(Asin)),
        "acos" => Some(AstVal::Func(Acos)),
        "atan" => Some(AstVal::Func(Atan)),
        "sqrt" | "√" => Some(AstVal::Func(Sqrt)),
        "abs" => Some(AstVal::Func(Abs)),
        "exp" => Some(AstVal::Func(Exp)),
        "ln" => Some(AstVal::Func(Ln)),
        "log" => Some(AstVal::Func(Log)),
        _ => None
    }
}

pub struct Parser {
    iter: Peekable<IntoIter<Token>>,
    paren_level: u32,
    abs_level: u32,
    end_pos: usize,
}

impl Parser {
    fn parse_expression(&mut self) -> CalcrResult<Ast> {
        if self.next_tok_is(Keyword(Let)) {
            self.consume_tok();
            if !self.toks_empty() {
                let Token { val: tok_val, span: tok_span } = self.consume_tok();
                match tok_val {
                    Name(ref name) if get_builtin_name(name).is_none() => {
                        if self.next_tok_is(Op(Assign)) {
                            let assign_tok = self.consume_tok();
                            let eq = try!(self.parse_equation());
                            let name_ast = Ast {
                                val: AstVal::Name(name.clone()),
                                span: tok_span,
                                branches: Leaf,
                            };
                            Ok(Ast {
                                val: AstVal::Op(Assign),
                                span: assign_tok.span,
                                branches: Binary(Box::new(name_ast), Box::new(eq)),
                            })
                        } else {
                            Err(CalcrError {
                                desc: "Expected assignment operator '=' after name".to_string(),
                                span: Some(tok_span),
                            })
                        }
                    },
                    Name(ref name) => Err(CalcrError {
                        desc: format!("Cannot assign to builtin name '{}'", name),
                        span: Some(tok_span),
                    }),
                    _ => Err(CalcrError {
                        desc: "Expected name to assign to".to_string(),
                        span: Some(tok_span),
                    }),
                }
            } else {
                Err(CalcrError {
                    desc: "Expected name to assign to".to_string(),
                    span: Some((self.end_pos, self.end_pos)),
                })
            }

        } else {
            self.parse_equation()
        }
    }

    fn parse_equation(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_product());
        while self.next_tok_matches(|val| *val == Op(Plus) || *val == Op(Minus)) {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            let rhs = try!(self.parse_product());
            lhs = Ast {
                val: AstVal::Op(tok_val.op().unwrap()),
                span: tok_span,
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            }
        }
        if self.next_tok_is(ParenClose) && self.paren_level < 1 {
            let Token { val: _, span: tok_span } = self.consume_tok();
            Err(CalcrError {
                desc: format!("Missing opening parentheses"),
                span: Some(tok_span),
            })
        } else if self.next_tok_is(AbsDelim) && self.abs_level < 1 {
            let Token { val: _, span: tok_span } = self.consume_tok();
            Err(CalcrError {
                desc: format!("Missing opening abs delimiter"),
                span: Some(tok_span),
            })
        } else {
            Ok(lhs)
        }
    }

    fn parse_product(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        while self.next_tok_matches(|val| *val == Op(Mult) || *val == Op(Div)) {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: AstVal::Op(tok_val.op().unwrap()),
                span: tok_span,
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CalcrResult<Ast> {
        // when we lex we only store `Minus`s since we do not have any context there,
        // however we know if we see a `Minus` now, then it is a `Neg`.
        if self.next_tok_is(Op(Minus)) {
            let tok_span = self.consume_tok().span;
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: AstVal::Op(Neg),
                span: tok_span,
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.next_tok_is(Op(Pow)) {
                let tok_span = self.consume_tok().span;
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: AstVal::Op(Pow),
                    span: tok_span,
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CalcrResult<Ast> {
        let mut out = try!(self.parse_number());

        while self.next_tok_is(Op(Fact)) {
            let tok_span = self.consume_tok().span;
            out = Ast {
                val: AstVal::Op(Fact),
                span: tok_span,
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CalcrResult<Ast> {
        if self.toks_empty() {
            Err(CalcrError {
                desc: format!("Expected number or constant"),
                span: Some((self.end_pos, self.end_pos)),
            })
        } else {
            let Token { val: tok_val, span: tok_span } = self.consume_tok();
            match tok_val {
                Name(ref name) => {
                    let val = match get_builtin_name(name) {
                        Some(val) => val,
                        None => AstVal::Name(name.clone()),
                    };
                    if let AstVal::Func(_) = val {
                        // it's a function so we need to grab its argument
                        if self.next_tok_is(ParenOpen) {
                            // since we know the next token is an open paren, we use
                            // this function to get its AST
                            let arg = try!(self.parse_equation());
                            Ok(Ast {
                                val: val,
                                span: tok_span,
                                branches: Unary(Box::new(arg)),
                            })
                        } else {
                            Err(CalcrError {
                                desc: "Missing opening parentheses after function".to_string(),
                                span: Some(tok_span),
                            })
                        }
                    } else {
                        Ok(Ast {
                            val: val,
                            span: tok_span,
                            branches: Leaf,
                        })
                    }
                },
                ParenOpen => {
                    self.paren_level += 1;
                    let eq = try!(self.parse_equation());
                    if !self.next_tok_is(ParenClose) {
                        Err(CalcrError {
                            desc: "Missing closing parentheses".to_string(),
                            span: Some(tok_span),
                        })
                    } else {
                        self.paren_level -= 1;
                        let close_paren_span = self.consume_tok().span;
                        Ok(Ast {
                            val: AstVal::Paren,
                            span: (tok_span.0, close_paren_span.1),
                            branches: Unary(Box::new(eq)),
                        })
                    }
                },
                AbsDelim => {
                    self.abs_level += 1;
                    let eq = try!(self.parse_equation());
                    if !self.next_tok_is(AbsDelim) {
                        Err(CalcrError {
                            desc: "Missing closing abs delimiter".to_string(),
                            span: Some(tok_span),
                        })
                    } else {
                        self.abs_level -= 1;
                        let close_delim_span = self.consume_tok().span;
                        Ok(Ast {
                            val: AstVal::Func(Abs),
                            span: (tok_span.0, close_delim_span.1),
                            branches: Unary(Box::new(eq)),
                        })
                    }
                },
                Num(num) => {
                    Ok(Ast {
                        val: AstVal::Num(num),
                        span: tok_span,
                        branches: Leaf,
                    })
                },
                _ => Err(CalcrError {
                    desc: format!("Expected number or constant"),
                    span: Some(tok_span),
                }),
            }
        }
    }

    /// Peeks at the next token and check whether its values is equal to `val`
    fn next_tok_is(&mut self, val: TokVal) -> bool {
        self.next_tok_matches(|v| *v == val)
    }

    /// Peeks at the next token and checks whether its value makes `pred` true
    fn next_tok_matches<F>(&mut self, pred: F) -> bool where F: FnOnce(&TokVal) -> bool {
        self.iter.peek().map_or(false, |ref tok| pred(&tok.val))
    }

    /// Checks if we have run out of `Token`s to parse
    fn toks_empty(&mut self) -> bool {
        self.iter.peek().is_none()
    }

    /// Consumes a `Token` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more `Token`s to consume
    fn consume_tok(&mut self) -> Token {
        let tok = self.iter.next();
        tok.unwrap()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use token::Token;
    use token::TokVal;
    use ast::Ast;
    use ast::AstVal;
    use ast::AstBranch;
    use ast::ConstKind::*;

    #[test]
    fn single_num() {
        let toks = vec!(Token { val: TokVal::Num(2.0), span: (0, 1) });
        let ast = parse_equation(toks);
        assert_eq!(ast, Ok(Ast { val: AstVal::Num(2.0), span: (0, 1), branches: AstBranch::Leaf }));
    }

    #[test]
    fn constants() {
        assert_eq!(parse_equation(vec!(Token { val: TokVal::Name("pi".to_string()), span: (0, 2)})),
                   Ok(Ast { val: AstVal::Const(Pi), span: (0, 2), branches: AstBranch::Leaf }));

        assert_eq!(parse_equation(vec!(Token { val: TokVal::Name("π".to_string()), span: (0, 1)})),
                   Ok(Ast { val: AstVal::Const(Pi), span: (0, 1), branches: AstBranch::Leaf }));

        assert_eq!(parse_equation(vec!(Token { val: TokVal::Name("e".to_string()), span: (0, 1)})),
                   Ok(Ast { val: AstVal::Const(E), span: (0, 1), branches: AstBranch::Leaf }));

        assert_eq!(parse_equation(vec!(Token { val: TokVal::Name("phi".to_string()), span: (0, 3)})),
                   Ok(Ast { val: AstVal::Const(Phi), span: (0, 3), branches: AstBranch::Leaf }));

        assert_eq!(parse_equation(vec!(Token { val: TokVal::Name("ϕ".to_string()), span: (0, 1)})),
                   Ok(Ast { val: AstVal::Const(Phi), span: (0, 1), branches: AstBranch::Leaf }));
    }

    #[test]
    fn empty() {
        let toks = vec!();
        let err = parse_equation(toks);
        assert!(err.is_err());
    }
}<|endoftext|>


<commit_before>#![allow(clippy::cast_lossless)]

use crate::{sector::Sector, World};
use calx::{
    compact_bits_by_2, hex_neighbors, spread_bits_by_2, CellSpace, CellVector, Dir6, GridNode,
    HexGeom, ProjectVec,
};
use euclid::{vec2, Vector2D};
use serde_derive::{Deserialize, Serialize};
use std::num::Wrapping;
use std::ops::{Add, Sub};

/// Unambiguous location in the game world.
#[derive(
    Copy, Eq, PartialEq, Clone, Hash, PartialOrd, Ord, Debug, Default, Serialize, Deserialize,
)]
pub struct Location {
    pub x: i16,
    pub y: i16,
    pub z: i16,
}

/// The type for a unique location in the game world.
///
/// IMPORTANT: Be careful where you use the simple "location + vec" algebra. That does not take
/// portals into account, and will usually cause unwanted effects near them in high-level code.
/// Most high-level logic should use `Location::jump` to displace locations. This will correctly
/// traverse portals.
impl Location {
    pub fn origin() -> Location { Location { x: 0, y: 0, z: 0 } }

    pub fn new(x: i16, y: i16, z: i16) -> Location { Location { x, y, z } }

    /// Construct a Location from a Morton code representation.
    ///
    /// Use the representation generated with `to_morton`. The odd bits of the low 32 bits are
    /// compacted to x value, the even bits of the low 32 bits to y and the first 16 of the high 32
    /// bits become z.
    pub fn from_morton(morton_code: u64) -> Location {
        let xy = (morton_code & 0xffff_ffff) as u32;
        let x = compact_bits_by_2(xy) as u16;
        let y = compact_bits_by_2(xy >> 1) as u16;
        let z = (morton_code >> 32) as u16;

        unsafe {
            Location {
                x: ::std::mem::transmute(x),
                y: ::std::mem::transmute(y),
                z: ::std::mem::transmute(z),
            }
        }
    }

    /// Turn the Location to a Morton code value.
    ///
    /// Spatially close locations are often numerically close in Morton codes, these are useful for
    /// quadtree-like structures.
    pub fn to_morton(self) -> u64 {
        let mut ret = 0;
        let x: u16 = unsafe { ::std::mem::transmute(self.x) };
        let y: u16 = unsafe { ::std::mem::transmute(self.y) };
        let z: u16 = unsafe { ::std::mem::transmute(self.z) };
        ret ^= spread_bits_by_2(x as u32) as u64;
        ret ^= (spread_bits_by_2(y as u32) << 1) as u64;
        ret ^= (z as u64) << 32;
        ret
    }

    /// Vector pointing from this location into the other one if the locations
    /// are on the same Euclidean plane.
    pub fn v2_at(self, other: Location) -> Option<CellVector> {
        if self.z != other.z {
            return None;
        }
        Some(vec2(other.x as i32, other.y as i32) - vec2(self.x as i32, self.y as i32))
    }

    /// Hex distance from this location to the other one, if applicable.
    pub fn distance_from(self, other: Location) -> Option<i32> {
        if let Some(v) = self.v2_at(other) {
            Some(v.hex_dist())
        } else {
            None
        }
    }

    /// Distance that defaults to max integer value for separate zones.
    ///
    /// Can be used for situations that want a straightforward metric function like A* search.
    pub fn metric_distance(self, other: Location) -> i32 {
        self.distance_from(other).unwrap_or(i32::max_value())
    }

    pub fn dir6_towards(self, other: Location) -> Option<Dir6> {
        if let Some(v) = self.v2_at(other) {
            Some(Dir6::from_v2(v))
        } else {
            None
        }
    }

    /// Offset location and follow any portals in target site.
    pub fn jump<V: Into<CellVector> + Sized>(self, ctx: &World, offset: V) -> Location {
        let loc = self + offset.into();
        ctx.portal(loc).unwrap_or(loc)
    }

    /// True for a one-cell wide border region between sectors
    pub fn on_sector_border(self) -> bool {
        let sec = Sector::from(self);
        // Only test along three adjacent directions. This way we get a 1-cell wide border
        // everywhere. Testing the full circle would produce a 2-cell wide border.
        hex_neighbors(self)
            .take(3)
            .map(Sector::from)
            .any(|s| s != sec)
    }

    /// Smooth noise offset for determinining overland cell boundaries at this location.
    pub fn terrain_cell_displacement(self) -> CellVector {
        use lazy_static::lazy_static;
        use noise::NoiseFn;
        lazy_static! {
            static ref NOISE: noise::OpenSimplex = noise::OpenSimplex::new();
        }

        let (dx, dy) = {
            const ZOOM: f64 = 1.0 / 2.0;
            const SCALE: f64 = 4.0;
            let (x, y) = (self.x as f64 * ZOOM, self.y as f64 * ZOOM);
            // Use 3D hex coordinates to get a symmetric kernel.
            // Sample the different components from different places in the noise plane.
            let dx = SCALE * NOISE.get([x, y]);
            let dy = SCALE * NOISE.get([x + 6553.0, y + 9203.0]);
            let dz = SCALE * NOISE.get([x + 9203.0, y + 6553.0]);
            (dx + dz, dy + dz)
        };
        vec2(dx.round() as i32, dy.round() as i32)
    }
}

impl From<Location> for CellVector {
    fn from(loc: Location) -> Self { vec2(loc.x as i32, loc.y as i32) }
}

impl From<Sector> for Location {
    fn from(sec: Sector) -> Self {
        Location::new(0, 0, sec.z) + Vector2D::from(sec).project::<CellSpace>()
    }
}

impl<V: Into<CellVector>> Add<V> for Location {
    type Output = Location;
    fn add(self, other: V) -> Location {
        let other = other.into();
        Location {
            x: (self.x as i32 + other.x) as i16,
            y: (self.y as i32 + other.y) as i16,
            z: self.z,
        }
    }
}

impl Add<Portal> for Location {
    type Output = Location;
    fn add(self, other: Portal) -> Location {
        Location {
            x: (Wrapping(self.x) + Wrapping(other.dx)).0,
            y: (Wrapping(self.y) + Wrapping(other.dy)).0,
            z: other.z,
        }
    }
}

impl<V: Into<CellVector>> Sub<V> for Location {
    type Output = Location;
    fn sub(self, other: V) -> Location {
        let other = other.into();
        Location {
            x: (self.x as i32 - other.x) as i16,
            y: (self.y as i32 - other.y) as i16,
            z: self.z,
        }
    }
}

impl GridNode for Location {
    fn neighbors(&self) -> Vec<Location> { hex_neighbors(*self).collect() }
}

#[derive(Copy, Eq, PartialEq, Clone, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
pub struct Portal {
    pub dx: i16,
    pub dy: i16,
    pub z: i16,
}

impl Portal {
    pub fn new(from: Location, to: Location) -> Portal {
        Portal {
            dx: (Wrapping(to.x) - Wrapping(from.x)).0,
            dy: (Wrapping(to.y) - Wrapping(from.y)).0,
            z: to.z,
        }
    }
}

impl Add<Portal> for Portal {
    type Output = Portal;
    fn add(self, other: Portal) -> Portal {
        Portal {
            dx: (Wrapping(self.dx) + Wrapping(other.dx)).0,
            dy: (Wrapping(self.dy) + Wrapping(other.dy)).0,
            z: other.z,
        }
    }
}

#[cfg(test)]
mod test {
    use super::Location;
    use crate::sector::Sector;
    use calx::{CellSpace, CellVector, ProjectVec, StaggeredHexSpace};
    use euclid::vec2;

    #[test]
    fn test_wraparound() {
        let l1 = Location::new(0, 0, 0);
        let l2 = l1 + vec2(66000, 66000);
        assert_eq!((464, 464), (l2.x, l2.y));
    }

    #[test]
    fn test_morton() {
        use rand::Rng;
        let mut rng = rand::thread_rng();

        for _ in 0..1000 {
            let x = rng.gen::<u64>() & 0xffff_ffff_ffff;
            assert_eq!(x, Location::from_morton(x).to_morton());
        }
    }

    #[test]
    fn test_location_to_sector() {
        // Sector division near origin
        assert_eq!(Sector::from(Location::new(0, 0, 0)), Sector::new(0, 0, 0));
        assert_eq!(Sector::from(Location::new(0, 1, 0)), Sector::new(-1, 0, 0));
        assert_eq!(
            Sector::from(Location::new(-1, 0, 0)),
            Sector::new(-1, -1, 0)
        );

        for y in -100..100 {
            for x in -100..100 {
                let loc = Location::new(x, y, 0);
                let vec = CellVector::from(loc);
                assert_eq!(
                    vec,
                    vec.project::<StaggeredHexSpace>().project::<CellSpace>()
                );

                assert!(
                    Sector::from(loc).iter().find(|&x| x == loc).is_some(),
                    format!("{:?} not found in sector {:?}", loc, Sector::from(loc))
                );
            }
        }
    }

    #[test]
    fn test_sector_iter() {
        let s = Sector::new(0, 0, 0);

        for loc in s.iter() {
            assert_eq!(s, Sector::from(loc), "Location: {:?}", loc);
        }
    }
}
<commit_msg>Compact Location serialization<commit_after>#![allow(clippy::cast_lossless)]

use crate::{sector::Sector, World};
use calx::{
    compact_bits_by_2, hex_neighbors, spread_bits_by_2, CellSpace, CellVector, Dir6, GridNode,
    HexGeom, ProjectVec,
};
use euclid::{vec2, Vector2D};
use serde_derive::{Deserialize, Serialize};
use std::num::Wrapping;
use std::ops::{Add, Sub};

/// Unambiguous location in the game world.
#[derive(Copy, Eq, PartialEq, Clone, Hash, PartialOrd, Ord, Debug, Default)]
pub struct Location {
    pub x: i16,
    pub y: i16,
    pub z: i16,
}

impl serde::Serialize for Location {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        (self.x, self.y, self.z).serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Location {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        let (x, y, z): (i16, i16, i16) = serde::Deserialize::deserialize(d)?;
        Ok(Location { x, y, z })
    }
}

/// The type for a unique location in the game world.
///
/// IMPORTANT: Be careful where you use the simple "location + vec" algebra. That does not take
/// portals into account, and will usually cause unwanted effects near them in high-level code.
/// Most high-level logic should use `Location::jump` to displace locations. This will correctly
/// traverse portals.
impl Location {
    pub fn origin() -> Location { Location { x: 0, y: 0, z: 0 } }

    pub fn new(x: i16, y: i16, z: i16) -> Location { Location { x, y, z } }

    /// Construct a Location from a Morton code representation.
    ///
    /// Use the representation generated with `to_morton`. The odd bits of the low 32 bits are
    /// compacted to x value, the even bits of the low 32 bits to y and the first 16 of the high 32
    /// bits become z.
    pub fn from_morton(morton_code: u64) -> Location {
        let xy = (morton_code & 0xffff_ffff) as u32;
        let x = compact_bits_by_2(xy) as u16;
        let y = compact_bits_by_2(xy >> 1) as u16;
        let z = (morton_code >> 32) as u16;

        unsafe {
            Location {
                x: ::std::mem::transmute(x),
                y: ::std::mem::transmute(y),
                z: ::std::mem::transmute(z),
            }
        }
    }

    /// Turn the Location to a Morton code value.
    ///
    /// Spatially close locations are often numerically close in Morton codes, these are useful for
    /// quadtree-like structures.
    pub fn to_morton(self) -> u64 {
        let mut ret = 0;
        let x: u16 = unsafe { ::std::mem::transmute(self.x) };
        let y: u16 = unsafe { ::std::mem::transmute(self.y) };
        let z: u16 = unsafe { ::std::mem::transmute(self.z) };
        ret ^= spread_bits_by_2(x as u32) as u64;
        ret ^= (spread_bits_by_2(y as u32) << 1) as u64;
        ret ^= (z as u64) << 32;
        ret
    }

    /// Vector pointing from this location into the other one if the locations
    /// are on the same Euclidean plane.
    pub fn v2_at(self, other: Location) -> Option<CellVector> {
        if self.z != other.z {
            return None;
        }
        Some(vec2(other.x as i32, other.y as i32) - vec2(self.x as i32, self.y as i32))
    }

    /// Hex distance from this location to the other one, if applicable.
    pub fn distance_from(self, other: Location) -> Option<i32> {
        if let Some(v) = self.v2_at(other) {
            Some(v.hex_dist())
        } else {
            None
        }
    }

    /// Distance that defaults to max integer value for separate zones.
    ///
    /// Can be used for situations that want a straightforward metric function like A* search.
    pub fn metric_distance(self, other: Location) -> i32 {
        self.distance_from(other).unwrap_or(i32::max_value())
    }

    pub fn dir6_towards(self, other: Location) -> Option<Dir6> {
        if let Some(v) = self.v2_at(other) {
            Some(Dir6::from_v2(v))
        } else {
            None
        }
    }

    /// Offset location and follow any portals in target site.
    pub fn jump<V: Into<CellVector> + Sized>(self, ctx: &World, offset: V) -> Location {
        let loc = self + offset.into();
        ctx.portal(loc).unwrap_or(loc)
    }

    /// True for a one-cell wide border region between sectors
    pub fn on_sector_border(self) -> bool {
        let sec = Sector::from(self);
        // Only test along three adjacent directions. This way we get a 1-cell wide border
        // everywhere. Testing the full circle would produce a 2-cell wide border.
        hex_neighbors(self)
            .take(3)
            .map(Sector::from)
            .any(|s| s != sec)
    }

    /// Smooth noise offset for determinining overland cell boundaries at this location.
    pub fn terrain_cell_displacement(self) -> CellVector {
        use lazy_static::lazy_static;
        use noise::NoiseFn;
        lazy_static! {
            static ref NOISE: noise::OpenSimplex = noise::OpenSimplex::new();
        }

        let (dx, dy) = {
            const ZOOM: f64 = 1.0 / 2.0;
            const SCALE: f64 = 4.0;
            let (x, y) = (self.x as f64 * ZOOM, self.y as f64 * ZOOM);
            // Use 3D hex coordinates to get a symmetric kernel.
            // Sample the different components from different places in the noise plane.
            let dx = SCALE * NOISE.get([x, y]);
            let dy = SCALE * NOISE.get([x + 6553.0, y + 9203.0]);
            let dz = SCALE * NOISE.get([x + 9203.0, y + 6553.0]);
            (dx + dz, dy + dz)
        };
        vec2(dx.round() as i32, dy.round() as i32)
    }
}

impl From<Location> for CellVector {
    fn from(loc: Location) -> Self { vec2(loc.x as i32, loc.y as i32) }
}

impl From<Sector> for Location {
    fn from(sec: Sector) -> Self {
        Location::new(0, 0, sec.z) + Vector2D::from(sec).project::<CellSpace>()
    }
}

impl<V: Into<CellVector>> Add<V> for Location {
    type Output = Location;
    fn add(self, other: V) -> Location {
        let other = other.into();
        Location {
            x: (self.x as i32 + other.x) as i16,
            y: (self.y as i32 + other.y) as i16,
            z: self.z,
        }
    }
}

impl Add<Portal> for Location {
    type Output = Location;
    fn add(self, other: Portal) -> Location {
        Location {
            x: (Wrapping(self.x) + Wrapping(other.dx)).0,
            y: (Wrapping(self.y) + Wrapping(other.dy)).0,
            z: other.z,
        }
    }
}

impl<V: Into<CellVector>> Sub<V> for Location {
    type Output = Location;
    fn sub(self, other: V) -> Location {
        let other = other.into();
        Location {
            x: (self.x as i32 - other.x) as i16,
            y: (self.y as i32 - other.y) as i16,
            z: self.z,
        }
    }
}

impl GridNode for Location {
    fn neighbors(&self) -> Vec<Location> { hex_neighbors(*self).collect() }
}

#[derive(Copy, Eq, PartialEq, Clone, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
pub struct Portal {
    pub dx: i16,
    pub dy: i16,
    pub z: i16,
}

impl Portal {
    pub fn new(from: Location, to: Location) -> Portal {
        Portal {
            dx: (Wrapping(to.x) - Wrapping(from.x)).0,
            dy: (Wrapping(to.y) - Wrapping(from.y)).0,
            z: to.z,
        }
    }
}

impl Add<Portal> for Portal {
    type Output = Portal;
    fn add(self, other: Portal) -> Portal {
        Portal {
            dx: (Wrapping(self.dx) + Wrapping(other.dx)).0,
            dy: (Wrapping(self.dy) + Wrapping(other.dy)).0,
            z: other.z,
        }
    }
}

#[cfg(test)]
mod test {
    use super::Location;
    use crate::sector::Sector;
    use calx::{CellSpace, CellVector, ProjectVec, StaggeredHexSpace};
    use euclid::vec2;

    #[test]
    fn test_wraparound() {
        let l1 = Location::new(0, 0, 0);
        let l2 = l1 + vec2(66000, 66000);
        assert_eq!((464, 464), (l2.x, l2.y));
    }

    #[test]
    fn test_morton() {
        use rand::Rng;
        let mut rng = rand::thread_rng();

        for _ in 0..1000 {
            let x = rng.gen::<u64>() & 0xffff_ffff_ffff;
            assert_eq!(x, Location::from_morton(x).to_morton());
        }
    }

    #[test]
    fn test_location_to_sector() {
        // Sector division near origin
        assert_eq!(Sector::from(Location::new(0, 0, 0)), Sector::new(0, 0, 0));
        assert_eq!(Sector::from(Location::new(0, 1, 0)), Sector::new(-1, 0, 0));
        assert_eq!(
            Sector::from(Location::new(-1, 0, 0)),
            Sector::new(-1, -1, 0)
        );

        for y in -100..100 {
            for x in -100..100 {
                let loc = Location::new(x, y, 0);
                let vec = CellVector::from(loc);
                assert_eq!(
                    vec,
                    vec.project::<StaggeredHexSpace>().project::<CellSpace>()
                );

                assert!(
                    Sector::from(loc).iter().find(|&x| x == loc).is_some(),
                    format!("{:?} not found in sector {:?}", loc, Sector::from(loc))
                );
            }
        }
    }

    #[test]
    fn test_sector_iter() {
        let s = Sector::new(0, 0, 0);

        for loc in s.iter() {
            assert_eq!(s, Sector::from(loc), "Location: {:?}", loc);
        }
    }
}
<|endoftext|>


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

/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
pub struct RcIter {
    /// The boxed iterator.
    pub rciter: Rc<RefCell>,
}

impl RcIter
{
    /// Create a new RcIter.
    pub fn new(iter: I) -> RcIter
    {
        RcIter{rciter: Rc::new(RefCell::new(iter))}
    }
}

impl Clone for RcIter
{
    #[inline]
    fn clone(&self) -> RcIter {
        RcIter{rciter: self.rciter.clone()}
    }
}

impl Iterator for RcIter where
    I: Iterator<Item=A>,
{
    type Item = A;
    #[inline]
    fn next(&mut self) -> Option
    {
        self.rciter.borrow_mut().next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.rciter.borrow().size_hint()
    }
}

impl DoubleEndedIterator for RcIter where
    I: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option
    {
        self.rciter.borrow_mut().next_back()
    }
}

impl ExactSizeIterator for RcIter where
    I: ExactSizeIterator
{}

/// Return an iterator from **&RcIter\** (by simply cloning it).
impl<'a, I> IntoIterator for &'a RcIter where
    I: Iterator,
{
    type Item = I::Item;
    type IntoIter = RcIter;

    fn into_iter(self) -> RcIter
    {
        self.clone()
    }
}
<commit_msg>Update docs<commit_after>
use std::iter::IntoIterator;
use std::rc::Rc;
use std::cell::RefCell;

/// A wrapper for **Rc\<RefCell\\>**, that implements the **Iterator** trait.
pub struct RcIter {
    /// The boxed iterator.
    pub rciter: Rc<RefCell>,
}

impl RcIter
{
    /// Create a new RcIter.
    pub fn new(iter: I) -> RcIter
    {
        RcIter{rciter: Rc::new(RefCell::new(iter))}
    }
}

impl Clone for RcIter
{
    #[inline]
    fn clone(&self) -> RcIter {
        RcIter{rciter: self.rciter.clone()}
    }
}

impl Iterator for RcIter where
    I: Iterator<Item=A>,
{
    type Item = A;
    #[inline]
    fn next(&mut self) -> Option
    {
        self.rciter.borrow_mut().next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.rciter.borrow().size_hint()
    }
}

impl DoubleEndedIterator for RcIter where
    I: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option
    {
        self.rciter.borrow_mut().next_back()
    }
}

impl ExactSizeIterator for RcIter where
    I: ExactSizeIterator
{}

/// Return an iterator from **&RcIter\** (by simply cloning it).
impl<'a, I> IntoIterator for &'a RcIter where
    I: Iterator,
{
    type Item = I::Item;
    type IntoIter = RcIter;

    fn into_iter(self) -> RcIter
    {
        self.clone()
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::io::Read;
use std::rc::Rc;
use std::str::{FromStr, from_utf8};

use failure::{err_msg, Error};
use serde_json::from_slice;

use Codec;
use decode::decode;
use schema::Schema;
use types::Value;

pub struct Reader<'a, R> {
    reader: R,
    reader_schema: Option<&'a Schema>,
    writer_schema: Schema,
    codec: Codec,
    marker: [u8; 16],
    items: VecDeque<Value>,
}

impl<'a, R: Read> Reader<'a, R> {
    pub fn new(reader: R) -> Reader<'a, R> {
        let mut reader = Reader {
            reader,
            reader_schema: None,
            writer_schema: Schema::Null,
            codec: Codec::Null,
            marker: [0u8; 16],
            items: VecDeque::new(),
        };

        reader.read_header().unwrap(); // TODO

        reader
    }

    pub fn with_schema(schema: &'a Schema, reader: R) -> Reader<'a, R> {
        let mut reader = Reader {
            reader,
            reader_schema: Some(schema),
            writer_schema: Schema::Null,
            codec: Codec::Null,
            marker: [0u8; 16],
            items: VecDeque::new(),
        };

        reader.read_header().unwrap(); // TODO

        reader
    }

    fn read_header(&mut self) -> Result<(), Error> {
        let meta_schema = Schema::Map(Rc::new(Schema::Bytes));

        let mut buf = [0u8; 4];
        self.reader.read_exact(&mut buf)?;

        if buf != ['O' as u8, 'b' as u8, 'j' as u8, 1u8] {
            return Err(err_msg("wrong magic in header"))
        }

        if let Value::Map(meta) = decode(&meta_schema, &mut self.reader)? {
            let schema = meta.get("avro.schema")
                .and_then(|bytes| {
                    if let &Value::Bytes(ref bytes) = bytes {
                        from_slice(bytes.as_ref()).ok()
                    } else {
                        None
                    }
                })
                .and_then(|json| Schema::parse(&json).ok());

            if let Some(schema) = schema {
                self.writer_schema = schema
            } else {
                return Err(err_msg("unable to parse schema"))
            }

            if let Some(codec) = meta.get("avro.codec")
                .and_then(|codec| {
                    if let &Value::Bytes(ref bytes) = codec {
                        from_utf8(bytes.as_ref()).ok()
                    } else {
                        None
                    }
                })
                .and_then(|codec| Codec::from_str(codec).ok())
            {
                self.codec = codec;
            }
        } else {
            return Err(err_msg("no metadata in header"))
        }

        let mut buf = [0u8; 16];
        self.reader.read_exact(&mut buf)?;

        self.marker = buf;

        Ok(())
    }

    fn read_block(&mut self) -> Result<(), Error> {
        if let Value::Long(block_len) = decode(&Schema::Long, &mut self.reader)? {
            if let Value::Long(block_bytes) = decode(&Schema::Long, &mut self.reader)? {
                let mut bytes = vec![0u8; block_bytes as usize];
                self.reader.read_exact(&mut bytes)?;

                let mut marker = [0u8; 16];
                self.reader.read_exact(&mut marker)?;

                if marker != self.marker {
                    return Err(err_msg("block marker does not match header marker"))
                }

                self.codec.decompress(&mut bytes)?;

                self.items.clear();
                self.items.reserve_exact(block_len as usize);

                for _ in 0..block_len {
                    let item = decode(&self.writer_schema, &mut &bytes[..])?;

                    let item = match self.reader_schema {
                        Some(ref schema) => item.resolve(schema)?,
                        None => item,
                    };

                    self.items.push_back(item)
                }

                return Ok(())
            }
        }

        Err(err_msg("unable to read block"))
    }
}

impl<'a, R: Read> Iterator for Reader<'a, R> {
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item> {
        if self.items.len() == 0 {
            if let Ok(_) = self.read_block() {
                return self.next()
            }
        }

        self.items.pop_front()
    }
}
<commit_msg>Add {reader,writer}_schema to Reader<commit_after>use std::collections::VecDeque;
use std::io::Read;
use std::rc::Rc;
use std::str::{FromStr, from_utf8};

use failure::{err_msg, Error};
use serde_json::from_slice;

use Codec;
use decode::decode;
use schema::Schema;
use types::Value;

pub struct Reader<'a, R> {
    reader: R,
    reader_schema: Option<&'a Schema>,
    writer_schema: Schema,
    codec: Codec,
    marker: [u8; 16],
    items: VecDeque<Value>,
}

impl<'a, R: Read> Reader<'a, R> {
    pub fn new(reader: R) -> Reader<'a, R> {
        let mut reader = Reader {
            reader,
            reader_schema: None,
            writer_schema: Schema::Null,
            codec: Codec::Null,
            marker: [0u8; 16],
            items: VecDeque::new(),
        };

        reader.read_header().unwrap(); // TODO

        reader
    }

    pub fn with_schema(schema: &'a Schema, reader: R) -> Reader<'a, R> {
        let mut reader = Reader {
            reader,
            reader_schema: Some(schema),
            writer_schema: Schema::Null,
            codec: Codec::Null,
            marker: [0u8; 16],
            items: VecDeque::new(),
        };

        reader.read_header().unwrap(); // TODO

        reader
    }

    pub fn writer_schema(&self) -> &Schema {
        &self.writer_schema
    }

    pub fn reader_schema(&self) -> Option<&Schema> {
        self.reader_schema
    }

    fn read_header(&mut self) -> Result<(), Error> {
        let meta_schema = Schema::Map(Rc::new(Schema::Bytes));

        let mut buf = [0u8; 4];
        self.reader.read_exact(&mut buf)?;

        if buf != ['O' as u8, 'b' as u8, 'j' as u8, 1u8] {
            return Err(err_msg("wrong magic in header"))
        }

        if let Value::Map(meta) = decode(&meta_schema, &mut self.reader)? {
            let schema = meta.get("avro.schema")
                .and_then(|bytes| {
                    if let &Value::Bytes(ref bytes) = bytes {
                        from_slice(bytes.as_ref()).ok()
                    } else {
                        None
                    }
                })
                .and_then(|json| Schema::parse(&json).ok());

            if let Some(schema) = schema {
                self.writer_schema = schema
            } else {
                return Err(err_msg("unable to parse schema"))
            }

            if let Some(codec) = meta.get("avro.codec")
                .and_then(|codec| {
                    if let &Value::Bytes(ref bytes) = codec {
                        from_utf8(bytes.as_ref()).ok()
                    } else {
                        None
                    }
                })
                .and_then(|codec| Codec::from_str(codec).ok())
            {
                self.codec = codec;
            }
        } else {
            return Err(err_msg("no metadata in header"))
        }

        let mut buf = [0u8; 16];
        self.reader.read_exact(&mut buf)?;

        self.marker = buf;

        Ok(())
    }

    fn read_block(&mut self) -> Result<(), Error> {
        if let Value::Long(block_len) = decode(&Schema::Long, &mut self.reader)? {
            if let Value::Long(block_bytes) = decode(&Schema::Long, &mut self.reader)? {
                let mut bytes = vec![0u8; block_bytes as usize];
                self.reader.read_exact(&mut bytes)?;

                let mut marker = [0u8; 16];
                self.reader.read_exact(&mut marker)?;

                if marker != self.marker {
                    return Err(err_msg("block marker does not match header marker"))
                }

                self.codec.decompress(&mut bytes)?;

                self.items.clear();
                self.items.reserve_exact(block_len as usize);

                for _ in 0..block_len {
                    let item = decode(&self.writer_schema, &mut &bytes[..])?;

                    let item = match self.reader_schema {
                        Some(ref schema) => item.resolve(schema)?,
                        None => item,
                    };

                    self.items.push_back(item)
                }

                return Ok(())
            }
        }

        Err(err_msg("unable to read block"))
    }
}

impl<'a, R: Read> Iterator for Reader<'a, R> {
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item> {
        if self.items.len() == 0 {
            if let Ok(_) = self.read_block() {
                return self.next()
            }
        }

        self.items.pop_front()
    }
}
<|endoftext|>


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

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static VERTEX_SRC: &'static [u8] = b"
    #version 120

    attribute ivec2 a_Pos;
    attribute vec3 a_Color;
    varying vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(a_Color, 1.0);
        gl_Position = u_Transform * vec4(a_Pos, 0.0, 1.0);
    }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 120

    varying vec4 v_Color;

    void main() {
        gl_FragColor = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct Vertex {
    #[name = "a_Pos"]
    pos: [u16; 2],

    #[name = "a_Color"]
    color: [f32; 3],
}

#[shader_param]
struct Params<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32; 4]; 4],

    _dummy: std::marker::PhantomData<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    solid_color_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let solid_color_program = match factory.link_program(VERTEX_SRC, FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let state = gfx::DrawState::new();

        RenderHelper {
            solid_color_program: solid_color_program,
            draw_state: state
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        data: RenderData)
    {
        // Prepare the uniforms to be used for rendering
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0);
        let params = Params::<R> {
            transform: proj.into_fixed(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        let rects_mesh = RenderHelper::<R>::create_rects_mesh(factory, data.rectangles);
        self.render_rects_mesh(output, renderer, &params, rects_mesh);
    }

    fn create_rects_mesh<F: gfx::Factory<R>>(factory: &mut F, rects: Vec<RectangleData>) -> gfx::Mesh<R> {
        let mut vertices = Vec::<Vertex>::new();

        for rect in rects {
            // Add our rectangle's vertices
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });

            vertices.push(Vertex { pos: [ rect.end[0], rect.end[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });
        }

        // Turn the vertices into a mesh
        factory.create_mesh(&vertices)
    }

    fn render_rects_mesh<O: gfx::Output<R>, C: gfx::CommandBuffer<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>,
        params: &Params<R>, mesh: gfx::Mesh<R>)
    {
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.solid_color_program, params);
        renderer.draw(&batch, output).unwrap();
    }
}

pub struct RenderData {
    rectangles: Vec<RectangleData>
}

pub struct RectangleData {
    start: [u16;2],
    end: [u16;2],
    color: [f32;3]
}

impl RenderData {
    pub fn new() -> RenderData {
        RenderData {
            rectangles: Vec::<RectangleData>::new()
        }
    }

    pub fn push_rectangle(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        let data = RectangleData {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]],
            color: color
        };

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

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static VERTEX_SRC: &'static [u8] = b"
    #version 130

    attribute ivec2 a_Pos;
    attribute vec3 a_Color;
    varying vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(a_Color, 1.0);
        gl_Position = u_Transform * vec4(a_Pos, 0.0, 1.0);
    }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 130

    varying vec4 v_Color;

    void main() {
        gl_FragColor = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct Vertex {
    #[name = "a_Pos"]
    pos: [u16; 2],

    #[name = "a_Color"]
    color: [f32; 3],
}

#[shader_param]
struct Params<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32; 4]; 4],

    _dummy: std::marker::PhantomData<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    solid_color_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let solid_color_program = match factory.link_program(VERTEX_SRC, FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let state = gfx::DrawState::new();

        RenderHelper {
            solid_color_program: solid_color_program,
            draw_state: state
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        data: RenderData)
    {
        // Prepare the uniforms to be used for rendering
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0);
        let params = Params::<R> {
            transform: proj.into_fixed(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        let rects_mesh = RenderHelper::<R>::create_rects_mesh(factory, data.rectangles);
        self.render_rects_mesh(output, renderer, &params, rects_mesh);
    }

    fn create_rects_mesh<F: gfx::Factory<R>>(factory: &mut F, rects: Vec<RectangleData>) -> gfx::Mesh<R> {
        let mut vertices = Vec::<Vertex>::new();

        for rect in rects {
            // Add our rectangle's vertices
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });

            vertices.push(Vertex { pos: [ rect.end[0], rect.end[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });
        }

        // Turn the vertices into a mesh
        factory.create_mesh(&vertices)
    }

    fn render_rects_mesh<O: gfx::Output<R>, C: gfx::CommandBuffer<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>,
        params: &Params<R>, mesh: gfx::Mesh<R>)
    {
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.solid_color_program, params);
        renderer.draw(&batch, output).unwrap();
    }
}

pub struct RenderData {
    rectangles: Vec<RectangleData>
}

pub struct RectangleData {
    start: [u16;2],
    end: [u16;2],
    color: [f32;3]
}

impl RenderData {
    pub fn new() -> RenderData {
        RenderData {
            rectangles: Vec::<RectangleData>::new()
        }
    }

    pub fn push_rectangle(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        let data = RectangleData {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]],
            color: color
        };

        self.rectangles.push(data);
    }
}
<|endoftext|>