<commit_before>use super::{flow::FlowLogic, Shell, Variables};
use parser::{assignments::*, pipelines::Pipeline};
use std::fmt::{self, Display, Formatter};
use std::mem;
use types::Identifier;

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct ElseIf {
    pub expression: Pipeline,
    pub success:    Vec<Statement>,
}

/// Represents a single branch in a match statement. For example, in the expression
/// ```ignore
/// match value
///   ...
///   case value
///     statement0
///     statement1
///     ...
///     statementN
///   end
/// end
/// ```
/// would be represented by the Case object:
/// ```rust,ignore
/// Case {
///     value:      Some(value),
///     statements: vec![statement0, statement1, ... statementN],
/// }
/// ```
/// The wildcard branch, a branch that matches any value, is represented as such:
/// ```rust,ignore
/// Case { value: None, ... }
/// ```
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Case {
    pub value:       Option<String>,
    pub binding:     Option<String>,
    pub conditional: Option<String>,
    pub statements:  Vec<Statement>,
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum LocalAction {
    List,
    Assign(String, Operator, String),
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum ExportAction {
    List,
    LocalExport(String),
    Assign(String, Operator, String),
}

// TODO: Enable statements and expressions to contain &str values.
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum Statement {
    Let(LocalAction),
    Case(Case),
    Export(ExportAction),
    If {
        expression: Pipeline,
        success:    Vec<Statement>,
        else_if:    Vec<ElseIf>,
        failure:    Vec<Statement>,
    },
    ElseIf(ElseIf),
    Function {
        name:        Identifier,
        description: Option<String>,
        args:        Vec<KeyBuf>,
        statements:  Vec<Statement>,
    },
    For {
        variable:   Identifier,
        values:     Vec<String>,
        statements: Vec<Statement>,
    },
    While {
        expression: Pipeline,
        statements: Vec<Statement>,
    },
    Match {
        expression: String,
        cases:      Vec<Case>,
    },
    Else,
    End,
    Error(i32),
    Break,
    Continue,
    Pipeline(Pipeline),
    Time(Box<Statement>),
    And(Box<Statement>),
    Or(Box<Statement>),
    Not(Box<Statement>),
    Default,
}

impl Statement {
    pub(crate) fn short(&self) -> &'static str {
        match *self {
            Statement::Let { .. } => "Let { .. }",
            Statement::Case(_) => "Case { .. }",
            Statement::Export(_) => "Export { .. }",
            Statement::If { .. } => "If { .. }",
            Statement::ElseIf(_) => "ElseIf { .. }",
            Statement::Function { .. } => "Function { .. }",
            Statement::For { .. } => "For { .. }",
            Statement::While { .. } => "While { .. }",
            Statement::Match { .. } => "Match { .. }",
            Statement::Else => "Else",
            Statement::End => "End",
            Statement::Error(_) => "Error { .. }",
            Statement::Break => "Break",
            Statement::Continue => "Continue",
            Statement::Pipeline(_) => "Pipeline { .. }",
            Statement::Time(_) => "Time { .. }",
            Statement::And(_) => "And { .. }",
            Statement::Or(_) => "Or { .. }",
            Statement::Not(_) => "Not { .. }",
            Statement::Default => "Default",
        }
    }
}

pub(crate) struct FlowControl {
    pub level:             usize,
    pub current_statement: Statement,
    pub current_if_mode:   u8, // { 0 = SUCCESS; 1 = FAILURE }
}

impl Default for FlowControl {
    fn default() -> FlowControl {
        FlowControl {
            level:             0,
            current_statement: Statement::Default,
            current_if_mode:   0,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Function {
    description: Option<String>,
    name:        Identifier,
    args:        Vec<KeyBuf>,
    statements:  Vec<Statement>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum FunctionError {
    InvalidArgumentCount,
    InvalidArgumentType(Primitive, String),
}

impl Display for FunctionError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        use self::FunctionError::*;
        match *self {
            InvalidArgumentCount => write!(fmt, "invalid number of arguments"),
            InvalidArgumentType(t, ref value) => write!(fmt, "{} is not of type {}", value, t),
        }
    }
}

impl Function {
    pub(crate) fn execute<S: AsRef<str>>(self, shell: &mut Shell, args: &[S]) -> Result<(), FunctionError> {
        if args.len() - 1 != self.args.len() {
            return Err(FunctionError::InvalidArgumentCount);
        }

        let name = self.name.clone();

        shell.with_vars(|mut vars| {
            while !vars.functions.borrow().contains_key(&name) {
                vars = vars.parent.expect("execute called on function that's not in scope");
            }
            let vars = vars.new_scope();
            // TODO: THIS IS SUPER UNSAFE!!!!!11111
            // I'm bypassing the borrow checker here because I'm too gosh darn lazy
            // to make Shell take a lifetime pararmeter.
            // THIS. IS. WRONG.
            // This should be fixed. Some day. Ugh.
            // Don't do this at home, kids!
            let vars: Variables<'static> = unsafe { mem::transmute(vars) };
            vars
        }, move |shell| {
            for (type_, value) in self.args.into_iter().zip(args.iter().skip(1)) {
                let value = match value_check(shell, value.as_ref(), type_.kind) {
                    Ok(value) => value,
                    Err(_) => {
                        return Err(FunctionError::InvalidArgumentType(
                            type_.kind,
                            value.as_ref().into(),
                        ))
                    }
                };

                match value {
                    ReturnValue::Vector(vector) => {
                        shell.variables.arrays.borrow_mut().insert(type_.name.into(), vector);
                    }
                    ReturnValue::Str(string) => {
                        shell.variables.variables.borrow_mut().insert(type_.name.into(), string);
                    }
                }
            }

            shell.execute_statements(self.statements);
            Ok(())
        })
    }

    pub(crate) fn get_description<'a>(&'a self) -> Option<&'a String> { self.description.as_ref() }

    pub(crate) fn new(
        description: Option<String>,
        name: Identifier,
        args: Vec<KeyBuf>,
        statements: Vec<Statement>,
    ) -> Function {
        Function {
            description,
            name,
            args,
            statements,
        }
    }
}

pub(crate) fn collect_cases<I>(
    iterator: &mut I,
    cases: &mut Vec<Case>,
    level: &mut usize,
) -> Result<(), String>
where
    I: Iterator<Item = Statement>,
{
    macro_rules! add_to_case {
        ($statement:expr) => {
            match cases.last_mut() {
                // XXX: When does this actually happen? What syntax error is this???
                None => {
                    return Err([
                        "ion: syntax error: encountered ",
                        $statement.short(),
                        " outside of `case ...` block",
                    ].concat())
                }
                Some(ref mut case) => case.statements.push($statement),
            }
        };
    }

    while let Some(statement) = iterator.next() {
        match statement {
            Statement::Case(case) => {
                if *level == 1 {
                    // If the level is 1, then we are at a top-level case
                    // statement for this match block and should push this case
                    cases.push(case);
                } else {
                    // This is just part of the current case block
                    add_to_case!(Statement::Case(case));
                }
            }
            Statement::End => {
                *level -= 1;
                if *level == 0 {
                    return Ok(());
                }
            }
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Match { .. }
            | Statement::Function { .. } => {
                *level += 1;
                add_to_case!(statement);
            }
            Statement::Default
            | Statement::Else
            | Statement::ElseIf { .. }
            | Statement::Error(_)
            | Statement::Export(_)
            | Statement::Continue
            | Statement::Let { .. }
            | Statement::Pipeline(_)
            | Statement::Time(_)
            | Statement::And(_)
            | Statement::Or(_)
            | Statement::Not(_)
            | Statement::Break => {
                // This is the default case with all of the other statements explicitly listed
                add_to_case!(statement);
            }
        }
    }
    return Ok(());
}

pub(crate) fn collect_loops<I: Iterator<Item = Statement>>(
    iterator: &mut I,
    statements: &mut Vec<Statement>,
    level: &mut usize,
) {
    #[allow(while_let_on_iterator)]
    while let Some(statement) = iterator.next() {
        match statement {
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Function { .. }
            | Statement::Match { .. } => *level += 1,
            Statement::Time(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::And(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::Or(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::Not(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::End if *level == 1 => {
                *level = 0;
                break;
            }
            Statement::End => *level -= 1,
            _ => (),
        }
        statements.push(statement);
    }
}

pub(crate) fn collect_if<I>(
    iterator: &mut I,
    success: &mut Vec<Statement>,
    else_if: &mut Vec<ElseIf>,
    failure: &mut Vec<Statement>,
    level: &mut usize,
    mut current_block: u8,
) -> Result<u8, &'static str>
where
    I: Iterator<Item = Statement>,
{
    #[allow(while_let_on_iterator)]
    while let Some(statement) = iterator.next() {
        match statement {
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Function { .. }
            | Statement::Match { .. } => *level += 1,
            Statement::ElseIf(ref elseif) if *level == 1 => if current_block == 1 {
                return Err("ion: syntax error: else block already given");
            } else {
                current_block = 2;
                else_if.push(elseif.clone());
                continue;
            },
            Statement::Else if *level == 1 => {
                current_block = 1;
                continue;
            }
            Statement::Else if *level == 1 && current_block == 1 => {
                return Err("ion: syntax error: else block already given")
            }
            Statement::End if *level == 1 => {
                *level = 0;
                break;
            }
            Statement::End => *level -= 1,
            _ => (),
        }

        match current_block {
            0 => success.push(statement),
            1 => failure.push(statement),
            2 => {
                let last = else_if.last_mut().unwrap(); // This is a bug if there isn't a value
                last.success.push(statement);
            }
            _ => unreachable!(),
        }
    }

    Ok(current_block)
}
<commit_msg>Fix herestring test<commit_after>use super::{flow::FlowLogic, Shell, Variables};
use parser::{assignments::*, pipelines::Pipeline};
use smallvec::SmallVec;
use std::fmt::{self, Display, Formatter};
use std::mem;
use types::Identifier;

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct ElseIf {
    pub expression: Pipeline,
    pub success:    Vec<Statement>,
}

/// Represents a single branch in a match statement. For example, in the expression
/// ```ignore
/// match value
///   ...
///   case value
///     statement0
///     statement1
///     ...
///     statementN
///   end
/// end
/// ```
/// would be represented by the Case object:
/// ```rust,ignore
/// Case {
///     value:      Some(value),
///     statements: vec![statement0, statement1, ... statementN],
/// }
/// ```
/// The wildcard branch, a branch that matches any value, is represented as such:
/// ```rust,ignore
/// Case { value: None, ... }
/// ```
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Case {
    pub value:       Option<String>,
    pub binding:     Option<String>,
    pub conditional: Option<String>,
    pub statements:  Vec<Statement>,
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum LocalAction {
    List,
    Assign(String, Operator, String),
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum ExportAction {
    List,
    LocalExport(String),
    Assign(String, Operator, String),
}

// TODO: Enable statements and expressions to contain &str values.
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum Statement {
    Let(LocalAction),
    Case(Case),
    Export(ExportAction),
    If {
        expression: Pipeline,
        success:    Vec<Statement>,
        else_if:    Vec<ElseIf>,
        failure:    Vec<Statement>,
    },
    ElseIf(ElseIf),
    Function {
        name:        Identifier,
        description: Option<String>,
        args:        Vec<KeyBuf>,
        statements:  Vec<Statement>,
    },
    For {
        variable:   Identifier,
        values:     Vec<String>,
        statements: Vec<Statement>,
    },
    While {
        expression: Pipeline,
        statements: Vec<Statement>,
    },
    Match {
        expression: String,
        cases:      Vec<Case>,
    },
    Else,
    End,
    Error(i32),
    Break,
    Continue,
    Pipeline(Pipeline),
    Time(Box<Statement>),
    And(Box<Statement>),
    Or(Box<Statement>),
    Not(Box<Statement>),
    Default,
}

impl Statement {
    pub(crate) fn short(&self) -> &'static str {
        match *self {
            Statement::Let { .. } => "Let { .. }",
            Statement::Case(_) => "Case { .. }",
            Statement::Export(_) => "Export { .. }",
            Statement::If { .. } => "If { .. }",
            Statement::ElseIf(_) => "ElseIf { .. }",
            Statement::Function { .. } => "Function { .. }",
            Statement::For { .. } => "For { .. }",
            Statement::While { .. } => "While { .. }",
            Statement::Match { .. } => "Match { .. }",
            Statement::Else => "Else",
            Statement::End => "End",
            Statement::Error(_) => "Error { .. }",
            Statement::Break => "Break",
            Statement::Continue => "Continue",
            Statement::Pipeline(_) => "Pipeline { .. }",
            Statement::Time(_) => "Time { .. }",
            Statement::And(_) => "And { .. }",
            Statement::Or(_) => "Or { .. }",
            Statement::Not(_) => "Not { .. }",
            Statement::Default => "Default",
        }
    }
}

pub(crate) struct FlowControl {
    pub level:             usize,
    pub current_statement: Statement,
    pub current_if_mode:   u8, // { 0 = SUCCESS; 1 = FAILURE }
}

impl Default for FlowControl {
    fn default() -> FlowControl {
        FlowControl {
            level:             0,
            current_statement: Statement::Default,
            current_if_mode:   0,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Function {
    description: Option<String>,
    name:        Identifier,
    args:        Vec<KeyBuf>,
    statements:  Vec<Statement>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum FunctionError {
    InvalidArgumentCount,
    InvalidArgumentType(Primitive, String),
}

impl Display for FunctionError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        use self::FunctionError::*;
        match *self {
            InvalidArgumentCount => write!(fmt, "invalid number of arguments"),
            InvalidArgumentType(t, ref value) => write!(fmt, "{} is not of type {}", value, t),
        }
    }
}

impl Function {
    pub(crate) fn execute<S: AsRef<str>>(self, shell: &mut Shell, args: &[S]) -> Result<(), FunctionError> {
        if args.len() - 1 != self.args.len() {
            return Err(FunctionError::InvalidArgumentCount);
        }

        let name = self.name.clone();

        let mut values: SmallVec<[_; 8]> = SmallVec::new();

        for (type_, value) in self.args.iter().zip(args.iter().skip(1)) {
            let value = match value_check(shell, value.as_ref(), type_.kind) {
                Ok(value) => value,
                Err(_) => {
                    return Err(FunctionError::InvalidArgumentType(
                        type_.kind,
                        value.as_ref().into(),
                    ))
                }
            };

            values.push((type_.clone(), value));
        }

        shell.with_vars(|mut vars| {
            while !vars.functions.borrow().contains_key(&name) {
                vars = vars.parent.expect("execute called on function that's not in scope");
            }
            let vars = vars.new_scope();
            // TODO: THIS IS SUPER UNSAFE!!!!!11111
            // I'm bypassing the borrow checker here because I'm too gosh darn lazy
            // to make Shell take a lifetime pararmeter.
            // THIS. IS. WRONG.
            // This should be fixed. Some day. Ugh.
            // Don't do this at home, kids!
            let vars: Variables<'static> = unsafe { mem::transmute(vars) };
            vars
        }, move |shell| {
            for (type_, value) in values {
                match value {
                    ReturnValue::Vector(vector) => {
                        shell.variables.arrays.borrow_mut().insert(type_.name.into(), vector);
                    }
                    ReturnValue::Str(string) => {
                        shell.variables.variables.borrow_mut().insert(type_.name.into(), string);
                    }
                }
            }

            shell.execute_statements(self.statements);
            Ok(())
        })
    }

    pub(crate) fn get_description<'a>(&'a self) -> Option<&'a String> { self.description.as_ref() }

    pub(crate) fn new(
        description: Option<String>,
        name: Identifier,
        args: Vec<KeyBuf>,
        statements: Vec<Statement>,
    ) -> Function {
        Function {
            description,
            name,
            args,
            statements,
        }
    }
}

pub(crate) fn collect_cases<I>(
    iterator: &mut I,
    cases: &mut Vec<Case>,
    level: &mut usize,
) -> Result<(), String>
where
    I: Iterator<Item = Statement>,
{
    macro_rules! add_to_case {
        ($statement:expr) => {
            match cases.last_mut() {
                // XXX: When does this actually happen? What syntax error is this???
                None => {
                    return Err([
                        "ion: syntax error: encountered ",
                        $statement.short(),
                        " outside of `case ...` block",
                    ].concat())
                }
                Some(ref mut case) => case.statements.push($statement),
            }
        };
    }

    while let Some(statement) = iterator.next() {
        match statement {
            Statement::Case(case) => {
                if *level == 1 {
                    // If the level is 1, then we are at a top-level case
                    // statement for this match block and should push this case
                    cases.push(case);
                } else {
                    // This is just part of the current case block
                    add_to_case!(Statement::Case(case));
                }
            }
            Statement::End => {
                *level -= 1;
                if *level == 0 {
                    return Ok(());
                }
            }
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Match { .. }
            | Statement::Function { .. } => {
                *level += 1;
                add_to_case!(statement);
            }
            Statement::Default
            | Statement::Else
            | Statement::ElseIf { .. }
            | Statement::Error(_)
            | Statement::Export(_)
            | Statement::Continue
            | Statement::Let { .. }
            | Statement::Pipeline(_)
            | Statement::Time(_)
            | Statement::And(_)
            | Statement::Or(_)
            | Statement::Not(_)
            | Statement::Break => {
                // This is the default case with all of the other statements explicitly listed
                add_to_case!(statement);
            }
        }
    }
    return Ok(());
}

pub(crate) fn collect_loops<I: Iterator<Item = Statement>>(
    iterator: &mut I,
    statements: &mut Vec<Statement>,
    level: &mut usize,
) {
    #[allow(while_let_on_iterator)]
    while let Some(statement) = iterator.next() {
        match statement {
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Function { .. }
            | Statement::Match { .. } => *level += 1,
            Statement::Time(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::And(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::Or(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::Not(ref box_stmt) => match box_stmt.as_ref() {
                &Statement::While { .. }
                | &Statement::For { .. }
                | &Statement::If { .. }
                | &Statement::Function { .. }
                | &Statement::Match { .. } => *level += 1,
                &Statement::End if *level == 1 => {
                    *level = 0;
                    break;
                }
                &Statement::End => *level -= 1,
                _ => (),
            },
            Statement::End if *level == 1 => {
                *level = 0;
                break;
            }
            Statement::End => *level -= 1,
            _ => (),
        }
        statements.push(statement);
    }
}

pub(crate) fn collect_if<I>(
    iterator: &mut I,
    success: &mut Vec<Statement>,
    else_if: &mut Vec<ElseIf>,
    failure: &mut Vec<Statement>,
    level: &mut usize,
    mut current_block: u8,
) -> Result<u8, &'static str>
where
    I: Iterator<Item = Statement>,
{
    #[allow(while_let_on_iterator)]
    while let Some(statement) = iterator.next() {
        match statement {
            Statement::While { .. }
            | Statement::For { .. }
            | Statement::If { .. }
            | Statement::Function { .. }
            | Statement::Match { .. } => *level += 1,
            Statement::ElseIf(ref elseif) if *level == 1 => if current_block == 1 {
                return Err("ion: syntax error: else block already given");
            } else {
                current_block = 2;
                else_if.push(elseif.clone());
                continue;
            },
            Statement::Else if *level == 1 => {
                current_block = 1;
                continue;
            }
            Statement::Else if *level == 1 && current_block == 1 => {
                return Err("ion: syntax error: else block already given")
            }
            Statement::End if *level == 1 => {
                *level = 0;
                break;
            }
            Statement::End => *level -= 1,
            _ => (),
        }

        match current_block {
            0 => success.push(statement),
            1 => failure.push(statement),
            2 => {
                let last = else_if.last_mut().unwrap(); // This is a bug if there isn't a value
                last.success.push(statement);
            }
            _ => unreachable!(),
        }
    }

    Ok(current_block)
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate rusqlite;

use common::bookmark::Bookmark;
use dao::query_parser::*;
use self::rusqlite::Connection;

#[derive(Debug)]
pub struct BookmarkDao {
    connection: rusqlite::Connection,

    read_sql: String,
    delete_sql: String,
    insert_sql: String,
    update_sql: String,
    list_sql: String
}

impl BookmarkDao {
    pub fn new() -> BookmarkDao {

        BookmarkDao {
            connection: Connection::open_in_memory().unwrap(),
            read_sql: load_sql_file("res/sql/bookmark/read.sql"),
            delete_sql: load_sql_file("res/sql/bookmark/delete.sql"),
            insert_sql: load_sql_file("res/sql/bookmark/insert.sql"),
            update_sql: load_sql_file("res/sql/bookmark/update.sql"),
            list_sql: load_sql_file("res/sql/bookmark/list.sql")
        }
    }

    pub fn insert(&self, b: Bookmark ) {
        //self.connection.execute(query, params: &[&ToSql])

    }

    pub fn delete(&self) {

    }

    pub fn read(&self, b: Bookmark) {

    }

    pub fn update(&self, b: Bookmark ){

    }

    pub fn list(&self, b: Bookmark) {
        let parsed_query = parse_query(&b.to_btree(), self.list_sql);

        match self.connection.execute(parsed_query.as_str(), &[] ) {
            Ok(listed) => println!("{} rows were listed", listed),
            Err(err) => println!("listed failed: {}", err),
        }
    }
}

pub fn hello_from_dao() -> String {
    "Hello, I am bookmark dao!".to_string()
}
<commit_msg>reference value fixes for list<commit_after>extern crate chrono;
extern crate rusqlite;

use common::bookmark::Bookmark;
use dao::query_parser::*;
use self::rusqlite::Connection;

#[derive(Debug)]
pub struct BookmarkDao {
    connection: rusqlite::Connection,

    read_sql: String,
    delete_sql: String,
    insert_sql: String,
    update_sql: String,
    list_sql: String
}

impl BookmarkDao {
    pub fn new() -> BookmarkDao {

        BookmarkDao {
            connection: Connection::open_in_memory().unwrap(),
            read_sql: load_sql_file("res/sql/bookmark/read.sql"),
            delete_sql: load_sql_file("res/sql/bookmark/delete.sql"),
            insert_sql: load_sql_file("res/sql/bookmark/insert.sql"),
            update_sql: load_sql_file("res/sql/bookmark/update.sql"),
            list_sql: load_sql_file("res/sql/bookmark/list.sql")
        }
    }

    pub fn insert(&self, b: Bookmark ) {
        //self.connection.execute(query, params: &[&ToSql])

    }

    pub fn delete(&self) {

    }

    pub fn read(&self, b: Bookmark) {

    }

    pub fn update(&self, b: Bookmark ){

    }

    pub fn list(&self, b: Bookmark) {
        let parsed_query = parse_query(&b.to_btree(), String::from(&*self.list_sql));

        match self.connection.execute(parsed_query.as_str(), &[] ) {
            Ok(listed) => println!("{} rows were listed", listed),
            Err(err) => println!("listed failed: {}", err),
        }
    }
}

pub fn hello_from_dao() -> String {
    "Hello, I am bookmark dao!".to_string()
}
<|endoftext|>


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

use lang::Lang;
use extractor::Extractor;

/// Generate the `lformat!` macro
pub fn generate_lformat(langs: &mut [Lang], extractor: &Extractor) -> String {
    let mut arg_variant = String::new();
    let mut noarg_variant = String::new();

    for i in 0..langs.len() {
        let (curr, rest) = langs.split_at_mut(i + 1);
        let ref mut hash = curr[i].content;

        // Write keys and translations from the po files
        for (key, value) in hash {
            let b = has_arguments(key);
            let mut inner = String::new();
            if b {
                inner.push_str(&format!("            \"{}\" => format!(\"{}\", $($arg)*),\n",
                                       curr[i].lang,
                                       value));
            } else {
                inner.push_str(&format!("            \"{}\" => format!(\"{}\"),\n",
                                       curr[i].lang,
                                       value));
            }

            for other_lang in rest.iter_mut() {
                let ref mut hash = other_lang.content;
                if let Some(value) = hash.remove(key) {
                    if b {
                        inner.push_str(&format!("            \"{}\" => format!(\"{}\", $($arg)*),\n",
                                                other_lang.lang,
                                                value));
                    } else {
                        inner.push_str(&format!("            \"{}\" => format!(\"{}\"),\n",
                                                        other_lang.lang,
                                                        value));
                    }
                }
            }

            if b {
                inner.push_str(&format!("            _ => format!(\"{}\", $($arg)*),\n",
                                        key));
            } else {
                inner.push_str(&format!("            _ => format!(\"{}\"),\n",
                                        key));
            }

            let this_variant = format!("        let __guard = $crate::__get_lang();
        match __guard.as_str() {{
{}        }}",
            inner);

            if b {
                arg_variant.push_str(&format!("    (\"{}\", $($arg:tt)*) => ({{
{}
    }});\n",
                                              key, this_variant));
            } else {
                noarg_variant.push_str(&format!("    (\"{}\") => ({{
{}
    }});\n",
                                                key, this_variant));
            }
        }

        // Add translations from exact msg formats used in lformat! to the ones
        // Used in .po files (e.g. might not have the same escape codes)
        for (key, value) in extractor.original_strings() {
            if has_arguments(key) {
                arg_variant.push_str(&format!("    (\"{}\", $($arg:tt)*) => (lformat!(\"{}\", $($arg)*));\n",
                                              key, value));
            } else {
                noarg_variant.push_str(&format!("    (\"{}\") => (lformat!(\"{}\"));\n",
                                              key, value));
            }
        }
    }

    format!("/// Localized format macro (or `lformat!` in short)
/// Should be similar to `format!`, except strings are localized
/// Generated automatically, you should not edit it.
#[macro_export] macro_rules! lformat {{
{}{}    ($($arg:tt)*) => (format!($($arg)*));
}}",
            &arg_variant,
            &noarg_variant)
}

/// Generate the file containing the localization macros
pub fn generate_macro_file(langs: &mut [Lang], extractor: &Extractor) -> String {
    let mut output = String::from(include_str!("../data/localize_macros.rs"));
    output.push_str(&generate_lformat(langs, extractor));
    output
}

/// Returns true if s contains arguments, false else
fn has_arguments(s: &str) -> bool {
    let chars:Vec<_> = s.chars().collect();
    for i in 0..chars.len() {
        let c = chars[i];
        if c == '{' || c == '}' {
            if i >= chars.len() - 1 {
                return true;
            } else {
                let next_c = chars[i+1];
                return !(c == next_c);
            }
        }
    }
    false
}

#[test]
fn test_arguments() {
    assert_eq!(has_arguments("foo bar"), false);
    assert_eq!(has_arguments("foo {}"), true);
    assert_eq!(has_arguments("foo {{bar}}"), false);
}
<commit_msg>Fix comment of lformat<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use lang::Lang;
use extractor::Extractor;

/// Generate the `lformat!` macro
pub fn generate_lformat(langs: &mut [Lang], extractor: &Extractor) -> String {
    let mut arg_variant = String::new();
    let mut noarg_variant = String::new();

    for i in 0..langs.len() {
        let (curr, rest) = langs.split_at_mut(i + 1);
        let ref mut hash = curr[i].content;

        // Write keys and translations from the po files
        for (key, value) in hash {
            let b = has_arguments(key);
            let mut inner = String::new();
            if b {
                inner.push_str(&format!("            \"{}\" => format!(\"{}\", $($arg)*),\n",
                                       curr[i].lang,
                                       value));
            } else {
                inner.push_str(&format!("            \"{}\" => format!(\"{}\"),\n",
                                       curr[i].lang,
                                       value));
            }

            for other_lang in rest.iter_mut() {
                let ref mut hash = other_lang.content;
                if let Some(value) = hash.remove(key) {
                    if b {
                        inner.push_str(&format!("            \"{}\" => format!(\"{}\", $($arg)*),\n",
                                                other_lang.lang,
                                                value));
                    } else {
                        inner.push_str(&format!("            \"{}\" => format!(\"{}\"),\n",
                                                        other_lang.lang,
                                                        value));
                    }
                }
            }

            if b {
                inner.push_str(&format!("            _ => format!(\"{}\", $($arg)*),\n",
                                        key));
            } else {
                inner.push_str(&format!("            _ => format!(\"{}\"),\n",
                                        key));
            }

            let this_variant = format!("        let __guard = $crate::__get_lang();
        match __guard.as_str() {{
{}        }}",
            inner);

            if b {
                arg_variant.push_str(&format!("    (\"{}\", $($arg:tt)*) => ({{
{}
    }});\n",
                                              key, this_variant));
            } else {
                noarg_variant.push_str(&format!("    (\"{}\") => ({{
{}
    }});\n",
                                                key, this_variant));
            }
        }

        // Add translations from exact msg formats used in lformat! to the ones
        // Used in .po files (e.g. might not have the same escape codes)
        for (key, value) in extractor.original_strings() {
            if has_arguments(key) {
                arg_variant.push_str(&format!("    (\"{}\", $($arg:tt)*) => (lformat!(\"{}\", $($arg)*));\n",
                                              key, value));
            } else {
                noarg_variant.push_str(&format!("    (\"{}\") => (lformat!(\"{}\"));\n",
                                              key, value));
            }
        }
    }

    format!("/// Localized format macro (or `lformat!` in short)
///
/// Should be similar to `format!`, except strings are localized.
/// Generated automatically, you should not edit it.
#[macro_export] macro_rules! lformat {{
{}{}    ($($arg:tt)*) => (format!($($arg)*));
}}",
            &arg_variant,
            &noarg_variant)
}

