<commit_before>use rustc::lint::*;
use rustc::ty;
use rustc_front::hir::*;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use syntax::parse::token::InternedString;
use syntax::util::small_vector::SmallVector;
use utils::{SpanlessEq, SpanlessHash};
use utils::{get_parent_expr, in_macro, span_note_and_lint};

/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is
/// `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if a == b { .. } else if a == b { .. }`
declare_lint! {
    pub IFS_SAME_COND,
    Warn,
    "consecutive `ifs` with the same condition"
}

/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the
/// *else* part. This lint is `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if .. { 42 } else { 42 }`
declare_lint! {
    pub IF_SAME_THEN_ELSE,
    Warn,
    "if with the same *then* and *else* blocks"
}

/// **What it does:** This lint checks for `match` with identical arm bodies.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust,ignore
/// match foo {
///     Bar => bar(),
///     Quz => quz(),
///     Baz => bar(), // <= oops
/// }
/// ```
declare_lint! {
    pub MATCH_SAME_ARMS,
    Warn,
    "`match` with identical arm bodies"
}

#[derive(Copy, Clone, Debug)]
pub struct CopyAndPaste;

impl LintPass for CopyAndPaste {
    fn get_lints(&self) -> LintArray {
        lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]
    }
}

impl LateLintPass for CopyAndPaste {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if !in_macro(cx, expr.span) {
            // skip ifs directly in else, it will be checked in the parent if
            if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) {
                if else_expr.id == expr.id {
                    return;
                }
            }

            let (conds, blocks) = if_sequence(expr);
            lint_same_then_else(cx, blocks.as_slice());
            lint_same_cond(cx, conds.as_slice());
            lint_match_arms(cx, expr);
        }
    }
}

/// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
    let hash: &Fn(&&Block) -> u64 = &|block| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_block(block);
        h.finish()
    };

    let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };

    if let Some((i, j)) = search_same(blocks, hash, eq) {
        span_note_and_lint(cx,
                           IF_SAME_THEN_ELSE,
                           j.span,
                           "this `if` has identical blocks",
                           i.span,
                           "same as this");
    }
}

/// Implementation of `IFS_SAME_COND`.
fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) {
    let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_expr(expr);
        h.finish()
    };

    let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };

    if let Some((i, j)) = search_same(conds, hash, eq) {
        span_note_and_lint(cx,
                           IFS_SAME_COND,
                           j.span,
                           "this `if` has the same condition as a previous if",
                           i.span,
                           "same as this");
    }
}

/// Implementation if `MATCH_SAME_ARMS`.
fn lint_match_arms(cx: &LateContext, expr: &Expr) {
    let hash = |arm: &Arm| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_expr(&arm.body);
        h.finish()
    };

    let eq = |lhs: &Arm, rhs: &Arm| -> bool {
        // Arms with a guard are ignored, those can’t always be merged together
        lhs.guard.is_none() && rhs.guard.is_none() &&
            SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) &&
            // all patterns should have the same bindings
            bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0])
    };

    if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node {
        if let Some((i, j)) = search_same(&arms, hash, eq) {
            span_note_and_lint(cx,
                               MATCH_SAME_ARMS,
                               j.body.span,
                               "this `match` has identical arm bodies",
                               i.body.span,
                               "same as this");
        }
    }
}

/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`.
/// Eg. would return `([a, b], [c, d, e])` for the expression
/// `if a { c } else if b { d } else { e }`.
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
    let mut conds = SmallVector::zero();
    let mut blocks = SmallVector::zero();

    while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
        conds.push(&**cond);
        blocks.push(&**then_block);

        if let Some(ref else_expr) = *else_expr {
            expr = else_expr;
        } else {
            break;
        }
    }

    // final `else {..}`
    if !blocks.is_empty() {
        if let ExprBlock(ref block) = expr.node {
            blocks.push(&**block);
        }
    }

    (conds, blocks)
}

/// Return the list of bindings in a pattern.
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> {
    fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) {
        match pat.node {
            PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
            PatKind::TupleStruct(_, Some(ref pats)) => {
                for pat in pats {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::Ident(_, ref ident, ref as_pat) => {
                if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) {
                    v.insert(cx.tcx.pat_ty(pat));
                }
                if let Some(ref as_pat) = *as_pat {
                    bindings_impl(cx, as_pat, map);
                }
            }
            PatKind::Struct(_, ref fields, _) => {
                for pat in fields {
                    bindings_impl(cx, &pat.node.pat, map);
                }
            }
            PatKind::Tup(ref fields) => {
                for pat in fields {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::Vec(ref lhs, ref mid, ref rhs) => {
                for pat in lhs {
                    bindings_impl(cx, pat, map);
                }
                if let Some(ref mid) = *mid {
                    bindings_impl(cx, mid, map);
                }
                for pat in rhs {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::TupleStruct(..) |
            PatKind::Lit(..) |
            PatKind::QPath(..) |
            PatKind::Range(..) |
            PatKind::Wild |
            PatKind::Path(..) => (),
        }
    }

    let mut result = HashMap::new();
    bindings_impl(cx, pat, &mut result);
    result
}

fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
    where Hash: Fn(&T) -> u64,
          Eq: Fn(&T, &T) -> bool
{
    // common cases
    if exprs.len() < 2 {
        return None;
    } else if exprs.len() == 2 {
        return if eq(&exprs[0], &exprs[1]) {
            Some((&exprs[0], &exprs[1]))
        } else {
            None
        };
    }

    let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len());

    for expr in exprs {
        match map.entry(hash(expr)) {
            Entry::Occupied(o) => {
                for o in o.get() {
                    if eq(&o, expr) {
                        return Some((&o, expr));
                    }
                }
            }
            Entry::Vacant(v) => {
                v.insert(vec![expr]);
            }
        }
    }

    None
}
<commit_msg>Improve the `match_same_arms` doc<commit_after>use rustc::lint::*;
use rustc::ty;
use rustc_front::hir::*;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use syntax::parse::token::InternedString;
use syntax::util::small_vector::SmallVector;
use utils::{SpanlessEq, SpanlessHash};
use utils::{get_parent_expr, in_macro, span_note_and_lint};

/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is
/// `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if a == b { .. } else if a == b { .. }`
declare_lint! {
    pub IFS_SAME_COND,
    Warn,
    "consecutive `ifs` with the same condition"
}

/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the
/// *else* part. This lint is `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if .. { 42 } else { 42 }`
declare_lint! {
    pub IF_SAME_THEN_ELSE,
    Warn,
    "if with the same *then* and *else* blocks"
}

/// **What it does:** This lint checks for `match` with identical arm bodies.
///
/// **Why is this bad?** This is probably a copy & paste error. If arm bodies are the same on
/// purpose, you can factor them
/// [using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns).
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust,ignore
/// match foo {
///     Bar => bar(),
///     Quz => quz(),
///     Baz => bar(), // <= oops
/// }
/// ```
declare_lint! {
    pub MATCH_SAME_ARMS,
    Warn,
    "`match` with identical arm bodies"
}

#[derive(Copy, Clone, Debug)]
pub struct CopyAndPaste;

impl LintPass for CopyAndPaste {
    fn get_lints(&self) -> LintArray {
        lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]
    }
}

impl LateLintPass for CopyAndPaste {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if !in_macro(cx, expr.span) {
            // skip ifs directly in else, it will be checked in the parent if
            if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) {
                if else_expr.id == expr.id {
                    return;
                }
            }

            let (conds, blocks) = if_sequence(expr);
            lint_same_then_else(cx, blocks.as_slice());
            lint_same_cond(cx, conds.as_slice());
            lint_match_arms(cx, expr);
        }
    }
}

/// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
    let hash: &Fn(&&Block) -> u64 = &|block| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_block(block);
        h.finish()
    };

    let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };

    if let Some((i, j)) = search_same(blocks, hash, eq) {
        span_note_and_lint(cx,
                           IF_SAME_THEN_ELSE,
                           j.span,
                           "this `if` has identical blocks",
                           i.span,
                           "same as this");
    }
}

