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

use super::autoderef;
use super::check_argument_types;
use super::check_expr;
use super::check_method_argument_types;
use super::demand;
use super::DeferredCallResolution;
use super::err_args;
use super::Expectation;
use super::expected_types_for_fn_args;
use super::FnCtxt;
use super::method;
use super::structurally_resolved_type;
use super::TupleArgumentsFlag;
use super::UnresolvedTypeAction;
use super::write_call;

use CrateCtxt;
use metadata::cstore::LOCAL_CRATE;
use middle::def_id::DefId;
use middle::infer;
use middle::ty::{self, LvaluePreference, Ty};
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ptr::P;

use rustc_front::hir;

/// Check that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called)
pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
    let tcx = ccx.tcx;
    let did = Some(trait_id);
    let li = &tcx.lang_items;

    if did == li.drop_trait() {
        span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
    } else if !tcx.sess.features.borrow().unboxed_closures {
        // the #[feature(unboxed_closures)] feature isn't
        // activated so we need to enforce the closure
        // restrictions.

        let method = if did == li.fn_trait() {
            "call"
        } else if did == li.fn_mut_trait() {
            "call_mut"
        } else if did == li.fn_once_trait() {
            "call_once"
        } else {
            return // not a closure method, everything is OK.
        };

        span_err!(tcx.sess, span, E0174,
                  "explicit use of unboxed closure method `{}` is experimental",
                  method);
        fileline_help!(tcx.sess, span,
                   "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
    }
}

pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            call_expr: &'tcx hir::Expr,
                            callee_expr: &'tcx hir::Expr,
                            arg_exprs: &'tcx [P<hir::Expr>],
                            expected: Expectation<'tcx>)
{
    check_expr(fcx, callee_expr);
    let original_callee_ty = fcx.expr_ty(callee_expr);
    let (callee_ty, _, result) =
        autoderef(fcx,
                  callee_expr.span,
                  original_callee_ty,
                  Some(callee_expr),
                  UnresolvedTypeAction::Error,
                  LvaluePreference::NoPreference,
                  |adj_ty, idx| {
                      try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx)
                  });

    match result {
        None => {
            // this will report an error since original_callee_ty is not a fn
            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected);
        }

        Some(CallStep::Builtin) => {
            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
        }

        Some(CallStep::DeferredClosure(fn_sig)) => {
            confirm_deferred_closure_call(fcx, call_expr, arg_exprs, expected, fn_sig);
        }

        Some(CallStep::Overloaded(method_callee)) => {
            confirm_overloaded_call(fcx, call_expr, callee_expr,
                                    arg_exprs, expected, method_callee);
        }
    }
}

enum CallStep<'tcx> {
    Builtin,
    DeferredClosure(ty::FnSig<'tcx>),
    Overloaded(ty::MethodCallee<'tcx>)
}

fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      call_expr: &'tcx hir::Expr,
                                      callee_expr: &'tcx hir::Expr,
                                      adjusted_ty: Ty<'tcx>,
                                      autoderefs: usize)
                                      -> Option<CallStep<'tcx>>
{
    debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
           call_expr,
           adjusted_ty,
           autoderefs);

    // If the callee is a bare function or a closure, then we're all set.
    match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
        ty::TyBareFn(..) => {
            fcx.write_autoderef_adjustment(callee_expr.id, autoderefs);
            return Some(CallStep::Builtin);
        }

        ty::TyClosure(def_id, ref substs) => {
            assert_eq!(def_id.krate, LOCAL_CRATE);

            // Check whether this is a call to a closure where we
            // haven't yet decided on whether the closure is fn vs
            // fnmut vs fnonce. If so, we have to defer further processing.
            if fcx.infcx().closure_kind(def_id).is_none() {
                let closure_ty =
                    fcx.infcx().closure_type(def_id, substs);
                let fn_sig =
                    fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                          infer::FnCall,
                                                                          &closure_ty.sig).0;
                fcx.record_deferred_call_resolution(def_id, Box::new(CallResolution {
                    call_expr: call_expr,
                    callee_expr: callee_expr,
                    adjusted_ty: adjusted_ty,
                    autoderefs: autoderefs,
                    fn_sig: fn_sig.clone(),
                    closure_def_id: def_id
                }));
                return Some(CallStep::DeferredClosure(fn_sig));
            }
        }

        // Hack: we know that there are traits implementing Fn for &F
        // where F:Fn and so forth. In the particular case of types
        // like `x: &mut FnMut()`, if there is a call `x()`, we would
        // normally translate to `FnMut::call_mut(&mut x, ())`, but
        // that winds up requiring `mut x: &mut FnMut()`. A little
        // over the top. The simplest fix by far is to just ignore
        // this case and deref again, so we wind up with
        // `FnMut::call_mut(&mut *x, ())`.
        ty::TyRef(..) if autoderefs == 0 => {
            return None;
        }

        _ => {}
    }

    try_overloaded_call_traits(fcx, call_expr, callee_expr, adjusted_ty, autoderefs)
        .map(|method_callee| CallStep::Overloaded(method_callee))
}

fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       call_expr: &hir::Expr,
                                       callee_expr: &hir::Expr,
                                       adjusted_ty: Ty<'tcx>,
                                       autoderefs: usize)
                                       -> Option<ty::MethodCallee<'tcx>>
{
    // Try the options that are least restrictive on the caller first.
    for &(opt_trait_def_id, method_name) in &[
        (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
        (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
        (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
    ] {
        let trait_def_id = match opt_trait_def_id {
            Some(def_id) => def_id,
            None => continue,
        };

        match method::lookup_in_trait_adjusted(fcx,
                                               call_expr.span,
                                               Some(&*callee_expr),
                                               method_name,
                                               trait_def_id,
                                               autoderefs,
                                               false,
                                               adjusted_ty,
                                               None) {
            None => continue,
            Some(method_callee) => {
                return Some(method_callee);
            }
        }
    }

    None
}

fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                 call_expr: &hir::Expr,
                                 callee_ty: Ty<'tcx>,
                                 arg_exprs: &'tcx [P<hir::Expr>],
                                 expected: Expectation<'tcx>)
{
    let error_fn_sig;

    let fn_sig = match callee_ty.sty {
        ty::TyBareFn(_, &ty::BareFnTy {ref sig, ..}) => {
            sig
        }
        _ => {
            fcx.type_error_message(call_expr.span, |actual| {
                format!("expected function, found `{}`", actual)
            }, callee_ty, None);

            // This is the "default" function signature, used in case of error.
            // In that case, we check each argument against "error" in order to
            // set up all the node type bindings.
            error_fn_sig = ty::Binder(ty::FnSig {
                inputs: err_args(fcx.tcx(), arg_exprs.len()),
                output: ty::FnConverging(fcx.tcx().types.err),
                variadic: false
            });

            &error_fn_sig
        }
    };

    // Replace any late-bound regions that appear in the function
    // signature with region variables. We also have to
    // renormalize the associated types at this point, since they
    // previously appeared within a `Binder<>` and hence would not
    // have been normalized before.
    let fn_sig =
        fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                              infer::FnCall,
                                                              fn_sig).0;
    let fn_sig =
        fcx.normalize_associated_types_in(call_expr.span, &fn_sig);

    // Call the generic checker.
    let expected_arg_tys = expected_types_for_fn_args(fcx,
                                                      call_expr.span,
                                                      expected,
                                                      fn_sig.output,
                                                      &fn_sig.inputs);
    check_argument_types(fcx,
                         call_expr.span,
                         &fn_sig.inputs,
                         &expected_arg_tys[..],
                         arg_exprs,
                         fn_sig.variadic,
                         TupleArgumentsFlag::DontTupleArguments);

    write_call(fcx, call_expr, fn_sig.output);
}

fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                          call_expr: &hir::Expr,
                                          arg_exprs: &'tcx [P<hir::Expr>],
                                          expected: Expectation<'tcx>,
                                          fn_sig: ty::FnSig<'tcx>)
{
    // `fn_sig` is the *signature* of the cosure being called. We
    // don't know the full details yet (`Fn` vs `FnMut` etc), but we
    // do know the types expected for each argument and the return
    // type.

    let expected_arg_tys =
        expected_types_for_fn_args(fcx,
                                   call_expr.span,
                                   expected,
                                   fn_sig.output.clone(),
                                   &*fn_sig.inputs);

    check_argument_types(fcx,
                         call_expr.span,
                         &*fn_sig.inputs,
                         &*expected_arg_tys,
                         arg_exprs,
                         fn_sig.variadic,
                         TupleArgumentsFlag::TupleArguments);

    write_call(fcx, call_expr, fn_sig.output);
}

fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                    call_expr: &hir::Expr,
                                    callee_expr: &'tcx hir::Expr,
                                    arg_exprs: &'tcx [P<hir::Expr>],
                                    expected: Expectation<'tcx>,
                                    method_callee: ty::MethodCallee<'tcx>)
{
    let output_type =
        check_method_argument_types(fcx,
                                    call_expr.span,
                                    method_callee.ty,
                                    callee_expr,
                                    arg_exprs,
                                    TupleArgumentsFlag::TupleArguments,
                                    expected);
    write_call(fcx, call_expr, output_type);

    write_overloaded_call_method_map(fcx, call_expr, method_callee);
}

fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                             call_expr: &hir::Expr,
                                             method_callee: ty::MethodCallee<'tcx>) {
    let method_call = ty::MethodCall::expr(call_expr.id);
    fcx.inh.tables.borrow_mut().method_map.insert(method_call, method_callee);
}

#[derive(Debug)]
struct CallResolution<'tcx> {
    call_expr: &'tcx hir::Expr,
    callee_expr: &'tcx hir::Expr,
    adjusted_ty: Ty<'tcx>,
    autoderefs: usize,
    fn_sig: ty::FnSig<'tcx>,
    closure_def_id: DefId,
}

impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
        debug!("DeferredCallResolution::resolve() {:?}",
               self);

        // we should not be invoked until the closure kind has been
        // determined by upvar inference
        assert!(fcx.infcx().closure_kind(self.closure_def_id).is_some());

        // We may now know enough to figure out fn vs fnmut etc.
        match try_overloaded_call_traits(fcx, self.call_expr, self.callee_expr,
                                         self.adjusted_ty, self.autoderefs) {
            Some(method_callee) => {
                // One problem is that when we get here, we are going
                // to have a newly instantiated function signature
                // from the call trait. This has to be reconciled with
                // the older function signature we had before. In
                // principle we *should* be able to fn_sigs(), but we
                // can't because of the annoying need for a TypeTrace.
                // (This always bites me, should find a way to
                // refactor it.)
                let method_sig = fcx.tcx().no_late_bound_regions(method_callee.ty.fn_sig())
                                          .unwrap();

                debug!("attempt_resolution: method_callee={:?}",
                       method_callee);

                for (&method_arg_ty, &self_arg_ty) in
                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
                {
                    demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
                }

                let nilty = fcx.tcx().mk_nil();
                demand::eqtype(fcx,
                               self.call_expr.span,
                               method_sig.output.unwrap_or(nilty),
                               self.fn_sig.output.unwrap_or(nilty));

                write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
            }
            None => {
                fcx.tcx().sess.span_bug(
                    self.call_expr.span,
                    "failed to find an overloaded call trait for closure call");
            }
        }
    }
}
<commit_msg>Add a note when trying to call a non-function<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::autoderef;
use super::check_argument_types;
use super::check_expr;
use super::check_method_argument_types;
use super::demand;
use super::DeferredCallResolution;
use super::err_args;
use super::Expectation;
use super::expected_types_for_fn_args;
use super::FnCtxt;
use super::method;
use super::structurally_resolved_type;
use super::TupleArgumentsFlag;
use super::UnresolvedTypeAction;
use super::write_call;

use CrateCtxt;
use metadata::cstore::LOCAL_CRATE;
use middle::def_id::DefId;
use middle::infer;
use middle::ty::{self, LvaluePreference, Ty};
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ptr::P;

use rustc_front::hir;

/// Check that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called)
pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
    let tcx = ccx.tcx;
    let did = Some(trait_id);
    let li = &tcx.lang_items;

    if did == li.drop_trait() {
        span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
    } else if !tcx.sess.features.borrow().unboxed_closures {
        // the #[feature(unboxed_closures)] feature isn't
        // activated so we need to enforce the closure
        // restrictions.

        let method = if did == li.fn_trait() {
            "call"
        } else if did == li.fn_mut_trait() {
            "call_mut"
        } else if did == li.fn_once_trait() {
            "call_once"
        } else {
            return // not a closure method, everything is OK.
        };

        span_err!(tcx.sess, span, E0174,
                  "explicit use of unboxed closure method `{}` is experimental",
                  method);
        fileline_help!(tcx.sess, span,
                   "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
    }
}

pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            call_expr: &'tcx hir::Expr,
                            callee_expr: &'tcx hir::Expr,
                            arg_exprs: &'tcx [P<hir::Expr>],
                            expected: Expectation<'tcx>)
{
    check_expr(fcx, callee_expr);
    let original_callee_ty = fcx.expr_ty(callee_expr);
    let (callee_ty, _, result) =
        autoderef(fcx,
                  callee_expr.span,
                  original_callee_ty,
                  Some(callee_expr),
                  UnresolvedTypeAction::Error,
                  LvaluePreference::NoPreference,
                  |adj_ty, idx| {
                      try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx)
                  });

    match result {
        None => {
            // this will report an error since original_callee_ty is not a fn
            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected);
        }

        Some(CallStep::Builtin) => {
            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
        }

        Some(CallStep::DeferredClosure(fn_sig)) => {
            confirm_deferred_closure_call(fcx, call_expr, arg_exprs, expected, fn_sig);
        }

        Some(CallStep::Overloaded(method_callee)) => {
            confirm_overloaded_call(fcx, call_expr, callee_expr,
                                    arg_exprs, expected, method_callee);
        }
    }
}

enum CallStep<'tcx> {
    Builtin,
    DeferredClosure(ty::FnSig<'tcx>),
    Overloaded(ty::MethodCallee<'tcx>)
}

fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      call_expr: &'tcx hir::Expr,
                                      callee_expr: &'tcx hir::Expr,
                                      adjusted_ty: Ty<'tcx>,
                                      autoderefs: usize)
                                      -> Option<CallStep<'tcx>>
{
    debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
           call_expr,
           adjusted_ty,
           autoderefs);

    // If the callee is a bare function or a closure, then we're all set.
    match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
        ty::TyBareFn(..) => {
            fcx.write_autoderef_adjustment(callee_expr.id, autoderefs);
            return Some(CallStep::Builtin);
        }

        ty::TyClosure(def_id, ref substs) => {
            assert_eq!(def_id.krate, LOCAL_CRATE);

            // Check whether this is a call to a closure where we
            // haven't yet decided on whether the closure is fn vs
            // fnmut vs fnonce. If so, we have to defer further processing.
            if fcx.infcx().closure_kind(def_id).is_none() {
                let closure_ty =
                    fcx.infcx().closure_type(def_id, substs);
                let fn_sig =
                    fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                          infer::FnCall,
                                                                          &closure_ty.sig).0;
                fcx.record_deferred_call_resolution(def_id, Box::new(CallResolution {
                    call_expr: call_expr,
                    callee_expr: callee_expr,
                    adjusted_ty: adjusted_ty,
                    autoderefs: autoderefs,
                    fn_sig: fn_sig.clone(),
                    closure_def_id: def_id
                }));
                return Some(CallStep::DeferredClosure(fn_sig));
            }
        }

        // Hack: we know that there are traits implementing Fn for &F
        // where F:Fn and so forth. In the particular case of types
        // like `x: &mut FnMut()`, if there is a call `x()`, we would
        // normally translate to `FnMut::call_mut(&mut x, ())`, but
        // that winds up requiring `mut x: &mut FnMut()`. A little
        // over the top. The simplest fix by far is to just ignore
        // this case and deref again, so we wind up with
        // `FnMut::call_mut(&mut *x, ())`.
        ty::TyRef(..) if autoderefs == 0 => {
            return None;
        }

        _ => {}
    }

    try_overloaded_call_traits(fcx, call_expr, callee_expr, adjusted_ty, autoderefs)
        .map(|method_callee| CallStep::Overloaded(method_callee))
}

fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       call_expr: &hir::Expr,
                                       callee_expr: &hir::Expr,
                                       adjusted_ty: Ty<'tcx>,
                                       autoderefs: usize)
                                       -> Option<ty::MethodCallee<'tcx>>
{
    // Try the options that are least restrictive on the caller first.
    for &(opt_trait_def_id, method_name) in &[
        (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
        (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
        (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
    ] {
        let trait_def_id = match opt_trait_def_id {
            Some(def_id) => def_id,
            None => continue,
        };

        match method::lookup_in_trait_adjusted(fcx,
                                               call_expr.span,
                                               Some(&*callee_expr),
                                               method_name,
                                               trait_def_id,
                                               autoderefs,
                                               false,
                                               adjusted_ty,
                                               None) {
            None => continue,
            Some(method_callee) => {
                return Some(method_callee);
            }
        }
    }

    None
}

fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                 call_expr: &hir::Expr,
                                 callee_ty: Ty<'tcx>,
                                 arg_exprs: &'tcx [P<hir::Expr>],
                                 expected: Expectation<'tcx>)
{
    let error_fn_sig;

    let fn_sig = match callee_ty.sty {
        ty::TyBareFn(_, &ty::BareFnTy {ref sig, ..}) => {
            sig
        }
        _ => {
            fcx.type_error_message(call_expr.span, |actual| {
                format!("expected function, found `{}`", actual)
            }, callee_ty, None);

            if let hir::ExprCall(ref expr, _) = call_expr.node {
                let tcx = fcx.tcx();
                if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
                    if pr.depth == 0 {
                        if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
                            tcx.sess.span_note(span, "defined here")
                        }
                    }
                }
            }

            // This is the "default" function signature, used in case of error.
            // In that case, we check each argument against "error" in order to
            // set up all the node type bindings.
            error_fn_sig = ty::Binder(ty::FnSig {
                inputs: err_args(fcx.tcx(), arg_exprs.len()),
                output: ty::FnConverging(fcx.tcx().types.err),
                variadic: false
            });

            &error_fn_sig
        }
    };

    // Replace any late-bound regions that appear in the function
    // signature with region variables. We also have to
    // renormalize the associated types at this point, since they
    // previously appeared within a `Binder<>` and hence would not
    // have been normalized before.
    let fn_sig =
        fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                              infer::FnCall,
                                                              fn_sig).0;
    let fn_sig =
        fcx.normalize_associated_types_in(call_expr.span, &fn_sig);

    // Call the generic checker.
    let expected_arg_tys = expected_types_for_fn_args(fcx,
                                                      call_expr.span,
                                                      expected,
                                                      fn_sig.output,
                                                      &fn_sig.inputs);
    check_argument_types(fcx,
                         call_expr.span,
                         &fn_sig.inputs,
                         &expected_arg_tys[..],
                         arg_exprs,
                         fn_sig.variadic,
                         TupleArgumentsFlag::DontTupleArguments);

    write_call(fcx, call_expr, fn_sig.output);
}

fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                          call_expr: &hir::Expr,
                                          arg_exprs: &'tcx [P<hir::Expr>],
                                          expected: Expectation<'tcx>,
                                          fn_sig: ty::FnSig<'tcx>)
{
    // `fn_sig` is the *signature* of the cosure being called. We
    // don't know the full details yet (`Fn` vs `FnMut` etc), but we
    // do know the types expected for each argument and the return
    // type.

    let expected_arg_tys =
        expected_types_for_fn_args(fcx,
                                   call_expr.span,
                                   expected,
                                   fn_sig.output.clone(),
                                   &*fn_sig.inputs);

    check_argument_types(fcx,
                         call_expr.span,
                         &*fn_sig.inputs,
                         &*expected_arg_tys,
                         arg_exprs,
                         fn_sig.variadic,
                         TupleArgumentsFlag::TupleArguments);

    write_call(fcx, call_expr, fn_sig.output);
}

fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                    call_expr: &hir::Expr,
                                    callee_expr: &'tcx hir::Expr,
                                    arg_exprs: &'tcx [P<hir::Expr>],
                                    expected: Expectation<'tcx>,
                                    method_callee: ty::MethodCallee<'tcx>)
{
    let output_type =
        check_method_argument_types(fcx,
                                    call_expr.span,
                                    method_callee.ty,
                                    callee_expr,
                                    arg_exprs,
                                    TupleArgumentsFlag::TupleArguments,
                                    expected);
    write_call(fcx, call_expr, output_type);

    write_overloaded_call_method_map(fcx, call_expr, method_callee);
}

fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                             call_expr: &hir::Expr,
                                             method_callee: ty::MethodCallee<'tcx>) {
    let method_call = ty::MethodCall::expr(call_expr.id);
    fcx.inh.tables.borrow_mut().method_map.insert(method_call, method_callee);
}

#[derive(Debug)]
struct CallResolution<'tcx> {
    call_expr: &'tcx hir::Expr,
    callee_expr: &'tcx hir::Expr,
    adjusted_ty: Ty<'tcx>,
    autoderefs: usize,
    fn_sig: ty::FnSig<'tcx>,
    closure_def_id: DefId,
}

impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
        debug!("DeferredCallResolution::resolve() {:?}",
               self);

        // we should not be invoked until the closure kind has been
        // determined by upvar inference
        assert!(fcx.infcx().closure_kind(self.closure_def_id).is_some());

        // We may now know enough to figure out fn vs fnmut etc.
        match try_overloaded_call_traits(fcx, self.call_expr, self.callee_expr,
                                         self.adjusted_ty, self.autoderefs) {
            Some(method_callee) => {
                // One problem is that when we get here, we are going
                // to have a newly instantiated function signature
                // from the call trait. This has to be reconciled with
                // the older function signature we had before. In
                // principle we *should* be able to fn_sigs(), but we
                // can't because of the annoying need for a TypeTrace.
                // (This always bites me, should find a way to
                // refactor it.)
                let method_sig = fcx.tcx().no_late_bound_regions(method_callee.ty.fn_sig())
                                          .unwrap();

                debug!("attempt_resolution: method_callee={:?}",
                       method_callee);

                for (&method_arg_ty, &self_arg_ty) in
                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
                {
                    demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
                }

                let nilty = fcx.tcx().mk_nil();
                demand::eqtype(fcx,
                               self.call_expr.span,
                               method_sig.output.unwrap_or(nilty),
                               self.fn_sig.output.unwrap_or(nilty));

                write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
            }
            None => {
                fcx.tcx().sess.span_bug(
                    self.call_expr.span,
                    "failed to find an overloaded call trait for closure call");
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use crate::io::spi::{Target, Transfer};
use crate::spiflash::sfdp::{BlockEraseSize, Sfdp, SupportedAddressModes};
use anyhow::{ensure, Result};
use std::convert::TryFrom;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
    #[error("address out of bounds: {0} >= {1}")]
    AddressOutOfBounds(u32, u32),
    #[error("erase at address {0} not aligned on {1}-byte boundary")]
    BadEraseAddress(u32, u32),
    #[error("erase length {0} not a multiple of {1} bytes")]
    BadEraseLength(u32, u32),
}

#[derive(Debug, PartialEq, Eq)]
pub enum AddressMode {
    Mode3b,
    Mode4b,
}

impl From<SupportedAddressModes> for AddressMode {
    fn from(mode: SupportedAddressModes) -> Self {
        match mode {
            SupportedAddressModes::Mode4b => AddressMode::Mode4b,
            _ => AddressMode::Mode3b,
        }
    }
}

impl Default for AddressMode {
    fn default() -> Self {
        AddressMode::Mode3b
    }
}

pub struct SpiFlash {
    pub size: u32,
    pub erase_size: u32,
    pub erase_opcode: u8,
    pub program_size: u32,
    pub address_mode: AddressMode,
    pub sfdp: Option<Sfdp>,
}

impl Default for SpiFlash {
    fn default() -> Self {
        SpiFlash {
            size: 16 * 1024 * 1024,
            erase_size: 4 * 1024,
            erase_opcode: 0x20,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::default(),
            sfdp: None,
        }
    }
}

impl SpiFlash {
    // Well known SPI Flash opcodes.
    pub const READ: u8 = 0x03;
    pub const PAGE_PROGRAM: u8 = 0x02;
    pub const SECTOR_ERASE: u8 = 0x20;
    pub const CHIP_ERASE: u8 = 0xc7;
    pub const WRITE_ENABLE: u8 = 0x06;
    pub const WRITE_DISABLE: u8 = 0x04;
    pub const READ_STATUS: u8 = 0x05;
    pub const READ_ID: u8 = 0x9f;
    pub const ENTER_4B: u8 = 0xb7;
    pub const EXIT_4B: u8 = 0xe9;
    pub const READ_SFDP: u8 = 0x5a;
    pub const NOP: u8 = 0x00;
    pub const RESET_ENABLE: u8 = 0x66;
    pub const RESET: u8 = 0x99;

    /// The legacy JEDEC page size for programming operations is 256 bytes.
    pub const LEGACY_PAGE_SIZE: u32 = 256;

    /// Status register bits:
    /// The `WIP` bit indicates a write in progress (sometimes called the busy bit).
    pub const STATUS_WIP: u8 = 0x01;
    /// The `WEL` bit is the write enable latch.
    pub const STATUS_WEL: u8 = 0x02;

    /// Prepare an opcode and address buffer according to the address_mode.
    fn opcode_with_address(&self, opcode: u8, address: u32) -> Result<Vec<u8>> {
        ensure!(
            address < self.size,
            Error::AddressOutOfBounds(address, self.size)
        );
        let mut buf = vec![opcode];
        if self.address_mode == AddressMode::Mode4b {
            buf.push((address >> 24) as u8);
        }
        buf.push((address >> 16) as u8);
        buf.push((address >> 8) as u8);
        buf.push(address as u8);
        Ok(buf)
    }

    /// Read `length` bytes of the JEDEC ID from the `spi` target.
    pub fn read_jedec_id(spi: &dyn Target, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_ID]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf)
    }

    /// Read status register from the `spi` target.
    pub fn read_status(spi: &dyn Target) -> Result<u8> {
        let mut buf = [0u8; 1];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_STATUS]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf[0])
    }

    /// Poll the status register waiting for the busy bit to clear.
    pub fn wait_for_busy_clear(spi: &dyn Target) -> Result<()> {
        while SpiFlash::read_status(spi)? & SpiFlash::STATUS_WIP != 0 {
            // Do nothing.
        }
        Ok(())
    }

    /// Send the WRITE_ENABLE opcode to the `spi` target.
    pub fn set_write_enable(spi: &dyn Target) -> Result<()> {
        let wren = [SpiFlash::WRITE_ENABLE];
        spi.run_transaction(&mut [Transfer::Write(&wren)])?;
        Ok(())
    }

    /// Read and parse the SFDP table from the `spi` target.
    pub fn read_sfdp(spi: &dyn Target) -> Result<Sfdp> {
        let mut buf = vec![0u8; 256];
        let mut tries = 0;
        loop {
            spi.run_transaction(&mut [
                // READ_SFDP always takes a 3-byte address followed by a dummy
                // byte regardless of address mode.  To simplify, we always
                // read from address zero.
                Transfer::Write(&[SpiFlash::READ_SFDP, 0, 0, 0, 0]),
                Transfer::Read(&mut buf),
            ])?;

            // We only want to give SFDP parsing one extra chance for length
            // extension. If parsing fails a second time, just return the error.
            let result = Sfdp::try_from(&buf[..]);
            if result.is_ok() || tries > 0 {
                return result;
            }
            buf.resize(Sfdp::length_required(&buf)?, 0);
            tries += 1;
        }
    }

    /// Create a new `SpiFlash` instance from an SFDP table.
    pub fn from_sfdp(sfdp: Sfdp) -> Self {
        let (erase_sz, erase_op) = match sfdp.jedec.block_erase_size {
            BlockEraseSize::Block4KiB => (4096, sfdp.jedec.erase_opcode_4kib),
            _ => (sfdp.jedec.sector[0].size, sfdp.jedec.sector[0].erase_opcode),
        };
        SpiFlash {
            size: sfdp.jedec.density,
            erase_size: erase_sz,
            erase_opcode: erase_op,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::from(sfdp.jedec.address_modes),
            sfdp: Some(sfdp),
        }
    }

    /// Create a new `SpiFlash` instance by reading an SFDP table from the `spi` Target.
    pub fn from_spi(spi: &dyn Target) -> Result<Self> {
        let sfdp = SpiFlash::read_sfdp(spi)?;
        Ok(SpiFlash::from_sfdp(sfdp))
    }

    /// Set the SPI flash addressing mode to either 3b or 4b mode.
    pub fn set_address_mode(&mut self, spi: &dyn Target, mode: AddressMode) -> Result<()> {
        let opcode = [match mode {
            AddressMode::Mode3b => SpiFlash::EXIT_4B,
            AddressMode::Mode4b => SpiFlash::ENTER_4B,
        }];
        spi.run_transaction(&mut [Transfer::Write(&opcode)])?;
        self.address_mode = mode;
        Ok(())
    }

    /// Automatically set the addressing mode based on the size of the SPI flash.
    pub fn set_address_mode_auto(&mut self, spi: &dyn Target) -> Result<()> {
        self.set_address_mode(
            spi,
            if self.size <= 16 * 1024 * 1024 {
                AddressMode::Mode3b
            } else {
                AddressMode::Mode4b
            },
        )
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    pub fn read(&self, spi: &dyn Target, address: u32, buffer: &mut [u8]) -> Result<()> {
        self.read_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    /// The `progress` callback will be invoked after each chunk of the read operation.
    pub fn read_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &mut [u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        // Break the read up according to the maximum chunksize the backend can handle.
        for chunk in buffer.chunks_mut(spi.max_chunk_size()?) {
            let op_addr = self.opcode_with_address(SpiFlash::READ, address)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr), Transfer::Read(chunk)])?;
            address += chunk.len() as u32;
            progress(address, chunk.len() as u32);
        }
        Ok(())
    }

    /// Erase the entire EEPROM via the CHIP_ERASE opcode.
    pub fn chip_erase(&self, spi: &dyn Target) -> Result<()> {
        Self::set_write_enable(spi)?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::CHIP_ERASE])])?;
        Self::wait_for_busy_clear(spi)?;
        Ok(())
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    pub fn erase(&self, spi: &dyn Target, address: u32, length: u32) -> Result<()> {
        self.erase_with_progress(spi, address, length, |_, _| {})
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    /// The `progress` callback will be invoked after each chunk of the erase operation.
    pub fn erase_with_progress(
        &self,
        spi: &dyn Target,
        address: u32,
        length: u32,
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        if address % self.erase_size != 0 {
            return Err(Error::BadEraseAddress(address, self.erase_size).into());
        }
        if length % self.erase_size != 0 {
            return Err(Error::BadEraseLength(length, self.erase_size).into());
        }
        let end = address + length;
        for addr in (address..end).step_by(self.erase_size as usize) {
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the erase transaction.
            let op_addr = self.opcode_with_address(SpiFlash::SECTOR_ERASE, addr)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr)])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            progress(addr, self.erase_size);
        }
        Ok(())
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    pub fn program(&self, spi: &dyn Target, address: u32, buffer: &[u8]) -> Result<()> {
        self.program_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    /// The `progress` callback will be invoked after each chunk of the program operation.
    pub fn program_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &[u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        let mut remain = buffer.len();
        let mut chunkstart = 0usize;
        while remain != 0 {
            // If the address isn't program-page-size aligned, adjust the first
            // chunk so that subsequent writes will be so-aligned.
            // This is necessary because the SPI eeprom will wrap within the
            // programming page and the resultant data in the eeprom will not
            // be what you intended.
            let chunk = (self.program_size - (address % self.program_size)) as usize;
            let chunk = std::cmp::min(chunk, remain);
            let chunkend = chunkstart + chunk;
            let op_addr = self.opcode_with_address(SpiFlash::PAGE_PROGRAM, address)?;
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the program operation.
            spi.run_transaction(&mut [
                Transfer::Write(&op_addr),
                Transfer::Write(&buffer[chunkstart..chunkend]),
            ])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            address += chunk as u32;
            chunkstart += chunk;
            remain -= chunk;
            progress(address, chunk as u32);
        }
        Ok(())
    }

    /// Send the software reset sequence to the `spi` target.
    pub fn chip_reset(spi: &dyn Target) -> Result<()> {
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET_ENABLE])])?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET])])?;
        Ok(())
    }
}
<commit_msg>[opentitantool] Add SpiFlash::set_write_disable()<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use crate::io::spi::{Target, Transfer};
use crate::spiflash::sfdp::{BlockEraseSize, Sfdp, SupportedAddressModes};
use anyhow::{ensure, Result};
use std::convert::TryFrom;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
    #[error("address out of bounds: {0} >= {1}")]
    AddressOutOfBounds(u32, u32),
    #[error("erase at address {0} not aligned on {1}-byte boundary")]
    BadEraseAddress(u32, u32),
    #[error("erase length {0} not a multiple of {1} bytes")]
    BadEraseLength(u32, u32),
}

