<commit_before>use std::ops::Deref;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::visit::FnKind;

use rustc::lint::{Context, LintArray, LintPass};
use rustc::middle::def::Def::{DefVariant, DefStruct};

use utils::{in_external_macro, snippet, span_lint};

declare_lint!(pub SHADOW_SAME, Allow,
    "rebinding a name to itself, e.g. `let mut x = &mut x`");
declare_lint!(pub SHADOW_REUSE, Allow,
    "rebinding a name to an expression that re-uses the original value, e.g. \
    `let x = x + 1`");
declare_lint!(pub SHADOW_UNRELATED, Warn,
    "The name is re-bound without even using the original value");

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

impl LintPass for ShadowPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED)
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl,
            block: &Block, _: Span, _: NodeId) {
        if in_external_macro(cx, block.span) { return; }
        check_fn(cx, decl, block);
    }
}

fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) {
    let mut bindings = Vec::new();
    for arg in &decl.inputs {
        if let PatIdent(_, ident, _) = arg.pat.node {
            bindings.push(ident.node.name)
        }
    }
    check_block(cx, block, &mut bindings);
}

fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) {
    let len = bindings.len();
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(ref decl, _) => check_decl(cx, decl, bindings),
            StmtExpr(ref e, _) | StmtSemi(ref e, _) =>
                check_expr(cx, e, bindings),
            _ => ()
        }
    }
    if let Some(ref o) = block.expr { check_expr(cx, o, bindings); }
    bindings.truncate(len);
}

fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) {
    if in_external_macro(cx, decl.span) { return; }
    if let DeclLocal(ref local) = decl.node {
        let Local{ ref pat, ref ty, ref init, id: _, span } = **local;
        if let &Some(ref t) = ty { check_ty(cx, t, bindings) }
        if let &Some(ref o) = init { check_expr(cx, o, bindings) }
        check_pat(cx, pat, init, span, bindings);
    }
}

fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span,
        bindings: &mut Vec<Name>) where T: Deref<Target=Expr> {
    //TODO: match more stuff / destructuring
    match pat.node {
        PatIdent(_, ref ident, ref inner) => {
            let name = ident.node.name;
            if pat_is_binding(&cx.tcx.def_map, pat) {
                if bindings.contains(&name) {
                    lint_shadow(cx, name, span, pat.span, init);
                }
                bindings.push(name);
            }
            if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); }
        },
        //PatEnum(Path, Option<Vec<P<Pat>>>),
        //PatQPath(QSelf, Path),
        //PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
        //PatTup(Vec<P<Pat>>),
        PatBox(ref inner) => {
            if let Some(ref initp) = *init {
                match initp.node {
                    ExprBox(_, ref inner_init) =>
                        check_pat(cx, inner, &Some(&**inner_init), span, bindings),
                    //TODO: ExprCall on Box::new
                    _ => check_pat(cx, inner, init, span, bindings),
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        //PatRegion(P<Pat>, Mutability),
        //PatRange(P<Expr>, P<Expr>),
        //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init:
        &Option<T>) where T: Deref<Target=Expr> {
    if let &Some(ref expr) = init {
        if is_self_shadow(name, expr) {
            span_lint(cx, SHADOW_SAME, span, &format!(
                "{} is shadowed by itself in {}",
                snippet(cx, lspan, "_"),
                snippet(cx, expr.span, "..")));
        } else {
            if contains_self(name, expr) {
                span_lint(cx, SHADOW_REUSE, span, &format!(
                    "{} is shadowed by {} which reuses the original value",
                    snippet(cx, lspan, "_"),
                    snippet(cx, expr.span, "..")));
            } else {
                span_lint(cx, SHADOW_UNRELATED, span, &format!(
                    "{} is shadowed by {} in this declaration",
                    snippet(cx, lspan, "_"),
                    snippet(cx, expr.span, "..")));
            }
        }
    } else {
        span_lint(cx, SHADOW_UNRELATED, span, &format!(
            "{} is shadowed in this declaration", snippet(cx, lspan, "_")));
    }
}

fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) {
    if in_external_macro(cx, expr.span) { return; }
    match expr.node {
        ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
        ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e)
            => { check_expr(cx, e, bindings) },
        ExprBox(Some(ref place), ref e) => {
            check_expr(cx, place, bindings); check_expr(cx, e, bindings) }
        ExprBlock(ref block) | ExprLoop(ref block, _) =>
            { check_block(cx, block, bindings) },
        //ExprCall
        //ExprMethodCall
        ExprVec(ref v) | ExprTup(ref v) =>
            for ref e in v { check_expr(cx, e, bindings) },
        ExprIf(ref cond, ref then, ref otherwise) => {
            check_expr(cx, cond, bindings);
            check_block(cx, then, bindings);
            if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); }
        },
        ExprWhile(ref cond, ref block, _) => {
            check_expr(cx, cond, bindings);
            check_block(cx, block, bindings);
        },
        ExprMatch(ref init, ref arms, _) => {
            check_expr(cx, init, bindings);
            for ref arm in arms {
                for ref pat in &arm.pats {
                    check_pat(cx, &pat, &Some(&**init), pat.span, bindings);
                    //TODO: This is ugly, but needed to get the right type
                }
                if let Some(ref guard) = arm.guard {
                    check_expr(cx, guard, bindings);
                }
                check_expr(cx, &arm.body, bindings);
            }
        },
        _ => ()
    }
}

fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<Name>) {
    match ty.node {
        TyParen(ref sty) | TyObjectSum(ref sty, _) |
        TyVec(ref sty) => check_ty(cx, sty, bindings),
        TyFixedLengthVec(ref fty, ref expr) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, expr, bindings);
        },
        TyPtr(MutTy{ ty: ref mty, .. }) |
        TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings),
        TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } },
        TyTypeof(ref expr) => check_expr(cx, expr, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprBox(_, ref inner) |
        ExprParen(ref inner) |
        ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
        ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().
            map_or(false, |ref e| is_self_shadow(name, e)),
        ExprUnary(op, ref inner) => (UnUniq == op || UnDeref == op) &&
            is_self_shadow(name, inner),
        ExprPath(_, ref path) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Name, path: &Path) -> bool {
    !path.global && path.segments.len() == 1 &&
        path.segments[0].identifier.name == name
}

fn contains_self(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
        ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e)
            => contains_self(name, e),
        ExprBinary(_, ref l, ref r) =>
            contains_self(name, l) || contains_self(name, r),
        ExprBlock(ref block) | ExprLoop(ref block, _) =>
            contains_block_self(name, block),
        ExprCall(ref fun, ref args) => contains_self(name, fun) ||
            args.iter().any(|ref a| contains_self(name, a)),
        ExprMethodCall(_, _, ref args) =>
            args.iter().any(|ref a| contains_self(name, a)),
        ExprVec(ref v) | ExprTup(ref v) =>
            v.iter().any(|ref e| contains_self(name, e)),
        ExprIf(ref cond, ref then, ref otherwise) =>
            contains_self(name, cond) || contains_block_self(name, then) ||
            otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)),
        ExprWhile(ref e, ref block, _)  =>
            contains_self(name, e) || contains_block_self(name, block),
        ExprMatch(ref e, ref arms, _) =>
            arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat|
                contains_pat_self(name, pat))) || contains_self(name, e),
        ExprPath(_, ref path) => path_eq_name(name, path),
        _ => false
    }
}

fn contains_block_self(name: Name, block: &Block) -> bool {
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(ref decl, _) =>
            if let DeclLocal(ref local) = decl.node {
                //TODO: We don't currently handle the case where the name
                //is shadowed wiithin the block; this means code including this
                //degenerate pattern will get the wrong warning.
                if let Some(ref init) = local.init {
                    if contains_self(name, init) { return true; }
                }
            },
            StmtExpr(ref e, _) | StmtSemi(ref e, _) =>
                if contains_self(name, e) { return true },
            _ => ()
        }
    }
    if let Some(ref e) = block.expr { contains_self(name, e) } else { false }
}

