<commit_before>use std::iter;
use std::collections;

use super::lexer::{Token, Tokens};
use super::ast::{Type, CondType, Statement, CreateTableQuery, DeleteQuery, InsertQuery, SelectQuery, Condition, CondArg, Value, ColumnTable, ValueSource, Constraint};

pub fn parse(tokens: Tokens) -> Result<Statement, String> {
    let mut iter = tokens.into_iter();
    match iter.next() {
        Some(Token::Create) => Ok(CreateTableQueryParser::new(iter).parse()),
        Some(Token::Delete) => Ok(DeleteQueryParser::new(iter).parse()),
        Some(Token::Insert) => Ok(InsertQueryParser::new(iter).parse()),
        Some(Token::Select) => Ok(SelectQueryParser::new(iter).parse()),
        _ => unimplemented!(),
    }
}

#[derive(Debug)]
struct CreateTableQueryParser<I: Iterator<Item = Token>> {
    tokens: I
}

impl<I: Iterator<Item = Token>> CreateTableQueryParser<I> {
    pub fn parse(mut self) -> Statement {
        if self.tokens.next() != Some(Token::Table) {
            unimplemented!();
        }

        let table_name = match self.tokens.next() {
            Some(Token::Ident(name)) => name,
            _ => unimplemented!(),
        };

        let mut columns = vec![];

        while let Some(token) = self.tokens.next() {
            match token {
                Token::LParent => {},
                Token::Semicolon => break,
                Token::Ident(name) => columns.push(self.parse_column(name)),
                t => panic!("unexpected token {:?}", t)
            }
        }

        Statement::Create(CreateTableQuery::new(table_name, columns))
    }

    fn new(tokens: I) -> CreateTableQueryParser<I> {
        CreateTableQueryParser {
            tokens: tokens
        }
    }

    fn parse_column(&mut self, column_name: String) -> ColumnTable {
        let column_type = match self.tokens.next() {
            Some(Token::Int) => Type::Integer,
            Some(Token::Character) => self.parse_var_char_type(),
            _ => unimplemented!(),
        };
        let mut column_constraints = collections::HashSet::new();
        let mut has_default = false;
        let mut is_primary_key = false;
        let mut is_foreign_key = false;
        while let Some(token) = self.tokens.next() {
            match token {
                Token::Primary => {
                    if Some(Token::Key) != self.tokens.next() {
                        unimplemented!()
                    }
                    is_primary_key = true;
                    column_constraints.insert(Constraint::PrimaryKey);
                },
                Token::Foreign => {
                    if Some(Token::Key) != self.tokens.next() {
                        unimplemented!()
                    }
                    if Some(Token::References) != self.tokens.next() {
                        unimplemented!();
                    }
                    match self.tokens.next() {
                        Some(Token::Ident(table_name)) => {
                            if Some(Token::LParent) != self.tokens.next() {
                                unimplemented!();
                            }
                            match self.tokens.next() {
                                Some(Token::Ident(col_name)) => {
                                    is_foreign_key = true;
                                    column_constraints.insert(Constraint::ForeignKey(table_name, col_name));
                                }
                                t => panic!("unexpected token {:?}", t)
                            }
                            if Some(Token::RParent) != self.tokens.next() {
                                unimplemented!();
                            }
                        }
                        t => panic!("unexpected token {:?}", t)
                    }
                }
                Token::Default => {
                    match self.tokens.next() {
                        Some(Token::NumConst(const_val))
                        | Some(Token::CharsConst(const_val)) => {
                            if !is_primary_key {
                                has_default = true;
                                column_constraints.insert(Constraint::DefaultValue(Some(const_val)));
                            }
                        },
                        t => panic!("unexpected token {:?}", t)
                    }
                },
                Token::Not => {
                    match self.tokens.next() {
                        Some(Token::Null) => {
                            column_constraints.insert(Constraint::Nullable(false));
                            match column_type {
                                Type::Integer => {
                                    column_constraints.insert(Constraint::DefaultValue(Some("0".to_owned())));
                                },
                                Type::VarChar(len) => {
                                    column_constraints.insert(Constraint::DefaultValue(Some(iter::repeat(" ").take(len as usize).collect::<String>())));
                                }
                            }
                        },
                        t => panic!("unexpected token {:?}", t)
                    }
                }
                Token::RParent | Token::Comma => {
                    if !is_primary_key && is_foreign_key && !column_constraints.contains(&Constraint::Nullable(false)) {
                        column_constraints.insert(Constraint::Nullable(true));
                    } else {
                        column_constraints.insert(Constraint::Nullable(false));
                    }
                    if !has_default {
                        column_constraints.insert(Constraint::DefaultValue(None));
                    }
                    break;
                },
                t => panic!("unexpected token {:?}", t)
            }
        };
        ColumnTable::new(column_name, column_type, column_constraints)
    }

    fn parse_var_char_type(&mut self) -> Type {
        if self.tokens.next() != Some(Token::LParent) {
            unimplemented!();
        }

        let size = self.parse_size();

        if self.tokens.next() != Some(Token::RParent) {
            unimplemented!();
        }

        Type::VarChar(size)
    }

    fn parse_size(&mut self) -> u8 {
        match self.tokens.next() {
            Some(Token::NumConst(num)) => match num.parse::<u8>() {
                Ok(size) => size,
                _ => unimplemented!(),
            },
            _ => unimplemented!(),
        }
    }
}

struct InsertQueryParser<I: Iterator<Item = Token>> {
    tokens: I
}

impl<I: Iterator<Item = Token>> InsertQueryParser<I> {
    pub fn new(tokens: I) -> InsertQueryParser<I> {
        InsertQueryParser {
            tokens: tokens
        }
    }

    fn parse_columns(&mut self) -> Vec<String> {
        let mut columns = vec![];
        while let Some(token) = self.tokens.next() {
            match token {
                Token::Comma => {},
                Token::Ident(col) => { columns.push(col); },
                Token::RParent => break,
                unexpected => panic!("panic find unexpected token {:?}", unexpected),
            }
        }
        columns
    }

    fn parse_values(&mut self) -> Vec<Value> {
        if self.tokens.next() != Some(Token::LParent) {
            unimplemented!();
        }
        let mut values = vec![];
        while let Some(token) = self.tokens.next() {
            match token {
                Token::NumConst(s) => values.push(Value::NumConst(s)),
                Token::CharsConst(s) => values.push(Value::StrConst(s)),
                Token::Comma => {},
                Token::RParent => break,
                unexpected => panic!("panic find unexpected token {:?}", unexpected),
            }
        }
        values
    }

    fn parse(mut self) -> Statement {
        if self.tokens.next() != Some(Token::Into) {
            unimplemented!();
        }
        let table_name = match self.tokens.next() {
            Some(Token::Ident(table_name)) => table_name,
            _ => unimplemented!(),
        };
        let mut columns = vec![];

        let mut sub_query = false;
        while let Some(token) = self.tokens.next() {
            match token {
                Token::LParent => columns = self.parse_columns(),
                Token::Values => {
                    sub_query = false;
                    break;
                },
                Token::Select => {
                    sub_query = true;
                    break;
                },
                Token::Semicolon => break,
                _ => unimplemented!(),
            }
        }

        let query = if sub_query {
            InsertQuery::new(table_name, columns, ValueSource::SubQuery(SelectQueryParser::new(self.tokens).parse_select()))
        } else {
            let query = InsertQuery::new(table_name, columns, ValueSource::Row(self.parse_values()));
            if self.tokens.next() != Some(Token::Semicolon) {
                unimplemented!();
            }
            query
        };
        Statement::Insert(query)
    }
}

struct DeleteQueryParser<I: Iterator<Item = Token>> {
    tokens: I
}

impl<I: Iterator<Item = Token>> DeleteQueryParser<I> {
    pub fn new(tokens: I) -> DeleteQueryParser<I> {
        DeleteQueryParser {
            tokens: tokens
        }
    }