#[derive(Debug, PartialEq, Eq)]
pub enum AddressMode {
    Mode3b,
    Mode4b,
}

impl From<SupportedAddressModes> for AddressMode {
    fn from(mode: SupportedAddressModes) -> Self {
        match mode {
            SupportedAddressModes::Mode4b => AddressMode::Mode4b,
            _ => AddressMode::Mode3b,
        }
    }
}

impl Default for AddressMode {
    fn default() -> Self {
        AddressMode::Mode3b
    }
}

pub struct SpiFlash {
    pub size: u32,
    pub erase_size: u32,
    pub erase_opcode: u8,
    pub program_size: u32,
    pub address_mode: AddressMode,
    pub sfdp: Option<Sfdp>,
}

impl Default for SpiFlash {
    fn default() -> Self {
        SpiFlash {
            size: 16 * 1024 * 1024,
            erase_size: 4 * 1024,
            erase_opcode: 0x20,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::default(),
            sfdp: None,
        }
    }
}

impl SpiFlash {
    // Well known SPI Flash opcodes.
    pub const READ: u8 = 0x03;
    pub const PAGE_PROGRAM: u8 = 0x02;
    pub const SECTOR_ERASE: u8 = 0x20;
    pub const CHIP_ERASE: u8 = 0xc7;
    pub const WRITE_ENABLE: u8 = 0x06;
    pub const WRITE_DISABLE: u8 = 0x04;
    pub const READ_STATUS: u8 = 0x05;
    pub const READ_ID: u8 = 0x9f;
    pub const ENTER_4B: u8 = 0xb7;
    pub const EXIT_4B: u8 = 0xe9;
    pub const READ_SFDP: u8 = 0x5a;
    pub const NOP: u8 = 0x00;
    pub const RESET_ENABLE: u8 = 0x66;
    pub const RESET: u8 = 0x99;

    /// The legacy JEDEC page size for programming operations is 256 bytes.
    pub const LEGACY_PAGE_SIZE: u32 = 256;

    /// Status register bits:
    /// The `WIP` bit indicates a write in progress (sometimes called the busy bit).
    pub const STATUS_WIP: u8 = 0x01;
    /// The `WEL` bit is the write enable latch.
    pub const STATUS_WEL: u8 = 0x02;

    /// Prepare an opcode and address buffer according to the address_mode.
    fn opcode_with_address(&self, opcode: u8, address: u32) -> Result<Vec<u8>> {
        ensure!(
            address < self.size,
            Error::AddressOutOfBounds(address, self.size)
        );
        let mut buf = vec![opcode];
        if self.address_mode == AddressMode::Mode4b {
            buf.push((address >> 24) as u8);
        }
        buf.push((address >> 16) as u8);
        buf.push((address >> 8) as u8);
        buf.push(address as u8);
        Ok(buf)
    }