fn contains_pat_self(name: Name, pat: &Pat) -> bool {
    match pat.node {
        PatIdent(_, ref ident, ref inner) => name == ident.node.name ||
            inner.as_ref().map_or(false, |ref p| contains_pat_self(name, p)),
        PatEnum(_, ref opats) => opats.as_ref().map_or(false,
            |pats| pats.iter().any(|p| contains_pat_self(name, p))),
        PatQPath(_, ref path) => path_eq_name(name, path),
        PatStruct(_, ref fieldpats, _) => fieldpats.iter().any(
            |ref fp| contains_pat_self(name, &fp.node.pat)),
        PatTup(ref ps) => ps.iter().any(|ref p| contains_pat_self(name, p)),
        PatBox(ref p) |
        PatRegion(ref p, _) => contains_pat_self(name, p),
        PatRange(ref from, ref until) =>
            contains_self(name, from) || contains_self(name, until),
        PatVec(ref pre, ref opt, ref post) =>
            pre.iter().any(|ref p| contains_pat_self(name, p)) ||
                opt.as_ref().map_or(false, |ref p| contains_pat_self(name, p)) ||
                post.iter().any(|ref p| contains_pat_self(name, p)),
        _ => false,
    }
}
<commit_msg>fixed false positives on structs/enum variants<commit_after>use std::ops::Deref;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::visit::FnKind;

use rustc::lint::{Context, LintArray, LintPass};
use rustc::middle::def::Def::{DefVariant, DefStruct};

use utils::{in_external_macro, snippet, span_lint};

declare_lint!(pub SHADOW_SAME, Allow,
    "rebinding a name to itself, e.g. `let mut x = &mut x`");
declare_lint!(pub SHADOW_REUSE, Allow,
    "rebinding a name to an expression that re-uses the original value, e.g. \
    `let x = x + 1`");
declare_lint!(pub SHADOW_UNRELATED, Warn,
    "The name is re-bound without even using the original value");

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

impl LintPass for ShadowPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED)
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl,
            block: &Block, _: Span, _: NodeId) {
        if in_external_macro(cx, block.span) { return; }
        check_fn(cx, decl, block);
    }
}

fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) {
    let mut bindings = Vec::new();
    for arg in &decl.inputs {
        if let PatIdent(_, ident, _) = arg.pat.node {
            bindings.push(ident.node.name)
        }
    }
    check_block(cx, block, &mut bindings);
}

fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<Name>) {
    let len = bindings.len();
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(ref decl, _) => check_decl(cx, decl, bindings),
            StmtExpr(ref e, _) | StmtSemi(ref e, _) =>
                check_expr(cx, e, bindings),
            _ => ()
        }
    }
    if let Some(ref o) = block.expr { check_expr(cx, o, bindings); }
    bindings.truncate(len);
}

fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<Name>) {
    if in_external_macro(cx, decl.span) { return; }
    if let DeclLocal(ref local) = decl.node {
        let Local{ ref pat, ref ty, ref init, id: _, span } = **local;
        if let &Some(ref t) = ty { check_ty(cx, t, bindings) }
        if let &Some(ref o) = init { check_expr(cx, o, bindings) }
        check_pat(cx, pat, init, span, bindings);
    }
}

fn is_binding(cx: &Context, pat: &Pat) -> bool {
    match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
        Some(DefVariant(..)) | Some(DefStruct(..)) => false,
        _ => true
    }
}

fn check_pat<T>(cx: &Context, pat: &Pat, init: &Option<T>, span: Span,
        bindings: &mut Vec<Name>) where T: Deref<Target=Expr> {
    //TODO: match more stuff / destructuring
    match pat.node {
        PatIdent(_, ref ident, ref inner) => {
            let name = ident.node.name;
            if is_binding(cx, pat) {
                if bindings.contains(&name) {
                    lint_shadow(cx, name, span, pat.span, init);
                }
                bindings.push(name);
            }
            if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); }
        },
        //PatEnum(Path, Option<Vec<P<Pat>>>),
        //PatQPath(QSelf, Path),
        //PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
        //PatTup(Vec<P<Pat>>),
        PatBox(ref inner) => {
            if let Some(ref initp) = *init {
                match initp.node {
                    ExprBox(_, ref inner_init) =>
                        check_pat(cx, inner, &Some(&**inner_init), span, bindings),
                    //TODO: ExprCall on Box::new
                    _ => check_pat(cx, inner, init, span, bindings),
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        //PatRegion(P<Pat>, Mutability),
        //PatRange(P<Expr>, P<Expr>),
        //PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init:
        &Option<T>) where T: Deref<Target=Expr> {
    if let &Some(ref expr) = init {
        if is_self_shadow(name, expr) {
            span_lint(cx, SHADOW_SAME, span, &format!(
                "{} is shadowed by itself in {}",
                snippet(cx, lspan, "_"),
                snippet(cx, expr.span, "..")));
        } else {
            if contains_self(name, expr) {
                span_lint(cx, SHADOW_REUSE, span, &format!(
                    "{} is shadowed by {} which reuses the original value",
                    snippet(cx, lspan, "_"),
                    snippet(cx, expr.span, "..")));
            } else {
                span_lint(cx, SHADOW_UNRELATED, span, &format!(
                    "{} is shadowed by {} in this declaration",
                    snippet(cx, lspan, "_"),
                    snippet(cx, expr.span, "..")));
            }
        }
    } else {
        span_lint(cx, SHADOW_UNRELATED, span, &format!(
            "{} is shadowed in this declaration", snippet(cx, lspan, "_")));
    }
}

fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<Name>) {
    if in_external_macro(cx, expr.span) { return; }
    match expr.node {
        ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
        ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e)
            => { check_expr(cx, e, bindings) },
        ExprBox(Some(ref place), ref e) => {
            check_expr(cx, place, bindings); check_expr(cx, e, bindings) }
        ExprBlock(ref block) | ExprLoop(ref block, _) =>
            { check_block(cx, block, bindings) },
        //ExprCall
        //ExprMethodCall
        ExprVec(ref v) | ExprTup(ref v) =>
            for ref e in v { check_expr(cx, e, bindings) },
        ExprIf(ref cond, ref then, ref otherwise) => {
            check_expr(cx, cond, bindings);
            check_block(cx, then, bindings);
            if let &Some(ref o) = otherwise { check_expr(cx, o, bindings); }
        },
        ExprWhile(ref cond, ref block, _) => {
            check_expr(cx, cond, bindings);
            check_block(cx, block, bindings);
        },
        ExprMatch(ref init, ref arms, _) => {
            check_expr(cx, init, bindings);
            for ref arm in arms {
                for ref pat in &arm.pats {
                    check_pat(cx, &pat, &Some(&**init), pat.span, bindings);
                    //TODO: This is ugly, but needed to get the right type
                }
                if let Some(ref guard) = arm.guard {
                    check_expr(cx, guard, bindings);
                }
                check_expr(cx, &arm.body, bindings);
            }
        },
        _ => ()
    }
}

fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<Name>) {
    match ty.node {
        TyParen(ref sty) | TyObjectSum(ref sty, _) |
        TyVec(ref sty) => check_ty(cx, sty, bindings),
        TyFixedLengthVec(ref fty, ref expr) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, expr, bindings);
        },
        TyPtr(MutTy{ ty: ref mty, .. }) |
        TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings),
        TyTup(ref tup) => { for ref t in tup { check_ty(cx, t, bindings) } },
        TyTypeof(ref expr) => check_expr(cx, expr, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprBox(_, ref inner) |
        ExprParen(ref inner) |
        ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
        ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().
            map_or(false, |ref e| is_self_shadow(name, e)),
        ExprUnary(op, ref inner) => (UnUniq == op || UnDeref == op) &&
            is_self_shadow(name, inner),
        ExprPath(_, ref path) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Name, path: &Path) -> bool {
    !path.global && path.segments.len() == 1 &&
        path.segments[0].identifier.name == name
}