/// Generate the file containing the localization macros
pub fn generate_macro_file(langs: &mut [Lang], extractor: &Extractor) -> String {
    let mut output = String::from(include_str!("../data/localize_macros.rs"));
    output.push_str(&generate_lformat(langs, extractor));
    output
}

/// Returns true if s contains arguments, false else
fn has_arguments(s: &str) -> bool {
    let chars:Vec<_> = s.chars().collect();
    for i in 0..chars.len() {
        let c = chars[i];
        if c == '{' || c == '}' {
            if i >= chars.len() - 1 {
                return true;
            } else {
                let next_c = chars[i+1];
                return !(c == next_c);
            }
        }
    }
    false
}

#[test]
fn test_arguments() {
    assert_eq!(has_arguments("foo bar"), false);
    assert_eq!(has_arguments("foo {}"), true);
    assert_eq!(has_arguments("foo {{bar}}"), false);
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

#[derive(Debug, PartialEq)]
pub struct Result {
    pub path: PathBuf,
    score: usize,
}

/// Given a set of paths, `find` returns a set of `Result` objects
/// ordered by increasing score values (first values are closest matches).
/// If the result set is larger than `max_results`, the set is reduced to
/// that size.
///
/// # Examples
///
/// ```rust
/// use std::path::PathBuf;
/// use bloodhound::matching::find;
///
/// let paths = vec![PathBuf::from("bloodhound.rs"), PathBuf::from("lib.rs")];
/// let matches = find("lib", paths, 1);
///
/// assert_eq!(matches[0].path.to_str().unwrap(), "lib.rs");
/// ```
pub fn find(needle: &str, haystack: &Vec<PathBuf>, max_results: usize) -> Vec<Result> {
    let mut results = Vec::new();

    // Calculate a score for each of the haystack entries.
    for path in haystack.iter() {
        match path.to_str() {
            Some(path_string) => {
                results.push(Result{
                    path: path.clone(),
                    score: edit_distance(needle, path_string)
                });
            },
            None => (),
        }
    }

    // Sort the results in ascending order (higher values are worse).
    results.sort_by(|a, b| a.score.cmp(&b.score));

    // Make sure we don't exceed the specified result limit.
    results.truncate(max_results);

    results
}

/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

#[cfg(test)]
mod tests {
    use super::find;
    use super::edit_distance;
    use std::path::PathBuf;

    #[test]
    fn find_returns_a_correctly_ordered_set_of_results() {
        let haystack = vec![PathBuf::from("src/hound.rs"),
            PathBuf::from("lib/hounds.rs"), PathBuf::from("Houndfile")];
        let expected_results = vec![PathBuf::from("Houndfile"), PathBuf::from("src/hound.rs")];
        let results = find("Hound", &haystack, 2);
        for i in 0..2 {
            assert_eq!(results[i].path, expected_results[i]);
        }
    }

    #[test]
    fn find_returns_a_correctly_limited_set_of_results() {
        let haystack = vec![PathBuf::from("src/hound.rs"),
            PathBuf::from("lib/hounds.rs"), PathBuf::from("Houndfile")];
        let results = find("Hound", &haystack, 2);
        assert_eq!(results.len(), 2);
    }

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<commit_msg>Update doc tests to pass a reference.<commit_after>use std::path::PathBuf;

#[derive(Debug, PartialEq)]
pub struct Result {
    pub path: PathBuf,
    score: usize,
}

/// Given a set of paths, `find` returns a set of `Result` objects
/// ordered by increasing score values (first values are closest matches).
/// If the result set is larger than `max_results`, the set is reduced to
/// that size.
///
/// # Examples
///
/// ```rust
/// use std::path::PathBuf;
/// use bloodhound::matching::find;
///
/// let paths = vec![PathBuf::from("bloodhound.rs"), PathBuf::from("lib.rs")];
/// let matches = find("lib", &paths, 1);
///
/// assert_eq!(matches[0].path.to_str().unwrap(), "lib.rs");
/// ```
pub fn find(needle: &str, haystack: &Vec<PathBuf>, max_results: usize) -> Vec<Result> {
    let mut results = Vec::new();

    // Calculate a score for each of the haystack entries.
    for path in haystack.iter() {
        match path.to_str() {
            Some(path_string) => {
                results.push(Result{
                    path: path.clone(),
                    score: edit_distance(needle, path_string)
                });
            },
            None => (),
        }
    }

    // Sort the results in ascending order (higher values are worse).
    results.sort_by(|a, b| a.score.cmp(&b.score));

    // Make sure we don't exceed the specified result limit.
    results.truncate(max_results);

    results
}

/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

#[cfg(test)]
mod tests {
    use super::find;
    use super::edit_distance;
    use std::path::PathBuf;

    #[test]
    fn find_returns_a_correctly_ordered_set_of_results() {
        let haystack = vec![PathBuf::from("src/hound.rs"),
            PathBuf::from("lib/hounds.rs"), PathBuf::from("Houndfile")];
        let expected_results = vec![PathBuf::from("Houndfile"), PathBuf::from("src/hound.rs")];
        let results = find("Hound", &haystack, 2);
        for i in 0..2 {
            assert_eq!(results[i].path, expected_results[i]);
        }
    }

    #[test]
    fn find_returns_a_correctly_limited_set_of_results() {
        let haystack = vec![PathBuf::from("src/hound.rs"),
            PathBuf::from("lib/hounds.rs"), PathBuf::from("Houndfile")];
        let results = find("Hound", &haystack, 2);
        assert_eq!(results.len(), 2);
    }

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<|endoftext|>


<commit_before>//! Updates crates.io index and builds new packages

use super::DocBuilder;
use DocBuilderError;
use rustc_serialize::json::Json;
use git2;
use db::connect_db;

impl DocBuilder {
    /// Updates crates.io-index repository and adds new crates into build queue
    pub fn get_new_crates(&self) -> Result<(), DocBuilderError> {

        let repo = try!(git2::Repository::open(&self.options.crates_io_index_path));

        let old_tree = try!(self.head_tree(&repo));
        try!(self.update_repo(&repo));
        let new_tree = try!(self.head_tree(&repo));

        let diff = try!(repo.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None));
        let conn = try!(connect_db());

        try!(diff.print(git2::DiffFormat::Patch, |_, _, diffline| -> bool {
            let line = String::from_utf8_lossy(diffline.content()).into_owned();
            // crate strings starts with '{'
            // skip if line is not a crate string
            if line.chars().nth(0) != Some('{') {
                return true;
            }
            let json = match Json::from_str(&line[..]) {
                Ok(j) => j,
                Err(err) => {
                    error!("Failed to parse crate string: {}", err);
                    // just continue even if we get an error for a crate
                    return true;
                }
            };

            if let Some((krate, version)) = json.as_object()
                                                .map(|obj| {
                                                    (obj.get("name")
                                                        .and_then(|n| n.as_string()),
                                                     obj.get("vers")
                                                        .and_then(|n| n.as_string()))
                                                }) {

                // Skip again if we can't get crate name and version
                if krate.is_none() || version.is_none() {
                    return true;
                }

                let _ = conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
                                     &[&krate.unwrap(), &version.unwrap()]);
            }

            true
        }));

        Ok(())
    }

    fn update_repo(&self, repo: &git2::Repository) -> Result<(), git2::Error> {
        let mut remote = try!(repo.find_remote("origin"));
        try!(remote.fetch(&["refs/heads/*:refs/remotes/origin/*"], None, None));

        // checkout master
        try!(repo.refname_to_id("refs/remotes/origin/master")
                 .and_then(|oid| repo.find_object(oid, None))
                 .and_then(|object| repo.reset(&object, git2::ResetType::Hard, None)));

        Ok(())
    }

    fn head_tree<'a>(&'a self, repo: &'a git2::Repository) -> Result<git2::Tree, git2::Error> {
        repo.head()
            .ok()
            .and_then(|head| head.target())
            .ok_or(git2::Error::from_str("HEAD SHA1 not found"))
            .and_then(|oid| repo.find_commit(oid))
            .and_then(|commit| commit.tree())
    }

    /// Builds packages from queue
    pub fn build_packages_queue(&mut self) -> Result<(), DocBuilderError> {
        let conn = try!(connect_db());

        for row in &try!(conn.query("SELECT id, name, version FROM queue ORDER BY id ASC", &[])) {
            let id: i32 = row.get(0);
            let name: String = row.get(1);
            let version: String = row.get(2);

            match self.build_package(&name[..], &version[..]) {
                Ok(_) => { let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]); },
                Err(e) => error!("Failed to build package {}-{} from queue: {}", name, version, e),
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use std::path::PathBuf;
    use {DocBuilder, DocBuilderOptions};

    #[test]
    #[ignore]
    fn test_get_new_crates() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let docbuilder = DocBuilder::new(options);
        assert!(docbuilder.get_new_crates().is_ok());
    }

    #[test]
    #[ignore]
    fn test_build_packages_queue() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let mut docbuilder = DocBuilder::new(options);
        assert!(docbuilder.build_packages_queue().is_ok());
    }
}
<commit_msg>Improve build queue<commit_after>//! Updates crates.io index and builds new packages