    /// Read `length` bytes of the JEDEC ID from the `spi` target.
    pub fn read_jedec_id(spi: &dyn Target, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_ID]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf)
    }

    /// Read status register from the `spi` target.
    pub fn read_status(spi: &dyn Target) -> Result<u8> {
        let mut buf = [0u8; 1];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_STATUS]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf[0])
    }

    /// Poll the status register waiting for the busy bit to clear.
    pub fn wait_for_busy_clear(spi: &dyn Target) -> Result<()> {
        while SpiFlash::read_status(spi)? & SpiFlash::STATUS_WIP != 0 {
            // Do nothing.
        }
        Ok(())
    }

    /// Send the WRITE_ENABLE opcode to the `spi` target.
    pub fn set_write_enable(spi: &dyn Target) -> Result<()> {
        let wren = [SpiFlash::WRITE_ENABLE];
        spi.run_transaction(&mut [Transfer::Write(&wren)])?;
        Ok(())
    }

    /// Send the WRITE_DISABLE opcode to the `spi` target.
    pub fn set_write_disable(spi: &dyn Target) -> Result<()> {
        let wrdi = [SpiFlash::WRITE_DISABLE];
        spi.run_transaction(&mut [Transfer::Write(&wrdi)])?;
        Ok(())
    }

    /// Read and parse the SFDP table from the `spi` target.
    pub fn read_sfdp(spi: &dyn Target) -> Result<Sfdp> {
        let mut buf = vec![0u8; 256];
        let mut tries = 0;
        loop {
            spi.run_transaction(&mut [
                // READ_SFDP always takes a 3-byte address followed by a dummy
                // byte regardless of address mode.  To simplify, we always
                // read from address zero.
                Transfer::Write(&[SpiFlash::READ_SFDP, 0, 0, 0, 0]),
                Transfer::Read(&mut buf),
            ])?;

            // We only want to give SFDP parsing one extra chance for length
            // extension. If parsing fails a second time, just return the error.
            let result = Sfdp::try_from(&buf[..]);
            if result.is_ok() || tries > 0 {
                return result;
            }
            buf.resize(Sfdp::length_required(&buf)?, 0);
            tries += 1;
        }
    }

    /// Create a new `SpiFlash` instance from an SFDP table.
    pub fn from_sfdp(sfdp: Sfdp) -> Self {
        let (erase_sz, erase_op) = match sfdp.jedec.block_erase_size {
            BlockEraseSize::Block4KiB => (4096, sfdp.jedec.erase_opcode_4kib),
            _ => (sfdp.jedec.sector[0].size, sfdp.jedec.sector[0].erase_opcode),
        };
        SpiFlash {
            size: sfdp.jedec.density,
            erase_size: erase_sz,
            erase_opcode: erase_op,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::from(sfdp.jedec.address_modes),
            sfdp: Some(sfdp),
        }
    }

    /// Create a new `SpiFlash` instance by reading an SFDP table from the `spi` Target.
    pub fn from_spi(spi: &dyn Target) -> Result<Self> {
        let sfdp = SpiFlash::read_sfdp(spi)?;
        Ok(SpiFlash::from_sfdp(sfdp))
    }

    /// Set the SPI flash addressing mode to either 3b or 4b mode.
    pub fn set_address_mode(&mut self, spi: &dyn Target, mode: AddressMode) -> Result<()> {
        let opcode = [match mode {
            AddressMode::Mode3b => SpiFlash::EXIT_4B,
            AddressMode::Mode4b => SpiFlash::ENTER_4B,
        }];
        spi.run_transaction(&mut [Transfer::Write(&opcode)])?;
        self.address_mode = mode;
        Ok(())
    }

    /// Automatically set the addressing mode based on the size of the SPI flash.
    pub fn set_address_mode_auto(&mut self, spi: &dyn Target) -> Result<()> {
        self.set_address_mode(
            spi,
            if self.size <= 16 * 1024 * 1024 {
                AddressMode::Mode3b
            } else {
                AddressMode::Mode4b
            },
        )
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    pub fn read(&self, spi: &dyn Target, address: u32, buffer: &mut [u8]) -> Result<()> {
        self.read_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    /// The `progress` callback will be invoked after each chunk of the read operation.
    pub fn read_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &mut [u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        // Break the read up according to the maximum chunksize the backend can handle.
        for chunk in buffer.chunks_mut(spi.max_chunk_size()?) {
            let op_addr = self.opcode_with_address(SpiFlash::READ, address)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr), Transfer::Read(chunk)])?;
            address += chunk.len() as u32;
            progress(address, chunk.len() as u32);
        }
        Ok(())
    }

    /// Erase the entire EEPROM via the CHIP_ERASE opcode.
    pub fn chip_erase(&self, spi: &dyn Target) -> Result<()> {
        Self::set_write_enable(spi)?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::CHIP_ERASE])])?;
        Self::wait_for_busy_clear(spi)?;
        Ok(())
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    pub fn erase(&self, spi: &dyn Target, address: u32, length: u32) -> Result<()> {
        self.erase_with_progress(spi, address, length, |_, _| {})
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    /// The `progress` callback will be invoked after each chunk of the erase operation.
    pub fn erase_with_progress(
        &self,
        spi: &dyn Target,
        address: u32,
        length: u32,
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        if address % self.erase_size != 0 {
            return Err(Error::BadEraseAddress(address, self.erase_size).into());
        }
        if length % self.erase_size != 0 {
            return Err(Error::BadEraseLength(length, self.erase_size).into());
        }
        let end = address + length;
        for addr in (address..end).step_by(self.erase_size as usize) {
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the erase transaction.
            let op_addr = self.opcode_with_address(SpiFlash::SECTOR_ERASE, addr)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr)])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            progress(addr, self.erase_size);
        }
        Ok(())
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    pub fn program(&self, spi: &dyn Target, address: u32, buffer: &[u8]) -> Result<()> {
        self.program_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    /// The `progress` callback will be invoked after each chunk of the program operation.
    pub fn program_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &[u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        let mut remain = buffer.len();
        let mut chunkstart = 0usize;
        while remain != 0 {
            // If the address isn't program-page-size aligned, adjust the first
            // chunk so that subsequent writes will be so-aligned.
            // This is necessary because the SPI eeprom will wrap within the
            // programming page and the resultant data in the eeprom will not
            // be what you intended.
            let chunk = (self.program_size - (address % self.program_size)) as usize;
            let chunk = std::cmp::min(chunk, remain);
            let chunkend = chunkstart + chunk;
            let op_addr = self.opcode_with_address(SpiFlash::PAGE_PROGRAM, address)?;
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the program operation.
            spi.run_transaction(&mut [
                Transfer::Write(&op_addr),
                Transfer::Write(&buffer[chunkstart..chunkend]),
            ])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            address += chunk as u32;
            chunkstart += chunk;
            remain -= chunk;
            progress(address, chunk as u32);
        }
        Ok(())
    }

    /// Send the software reset sequence to the `spi` target.
    pub fn chip_reset(spi: &dyn Target) -> Result<()> {
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET_ENABLE])])?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET])])?;
        Ok(())
    }
}
<|endoftext|>


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

//! Values that should be shared across all modules, without necessarily
//! having to pass them all over the place, but aren't consensus values.
//! should be used sparingly.

/// An enum collecting sets of parameters used throughout the
/// code wherever mining is needed. This should allow for
/// different sets of parameters for different purposes,
/// e.g. CI, User testing, production values

use std::sync::RwLock;
use consensus::PROOFSIZE;
use consensus::DEFAULT_SIZESHIFT;
use consensus::COINBASE_MATURITY;
use consensus::{BLOCK_TIME_SEC, CUT_THROUGH_HORIZON, DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY,
                MEDIAN_TIME_WINDOW};
use core::target::Difficulty;
use consensus::TargetError;

/// Define these here, as they should be developer-set, not really tweakable
/// by users

/// Automated testing sizeshift
pub const AUTOMATED_TESTING_SIZESHIFT: u8 = 10;

/// Automated testing proof size
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 4;

/// User testing sizeshift
pub const USER_TESTING_SIZESHIFT: u8 = 16;

/// User testing proof size
pub const USER_TESTING_PROOF_SIZE: usize = 42;

/// Automated testing coinbase maturity
pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3;

/// User testing coinbase maturity
pub const USER_TESTING_COINBASE_MATURITY: u64 = 3;

/// Testing cut through horizon in blocks
pub const TESTING_CUT_THROUGH_HORIZON: u32 = 20;

/// Testing initial block difficulty
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;

/// Testing initial block difficulty, testnet 2
/// we want to overestimate here as well
/// Setting to 1 for development, but should be 1000 at T2 launch
pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1;

/// The target is the 32-bytes hash block hashes must be lower than.
pub const MAX_PROOF_TARGET: [u8; 8] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// We want to slow this right down for user testing at cuckoo 16, so pick a
/// smaller max
pub const MAX_PROOF_TARGET_TESTING: [u8; 8] = [0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainTypes {
	/// For CI testing
	AutomatedTesting,

	/// For User testing
	UserTesting,

	/// First test network
	Testnet1,

	/// Second test network
	Testnet2,

	/// Main production network
	Mainnet,
}

impl Default for ChainTypes {
	fn default() -> ChainTypes {
		ChainTypes::UserTesting
	}
}

lazy_static!{
	/// The mining parameter mode
	pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
			RwLock::new(ChainTypes::Mainnet);
}

/// Set the mining mode
pub fn set_mining_mode(mode: ChainTypes) {
	let mut param_ref = CHAIN_TYPE.write().unwrap();
	*param_ref = mode;
}

/// The sizeshift
pub fn sizeshift() -> u8 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
		ChainTypes::UserTesting => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet1 => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet2 => DEFAULT_SIZESHIFT,
		ChainTypes::Mainnet => DEFAULT_SIZESHIFT,
	}
}

/// The proofsize
pub fn proofsize() -> usize {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
		ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
		ChainTypes::Testnet1 => PROOFSIZE,
		ChainTypes::Testnet2 => PROOFSIZE,
		ChainTypes::Mainnet => PROOFSIZE,
	}
}

/// Coinbase maturity
pub fn coinbase_maturity() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
		ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
		ChainTypes::Testnet1 => COINBASE_MATURITY,
		ChainTypes::Testnet2 => COINBASE_MATURITY,
		ChainTypes::Mainnet => COINBASE_MATURITY,
	}
}

/// Max Proof Target
pub fn max_proof_target() -> [u8; 8] {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::UserTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet1 => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet2 => MAX_PROOF_TARGET,
		ChainTypes::Mainnet => MAX_PROOF_TARGET,
	}
}

/// Initial mining difficulty
pub fn initial_block_difficulty() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet1 => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet2 => TESTNET2_INITIAL_DIFFICULTY,
		ChainTypes::Mainnet => INITIAL_DIFFICULTY,
	}
}

/// Horizon at which we can cut-through and do full local pruning
pub fn cut_through_horizon() -> u32 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_CUT_THROUGH_HORIZON,
		ChainTypes::UserTesting => TESTING_CUT_THROUGH_HORIZON,
		ChainTypes::Testnet1 => CUT_THROUGH_HORIZON,
		ChainTypes::Testnet2 => CUT_THROUGH_HORIZON,
		ChainTypes::Mainnet => CUT_THROUGH_HORIZON,
	}
}

/// Are we in automated testing mode?
pub fn is_automated_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::AutomatedTesting == *param_ref
}

/// Are we in user testing mode?
pub fn is_user_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::UserTesting == *param_ref
}

/// Are we in production mode (a live public network)?
pub fn is_production_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::Testnet1 == *param_ref || ChainTypes::Testnet2 == *param_ref
		|| ChainTypes::Mainnet == *param_ref
}

/// Helper function to get a nonce known to create a valid POW on
/// the genesis block, to prevent it taking ages. Should be fine for now
/// as the genesis block POW solution turns out to be the same for every new
/// block chain at the moment
pub fn get_genesis_nonce() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		// won't make a difference
		ChainTypes::AutomatedTesting => 0,
		// Magic nonce for current genesis block at cuckoo16
		ChainTypes::UserTesting => 27944,
		// Magic nonce for genesis block for testnet2 (cuckoo30)
		_ => panic!("Pre-set"),
	}
}

/// Converts an iterator of block difficulty data to more a more mangeable vector and pads
/// if needed (which will) only be needed for the first few blocks after genesis