fn contains_self(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
        ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e)
            => contains_self(name, e),
        ExprBinary(_, ref l, ref r) =>
            contains_self(name, l) || contains_self(name, r),
        ExprBlock(ref block) | ExprLoop(ref block, _) =>
            contains_block_self(name, block),
        ExprCall(ref fun, ref args) => contains_self(name, fun) ||
            args.iter().any(|ref a| contains_self(name, a)),
        ExprMethodCall(_, _, ref args) =>
            args.iter().any(|ref a| contains_self(name, a)),
        ExprVec(ref v) | ExprTup(ref v) =>
            v.iter().any(|ref e| contains_self(name, e)),
        ExprIf(ref cond, ref then, ref otherwise) =>
            contains_self(name, cond) || contains_block_self(name, then) ||
            otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)),
        ExprWhile(ref e, ref block, _)  =>
            contains_self(name, e) || contains_block_self(name, block),
        ExprMatch(ref e, ref arms, _) =>
            arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat|
                contains_pat_self(name, pat))) || contains_self(name, e),
        ExprPath(_, ref path) => path_eq_name(name, path),
        _ => false
    }
}

fn contains_block_self(name: Name, block: &Block) -> bool {
    for stmt in &block.stmts {
        match stmt.node {
            StmtDecl(ref decl, _) =>
            if let DeclLocal(ref local) = decl.node {
                //TODO: We don't currently handle the case where the name
                //is shadowed wiithin the block; this means code including this
                //degenerate pattern will get the wrong warning.
                if let Some(ref init) = local.init {
                    if contains_self(name, init) { return true; }
                }
            },
            StmtExpr(ref e, _) | StmtSemi(ref e, _) =>
                if contains_self(name, e) { return true },
            _ => ()
        }
    }
    if let Some(ref e) = block.expr { contains_self(name, e) } else { false }
}

fn contains_pat_self(name: Name, pat: &Pat) -> bool {
    match pat.node {
        PatIdent(_, ref ident, ref inner) => name == ident.node.name ||
            inner.as_ref().map_or(false, |ref p| contains_pat_self(name, p)),
        PatEnum(_, ref opats) => opats.as_ref().map_or(false,
            |pats| pats.iter().any(|p| contains_pat_self(name, p))),
        PatQPath(_, ref path) => path_eq_name(name, path),
        PatStruct(_, ref fieldpats, _) => fieldpats.iter().any(
            |ref fp| contains_pat_self(name, &fp.node.pat)),
        PatTup(ref ps) => ps.iter().any(|ref p| contains_pat_self(name, p)),
        PatBox(ref p) |
        PatRegion(ref p, _) => contains_pat_self(name, p),
        PatRange(ref from, ref until) =>
            contains_self(name, from) || contains_self(name, until),
        PatVec(ref pre, ref opt, ref post) =>
            pre.iter().any(|ref p| contains_pat_self(name, p)) ||
                opt.as_ref().map_or(false, |ref p| contains_pat_self(name, p)) ||
                post.iter().any(|ref p| contains_pat_self(name, p)),
        _ => false,
    }
}
<|endoftext|>


<commit_before>//! This crate aims to provide a common set of tools that can be used to create a "environment" to
//! run Lighthouse services like the `beacon_node` or `validator_client`. This allows for the
//! unification of creating tokio runtimes, loggers and eth2 specifications in production and in
//! testing.
//!
//! The idea is that the main thread creates an `Environment`, which is then used to spawn a
//! `Context` which can be handed to any service that wishes to start async tasks or perform
//! logging.

use eth2_config::Eth2Config;
use futures::{sync::oneshot, Future};
use slog::{info, o, Drain, Level, Logger};
use sloggers::{null::NullLoggerBuilder, Build};
use std::cell::RefCell;
use std::fs::OpenOptions;
use std::path::PathBuf;
use std::sync::Mutex;
use tokio::runtime::{Builder as RuntimeBuilder, Runtime, TaskExecutor};
use types::{EthSpec, InteropEthSpec, MainnetEthSpec, MinimalEthSpec};

/// Builds an `Environment`.
pub struct EnvironmentBuilder<E: EthSpec> {
    runtime: Option<Runtime>,
    log: Option<Logger>,
    eth_spec_instance: E,
    eth2_config: Eth2Config,
}

impl EnvironmentBuilder<MinimalEthSpec> {
    /// Creates a new builder using the `minimal` eth2 specification.
    pub fn minimal() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: MinimalEthSpec,
            eth2_config: Eth2Config::minimal(),
        }
    }
}

impl EnvironmentBuilder<MainnetEthSpec> {
    /// Creates a new builder using the `mainnet` eth2 specification.
    pub fn mainnet() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: MainnetEthSpec,
            eth2_config: Eth2Config::mainnet(),
        }
    }
}

impl EnvironmentBuilder<InteropEthSpec> {
    /// Creates a new builder using the `interop` eth2 specification.
    pub fn interop() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: InteropEthSpec,
            eth2_config: Eth2Config::interop(),
        }
    }
}

impl<E: EthSpec> EnvironmentBuilder<E> {
    /// Specifies that a multi-threaded tokio runtime should be used. Ideal for production uses.
    ///
    /// The `Runtime` used is just the standard tokio runtime.
    pub fn multi_threaded_tokio_runtime(mut self) -> Result<Self, String> {
        self.runtime =
            Some(Runtime::new().map_err(|e| format!("Failed to start runtime: {:?}", e))?);
        Ok(self)
    }

    /// Specifies that a single-threaded tokio runtime should be used. Ideal for testing purposes
    /// where tests are already multi-threaded.
    ///
    /// This can solve problems if "too many open files" errors are thrown during tests.
    pub fn single_thread_tokio_runtime(mut self) -> Result<Self, String> {
        self.runtime = Some(
            RuntimeBuilder::new()
                .core_threads(1)
                .build()
                .map_err(|e| format!("Failed to start runtime: {:?}", e))?,
        );
        Ok(self)
    }

    /// Specifies that all logs should be sent to `null` (i.e., ignored).
    pub fn null_logger(mut self) -> Result<Self, String> {
        self.log = Some(null_logger()?);
        Ok(self)
    }

    /// Specifies that the `slog` asynchronous logger should be used. Ideal for production.
    ///
    /// The logger is "async" because it has a dedicated thread that accepts logs and then
    /// asynchronously flushes them to stdout/files/etc. This means the thread that raised the log
    /// does not have to wait for the logs to be flushed.
    pub fn async_logger(mut self, debug_level: &str) -> Result<Self, String> {
        // Build the initial logger.
        let decorator = slog_term::TermDecorator::new().build();
        let decorator = logging::AlignedTermDecorator::new(decorator, logging::MAX_MESSAGE_WIDTH);
        let drain = slog_term::FullFormat::new(decorator).build().fuse();
        let drain = slog_async::Async::new(drain).build();

        let drain = match debug_level {
            "info" => drain.filter_level(Level::Info),
            "debug" => drain.filter_level(Level::Debug),
            "trace" => drain.filter_level(Level::Trace),
            "warn" => drain.filter_level(Level::Warning),
            "error" => drain.filter_level(Level::Error),
            "crit" => drain.filter_level(Level::Critical),
            unknown => return Err(format!("Unknown debug-level: {}", unknown)),
        };

        self.log = Some(Logger::root(drain.fuse(), o!()));
        Ok(self)
    }