use super::DocBuilder;
use DocBuilderError;
use rustc_serialize::json::Json;
use git2;
use db::connect_db;

impl DocBuilder {
    /// Updates crates.io-index repository and adds new crates into build queue
    pub fn get_new_crates(&self) -> Result<(), DocBuilderError> {

        let repo = try!(git2::Repository::open(&self.options.crates_io_index_path));

        let old_tree = try!(self.head_tree(&repo));
        try!(self.update_repo(&repo));
        let new_tree = try!(self.head_tree(&repo));

        let diff = try!(repo.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None));
        let conn = try!(connect_db());
        let mut line_n = 0;

        try!(diff.print(git2::DiffFormat::Patch, |_, hunk, diffline| -> bool {
            let line = String::from_utf8_lossy(diffline.content()).into_owned();
            // crate strings starts with '{'
            // skip if line is not a crate string
            if line.chars().nth(0) != Some('{') {
                line_n = 0;
                return true;
            }

            line_n += 1;

            if match hunk {
                Some(hunk) => hunk.new_lines() != line_n,
                None => true,
            } {
                return true;
            }

            let json = match Json::from_str(&line[..]) {
                Ok(j) => j,
                Err(err) => {
                    error!("Failed to parse crate string: {}", err);
                    // just continue even if we get an error for a crate
                    return true;
                }
            };

            // check if a crate is yanked just in case
            if json.as_object()
                .and_then(|obj| obj.get("yanked"))
                .and_then(|y| y.as_boolean())
                .unwrap_or(true) {
                return true;
            }

            if let Some((krate, version)) = json.as_object()
                .map(|obj| {
                    (obj.get("name")
                        .and_then(|n| n.as_string()),
                     obj.get("vers")
                        .and_then(|n| n.as_string()))
                }) {

                // Skip again if we can't get crate name and version
                if krate.is_none() || version.is_none() {
                    return true;
                }

                let _ = conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
                                     &[&krate.unwrap(), &version.unwrap()]);
            }

            true
        }));

        Ok(())
    }

    fn update_repo(&self, repo: &git2::Repository) -> Result<(), git2::Error> {
        let mut remote = try!(repo.find_remote("origin"));
        try!(remote.fetch(&["refs/heads/*:refs/remotes/origin/*"], None, None));

        // checkout master
        try!(repo.refname_to_id("refs/remotes/origin/master")
            .and_then(|oid| repo.find_object(oid, None))
            .and_then(|object| repo.reset(&object, git2::ResetType::Hard, None)));

        Ok(())
    }

    fn head_tree<'a>(&'a self, repo: &'a git2::Repository) -> Result<git2::Tree, git2::Error> {
        repo.head()
            .ok()
            .and_then(|head| head.target())
            .ok_or(git2::Error::from_str("HEAD SHA1 not found"))
            .and_then(|oid| repo.find_commit(oid))
            .and_then(|commit| commit.tree())
    }

    /// Builds packages from queue
    pub fn build_packages_queue(&mut self) -> Result<(), DocBuilderError> {
        let conn = try!(connect_db());

        for row in &try!(conn.query("SELECT id, name, version FROM queue ORDER BY id ASC", &[])) {
            let id: i32 = row.get(0);
            let name: String = row.get(1);
            let version: String = row.get(2);

            match self.build_package(&name[..], &version[..]) {
                Ok(_) => {
                    let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]);
                }
                Err(e) => {
                    error!("Failed to build package {}-{} from queue: {}",
                           name,
                           version,
                           e)
                }
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use std::path::PathBuf;
    use {DocBuilder, DocBuilderOptions};

    #[test]
    #[ignore]
    fn test_get_new_crates() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let docbuilder = DocBuilder::new(options);
        assert!(docbuilder.get_new_crates().is_ok());
    }

    #[test]
    #[ignore]
    fn test_build_packages_queue() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let mut docbuilder = DocBuilder::new(options);
        assert!(docbuilder.build_packages_queue().is_ok());
    }
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