pub fn difficulty_data_to_vector<T>(cursor: T) -> Vec<Result<(u64, Difficulty), TargetError>>
where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>,
{
	// Convert iterator to vector, so we can append to it if necessary
	let needed_block_count = (MEDIAN_TIME_WINDOW + DIFFICULTY_ADJUST_WINDOW) as usize;
	let mut last_n: Vec<Result<(u64, Difficulty), TargetError>> =
		cursor.into_iter().take(needed_block_count).collect();

	// Sort blocks from earliest to latest (to keep conceptually easier)
	last_n.reverse();
	// Only needed just after blockchain launch... basically ensures there's
	// always enough data by simulating perfectly timed pre-genesis
	// blocks at the genesis difficulty as needed.
	let block_count_difference = needed_block_count - last_n.len();
	if block_count_difference > 0 {
		// Collect any real data we have
		let mut live_intervals: Vec<(u64, Difficulty)> = last_n
			.iter()
			.map(|b| (b.clone().unwrap().0, b.clone().unwrap().1))
			.collect();
		for i in (1..live_intervals.len()).rev() {
			// prevents issues with very fast automated test chains
			if live_intervals[i - 1].0 > live_intervals[i].0 {
				live_intervals[i].0 = 0;
			} else {
				live_intervals[i].0 = live_intervals[i].0 - live_intervals[i - 1].0;
			}
		}
		//
		// Remove genesis "interval"
		if live_intervals.len() > 1 {
			live_intervals.remove(0);
		} else {
			//if it's just genesis, adjust the interval
			live_intervals[0].0 = BLOCK_TIME_SEC;
		}
		let mut interval_index = live_intervals.len() - 1;
		let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0;
		// fill in simulated blocks, repeating whatever pattern we've obtained from
		// real data
		// if we have, say, 15 blocks so far with intervals of I1..I15, then
		// the 71-15=56 pre genesis blocks will have
		// intervals/difficulties I1..I15 I1..I15 I1..I15 I1..I11
		for _ in 0..block_count_difference {
			last_ts = last_ts - live_intervals[interval_index].0;
			let last_diff = &live_intervals[interval_index].1;
			last_n.insert(0, Ok((last_ts, last_diff.clone())));
			interval_index = match interval_index {
				0 => live_intervals.len() - 1,
				_ => interval_index - 1,
			};
		}
	}
	last_n
}
<commit_msg>Fix difficulty calc for short chains<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Values that should be shared across all modules, without necessarily
//! having to pass them all over the place, but aren't consensus values.
//! should be used sparingly.

/// An enum collecting sets of parameters used throughout the
/// code wherever mining is needed. This should allow for
/// different sets of parameters for different purposes,
/// e.g. CI, User testing, production values

use std::sync::RwLock;
use consensus::PROOFSIZE;
use consensus::DEFAULT_SIZESHIFT;
use consensus::COINBASE_MATURITY;
use consensus::{BLOCK_TIME_SEC, CUT_THROUGH_HORIZON, DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY,
                MEDIAN_TIME_WINDOW};
use core::target::Difficulty;
use consensus::TargetError;

/// Define these here, as they should be developer-set, not really tweakable
/// by users

/// Automated testing sizeshift
pub const AUTOMATED_TESTING_SIZESHIFT: u8 = 10;

/// Automated testing proof size
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 4;

/// User testing sizeshift
pub const USER_TESTING_SIZESHIFT: u8 = 16;

/// User testing proof size
pub const USER_TESTING_PROOF_SIZE: usize = 42;

/// Automated testing coinbase maturity
pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3;

/// User testing coinbase maturity
pub const USER_TESTING_COINBASE_MATURITY: u64 = 3;

/// Testing cut through horizon in blocks
pub const TESTING_CUT_THROUGH_HORIZON: u32 = 20;

/// Testing initial block difficulty
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;

/// Testing initial block difficulty, testnet 2
/// we want to overestimate here as well
/// Setting to 1 for development, but should be 1000 at T2 launch
pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1;

/// The target is the 32-bytes hash block hashes must be lower than.
pub const MAX_PROOF_TARGET: [u8; 8] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// We want to slow this right down for user testing at cuckoo 16, so pick a
/// smaller max
pub const MAX_PROOF_TARGET_TESTING: [u8; 8] = [0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainTypes {
	/// For CI testing
	AutomatedTesting,

	/// For User testing
	UserTesting,

	/// First test network
	Testnet1,

	/// Second test network
	Testnet2,

	/// Main production network
	Mainnet,
}

impl Default for ChainTypes {
	fn default() -> ChainTypes {
		ChainTypes::UserTesting
	}
}

lazy_static!{
	/// The mining parameter mode
	pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
			RwLock::new(ChainTypes::Mainnet);
}

/// Set the mining mode
pub fn set_mining_mode(mode: ChainTypes) {
	let mut param_ref = CHAIN_TYPE.write().unwrap();
	*param_ref = mode;
}

/// The sizeshift
pub fn sizeshift() -> u8 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
		ChainTypes::UserTesting => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet1 => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet2 => DEFAULT_SIZESHIFT,
		ChainTypes::Mainnet => DEFAULT_SIZESHIFT,
	}
}

/// The proofsize
pub fn proofsize() -> usize {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
		ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
		ChainTypes::Testnet1 => PROOFSIZE,
		ChainTypes::Testnet2 => PROOFSIZE,
		ChainTypes::Mainnet => PROOFSIZE,
	}
}

/// Coinbase maturity
pub fn coinbase_maturity() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
		ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
		ChainTypes::Testnet1 => COINBASE_MATURITY,
		ChainTypes::Testnet2 => COINBASE_MATURITY,
		ChainTypes::Mainnet => COINBASE_MATURITY,
	}
}

/// Max Proof Target
pub fn max_proof_target() -> [u8; 8] {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::UserTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet1 => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet2 => MAX_PROOF_TARGET,
		ChainTypes::Mainnet => MAX_PROOF_TARGET,
	}
}

/// Initial mining difficulty
pub fn initial_block_difficulty() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet1 => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet2 => TESTNET2_INITIAL_DIFFICULTY,
		ChainTypes::Mainnet => INITIAL_DIFFICULTY,
	}
}

/// Horizon at which we can cut-through and do full local pruning
pub fn cut_through_horizon() -> u32 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_CUT_THROUGH_HORIZON,
		ChainTypes::UserTesting => TESTING_CUT_THROUGH_HORIZON,
		ChainTypes::Testnet1 => CUT_THROUGH_HORIZON,
		ChainTypes::Testnet2 => CUT_THROUGH_HORIZON,
		ChainTypes::Mainnet => CUT_THROUGH_HORIZON,
	}
}

/// Are we in automated testing mode?
pub fn is_automated_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::AutomatedTesting == *param_ref
}

/// Are we in user testing mode?
pub fn is_user_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::UserTesting == *param_ref
}

/// Are we in production mode (a live public network)?
pub fn is_production_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::Testnet1 == *param_ref || ChainTypes::Testnet2 == *param_ref
		|| ChainTypes::Mainnet == *param_ref
}

/// Helper function to get a nonce known to create a valid POW on
/// the genesis block, to prevent it taking ages. Should be fine for now
/// as the genesis block POW solution turns out to be the same for every new
/// block chain at the moment
pub fn get_genesis_nonce() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		// won't make a difference
		ChainTypes::AutomatedTesting => 0,
		// Magic nonce for current genesis block at cuckoo16
		ChainTypes::UserTesting => 27944,
		// Magic nonce for genesis block for testnet2 (cuckoo30)
		_ => panic!("Pre-set"),
	}
}

/// Converts an iterator of block difficulty data to more a more mangeable vector and pads
/// if needed (which will) only be needed for the first few blocks after genesis

pub fn difficulty_data_to_vector<T>(cursor: T) -> Vec<Result<(u64, Difficulty), TargetError>>
where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>,
{
	// Convert iterator to vector, so we can append to it if necessary
	let needed_block_count = (MEDIAN_TIME_WINDOW + DIFFICULTY_ADJUST_WINDOW) as usize;
	let mut last_n: Vec<Result<(u64, Difficulty), TargetError>> =
		cursor.into_iter().take(needed_block_count).collect();

	// Sort blocks from earliest to latest (to keep conceptually easier)
	last_n.reverse();
	// Only needed just after blockchain launch... basically ensures there's
	// always enough data by simulating perfectly timed pre-genesis
	// blocks at the genesis difficulty as needed.
	let block_count_difference = needed_block_count - last_n.len();
	if block_count_difference > 0 {
		// Collect any real data we have
		let mut live_intervals: Vec<(u64, Difficulty)> = last_n
			.iter()
			.map(|b| (b.clone().unwrap().0, b.clone().unwrap().1))
			.collect();
		for i in (1..live_intervals.len()).rev() {
			// prevents issues with very fast automated test chains
			if live_intervals[i - 1].0 > live_intervals[i].0 {
				live_intervals[i].0 = 0;
			} else {
				live_intervals[i].0 = live_intervals[i].0 - live_intervals[i - 1].0;
			}
		}
		//
		// Remove genesis "interval"
		if live_intervals.len() > 1 {
			live_intervals.remove(0);
		} else {
			//if it's just genesis, adjust the interval
			live_intervals[0].0 = BLOCK_TIME_SEC;
		}
		let mut interval_index = live_intervals.len() - 1;
		let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0;
		// fill in simulated blocks, repeating whatever pattern we've obtained from
		// real data
		// if we have, say, 15 blocks so far with intervals of I1..I15, then
		// the 71-15=56 pre genesis blocks will have
		// intervals/difficulties I1..I15 I1..I15 I1..I15 I1..I11
		for _ in 0..block_count_difference {
			last_ts = last_ts.saturating_sub(live_intervals[interval_index].0);
			let last_diff = &live_intervals[interval_index].1;
			last_n.insert(0, Ok((last_ts, last_diff.clone())));
			interval_index = match interval_index {
				0 => live_intervals.len() - 1,
				_ => interval_index - 1,
			};
		}
	}
	last_n
}
<|endoftext|>


<commit_before>use std::fmt;
use terminal::config::{ConfigPart, escape_config_string};

/// One input filter element.
///
/// `both`s are equivalent in effect to `+`s -- let through both keypresses and keyreleases.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilter {
	Event{name: InputFilterEvent, both: bool},
	Group{group: InputFilterGroup, both: bool},
	Alnum{keys: String, both: bool},
}