    fn parse(mut self) -> Statement {
        if self.tokens.next() != Some(Token::From) {
            unimplemented!();
        }

        let table_name = match self.tokens.next() {
            Some(Token::Ident(name)) => name,
            _ => unimplemented!(),
        };

        Statement::Delete(DeleteQuery::new(table_name, PredicateParser::new(self.tokens).parse_where()))
    }
}

struct SelectQueryParser<I: Iterator<Item = Token>> {
    tokens: I
}

impl<I: Iterator<Item = Token>> SelectQueryParser<I> {
    pub fn new(tokens: I) -> SelectQueryParser<I> {
        SelectQueryParser {
            tokens: tokens
        }
    }

    fn parse_select(mut self) -> SelectQuery {
        let columns = self.parse_columns_list();

        let table_name = match self.tokens.next() {
            Some(Token::Ident(table_name)) => table_name,
            _ => unimplemented!()
        };

        SelectQuery::new(table_name, columns, PredicateParser::new(self.tokens).parse_where())
    }

    fn parse_columns_list(&mut self) -> Vec<String> {
        let mut columns = vec![];
        loop {
            match self.tokens.next() {
                Some(Token::From) => break, // skip 'FROM' keyword
                Some(Token::Ident(column_name)) => columns.push(column_name),
                Some(Token::Comma) => {},
                t => panic!("unexpected token {:?} - ", t),
            }
        }
        columns
    }

    fn parse(self) -> Statement {
        Statement::Select(self.parse_select())
    }
}

struct PredicateParser<I: Iterator<Item = Token>> {
    tokens: I
}

impl<I: Iterator<Item = Token>> PredicateParser<I> {
    fn new(tokens: I) -> PredicateParser<I> {
        PredicateParser {
            tokens: tokens
        }
    }

    fn parse_where(&mut self) -> Option<Condition> {
        match self.tokens.next() {
            Some(Token::Where) => {
                let left = self.parse_predicate_arguments();

                let cond_type = match self.tokens.next() {
                    Some(Token::EqualSign) => CondType::Eq,
                    Some(Token::NotEqualSign) => CondType::NotEq,
                    _ => unimplemented!(),
                };
                let right = self.parse_predicate_arguments();
                Some(Condition::new(left, right, cond_type))
            },
            Some(Token::Semicolon) => None,
            _ => unimplemented!(),
        }
    }

    fn parse_predicate_arguments(&mut self) -> CondArg {
        match self.tokens.next() {
            Some(Token::CharsConst(s)) => CondArg::StringConstant(s),
            Some(Token::NumConst(s)) => CondArg::NumConst(s),
            Some(Token::Limit) => CondArg::Limit,
            Some(Token::Ident(s)) => CondArg::ColumnName(s),
            c => panic!("unexpected token - {:?}", c),
        }
    }
}
<commit_msg>use functions to parse queries instead of structs<commit_after>use std::iter;
use std::collections;

use super::lexer::{Token, Tokens};
use super::ast::{Type, CondType, Statement, CreateTableQuery, DeleteQuery, InsertQuery, SelectQuery, Condition, CondArg, Value, ColumnTable, ValueSource, Constraint};

pub fn parse(tokens: Tokens) -> Result<Statement, String> {
    let mut iter = tokens.into_iter();
    match iter.next() {
        Some(Token::Create) => Ok(Statement::Create(parse_create_table(iter.by_ref()))),
        Some(Token::Delete) => Ok(Statement::Delete(parse_delete_query(iter.by_ref()))),
        Some(Token::Insert) => Ok(Statement::Insert(parse_insert_query(iter.by_ref()))),
        Some(Token::Select) => Ok(Statement::Select(parse_select_query(iter.by_ref()))),
        _ => unimplemented!(),
    }
}

fn parse_create_table<I: Iterator<Item = Token>>(tokens: &mut I) -> CreateTableQuery {
    if tokens.next() != Some(Token::Table) {
        unimplemented!();
    }

    let table_name = match tokens.next() {
        Some(Token::Ident(name)) => name,
        _ => unimplemented!(),
    };

    let mut columns = vec![];

    while let Some(token) = tokens.next() {
        match token {
            Token::LParent => {},
            Token::Semicolon => break,
            Token::Ident(name) => columns.push(parse_table_column(tokens.by_ref(), name)),
            t => panic!("unexpected token {:?}", t)
        }
    }

    CreateTableQuery::new(table_name, columns)
}

fn parse_table_column<I: Iterator<Item = Token>>(tokens: &mut I, column_name: String) -> ColumnTable {
    let column_type = match tokens.next() {
        Some(Token::Int) => Type::Integer,
        Some(Token::Character) => parse_var_char_type(tokens.by_ref()),
        _ => unimplemented!(),
    };
    let mut column_constraints = collections::HashSet::new();
    let mut has_default = false;
    let mut is_primary_key = false;
    let mut is_foreign_key = false;
    while let Some(token) = tokens.next() {
        match token {
            Token::Primary => {
                if Some(Token::Key) != tokens.next() {
                    unimplemented!()
                }
                is_primary_key = true;
                column_constraints.insert(Constraint::PrimaryKey);
            },
            Token::Foreign => {
                if Some(Token::Key) != tokens.next() {
                    unimplemented!()
                }
                if Some(Token::References) != tokens.next() {
                    unimplemented!();
                }
                match tokens.next() {
                    Some(Token::Ident(table_name)) => {
                        if Some(Token::LParent) != tokens.next() {
                            unimplemented!();
                        }
                        match tokens.next() {
                            Some(Token::Ident(col_name)) => {
                                is_foreign_key = true;
                                column_constraints.insert(Constraint::ForeignKey(table_name, col_name));
                            }
                            t => panic!("unexpected token {:?}", t)
                        }
                        if Some(Token::RParent) != tokens.next() {
                            unimplemented!();
                        }
                    }
                    t => panic!("unexpected token {:?}", t)
                }
            }
            Token::Default => {
                match tokens.next() {
                    Some(Token::NumConst(const_val))
                    | Some(Token::CharsConst(const_val)) => {
                        if !is_primary_key {
                            has_default = true;
                            column_constraints.insert(Constraint::DefaultValue(Some(const_val)));
                        }
                    },
                    t => panic!("unexpected token {:?}", t)
                }
            },
            Token::Not => {
                match tokens.next() {
                    Some(Token::Null) => {
                        column_constraints.insert(Constraint::Nullable(false));
                        match column_type {
                            Type::Integer => {
                                column_constraints.insert(Constraint::DefaultValue(Some("0".to_owned())));
                            },
                            Type::VarChar(len) => {
                                column_constraints.insert(Constraint::DefaultValue(Some(iter::repeat(" ").take(len as usize).collect::<String>())));
                            }
                        }
                    },
                    t => panic!("unexpected token {:?}", t)
                }
            }
            Token::RParent | Token::Comma => {
                if !is_primary_key && is_foreign_key && !column_constraints.contains(&Constraint::Nullable(false)) {
                    column_constraints.insert(Constraint::Nullable(true));
                } else {
                    column_constraints.insert(Constraint::Nullable(false));
                }
                if !has_default {
                    column_constraints.insert(Constraint::DefaultValue(None));
                }
                break;
            },
            t => panic!("unexpected token {:?}", t)
        }
    };
    ColumnTable::new(column_name, column_type, column_constraints)
}

fn parse_var_char_type<I: Iterator<Item = Token>>(tokens: &mut I) -> Type {
    if tokens.next() != Some(Token::LParent) {
        unimplemented!();
    }

    let size = parse_size(tokens.by_ref());

    if tokens.next() != Some(Token::RParent) {
        unimplemented!();
    }

    Type::VarChar(size)
}

fn parse_size<I: Iterator<Item = Token>>(tokens: &mut I) -> u8 {
    match tokens.next() {
        Some(Token::NumConst(num)) => match num.parse::<u8>() {
            Ok(size) => size,
            _ => unimplemented!(),
        },
        _ => unimplemented!(),
    }
}