//
// cargo test listedit::experiments -- --nocapture
//

extern crate adapton ;
extern crate test;
extern crate quickcheck;
extern crate rand;

use adapton::adapton_sigs::* ;
use adapton::collection::*;
use adapton::engine;
use adapton::naive;

type Edits = Vec<CursorEdit<u32, Dir2>>;

fn compare_naive_and_cached(edits: &Edits) -> bool {
    let reduction = ListReduce::Max;
    let mut n_st = naive::AdaptonFromScratch::new();
    let mut e_st = engine::Engine::new();

    let results_1 = Experiment::run(&mut n_st, edits.clone(), reduction.clone());
    let results_2 = Experiment::run(&mut e_st, edits.clone(), reduction.clone());

    let mut idx = 0;
    for (a, b) in results_1.iter().zip(results_2.iter()) {
        if a.0 != b.0 {
            println!("After edit {}, {:?}, expected {:?} to be {:?}, but found {:?}.",
                     idx, edits[idx], &reduction, a.0, b.0);
            return false;
        }
        idx += 1;
    }

    true
}

#[test]
fn ensure_consistency_randomly() {
    let rng = rand::thread_rng();
    let mut gen = quickcheck::StdGen::new(rng, 100);
    for _ in 0..100 {
        let testv = <Edits as quickcheck::Arbitrary>::arbitrary(&mut gen);
        if !compare_naive_and_cached(&testv) {
            panic!("{:?}", testv);
        }
    }
}