/// From [here](http://foo.wyrd.name/en:bearlibterminal:reference:input#inputfilter).
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilterGroup {
	Arrow,
	Keypad,
	Keyboard,
	Mouse,
	/// Close + Resized
	System,
}

// As enumerated [here](foo.wyrd.name/en:bearlibterminal:reference:input#event_and_state_constants)
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilterEvent {
	A,
	B,
	C,
	D,
	E,
	F,
	G,
	H,
	I,
	J,
	K,
	L,
	M,
	N,
	O,
	P,
	Q,
	R,
	S,
	T,
	U,
	V,
	W,
	X,
	Y,
	Z,
	Row0,
	Row1,
	Row2,
	Row3,
	Row4,
	Row5,
	Row6,
	Row7,
	Row8,
	Row9,
	Space,
	Minus,
	Equals,
	LBracket,
	RBracket,
	Backslash,
	Semicolon,
	Apostrophe,
	Grave,
	Comma,
	Period,
	Slash,
	F1,
	F2,
	F3,
	F4,
	F5,
	F6,
	F7,
	F8,
	F9,
	F10,
	F11,
	F12,
	Return,
	Escape,
	Backspace,
	Tab,
	Pause,
	Insert,
	Home,
	Pageup,
	Delete,
	End,
	Pagedown,
	Right,
	Left,
	Down,
	Up,
	Shift,
	Control,
	Pad0,
	Pad1,
	Pad2,
	Pad3,
	Pad4,
	Pad5,
	Pad6,
	Pad7,
	Pad8,
	Pad9,
	PadDivide,
	PadMultiply,
	PadMinus,
	PadPlus,
	PadPeriod,
	PadEnter,
	MouseLeft,
	MouseRight,
	MouseMiddle,
	MouseX1,
	MouseX2,
	MouseMove,
	MouseScroll,
	MouseWheel,
	MouseX,
	MouseY,
	MousePixelX,
	MousePixelY,
	MouseClicks,
	Width,
	Height,
	CellWidth,
	CellHeight,
	Color,
	Bkcolor,
	Layer,
	Composition,
	Char,
	Wchar,
	Event,
	Fullscreen,
	Close,
	Resized,
}

impl ConfigPart for Vec<InputFilter> {
	fn to_config_str(&self) -> String {
		escape_config_string(&format!("[{}]", {
			let mut elems = "".to_string();
			for filter in self {
				elems = format!("{}{}, ", elems, match filter {
					&InputFilter::Event{ref name,  both} => format!("{}{}", name,  if both {"+"} else {""}),
					&InputFilter::Group{ref group, both} => format!("{}{}", group, if both {"+"} else {""}),
					&InputFilter::Alnum{ref keys,  both} => format!("{}{}", keys,  if both {"+"} else {""}),
				});
			}
			elems.pop();
			elems.pop();
			elems
		}))
	}
}

impl fmt::Display for InputFilterGroup {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str(match self {
			&InputFilterGroup::Arrow    => "arrow",
			&InputFilterGroup::Keypad   => "keypad",
			&InputFilterGroup::Keyboard => "keyboard",
			&InputFilterGroup::Mouse    => "mouse",
			&InputFilterGroup::System   => "system",
		})
	}
}

impl fmt::Display for InputFilterEvent {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str(match self {
			&InputFilterEvent::A           => "A",
			&InputFilterEvent::B           => "B",
			&InputFilterEvent::C           => "C",
			&InputFilterEvent::D           => "D",
			&InputFilterEvent::E           => "E",
			&InputFilterEvent::F           => "F",
			&InputFilterEvent::G           => "G",
			&InputFilterEvent::H           => "H",
			&InputFilterEvent::I           => "I",
			&InputFilterEvent::J           => "J",
			&InputFilterEvent::K           => "K",
			&InputFilterEvent::L           => "L",
			&InputFilterEvent::M           => "M",
			&InputFilterEvent::N           => "N",
			&InputFilterEvent::O           => "O",
			&InputFilterEvent::P           => "P",
			&InputFilterEvent::Q           => "Q",
			&InputFilterEvent::R           => "R",
			&InputFilterEvent::S           => "S",
			&InputFilterEvent::T           => "T",
			&InputFilterEvent::U           => "U",
			&InputFilterEvent::V           => "V",
			&InputFilterEvent::W           => "W",
			&InputFilterEvent::X           => "X",
			&InputFilterEvent::Y           => "Y",
			&InputFilterEvent::Z           => "Z",
			&InputFilterEvent::Row0        => "0",
			&InputFilterEvent::Row1        => "1",
			&InputFilterEvent::Row2        => "2",
			&InputFilterEvent::Row3        => "3",
			&InputFilterEvent::Row4        => "4",
			&InputFilterEvent::Row5        => "5",
			&InputFilterEvent::Row6        => "6",
			&InputFilterEvent::Row7        => "7",
			&InputFilterEvent::Row8        => "8",
			&InputFilterEvent::Row9        => "9",
			&InputFilterEvent::Space       => "space",
			&InputFilterEvent::Minus       => "minus",
			&InputFilterEvent::Equals      => "equals",
			&InputFilterEvent::LBracket    => "lbracket",
			&InputFilterEvent::RBracket    => "rbracket",
			&InputFilterEvent::Backslash   => "backslash",
			&InputFilterEvent::Semicolon   => "semicolon",
			&InputFilterEvent::Apostrophe  => "apostrophe",
			&InputFilterEvent::Grave       => "grave",
			&InputFilterEvent::Comma       => "comma",
			&InputFilterEvent::Period      => "period",
			&InputFilterEvent::Slash       => "slash",
			&InputFilterEvent::F1          => "F1",
			&InputFilterEvent::F2          => "F2",
			&InputFilterEvent::F3          => "F3",
			&InputFilterEvent::F4          => "F4",
			&InputFilterEvent::F5          => "F5",
			&InputFilterEvent::F6          => "F6",
			&InputFilterEvent::F7          => "F7",
			&InputFilterEvent::F8          => "F8",
			&InputFilterEvent::F9          => "F9",
			&InputFilterEvent::F10         => "F10",
			&InputFilterEvent::F11         => "F11",
			&InputFilterEvent::F12         => "F12",
			&InputFilterEvent::Return      => "return",
			&InputFilterEvent::Escape      => "escape",
			&InputFilterEvent::Backspace   => "backspace",
			&InputFilterEvent::Tab         => "tab",
			&InputFilterEvent::Pause       => "pause",
			&InputFilterEvent::Insert      => "insert",
			&InputFilterEvent::Home        => "home",
			&InputFilterEvent::Pageup      => "pageup",
			&InputFilterEvent::Delete      => "delete",
			&InputFilterEvent::End         => "end",
			&InputFilterEvent::Pagedown    => "pagedown",
			&InputFilterEvent::Right       => "right",
			&InputFilterEvent::Left        => "left",
			&InputFilterEvent::Down        => "down",
			&InputFilterEvent::Up          => "up",
			&InputFilterEvent::Shift       => "shift",
			&InputFilterEvent::Control     => "control",
			&InputFilterEvent::Pad0        => "KP_0",
			&InputFilterEvent::Pad1        => "KP_1",
			&InputFilterEvent::Pad2        => "KP_2",
			&InputFilterEvent::Pad3        => "KP_3",
			&InputFilterEvent::Pad4        => "KP_4",
			&InputFilterEvent::Pad5        => "KP_5",
			&InputFilterEvent::Pad6        => "KP_6",
			&InputFilterEvent::Pad7        => "KP_7",
			&InputFilterEvent::Pad8        => "KP_8",
			&InputFilterEvent::Pad9        => "KP_9",
			&InputFilterEvent::PadDivide   => "KP_divide",
			&InputFilterEvent::PadMultiply => "KP_multiply",
			&InputFilterEvent::PadMinus    => "KP_minus",
			&InputFilterEvent::PadPlus     => "KP_plus",
			&InputFilterEvent::PadPeriod   => "KP_period",
			&InputFilterEvent::PadEnter    => "KP_enter",
			&InputFilterEvent::MouseLeft   => "mouse_left",
			&InputFilterEvent::MouseRight  => "mouse_right",
			&InputFilterEvent::MouseMiddle => "mouse_middle",
			&InputFilterEvent::MouseX1     => "mouse_x1",
			&InputFilterEvent::MouseX2     => "mouse_x2",
			&InputFilterEvent::MouseMove   => "mouse_move",
			&InputFilterEvent::MouseScroll => "mouse_scroll",
			&InputFilterEvent::MouseWheel  => "mouse_wheel",
			&InputFilterEvent::MouseX      => "mouse_x",
			&InputFilterEvent::MouseY      => "mouse_y",
			&InputFilterEvent::MousePixelX => "mouse_pixelx",
			&InputFilterEvent::MousePixelY => "mouse_pixely",
			&InputFilterEvent::MouseClicks => "mouse_clicks",
			&InputFilterEvent::Width       => "width",
			&InputFilterEvent::Height      => "height",
			&InputFilterEvent::CellWidth   => "cell_width",
			&InputFilterEvent::CellHeight  => "cell_height",
			&InputFilterEvent::Color       => "color",
			&InputFilterEvent::Bkcolor     => "bkcolor",
			&InputFilterEvent::Layer       => "layer",
			&InputFilterEvent::Composition => "composition",
			&InputFilterEvent::Char        => "char",
			&InputFilterEvent::Wchar       => "wchar",
			&InputFilterEvent::Event       => "event",
			&InputFilterEvent::Fullscreen  => "fullscreen",
			&InputFilterEvent::Close       => "close",
			&InputFilterEvent::Resized     => "resized",
		})
	}
}
<commit_msg>Actually add the assignment prop<commit_after>use std::fmt;
use terminal::config::{ConfigPart, escape_config_string};

/// One input filter element.
///
/// `both`s are equivalent in effect to `+`s -- let through both keypresses and keyreleases.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilter {
	Event{name: InputFilterEvent, both: bool},
	Group{group: InputFilterGroup, both: bool},
	Alnum{keys: String, both: bool},
}