fn parse_columns<I: Iterator<Item = Token>>(tokens: &mut I) -> Vec<String> {
    let mut columns = vec![];
    while let Some(token) = tokens.next() {
        match token {
            Token::Comma => {},
            Token::Ident(col) => { columns.push(col); },
            Token::RParent => break,
            unexpected => panic!("panic find unexpected token {:?}", unexpected),
        }
    }
    columns
}

fn parse_values<I: Iterator<Item = Token>>(tokens: &mut I) -> Vec<Value> {
    if tokens.next() != Some(Token::LParent) {
        unimplemented!();
    }
    let mut values = vec![];
    while let Some(token) = tokens.next() {
        match token {
            Token::NumConst(s) => values.push(Value::NumConst(s)),
            Token::CharsConst(s) => values.push(Value::StrConst(s)),
            Token::Comma => {},
            Token::RParent => break,
            unexpected => panic!("panic find unexpected token {:?}", unexpected),
        }
    }
    values
}

fn parse_insert_query<I: Iterator<Item = Token>>(tokens: &mut I) -> InsertQuery {
    if tokens.next() != Some(Token::Into) {
        unimplemented!();
    }
    let table_name = match tokens.next() {
        Some(Token::Ident(table_name)) => table_name,
        _ => unimplemented!(),
    };
    let mut columns = vec![];

    let mut sub_query = false;
    while let Some(token) = tokens.next() {
        match token {
            Token::LParent => columns = parse_columns(tokens.by_ref()),
            Token::Values => {
                sub_query = false;
                break;
            },
            Token::Select => {
                sub_query = true;
                break;
            },
            Token::Semicolon => break,
            _ => unimplemented!(),
        }
    }

    if sub_query {
        InsertQuery::new(table_name, columns, ValueSource::SubQuery(parse_select_query(tokens.by_ref())))
    } else {
        let query = InsertQuery::new(table_name, columns, ValueSource::Row(parse_values(tokens.by_ref())));
        if tokens.next() != Some(Token::Semicolon) {
            unimplemented!();
        }
        query
    }
}

fn parse_delete_query<I: Iterator<Item = Token>>(tokens: &mut I) -> DeleteQuery {
    if tokens.next() != Some(Token::From) {
        unimplemented!();
    }

    let table_name = match tokens.next() {
        Some(Token::Ident(name)) => name,
        _ => unimplemented!(),
    };

    DeleteQuery::new(table_name, parse_where(tokens.by_ref()))
}

fn parse_select_query<I: Iterator<Item = Token>>(tokens: &mut I) -> SelectQuery {
    let columns = parse_columns_list(tokens.by_ref());

    let table_name = match tokens.next() {
        Some(Token::Ident(table_name)) => table_name,
        _ => unimplemented!()
    };

    SelectQuery::new(table_name, columns, parse_where(tokens.by_ref()))
}

fn parse_columns_list<I: Iterator<Item = Token>>(tokens: &mut I) -> Vec<String> {
    let mut columns = vec![];
    loop {
        match tokens.next() {
            Some(Token::From) => break, // skip 'FROM' keyword
            Some(Token::Ident(column_name)) => columns.push(column_name),
            Some(Token::Comma) => {},
            t => panic!("unexpected token {:?} - ", t),
        }
    }
    columns
}

fn parse_where<I: Iterator<Item = Token>>(tokens: &mut I) -> Option<Condition> {
    match tokens.next() {
        Some(Token::Where) => {
            let left = parse_predicate_arguments(tokens.by_ref());

            let cond_type = match tokens.next() {
                Some(Token::EqualSign) => CondType::Eq,
                Some(Token::NotEqualSign) => CondType::NotEq,
                _ => unimplemented!(),
            };
            let right = parse_predicate_arguments(tokens.by_ref());
            Some(Condition::new(left, right, cond_type))
        },
        Some(Token::Semicolon) => None,
        _ => unimplemented!(),
    }
}

fn parse_predicate_arguments<I: Iterator<Item = Token>>(tokens: &mut I) -> CondArg {
    match tokens.next() {
        Some(Token::CharsConst(s)) => CondArg::StringConstant(s),
        Some(Token::NumConst(s)) => CondArg::NumConst(s),
        Some(Token::Limit) => CondArg::Limit,
        Some(Token::Ident(s)) => CondArg::ColumnName(s),
        c => panic!("unexpected token - {:?}", c),
    }
}
<|endoftext|>


<commit_before>use nom::*;

#[derive(Debug)]
enum Instruction {
    THUMB1 {
        tag: u8,
        opcode: u8,
        offset: u8,
        source_register: u8,
        destination_register: u8,
    },
    THUMB2 {
        tag: u8,
        opcode: u8,
        operand: u8,
        source_register: u8,
        destination_register: u8,
    },
    THUMB3 {
        tag: u8,
        opcode: u8,
        destination_register: u8,
        unsigned_immediate: u8,
    },
    THUMB4 {
        tag: u8,
        opcode: u8,
        source_register: u8,
        destination_register: u8,
    }
}

named!(parse_thumb1<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 3, 0b000) >>
            opcode: take_bits!(u8, 2) >>
            offset: take_bits!(u8, 5) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB1 {
                tag: tag,
                opcode: opcode,
                offset: offset,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb2<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 5, 0b00011) >>
            opcode: take_bits!(u8, 2) >>
            operand: take_bits!(u8, 3) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB2 {
                tag: tag,
                opcode: opcode,
                operand: operand,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb3<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 3, 0b001) >>
            opcode: take_bits!(u8, 2) >>
            destination_register: take_bits!(u8, 3) >>
            unsigned_immediate: take_bits!(u8, 8) >>
            (Instruction::THUMB3 {
                tag: tag,
                opcode: opcode,
                destination_register: destination_register,
                unsigned_immediate: unsigned_immediate,
            })
        )
    )
);

named!(parse_thumb4<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 6, 0b010000) >>
            opcode: take_bits!(u8, 4) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB4 {
                tag: tag,
                opcode: opcode,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb<Vec<Instruction>>,
    many0!(
        alt!(
            parse_thumb1 |
            parse_thumb2 |
            parse_thumb3 |
            parse_thumb4
        )
    )
);

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

    #[test]
    fn parse_instruction() {
        let move_shift_thumb1 = vec![ 0b00011101, 0b11001000, ];
        let add_immediate_thumb2 = vec![ 0b00011101, 0b11001000, ];
        let add_immediate_128_to_r7 = vec![ 0b00110111, 0b10000000 ];
        let rotate_r4_right_by_r5 = vec![ 0b01000001, 0b11101100 ];
        println!("{:?}", parse_thumb(&rotate_r4_right_by_r5));
    }
}
<commit_msg>Remove tag bit from Instruction structs<commit_after>use nom::*;

#[derive(Debug)]
enum Instruction {
    THUMB1 {
        opcode: u8,
        offset: u8,
        source_register: u8,
        destination_register: u8,
    },
    THUMB2 {
        opcode: u8,
        operand: u8,
        source_register: u8,
        destination_register: u8,
    },
    THUMB3 {
        opcode: u8,
        destination_register: u8,
        unsigned_immediate: u8,
    },
    THUMB4 {
        opcode: u8,
        source_register: u8,
        destination_register: u8,
    }
}

named!(parse_thumb1<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 3, 0b000) >>
            opcode: take_bits!(u8, 2) >>
            offset: take_bits!(u8, 5) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB1 {
                opcode: opcode,
                offset: offset,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb2<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 5, 0b00011) >>
            opcode: take_bits!(u8, 2) >>
            operand: take_bits!(u8, 3) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB2 {
                opcode: opcode,
                operand: operand,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb3<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 3, 0b001) >>
            opcode: take_bits!(u8, 2) >>
            destination_register: take_bits!(u8, 3) >>
            unsigned_immediate: take_bits!(u8, 8) >>
            (Instruction::THUMB3 {
                opcode: opcode,
                destination_register: destination_register,
                unsigned_immediate: unsigned_immediate,
            })
        )
    )
);