    /// Consumes the builder, returning an `Environment`.
    pub fn build(self) -> Result<Environment<E>, String> {
        Ok(Environment {
            runtime: self
                .runtime
                .ok_or_else(|| "Cannot build environment without runtime".to_string())?,
            log: self
                .log
                .ok_or_else(|| "Cannot build environment without log".to_string())?,
            eth_spec_instance: self.eth_spec_instance,
            eth2_config: self.eth2_config,
        })
    }
}

/// An execution context that can be used by a service.
///
/// Distinct from an `Environment` because a `Context` is not able to give a mutable reference to a
/// `Runtime`, instead it only has access to a `TaskExecutor`.
#[derive(Clone)]
pub struct RuntimeContext<E: EthSpec> {
    pub executor: TaskExecutor,
    pub log: Logger,
    pub eth_spec_instance: E,
    pub eth2_config: Eth2Config,
}

impl<E: EthSpec> RuntimeContext<E> {
    /// Returns a sub-context of this context.
    ///
    /// The generated service will have the `service_name` in all it's logs.
    pub fn service_context(&self, service_name: String) -> Self {
        Self {
            executor: self.executor.clone(),
            log: self.log.new(o!("service" => service_name)),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Returns the `eth2_config` for this service.
    pub fn eth2_config(&self) -> &Eth2Config {
        &self.eth2_config
    }
}

/// An environment where Lighthouse services can run. Used to start a production beacon node or
/// validator client, or to run tests that involve logging and async task execution.
pub struct Environment<E: EthSpec> {
    runtime: Runtime,
    log: Logger,
    eth_spec_instance: E,
    pub eth2_config: Eth2Config,
}

impl<E: EthSpec> Environment<E> {
    /// Returns a mutable reference to the `tokio` runtime.
    ///
    /// Useful in the rare scenarios where it's necessary to block the current thread until a task
    /// is finished (e.g., during testing).
    pub fn runtime(&mut self) -> &mut Runtime {
        &mut self.runtime
    }

    /// Returns a `Context` where no "service" has been added to the logger output.
    pub fn core_context(&mut self) -> RuntimeContext<E> {
        RuntimeContext {
            executor: self.runtime.executor(),
            log: self.log.clone(),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Returns a `Context` where the `service_name` is added to the logger output.
    pub fn service_context(&mut self, service_name: String) -> RuntimeContext<E> {
        RuntimeContext {
            executor: self.runtime.executor(),
            log: self.log.new(o!("service" => service_name)),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Block the current thread until Ctrl+C is received.
    pub fn block_until_ctrl_c(&mut self) -> Result<(), String> {
        let (ctrlc_send, ctrlc_oneshot) = oneshot::channel();
        let ctrlc_send_c = RefCell::new(Some(ctrlc_send));
        ctrlc::set_handler(move || {
            if let Some(ctrlc_send) = ctrlc_send_c.try_borrow_mut().unwrap().take() {
                ctrlc_send.send(()).expect("Error sending ctrl-c message");
            }
        })
        .map_err(|e| format!("Could not set ctrlc handler: {:?}", e))?;

        // Block this thread until Crtl+C is pressed.
        self.runtime()
            .block_on(ctrlc_oneshot)
            .map_err(|e| format!("Ctrlc oneshot failed: {:?}", e))
    }

    /// Shutdown the `tokio` runtime when all tasks are idle.
    pub fn shutdown_on_idle(self) -> Result<(), String> {
        self.runtime
            .shutdown_on_idle()
            .wait()
            .map_err(|e| format!("Tokio runtime shutdown returned an error: {:?}", e))
    }

    /// Sets the logger (and all child loggers) to log to a file.
    pub fn log_to_json_file(&mut self, path: PathBuf, debug_level: &str) -> Result<(), String> {
        let file = OpenOptions::new()
            .create(true)
            .write(true)
            .truncate(true)
            .open(&path)
            .map_err(|e| format!("Unable to open logfile: {:?}", e))?;

        let drain = Mutex::new(slog_json::Json::default(file)).fuse();
        let drain = slog_async::Async::new(drain).build();

        let drain = match debug_level {
            "info" => drain.filter_level(Level::Info),
            "debug" => drain.filter_level(Level::Debug),
            "trace" => drain.filter_level(Level::Trace),
            "warn" => drain.filter_level(Level::Warning),
            "error" => drain.filter_level(Level::Error),
            "crit" => drain.filter_level(Level::Critical),
            unknown => return Err(format!("Unknown debug-level: {}", unknown)),
        };

        self.log = Logger::root(drain.fuse(), o!());

        info!(
            self.log,
            "Logging to JSON file";
            "path" => format!("{:?}", path)
        );

        Ok(())
    }

    pub fn eth_spec_instance(&self) -> &E {
        &self.eth_spec_instance
    }

    pub fn eth2_config(&self) -> &Eth2Config {
        &self.eth2_config
    }
}

pub fn null_logger() -> Result<Logger, String> {
    let log_builder = NullLoggerBuilder;
    log_builder
        .build()
        .map_err(|e| format!("Failed to start null logger: {:?}", e))
}
<commit_msg>Create backup instead of overwriting log files (#686)<commit_after>//! This crate aims to provide a common set of tools that can be used to create a "environment" to
//! run Lighthouse services like the `beacon_node` or `validator_client`. This allows for the
//! unification of creating tokio runtimes, loggers and eth2 specifications in production and in
//! testing.
//!
//! The idea is that the main thread creates an `Environment`, which is then used to spawn a
//! `Context` which can be handed to any service that wishes to start async tasks or perform
//! logging.

use eth2_config::Eth2Config;
use futures::{sync::oneshot, Future};
use slog::{info, o, Drain, Level, Logger};
use sloggers::{null::NullLoggerBuilder, Build};
use std::cell::RefCell;
use std::ffi::OsStr;
use std::fs::{rename as FsRename, OpenOptions};
use std::path::PathBuf;
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::runtime::{Builder as RuntimeBuilder, Runtime, TaskExecutor};
use types::{EthSpec, InteropEthSpec, MainnetEthSpec, MinimalEthSpec};

/// Builds an `Environment`.
pub struct EnvironmentBuilder<E: EthSpec> {
    runtime: Option<Runtime>,
    log: Option<Logger>,
    eth_spec_instance: E,
    eth2_config: Eth2Config,
}

impl EnvironmentBuilder<MinimalEthSpec> {
    /// Creates a new builder using the `minimal` eth2 specification.
    pub fn minimal() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: MinimalEthSpec,
            eth2_config: Eth2Config::minimal(),
        }
    }
}

impl EnvironmentBuilder<MainnetEthSpec> {
    /// Creates a new builder using the `mainnet` eth2 specification.
    pub fn mainnet() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: MainnetEthSpec,
            eth2_config: Eth2Config::mainnet(),
        }
    }
}

impl EnvironmentBuilder<InteropEthSpec> {
    /// Creates a new builder using the `interop` eth2 specification.
    pub fn interop() -> Self {
        Self {
            runtime: None,
            log: None,
            eth_spec_instance: InteropEthSpec,
            eth2_config: Eth2Config::interop(),
        }
    }
}

impl<E: EthSpec> EnvironmentBuilder<E> {
    /// Specifies that a multi-threaded tokio runtime should be used. Ideal for production uses.
    ///
    /// The `Runtime` used is just the standard tokio runtime.
    pub fn multi_threaded_tokio_runtime(mut self) -> Result<Self, String> {
        self.runtime =
            Some(Runtime::new().map_err(|e| format!("Failed to start runtime: {:?}", e))?);
        Ok(self)
    }

    /// Specifies that a single-threaded tokio runtime should be used. Ideal for testing purposes
    /// where tests are already multi-threaded.
    ///
    /// This can solve problems if "too many open files" errors are thrown during tests.
    pub fn single_thread_tokio_runtime(mut self) -> Result<Self, String> {
        self.runtime = Some(
            RuntimeBuilder::new()
                .core_threads(1)
                .build()
                .map_err(|e| format!("Failed to start runtime: {:?}", e))?,
        );
        Ok(self)
    }

    /// Specifies that all logs should be sent to `null` (i.e., ignored).
    pub fn null_logger(mut self) -> Result<Self, String> {
        self.log = Some(null_logger()?);
        Ok(self)
    }

    /// Specifies that the `slog` asynchronous logger should be used. Ideal for production.
    ///
    /// The logger is "async" because it has a dedicated thread that accepts logs and then
    /// asynchronously flushes them to stdout/files/etc. This means the thread that raised the log
    /// does not have to wait for the logs to be flushed.
    pub fn async_logger(mut self, debug_level: &str) -> Result<Self, String> {
        // Build the initial logger.
        let decorator = slog_term::TermDecorator::new().build();
        let decorator = logging::AlignedTermDecorator::new(decorator, logging::MAX_MESSAGE_WIDTH);
        let drain = slog_term::FullFormat::new(decorator).build().fuse();
        let drain = slog_async::Async::new(drain).build();

        let drain = match debug_level {
            "info" => drain.filter_level(Level::Info),
            "debug" => drain.filter_level(Level::Debug),
            "trace" => drain.filter_level(Level::Trace),
            "warn" => drain.filter_level(Level::Warning),
            "error" => drain.filter_level(Level::Error),
            "crit" => drain.filter_level(Level::Critical),
            unknown => return Err(format!("Unknown debug-level: {}", unknown)),
        };

        self.log = Some(Logger::root(drain.fuse(), o!()));
        Ok(self)
    }

    /// Consumes the builder, returning an `Environment`.
    pub fn build(self) -> Result<Environment<E>, String> {
        Ok(Environment {
            runtime: self
                .runtime
                .ok_or_else(|| "Cannot build environment without runtime".to_string())?,
            log: self
                .log
                .ok_or_else(|| "Cannot build environment without log".to_string())?,
            eth_spec_instance: self.eth_spec_instance,
            eth2_config: self.eth2_config,
        })
    }
}

/// An execution context that can be used by a service.
///
/// Distinct from an `Environment` because a `Context` is not able to give a mutable reference to a
/// `Runtime`, instead it only has access to a `TaskExecutor`.
#[derive(Clone)]
pub struct RuntimeContext<E: EthSpec> {
    pub executor: TaskExecutor,
    pub log: Logger,
    pub eth_spec_instance: E,
    pub eth2_config: Eth2Config,
}

impl<E: EthSpec> RuntimeContext<E> {
    /// Returns a sub-context of this context.
    ///
    /// The generated service will have the `service_name` in all it's logs.
    pub fn service_context(&self, service_name: String) -> Self {
        Self {
            executor: self.executor.clone(),
            log: self.log.new(o!("service" => service_name)),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Returns the `eth2_config` for this service.
    pub fn eth2_config(&self) -> &Eth2Config {
        &self.eth2_config
    }
}

/// An environment where Lighthouse services can run. Used to start a production beacon node or
/// validator client, or to run tests that involve logging and async task execution.
pub struct Environment<E: EthSpec> {
    runtime: Runtime,
    log: Logger,
    eth_spec_instance: E,
    pub eth2_config: Eth2Config,
}

impl<E: EthSpec> Environment<E> {
    /// Returns a mutable reference to the `tokio` runtime.
    ///
    /// Useful in the rare scenarios where it's necessary to block the current thread until a task
    /// is finished (e.g., during testing).
    pub fn runtime(&mut self) -> &mut Runtime {
        &mut self.runtime
    }

    /// Returns a `Context` where no "service" has been added to the logger output.
    pub fn core_context(&mut self) -> RuntimeContext<E> {
        RuntimeContext {
            executor: self.runtime.executor(),
            log: self.log.clone(),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Returns a `Context` where the `service_name` is added to the logger output.
    pub fn service_context(&mut self, service_name: String) -> RuntimeContext<E> {
        RuntimeContext {
            executor: self.runtime.executor(),
            log: self.log.new(o!("service" => service_name)),
            eth_spec_instance: self.eth_spec_instance.clone(),
            eth2_config: self.eth2_config.clone(),
        }
    }

    /// Block the current thread until Ctrl+C is received.
    pub fn block_until_ctrl_c(&mut self) -> Result<(), String> {
        let (ctrlc_send, ctrlc_oneshot) = oneshot::channel();
        let ctrlc_send_c = RefCell::new(Some(ctrlc_send));
        ctrlc::set_handler(move || {
            if let Some(ctrlc_send) = ctrlc_send_c.try_borrow_mut().unwrap().take() {
                ctrlc_send.send(()).expect("Error sending ctrl-c message");
            }
        })
        .map_err(|e| format!("Could not set ctrlc handler: {:?}", e))?;

        // Block this thread until Crtl+C is pressed.
        self.runtime()
            .block_on(ctrlc_oneshot)
            .map_err(|e| format!("Ctrlc oneshot failed: {:?}", e))
    }

    /// Shutdown the `tokio` runtime when all tasks are idle.
    pub fn shutdown_on_idle(self) -> Result<(), String> {
        self.runtime
            .shutdown_on_idle()
            .wait()
            .map_err(|e| format!("Tokio runtime shutdown returned an error: {:?}", e))
    }

    /// Sets the logger (and all child loggers) to log to a file.
    pub fn log_to_json_file(&mut self, path: PathBuf, debug_level: &str) -> Result<(), String> {
        // Creating a backup if the logfile already exists.
        if path.exists() {
            let start = SystemTime::now();
            let timestamp = start
                .duration_since(UNIX_EPOCH)
                .map_err(|e| e.to_string())?
                .as_secs();
            let file_stem = path
                .file_stem()
                .ok_or_else(|| "Invalid file name".to_string())?
                .to_str()
                .ok_or_else(|| "Failed to create str from filename".to_string())?;
            let file_ext = path.extension().unwrap_or_else(|| OsStr::new(""));
            let backup_name = format!("{}_backup_{}", file_stem, timestamp);
            let backup_path = path.with_file_name(backup_name).with_extension(file_ext);
            FsRename(&path, &backup_path).map_err(|e| e.to_string())?;
        }

        let file = OpenOptions::new()
            .create(true)
            .write(true)
            .truncate(true)
            .open(&path)
            .map_err(|e| format!("Unable to open logfile: {:?}", e))?;

        let drain = Mutex::new(slog_json::Json::default(file)).fuse();
        let drain = slog_async::Async::new(drain).build();

        let drain = match debug_level {
            "info" => drain.filter_level(Level::Info),
            "debug" => drain.filter_level(Level::Debug),
            "trace" => drain.filter_level(Level::Trace),
            "warn" => drain.filter_level(Level::Warning),
            "error" => drain.filter_level(Level::Error),
            "crit" => drain.filter_level(Level::Critical),
            unknown => return Err(format!("Unknown debug-level: {}", unknown)),
        };

        self.log = Logger::root(drain.fuse(), o!());

        info!(
            self.log,
            "Logging to JSON file";
            "path" => format!("{:?}", path)
        );

        Ok(())
    }

    pub fn eth_spec_instance(&self) -> &E {
        &self.eth_spec_instance
    }

    pub fn eth2_config(&self) -> &Eth2Config {
        &self.eth2_config
    }
}

pub fn null_logger() -> Result<Logger, String> {
    let log_builder = NullLoggerBuilder;
    log_builder
        .build()
        .map_err(|e| format!("Failed to start null logger: {:?}", e))
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// 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
// http://mozilla.org/MPL/2.0/.

use std::mem;
use std::os::unix::io::{RawFd, AsRawFd};
use std::io::{Read, Write, Error, ErrorKind};

use libc;
use errno::errno;
use libc::{c_int, c_void};

use stream::StreamShutdown;

/// The `TcpOptions` trait allows for various TCP setting used in syscalls
/// throughout Unix-like kernels.
pub trait TcpOptions {
    /// Sets the `SO_KEEPALIVE` flag to `keepalive` on this socket.
    fn set_tcp_keepalive(&mut self, keepalive: bool) -> Result<(), Error>;
    /// Sets the `TCP_NODELAY` flag to `nodelay` on this socket.
    fn set_tcp_nodelay(&mut self, nodelay: bool) -> Result<(), Error>;
}

#[derive(Clone, Eq, PartialEq)]
pub struct Socket {
    fd: RawFd,
}

impl Socket {
    /// Creates a new socket, with ownership of the `RawFd`
    pub fn new(fd: RawFd) -> Socket {
        Socket {
            fd: fd
        }
    }
}

impl TcpOptions for Socket {
    fn set_tcp_keepalive(&mut self, keepalive: bool) -> Result<(), Error> {
        let optval: c_int = match keepalive {
            true => 1,
            false => 0
        };
        let opt_result = unsafe {
            libc::setsockopt(self.fd,
                             libc::SOL_SOCKET,
                             libc::SO_KEEPALIVE,
                             &optval as *const _ as *const c_void,
                             mem::size_of::<c_int>() as u32)
        };
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }

    fn set_tcp_nodelay(&mut self, nodelay: bool) -> Result<(), Error> {
        const SOL_TCP: c_int = 6;

        let optval: c_int = match nodelay {
            true => 1,
            false => 0
        };
        let opt_result = unsafe {
            libc::setsockopt(self.fd,
                             SOL_TCP,
                             libc::TCP_NODELAY,
                             &optval as *const _ as *const c_void,
                             mem::size_of::<c_int>() as u32)
        };
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if buf.len() < 1 {
            return Err(Error::new(ErrorKind::Other, "Invalid buffer"));
        }

        let result = unsafe { libc::read(self.fd, buf as *mut _ as *mut c_void, buf.len()) };

        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        if result == 0 {
            return Err(Error::new(ErrorKind::Other, "EOF"));
        }

        Ok(result as usize)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        let result = unsafe {
            libc::write(self.fd, buf as *const _ as *const c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(result as usize)
    }

    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

impl StreamShutdown for Socket {
    fn shutdown(&self) -> Result<(), Error> {
        let result = unsafe {
            libc::close(self.fd)
        };
        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }
}

impl AsRawFd for Socket {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}
<commit_msg>Socket docs<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// 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
// http://mozilla.org/MPL/2.0/.

use std::mem;
use std::os::unix::io::{RawFd, AsRawFd};
use std::io::{Read, Write, Error, ErrorKind};

use libc;
use errno::errno;
use libc::{c_int, c_void};

use stream::StreamShutdown;

/// The `TcpOptions` trait allows for various TCP setting used in syscalls
/// throughout Unix-like kernels.
pub trait TcpOptions {
    /// Sets the `SO_KEEPALIVE` flag to `keepalive` on this socket.
    fn set_tcp_keepalive(&mut self, keepalive: bool) -> Result<(), Error>;
    /// Sets the `TCP_NODELAY` flag to `nodelay` on this socket.
    fn set_tcp_nodelay(&mut self, nodelay: bool) -> Result<(), Error>;
}

#[derive(Clone, Eq, PartialEq)]
pub struct Socket {
    fd: RawFd,
}

impl Socket {
    /// Creates a new socket with assumed ownership of `fd`
    pub fn new(fd: RawFd) -> Socket {
        Socket {
            fd: fd
        }
    }
}

impl TcpOptions for Socket {
    fn set_tcp_keepalive(&mut self, keepalive: bool) -> Result<(), Error> {
        let optval: c_int = match keepalive {
            true => 1,
            false => 0
        };
        let opt_result = unsafe {
            libc::setsockopt(self.fd,
                             libc::SOL_SOCKET,
                             libc::SO_KEEPALIVE,
                             &optval as *const _ as *const c_void,
                             mem::size_of::<c_int>() as u32)
        };
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }

    fn set_tcp_nodelay(&mut self, nodelay: bool) -> Result<(), Error> {
        const SOL_TCP: c_int = 6;

        let optval: c_int = match nodelay {
            true => 1,
            false => 0
        };
        let opt_result = unsafe {
            libc::setsockopt(self.fd,
                             SOL_TCP,
                             libc::TCP_NODELAY,
                             &optval as *const _ as *const c_void,
                             mem::size_of::<c_int>() as u32)
        };
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if buf.len() < 1 {
            return Err(Error::new(ErrorKind::Other, "Invalid buffer"));
        }

        let result = unsafe { libc::read(self.fd, buf as *mut _ as *mut c_void, buf.len()) };

        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        if result == 0 {
            return Err(Error::new(ErrorKind::Other, "EOF"));
        }

        Ok(result as usize)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        let result = unsafe {
            libc::write(self.fd, buf as *const _ as *const c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(result as usize)
    }

    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

impl StreamShutdown for Socket {
    fn shutdown(&self) -> Result<(), Error> {
        let result = unsafe {
            libc::close(self.fd)
        };
        if result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }

        Ok(())
    }
}

impl AsRawFd for Socket {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Jeff Belgum
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without
// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

extern crate rand;
extern crate num;

use num::{Float,
          Num,
          NumCast,
          One,
          Zero};

pub enum Degree {
    One,
    Two,
    Three,
    Four
}

pub fn std_moment<T>(v: &[T], r: Degree, _mean: Option<T>, pstdev: Option<T>) -> T
    where T: Float
{
    let _mean = _mean.unwrap_or_else(|| mean(v));
    let pstdev = pstdev.unwrap_or_else(|| population_standard_deviation(v, Some(_mean)));
    let r = match r {
        Degree::One => 1,
        Degree::Two => 2,
        Degree::Three => 3,
        Degree::Four => 4
    };
    v.iter().map(|&x| ((x-_mean)/pstdev).powi(r)).fold(T::zero(), |acc, elem| acc + elem)
}

/// The mean is the sum of a collection of numbers divided by the number of numbers in the collection.
/// (reference)[http://en.wikipedia.org/wiki/Arithmetic_mean]
pub fn mean<T>(v: &[T]) -> T
    where T: Float
{
    let len = num::cast(v.len()).unwrap();
    v.iter().fold(T::zero(), |acc: T, elem| acc + *elem) / len
}

/// The median is the number separating the higher half of a data sample, a population, or
/// a probability distribution, from the lower half (reference)[http://en.wikipedia.org/wiki/Median)
pub fn median<T>(v: &[T]) -> T
    where T: Copy + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch: Vec<&T> = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / num::cast(2).unwrap()
    }
}

pub fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Float
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(T::zero(), |acc, elem| acc + elem);
    assert!(sum >= T::zero(), "negative sum of square root deviations");
    sum
}

/// (Sample variance)[http://en.wikipedia.org/wiki/Variance#Sample_variance]
pub fn variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float
{
    assert!(v.len() > 1, "variance requires at least two data points");
    let len: T = num::cast(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - T::one())
}

/// (Population variance)[http://en.wikipedia.org/wiki/Variance#Population_variance]
pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Float
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = num::cast(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

///  Standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float
{
    let var = variance(v, xbar);
    var.sqrt()
}

///  Population standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

/// Standard score is a given datum's (signed) number of standard deviations above the mean.
/// (reference)[http://en.wikipedia.org/wiki/Standard_score]
/// Method returns a vector of scores for a vector of inputs. scores[n] is the score of v[n]
pub fn standard_scores<T>(v: &[T]) -> Vec<T>
    where T: Float
{
    let mean = mean(&v);
    let standard_deviation = standard_deviation(&v, None);
    let scores: Vec<T> = v.iter().map(|val| (*val - mean)/standard_deviation).collect();
    return scores;
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T])
    where T: Copy
{
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize
    where T: PartialOrd + Copy
{
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

pub fn quicksort<T>(v: &mut [T])
    where T: PartialOrd + Copy
{
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        assert_eq!(mean(&vec), 1.375);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        assert_eq!(median(&vec), 2.0);
        let vec = vec![1.0, 3.0, 5.0];
        assert_eq!(median(&vec), 3.0);
        let vec = vec![1.0, 3.0, 5.0, 7.0];
        assert_eq!(median(&vec), 4.0);
    }

    #[test]
    fn test_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;
        let epsilon = 1e-6;
        assert!((expected - variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;
        let epsilon = 1e-6;
        assert!((expected - population_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;
        let epsilon = 1e-6;
        assert!((expected - standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;
        let epsilon = 1e-6;
        assert!((expected - population_standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_scores() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        let expected = vec![-1.150407536484354, -0.941242529850835, -0.941242529850835, -0.10458250331675945, 0.10458250331675945, 0.31374750995027834, 1.150407536484354, 1.5687375497513918];
        assert!(expected == standard_scores(&v));
    }

    #[test]
    fn test_qsort_empty() {
        let mut vec: Vec<f64> = vec![];
        quicksort(&mut vec);
        assert_eq!(vec, vec![]);
    }

    #[test]
    fn test_qsort_small() {
        let len = 10;
        let mut vec = Vec::with_capacity(len);
        for _ in 0..len { vec.push(rand::random::<f64>()); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_large() {
        let len = 1_000_000;
        let mut vec = Vec::with_capacity(len);
        for _ in 0..len { vec.push(rand::random::<f64>()); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_sorted() {
        let len = 1_000;
        let mut vec = Vec::with_capacity(len);
        for n in 0..len { vec.push(n); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_reverse_sorted() {
        let len = 1_000;
        let mut vec = Vec::with_capacity(len);
        for n in 0..len { vec.push(len-n); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

}
<commit_msg>updated tests to compare if expected value is within an epsilon instead of equality<commit_after>// Copyright (c) 2015 Jeff Belgum
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without
// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

extern crate rand;
extern crate num;

use num::{Float,
          Num,
          NumCast,
          One,
          Zero};

pub enum Degree {
    One,
    Two,
    Three,
    Four
}

pub fn std_moment<T>(v: &[T], r: Degree, _mean: Option<T>, pstdev: Option<T>) -> T
    where T: Float
{
    let _mean = _mean.unwrap_or_else(|| mean(v));
    let pstdev = pstdev.unwrap_or_else(|| population_standard_deviation(v, Some(_mean)));
    let r = match r {
        Degree::One => 1,
        Degree::Two => 2,
        Degree::Three => 3,
        Degree::Four => 4
    };
    v.iter().map(|&x| ((x-_mean)/pstdev).powi(r)).fold(T::zero(), |acc, elem| acc + elem)
}

/// The mean is the sum of a collection of numbers divided by the number of numbers in the collection.
/// (reference)[http://en.wikipedia.org/wiki/Arithmetic_mean]
pub fn mean<T>(v: &[T]) -> T
    where T: Float
{
    let len = num::cast(v.len()).unwrap();
    v.iter().fold(T::zero(), |acc: T, elem| acc + *elem) / len
}

/// The median is the number separating the higher half of a data sample, a population, or
/// a probability distribution, from the lower half (reference)[http://en.wikipedia.org/wiki/Median)
pub fn median<T>(v: &[T]) -> T
    where T: Copy + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch: Vec<&T> = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / num::cast(2).unwrap()
    }
}

pub fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Float
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(T::zero(), |acc, elem| acc + elem);
    assert!(sum >= T::zero(), "negative sum of square root deviations");
    sum
}

/// (Sample variance)[http://en.wikipedia.org/wiki/Variance#Sample_variance]
pub fn variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float
{
    assert!(v.len() > 1, "variance requires at least two data points");
    let len: T = num::cast(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - T::one())
}

/// (Population variance)[http://en.wikipedia.org/wiki/Variance#Population_variance]
pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Float
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = num::cast(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

///  Standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float
{
    let var = variance(v, xbar);
    var.sqrt()
}

///  Population standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

/// Standard score is a given datum's (signed) number of standard deviations above the mean.
/// (reference)[http://en.wikipedia.org/wiki/Standard_score]
/// Method returns a vector of scores for a vector of inputs. scores[n] is the score of v[n]
pub fn standard_scores<T>(v: &[T]) -> Vec<T>
    where T: Float
{
    let mean = mean(&v);
    let standard_deviation = standard_deviation(&v, None);
    let scores: Vec<T> = v.iter().map(|val| (*val - mean)/standard_deviation).collect();
    return scores;
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T])
    where T: Copy
{
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize
    where T: PartialOrd + Copy
{
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

pub fn quicksort<T>(v: &mut [T])
    where T: PartialOrd + Copy
{
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;
    use num::abs;

    const EPSILON: f32 = 1e-6;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];

        let diff = abs(mean(&vec) - 1.375);

        assert!(diff <= EPSILON);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        let diff = abs(median(&vec) - 2.0);

        assert!(diff <= EPSILON);

        let vec = vec![1.0, 3.0, 5.0];
        let diff = abs(median(&vec) - 3.0);

        assert!(diff <= EPSILON);

        let vec = vec![1.0, 3.0, 5.0, 7.0];
        let diff = abs(median(&vec) - 4.0);

        assert!(diff <= EPSILON);
    }

    #[test]
    fn test_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;

        assert!((expected - variance(&v, None)).abs() < EPSILON);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;

        assert!((expected - population_variance(&v, None)).abs() < EPSILON);
    }

    #[test]
    fn test_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;

        assert!((expected - standard_deviation(&v, None)).abs() < EPSILON);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;

        assert!((expected - population_standard_deviation(&v, None)).abs() < EPSILON);
    }

    #[test]
    fn test_standard_scores() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        let expected = vec![-1.150407536484354, -0.941242529850835, -0.941242529850835, -0.10458250331675945, 0.10458250331675945, 0.31374750995027834, 1.150407536484354, 1.5687375497513918];
        assert!(expected == standard_scores(&v));
    }

    #[test]
    fn test_qsort_empty() {
        let mut vec: Vec<f64> = vec![];
        quicksort(&mut vec);
        assert_eq!(vec, vec![]);
    }

    #[test]
    fn test_qsort_small() {
        let len = 10;
        let mut vec = Vec::with_capacity(len);
        for _ in 0..len { vec.push(rand::random::<f64>()); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_large() {
        let len = 1_000_000;
        let mut vec = Vec::with_capacity(len);
        for _ in 0..len { vec.push(rand::random::<f64>()); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_sorted() {
        let len = 1_000;
        let mut vec = Vec::with_capacity(len);
        for n in 0..len { vec.push(n); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

    #[test]
    fn test_qsort_reverse_sorted() {
        let len = 1_000;
        let mut vec = Vec::with_capacity(len);
        for n in 0..len { vec.push(len-n); }
        quicksort(&mut vec);
        for i in 0..(len-1) {
            assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
        }
    }

}
<|endoftext|>


<commit_before>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  pub fn iter(&mut self) -> Iter {
    Iter::new(self)
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  frame_index: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iter<'a> {
  pub fn new(stream: &'a mut Stream) -> Iter<'a> {
    let samples_left = stream.info.total_samples;

    Iter {
      stream: stream,
      channel: 0,
      frame_index: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.block_size == 0 || self.sample_index == self.block_size {
      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[self.frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel      += 1;
    self.samples_left -= 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Add documentation for turning `Stream` to `Iter`<commit_after>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  pub fn iter(&mut self) -> Iter {
    Iter::new(self)
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  frame_index: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iter<'a> {
  pub fn new(stream: &'a mut Stream) -> Iter<'a> {
    let samples_left = stream.info.total_samples;

    Iter {
      stream: stream,
      channel: 0,
      frame_index: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.block_size == 0 || self.sample_index == self.block_size {
      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[self.frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel      += 1;
    self.samples_left -= 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


<commit_before>use {Connection, DataTransfer, Error, Io};
use server::Client;
use {server, protocol};

use std::io::prelude::*;
use std::io;
use std;

use mio;

pub fn handle_event(client: &mut Client,
                    event: &mio::Event,
                    connection: &mut Connection,
                    the_token: mio::Token,
                    ftp: &mut server::FileTransferProtocol,
                    io: &mut Io)
    -> Result<(), Error> {
    let mut buffer: [u8; 10000] = [0; 10000];
    if the_token == connection.pi.token && event.kind().is_readable() {
        let bytes_written = connection.pi.stream.read(&mut buffer)?;
        let mut data = io::Cursor::new(&buffer[0..bytes_written]);

        if !data.get_ref().is_empty() {
            let command = protocol::CommandKind::read(&mut data)?;
            let reply = match client.handle_command(&command, ftp) {
                Ok(reply) => reply,
                Err(e) => match e {
                    // If it was client error, tell them.
                    Error::Protocol(protocol::Error::Client(e)) => {
                        println!("error from client: {}", e.message());
                        protocol::Reply::new(e.reply_code(), format!("error: {}", e.message()))
                    },
                    e => return Err(e),
                },
            };

            reply.write(&mut connection.pi.stream)?;
        }
    } else {
        if event.kind().is_writable() {
            let dtp = std::mem::replace(&mut connection.dtp,
                                        DataTransfer::None);

            connection.dtp = match dtp {
                DataTransfer::None => unreachable!(),
                DataTransfer::Listening { listener, token } => {
                    assert_eq!(the_token, token);

                    let (sock, _) = listener.accept()?;

                    let connection_token = io.allocate_token();
                    io.poll.register(&sock, connection_token,
                                     mio::Ready::readable() | mio::Ready::hup(),
                                     mio::PollOpt::edge())?;

                    println!("data connection established via PASV mode");

                    DataTransfer::Connecting {
                        stream: sock,
                        token: connection_token,
                    }
                },
                DataTransfer::Connecting { stream, token } => {
                    println!("ACTIVE connection established");

                    // If we received an event on a connecting socket,
                    // it must be writable.
                    DataTransfer::Connected { stream: stream, token: token }
                },
                DataTransfer::Connected { stream, token } => {
                    assert_eq!(the_token, token);
                    DataTransfer::Connected { stream: stream, token: token }
                },
            }
        }

        if event.kind().is_readable() {
            let dtp = std::mem::replace(&mut connection.dtp, DataTransfer::None);

            connection.dtp = match dtp {
                DataTransfer::None => unreachable!(),
                DataTransfer::Listening { listener, .. } => {
                    let (sock, _) = listener.accept()?;

                    let connection_token = io.allocate_token();
                    io.poll.register(&sock, connection_token,
                                     mio::Ready::readable() | mio::Ready::hup(),
                                     mio::PollOpt::edge())?;

                    DataTransfer::Connected {
                        stream: sock,
                        token: connection_token,
                    }
                },
                dtp => dtp,
            };
        }
    }

    Ok(())
}
<commit_msg>Split client_io up into two methods<commit_after>use {Connection, DataTransfer, Error, Io};
use server::Client;
use {server, protocol};

use std::io::prelude::*;
use std::io;
use std;

use mio;

/// Handles an IO event on the protocol or data connections.
pub fn handle_event(client: &mut Client,
                    event: &mio::Event,
                    connection: &mut Connection,
                    the_token: mio::Token,
                    ftp: &mut server::FileTransferProtocol,
                    io: &mut Io)
    -> Result<(), Error> {
    if the_token == connection.pi.token && event.kind().is_readable() {
        handle_protocol_event(client, event, connection, the_token, ftp, io)
    } else {
        handle_data_event(client, event, connection, the_token, ftp, io)
    }
}

/// Handles an IO event on the protocol stream.
fn handle_protocol_event(client: &mut Client,
                             event: &mio::Event,
                             connection: &mut Connection,
                             the_token: mio::Token,
                             ftp: &mut server::FileTransferProtocol,
                             io: &mut Io)
    -> Result<(), Error> {
    let mut buffer: [u8; 10000] = [0; 10000];
    let bytes_written = connection.pi.stream.read(&mut buffer)?;
    let mut data = io::Cursor::new(&buffer[0..bytes_written]);

    if !data.get_ref().is_empty() {
        let command = protocol::CommandKind::read(&mut data)?;
        let reply = match client.handle_command(&command, ftp) {
            Ok(reply) => reply,
            Err(e) => match e {
                // If it was client error, tell them.
                Error::Protocol(protocol::Error::Client(e)) => {
                    println!("error from client: {}", e.message());
                    protocol::Reply::new(e.reply_code(), format!("error: {}", e.message()))
                },
                e => return Err(e),
            },
        };

        reply.write(&mut connection.pi.stream)?;
    }

    Ok(())
}

/// Handles an IO event on the data stream.
fn handle_data_event(client: &mut Client,
                         event: &mio::Event,
                         connection: &mut Connection,
                         the_token: mio::Token,
                         ftp: &mut server::FileTransferProtocol,
                         io: &mut Io)
    -> Result<(), Error> {
    let mut buffer: [u8; 10000] = [0; 10000];
    if event.kind().is_writable() {
        let dtp = std::mem::replace(&mut connection.dtp,
                                    DataTransfer::None);

        connection.dtp = match dtp {
            DataTransfer::None => unreachable!(),
            DataTransfer::Listening { listener, token } => {
                assert_eq!(the_token, token);

                let (sock, _) = listener.accept()?;

                let connection_token = io.allocate_token();
                io.poll.register(&sock, connection_token,
                                 mio::Ready::readable() | mio::Ready::hup(),
                                 mio::PollOpt::edge())?;

                println!("data connection established via PASV mode");

                DataTransfer::Connecting {
                    stream: sock,
                    token: connection_token,
                }
            },
            DataTransfer::Connecting { stream, token } => {
                println!("ACTIVE connection established");

                // If we received an event on a connecting socket,
                // it must be writable.
                DataTransfer::Connected { stream: stream, token: token }
            },
            DataTransfer::Connected { stream, token } => {
                assert_eq!(the_token, token);
                DataTransfer::Connected { stream: stream, token: token }
            },
        }
    }

    if event.kind().is_readable() {
        let dtp = std::mem::replace(&mut connection.dtp, DataTransfer::None);

        connection.dtp = match dtp {
            DataTransfer::None => unreachable!(),
            DataTransfer::Listening { listener, .. } => {
                let (sock, _) = listener.accept()?;

                let connection_token = io.allocate_token();
                io.poll.register(&sock, connection_token,
                                 mio::Ready::readable() | mio::Ready::hup(),
                                 mio::PollOpt::edge())?;

                DataTransfer::Connected {
                    stream: sock,
                    token: connection_token,
                }
            },
            dtp => dtp,
        };
    }

    Ok(())
}

<|endoftext|>