/// Implementation of `IFS_SAME_COND`.
fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) {
    let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_expr(expr);
        h.finish()
    };

    let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };

    if let Some((i, j)) = search_same(conds, hash, eq) {
        span_note_and_lint(cx,
                           IFS_SAME_COND,
                           j.span,
                           "this `if` has the same condition as a previous if",
                           i.span,
                           "same as this");
    }
}

/// Implementation if `MATCH_SAME_ARMS`.
fn lint_match_arms(cx: &LateContext, expr: &Expr) {
    let hash = |arm: &Arm| -> u64 {
        let mut h = SpanlessHash::new(cx);
        h.hash_expr(&arm.body);
        h.finish()
    };

    let eq = |lhs: &Arm, rhs: &Arm| -> bool {
        // Arms with a guard are ignored, those can’t always be merged together
        lhs.guard.is_none() && rhs.guard.is_none() &&
            SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) &&
            // all patterns should have the same bindings
            bindings(cx, &lhs.pats[0]) == bindings(cx, &rhs.pats[0])
    };

    if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node {
        if let Some((i, j)) = search_same(&arms, hash, eq) {
            span_note_and_lint(cx,
                               MATCH_SAME_ARMS,
                               j.body.span,
                               "this `match` has identical arm bodies",
                               i.body.span,
                               "same as this");
        }
    }
}

/// Return the list of condition expressions and the list of blocks in a sequence of `if/else`.
/// Eg. would return `([a, b], [c, d, e])` for the expression
/// `if a { c } else if b { d } else { e }`.
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
    let mut conds = SmallVector::zero();
    let mut blocks = SmallVector::zero();

    while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
        conds.push(&**cond);
        blocks.push(&**then_block);

        if let Some(ref else_expr) = *else_expr {
            expr = else_expr;
        } else {
            break;
        }
    }

    // final `else {..}`
    if !blocks.is_empty() {
        if let ExprBlock(ref block) = expr.node {
            blocks.push(&**block);
        }
    }

    (conds, blocks)
}