named!(parse_thumb4<Instruction>,
    bits!(
        do_parse!(
            tag: tag_bits!(u8, 6, 0b010000) >>
            opcode: take_bits!(u8, 4) >>
            source_register: take_bits!(u8, 3) >>
            destination_register: take_bits!(u8, 3) >>
            (Instruction::THUMB4 {
                opcode: opcode,
                source_register: source_register,
                destination_register: destination_register,
            })
        )
    )
);

named!(parse_thumb<Vec<Instruction>>,
    many0!(
        alt!(
            parse_thumb1 |
            parse_thumb2 |
            parse_thumb3 |
            parse_thumb4
        )
    )
);

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

    #[test]
    fn parse_instruction() {
        let move_shift_thumb1 = vec![ 0b00011101, 0b11001000, ];
        let add_immediate_thumb2 = vec![ 0b00011101, 0b11001000, ];
        let add_immediate_128_to_r7 = vec![ 0b00110111, 0b10000000 ];
        let rotate_r4_right_by_r5 = vec![ 0b01000001, 0b11101100 ];
        println!("{:?}", parse_thumb(&rotate_r4_right_by_r5));
    }
}
<|endoftext|>


<commit_before>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = (stmt_or_decl terminator?)* > program

    stmt_or_decl
        = (stmt / decl)

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = def_kw ident lparen param_list rparen block > method_decl

    block
        = lbracket (stmt terminator?)* rbracket > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    lsqbracket = "[" spacing
    rsqbracket = "]" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<(PNode, Option<()>)>) -> PNode {
        let stmts = stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect();

        PNode(Block(stmts))
    }

    fn program(stmts: Vec<(PNode, Option<()>)>) -> Vec<PNode> {
        stmts.into_iter().map(|stmt| {
            match stmt { (s, _) => s }
        }).collect()
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<commit_msg>First sort of functional version of '\n' as statement separator.<commit_after>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = (newlines stmt_or_decl terminator)*

    stmt_or_decl
        = stmt
        / decl

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = newlines def_kw ident lparen param_list rparen block > method_decl

    block
        = lbracket (newlines stmt terminator)* rbracket spacing > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = newlines cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \r\t"]
    spacing = spacing_char* -> ()
    newline = "\n" spacing -> ()
    semicolon = ";" spacing -> ()
    terminator = newline / semicolon -> ()
    newlines = newline* spacing -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" newlines -> ()
    rbracket = newlines "}" -> ()
    lsqbracket = "[" spacing
    rsqbracket = "]" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<PNode>) -> PNode {
        PNode(Block(stmts))
    }

    fn program(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use keys::*;
use event::KeyEvent;
use keyboard::KeyboardInternal;
use libusb::{Result as UsbResult, Error as UsbError};

#[derive(Debug, Clone, PartialEq)]
pub struct Packet<'a> {
    pub endpoint: u8,
    pub buf: &'a [u8],
}

impl<'a> Packet<'a> {
    pub fn new(endpoint_direction: u8, buf: &'a [u8]) -> Packet {
        Packet {
            endpoint: endpoint_direction & 0x7f,
            buf: buf
        }
    }
}

pub enum Parser {
    ParseKey(Box<ParseKey>),
    ParseControl(Box<ParseControl>),
}

pub trait ParseKey {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>>;
}

pub trait ParseControl {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyParser {
    pressed_keys1: HashSet<Key>,
    pressed_keys2: HashSet<Key>,
}

impl KeyParser {
    pub fn new() -> KeyParser {
        KeyParser {
            pressed_keys1: HashSet::new(),
            pressed_keys2: HashSet::new(),
        }
    }
}

impl ParseKey for KeyParser {
    fn accept(&self, packet: &Packet) -> bool {
        // interface 1 - normal key || interface 2 - rollover
        packet.buf.len() >= 8
            && packet.endpoint == 1
            || (packet.endpoint == 2 && packet.buf[0] == 0x01)
    }

    #[allow(unused_variables)]
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>> {
        let mut state = HashSet::new();
        // TODO: add modifier keys
        for k in &packet.buf[1..] {
            match StandardKey::from(*k) {
                StandardKey::None => {},
                s => { state.insert(s.into()); }
            }
        }

        let mut added: Vec<_>;
        let mut removed: Vec<_>;
        if packet.endpoint == 1 {
            added = state.difference(&self.pressed_keys1).cloned().collect();
            removed = self.pressed_keys1.difference(&state).cloned().collect();
            self.pressed_keys1 = state;
        } else {
            added = state.difference(&self.pressed_keys2).cloned().collect();
            removed = self.pressed_keys2.difference(&state).cloned().collect();
            self.pressed_keys2 = state;
        }
        let added_len = added.len();
        let removed_len = removed.len();
        let res = added.drain(0..added_len).map(|e| KeyEvent::KeyPressed(e))
            .chain(removed.drain(0..removed_len).map(|e| KeyEvent::KeyReleased(e)))
            .collect();
        Ok(res)
    }
}

impl From<KeyParser> for Parser {
    fn from(parser: KeyParser) -> Parser {
        Parser::ParseKey(Box::new(parser))
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ControlParser;

impl ControlParser {
    pub fn new() -> ControlParser {
        ControlParser { }
    }
}

impl ParseControl for ControlParser {
    fn accept(&self, packet: &Packet) -> bool {
        packet.endpoint == 0 || (packet.endpoint == 2 && packet.buf[0] == 0x11)
    }

    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()> {
        if packet.buf.len() == 0 {
            println!("buf empty");
            Ok(())
        } else if packet.endpoint == 0
             && !(packet.buf[0] == 0x11 || packet.buf[0] == 0x12) {
            println!("Trying to parse unknown packet from iface 0: {:?}", packet);
            Err(UsbError::NotSupported)
        } else if packet.endpoint == 2
            && !(packet.buf[0] == 0x11) {
            println!("Trying to parse unknown packet from iface 2: {:?}", packet);
            Err(UsbError::NotSupported)
        // wait for the acknoledgement of the control packet before
        // sending the next one
        } else if packet.endpoint == 2 {
            keyboard_internal.send_next_control()
        } else {
            Ok(())
        }
    }
}

impl From<ControlParser> for Parser {
    fn from(parser: ControlParser) -> Parser {
        Parser::ParseControl(Box::new(parser))
    }
}

<commit_msg>feat(parser): Parse modifier keys<commit_after>use std::collections::HashSet;
use keys::*;
use event::KeyEvent;
use keyboard::KeyboardInternal;
use libusb::{Result as UsbResult, Error as UsbError};

#[derive(Debug, Clone, PartialEq)]
pub struct Packet<'a> {
    pub endpoint: u8,
    pub buf: &'a [u8],
}

impl<'a> Packet<'a> {
    pub fn new(endpoint_direction: u8, buf: &'a [u8]) -> Packet {
        Packet {
            endpoint: endpoint_direction & 0x7f,
            buf: buf
        }
    }
}

pub enum Parser {
    ParseKey(Box<ParseKey>),
    ParseControl(Box<ParseControl>),
}

pub trait ParseKey {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>>;
}

pub trait ParseControl {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyParser {
    pressed_keys1: HashSet<Key>,
    pressed_keys2: HashSet<Key>,
}

impl KeyParser {
    pub fn new() -> KeyParser {
        KeyParser {
            pressed_keys1: HashSet::new(),
            pressed_keys2: HashSet::new(),
        }
    }
}

impl ParseKey for KeyParser {
    fn accept(&self, packet: &Packet) -> bool {
        // interface 1 - normal key || interface 2 - rollover
        packet.buf.len() >= 8
            && packet.endpoint == 1
            || (packet.endpoint == 2 && packet.buf[0] == 0x01)
    }