#[test]
#[ignore]
fn ensure_consistency_regression_testcase1() { assert!( compare_naive_and_cached(&testcase1())) }

#[test]
#[ignore]
fn ensure_consistency_regression_testcase2() { assert!( compare_naive_and_cached(&testcase2())) }

#[test]
#[ignore]
fn ensure_consistency_regression_testcase3() { assert!( compare_naive_and_cached(&testcase3())) }

fn testcase1 () -> Edits {
    vec![
        CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Insert(Dir2::Right, 44), CursorEdit::Remove(Dir2::Right), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Insert(Dir2::Right, 23),
        CursorEdit::Insert(Dir2::Left, 41), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 13), CursorEdit::Insert(Dir2::Left, 21), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 41),
        CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Replace(Dir2::Left, 11), CursorEdit::Goto(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Insert(Dir2::Left, 45), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 12), CursorEdit::Insert(Dir2::Right, 14),
        CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 39),
        CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 36), CursorEdit::Insert(Dir2::Left, 85),
        CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Left, 93), CursorEdit::Insert(Dir2::Right, 52), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right)
       ]
}

fn testcase2 () -> Edits {
    vec![CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 76), CursorEdit::Insert(Dir2::Right, 39), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 63), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 54), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 77), CursorEdit::Insert(Dir2::Right, 32), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Replace(Dir2::Right, 57), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 6), CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Replace(Dir2::Left, 72), CursorEdit::Insert(Dir2::Left, 51), CursorEdit::Remove(Dir2::Right), CursorEdit::Insert(Dir2::Left, 49),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 6),
         CursorEdit::Insert(Dir2::Right, 82), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 89), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 9), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 26), CursorEdit::Replace(Dir2::Left, 35),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 5), CursorEdit::Insert(Dir2::Left, 75),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 32), CursorEdit::Replace(Dir2::Right, 74), CursorEdit::Insert(Dir2::Left, 77),
         CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Insert(Dir2::Left, 44), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 81),
         CursorEdit::Insert(Dir2::Left, 61), CursorEdit::Insert(Dir2::Right, 92), CursorEdit::Insert(Dir2::Left, 68), CursorEdit::Replace(Dir2::Right, 42),
         CursorEdit::Insert(Dir2::Right, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 31),
         CursorEdit::Insert(Dir2::Right, 72), CursorEdit::Insert(Dir2::Right, 70), CursorEdit::Insert(Dir2::Left, 87), CursorEdit::Insert(Dir2::Right, 95),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Replace(Dir2::Right, 96), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Left)]
}