/// Return the list of bindings in a pattern.
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> {
    fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) {
        match pat.node {
            PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
            PatKind::TupleStruct(_, Some(ref pats)) => {
                for pat in pats {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::Ident(_, ref ident, ref as_pat) => {
                if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) {
                    v.insert(cx.tcx.pat_ty(pat));
                }
                if let Some(ref as_pat) = *as_pat {
                    bindings_impl(cx, as_pat, map);
                }
            }
            PatKind::Struct(_, ref fields, _) => {
                for pat in fields {
                    bindings_impl(cx, &pat.node.pat, map);
                }
            }
            PatKind::Tup(ref fields) => {
                for pat in fields {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::Vec(ref lhs, ref mid, ref rhs) => {
                for pat in lhs {
                    bindings_impl(cx, pat, map);
                }
                if let Some(ref mid) = *mid {
                    bindings_impl(cx, mid, map);
                }
                for pat in rhs {
                    bindings_impl(cx, pat, map);
                }
            }
            PatKind::TupleStruct(..) |
            PatKind::Lit(..) |
            PatKind::QPath(..) |
            PatKind::Range(..) |
            PatKind::Wild |
            PatKind::Path(..) => (),
        }
    }

    let mut result = HashMap::new();
    bindings_impl(cx, pat, &mut result);
    result
}

fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
    where Hash: Fn(&T) -> u64,
          Eq: Fn(&T, &T) -> bool
{
    // common cases
    if exprs.len() < 2 {
        return None;
    } else if exprs.len() == 2 {
        return if eq(&exprs[0], &exprs[1]) {
            Some((&exprs[0], &exprs[1]))
        } else {
            None
        };
    }

    let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len());

    for expr in exprs {
        match map.entry(hash(expr)) {
            Entry::Occupied(o) => {
                for o in o.get() {
                    if eq(&o, expr) {
                        return Some((&o, expr));
                    }
                }
            }
            Entry::Vacant(v) => {
                v.insert(vec![expr]);
            }
        }
    }

    None
}
<|endoftext|>


<commit_before>use num::Num;

#[inline(always)]
pub fn new<T: Num>(
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> [T; 9] {[
    m11, m12, m13,
    m21, m22, m23,
    m31, m32, m33
]}
#[inline(always)]
pub fn create<T: Num>(
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> [T; 9] {create(
    m11, m12, m13,
    m21, m22, m23,
    m31, m32, m33
)}
#[test]
fn test_new() {
    let m = new(1, 0, 0, 0, 1, 0, 0, 0, 1);
    assert!(m[0] == 1);
    assert!(m[1] == 0);
    assert!(m[2] == 0);
    assert!(m[3] == 0);
    assert!(m[4] == 1);
    assert!(m[5] == 0);
    assert!(m[6] == 0);
    assert!(m[7] == 0);
    assert!(m[8] == 1);
}

#[inline(always)]
pub fn new_identity<T: Num>() -> [T; 9] {
    new(
        T::one(), T::zero(), T::zero(),
        T::zero(), T::one(), T::zero(),
        T::zero(), T::one(), T::one()
    )
}
#[inline(always)]
pub fn new_zero<T: Num>() -> [T; 9] {
    new(
        T::zero(), T::zero(), T::zero(),
        T::zero(), T::zero(), T::zero(),
        T::zero(), T::zero(), T::zero()
    )
}

#[inline(always)]
pub fn clone<T: Num>(m: [T; 9]) -> [T; 9] {
    new(
        m[0], m[3], m[6],
        m[1], m[4], m[7],
        m[2], m[5], m[8]
    )
}

#[inline(always)]
pub fn copy<T: Num>(out: &mut [T; 9], a: [T; 9]) -> &mut [T; 9] {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4];
    out[5] = a[5];
    out[6] = a[6];
    out[7] = a[7];
    out[8] = a[8];
    out
}
<commit_msg>added new<commit_after>use num::Num;

#[inline(always)]
pub fn new<T: Num>(
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> [T; 9] {[
    m11, m12, m13,
    m21, m22, m23,
    m31, m32, m33
]}
#[inline(always)]
pub fn create<T: Num>(
    m11: T, m12: T, m13: T,
    m21: T, m22: T, m23: T,
    m31: T, m32: T, m33: T
) -> [T; 9] {new(
    m11, m12, m13,
    m21, m22, m23,
    m31, m32, m33
)}
#[test]
fn test_new() {
    let m = new(1, 0, 0, 0, 1, 0, 0, 0, 1);
    assert!(m[0] == 1);
    assert!(m[1] == 0);
    assert!(m[2] == 0);
    assert!(m[3] == 0);
    assert!(m[4] == 1);
    assert!(m[5] == 0);
    assert!(m[6] == 0);
    assert!(m[7] == 0);
    assert!(m[8] == 1);
}

#[inline(always)]
pub fn new_identity<T: Num>() -> [T; 9] {
    new(
        T::one(), T::zero(), T::zero(),
        T::zero(), T::one(), T::zero(),
        T::zero(), T::one(), T::one()
    )
}
#[inline(always)]
pub fn new_zero<T: Num>() -> [T; 9] {
    new(
        T::zero(), T::zero(), T::zero(),
        T::zero(), T::zero(), T::zero(),
        T::zero(), T::zero(), T::zero()
    )
}

#[inline(always)]
pub fn clone<T: Num>(m: [T; 9]) -> [T; 9] {
    new(
        m[0], m[3], m[6],
        m[1], m[4], m[7],
        m[2], m[5], m[8]
    )
}

#[inline(always)]
pub fn copy<T: Num>(out: &mut [T; 9], a: [T; 9]) -> &mut [T; 9] {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4];
    out[5] = a[5];
    out[6] = a[6];
    out[7] = a[7];
    out[8] = a[8];
    out
}
<|endoftext|>


<commit_before>use nom::{alphanumeric, digit, multispace};
use nom::{IResult, Err, ErrorKind, Needed};
use std::str;
use std::str::FromStr;

use common::{column_identifier, field_list, sql_identifier, statement_terminator, table_reference,
             value_list};
use column::Column;
use table::Table;

#[derive(Clone, Debug, Default, Hash, PartialEq)]
pub struct CreateTableStatement {
    pub table: Table,
    pub fields: Vec<Column>,
}

#[derive(Clone, Debug, Hash, PartialEq)]
pub enum SqlType {
    Char(u16),
    Varchar(u16),
    Int(u16),
    Bigint(u16),
    Tinyint(u16),
    Tinyblob,
    Blob,
    Real,
    Tinytext,
    Mediumtext,
    Text,
}

fn len_as_u16(len: &[u8]) -> u16 {
    match str::from_utf8(len) {
        Ok(s) => {
            match u16::from_str(s) {
                Ok(v) => v,
                Err(e) => panic!(e),
            }
        }
        Err(e) => panic!(e),
    }
}

/// A SQL type specifier.
named!(pub type_identifier<&[u8], SqlType>,
    alt_complete!(
          chain!(
              caseless_tag!("mediumtext"),
              || { SqlType::Mediumtext }
          )
        | chain!(
              caseless_tag!("tinyblob"),
              || { SqlType::Tinyblob }
          )
        | chain!(
              caseless_tag!("tinytext"),
              || { SqlType::Tinytext }
          )
        | chain!(
              caseless_tag!("varchar") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              binary: opt!(caseless_tag!("binary")),
              || { SqlType::Varchar(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("tinyint") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Tinyint(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("bigint") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Bigint(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("blob"),
              || { SqlType::Blob }
          )
        | chain!(
              caseless_tag!("real") ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Real }
          )
        | chain!(
              caseless_tag!("text"),
              || { SqlType::Text }
          )
        | chain!(
              caseless_tag!("char") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              binary: opt!(caseless_tag!("binary")),
              || { SqlType::Char(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("int") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Int(len_as_u16(len)) }
          )
    )
);

/// Parse rule for key specifications.
named!(pub key_specification<&[u8], ()>,
    alt_complete!(
          chain!(
              caseless_tag!("unique key") ~
              multispace ~
              name: opt!(sql_identifier) ~
              multispace? ~
              column: delimited!(tag!("("), field_list, tag!(")")),
              || {}
          )
        | chain!(
              caseless_tag!("primary key") ~
              multispace ~
              //name: sql_identifier ~
              //multispace ~
              column: delimited!(tag!("("), column_identifier, tag!(")")) ~
              multispace? ~
              caseless_tag!("autoincrement"),
              || {}
          )
    )
);

/// Parse rule for a comma-separated list.
named!(pub field_specification_list<&[u8], Vec<Column> >,
       many1!(
           complete!(chain!(
               fieldname: column_identifier ~
               multispace ~
               fieldtype: type_identifier ~
               // XXX(malte): some of these are mutually exclusive...
               opt!(chain!(multispace? ~
                           caseless_tag!("not null") ~
                           multispace?,
                           || {}
                    )
               ) ~
               opt!(chain!(multispace? ~
                           caseless_tag!("auto_increment") ~
                           multispace?,
                           || {}
                    )
               ) ~
               opt!(complete!(
                       chain!(
                           multispace? ~
                           caseless_tag!("default") ~
                           multispace ~
                           alt_complete!(
                                 delimited!(tag!("'"), alphanumeric, tag!("'"))
                               | digit
                               | tag!("''")
                           ) ~
                           multispace?,
                           || {}
                       ))
               ) ~
               opt!(
                   complete!(chain!(
                       multispace? ~
                       tag!(",") ~
                       multispace?,
                       || {}
                   ))
               ),
               || { fieldname }
           ))
       )
);

/// Parse rule for a SQL CREATE TABLE query.
/// TODO(malte): support types, TEMPORARY tables, IF NOT EXISTS, AS stmt
named!(pub creation<&[u8], CreateTableStatement>,
    complete!(chain!(
        caseless_tag!("create") ~
        multispace ~
        caseless_tag!("table") ~
        multispace ~
        table: table_reference ~
        multispace ~
        fields: chain!(
                tag!("(") ~
                multispace? ~
                fields: field_specification_list ~
                multispace? ~
                opt!(key_specification) ~
                multispace? ~
                tag!(")"),
                || { fields }
            ) ~
        multispace? ~
        // XXX(malte): wrap the two below in a permutation! rule that permits arbitrary ordering
        opt!(
            complete!(
                chain!(
                    caseless_tag!("type") ~
                    multispace? ~
                    tag!("=") ~
                    multispace? ~
                    alphanumeric,
                    || {}
                )
            )
        ) ~
        multispace? ~
        opt!(
            complete!(
                chain!(
                    caseless_tag!("pack_keys") ~
                    multispace? ~
                    tag!("=") ~
                    multispace? ~
                    alt_complete!(tag!("0") | tag!("1")),
                    || {}
                )
            )
        ) ~
        statement_terminator,
        || {
            // "table AS alias" isn't legal in CREATE statements
            assert!(table.alias.is_none());
            CreateTableStatement {
                table: table,
                fields: fields,
            }
        }
    ))
);

#[cfg(test)]
mod tests {
    use super::*;
    use column::Column;
    use table::Table;

    #[test]
    fn sql_types() {
        let type0 = "bigint(20) unsigned";
        let type1 = "varchar(255) binary";

        let res = type_identifier(type0.as_bytes());
        assert_eq!(res.unwrap().1, SqlType::Bigint(20));
        let res = type_identifier(type1.as_bytes());
        assert_eq!(res.unwrap().1, SqlType::Varchar(255));
    }

    #[test]
    fn field_spec() {
        // N.B. trailing comma here because field_specification_list! doesn't handle the eof case
        // because it is never validly the end of a query
        let qstring = "id bigint(20), name varchar(255),";

        let res = field_specification_list(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   vec![Column::from("id"), Column::from("name")]);
    }

    #[test]
    fn simple_create() {
        let qstring = "CREATE TABLE users (id bigint(20), name varchar(255), email varchar(255));";

        let res = creation(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   CreateTableStatement {
                       table: Table::from("users"),
                       fields: vec![Column::from("id"),
                                    Column::from("name"),
                                    Column::from("email")],
                       ..Default::default()
                   });
    }

    #[test]
    fn mediawiki_create() {
        let qstring = "CREATE TABLE user_newtalk (  user_id int(5) NOT NULL default '0',  user_ip \
                       varchar(40) NOT NULL default '') TYPE=MyISAM;";
        let res = creation(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   CreateTableStatement {
                       table: Table::from("user_newtalk"),
                       fields: vec![Column::from("user_id"), Column::from("user_ip")],
                       ..Default::default()
                   });
    }
}
<commit_msg>Support more SQL types<commit_after>use nom::{alphanumeric, digit, multispace};
use nom::{IResult, Err, ErrorKind, Needed};
use std::str;
use std::str::FromStr;

use common::{column_identifier, field_list, sql_identifier, statement_terminator, table_reference,
             value_list};
use column::Column;
use table::Table;

#[derive(Clone, Debug, Default, Hash, PartialEq)]
pub struct CreateTableStatement {
    pub table: Table,
    pub fields: Vec<Column>,
}

#[derive(Clone, Debug, Hash, PartialEq)]
pub enum SqlType {
    Char(u16),
    Varchar(u16),
    Int(u16),
    Bigint(u16),
    Tinyint(u16),
    Tinyblob,
    Blob,
    Double,
    Real,
    Tinytext,
    Mediumtext,
    Text,
    Date,
    Timestamp,
}

fn len_as_u16(len: &[u8]) -> u16 {
    match str::from_utf8(len) {
        Ok(s) => {
            match u16::from_str(s) {
                Ok(v) => v,
                Err(e) => panic!(e),
            }
        }
        Err(e) => panic!(e),
    }
}

/// A SQL type specifier.
named!(pub type_identifier<&[u8], SqlType>,
    alt_complete!(
          chain!(
              caseless_tag!("mediumtext"),
              || { SqlType::Mediumtext }
          )
        | chain!(
              caseless_tag!("timestamp"),
              || { SqlType::Timestamp }
          )
        | chain!(
              caseless_tag!("tinyblob"),
              || { SqlType::Tinyblob }
          )
        | chain!(
              caseless_tag!("tinytext"),
              || { SqlType::Tinytext }
          )
        | chain!(
              caseless_tag!("varchar") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              binary: opt!(caseless_tag!("binary")),
              || { SqlType::Varchar(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("tinyint") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Tinyint(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("bigint") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Bigint(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("double") ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Double }
          )
        | chain!(
              caseless_tag!("blob"),
              || { SqlType::Blob }
          )
        | chain!(
              caseless_tag!("date"),
              || { SqlType::Date }
          )
        | chain!(
              caseless_tag!("real") ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Real }
          )
        | chain!(
              caseless_tag!("text"),
              || { SqlType::Text }
          )
        | chain!(
              caseless_tag!("char") ~
              len: delimited!(tag!("("), digit, tag!(")")) ~
              multispace? ~
              binary: opt!(caseless_tag!("binary")),
              || { SqlType::Char(len_as_u16(len)) }
          )
        | chain!(
              caseless_tag!("int") ~
              len: opt!(delimited!(tag!("("), digit, tag!(")"))) ~
              multispace? ~
              signed: opt!(alt_complete!(caseless_tag!("unsigned") | caseless_tag!("signed"))),
              || { SqlType::Int(match len {
                  Some(len) => len_as_u16(len),
                  None => 32 as u16,
              }) }
          )
    )
);

/// Parse rule for key specifications.
named!(pub key_specification<&[u8], ()>,
    alt_complete!(
          chain!(
              caseless_tag!("unique key") ~
              multispace ~
              name: opt!(sql_identifier) ~
              multispace? ~
              column: delimited!(tag!("("), field_list, tag!(")")),
              || {}
          )
        | chain!(
              caseless_tag!("primary key") ~
              multispace ~
              //name: sql_identifier ~
              //multispace ~
              column: delimited!(tag!("("), column_identifier, tag!(")")) ~
              multispace? ~
              caseless_tag!("autoincrement"),
              || {}
          )
    )
);

/// Parse rule for a comma-separated list.
named!(pub field_specification_list<&[u8], Vec<Column> >,
       many1!(
           complete!(chain!(
               fieldname: column_identifier ~
               multispace ~
               fieldtype: type_identifier ~
               // XXX(malte): some of these are mutually exclusive...
               opt!(chain!(multispace? ~
                           caseless_tag!("not null") ~
                           multispace?,
                           || {}
                    )
               ) ~
               opt!(chain!(multispace? ~
                           caseless_tag!("auto_increment") ~
                           multispace?,
                           || {}
                    )
               ) ~
               opt!(complete!(
                       chain!(
                           multispace? ~
                           caseless_tag!("default") ~
                           multispace ~
                           alt_complete!(
                                 delimited!(tag!("'"), alphanumeric, tag!("'"))
                               | digit
                               | tag!("''")
                           ) ~
                           multispace?,
                           || {}
                       ))
               ) ~
               opt!(
                   complete!(chain!(
                       multispace? ~
                       tag!(",") ~
                       multispace?,
                       || {}
                   ))
               ),
               || { fieldname }
           ))
       )
);

/// Parse rule for a SQL CREATE TABLE query.
/// TODO(malte): support types, TEMPORARY tables, IF NOT EXISTS, AS stmt
named!(pub creation<&[u8], CreateTableStatement>,
    complete!(chain!(
        caseless_tag!("create") ~
        multispace ~
        caseless_tag!("table") ~
        multispace ~
        table: table_reference ~
        multispace ~
        fields: chain!(
                tag!("(") ~
                multispace? ~
                fields: field_specification_list ~
                multispace? ~
                opt!(key_specification) ~
                multispace? ~
                tag!(")"),
                || { fields }
            ) ~
        multispace? ~
        // XXX(malte): wrap the two below in a permutation! rule that permits arbitrary ordering
        opt!(
            complete!(
                chain!(
                    caseless_tag!("type") ~
                    multispace? ~
                    tag!("=") ~
                    multispace? ~
                    alphanumeric,
                    || {}
                )
            )
        ) ~
        multispace? ~
        opt!(
            complete!(
                chain!(
                    caseless_tag!("pack_keys") ~
                    multispace? ~
                    tag!("=") ~
                    multispace? ~
                    alt_complete!(tag!("0") | tag!("1")),
                    || {}
                )
            )
        ) ~
        statement_terminator,
        || {
            // "table AS alias" isn't legal in CREATE statements
            assert!(table.alias.is_none());
            CreateTableStatement {
                table: table,
                fields: fields,
            }
        }
    ))
);

#[cfg(test)]
mod tests {
    use super::*;
    use column::Column;
    use table::Table;

    #[test]
    fn sql_types() {
        let type0 = "bigint(20) unsigned";
        let type1 = "varchar(255) binary";

        let res = type_identifier(type0.as_bytes());
        assert_eq!(res.unwrap().1, SqlType::Bigint(20));
        let res = type_identifier(type1.as_bytes());
        assert_eq!(res.unwrap().1, SqlType::Varchar(255));
    }

    #[test]
    fn field_spec() {
        // N.B. trailing comma here because field_specification_list! doesn't handle the eof case
        // because it is never validly the end of a query
        let qstring = "id bigint(20), name varchar(255),";

        let res = field_specification_list(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   vec![Column::from("id"), Column::from("name")]);
    }

    #[test]
    fn simple_create() {
        let qstring = "CREATE TABLE users (id bigint(20), name varchar(255), email varchar(255));";

        let res = creation(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   CreateTableStatement {
                       table: Table::from("users"),
                       fields: vec![Column::from("id"),
                                    Column::from("name"),
                                    Column::from("email")],
                       ..Default::default()
                   });
    }

    #[test]
    fn mediawiki_create() {
        let qstring = "CREATE TABLE user_newtalk (  user_id int(5) NOT NULL default '0',  user_ip \
                       varchar(40) NOT NULL default '') TYPE=MyISAM;";
        let res = creation(qstring.as_bytes());
        assert_eq!(res.unwrap().1,
                   CreateTableStatement {
                       table: Table::from("user_newtalk"),
                       fields: vec![Column::from("user_id"), Column::from("user_ip")],
                       ..Default::default()
                   });
    }
}
<|endoftext|>


<commit_before>use relation::Change;
use flow::Flow;
use value::{Value, Field, Tuple};
use relation::Reference;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    Add,
    Subtract,
    Count,
    Sum,
    Min,
    Max,
    Any
}

// TODO we hackily assign source numbers to inner and outer
//      will be fixed when Reference goes away
const OUTER: usize = 0;
const INNER: usize = 1;

impl Reference {
    pub fn resolve_as_vector<'a>(&'a self, outer: &'a Tuple, inner_fields: &[Field], inner_values: &'a [Vec<Value>]) -> Vec<&Value> {
        match *self {
            Reference::Constant{ref value} => {
                vec![value]
            },
            Reference::Variable{source, ref field} => {
                match source {
                    OUTER => {
                        vec![outer.field(field)]
                    }
                    INNER => {
                        let ix = inner_fields.iter().position(|inner_field| inner_field == field).unwrap();
                        inner_values.iter().map(|values| &values[ix]).collect()
                    }
                    _ => unreachable!(),
                }
            }
        }
    }
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, arguments: &[Reference], inputs: &[Tuple]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = arguments.iter().map(|reference|
            reference.resolve(&inputs[..])
            ).collect::<Vec<_>>();
        match (*self, &values[..]) {
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Count, _) => panic!("Cannot use {:?} in a join", self),
            (Sum, _) => panic!("Cannot use {:?} in a join", self),
            (Min, _) => panic!("Cannot use {:?} in a join", self),
            (Max, _) => panic!("Cannot use {:?} in a join", self),
            (Any, _) => panic!("Cannot use {:?} in a join", self),
            _ => panic!("Type error while calling: {:?} {:?}", self, &arguments)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[Reference], outer: &Tuple, inner_fields: &[Field], inner_values: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner_values.len() as f64)]]
            }
            (Sum, [ref in_ref]) => {
                let in_values = in_ref.resolve_as_vector(outer, inner_fields, inner_values);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Min, [ref by_ref, ref of_ref]) => {
                let by_values = by_ref.resolve_as_vector(outer, inner_fields, inner_values);
                let of_values = of_ref.resolve_as_vector(outer, inner_fields, inner_values);
                assert!(by_values.len() == of_values.len());
                if by_values.len() == 0 {
                    vec![]
                } else {
                    let (_, min) = by_values[1..].into_iter().zip(of_values[1..].into_iter()).fold(
                        (&by_values[0], &of_values[0]),
                        |(min_by_value, min_of_value), (by_value, of_value)| {
                            if by_value < min_by_value {
                                (by_value, of_value)
                            } else {
                                (min_by_value, min_of_value)
                            }
                        });
                    vec![vec![(*min).clone()]]
                }
            },
            (Max, [ref by_ref, ref of_ref]) => {
                let by_values = by_ref.resolve_as_vector(outer, inner_fields, inner_values);
                let of_values = of_ref.resolve_as_vector(outer, inner_fields, inner_values);
                assert!(by_values.len() == of_values.len());
                if by_values.len() == 0 {
                    vec![]
                } else {
                    let (_, max) = by_values[1..].into_iter().zip(of_values[1..].into_iter()).fold(
                        (&by_values[0], &of_values[0]),
                        |(max_by_value, max_of_value), (by_value, of_value)| {
                            if by_value > max_by_value {
                                (by_value, of_value)
                            } else {
                                (max_by_value, max_of_value)
                            }
                        });
                    vec![vec![(*max).clone()]]
                }
            },
            (Any, [ref in_ref]) => {
                let in_values = in_ref.resolve_as_vector(outer, inner_fields, inner_values);
                vec![vec![Bool(in_values.len() > 0)]]
            }
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "min" => Primitive::Min,
            "max" => Primitive::Max,
            "any" => Primitive::Any,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("min", vec![], vec!["by", "of"], vec!["out"]),
        ("max", vec![], vec!["by", "of"], vec!["out"]),
        ("any", vec![], vec!["in"], vec!["out"]),
    ]
}

pub fn install(flow: &mut Flow) {
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut display_name_values = Vec::new();
    for (name, scalar_inputs, vector_inputs, outputs) in primitives().into_iter() {
        view_values.push(vec![string!("{}", name), string!("primitive")]);
        display_name_values.push(vec![string!("{}", name), string!("{}", name)]);
        for field in scalar_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("scalar input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in vector_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("vector input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in outputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
    }
    flow.get_output_mut("view").change(Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("display name").change(Change{
        fields: vec!["display name: id".to_owned(), "display name: name".to_owned()],
        insert: display_name_values,
        remove: Vec::new(),
    });
}<commit_msg>Remove min/max. It was a trick.<commit_after>use relation::Change;
use flow::Flow;
use value::{Value, Field, Tuple};
use relation::Reference;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    Add,
    Subtract,
    Count,
    Sum,
    Any
}

// TODO we hackily assign source numbers to inner and outer
//      will be fixed when Reference goes away
const OUTER: usize = 0;
const INNER: usize = 1;

impl Reference {
    pub fn resolve_as_vector<'a>(&'a self, outer: &'a Tuple, inner_fields: &[Field], inner_values: &'a [Vec<Value>]) -> Vec<&Value> {
        match *self {
            Reference::Constant{ref value} => {
                vec![value]
            },
            Reference::Variable{source, ref field} => {
                match source {
                    OUTER => {
                        vec![outer.field(field)]
                    }
                    INNER => {
                        let ix = inner_fields.iter().position(|inner_field| inner_field == field).unwrap();
                        inner_values.iter().map(|values| &values[ix]).collect()
                    }
                    _ => unreachable!(),
                }
            }
        }
    }
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, arguments: &[Reference], inputs: &[Tuple]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = arguments.iter().map(|reference|
            reference.resolve(&inputs[..])
            ).collect::<Vec<_>>();
        match (*self, &values[..]) {
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Count, _) => panic!("Cannot use {:?} in a join", self),
            (Sum, _) => panic!("Cannot use {:?} in a join", self),
            (Any, _) => panic!("Cannot use {:?} in a join", self),
            _ => panic!("Type error while calling: {:?} {:?}", self, &arguments)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[Reference], outer: &Tuple, inner_fields: &[Field], inner_values: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner_values.len() as f64)]]
            }
            (Sum, [ref in_ref]) => {
                let in_values = in_ref.resolve_as_vector(outer, inner_fields, inner_values);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Any, [ref in_ref]) => {
                let in_values = in_ref.resolve_as_vector(outer, inner_fields, inner_values);
                vec![vec![Bool(in_values.len() > 0)]]
            }
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "any" => Primitive::Any,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("any", vec![], vec!["in"], vec!["out"]),
    ]
}