    #[allow(unused_variables)]
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>> {
        let mut state = HashSet::new();
        // TODO: parse media keys
        for k in &packet.buf[1..] {
            match StandardKey::from(*k) {
                StandardKey::None => {},
                s => { state.insert(s.into()); }
            }
        }

        let mut added: Vec<_>;
        let mut removed: Vec<_>;
        if packet.endpoint == 1 {
            // byte 0 has modifier keys as bytemap:
            // 0b0 0 0 0 0 0 0 0
            //   R R R R L L L L
            //   W A S C W A S C
            //   I L H T I L H T
            //   N T I R N T I R
            //     G F L     F L
            //     R T       T
            //   L L L L R R R R
            //   C S A W C S A W
            //   T H L I T H L I
            //   R I T N L I T N
            //   L F       F G
            //     T       T R
            if packet.buf[0] & 0x01 == 0x01 {
                state.insert(StandardKey::LeftControl.into());
            }
            if packet.buf[0] & 0x02 == 0x02 {
                state.insert(StandardKey::LeftShift.into());
            }
            if packet.buf[0] & 0x04 == 0x04 {
                state.insert(StandardKey::LeftAlt.into());
            }
            if packet.buf[0] & 0x08 == 0x08 {
                state.insert(StandardKey::LeftWindows.into());
            }
            if packet.buf[0] & 0x10 == 0x10 {
                state.insert(StandardKey::RightControl.into());
            }
            if packet.buf[0] & 0x20 == 0x20 {
                state.insert(StandardKey::RightShift.into());
            }
            if packet.buf[0] & 0x40 == 0x40 {
                state.insert(StandardKey::RightAlt.into());
            }
            if packet.buf[0] & 0x80 == 0x80 {
                state.insert(StandardKey::RightWindows.into());
            }
            added = state.difference(&self.pressed_keys1).cloned().collect();
            removed = self.pressed_keys1.difference(&state).cloned().collect();
            self.pressed_keys1 = state;
        } else {
            added = state.difference(&self.pressed_keys2).cloned().collect();
            removed = self.pressed_keys2.difference(&state).cloned().collect();
            self.pressed_keys2 = state;
        }
        let res = added.drain(..).map(|e| KeyEvent::KeyPressed(e))
            .chain(removed.drain(..).map(|e| KeyEvent::KeyReleased(e)))
            .collect();
        Ok(res)
    }
}

impl From<KeyParser> for Parser {
    fn from(parser: KeyParser) -> Parser {
        Parser::ParseKey(Box::new(parser))
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ControlParser;

impl ControlParser {
    pub fn new() -> ControlParser {
        ControlParser { }
    }
}

impl ParseControl for ControlParser {
    fn accept(&self, packet: &Packet) -> bool {
        packet.endpoint == 0 || (packet.endpoint == 2 && packet.buf[0] == 0x11)
    }

    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()> {
        if packet.buf.len() == 0 {
            println!("buf empty");
            Ok(())
        } else if packet.endpoint == 0
             && !(packet.buf[0] == 0x11 || packet.buf[0] == 0x12) {
            println!("Trying to parse unknown packet from iface 0: {:?}", packet);
            Err(UsbError::NotSupported)
        } else if packet.endpoint == 2
            && !(packet.buf[0] == 0x11) {
            println!("Trying to parse unknown packet from iface 2: {:?}", packet);
            Err(UsbError::NotSupported)
        // wait for the acknoledgement of the control packet before
        // sending the next one
        } else if packet.endpoint == 2 {
            keyboard_internal.send_next_control()
        } else {
            Ok(())
        }
    }
}

impl From<ControlParser> for Parser {
    fn from(parser: ControlParser) -> Parser {
        Parser::ParseControl(Box::new(parser))
    }
}

<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::BufRead;

use error::*;
use types::*;

pub struct Reader<R> {
    reader: io::BufReader<R>,
}

macro_rules! parse_line {
    ($reader:ident) => {{
        let mut buffer = String::new();
        $reader.read_line(&mut buffer)?;
        buffer
    }};
    ($reader:ident, $t:ty) => {{
        let mut buffer = String::new();
        $reader.read_line(&mut buffer)?;
        buffer.trim().parse::<$t>()?
    }}
}

impl<R: io::Read> Reader<R> {
    pub fn new(inner: R) -> Self {
        Reader {
            reader: io::BufReader::new(inner)
        }
    }

    pub fn snapshot(&mut self) -> Result<Snapshot> {
        let reader = &mut self.reader;

        let num_atoms = parse_line!(reader, i32);
        let comment = parse_line!(reader);

        let mut atoms: Vec<Atom> = Vec::new();
        for _ in 0..num_atoms {
            atoms.push(parse_line!(reader, Atom));
        }

        Ok(Snapshot {
            comment: comment,
            atoms: atoms
        })
    }
}

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

    #[test]
    fn test_reader() {
        let data: &[u8] = b"\
            3
            comment
            C 1.0 2.0 3.0
            O 4.0 3.0 6.0
            H 5.0 1.5 4.0";
        let mut reader = Reader::new(data);
        let success = reader.snapshot();
        assert!(success.is_ok());

        let snapshot = success.unwrap();
        assert_eq!(3, snapshot.size());
    }
}
<commit_msg>Implement Iterator for Reader<commit_after>use std::io;
use std::io::prelude::BufRead;
use std::iter::Iterator;

use error::*;
use types::*;

pub struct Reader<R> {
    reader: io::BufReader<R>,
}

macro_rules! parse_line {
    ($reader:ident) => {{
        let mut buffer = String::new();
        $reader.read_line(&mut buffer)?;
        buffer
    }};
    ($reader:ident, $t:ty) => {{
        let mut buffer = String::new();
        $reader.read_line(&mut buffer)?;
        buffer.trim().parse::<$t>()?
    }}
}

impl<R: io::Read> Reader<R> {
    pub fn new(inner: R) -> Self {
        Reader {
            reader: io::BufReader::new(inner)
        }
    }

    pub fn snapshot(&mut self) -> Result<Snapshot> {
        let reader = &mut self.reader;

        let num_atoms = parse_line!(reader, i32);
        let comment = parse_line!(reader);

        let mut atoms: Vec<Atom> = Vec::new();
        for _ in 0..num_atoms {
            atoms.push(parse_line!(reader, Atom));
        }

        Ok(Snapshot {
            comment: comment,
            atoms: atoms
        })
    }
}

impl<R: io::Read> Iterator for Reader<R> {
    type Item = Snapshot;

    fn next(&mut self) -> Option<Self::Item> {
        self.snapshot().ok()
    }
}

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

    #[test]
    fn test_reader() {
        let data: &[u8] = b"\
            3
            comment
            C 1.0 2.0 3.0
            O 4.0 3.0 6.0
            H 5.0 1.5 4.0";
        let mut reader = Reader::new(data);
        let success = reader.snapshot();
        assert!(success.is_ok());

        let snapshot = success.unwrap();
        assert_eq!(3, snapshot.size());
    }