fn testcase3 () -> Edits {
    vec![CursorEdit::Insert(Dir2::Left, 86),
         CursorEdit::Insert(Dir2::Right, 37),
         CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Left, 42),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 68),
         CursorEdit::Insert(Dir2::Right, 18),
         CursorEdit::Remove(Dir2::Left),
         CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Replace(Dir2::Left, 68),
         CursorEdit::Insert(Dir2::Left, 82),
         CursorEdit::Insert(Dir2::Right, 30),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 78),
         CursorEdit::Insert(Dir2::Right, 88),
         CursorEdit::Insert(Dir2::Left, 38),
         CursorEdit::Insert(Dir2::Right, 91),
         CursorEdit::Goto(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 67),
         CursorEdit::Insert(Dir2::Right, 3),
         CursorEdit::Remove(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 16),
         CursorEdit::Insert(Dir2::Left, 4),
         CursorEdit::Insert(Dir2::Right, 29),
         CursorEdit::Insert(Dir2::Right, 92),
         CursorEdit::Insert(Dir2::Left, 79),
         CursorEdit::Replace(Dir2::Left, 88),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left),
         // CursorEdit::Insert(Dir2::Left, 25), CursorEdit::Insert(Dir2::Left, 46), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         // CursorEdit::Insert(Dir2::Left, 18), CursorEdit::Insert(Dir2::Left, 1), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left),
         // CursorEdit::Insert(Dir2::Right, 93), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 10), CursorEdit::Remove(Dir2::Left),
         // CursorEdit::Insert(Dir2::Right, 34), CursorEdit::Remove(Dir2::Left), CursorEdit::Replace(Dir2::Left, 47), CursorEdit::Goto(Dir2::Right),
         // CursorEdit::Insert(Dir2::Left, 56), CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Replace(Dir2::Right, 99), CursorEdit::Insert(Dir2::Right, 19),
         // CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 94), CursorEdit::Replace(Dir2::Right, 58), CursorEdit::Goto(Dir2::Right),
         // CursorEdit::Insert(Dir2::Left, 71)
         ]
}
<commit_msg>added another failing testcase<commit_after>#![feature(test)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

//
// cargo test listedit::experiments -- --nocapture
//

extern crate adapton ;
extern crate test;
extern crate quickcheck;
extern crate rand;

use adapton::adapton_sigs::* ;
use adapton::collection::*;
use adapton::engine;
use adapton::naive;

type Edits = Vec<CursorEdit<u32, Dir2>>;

fn compare_naive_and_cached(edits: &Edits) -> bool {
    let reduction = ListReduce::Max;
    let mut n_st = naive::AdaptonFromScratch::new();
    let mut e_st = engine::Engine::new();

    let results_1 = Experiment::run(&mut n_st, edits.clone(), reduction.clone());
    let results_2 = Experiment::run(&mut e_st, edits.clone(), reduction.clone());

    let mut idx = 0;
    for (a, b) in results_1.iter().zip(results_2.iter()) {
        if a.0 != b.0 {
            println!("After edit {}, {:?}, expected {:?} to be {:?}, but found {:?}.",
                     idx, edits[idx], &reduction, a.0, b.0);
            return false;
        }
        idx += 1;
    }

    true
}

#[test]
fn ensure_consistency_randomly() {
    let rng = rand::thread_rng();
    let mut gen = quickcheck::StdGen::new(rng, 100);
    for _ in 0..100 {
        let testv = <Edits as quickcheck::Arbitrary>::arbitrary(&mut gen);
        if !compare_naive_and_cached(&testv) {
            panic!("{:?}", testv);
        }
    }
}