pub fn install(flow: &mut Flow) {
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut display_name_values = Vec::new();
    for (name, scalar_inputs, vector_inputs, outputs) in primitives().into_iter() {
        view_values.push(vec![string!("{}", name), string!("primitive")]);
        display_name_values.push(vec![string!("{}", name), string!("{}", name)]);
        for field in scalar_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("scalar input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in vector_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("vector input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in outputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
    }
    flow.get_output_mut("view").change(Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("display name").change(Change{
        fields: vec!["display name: id".to_owned(), "display name: name".to_owned()],
        insert: display_name_values,
        remove: Vec::new(),
    });
}<|endoftext|>


<commit_before>extern crate iron;
extern crate rustc_serialize;
extern crate queryst;

use rustc_serialize::json::{self, Json};
use iron::prelude::*;
use iron::status;
use queryst::parse;

#[derive(RustcEncodable)]
pub struct PadJson {
    str: String
}

fn left_pad(string: &str, len: u32, ch: &str) -> String {

    let mut i: i32 = -1;
    let temp_len: i32 = len as i32 - (string.len() as i32);
    let mut return_string : String = string.to_string();

    while i < temp_len {
        return_string = ch.to_string() + &string.to_string();
        i = i + 1;
    }

    return String::from(return_string);
}

fn main() {
    fn handler(req: &mut Request) -> IronResult<Response> {

        let query = req.url.query.clone().unwrap_or("".to_string());

        let query_params: Json = parse(&query.to_string()).unwrap();
        let obj                = query_params.as_object().unwrap();

        let string : &str = obj.get("str").unwrap().as_string().unwrap();
        let len : u32     = obj.get("len").unwrap().as_string().unwrap().parse().unwrap();
        let ch : &str     = obj.get("ch").unwrap().as_string().unwrap();

        let padded_resp = PadJson {
            str: left_pad(string, len, ch),
        };

        Ok(Response::with((status::Ok, json::encode(&padded_resp).unwrap())))
    }

    Iron::new(handler).http("localhost:3000").unwrap();
}
<commit_msg>Add functional rust leftpad output<commit_after>extern crate iron;
extern crate rustc_serialize;
extern crate queryst;

use rustc_serialize::json::{self, Json};
use iron::prelude::*;
use iron::status;
use queryst::parse;

#[derive(RustcEncodable)]
pub struct PadJson {
    str: String
}

fn left_pad(string: &str, len: u32, ch: &str) -> String {

    let mut i             : i32    = -1;
    let temp_len          : i32    = len as i32 - (string.len() as i32);
    let mut padded_string : String = string.to_string();

    while i < temp_len {
        padded_string = ch.to_string() + &padded_string;
        i = i + 1;
    }

    return padded_string;
}

fn main() {
    fn handler(req: &mut Request) -> IronResult<Response> {

        let query = req.url.query.clone().unwrap_or("".to_string());

        let query_params: Json = parse(&query.to_string()).unwrap();
        let obj                = query_params.as_object().unwrap();

        let string : &str = obj.get("str").unwrap().as_string().unwrap();
        let len : u32     = obj.get("len").unwrap().as_string().unwrap().parse().unwrap();
        let ch : &str     = obj.get("ch").unwrap().as_string().unwrap();

        let padded_resp = PadJson {
            str: left_pad(string, len, ch),
        };

        Ok(Response::with((status::Ok, json::encode(&padded_resp).unwrap())))
    }

    Iron::new(handler).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>extern crate rustbox;

use std::char;
use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use super::Response;
use cursor::Direction;
use keyboard::Key;
use view::View;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub sender: Sender<rustbox::Event>,
    events: Receiver<rustbox::Event>,
    view: View<'e>,

    pub running: bool,
}

impl<'e> Editor<'e> {
    pub fn new(filename: String) -> Editor<'e> {
        let path = Path::new(filename);
        let view = View::new(&path);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            view: view,
            running: false,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let input_key: Option<Key> = num::from_u16(key);

        let event_status = self.handle_system_event(input_key);
        match event_status {
            EventStatus::Handled(r) => { return r }
            EventStatus::NotHandled => { /* keep going */ }
        }

        print!("k: {} ", key);
        print!("c: {} **", ch);

        match char::from_u32(ch) {
            Some(c) => {
                self.view.insert_char(c);
                return Response::Continue
            }
            _ => {}
        }

        Response::Continue
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.view.buffer.lines;
        let path = Path::new(&self.view.buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let data = format!("{}\n", line.borrow().data);
            let result = file.write(data.as_bytes());

            if result.is_err() {
                // TODO(greg): figure out what to do here.
            }
        }
    }

    pub fn draw(&mut self) {
        self.view.draw();
        self.view.draw_status();
        self.view.draw_cursor();
    }

    pub fn start(&mut self) {
        self.running = true;
        self.event_loop();
        self.main_loop();
    }

    fn main_loop(&mut self) {
        while self.running {
            self.view.clear();
            self.draw();
            rustbox::present();
            match self.events.recv() {
                rustbox::KeyEvent(_, key, ch) => {
                    match self.handle_key_event(key, ch) {
                        // TODO(greg): refactor event handling responses
                        Response::Continue => { /* keep going*/ }
                        Response::Quit     => self.running = false,
                    }
                },
                _ => {}
            }
        }
    }

    fn event_loop(&self) {
        // clone the sender so that we can use it in the proc
        let sender = self.sender.clone();

        spawn(proc() {
            loop {
                sender.send(rustbox::poll_event());
            }
        });
    }

    fn handle_system_event(&mut self, k: Option<Key>) -> EventStatus {
        if k.is_none() {
            return EventStatus::NotHandled
        }

        let key = k.unwrap();
        match key {
            Key::Up        => { self.view.move_cursor(Direction::Up); }
            Key::Down      => { self.view.move_cursor(Direction::Down); }
            Key::Left      => { self.view.move_cursor(Direction::Left); }
            Key::Right     => { self.view.move_cursor(Direction::Right); }
            Key::Enter     => { self.view.insert_line(); }
            Key::Space     => { self.view.insert_char(' '); }
            Key::Backspace => { self.view.delete_char(Direction::Left); }
            Key::Delete    => { self.view.delete_char(Direction::Right); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<commit_msg>Remove unnecessary variable<commit_after>extern crate rustbox;

use std::char;
use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use super::Response;
use cursor::Direction;
use keyboard::Key;
use view::View;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub sender: Sender<rustbox::Event>,
    events: Receiver<rustbox::Event>,
    view: View<'e>,

    pub running: bool,
}

impl<'e> Editor<'e> {
    pub fn new(filename: String) -> Editor<'e> {
        let path = Path::new(filename);
        let view = View::new(&path);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            view: view,
            running: false,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let input_key: Option<Key> = num::from_u16(key);

        match self.handle_system_event(input_key) {
            EventStatus::Handled(r) => { return r }
            EventStatus::NotHandled => { /* keep going */ }
        }

        print!("k: {} ", key);
        print!("c: {} **", ch);

        match char::from_u32(ch) {
            Some(c) => {
                self.view.insert_char(c);
                return Response::Continue
            }
            _ => {}
        }

        Response::Continue
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.view.buffer.lines;
        let path = Path::new(&self.view.buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let data = format!("{}\n", line.borrow().data);
            let result = file.write(data.as_bytes());

            if result.is_err() {
                // TODO(greg): figure out what to do here.
            }
        }
    }

    pub fn draw(&mut self) {
        self.view.draw();
        self.view.draw_status();
        self.view.draw_cursor();
    }

    pub fn start(&mut self) {
        self.running = true;
        self.event_loop();
        self.main_loop();
    }

    fn main_loop(&mut self) {
        while self.running {
            self.view.clear();
            self.draw();
            rustbox::present();
            match self.events.recv() {
                rustbox::KeyEvent(_, key, ch) => {
                    match self.handle_key_event(key, ch) {
                        // TODO(greg): refactor event handling responses
                        Response::Continue => { /* keep going*/ }
                        Response::Quit     => self.running = false,
                    }
                },
                _ => {}
            }
        }
    }

    fn event_loop(&self) {
        // clone the sender so that we can use it in the proc
        let sender = self.sender.clone();

        spawn(proc() {
            loop {
                sender.send(rustbox::poll_event());
            }
        });
    }

    fn handle_system_event(&mut self, k: Option<Key>) -> EventStatus {
        if k.is_none() {
            return EventStatus::NotHandled
        }

        let key = k.unwrap();
        match key {
            Key::Up        => { self.view.move_cursor(Direction::Up); }
            Key::Down      => { self.view.move_cursor(Direction::Down); }
            Key::Left      => { self.view.move_cursor(Direction::Left); }
            Key::Right     => { self.view.move_cursor(Direction::Right); }
            Key::Enter     => { self.view.insert_line(); }
            Key::Space     => { self.view.insert_char(' '); }
            Key::Backspace => { self.view.delete_char(Direction::Left); }
            Key::Delete    => { self.view.delete_char(Direction::Right); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<|endoftext|>


<commit_before>use crate::component_for_bin;
use crate::dist::manifest::{Component, Manifest};
use crate::dist::temp;
use error_chain::error_chain;
use std::ffi::OsString;
use std::io::{self, Write};
use std::path::PathBuf;
use url::Url;

pub const TOOLSTATE_MSG: &str =
    "If you require these components, please install and use the latest successful build version,\n\
     which you can find at <https://rust-lang-nursery.github.io/rust-toolstate>.\n\nAfter determining \
     the correct date, install it with a command such as:\n\n    \
     rustup toolchain install nightly-2018-12-27\n\n\
     Then you can use the toolchain with commands such as:\n\n    \
     cargo +nightly-2018-12-27 build";

error_chain! {
    links {
        Download(download::Error, download::ErrorKind);
    }

    foreign_links {
        Temp(temp::Error);
        Io(io::Error);
        Open(opener::OpenError);
    }

    errors {
        LocatingWorkingDir {
            description("could not locate working directory")
        }
        ReadingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not read file")
            display("could not read {} file: '{}'", name, path.display())
        }
        ReadingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not read directory")
            display("could not read {} directory: '{}'", name, path.display())
        }
        WritingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not write file")
            display("could not write {} file: '{}'", name, path.display())
        }
        CreatingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not create directory")
            display("could not create {} directory: '{}'", name, path.display())
        }
        ExpectedType(t: &'static str, n: String) {
            description("expected type")
            display("expected type: '{}' for '{}'", t, n)
        }
        FilteringFile {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy file")
            display("could not copy {} file from '{}' to '{}'", name, src.display(), dest.display())
        }
        RenamingFile {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not rename file")
            display("could not rename {} file from '{}' to '{}'",
                name, src.display(), dest.display())
        }
        RenamingDirectory {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not rename directory")
            display("could not rename {} directory from '{}' to '{}'", name, src.display(), dest.display())
        }
        DownloadingFile {
            url: Url,
            path: PathBuf,
        } {
            description("could not download file")
            display("could not download file from '{}' to '{}'", url, path.display())
        }
        DownloadNotExists {
            url: Url,
            path: PathBuf,
        } {
            description("could not download file")
            display("could not download file from '{}' to '{}'", url, path.display())
        }
        InvalidUrl {
            url: String,
        } {
            description("invalid url")
            display("invalid url: {}", url)
        }
        RunningCommand {
            name: OsString,
        } {
            description("command failed")
            display("command failed: '{}'", PathBuf::from(name).display())
        }
        NotAFile {
            path: PathBuf,
        } {
            description("not a file")
            display("not a file: '{}'", path.display())
        }
        NotADirectory {
            path: PathBuf,
        } {
            description("not a directory")
            display("not a directory: '{}'", path.display())
        }
        LinkingFile {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not link file")
            display("could not create link from '{}' to '{}'", src.display(), dest.display())
        }
        LinkingDirectory {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not symlink directory")
            display("could not create link from '{}' to '{}'", src.display(), dest.display())
        }
        CopyingDirectory {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy directory")
            display("could not copy directory from '{}' to '{}'", src.display(), dest.display())
        }
        CopyingFile {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy file")
            display("could not copy file from '{}' to '{}'", src.display(), dest.display())
        }
        RemovingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not remove file")
            display("could not remove '{}' file: '{}'", name, path.display())
        }
        RemovingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not remove directory")
            display("could not remove '{}' directory: '{}'", name, path.display())
        }
        SettingPermissions {
            path: PathBuf,
        } {
            description("failed to set permissions")
            display("failed to set permissions for '{}'", path.display())
        }
        GettingCwd {
            description("couldn't get current working directory")
        }
        CargoHome {
            description("couldn't find value of CARGO_HOME")
        }
        RustupHome {
            description("couldn't find value of RUSTUP_HOME")
        }
        InvalidToolchainName(t: String) {
            description("invalid toolchain name")
            display("invalid toolchain name: '{}'", t)
        }
        InvalidCustomToolchainName(t: String) {
            description("invalid custom toolchain name")
            display("invalid custom toolchain name: '{}'", t)
        }
        ChecksumFailed {
            url: String,
            expected: String,
            calculated: String,
        } {
            description("checksum failed")
            display("checksum failed, expected: '{}', calculated: '{}'",
                    expected,
                    calculated)
        }
        ComponentConflict {
            name: String,
            path: PathBuf,
        } {
            description("conflicting component")
            display("failed to install component: '{}', detected conflict: '{:?}'",
                    name,
                    path)
        }
        ComponentMissingFile {
            name: String,
            path: PathBuf,
        } {
            description("missing file in component")
            display("failure removing component '{}', directory does not exist: '{:?}'",
                    name,
                    path)
        }
        ComponentMissingDir {
            name: String,
            path: PathBuf,
        } {
            description("missing directory in component")
            display("failure removing component '{}', directory does not exist: '{:?}'",
                    name,
                    path)
        }
        CorruptComponent(name: String) {
            description("corrupt component manifest")
            display("component manifest for '{}' is corrupt", name)
        }
        ExtractingPackage {
            description("failed to extract package (perhaps you ran out of disk space?)")
        }
        BadInstallerVersion(v: String) {
            description("unsupported installer version")
            display("unsupported installer version: {}", v)
        }
        BadInstalledMetadataVersion(v: String) {
            description("unsupported metadata version in existing installation")
            display("unsupported metadata version in existing installation: {}", v)
        }
        ComponentDirPermissionsFailed {
            description("I/O error walking directory during install")
        }
        ComponentFilePermissionsFailed {
            description("error setting file permissions during install")
        }
        ComponentDownloadFailed(c: String) {
            description("component download failed")
            display("component download failed for {}", c)
        }
        Parsing(e: toml::de::Error) {
            description("error parsing manifest")
        }
        UnsupportedVersion(v: String) {
            description("unsupported manifest version")
            display("manifest version '{}' is not supported", v)
        }
        MissingPackageForComponent(name: String) {
            description("missing package for component")
            display("server sent a broken manifest: missing package for component {}", name)
        }
        MissingPackageForRename(name: String) {
            description("missing package for the target of a rename")
            display("server sent a broken manifest: missing package for the target of a rename {}", name)
        }
        RequestedComponentsUnavailable(c: Vec<Component>, manifest: Manifest, toolchain: String) {
            description("some requested components are unavailable to download")
            display("{} for channel '{}'\n{}", component_unavailable_msg(&c, &manifest), toolchain, TOOLSTATE_MSG)
        }
        UnknownMetadataVersion(v: String) {
            description("unknown metadata version")
            display("unknown metadata version: '{}'", v)
        }
        ToolchainNotInstalled(t: String) {
            description("toolchain is not installed")
            display("toolchain '{}' is not installed", t)
        }
        OverrideToolchainNotInstalled(t: String) {
            description("override toolchain is not installed")
            display("override toolchain '{}' is not installed", t)
        }
        BinaryNotFound(bin: String, t: String, is_default: bool) {
            description("toolchain does not contain binary")
            display("'{}' is not installed for the toolchain '{}'{}", bin, t, install_msg(bin, t, *is_default))
        }
        NeedMetadataUpgrade {
            description("rustup's metadata is out of date. run `rustup self upgrade-data`")
        }
        UpgradeIoError {
            description("I/O error during upgrade")
        }
        BadInstallerType(s: String) {
            description("invalid extension for installer")
            display("invalid extension for installer: '{}'", s)
        }
        ComponentsUnsupported(t: String) {
            description("toolchain does not support components")
            display("toolchain '{}' does not support components", t)
        }
        UnknownComponent(t: String, c: String, s: Option<String>) {
            description("toolchain does not contain component")
            display("toolchain '{}' does not contain component {}{}", t, c, if let Some(suggestion) = s {
                format!("; did you mean '{}'?", suggestion)
            } else {
                "".to_string()
            })
        }
        AddingRequiredComponent(t: String, c: String) {
            description("required component cannot be added")
            display("component {} was automatically added because it is required for toolchain '{}'",
                    c, t)
        }
        ParsingSettings(e: toml::de::Error) {
            description("error parsing settings")
        }
        RemovingRequiredComponent(t: String, c: String) {
            description("required component cannot be removed")
            display("component {} is required for toolchain '{}' and cannot be removed",
                    c, t)
        }
        NoExeName {
            description("couldn't determine self executable name")
        }
    }
}

fn component_unavailable_msg(cs: &[Component], manifest: &Manifest) -> String {
    assert!(!cs.is_empty());

    let mut buf = vec![];

    if cs.len() == 1 {
        let _ = write!(
            buf,
            "component {} is unavailable for download",
            &cs[0].description(manifest)
        );
    } else {
        let same_target = cs
            .iter()
            .all(|c| c.target == cs[0].target || c.target.is_none());
        if same_target {
            let cs_str = cs
                .iter()
                .map(|c| format!("'{}'", c.short_name(manifest)))
                .collect::<Vec<_>>()
                .join(", ");
            let _ = write!(buf, "some components unavailable for download: {}", cs_str,);
        } else {
            let cs_str = cs
                .iter()
                .map(|c| c.description(manifest))
                .collect::<Vec<_>>()
                .join(", ");
            let _ = write!(buf, "some components unavailable for download: {}", cs_str,);
        }
    }

    String::from_utf8(buf).expect("")
}

fn install_msg(bin: &str, toolchain: &str, is_default: bool) -> String {
    match component_for_bin(bin) {
        Some(c) => format!("\nTo install, run `rustup component add {}{}`", c, {
            if is_default {
                String::new()
            } else {
                format!(" --toolchain {}", toolchain)
            }
        }),
        None => String::new(),
    }
}
<commit_msg>Link to rustup-components-history instead on missing component<commit_after>use crate::component_for_bin;
use crate::dist::manifest::{Component, Manifest};
use crate::dist::temp;
use error_chain::error_chain;
use std::ffi::OsString;
use std::io::{self, Write};
use std::path::PathBuf;
use url::Url;

pub const TOOLSTATE_MSG: &str =
    "If you require these components, please install and use the latest successful build version,\n\
     which you can find at <https://rust-lang.github.io/rustup-components-history>.\n\nAfter determining \
     the correct date, install it with a command such as:\n\n    \
     rustup toolchain install nightly-2018-12-27\n\n\
     Then you can use the toolchain with commands such as:\n\n    \
     cargo +nightly-2018-12-27 build";

error_chain! {
    links {
        Download(download::Error, download::ErrorKind);
    }

    foreign_links {
        Temp(temp::Error);
        Io(io::Error);
        Open(opener::OpenError);
    }

    errors {
        LocatingWorkingDir {
            description("could not locate working directory")
        }
        ReadingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not read file")
            display("could not read {} file: '{}'", name, path.display())
        }
        ReadingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not read directory")
            display("could not read {} directory: '{}'", name, path.display())
        }
        WritingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not write file")
            display("could not write {} file: '{}'", name, path.display())
        }
        CreatingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not create directory")
            display("could not create {} directory: '{}'", name, path.display())
        }
        ExpectedType(t: &'static str, n: String) {
            description("expected type")
            display("expected type: '{}' for '{}'", t, n)
        }
        FilteringFile {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy file")
            display("could not copy {} file from '{}' to '{}'", name, src.display(), dest.display())
        }
        RenamingFile {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not rename file")
            display("could not rename {} file from '{}' to '{}'",
                name, src.display(), dest.display())
        }
        RenamingDirectory {
            name: &'static str,
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not rename directory")
            display("could not rename {} directory from '{}' to '{}'", name, src.display(), dest.display())
        }
        DownloadingFile {
            url: Url,
            path: PathBuf,
        } {
            description("could not download file")
            display("could not download file from '{}' to '{}'", url, path.display())
        }
        DownloadNotExists {
            url: Url,
            path: PathBuf,
        } {
            description("could not download file")
            display("could not download file from '{}' to '{}'", url, path.display())
        }
        InvalidUrl {
            url: String,
        } {
            description("invalid url")
            display("invalid url: {}", url)
        }
        RunningCommand {
            name: OsString,
        } {
            description("command failed")
            display("command failed: '{}'", PathBuf::from(name).display())
        }
        NotAFile {
            path: PathBuf,
        } {
            description("not a file")
            display("not a file: '{}'", path.display())
        }
        NotADirectory {
            path: PathBuf,
        } {
            description("not a directory")
            display("not a directory: '{}'", path.display())
        }
        LinkingFile {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not link file")
            display("could not create link from '{}' to '{}'", src.display(), dest.display())
        }
        LinkingDirectory {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not symlink directory")
            display("could not create link from '{}' to '{}'", src.display(), dest.display())
        }
        CopyingDirectory {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy directory")
            display("could not copy directory from '{}' to '{}'", src.display(), dest.display())
        }
        CopyingFile {
            src: PathBuf,
            dest: PathBuf,
        } {
            description("could not copy file")
            display("could not copy file from '{}' to '{}'", src.display(), dest.display())
        }
        RemovingFile {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not remove file")
            display("could not remove '{}' file: '{}'", name, path.display())
        }
        RemovingDirectory {
            name: &'static str,
            path: PathBuf,
        } {
            description("could not remove directory")
            display("could not remove '{}' directory: '{}'", name, path.display())
        }
        SettingPermissions {
            path: PathBuf,
        } {
            description("failed to set permissions")
            display("failed to set permissions for '{}'", path.display())
        }
        GettingCwd {
            description("couldn't get current working directory")
        }
        CargoHome {
            description("couldn't find value of CARGO_HOME")
        }
        RustupHome {
            description("couldn't find value of RUSTUP_HOME")
        }
        InvalidToolchainName(t: String) {
            description("invalid toolchain name")
            display("invalid toolchain name: '{}'", t)
        }
        InvalidCustomToolchainName(t: String) {
            description("invalid custom toolchain name")
            display("invalid custom toolchain name: '{}'", t)
        }
        ChecksumFailed {
            url: String,
            expected: String,
            calculated: String,
        } {
            description("checksum failed")
            display("checksum failed, expected: '{}', calculated: '{}'",
                    expected,
                    calculated)
        }
        ComponentConflict {
            name: String,
            path: PathBuf,
        } {
            description("conflicting component")
            display("failed to install component: '{}', detected conflict: '{:?}'",
                    name,
                    path)
        }
        ComponentMissingFile {
            name: String,
            path: PathBuf,
        } {
            description("missing file in component")
            display("failure removing component '{}', directory does not exist: '{:?}'",
                    name,
                    path)
        }
        ComponentMissingDir {
            name: String,
            path: PathBuf,
        } {
            description("missing directory in component")
            display("failure removing component '{}', directory does not exist: '{:?}'",
                    name,
                    path)
        }
        CorruptComponent(name: String) {
            description("corrupt component manifest")
            display("component manifest for '{}' is corrupt", name)
        }
        ExtractingPackage {
            description("failed to extract package (perhaps you ran out of disk space?)")
        }
        BadInstallerVersion(v: String) {
            description("unsupported installer version")
            display("unsupported installer version: {}", v)
        }
        BadInstalledMetadataVersion(v: String) {
            description("unsupported metadata version in existing installation")
            display("unsupported metadata version in existing installation: {}", v)
        }
        ComponentDirPermissionsFailed {
            description("I/O error walking directory during install")
        }
        ComponentFilePermissionsFailed {
            description("error setting file permissions during install")
        }
        ComponentDownloadFailed(c: String) {
            description("component download failed")
            display("component download failed for {}", c)
        }
        Parsing(e: toml::de::Error) {
            description("error parsing manifest")
        }
        UnsupportedVersion(v: String) {
            description("unsupported manifest version")
            display("manifest version '{}' is not supported", v)
        }
        MissingPackageForComponent(name: String) {
            description("missing package for component")
            display("server sent a broken manifest: missing package for component {}", name)
        }
        MissingPackageForRename(name: String) {
            description("missing package for the target of a rename")
            display("server sent a broken manifest: missing package for the target of a rename {}", name)
        }
        RequestedComponentsUnavailable(c: Vec<Component>, manifest: Manifest, toolchain: String) {
            description("some requested components are unavailable to download")
            display("{} for channel '{}'\n{}", component_unavailable_msg(&c, &manifest), toolchain, TOOLSTATE_MSG)
        }
        UnknownMetadataVersion(v: String) {
            description("unknown metadata version")
            display("unknown metadata version: '{}'", v)
        }
        ToolchainNotInstalled(t: String) {
            description("toolchain is not installed")
            display("toolchain '{}' is not installed", t)
        }
        OverrideToolchainNotInstalled(t: String) {
            description("override toolchain is not installed")
            display("override toolchain '{}' is not installed", t)
        }
        BinaryNotFound(bin: String, t: String, is_default: bool) {
            description("toolchain does not contain binary")
            display("'{}' is not installed for the toolchain '{}'{}", bin, t, install_msg(bin, t, *is_default))
        }
        NeedMetadataUpgrade {
            description("rustup's metadata is out of date. run `rustup self upgrade-data`")
        }
        UpgradeIoError {
            description("I/O error during upgrade")
        }
        BadInstallerType(s: String) {
            description("invalid extension for installer")
            display("invalid extension for installer: '{}'", s)
        }
        ComponentsUnsupported(t: String) {
            description("toolchain does not support components")
            display("toolchain '{}' does not support components", t)
        }
        UnknownComponent(t: String, c: String, s: Option<String>) {
            description("toolchain does not contain component")
            display("toolchain '{}' does not contain component {}{}", t, c, if let Some(suggestion) = s {
                format!("; did you mean '{}'?", suggestion)
            } else {
                "".to_string()
            })
        }
        AddingRequiredComponent(t: String, c: String) {
            description("required component cannot be added")
            display("component {} was automatically added because it is required for toolchain '{}'",
                    c, t)
        }
        ParsingSettings(e: toml::de::Error) {
            description("error parsing settings")
        }
        RemovingRequiredComponent(t: String, c: String) {
            description("required component cannot be removed")
            display("component {} is required for toolchain '{}' and cannot be removed",
                    c, t)
        }
        NoExeName {
            description("couldn't determine self executable name")
        }
    }
}