    #[test]
    fn test_iterator() {
        let data: &[u8] = b"\
            3
            1st snapshot
            C 1.0 2.0 3.0
            O 4.0 3.0 6.0
            H 5.0 1.5 4.0
            3
            2nd snapshot
            C 1.1 1.9 2.8
            O 4.2 3.0 5.9
            H 5.0 1.6 4.0";
        let mut reader = Reader::new(data);
        assert!(reader.next().is_some());
        assert!(reader.next().is_some());
        assert!(reader.next().is_none());
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::str::{self, FromStr};

use error::{S3Result, S3Error};

/// AWS S3 [region identifier](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
///
/// # Example
/// ```
/// use std::str::FromStr;
/// use s3::region::Region;
///
/// // Parse from a string
/// let region: Region = "us-east-1".parse().unwrap();
///
/// // Choose region directly
/// let region = Region::EuWest2;
/// ```
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Region {
    /// us-east-1
    UsEast1,
    /// us-east-2
    UsEast2,
    /// us-west-1
    UsWest1,
    /// us-west-2
    UsWest2,
    /// ca-central-1
    CaCentral1,
    /// ap-south-1
    ApSouth1,
    /// ap-northeast-1
    ApNortheast1,
    /// ap-northeast-2
    ApNortheast2,
    /// ap-southeast-1
    ApSoutheast1,
    /// ap-southeast-2
    ApSoutheast2,
    /// eu-central-1
    EuCentral1,
    /// eu-west-1
    EuWest1,
    /// eu-west-2
    EuWest2,
    /// sa-east-1
    SaEast1,
}

impl fmt::Display for Region {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Region::*;
        match *self {
            UsEast1 => write!(f, "us-east-1"),
            UsEast2 => write!(f, "us-east-2"),
            UsWest1 => write!(f, "us-west-1"),
            UsWest2 => write!(f, "us-west-2"),
            CaCentral1 => write!(f, "ca-central-1"),
            ApSouth1 => write!(f, "ap-south-1"),
            ApNortheast1 => write!(f, "ap-northeast-1"),
            ApNortheast2 => write!(f, "ap-northeast-2"),
            ApSoutheast1 => write!(f, "ap-southeast-1"),
            ApSoutheast2 => write!(f, "ap-southeast-2"),
            EuCentral1 => write!(f, "eu-central-1"),
            EuWest1 => write!(f, "eu-west-1"),
            EuWest2 => write!(f, "eu-west-2"),
            SaEast1 => write!(f, "sa-east-1"),
        }
    }
}

impl FromStr for Region {
    type Err = S3Error;

    fn from_str(s: &str) -> S3Result<Self> {
        use self::Region::*;
        match s {
            "us-east-1" => Ok(UsEast1),
            "us-east-2" => Ok(UsEast2),
            "us-west-1" => Ok(UsWest1),
            "us-west-2" => Ok(UsWest2),
            "ca-central-1" => Ok(CaCentral1),
            "ap-south-1" => Ok(ApSouth1),
            "ap-northeast-1" => Ok(ApNortheast1),
            "ap-northeast-2" => Ok(ApNortheast2),
            "ap-southeast-1" => Ok(ApSoutheast1),
            "ap-southeast-2" => Ok(ApSoutheast2),
            "eu-central-1" => Ok(EuCentral1),
            "eu-west-1" => Ok(EuWest1),
            "eu-west-2" => Ok(EuWest2),
            "sa-east-1" => Ok(SaEast1),
            _ => Err(s.to_string().into()),
        }
    }
}

impl Region {
    pub fn endpoint(&self) -> &str {
        use self::Region::*;
        match *self {
            // Surprisingly, us-east-1 does not have a
            // s3-us-east-1.amazonaws.com DNS record
            UsEast1 => "s3.amazonaws.com",
            UsEast2 => "s3-us-east-2.amazonaws.com",
            UsWest1 => "s3-us-west-1.amazonaws.com",
            UsWest2 => "s3-us-west-2.amazonaws.com",
            CaCentral1 => "s3-ca-central-1.amazonaws.com",
            ApSouth1 => "s3-ap-south-1.amazonaws.com",
            ApNortheast1 => "s3-ap-northeast-1.amazonaws.com",
            ApNortheast2 => "s3-ap-northeast-2.amazonaws.com",
            ApSoutheast1 => "s3-ap-southeast-1.amazonaws.com",
            ApSoutheast2 => "s3-ap-southeast-2.amazonaws.com",
            EuCentral1 => "s3-eu-central-1.amazonaws.com",
            EuWest1 => "s3-eu-west-1.amazonaws.com",
            EuWest2 => "s3-eu-west-2.amazonaws.com",
            SaEast1 => "s3-sa-east-1.amazonaws.com",
        }
    }
}<commit_msg>Add digital ocean's nyc3 region to the list of possible regions<commit_after>use std::fmt;
use std::str::{self, FromStr};

use error::{S3Result, S3Error};

/// AWS S3 [region identifier](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
///
/// # Example
/// ```
/// use std::str::FromStr;
/// use s3::region::Region;
///
/// // Parse from a string
/// let region: Region = "us-east-1".parse().unwrap();
///
/// // Choose region directly
/// let region = Region::EuWest2;
/// ```
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Region {
    /// us-east-1
    UsEast1,
    /// us-east-2
    UsEast2,
    /// us-west-1
    UsWest1,
    /// us-west-2
    UsWest2,
    /// ca-central-1
    CaCentral1,
    /// ap-south-1
    ApSouth1,
    /// ap-northeast-1
    ApNortheast1,
    /// ap-northeast-2
    ApNortheast2,
    /// ap-southeast-1
    ApSoutheast1,
    /// ap-southeast-2
    ApSoutheast2,
    /// eu-central-1
    EuCentral1,
    /// eu-west-1
    EuWest1,
    /// eu-west-2
    EuWest2,
    /// sa-east-1
    SaEast1,
    /// Digital Ocean nyc3
    DoNyc3,
}

impl fmt::Display for Region {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Region::*;
        match *self {
            UsEast1 => write!(f, "us-east-1"),
            UsEast2 => write!(f, "us-east-2"),
            UsWest1 => write!(f, "us-west-1"),
            UsWest2 => write!(f, "us-west-2"),
            CaCentral1 => write!(f, "ca-central-1"),
            ApSouth1 => write!(f, "ap-south-1"),
            ApNortheast1 => write!(f, "ap-northeast-1"),
            ApNortheast2 => write!(f, "ap-northeast-2"),
            ApSoutheast1 => write!(f, "ap-southeast-1"),
            ApSoutheast2 => write!(f, "ap-southeast-2"),
            EuCentral1 => write!(f, "eu-central-1"),
            EuWest1 => write!(f, "eu-west-1"),
            EuWest2 => write!(f, "eu-west-2"),
            SaEast1 => write!(f, "sa-east-1"),
            DoNyc3 => write!(f, "nyc3"),
        }
    }
}

impl FromStr for Region {
    type Err = S3Error;

    fn from_str(s: &str) -> S3Result<Self> {
        use self::Region::*;
        match s {
            "us-east-1" => Ok(UsEast1),
            "us-east-2" => Ok(UsEast2),
            "us-west-1" => Ok(UsWest1),
            "us-west-2" => Ok(UsWest2),
            "ca-central-1" => Ok(CaCentral1),
            "ap-south-1" => Ok(ApSouth1),
            "ap-northeast-1" => Ok(ApNortheast1),
            "ap-northeast-2" => Ok(ApNortheast2),
            "ap-southeast-1" => Ok(ApSoutheast1),
            "ap-southeast-2" => Ok(ApSoutheast2),
            "eu-central-1" => Ok(EuCentral1),
            "eu-west-1" => Ok(EuWest1),
            "eu-west-2" => Ok(EuWest2),
            "sa-east-1" => Ok(SaEast1),
            "nyc3" => Ok(DoNyc3),
            _ => Err(s.to_string().into()),
        }
    }
}

impl Region {
    pub fn endpoint(&self) -> &str {
        use self::Region::*;
        match *self {
            // Surprisingly, us-east-1 does not have a
            // s3-us-east-1.amazonaws.com DNS record
            UsEast1 => "s3.amazonaws.com",
            UsEast2 => "s3-us-east-2.amazonaws.com",
            UsWest1 => "s3-us-west-1.amazonaws.com",
            UsWest2 => "s3-us-west-2.amazonaws.com",
            CaCentral1 => "s3-ca-central-1.amazonaws.com",
            ApSouth1 => "s3-ap-south-1.amazonaws.com",
            ApNortheast1 => "s3-ap-northeast-1.amazonaws.com",
            ApNortheast2 => "s3-ap-northeast-2.amazonaws.com",
            ApSoutheast1 => "s3-ap-southeast-1.amazonaws.com",
            ApSoutheast2 => "s3-ap-southeast-2.amazonaws.com",
            EuCentral1 => "s3-eu-central-1.amazonaws.com",
            EuWest1 => "s3-eu-west-1.amazonaws.com",
            EuWest2 => "s3-eu-west-2.amazonaws.com",
            SaEast1 => "s3-sa-east-1.amazonaws.com",
            DoNyc3 => "nyc3.digitaloceanspaces.com",
        }
    }
}
<|endoftext|>


<commit_before>use serialize::{Decodable, json};
use request::Request;
use typemap::Key;
use plugin::{Plugin, Pluggable};
use std::io;
use std::io::{Read, ErrorKind};
use std::rc::Rc;

// Plugin boilerplate
struct JsonBodyParser;
impl Key for JsonBodyParser { type Value = String; }
impl<'a, 'b, 'k> Plugin<Request<'a, 'b, 'k>> for JsonBodyParser {
    // FIXME: Plugin requires Error to be `Clone`, but we can probably
    // do something so we don't need to have an `Rc`
    type Error = Rc<io::Error>;