/// From [here](http://foo.wyrd.name/en:bearlibterminal:reference:input#inputfilter).
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilterGroup {
	Arrow,
	Keypad,
	Keyboard,
	Mouse,
	/// Close + Resized
	System,
}

// As enumerated [here](foo.wyrd.name/en:bearlibterminal:reference:input#event_and_state_constants)
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum InputFilterEvent {
	A,
	B,
	C,
	D,
	E,
	F,
	G,
	H,
	I,
	J,
	K,
	L,
	M,
	N,
	O,
	P,
	Q,
	R,
	S,
	T,
	U,
	V,
	W,
	X,
	Y,
	Z,
	Row0,
	Row1,
	Row2,
	Row3,
	Row4,
	Row5,
	Row6,
	Row7,
	Row8,
	Row9,
	Space,
	Minus,
	Equals,
	LBracket,
	RBracket,
	Backslash,
	Semicolon,
	Apostrophe,
	Grave,
	Comma,
	Period,
	Slash,
	F1,
	F2,
	F3,
	F4,
	F5,
	F6,
	F7,
	F8,
	F9,
	F10,
	F11,
	F12,
	Return,
	Escape,
	Backspace,
	Tab,
	Pause,
	Insert,
	Home,
	Pageup,
	Delete,
	End,
	Pagedown,
	Right,
	Left,
	Down,
	Up,
	Shift,
	Control,
	Pad0,
	Pad1,
	Pad2,
	Pad3,
	Pad4,
	Pad5,
	Pad6,
	Pad7,
	Pad8,
	Pad9,
	PadDivide,
	PadMultiply,
	PadMinus,
	PadPlus,
	PadPeriod,
	PadEnter,
	MouseLeft,
	MouseRight,
	MouseMiddle,
	MouseX1,
	MouseX2,
	MouseMove,
	MouseScroll,
	MouseWheel,
	MouseX,
	MouseY,
	MousePixelX,
	MousePixelY,
	MouseClicks,
	Width,
	Height,
	CellWidth,
	CellHeight,
	Color,
	Bkcolor,
	Layer,
	Composition,
	Char,
	Wchar,
	Event,
	Fullscreen,
	Close,
	Resized,
}

impl ConfigPart for Vec<InputFilter> {
	fn to_config_str(&self) -> String {
		format!("input.filter = [{}];", {
			let mut elems = "".to_string();
			for filter in self {
				elems = format!("{}{}, ", elems, escape_config_string(&match filter {
					&InputFilter::Event{ref name,  both} => format!("{}{}", name,  if both {"+"} else {""}),
					&InputFilter::Group{ref group, both} => format!("{}{}", group, if both {"+"} else {""}),
					&InputFilter::Alnum{ref keys,  both} => format!("{}{}", keys,  if both {"+"} else {""}),
				}));
			}
			elems.pop();
			elems.pop();
			elems
		})
	}
}

impl fmt::Display for InputFilterGroup {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str(match self {
			&InputFilterGroup::Arrow    => "arrow",
			&InputFilterGroup::Keypad   => "keypad",
			&InputFilterGroup::Keyboard => "keyboard",
			&InputFilterGroup::Mouse    => "mouse",
			&InputFilterGroup::System   => "system",
		})
	}
}

impl fmt::Display for InputFilterEvent {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str(match self {
			&InputFilterEvent::A           => "A",
			&InputFilterEvent::B           => "B",
			&InputFilterEvent::C           => "C",
			&InputFilterEvent::D           => "D",
			&InputFilterEvent::E           => "E",
			&InputFilterEvent::F           => "F",
			&InputFilterEvent::G           => "G",
			&InputFilterEvent::H           => "H",
			&InputFilterEvent::I           => "I",
			&InputFilterEvent::J           => "J",
			&InputFilterEvent::K           => "K",
			&InputFilterEvent::L           => "L",
			&InputFilterEvent::M           => "M",
			&InputFilterEvent::N           => "N",
			&InputFilterEvent::O           => "O",
			&InputFilterEvent::P           => "P",
			&InputFilterEvent::Q           => "Q",
			&InputFilterEvent::R           => "R",
			&InputFilterEvent::S           => "S",
			&InputFilterEvent::T           => "T",
			&InputFilterEvent::U           => "U",
			&InputFilterEvent::V           => "V",
			&InputFilterEvent::W           => "W",
			&InputFilterEvent::X           => "X",
			&InputFilterEvent::Y           => "Y",
			&InputFilterEvent::Z           => "Z",
			&InputFilterEvent::Row0        => "0",
			&InputFilterEvent::Row1        => "1",
			&InputFilterEvent::Row2        => "2",
			&InputFilterEvent::Row3        => "3",
			&InputFilterEvent::Row4        => "4",
			&InputFilterEvent::Row5        => "5",
			&InputFilterEvent::Row6        => "6",
			&InputFilterEvent::Row7        => "7",
			&InputFilterEvent::Row8        => "8",
			&InputFilterEvent::Row9        => "9",
			&InputFilterEvent::Space       => "space",
			&InputFilterEvent::Minus       => "minus",
			&InputFilterEvent::Equals      => "equals",
			&InputFilterEvent::LBracket    => "lbracket",
			&InputFilterEvent::RBracket    => "rbracket",
			&InputFilterEvent::Backslash   => "backslash",
			&InputFilterEvent::Semicolon   => "semicolon",
			&InputFilterEvent::Apostrophe  => "apostrophe",
			&InputFilterEvent::Grave       => "grave",
			&InputFilterEvent::Comma       => "comma",
			&InputFilterEvent::Period      => "period",
			&InputFilterEvent::Slash       => "slash",
			&InputFilterEvent::F1          => "F1",
			&InputFilterEvent::F2          => "F2",
			&InputFilterEvent::F3          => "F3",
			&InputFilterEvent::F4          => "F4",
			&InputFilterEvent::F5          => "F5",
			&InputFilterEvent::F6          => "F6",
			&InputFilterEvent::F7          => "F7",
			&InputFilterEvent::F8          => "F8",
			&InputFilterEvent::F9          => "F9",
			&InputFilterEvent::F10         => "F10",
			&InputFilterEvent::F11         => "F11",
			&InputFilterEvent::F12         => "F12",
			&InputFilterEvent::Return      => "return",
			&InputFilterEvent::Escape      => "escape",
			&InputFilterEvent::Backspace   => "backspace",
			&InputFilterEvent::Tab         => "tab",
			&InputFilterEvent::Pause       => "pause",
			&InputFilterEvent::Insert      => "insert",
			&InputFilterEvent::Home        => "home",
			&InputFilterEvent::Pageup      => "pageup",
			&InputFilterEvent::Delete      => "delete",
			&InputFilterEvent::End         => "end",
			&InputFilterEvent::Pagedown    => "pagedown",
			&InputFilterEvent::Right       => "right",
			&InputFilterEvent::Left        => "left",
			&InputFilterEvent::Down        => "down",
			&InputFilterEvent::Up          => "up",
			&InputFilterEvent::Shift       => "shift",
			&InputFilterEvent::Control     => "control",
			&InputFilterEvent::Pad0        => "KP_0",
			&InputFilterEvent::Pad1        => "KP_1",
			&InputFilterEvent::Pad2        => "KP_2",
			&InputFilterEvent::Pad3        => "KP_3",
			&InputFilterEvent::Pad4        => "KP_4",
			&InputFilterEvent::Pad5        => "KP_5",
			&InputFilterEvent::Pad6        => "KP_6",
			&InputFilterEvent::Pad7        => "KP_7",
			&InputFilterEvent::Pad8        => "KP_8",
			&InputFilterEvent::Pad9        => "KP_9",
			&InputFilterEvent::PadDivide   => "KP_divide",
			&InputFilterEvent::PadMultiply => "KP_multiply",
			&InputFilterEvent::PadMinus    => "KP_minus",
			&InputFilterEvent::PadPlus     => "KP_plus",
			&InputFilterEvent::PadPeriod   => "KP_period",
			&InputFilterEvent::PadEnter    => "KP_enter",
			&InputFilterEvent::MouseLeft   => "mouse_left",
			&InputFilterEvent::MouseRight  => "mouse_right",
			&InputFilterEvent::MouseMiddle => "mouse_middle",
			&InputFilterEvent::MouseX1     => "mouse_x1",
			&InputFilterEvent::MouseX2     => "mouse_x2",
			&InputFilterEvent::MouseMove   => "mouse_move",
			&InputFilterEvent::MouseScroll => "mouse_scroll",
			&InputFilterEvent::MouseWheel  => "mouse_wheel",
			&InputFilterEvent::MouseX      => "mouse_x",
			&InputFilterEvent::MouseY      => "mouse_y",
			&InputFilterEvent::MousePixelX => "mouse_pixelx",
			&InputFilterEvent::MousePixelY => "mouse_pixely",
			&InputFilterEvent::MouseClicks => "mouse_clicks",
			&InputFilterEvent::Width       => "width",
			&InputFilterEvent::Height      => "height",
			&InputFilterEvent::CellWidth   => "cell_width",
			&InputFilterEvent::CellHeight  => "cell_height",
			&InputFilterEvent::Color       => "color",
			&InputFilterEvent::Bkcolor     => "bkcolor",
			&InputFilterEvent::Layer       => "layer",
			&InputFilterEvent::Composition => "composition",
			&InputFilterEvent::Char        => "char",
			&InputFilterEvent::Wchar       => "wchar",
			&InputFilterEvent::Event       => "event",
			&InputFilterEvent::Fullscreen  => "fullscreen",
			&InputFilterEvent::Close       => "close",
			&InputFilterEvent::Resized     => "resized",
		})
	}
}
<|endoftext|>


<commit_before><commit_msg>fix(front): Ensure exceprt is rendered before used<commit_after><|endoftext|>