fn component_unavailable_msg(cs: &[Component], manifest: &Manifest) -> String {
    assert!(!cs.is_empty());

    let mut buf = vec![];

    if cs.len() == 1 {
        let _ = write!(
            buf,
            "component {} is unavailable for download",
            &cs[0].description(manifest)
        );
    } else {
        let same_target = cs
            .iter()
            .all(|c| c.target == cs[0].target || c.target.is_none());
        if same_target {
            let cs_str = cs
                .iter()
                .map(|c| format!("'{}'", c.short_name(manifest)))
                .collect::<Vec<_>>()
                .join(", ");
            let _ = write!(buf, "some components unavailable for download: {}", cs_str,);
        } else {
            let cs_str = cs
                .iter()
                .map(|c| c.description(manifest))
                .collect::<Vec<_>>()
                .join(", ");
            let _ = write!(buf, "some components unavailable for download: {}", cs_str,);
        }
    }

    String::from_utf8(buf).expect("")
}

fn install_msg(bin: &str, toolchain: &str, is_default: bool) -> String {
    match component_for_bin(bin) {
        Some(c) => format!("\nTo install, run `rustup component add {}{}`", c, {
            if is_default {
                String::new()
            } else {
                format!(" --toolchain {}", toolchain)
            }
        }),
        None => String::new(),
    }
}
<|endoftext|>