    fn eval(req: &mut Request) -> Result<String, Rc<io::Error>> {
        let mut s = String::new();
        try!(req.origin.read_to_string(&mut s)
                       .map_err(Rc::new));
        Ok(s)
    }
}

pub trait JsonBody {
    fn json_as<T: Decodable>(&mut self) -> Result<T, Rc<io::Error>>;
}

impl<'a, 'b, 'k> JsonBody for Request<'a, 'b, 'k> {
    fn json_as<T: Decodable>(&mut self) -> Result<T, Rc<io::Error>> {
        self.get::<JsonBodyParser>().and_then(|parsed|
            json::decode::<T>(&*parsed).map_err(|_err|
                Rc::new(io::Error::new(ErrorKind::Other,
                               "Failed to parse JSON"))
                               // FIXME: change to below when rust#23979 lands
                               //format!("Failed to parse JSON: {}", err)
            )
        )
    }
}
<commit_msg>fix(json): return descriptive errors on failures in json_as<commit_after>use serialize::{Decodable, json};
use request::Request;
use typemap::Key;
use plugin::{Plugin, Pluggable};
use std::io;
use std::io::{Read, ErrorKind};
use std::rc::Rc;

// Plugin boilerplate
struct JsonBodyParser;
impl Key for JsonBodyParser { type Value = String; }
impl<'a, 'b, 'k> Plugin<Request<'a, 'b, 'k>> for JsonBodyParser {
    // FIXME: Plugin requires Error to be `Clone`, but we can probably
    // do something so we don't need to have an `Rc`
    type Error = Rc<io::Error>;

    fn eval(req: &mut Request) -> Result<String, Rc<io::Error>> {
        let mut s = String::new();
        try!(req.origin.read_to_string(&mut s)
                       .map_err(Rc::new));
        Ok(s)
    }
}

pub trait JsonBody {
    fn json_as<T: Decodable>(&mut self) -> Result<T, Rc<io::Error>>;
}

impl<'a, 'b, 'k> JsonBody for Request<'a, 'b, 'k> {
    fn json_as<T: Decodable>(&mut self) -> Result<T, Rc<io::Error>> {
        self.get::<JsonBodyParser>().and_then(|parsed|
            json::decode::<T>(&*parsed).map_err(|_err|
                Rc::new(io::Error::new(ErrorKind::Other,
                                   format!("Failed to parse JSON: {}", _err)))

            )
        )
    }
}
<|endoftext|>


<commit_before>/*!

Sendable hash maps.  Very much a work in progress.

*/

use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;

trait SendMap<K:Eq Hash, V: Copy> {
    // FIXME(#3148)  ^^^^ once find_ref() works, we can drop V:copy

    fn insert(&mut self, +k: K, +v: V) -> bool;
    fn remove(&mut self, k: &K) -> bool;
    fn clear(&mut self);
    pure fn len(&const self) -> uint;
    pure fn is_empty(&const self) -> bool;
    fn contains_key(&const self, k: &K) -> bool;
    fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool);
    fn each_key_ref(&self, blk: fn(k: &K) -> bool);
    fn each_value_ref(&self, blk: fn(v: &V) -> bool);
    fn find(&const self, k: &K) -> Option<V>;
    fn get(&const self, k: &K) -> V;
}

/// Open addressing with linear probing.
mod linear {
    export LinearMap, linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    struct Bucket<K:Eq Hash,V> {
        hash: uint,
        key: K,
        value: V,
    }
    struct LinearMap<K:Eq Hash,V> {
        k0: u64,
        k1: u64,
        resize_at: uint,
        size: uint,
        buckets: ~[Option<Bucket<K,V>>],
    }

    // FIXME(#3148) -- we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    // However, that won't work until #3148 is fixed
    enum SearchResult {
        FoundEntry(uint), FoundHole(uint), TableFull
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
        linear_map_with_capacity(32)
    }

    fn linear_map_with_capacity<K:Eq Hash,V>(
        initial_capacity: uint) -> LinearMap<K,V> {
        let r = rand::Rng();
        linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
                                          initial_capacity)
    }

    fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
        k0: u64, k1: u64,
        initial_capacity: uint) -> LinearMap<K,V> {
        LinearMap {
            k0: k0, k1: k1,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| None)
        }
    }

    priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
        #[inline(always)]
        pure fn to_bucket(&const self,
                          h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(&const self,
                            idx: uint,
                            len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n);
            }
            return n;
        }

        #[inline(always)]
        pure fn bucket_sequence(&const self,
                                hash: uint,
                                op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    return idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    return start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(&const self,
                               buckets: &[Option<Bucket<K,V>>],
                               k: &K) -> SearchResult {
            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(&const self,
                                         buckets: &[Option<Bucket<K,V>>],
                                         hash: uint,
                                         k: &K) -> SearchResult {
            let _ = for self.bucket_sequence(hash) |i| {
                match buckets[i] {
                  Some(bkt) => if bkt.hash == hash && *k == bkt.key {
                    return FoundEntry(i);
                  },
                  None => return FoundHole(i)
                }
            };
            return TableFull;
        }

        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand(&mut self) {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| None);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = None;
                bucket <-> old_buckets[i];
                self.insert_opt_bucket(move bucket);
            }
        }

        fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
            match move bucket {
              Some(Bucket {hash: move hash,
                           key: move key,
                           value: move value}) => {
                self.insert_internal(hash, move key, move value);
              }
              None => {}
            }
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(&mut self, hash: uint, +k: K, +v: V) -> bool {
            match self.bucket_for_key_with_hash(self.buckets, hash, &k) {
              TableFull => {fail ~"Internal logic error";}
              FoundHole(idx) => {
                debug!("insert fresh (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash);
                self.buckets[idx] = Some(Bucket {hash: hash,
                                                 key: k,
                                                 value: v});
                self.size += 1;
                return true;
              }
              FoundEntry(idx) => {
                debug!("insert overwrite (%?->%?) at idx %?, hash %?",
                       k, v, idx, hash);
                self.buckets[idx] = Some(Bucket {hash: hash,
                                                 key: k,
                                                 value: v});
                return false;
              }
            }
        }

        fn search(&self,
                  hash: uint,
                  op: fn(x: &Option<Bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
        fn insert(&mut self, +k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.insert_internal(hash, move k, move v)
        }

        fn remove(&mut self, k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = match self.bucket_for_key(self.buckets, k) {
              TableFull | FoundHole(_) => {
                return false;
              }
              FoundEntry(idx) => {
                idx
              }
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = None;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = None;
                bucket <-> self.buckets[idx];
                self.insert_opt_bucket(move bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            self.size -= 1;
            return true;
        }

        fn clear(&mut self) {
            for uint::range(0, self.buckets.len()) |idx| {
                self.buckets[idx] = None;
            }
            self.size = 0;
        }

        pure fn len(&const self) -> uint {
            self.size
        }

        pure fn is_empty(&const self) -> bool {
            self.len() == 0
        }

        fn contains_key(&const self,
                        k: &K) -> bool {
            match self.bucket_for_key(self.buckets, k) {
              FoundEntry(_) => {true}
              TableFull | FoundHole(_) => {false}
            }
        }

        /*
        FIXME(#3148)--region inference fails to capture needed deps

        fn find_ref(&self, k: &K) -> option<&self/V> {
            match self.bucket_for_key(self.buckets, k) {
              FoundEntry(idx) => {
                match check self.buckets[idx] {
                  some(ref bkt) => some(&bkt.value)
                }
              }
              TableFull | FoundHole(_) => {
                none
              }
            }
        }
        */

        fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }

        fn each_key_ref(&self, blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }

        fn each_value_ref(&self, blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl<K:Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn find(&const self, k: &K) -> Option<V> {
            match self.bucket_for_key(self.buckets, k) {
              FoundEntry(idx) => {
                // FIXME (#3148): Once we rewrite found_entry, this
                // failure case won't be necessary
                match self.buckets[idx] {
                    Some(bkt) => {Some(copy bkt.value)}
                    None => fail ~"LinearMap::find: internal logic error"
                }
              }
              TableFull | FoundHole(_) => {
                None
              }
            }
        }

        fn get(&const self, k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!("No entry found for key: %?", k);
            }
            option::unwrap(move value)
        }

    }

    impl<K: Hash IterBytes Eq Copy, V: Copy> LinearMap<K,V> {
        fn each(&self, blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl<K: Hash IterBytes Eq Copy, V> LinearMap<K,V> {
        fn each_key(&self, blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl<K: Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn each_value(&self, blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    use linear::LinearMap;

    fn int_linear_map<V>() -> LinearMap<uint,V> {
        return LinearMap();
    }

    #[test]
    fn inserts() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn empty() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert !m.is_empty();
        assert m.remove(&1);
        assert m.is_empty();
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(4);
        for uint::range(0, 32) |i| {
            assert m.insert(i, i*2);
        }
        let mut observed = 0;
        for m.each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }
}
<commit_msg>libcore: modernize send_map's whitespacing<commit_after>/*!

Sendable hash maps.  Very much a work in progress.

*/

use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;

trait SendMap<K:Eq Hash, V: Copy> {
    // FIXME(#3148)  ^^^^ once find_ref() works, we can drop V:copy

    fn insert(&mut self, +k: K, +v: V) -> bool;
    fn remove(&mut self, k: &K) -> bool;
    fn clear(&mut self);
    pure fn len(&const self) -> uint;
    pure fn is_empty(&const self) -> bool;
    fn contains_key(&const self, k: &K) -> bool;
    fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool);
    fn each_key_ref(&self, blk: fn(k: &K) -> bool);
    fn each_value_ref(&self, blk: fn(v: &V) -> bool);
    fn find(&const self, k: &K) -> Option<V>;
    fn get(&const self, k: &K) -> V;
}

/// Open addressing with linear probing.
mod linear {
    export LinearMap, linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    struct Bucket<K:Eq Hash,V> {
        hash: uint,
        key: K,
        value: V,
    }
    struct LinearMap<K:Eq Hash,V> {
        k0: u64,
        k1: u64,
        resize_at: uint,
        size: uint,
        buckets: ~[Option<Bucket<K,V>>],
    }

    // FIXME(#3148) -- we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    // However, that won't work until #3148 is fixed
    enum SearchResult {
        FoundEntry(uint), FoundHole(uint), TableFull
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
        linear_map_with_capacity(32)
    }

    fn linear_map_with_capacity<K:Eq Hash,V>(
        initial_capacity: uint) -> LinearMap<K,V> {
        let r = rand::Rng();
        linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
                                          initial_capacity)
    }

    fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
        k0: u64, k1: u64,
        initial_capacity: uint) -> LinearMap<K,V> {
        LinearMap {
            k0: k0, k1: k1,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| None)
        }
    }

    priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
        #[inline(always)]
        pure fn to_bucket(&const self,
                          h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(&const self,
                            idx: uint,
                            len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n);
            }
            return n;
        }

        #[inline(always)]
        pure fn bucket_sequence(&const self,
                                hash: uint,
                                op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    return idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    return start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(&const self,
                               buckets: &[Option<Bucket<K,V>>],
                               k: &K) -> SearchResult {
            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(&const self,
                                         buckets: &[Option<Bucket<K,V>>],
                                         hash: uint,
                                         k: &K) -> SearchResult {
            let _ = for self.bucket_sequence(hash) |i| {
                match buckets[i] {
                    Some(bkt) => if bkt.hash == hash && *k == bkt.key {
                        return FoundEntry(i);
                    },
                    None => return FoundHole(i)
                }
            };
            return TableFull;
        }

        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand(&mut self) {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| None);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = None;
                bucket <-> old_buckets[i];
                self.insert_opt_bucket(move bucket);
            }
        }

        fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
            match move bucket {
                Some(Bucket {hash: move hash,
                             key: move key,
                             value: move value}) => {
                    self.insert_internal(hash, move key, move value);
                }
                None => {}
            }
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(&mut self, hash: uint, +k: K, +v: V) -> bool {
            match self.bucket_for_key_with_hash(self.buckets, hash, &k) {
                TableFull => { fail ~"Internal logic error"; }
                FoundHole(idx) => {
                    debug!("insert fresh (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    self.size += 1;
                    true
                }
                FoundEntry(idx) => {
                    debug!("insert overwrite (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    false
                }
            }
        }

        fn search(&self,
                  hash: uint,
                  op: fn(x: &Option<Bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
        fn insert(&mut self, +k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.insert_internal(hash, move k, move v)
        }

        fn remove(&mut self, k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = match self.bucket_for_key(self.buckets, k) {
                TableFull | FoundHole(_) => return false,
                FoundEntry(idx) => idx
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = None;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = None;
                bucket <-> self.buckets[idx];
                self.insert_opt_bucket(move bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            self.size -= 1;
            return true;
        }

        fn clear(&mut self) {
            for uint::range(0, self.buckets.len()) |idx| {
                self.buckets[idx] = None;
            }
            self.size = 0;
        }

        pure fn len(&const self) -> uint {
            self.size
        }

        pure fn is_empty(&const self) -> bool {
            self.len() == 0
        }

        fn contains_key(&const self,
                        k: &K) -> bool {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(_) => {true}
                TableFull | FoundHole(_) => {false}
            }
        }

        /*
        FIXME(#3148)--region inference fails to capture needed deps

        fn find_ref(&self, k: &K) -> option<&self/V> {
            match self.bucket_for_key(self.buckets, k) {
              FoundEntry(idx) => {
                match check self.buckets[idx] {
                  some(ref bkt) => some(&bkt.value)
                }
              }
              TableFull | FoundHole(_) => {
                none
              }
            }
        }
        */

        fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }

        fn each_key_ref(&self, blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }

        fn each_value_ref(&self, blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl<K:Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn find(&const self, k: &K) -> Option<V> {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(idx) => {
                    // FIXME (#3148): Once we rewrite found_entry, this
                    // failure case won't be necessary
                    match self.buckets[idx] {
                        Some(bkt) => {Some(copy bkt.value)}
                        None => fail ~"LinearMap::find: internal logic error"
                    }
                }
                TableFull | FoundHole(_) => {
                    None
                }
            }
        }

        fn get(&const self, k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!("No entry found for key: %?", k);
            }
            option::unwrap(move value)
        }

    }

    impl<K: Hash IterBytes Eq Copy, V: Copy> LinearMap<K,V> {
        fn each(&self, blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl<K: Hash IterBytes Eq Copy, V> LinearMap<K,V> {
        fn each_key(&self, blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl<K: Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn each_value(&self, blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    use linear::LinearMap;

    fn int_linear_map<V>() -> LinearMap<uint,V> {
        return LinearMap();
    }

    #[test]
    fn inserts() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn empty() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert !m.is_empty();
        assert m.remove(&1);
        assert m.is_empty();
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(4);
        for uint::range(0, 32) |i| {
            assert m.insert(i, i*2);
        }
        let mut observed = 0;
        for m.each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }
}
<|endoftext|>