#[test]
#[ignore]
fn ensure_consistency_regression_testcase1() { assert!( compare_naive_and_cached(&testcase1())) }

#[test]
#[ignore]
fn ensure_consistency_regression_testcase2() { assert!( compare_naive_and_cached(&testcase2())) }

#[test]
#[ignore]
fn ensure_consistency_regression_testcase3() { assert!( compare_naive_and_cached(&testcase3())) }

#[test]
fn ensure_consistency_regression_testcase4() { assert!( compare_naive_and_cached(&testcase4())) }

fn testcase1 () -> Edits {
    vec![
        CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Insert(Dir2::Right, 44), CursorEdit::Remove(Dir2::Right), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Insert(Dir2::Right, 23),
        CursorEdit::Insert(Dir2::Left, 41), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 13), CursorEdit::Insert(Dir2::Left, 21), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 41),
        CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Replace(Dir2::Left, 11), CursorEdit::Goto(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Insert(Dir2::Left, 45), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 12), CursorEdit::Insert(Dir2::Right, 14),
        CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 39),
        CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 36), CursorEdit::Insert(Dir2::Left, 85),
        CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Left, 93), CursorEdit::Insert(Dir2::Right, 52), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right)
       ]
}

fn testcase2 () -> Edits {
    vec![CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 76), CursorEdit::Insert(Dir2::Right, 39), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 63), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 54), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 77), CursorEdit::Insert(Dir2::Right, 32), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Replace(Dir2::Right, 57), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 6), CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Replace(Dir2::Left, 72), CursorEdit::Insert(Dir2::Left, 51), CursorEdit::Remove(Dir2::Right), CursorEdit::Insert(Dir2::Left, 49),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 6),
         CursorEdit::Insert(Dir2::Right, 82), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 89), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 9), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 26), CursorEdit::Replace(Dir2::Left, 35),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 5), CursorEdit::Insert(Dir2::Left, 75),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 32), CursorEdit::Replace(Dir2::Right, 74), CursorEdit::Insert(Dir2::Left, 77),
         CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Insert(Dir2::Left, 44), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 81),
         CursorEdit::Insert(Dir2::Left, 61), CursorEdit::Insert(Dir2::Right, 92), CursorEdit::Insert(Dir2::Left, 68), CursorEdit::Replace(Dir2::Right, 42),
         CursorEdit::Insert(Dir2::Right, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 31),
         CursorEdit::Insert(Dir2::Right, 72), CursorEdit::Insert(Dir2::Right, 70), CursorEdit::Insert(Dir2::Left, 87), CursorEdit::Insert(Dir2::Right, 95),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Replace(Dir2::Right, 96), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Left)]
}

fn testcase3 () -> Edits {
    vec![CursorEdit::Insert(Dir2::Left, 86),
         CursorEdit::Insert(Dir2::Right, 37),
         CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Left, 42),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 68),
         CursorEdit::Insert(Dir2::Right, 18),
         CursorEdit::Remove(Dir2::Left),
         CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Replace(Dir2::Left, 68),
         CursorEdit::Insert(Dir2::Left, 82),
         CursorEdit::Insert(Dir2::Right, 30),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 78),
         CursorEdit::Insert(Dir2::Right, 88),
         CursorEdit::Insert(Dir2::Left, 38),
         CursorEdit::Insert(Dir2::Right, 91),
         CursorEdit::Goto(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 67),
         CursorEdit::Insert(Dir2::Right, 3),
         CursorEdit::Remove(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 16),
         CursorEdit::Insert(Dir2::Left, 4),
         CursorEdit::Insert(Dir2::Right, 29),
         CursorEdit::Insert(Dir2::Right, 92),
         CursorEdit::Insert(Dir2::Left, 79),
         CursorEdit::Replace(Dir2::Left, 88),
         CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left),
         // CursorEdit::Insert(Dir2::Left, 25), CursorEdit::Insert(Dir2::Left, 46), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         // CursorEdit::Insert(Dir2::Left, 18), CursorEdit::Insert(Dir2::Left, 1), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left),
         // CursorEdit::Insert(Dir2::Right, 93), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 10), CursorEdit::Remove(Dir2::Left),
         // CursorEdit::Insert(Dir2::Right, 34), CursorEdit::Remove(Dir2::Left), CursorEdit::Replace(Dir2::Left, 47), CursorEdit::Goto(Dir2::Right),
         // CursorEdit::Insert(Dir2::Left, 56), CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Replace(Dir2::Right, 99), CursorEdit::Insert(Dir2::Right, 19),
         // CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 94), CursorEdit::Replace(Dir2::Right, 58), CursorEdit::Goto(Dir2::Right),
         // CursorEdit::Insert(Dir2::Left, 71)
         ]
}

fn testcase4 () -> Edits {
    vec![
        CursorEdit::Replace(Dir2::Left, 29),
        CursorEdit::Replace(Dir2::Left, 34),
        CursorEdit::Goto(Dir2::Right),
        CursorEdit::Goto(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 30),
        CursorEdit::Insert(Dir2::Left, 26),
        CursorEdit::Insert(Dir2::Right, 26),
        CursorEdit::Insert(Dir2::Left, 7),
        CursorEdit::Remove(Dir2::Left),
        CursorEdit::Goto(Dir2::Left),
        CursorEdit::Insert(Dir2::Left, 19),
        CursorEdit::Insert(Dir2::Left, 16),
        CursorEdit::Goto(Dir2::Right),
        CursorEdit::Goto(Dir2::Left),
        CursorEdit::Insert(Dir2::Right, 27),
        CursorEdit::Insert(Dir2::Right, 3),
        CursorEdit::Insert(Dir2::Left, 13),
        CursorEdit::Goto(Dir2::Left),
        CursorEdit::Insert(Dir2::Left, 26),
        CursorEdit::Insert(Dir2::Left, 10),
        CursorEdit::Insert(Dir2::Right, 2),
        CursorEdit::Insert(Dir2::Right, 38),
        CursorEdit::Insert(Dir2::Left, 36),
        CursorEdit::Replace(Dir2::Left, 36),
        CursorEdit::Insert(Dir2::Left, 8),
        CursorEdit::Insert(Dir2::Left, 39),
        CursorEdit::Replace(Dir2::Right, 7),
        CursorEdit::Insert(Dir2::Right, 30),
        CursorEdit::Goto(Dir2::Left),
        CursorEdit::Goto(Dir2::Right),
        //CursorEdit::Goto(Dir2::Right),
        //CursorEdit::Insert(Dir2::Right, 25),
        //CursorEdit::Insert(Dir2::Left, 0),
        //CursorEdit::Insert(Dir2::Left, 0),
        //CursorEdit::Goto(Dir2::Right),
        //CursorEdit::Goto(Dir2::Right)
      ]
}

// ---- ensure_consistency stdout ----
//     after edit 29: Replace(Dir2::Right, 47): expected Max to be [47], but found [45]
//     thread 'ensure_consistency' panicked at '[Goto(Dir2::Right), Insert(Dir2::Left, 45), Remove(Dir2::Right), Remove(Dir2::Right), Insert(Dir2::Right, 19), Goto(Dir2::Left), Goto(Dir2::Right), Insert(Dir2::Left, 23), Goto(Dir2::Right), Insert(Dir2::Right, 14), Insert(Dir2::Left, 28), Goto(Dir2::Right), Goto(Dir2::Right), Insert(Dir2::Right, 37), Replace(Dir2::Left, 35), Insert(Dir2::Right, 0), Insert(Dir2::Right, 23), Insert(Dir2::Left, 27), Goto(Dir2::Left), Insert(Dir2::Right, 11), Insert(Dir2::Right, 30), Insert(Dir2::Right, 25), Insert(Dir2::Right, 38), Goto(Dir2::Right), Insert(Dir2::Left, 24), Insert(Dir2::Left, 45), Replace(Dir2::Left, 31), Replace(Dir2::Right, 43), Replace(Dir2::Right, 2), Replace(Dir2::Right, 47), Insert(Dir2::Right, 46), Insert(Dir2::Left, 27), Goto(Dir2::Right), Remove(Dir2::Right), Goto(Dir2::Left), Insert(Dir2::Left, 44), Goto(Dir2::Left), Insert(Dir2::Right, 27), Goto(Dir2::Left)]', tests/listedit.rs:52

// ---- ensure_consistency stdout ----
//     after edit 41: Goto(Dir2::Right): expected Max to be [49], but found [44]
//     thread 'ensure_consistency' panicked at '[Replace(Dir2::Right, 45), Insert(Dir2::Right, 0), Insert(Dir2::Left, 12), Insert(Dir2::Right, 22), Goto(Dir2::Right), Goto(Dir2::Right), Insert(Dir2::Left, 16), Replace(Dir2::Right, 7), Goto(Dir2::Right), Insert(Dir2::Left, 16), Insert(Dir2::Right, 27), Insert(Dir2::Left, 0), Goto(Dir2::Right), Insert(Dir2::Right, 36), Goto(Dir2::Right), Goto(Dir2::Right), Insert(Dir2::Right, 11), Goto(Dir2::Right), Insert(Dir2::Right, 32), Remove(Dir2::Left), Insert(Dir2::Right, 14), Remove(Dir2::Right), Goto(Dir2::Right), Replace(Dir2::Right, 23), Insert(Dir2::Left, 34), Replace(Dir2::Right, 49), Insert(Dir2::Left, 0), Insert(Dir2::Left, 16), Remove(Dir2::Left), Insert(Dir2::Left, 4), Goto(Dir2::Right), Replace(Dir2::Right, 23), Insert(Dir2::Left, 44), Goto(Dir2::Left), Insert(Dir2::Left, 23), Goto(Dir2::Right), Insert(Dir2::Left, 18), Insert(Dir2::Right, 15), Replace(Dir2::Left, 49), Insert(Dir2::Right, 16), Goto(Dir2::Left), Goto(Dir2::Right), Insert(Dir2::Left, 46), Goto(Dir2::Left)]', tests/listedit.rs:52

<|endoftext|>


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

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use u32;
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        rng.gen::<f64>() as f32
    }
}

static SCALE : f64 = (u32::max_value as f64) + 1.0f64;
impl Rand for f64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        let u1 = rng.next_u32() as f64;
        let u2 = rng.next_u32() as f64;
        let u3 = rng.next_u32() as f64;

        ((u1 / SCALE + u2) / SCALE + u3) / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}
<commit_msg>std::rand: adjust the f32 & f64 Rand instances.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    /// A random `f32` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        // weird, but this is the easiest way to get 2**32
        static SCALE: f32 = 2.0 * (1u32 << 31) as f32;
        rng.next_u32() as f32 / SCALE
    }
}

impl Rand for f64 {
    /// A random `f64` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        // weird, but this is the easiest way to get 2**64
        static SCALE: f64 = 2.0 * (1u64 << 63) as f64;

        rng.next_u64() as f64 / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Commands that the GPU will execute (includes draw commands).
//!
//! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer
//! is a list of commands that will executed by the GPU. Once a command buffer is created, you can
//! execute it. A command buffer must be created even for the most simple tasks.
//!
//! # Pools
//!
//! Command buffers are allocated from pools. You must first create a command buffer pool which
//! you will create command buffers from.
//!
//! A pool is linked to a queue family. Command buffers that are created from a certain pool can
//! only be submitted to queues that belong to that specific family.
//!
//! # Primary and secondary command buffers.
//!
//! There are three types of command buffers:
//!
//! - **Primary command buffers**. They can contain any command. They are the only type of command
//!   buffer that can be submitted to a queue.
//! - **Secondary "graphics" command buffers**. They contain draw and clear commands. They can be
//!   called from a primary command buffer once a framebuffer has been selected.
//! - **Secondary "compute" command buffers**. They can contain non-draw and non-clear commands
//!   (eg. copying between buffers) and can be called from a primary command buffer outside of a
//!   render pass.
//!
//! Note that secondary command buffers cannot call other command buffers.
//!

// Implementation note.
// There are various restrictions about which command can be used at which moment. Therefore the
// API has several different command buffer wrappers, but they all use the same internal
// struct. The restrictions are enforced only in the public types.

pub use self::submit::Submit;

use std::sync::Arc;
use std::time::Duration;

use device::Queue;
use pipeline::viewport::Viewport;
use pipeline::viewport::Scissor;
use sync::FenceWaitError;

pub mod pool;
pub mod states_manager;
pub mod std;
pub mod submit;
pub mod sys;

// TODO: temporary object to make old system compile
// TODO: remove
#[derive(Debug)]
pub struct Submission;
impl Submission {
    pub fn destroying_would_block(&self) -> bool { false }
    pub fn finished(&self) -> bool { true }
    pub fn wait(&self, timeout: Duration) -> Result<(), FenceWaitError> { Ok(()) }
    pub fn queue(&self) -> &Arc<Queue> { unimplemented!() }
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndirectCommand {
    pub vertex_count: u32,
    pub instance_count: u32,
    pub first_vertex: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndexedIndirectCommand {
    pub index_count: u32,
    pub instance_count: u32,
    pub first_index: u32,
    pub vertex_offset: u32,
    pub first_instance: u32,
}

/// The dynamic state to use for a draw command.
#[derive(Debug, Clone)]
pub struct DynamicState {
    pub line_width: Option<f32>,
    pub viewports: Option<Vec<Viewport>>,
    pub scissors: Option<Vec<Scissor>>,
}

impl DynamicState {
    #[inline]
    pub fn none() -> DynamicState {
        DynamicState {
            line_width: None,
            viewports: None,
            scissors: None,
        }
    }
}

impl Default for DynamicState {
    #[inline]
    fn default() -> DynamicState {
        DynamicState::none()
    }
}
<commit_msg>Some convenient reexports<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Commands that the GPU will execute (includes draw commands).
//!
//! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer
//! is a list of commands that will executed by the GPU. Once a command buffer is created, you can
//! execute it. A command buffer must be created even for the most simple tasks.
//!
//! # Pools
//!
//! Command buffers are allocated from pools. You must first create a command buffer pool which
//! you will create command buffers from.
//!
//! A pool is linked to a queue family. Command buffers that are created from a certain pool can
//! only be submitted to queues that belong to that specific family.
//!
//! # Primary and secondary command buffers.
//!
//! There are three types of command buffers:
//!
//! - **Primary command buffers**. They can contain any command. They are the only type of command
//!   buffer that can be submitted to a queue.
//! - **Secondary "graphics" command buffers**. They contain draw and clear commands. They can be
//!   called from a primary command buffer once a framebuffer has been selected.
//! - **Secondary "compute" command buffers**. They can contain non-draw and non-clear commands
//!   (eg. copying between buffers) and can be called from a primary command buffer outside of a
//!   render pass.
//!
//! Note that secondary command buffers cannot call other command buffers.
//!

// Implementation note.
// There are various restrictions about which command can be used at which moment. Therefore the
// API has several different command buffer wrappers, but they all use the same internal
// struct. The restrictions are enforced only in the public types.

pub use self::std::CommandBuffer;
pub use self::std::CommandsList;
pub use self::submit::Submit;

use std::sync::Arc;
use std::time::Duration;

use device::Queue;
use pipeline::viewport::Viewport;
use pipeline::viewport::Scissor;
use sync::FenceWaitError;

pub mod pool;
pub mod states_manager;
pub mod std;
pub mod submit;
pub mod sys;

// TODO: temporary object to make old system compile
// TODO: remove
#[derive(Debug)]
pub struct Submission;
impl Submission {
    pub fn destroying_would_block(&self) -> bool { false }
    pub fn finished(&self) -> bool { true }
    pub fn wait(&self, timeout: Duration) -> Result<(), FenceWaitError> { Ok(()) }
    pub fn queue(&self) -> &Arc<Queue> { unimplemented!() }
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndirectCommand {
    pub vertex_count: u32,
    pub instance_count: u32,
    pub first_vertex: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndexedIndirectCommand {
    pub index_count: u32,
    pub instance_count: u32,
    pub first_index: u32,
    pub vertex_offset: u32,
    pub first_instance: u32,
}

/// The dynamic state to use for a draw command.
#[derive(Debug, Clone)]
pub struct DynamicState {
    pub line_width: Option<f32>,
    pub viewports: Option<Vec<Viewport>>,
    pub scissors: Option<Vec<Scissor>>,
}

impl DynamicState {
    #[inline]
    pub fn none() -> DynamicState {
        DynamicState {
            line_width: None,
            viewports: None,
            scissors: None,
        }
    }
}

impl Default for DynamicState {
    #[inline]
    fn default() -> DynamicState {
        DynamicState::none()
    }
}
<|endoftext|>