<commit_before>use rustc_hir as hir;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::Node;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::{self, Region, TyCtxt};

/// This function calls the `visit_ty` method for the parameters
/// corresponding to the anonymous regions. The `nested_visitor.found_type`
/// contains the anonymous type.
///
/// # Arguments
/// region - the anonymous region corresponding to the anon_anon conflict
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
///
/// # Example
/// ```
/// fn foo(x: &mut Vec<&u8>, y: &u8)
///    { x.push(y); }
/// ```
/// The function returns the nested type corresponding to the anonymous region
/// for e.g., `&u8` and Vec<`&u8`.
pub(crate) fn find_anon_type(
    tcx: TyCtxt<'tcx>,
    region: Region<'tcx>,
    br: &ty::BoundRegionKind,
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> {
    if let Some(anon_reg) = tcx.is_suitable_region(region) {
        let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
        let fndecl = match tcx.hir().get(hir_id) {
            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
            | Node::TraitItem(&hir::TraitItem {
                kind: hir::TraitItemKind::Fn(ref m, ..), ..
            })
            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => {
                &m.decl
            }
            _ => return None,
        };

        fndecl
            .inputs
            .iter()
            .find_map(|arg| find_component_for_bound_region(tcx, arg, br))
            .map(|ty| (ty, &**fndecl))
    } else {
        None
    }
}

// This method creates a FindNestedTypeVisitor which returns the type corresponding
// to the anonymous region.
fn find_component_for_bound_region(
    tcx: TyCtxt<'tcx>,
    arg: &'tcx hir::Ty<'tcx>,
    br: &ty::BoundRegionKind,
) -> Option<&'tcx hir::Ty<'tcx>> {
    let mut nested_visitor = FindNestedTypeVisitor {
        tcx,
        bound_region: *br,
        found_type: None,
        current_index: ty::INNERMOST,
    };
    nested_visitor.visit_ty(arg);
    nested_visitor.found_type
}

// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
// anonymous region. The example above would lead to a conflict between
// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
// would be invoked twice, once for each lifetime, and would
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct FindNestedTypeVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    // The bound_region corresponding to the Refree(freeregion)
    // associated with the anonymous region we are looking for.
    bound_region: ty::BoundRegionKind,
    // The type where the anonymous lifetime appears
    // for e.g., Vec<`&u8`> and <`&u8`>
    found_type: Option<&'tcx hir::Ty<'tcx>>,
    current_index: ty::DebruijnIndex,
}

impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
    type Map = Map<'tcx>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::OnlyBodies(self.tcx.hir())
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        match arg.kind {
            hir::TyKind::BareFn(_) => {
                self.current_index.shift_in(1);
                intravisit::walk_ty(self, arg);
                self.current_index.shift_out(1);
                return;
            }

            hir::TyKind::TraitObject(bounds, _) => {
                for bound in bounds {
                    self.current_index.shift_in(1);
                    self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                    self.current_index.shift_out(1);
                }
            }

            hir::TyKind::Rptr(ref lifetime, _) => {
                // the lifetime of the TyRptr
                let hir_id = lifetime.hir_id;
                match (self.tcx.named_region(hir_id), self.bound_region) {
                    // Find the index of the anonymous region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
                        ty::BrAnon(br_index),
                    ) => {
                        debug!(
                            "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
                            debruijn_index, anon_index, br_index
                        );
                        if debruijn_index == self.current_index && anon_index == br_index {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                        debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                        if id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBound(debruijn_index, id, _)),
                        ty::BrNamed(def_id, _),
                    ) => {
                        debug!(
                            "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                            debruijn_index
                        );
                        debug!("LateBound id={:?} def_id={:?}", id, def_id);
                        if debruijn_index == self.current_index && id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    (
                        Some(
                            rl::Region::Static
                            | rl::Region::Free(_, _)
                            | rl::Region::EarlyBound(_, _, _)
                            | rl::Region::LateBound(_, _, _)
                            | rl::Region::LateBoundAnon(_, _),
                        )
                        | None,
                        _,
                    ) => {
                        debug!("no arg found");
                    }
                }
            }
            // Checks if it is of type `hir::TyKind::Path` which corresponds to a struct.
            hir::TyKind::Path(_) => {
                let subvisitor = &mut TyPathVisitor {
                    tcx: self.tcx,
                    found_it: false,
                    bound_region: self.bound_region,
                    current_index: self.current_index,
                };
                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
                // this will visit only outermost type
                if subvisitor.found_it {
                    self.found_type = Some(arg);
                }
            }
            _ => {}
        }
        // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
        // go on to visit `&Foo`
        intravisit::walk_ty(self, arg);
    }
}

// The visitor captures the corresponding `hir::Ty` of the anonymous region
// in the case of structs ie. `hir::TyKind::Path`.
// This visitor would be invoked for each lifetime corresponding to a struct,
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct TyPathVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    found_it: bool,
    bound_region: ty::BoundRegionKind,
    current_index: ty::DebruijnIndex,
}

impl Visitor<'tcx> for TyPathVisitor<'tcx> {
    type Map = Map<'tcx>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Map<'tcx>> {
        NestedVisitorMap::OnlyBodies(self.tcx.hir())
    }

    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
        match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
            // the lifetime of the TyPath!
            (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
                if debruijn_index == self.current_index && anon_index == br_index {
                    self.found_it = true;
                    return;
                }
            }

            (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                if id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
                debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
                debug!("id={:?}", id);
                debug!("def_id={:?}", def_id);
                if debruijn_index == self.current_index && id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (
                Some(
                    rl::Region::Static
                    | rl::Region::EarlyBound(_, _, _)
                    | rl::Region::LateBound(_, _, _)
                    | rl::Region::LateBoundAnon(_, _)
                    | rl::Region::Free(_, _),
                )
                | None,
                _,
            ) => {
                debug!("no arg found");
            }
        }
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        // ignore nested types
        //
        // If you have a type like `Foo<'a, &Ty>` we
        // are only interested in the immediate lifetimes ('a).
        //
        // Making `visit_ty` empty will ignore the `&Ty` embedded
        // inside, it will get reached by the outer visitor.
        debug!("`Ty` corresponding to a struct is {:?}", arg);
    }
}
<commit_msg>Rollup merge of #82630 - JohnTitor:fix-typo-in-find-anon-type-doc, r=petrochenkov<commit_after>use rustc_hir as hir;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::Node;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::{self, Region, TyCtxt};

/// This function calls the `visit_ty` method for the parameters
/// corresponding to the anonymous regions. The `nested_visitor.found_type`
/// contains the anonymous type.
///
/// # Arguments
/// region - the anonymous region corresponding to the anon_anon conflict
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
///
/// # Example
/// ```
/// fn foo(x: &mut Vec<&u8>, y: &u8)
///    { x.push(y); }
/// ```
/// The function returns the nested type corresponding to the anonymous region
/// for e.g., `&u8` and `Vec<&u8>`.
pub(crate) fn find_anon_type(
    tcx: TyCtxt<'tcx>,
    region: Region<'tcx>,
    br: &ty::BoundRegionKind,
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> {
    if let Some(anon_reg) = tcx.is_suitable_region(region) {
        let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
        let fndecl = match tcx.hir().get(hir_id) {
            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
            | Node::TraitItem(&hir::TraitItem {
                kind: hir::TraitItemKind::Fn(ref m, ..), ..
            })
            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => {
                &m.decl
            }
            _ => return None,
        };

        fndecl
            .inputs
            .iter()
            .find_map(|arg| find_component_for_bound_region(tcx, arg, br))
            .map(|ty| (ty, &**fndecl))
    } else {
        None
    }
}

// This method creates a FindNestedTypeVisitor which returns the type corresponding
// to the anonymous region.
fn find_component_for_bound_region(
    tcx: TyCtxt<'tcx>,
    arg: &'tcx hir::Ty<'tcx>,
    br: &ty::BoundRegionKind,
) -> Option<&'tcx hir::Ty<'tcx>> {
    let mut nested_visitor = FindNestedTypeVisitor {
        tcx,
        bound_region: *br,
        found_type: None,
        current_index: ty::INNERMOST,
    };
    nested_visitor.visit_ty(arg);
    nested_visitor.found_type
}

// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
// anonymous region. The example above would lead to a conflict between
// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
// would be invoked twice, once for each lifetime, and would
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct FindNestedTypeVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    // The bound_region corresponding to the Refree(freeregion)
    // associated with the anonymous region we are looking for.
    bound_region: ty::BoundRegionKind,
    // The type where the anonymous lifetime appears
    // for e.g., Vec<`&u8`> and <`&u8`>
    found_type: Option<&'tcx hir::Ty<'tcx>>,
    current_index: ty::DebruijnIndex,
}

impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
    type Map = Map<'tcx>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::OnlyBodies(self.tcx.hir())
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        match arg.kind {
            hir::TyKind::BareFn(_) => {
                self.current_index.shift_in(1);
                intravisit::walk_ty(self, arg);
                self.current_index.shift_out(1);
                return;
            }

            hir::TyKind::TraitObject(bounds, _) => {
                for bound in bounds {
                    self.current_index.shift_in(1);
                    self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                    self.current_index.shift_out(1);
                }
            }

            hir::TyKind::Rptr(ref lifetime, _) => {
                // the lifetime of the TyRptr
                let hir_id = lifetime.hir_id;
                match (self.tcx.named_region(hir_id), self.bound_region) {
                    // Find the index of the anonymous region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
                        ty::BrAnon(br_index),
                    ) => {
                        debug!(
                            "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
                            debruijn_index, anon_index, br_index
                        );
                        if debruijn_index == self.current_index && anon_index == br_index {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                        debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                        if id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBound(debruijn_index, id, _)),
                        ty::BrNamed(def_id, _),
                    ) => {
                        debug!(
                            "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                            debruijn_index
                        );
                        debug!("LateBound id={:?} def_id={:?}", id, def_id);
                        if debruijn_index == self.current_index && id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    (
                        Some(
                            rl::Region::Static
                            | rl::Region::Free(_, _)
                            | rl::Region::EarlyBound(_, _, _)
                            | rl::Region::LateBound(_, _, _)
                            | rl::Region::LateBoundAnon(_, _),
                        )
                        | None,
                        _,
                    ) => {
                        debug!("no arg found");
                    }
                }
            }
            // Checks if it is of type `hir::TyKind::Path` which corresponds to a struct.
            hir::TyKind::Path(_) => {
                let subvisitor = &mut TyPathVisitor {
                    tcx: self.tcx,
                    found_it: false,
                    bound_region: self.bound_region,
                    current_index: self.current_index,
                };
                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
                // this will visit only outermost type
                if subvisitor.found_it {
                    self.found_type = Some(arg);
                }
            }
            _ => {}
        }
        // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
        // go on to visit `&Foo`
        intravisit::walk_ty(self, arg);
    }
}

// The visitor captures the corresponding `hir::Ty` of the anonymous region
// in the case of structs ie. `hir::TyKind::Path`.
// This visitor would be invoked for each lifetime corresponding to a struct,
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct TyPathVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    found_it: bool,
    bound_region: ty::BoundRegionKind,
    current_index: ty::DebruijnIndex,
}

impl Visitor<'tcx> for TyPathVisitor<'tcx> {
    type Map = Map<'tcx>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Map<'tcx>> {
        NestedVisitorMap::OnlyBodies(self.tcx.hir())
    }

    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
        match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
            // the lifetime of the TyPath!
            (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
                if debruijn_index == self.current_index && anon_index == br_index {
                    self.found_it = true;
                    return;
                }
            }

            (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                if id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
                debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
                debug!("id={:?}", id);
                debug!("def_id={:?}", def_id);
                if debruijn_index == self.current_index && id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (
                Some(
                    rl::Region::Static
                    | rl::Region::EarlyBound(_, _, _)
                    | rl::Region::LateBound(_, _, _)
                    | rl::Region::LateBoundAnon(_, _)
                    | rl::Region::Free(_, _),
                )
                | None,
                _,
            ) => {
                debug!("no arg found");
            }
        }
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        // ignore nested types
        //
        // If you have a type like `Foo<'a, &Ty>` we
        // are only interested in the immediate lifetimes ('a).
        //
        // Making `visit_ty` empty will ignore the `&Ty` embedded
        // inside, it will get reached by the outer visitor.
        debug!("`Ty` corresponding to a struct is {:?}", arg);
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use rustc::middle::ty;

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

declare_lint!(pub SINGLE_MATCH, Warn,
              "a match statement with a single nontrivial arm (i.e, where the other arm \
               is `_ => {}`) is used; recommends `if let` instead");
declare_lint!(pub MATCH_REF_PATS, Warn,
              "a match has all arms prefixed with `&`; the match expression can be \
               dereferenced instead");
declare_lint!(pub MATCH_BOOL, Warn,
              "a match on boolean expression; recommends `if..else` block instead");

#[allow(missing_copy_implementations)]
pub struct MatchPass;

impl LintPass for MatchPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL)
    }
}

impl LateLintPass for MatchPass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node {
            // check preconditions for SINGLE_MATCH
                // only two arms
            if arms.len() == 2 &&
                // both of the arms have a single pattern and no guard
                arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
                arms[1].pats.len() == 1 && arms[1].guard.is_none() &&
                // and the second pattern is a `_` wildcard: this is not strictly necessary,
                // since the exhaustiveness check will ensure the last one is a catch-all,
                // but in some cases, an explicit match is preferred to catch situations
                // when an enum is extended, so we don't consider these cases
                arms[1].pats[0].node == PatWild(PatWildSingle) &&
                // finally, we don't want any content in the second arm (unit or empty block)
                is_unit_expr(&arms[1].body)
            {
                if in_external_macro(cx, expr.span) {return;}
                span_help_and_lint(cx, SINGLE_MATCH, expr.span,
                                   "you seem to be trying to use match for destructuring a \
                                    single pattern. Consider using `if let`",
                                   &format!("try\nif let {} = {} {}",
                                            snippet(cx, arms[0].pats[0].span, ".."),
                                            snippet(cx, ex.span, ".."),
                                            expr_block(cx, &arms[0].body, None, "..")));
            }

            // check preconditions for MATCH_REF_PATS
            if has_only_ref_pats(arms) {
                if in_external_macro(cx, expr.span) { return; }
                if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node {
                    span_lint(cx, MATCH_REF_PATS, expr.span, &format!(
                        "you don't need to add `&` to both the expression to match \
                         and the patterns: use `match {} {{ ...`", snippet(cx, inner.span, "..")));
                } else {
                    span_lint(cx, MATCH_REF_PATS, expr.span, &format!(
                        "instead of prefixing all patterns with `&`, you can dereference the \
                         expression to match: `match *{} {{ ...`", snippet(cx, ex.span, "..")));
                }
            }

            // check preconditions for MATCH_BOOL
            // type of expression == bool
            if is_bool_expr(cx, ex) {
                if in_external_macro(cx, expr.span) { return; }

                span_lint(cx, MATCH_BOOL, expr.span,
                                   "you seem to be trying to match on a boolean expression. \
                                   Consider using if..else block");
            }
        }
    }
}

fn is_unit_expr(expr: &Expr) -> bool {
    match expr.node {
        ExprTup(ref v) if v.is_empty() => true,
        ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true,
        _ => false,
    }
}

fn is_bool_expr(cx: &LateContext, ex: &Expr ) -> bool {
    cx.tcx.expr_ty(ex).sty == ty::TyBool
}

fn has_only_ref_pats(arms: &[Arm]) -> bool {
    let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node {
        PatRegion(..) => Some(true),  // &-patterns
        PatWild(..) => Some(false),   // an "anything" wildcard is also fine
        _ => None,                    // any other pattern is not fine
    }).collect::<Option<Vec<bool>>>();
    // look for Some(v) where there's at least one true element
    mapped.map_or(false, |v| v.iter().any(|el| *el))
}
<commit_msg>Fixups from review comments<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use rustc::middle::ty;

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

declare_lint!(pub SINGLE_MATCH, Warn,
              "a match statement with a single nontrivial arm (i.e, where the other arm \
               is `_ => {}`) is used; recommends `if let` instead");
declare_lint!(pub MATCH_REF_PATS, Warn,
              "a match has all arms prefixed with `&`; the match expression can be \
               dereferenced instead");
declare_lint!(pub MATCH_BOOL, Warn,
              "a match on boolean expression; recommends `if..else` block instead");

#[allow(missing_copy_implementations)]
pub struct MatchPass;

impl LintPass for MatchPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(SINGLE_MATCH, MATCH_REF_PATS, MATCH_BOOL)
    }
}

impl LateLintPass for MatchPass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node {
            if in_external_macro(cx, expr.span) { return; }

            // check preconditions for SINGLE_MATCH
                // only two arms
            if arms.len() == 2 &&
                // both of the arms have a single pattern and no guard
                arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
                arms[1].pats.len() == 1 && arms[1].guard.is_none() &&
                // and the second pattern is a `_` wildcard: this is not strictly necessary,
                // since the exhaustiveness check will ensure the last one is a catch-all,
                // but in some cases, an explicit match is preferred to catch situations
                // when an enum is extended, so we don't consider these cases
                arms[1].pats[0].node == PatWild(PatWildSingle) &&
                // finally, we don't want any content in the second arm (unit or empty block)
                is_unit_expr(&arms[1].body)
            {
                span_help_and_lint(cx, SINGLE_MATCH, expr.span,
                                   "you seem to be trying to use match for destructuring a \
                                    single pattern. Consider using `if let`",
                                   &format!("try\nif let {} = {} {}",
                                            snippet(cx, arms[0].pats[0].span, ".."),
                                            snippet(cx, ex.span, ".."),
                                            expr_block(cx, &arms[0].body, None, "..")));
            }

            // check preconditions for MATCH_REF_PATS
            if has_only_ref_pats(arms) {
                if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node {
                    span_lint(cx, MATCH_REF_PATS, expr.span, &format!(
                        "you don't need to add `&` to both the expression to match \
                         and the patterns: use `match {} {{ ...`", snippet(cx, inner.span, "..")));
                } else {
                    span_lint(cx, MATCH_REF_PATS, expr.span, &format!(
                        "instead of prefixing all patterns with `&`, you can dereference the \
                         expression to match: `match *{} {{ ...`", snippet(cx, ex.span, "..")));
                }
            }

            // check preconditions for MATCH_BOOL
            // type of expression == bool
            if cx.tcx.expr_ty(ex).sty == ty::TyBool {

                span_lint(cx, MATCH_BOOL, expr.span,
                                   "you seem to be trying to match on a boolean expression. \
                                   Consider using an if..else block");
            }
        }
    }
}

fn is_unit_expr(expr: &Expr) -> bool {
    match expr.node {
        ExprTup(ref v) if v.is_empty() => true,
        ExprBlock(ref b) if b.stmts.is_empty() && b.expr.is_none() => true,
        _ => false,
    }
}

fn has_only_ref_pats(arms: &[Arm]) -> bool {
    let mapped = arms.iter().flat_map(|a| &a.pats).map(|p| match p.node {
        PatRegion(..) => Some(true),  // &-patterns
        PatWild(..) => Some(false),   // an "anything" wildcard is also fine
        _ => None,                    // any other pattern is not fine
    }).collect::<Option<Vec<bool>>>();
    // look for Some(v) where there's at least one true element
    mapped.map_or(false, |v| v.iter().any(|el| *el))
}
<|endoftext|>


<commit_before>use super::managed_display::ManagedDisplay;
use entities::{ EntitiesState, EntitiesHelper, EntityID, ComponentID, NativeComponentType };
use nalgebra::na;
use nalgebra::na::{ Vec3, Eye };
use std::collections::{ HashSet, HashMap };
use std::sync::Arc;
use super::sprite_displayer::SpriteDisplayer;
use super::Drawable;

mod custom_display_system;

pub struct DisplaySystem {
	display: Arc<ManagedDisplay>,
	customDisplay: custom_display_system::CustomDisplaySystem,
	sprites: HashMap<ComponentID, (Option<SpriteDisplayer>, String)>,
	logger: Box<::log::Logger>
}

impl DisplaySystem {
	pub fn new<L: ::log::Logger + 'static>(display: Arc<ManagedDisplay>, state: &EntitiesState, mut logger: L)
		-> DisplaySystem
	{
		declmagic_info!(logger, "created display system");

		DisplaySystem {
			display: display.clone(),
			customDisplay: custom_display_system::CustomDisplaySystem::new(display.clone(), state, logger.clone()),
			sprites: HashMap::new(),
			logger: box logger
		}
	}

	pub fn draw(&mut self, state: &EntitiesState, _: &f64)
	{
		self.update_sprite_displayers(state);

		let camera = DisplaySystem::get_camera(state).unwrap_or_else(|| {
			declmagic_warn!(self.logger, "no active camera on the scene");
			Eye::new_identity(4)
		});

	 	for (cmp, &(ref sprite, _)) in self.sprites.iter() {
	 		let pos = ::physics::PhysicsSystem::get_entity_position(state, &state.get_owner(cmp).unwrap());
	 		let translationMatrix = na::Mat4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, pos.x, pos.y, pos.z, 1.0);
			sprite.as_ref().map(|e| e.draw(&(translationMatrix * camera)));
		}

		self.customDisplay.draw(state);
	}

	fn update_sprite_displayers(&mut self, state: &EntitiesState)
	{
		// getting the list of all sprite displayer components
		let listOfComponents = state
			.get_visible_native_components("spriteDisplay").move_iter()
			.collect::<HashSet<ComponentID>>();

		// removing from the list the elements that have disappeared
		{	let toRemove = self.sprites.keys().filter(|e| !listOfComponents.contains(e.clone())).map(|e| e.clone()).collect::<Vec<ComponentID>>();
			for c in toRemove.move_iter() {
				self.sprites.remove(&c);
			}
		}

		// adding elements that are not yet created
		{	let toCreate = listOfComponents.iter().filter(|e| !self.sprites.contains_key(e.clone())).map(|e| e.clone()).collect::<Vec<ComponentID>>();
			for spriteDisplayComponent in toCreate.move_iter() {
				// inserting in sprites list
				self.sprites.insert(spriteDisplayComponent.clone(), (None, format!("")));
			}
		}

		// updating everything
		for (component, &(ref mut sprite, ref mut currTexName)) in self.sprites.mut_iter() {
			// getting the name of the texture
			let textureName = match state.get_as_string(component, "texture") {
				Some(s) => s,
				_ => {
					// TODO:
					//declmagic_error!(self.logger, "component {} has no valid \"texture\" element", component)
					continue
				}
			};

			if sprite.is_none() || currTexName.as_slice() != textureName.as_slice() {
				(*sprite) = Some(SpriteDisplayer::new(self.display.clone(), textureName.as_slice()).unwrap());
			}

			// getting coordinates
			match sprite {
				&Some(ref mut s) =>
					s.set_rectangle_coords(
						state.get_as_number(component, "leftX").map(|n| n as f32),
						state.get_as_number(component, "topY").map(|n| n as f32),
						state.get_as_number(component, "rightX").map(|n| n as f32),
						state.get_as_number(component, "bottomY").map(|n| n as f32)
					),
				_ => fail!()
			}
		}
	}

	/// Returns the camera matrix of the scene.
	pub fn get_camera(state: &EntitiesState)
		-> Option<na::Mat4<f32>>
	{
		let cameraInfos = state
			.get_visible_native_components("camera").move_iter()
			.max_by(|c| match state.get(c, "priority") { Ok(&::entities::Number(ref n)) => (((*n) * 1000f64) as int), _ => 1000 })
			.and_then(|c| match state.get(&c, "matrix") { Ok(&::entities::List(ref data)) => Some((c, data)), _ => None })
			.map(|(c, data)| (c, data.iter().filter_map(|elem| match elem { &::entities::Number(ref n) => Some(n.clone() as f32), _ => None }).collect::<Vec<f32>>()) );

		if cameraInfos.is_none() {
			return None;
		}

		let (cameraComponent, matrixData) = cameraInfos.unwrap();
		let matrix = na::Mat4::new(*matrixData.get(0), *matrixData.get(1), *matrixData.get(2), *matrixData.get(3), *matrixData.get(4), *matrixData.get(5), *matrixData.get(6), *matrixData.get(7), *matrixData.get(8), *matrixData.get(9), *matrixData.get(10), *matrixData.get(11), *matrixData.get(12), *matrixData.get(13), *matrixData.get(14), *matrixData.get(15));

		let position = ::physics::PhysicsSystem::get_entity_position(state, &state.get_owner(&cameraComponent).unwrap());
		let positionMatrix = na::Mat4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -position.x, -position.y, -position.z, 1.0);

		Some(positionMatrix * matrix)
	}
}
<commit_msg>Fix performance issue with sprites<commit_after>use super::managed_display::ManagedDisplay;
use entities::{ EntitiesState, EntitiesHelper, EntityID, ComponentID, NativeComponentType };
use nalgebra::na;
use nalgebra::na::{ Vec3, Eye };
use std::collections::{ HashSet, HashMap };
use std::sync::Arc;
use super::sprite_displayer::SpriteDisplayer;
use super::Drawable;

mod custom_display_system;

pub struct DisplaySystem {
	display: Arc<ManagedDisplay>,
	customDisplay: custom_display_system::CustomDisplaySystem,
	sprites: HashMap<ComponentID, (Option<SpriteDisplayer>, String)>,
	logger: Box<::log::Logger>
}

impl DisplaySystem {
	pub fn new<L: ::log::Logger + 'static>(display: Arc<ManagedDisplay>, state: &EntitiesState, mut logger: L)
		-> DisplaySystem
	{
		declmagic_info!(logger, "created display system");

		DisplaySystem {
			display: display.clone(),
			customDisplay: custom_display_system::CustomDisplaySystem::new(display.clone(), state, logger.clone()),
			sprites: HashMap::new(),
			logger: box logger
		}
	}

	pub fn draw(&mut self, state: &EntitiesState, _: &f64)
	{
		self.update_sprite_displayers(state);

		let camera = DisplaySystem::get_camera(state).unwrap_or_else(|| {
			declmagic_warn!(self.logger, "no active camera on the scene");
			Eye::new_identity(4)
		});

	 	for (cmp, &(ref sprite, _)) in self.sprites.iter() {
	 		let pos = ::physics::PhysicsSystem::get_entity_position(state, &state.get_owner(cmp).unwrap());
	 		let translationMatrix = na::Mat4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, pos.x, pos.y, pos.z, 1.0);
			sprite.as_ref().map(|e| e.draw(&(translationMatrix * camera)));
		}

		self.customDisplay.draw(state);
	}

	fn update_sprite_displayers(&mut self, state: &EntitiesState)
	{
		// getting the list of all sprite displayer components
		let listOfComponents = state
			.get_visible_native_components("spriteDisplay").move_iter()
			.collect::<HashSet<ComponentID>>();

		// removing from the list the elements that have disappeared
		{	let toRemove = self.sprites.keys().filter(|e| !listOfComponents.contains(e.clone())).map(|e| e.clone()).collect::<Vec<ComponentID>>();
			for c in toRemove.move_iter() {
				self.sprites.remove(&c);
			}
		}

		// adding elements that are not yet created
		{	let toCreate = listOfComponents.iter().filter(|e| !self.sprites.contains_key(e.clone())).map(|e| e.clone()).collect::<Vec<ComponentID>>();
			for spriteDisplayComponent in toCreate.move_iter() {
				// inserting in sprites list
				self.sprites.insert(spriteDisplayComponent.clone(), (None, format!("")));
			}
		}

		// updating everything
		for (component, &(ref mut sprite, ref mut currTexName)) in self.sprites.mut_iter() {
			// getting the name of the texture
			let textureName = match state.get_as_string(component, "texture") {
				Some(s) => s,
				_ => {
					// TODO:
					//declmagic_error!(self.logger, "component {} has no valid \"texture\" element", component)
					continue
				}
			};

			if sprite.is_none() || currTexName.as_slice() != textureName.as_slice() {
				(*sprite) = Some(SpriteDisplayer::new(self.display.clone(), textureName.as_slice()).unwrap());
				*currTexName = textureName;
			}

			// getting coordinates
			match sprite {
				&Some(ref mut s) =>
					s.set_rectangle_coords(
						state.get_as_number(component, "leftX").map(|n| n as f32),
						state.get_as_number(component, "topY").map(|n| n as f32),
						state.get_as_number(component, "rightX").map(|n| n as f32),
						state.get_as_number(component, "bottomY").map(|n| n as f32)
					),
				_ => fail!()
			}
		}
	}

	/// Returns the camera matrix of the scene.
	pub fn get_camera(state: &EntitiesState)
		-> Option<na::Mat4<f32>>
	{
		let cameraInfos = state
			.get_visible_native_components("camera").move_iter()
			.max_by(|c| match state.get(c, "priority") { Ok(&::entities::Number(ref n)) => (((*n) * 1000f64) as int), _ => 1000 })
			.and_then(|c| match state.get(&c, "matrix") { Ok(&::entities::List(ref data)) => Some((c, data)), _ => None })
			.map(|(c, data)| (c, data.iter().filter_map(|elem| match elem { &::entities::Number(ref n) => Some(n.clone() as f32), _ => None }).collect::<Vec<f32>>()) );

		if cameraInfos.is_none() {
			return None;
		}

		let (cameraComponent, matrixData) = cameraInfos.unwrap();
		let matrix = na::Mat4::new(*matrixData.get(0), *matrixData.get(1), *matrixData.get(2), *matrixData.get(3), *matrixData.get(4), *matrixData.get(5), *matrixData.get(6), *matrixData.get(7), *matrixData.get(8), *matrixData.get(9), *matrixData.get(10), *matrixData.get(11), *matrixData.get(12), *matrixData.get(13), *matrixData.get(14), *matrixData.get(15));

		let position = ::physics::PhysicsSystem::get_entity_position(state, &state.get_owner(&cameraComponent).unwrap());
		let positionMatrix = na::Mat4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -position.x, -position.y, -position.z, 1.0);

		Some(positionMatrix * matrix)
	}
}
<|endoftext|>


<commit_before>//! The neural network struct.

use std::ops::Range;
use std::io;

use utils::Stack;
use file;
use gene::*;
use gene::GeneExtras::*;

const BIAS_GENE_VALUE: f64 = 1.0;

#[derive(Clone, Debug, PartialEq)]
pub struct Network {
    // size should be the length of the genome minus one, don't forget
    pub size: usize,
    pub genome: Vec<Gene>
}

impl Network {
    /// Evaluates the neural network with the given inputs, returning a vector of outputs. The encoding can
    /// encode recurrent connections and bias inputs, so an internal state is used. It is important to run
    /// the clear_state method before calling evaluate again, unless it is desired to allow data
    /// carry over from the previous evaluation, for example if the network is being used as a real
    /// time controller.
    ///
    /// If too little inputs are given, the empty inputs will have a value of zero. If too many
    /// inputs are given, the extras are discarded.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Load a neural network
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    ///
    /// // Get the output of the neural network the the specified inputs
    /// let result = network.evaluate(&vec![1.0, 1.0]);
    ///
    /// // Get the output of the neural network with no inputs
    /// let result = network.evaluate(&Vec::new());
    ///
    /// // Get the output of the neural network with too many inputs (extras aren't used)
    /// let result = network.evaluate(&vec![1.0, 1.0, 1.0]);
    ///
    /// // Let's say adder.ann is a file with a neural network with recurrent connections, used for
    /// // adding numbers together.
    /// let mut adder = Network::load_from_file("adder.ann").unwrap();
    ///
    /// // result_one will be 1.0
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// // result_two will be 3.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    ///
    /// // result_three will be 5.0
    /// let result_three = adder.evaluate(&vec![2.0]);
    ///
    /// // If this behavior is not desired, call the clear_state method between evaluations:
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// adder.clear_state();
    ///
    /// // The 1.0 from the previous call is gone, so result_two will be 2.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    /// ```
    pub fn evaluate(&mut self, inputs: &Vec<f64>) -> Vec<f64> {
        // Set inputs
        for gene in &mut self.genome {
            if let Input(ref mut current_value) = gene.variant {
                *current_value = match inputs.get(gene.id) {
                    Some(v) => *v,
                    None => 0.0
                }
            }
        }

        let size = self.size;
        self.evaluate_slice(0..size, true)
    }

    /// Clears the internal state of the neural network.
    pub fn clear_state(&mut self) {
        for gene in &mut self.genome {
            match gene.variant {
                Input(ref mut current_value) => {
                    *current_value = 0.0;
                },
                Neuron(ref mut current_value, _) => {
                    *current_value = 0.0;
                }
                _ => {}
            }
        }
    }

    /// Saves the neural network to a file. Returns an empty tuple on success, or an io error.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Create a neural network
    /// let network = Network {
    ///     size: 0,
    ///     genome: Vec::new()
    /// };
    ///
    /// // Save network to neural_network.ann
    /// network.save_to_file("neural_network.ann");
    /// ```
    pub fn save_to_file(&self, path: &str) -> io::Result<()> {
        file::write_network(self, path)
    }

    /// Loads a neural network from a file. No guarantees are made about the validity of the
    /// genome. Returns the network, or an io error. If the file is in a bad format,
    /// io::ErrorKind::InvalidData is returned.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Loads a network from the file neural_network.ann
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    /// ```
    pub fn load_from_file(path: &str) -> io::Result<Network> {
        file::read_network(path)
    }

    // Returns the output of sub-linear genome in the given range
    fn evaluate_slice(&mut self, range: Range<usize>, neuron_update: bool) -> Vec<f64> {
        let mut gene_index = range.end;
        // Initialize a stack for evaluating the neural network
        let mut stack = Stack::new();

        // Iterate backwards over the specified slice
        while gene_index >= range.start {
            let variant = self.genome[gene_index].variant.clone();

            // For debugging: uncomment these print statements
            // Perhaps add it as an option to help users
            // println!("{:?}", variant);

            match variant {
                Input(_) => {
                    // If the gene is an input, push its value multiplied by the inputs weight onto
                    // the stack
                    let (weight, _, value) = self.genome[gene_index].ref_input().unwrap();
                    stack.push(weight * value);
                },
                Neuron(_, _) => {
                    // If the gene is a neuron, pop a number (the neurons input count) of inputs
                    // off the stack, and push their sum multiplied by the neurons weight onto the
                    // stack
                    let (weight, _, value, inputs) = self.genome[gene_index].ref_mut_neuron().unwrap();
                    let new_value = stack.pop(*inputs).unwrap().iter().fold(0.0, |acc, i| acc + i);

                    if neuron_update {
                        *value = new_value;
                    }

                    stack.push(*weight * new_value);
                },
                Forward => {
                    // This is inefficient because it can run the neuron evaluation code multiple
                    // times
                    // TODO: Turn current value of neurons into a struct with a flag representing
                    // whether the neuron has been evaluated this network evaluation. Reset this
                    // flag after every network evaluation.

                    // If the gene is a forward jumper, evaluate the subnetwork starting at the
                    // neuron with id of the jumper, and push the result multiplied by the jumpers
                    // weight onto the stack
                    let weight = self.genome[gene_index].weight;
                    let id = self.genome[gene_index].id;
                    let subnetwork_range = self.get_subnetwork_index(id).unwrap();

                    let result = self.evaluate_slice(subnetwork_range, false);
                    // println!("{:?}", result);
                    stack.push(weight * result[0]);
                },
                Recurrent => {
                    // If the gene is a recurrent jumper, push the previous value of the neuron
                    // with the id of the jumper multiplied by the jumpers weight onto the stack
                    let gene = &self.genome[gene_index];
                    let neuron = &self.genome[self.get_neuron_index(gene.id).unwrap()];

                    if let Neuron(ref current_value, _) = neuron.variant {
                        stack.push(gene.weight * *current_value);
                    }
                },
                Bias => {
                    // If the gene is a bias input, push the bias constant multiplied by the genes
                    // weight onto the stack
                    let gene = &self.genome[gene_index];
                    stack.push(gene.weight * BIAS_GENE_VALUE);
                }
            }

            if gene_index == range.start {
                break;
            }

            gene_index -= 1;
            // println!("{:?}", stack.data);
        }

        stack.data
    }

    /// Returns the start and end index of the subnetwork starting at the neuron with the given id,
    /// or None if it does not exist.
    pub fn get_subnetwork_index(&self, id: usize) -> Option<Range<usize>> {
        let start = match self.get_neuron_index(id) {
            Some(i) => i,
            None => return None
        };

        let mut end = start;
        let mut sum = 0;

        // Iterate through genes after the start index, modifying the sum each step
        // I could use an iterator here, but it would be messy
        for gene in &self.genome[start..self.size] {
            match gene.variant {
                Neuron(_, ref inputs) => {
                    sum += 1 - *inputs as i32;
                },
                _ => {
                    sum += 1;
                }
            }

            if sum == 1 {
                break;
            }

            end += 1;
        }

        if sum != 1 {
            None
        } else {
            Some(Range {
                start: start,
                end: end
            })
        }
    }

    /// Returns the index of the neuron with the given id, or None if it does not exist.
    pub fn get_neuron_index(&self, id: usize) -> Option<usize> {
        let mut result = None;

        for (i, gene) in self.genome.iter().enumerate() {
            if let Neuron(_, _) = gene.variant {
                if gene.id == id {
                    result = Some(i);
                }
            }
        }

        result
    }
}
<commit_msg>very bad things<commit_after>//! The neural network struct.

use std::ops::Range;
use std::io;

use utils::Stack;
use file;
use gene::*;
use gene::GeneExtras::*;

const BIAS_GENE_VALUE: f64 = 1.0;

#[derive(Clone, Debug, PartialEq)]
pub struct Network {
    // size should be the length of the genome minus one, don't forget
    pub size: usize,
    pub genome: Vec<Gene>
}

impl Network {
    /// Evaluates the neural network with the given inputs, returning a vector of outputs. The encoding can
    /// encode recurrent connections and bias inputs, so an internal state is used. It is important to run
    /// the clear_state method before calling evaluate again, unless it is desired to allow data
    /// carry over from the previous evaluation, for example if the network is being used as a real
    /// time controller.
    ///
    /// If too little inputs are given, the empty inputs will have a value of zero. If too many
    /// inputs are given, the extras are discarded.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Load a neural network
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    ///
    /// // Get the output of the neural network the the specified inputs
    /// let result = network.evaluate(&vec![1.0, 1.0]);
    ///
    /// // Get the output of the neural network with no inputs
    /// let result = network.evaluate(&Vec::new());
    ///
    /// // Get the output of the neural network with too many inputs (extras aren't used)
    /// let result = network.evaluate(&vec![1.0, 1.0, 1.0]);
    ///
    /// // Let's say adder.ann is a file with a neural network with recurrent connections, used for
    /// // adding numbers together.
    /// let mut adder = Network::load_from_file("adder.ann").unwrap();
    ///
    /// // result_one will be 1.0
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// // result_two will be 3.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    ///
    /// // result_three will be 5.0
    /// let result_three = adder.evaluate(&vec![2.0]);
    ///
    /// // If this behavior is not desired, call the clear_state method between evaluations:
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// adder.clear_state();
    ///
    /// // The 1.0 from the previous call is gone, so result_two will be 2.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    /// ```
    pub fn evaluate(&mut self, inputs: &Vec<f64>) -> Vec<f64> {
        // Set inputs
        for gene in &mut self.genome {
            if let Input(ref mut current_value) = gene.variant {
                *current_value = match inputs.get(gene.id) {
                    Some(v) => *v,
                    None => 0.0
                }
            }
        }

        let size = self.size;
        self.evaluate_slice(0..size, true, 0)
    }

    /// Clears the internal state of the neural network.
    pub fn clear_state(&mut self) {
        for gene in &mut self.genome {
            match gene.variant {
                Input(ref mut current_value) => {
                    *current_value = 0.0;
                },
                Neuron(ref mut current_value, _) => {
                    *current_value = 0.0;
                }
                _ => {}
            }
        }
    }

    /// Saves the neural network to a file. Returns an empty tuple on success, or an io error.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Create a neural network
    /// let network = Network {
    ///     size: 0,
    ///     genome: Vec::new()
    /// };
    ///
    /// // Save network to neural_network.ann
    /// network.save_to_file("neural_network.ann");
    /// ```
    pub fn save_to_file(&self, path: &str) -> io::Result<()> {
        file::write_network(self, path)
    }

    /// Loads a neural network from a file. No guarantees are made about the validity of the
    /// genome. Returns the network, or an io error. If the file is in a bad format,
    /// io::ErrorKind::InvalidData is returned.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Loads a network from the file neural_network.ann
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    /// ```
    pub fn load_from_file(path: &str) -> io::Result<Network> {
        file::read_network(path)
    }

    // Returns the output of sub-linear genome in the given range
    fn evaluate_slice(&mut self, range: Range<usize>, neuron_update: bool, depth: usize) -> Vec<f64> {
        let mut gene_index = range.end;
        // Initialize a stack for evaluating the neural network
        let mut stack = Stack::new();

        // Iterate backwards over the specified slice
        while gene_index >= range.start {
            let variant = self.genome[gene_index].variant.clone();

            // For debugging: uncomment these print statements
            // Perhaps add it as an option to help users
            // println!("{:?}", variant);

            match variant {
                Input(_) => {
                    // If the gene is an input, push its value multiplied by the inputs weight onto
                    // the stack
                    let (weight, _, value) = self.genome[gene_index].ref_input().unwrap();
                    stack.push(weight * value);
                },
                Neuron(_, _) => {
                    // If the gene is a neuron, pop a number (the neurons input count) of inputs
                    // off the stack, and push their sum multiplied by the neurons weight onto the
                    // stack
                    let (weight, _, value, inputs) = self.genome[gene_index].ref_mut_neuron().unwrap();
                    let new_value = stack.pop(*inputs).unwrap().iter().fold(0.0, |acc, i| acc + i);

                    if neuron_update {
                        *value = new_value;
                    }

                    stack.push(*weight * new_value);
                },
                Forward => {
                    // This is inefficient because it can run the neuron evaluation code multiple
                    // times
                    // TODO: Turn current value of neurons into a struct with a flag representing
                    // whether the neuron has been evaluated this network evaluation. Reset this
                    // flag after every network evaluation.

                    // If the gene is a forward jumper, evaluate the subnetwork starting at the
                    // neuron with id of the jumper, and push the result multiplied by the jumpers
                    // weight onto the stack
                    let weight = self.genome[gene_index].weight;
                    let id = self.genome[gene_index].id;
                    let subnetwork_range = self.get_subnetwork_index(id).unwrap();

                    println!("{:?}", depth);
                    let result = self.evaluate_slice(subnetwork_range, false, depth + 1);
                    // println!("{:?}", result);
                    stack.push(weight * result[0]);
                },
                Recurrent => {
                    // If the gene is a recurrent jumper, push the previous value of the neuron
                    // with the id of the jumper multiplied by the jumpers weight onto the stack
                    let gene = &self.genome[gene_index];
                    let neuron = &self.genome[self.get_neuron_index(gene.id).unwrap()];

                    if let Neuron(ref current_value, _) = neuron.variant {
                        stack.push(gene.weight * *current_value);
                    }
                },
                Bias => {
                    // If the gene is a bias input, push the bias constant multiplied by the genes
                    // weight onto the stack
                    let gene = &self.genome[gene_index];
                    stack.push(gene.weight * BIAS_GENE_VALUE);
                }
            }

            if gene_index == range.start {
                break;
            }

            gene_index -= 1;
            // println!("{:?}", stack.data);
        }

        stack.data
    }

    /// Returns the start and end index of the subnetwork starting at the neuron with the given id,
    /// or None if it does not exist.
    pub fn get_subnetwork_index(&self, id: usize) -> Option<Range<usize>> {
        let start = match self.get_neuron_index(id) {
            Some(i) => i,
            None => return None
        };

        let mut end = start;
        let mut sum = 0;

        // Iterate through genes after the start index, modifying the sum each step
        // I could use an iterator here, but it would be messy
        for gene in &self.genome[start..self.size] {
            match gene.variant {
                Neuron(_, ref inputs) => {
                    sum += 1 - *inputs as i32;
                },
                _ => {
                    sum += 1;
                }
            }

            if sum == 1 {
                break;
            }

            end += 1;
        }

        if sum != 1 {
            None
        } else {
            Some(Range {
                start: start,
                end: end
            })
        }
    }

    /// Returns the index of the neuron with the given id, or None if it does not exist.
    pub fn get_neuron_index(&self, id: usize) -> Option<usize> {
        let mut result = None;

        for (i, gene) in self.genome.iter().enumerate() {
            if let Neuron(_, _) = gene.variant {
                if gene.id == id {
                    result = Some(i);
                }
            }
        }

        result
    }
}
<|endoftext|>


<commit_before>enum PackageType {
    Bin, // Binary
    Lib, // Library
    Src, // Source
}

struct Version {
    major: u32,
    minor: u32,
    patch: u32,
    additional: Option<String>,
}

struct Package {
    name: String,
    hash: u32,
    version: Version,
    package_type: PackageType,
    dependencies: Vec<Package>,
}

struct Repository {
    url: String,
    packages: Vec<Package>,
}
<commit_msg>Allow comparison between `Version`s<commit_after>use std::cmp::Ordering;

enum PackageType {
    Bin, // Binary
    Lib, // Library
    Src, // Source
}

struct Version {
    major: u32,
    minor: u32,
    patch: u32,
    additional: Option<String>,
}

struct Package {
    name: String,
    hash: u32,
    version: Version,
    package_type: PackageType,
    dependencies: Vec<Package>,
}

struct Repository {
    url: String,
    packages: Vec<Package>,
}

impl PartialEq for Version {
    fn eq(&self, other: &Self) -> bool {
        self == other
    }
}

impl Eq for Version {}

impl PartialOrd for Version {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Version {
    /// This compares one `Version` with another. It only compares the
    /// three main parts of Version (`major`, `minor`, `patch`) and ignores
    /// `additional` as it is meant to let the package host to put additional
    /// messages such as `alpha`, `beta`.
    fn cmp(&self, other: &Self) -> Ordering {
        if self.major > other.major { Ordering::Greater } else
        if self.major < other.major { Ordering::Less }
        else {
            if self.minor > other.minor { Ordering::Greater } else
            if self.minor < other.minor { Ordering::Less }
            else {
                if self.patch > other.patch { Ordering::Greater } else
                if self.patch < other.patch { Ordering::Less }
                else { Ordering::Equal }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use helper::*;
use nom::{self, is_digit};
use super::{Time, DateTime, Date};

macro_rules! empty_or(
    ($i:expr, $submac:ident!( $($args:tt)* )) => (
        if $i.len() == 0 {
            nom::IResult::Done($i, None)
        } else {
            match $submac!($i, $($args)*) {
                nom::IResult::Done(i,o)     => nom::IResult::Done(i, Some(o)),
                nom::IResult::Error(_)      => nom::IResult::Done($i, None),
                nom::IResult::Incomplete(i) => nom::IResult::Incomplete(i)

            }
        }
    );
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (

    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        nom::IResult::Error(nom::Err::Position(nom::ErrorKind::Custom(20),$input))
      } else {
        nom::IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        {
        fn f(c: u8) -> bool { c >= ($min as u8) && c <= ($max as u8)}
        flat_map!($input, take!(1), check!(f))
        }
    );
);

named!(take_4_digits, flat_map!(take!(4), check!(is_digit)));

// year
named!(year_prefix, alt!(tag!("+") | tag!("-")));
named!(year <i32>, chain!(
        pref: opt!(complete!(year_prefix)) ~
        year: call!(take_4_digits)
        ,
        || {
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        }));

// MM
named!(lower_month <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(upper_month <u32>, chain!(tag!("1") ~ s:char_between!('0', '2') , || 10+buf_to_u32(s)));
named!(month <u32>, alt!(lower_month | upper_month));

// DD
named!(day_zero  <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(day_one   <u32>, chain!(tag!("1") ~ s:char_between!('0', '9') , || 10+buf_to_u32(s)));
named!(day_two   <u32>, chain!(tag!("2") ~ s:char_between!('0', '9') , || 20+buf_to_u32(s)));
named!(day_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '1') , || 30+buf_to_u32(s)));
named!(day <u32>, alt!(day_zero | day_one | day_two | day_three));

// WW
// reusing day_N parsers, sorry
named!(week_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '9') , || 30+buf_to_u32(s)));
named!(week_four  <u32>, chain!(tag!("4") ~ s:char_between!('0', '9') , || 40+buf_to_u32(s)));
named!(week_five  <u32>, chain!(tag!("5") ~ s:char_between!('0', '3') , || 50+buf_to_u32(s)));

named!(week <u32>, alt!(day_zero | day_one | day_two | week_three| week_four | week_five ));
named!(week_day <u32>, chain!(s:char_between!('1', '7') , || buf_to_u32(s)));

// ordinal DDD
named!(ord_day <u32>, chain!(
        a:char_between!('0','3') ~
        b:char_between!('0','9') ~
        c:char_between!('0','9')
        ,
        || { buf_to_u32(a)*100 + buf_to_u32(b)*10 + buf_to_u32(c) }
        ));

// YYYY-MM-DD
named!(pub ymd_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        m: month ~
        opt!(complete!(tag!("-"))) ~
        d: day
        ,
        || { Date::YMD{ year: y, month: m, day: d } }
        ));

// YYYY-MM-DD
named!(pub ordinal_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        d: ord_day
        ,
        || { Date::Ordinal{ year: y, ddd: d } }
        ));

// YYYY-"W"WW-D
named!(pub iso_week_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        tag!("W") ~
        w: week ~
        opt!(complete!(tag!("-"))) ~
        d: week_day
        ,
        || { Date::Week{ year: y, ww: w, d: d } }
        ));

named!(pub parse_date <Date>, alt!( ymd_date | iso_week_date | ordinal_date ) );

// TIME

// HH
named!(lower_hour <u32>, chain!(f:char_between!('0','1') ~ s:char_between!('0','9') ,
                                       || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upper_hour <u32>, chain!(tag!("2") ~ s:char_between!('0','4') , || 20+buf_to_u32(s)));
named!(hour <u32>, alt!(lower_hour | upper_hour));

// MM
named!(below_sixty <u32>, chain!(f:char_between!('0','5') ~ s:char_between!('0','9'), || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upto_sixty <u32>, alt!(below_sixty | map!(tag!("60"), |_| 60)));

named!(minute <u32>, call!(below_sixty));
named!(second <u32>, call!(upto_sixty));
named!(millisecond <u32>, map!( is_a!("0123456789"), |ms| buf_to_u32(ms) ) );

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
named!(pub parse_time <Time>, chain!(
        h: hour ~
        opt!(complete!(tag!(":"))) ~
        m: minute ~
        s:  opt!(complete!( chain!( opt!(tag!(":")) ~ s:second, || s))) ~
        ms: opt!(complete!( chain!( tag!(".") ~ ms:millisecond, || ms))) ~
        z:  opt!(complete!( alt!( timezone_hour | timezone_utc) )) ,
        || {
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                millisecond: ms.unwrap_or(0),
                tz_offset_hours: z.unwrap_or((0,0)).0,
                tz_offset_minutes: z.unwrap_or((0,0)).1
            }
        }
        ));

named!(sign <i32>, alt!(
        tag!("-") => { |_| -1 } |
        tag!("+") => { |_| 1 }
        )
    );

named!(timezone_hour <(i32,i32)>, chain!(
        s: sign ~
        h: hour ~
        m: empty_or!(
            chain!(
                tag!(":")? ~ m: minute , || { m }
            ))
        ,
        || { (s * (h as i32) , s * (m.unwrap_or(0) as i32)) }
        ));

named!(timezone_utc <(i32,i32)>, map!(tag!("Z"), |_| (0,0)));

// Full ISO8601
named!(pub parse_datetime <DateTime>, chain!(
        d: parse_date ~
        tag!("T") ~
        t: parse_time
        ,
        || {
            DateTime{
                date: d,
                time: t,
            }
        }
        ));

#[cfg(test)]
mod tests{

    use super::{year, month, day};
    use super::{hour, minute, second};
    use nom::IResult::*;

    #[test]
    fn test_year() {
        assert_eq!(Done(&[][..],   2015), year(b"2015"));
        assert_eq!(Done(&[][..],  -0333), year(b"-0333"));
        assert_eq!(Done(&b"-"[..], 2015), year(b"2015-"));
        assert!(year(b"abcd").is_err());
        assert!(year(b"2a03").is_err());
    }

    #[test]
    fn test_month() {
        assert_eq!(Done(&[][..], 1),    month(b"01"));
        assert_eq!(Done(&[][..], 6),    month(b"06"));
        assert_eq!(Done(&[][..], 12),   month(b"12"));
        assert_eq!(Done(&b"-"[..], 12), month(b"12-"));

        assert!(month(b"13").is_err());
        assert!(month(b"00").is_err());
    }

    #[test]
    fn test_day() {
        assert_eq!(Done(&[][..], 1),    day(b"01"));
        assert_eq!(Done(&[][..], 12),   day(b"12"));
        assert_eq!(Done(&[][..], 20),   day(b"20"));
        assert_eq!(Done(&[][..], 28),   day(b"28"));
        assert_eq!(Done(&[][..], 30),   day(b"30"));
        assert_eq!(Done(&[][..], 31),   day(b"31"));
        assert_eq!(Done(&b"-"[..], 31), day(b"31-"));

        assert!(day(b"00").is_err());
        assert!(day(b"32").is_err());
    }

    #[test]
    fn test_hour() {
        assert_eq!(Done(&[][..], 0),  hour(b"00"));
        assert_eq!(Done(&[][..], 1),  hour(b"01"));
        assert_eq!(Done(&[][..], 6),  hour(b"06"));
        assert_eq!(Done(&[][..], 12), hour(b"12"));
        assert_eq!(Done(&[][..], 13), hour(b"13"));
        assert_eq!(Done(&[][..], 20), hour(b"20"));
        assert_eq!(Done(&[][..], 24), hour(b"24"));

        assert!(hour(b"25").is_err());
        assert!(hour(b"30").is_err());
        assert!(hour(b"ab").is_err());
    }

    #[test]
    fn test_minute() {
        assert_eq!(Done(&[][..], 0),  minute(b"00"));
        assert_eq!(Done(&[][..], 1),  minute(b"01"));
        assert_eq!(Done(&[][..], 30), minute(b"30"));
        assert_eq!(Done(&[][..], 59), minute(b"59"));

        assert!(minute(b"60").is_err());
        assert!(minute(b"61").is_err());
        assert!(minute(b"ab").is_err());
    }

    #[test]
    fn test_second() {
        assert_eq!(Done(&[][..], 0),  second(b"00"));
        assert_eq!(Done(&[][..], 1),  second(b"01"));
        assert_eq!(Done(&[][..], 30), second(b"30"));
        assert_eq!(Done(&[][..], 59), second(b"59"));
        assert_eq!(Done(&[][..], 60), second(b"60"));

        assert!(second(b"61").is_err());
        assert!(second(b"ab").is_err());
    }

}
<commit_msg>fix: Make it compile with pre-2.0 nom<commit_after>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use helper::*;
use nom::{self, is_digit};
use super::{Time, DateTime, Date};

macro_rules! empty_or(
    ($i:expr, $submac:ident!( $($args:tt)* )) => (
        if $i.len() == 0 {
            nom::IResult::Done($i, None)
        } else {
            match $submac!($i, $($args)*) {
                nom::IResult::Done(i,o)     => nom::IResult::Done(i, Some(o)),
                nom::IResult::Error(_)      => nom::IResult::Done($i, None),
                nom::IResult::Incomplete(i) => nom::IResult::Incomplete(i)

            }
        }
    );
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (

    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        nom::IResult::Error(nom::ErrorKind::Custom(20))
      } else {
        nom::IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        {
        fn f(c: u8) -> bool { c >= ($min as u8) && c <= ($max as u8)}
        flat_map!($input, take!(1), check!(f))
        }
    );
);

named!(take_4_digits, flat_map!(take!(4), check!(is_digit)));

// year
named!(year_prefix, alt!(tag!("+") | tag!("-")));
named!(year <i32>, chain!(
        pref: opt!(complete!(year_prefix)) ~
        year: call!(take_4_digits)
        ,
        || {
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        }));

// MM
named!(lower_month <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(upper_month <u32>, chain!(tag!("1") ~ s:char_between!('0', '2') , || 10+buf_to_u32(s)));
named!(month <u32>, alt!(lower_month | upper_month));

// DD
named!(day_zero  <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(day_one   <u32>, chain!(tag!("1") ~ s:char_between!('0', '9') , || 10+buf_to_u32(s)));
named!(day_two   <u32>, chain!(tag!("2") ~ s:char_between!('0', '9') , || 20+buf_to_u32(s)));
named!(day_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '1') , || 30+buf_to_u32(s)));
named!(day <u32>, alt!(day_zero | day_one | day_two | day_three));

// WW
// reusing day_N parsers, sorry
named!(week_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '9') , || 30+buf_to_u32(s)));
named!(week_four  <u32>, chain!(tag!("4") ~ s:char_between!('0', '9') , || 40+buf_to_u32(s)));
named!(week_five  <u32>, chain!(tag!("5") ~ s:char_between!('0', '3') , || 50+buf_to_u32(s)));

named!(week <u32>, alt!(day_zero | day_one | day_two | week_three| week_four | week_five ));
named!(week_day <u32>, chain!(s:char_between!('1', '7') , || buf_to_u32(s)));

// ordinal DDD
named!(ord_day <u32>, chain!(
        a:char_between!('0','3') ~
        b:char_between!('0','9') ~
        c:char_between!('0','9')
        ,
        || { buf_to_u32(a)*100 + buf_to_u32(b)*10 + buf_to_u32(c) }
        ));

// YYYY-MM-DD
named!(pub ymd_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        m: month ~
        opt!(complete!(tag!("-"))) ~
        d: day
        ,
        || { Date::YMD{ year: y, month: m, day: d } }
        ));

// YYYY-MM-DD
named!(pub ordinal_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        d: ord_day
        ,
        || { Date::Ordinal{ year: y, ddd: d } }
        ));

// YYYY-"W"WW-D
named!(pub iso_week_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        tag!("W") ~
        w: week ~
        opt!(complete!(tag!("-"))) ~
        d: week_day
        ,
        || { Date::Week{ year: y, ww: w, d: d } }
        ));

named!(pub parse_date <Date>, alt!( ymd_date | iso_week_date | ordinal_date ) );

// TIME

// HH
named!(lower_hour <u32>, chain!(f:char_between!('0','1') ~ s:char_between!('0','9') ,
                                       || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upper_hour <u32>, chain!(tag!("2") ~ s:char_between!('0','4') , || 20+buf_to_u32(s)));
named!(hour <u32>, alt!(lower_hour | upper_hour));

// MM
named!(below_sixty <u32>, chain!(f:char_between!('0','5') ~ s:char_between!('0','9'), || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upto_sixty <u32>, alt!(below_sixty | map!(tag!("60"), |_| 60)));

named!(minute <u32>, call!(below_sixty));
named!(second <u32>, call!(upto_sixty));
named!(millisecond <u32>, map!( is_a!("0123456789"), |ms| buf_to_u32(ms) ) );

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
named!(pub parse_time <Time>, chain!(
        h: hour ~
        opt!(complete!(tag!(":"))) ~
        m: minute ~
        s:  opt!(complete!( chain!( opt!(tag!(":")) ~ s:second, || s))) ~
        ms: opt!(complete!( chain!( tag!(".") ~ ms:millisecond, || ms))) ~
        z:  opt!(complete!( alt!( timezone_hour | timezone_utc) )) ,
        || {
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                millisecond: ms.unwrap_or(0),
                tz_offset_hours: z.unwrap_or((0,0)).0,
                tz_offset_minutes: z.unwrap_or((0,0)).1
            }
        }
        ));

named!(sign <i32>, alt!(
        tag!("-") => { |_| -1 } |
        tag!("+") => { |_| 1 }
        )
    );

named!(timezone_hour <(i32,i32)>, chain!(
        s: sign ~
        h: hour ~
        m: empty_or!(
            chain!(
                tag!(":")? ~ m: minute , || { m }
            ))
        ,
        || { (s * (h as i32) , s * (m.unwrap_or(0) as i32)) }
        ));

named!(timezone_utc <(i32,i32)>, map!(tag!("Z"), |_| (0,0)));

// Full ISO8601
named!(pub parse_datetime <DateTime>, chain!(
        d: parse_date ~
        tag!("T") ~
        t: parse_time
        ,
        || {
            DateTime{
                date: d,
                time: t,
            }
        }
        ));

#[cfg(test)]
mod tests{

    use super::{year, month, day};
    use super::{hour, minute, second};
    use nom::IResult::*;

    #[test]
    fn test_year() {
        assert_eq!(Done(&[][..],   2015), year(b"2015"));
        assert_eq!(Done(&[][..],  -0333), year(b"-0333"));
        assert_eq!(Done(&b"-"[..], 2015), year(b"2015-"));
        assert!(year(b"abcd").is_err());
        assert!(year(b"2a03").is_err());
    }

    #[test]
    fn test_month() {
        assert_eq!(Done(&[][..], 1),    month(b"01"));
        assert_eq!(Done(&[][..], 6),    month(b"06"));
        assert_eq!(Done(&[][..], 12),   month(b"12"));
        assert_eq!(Done(&b"-"[..], 12), month(b"12-"));

        assert!(month(b"13").is_err());
        assert!(month(b"00").is_err());
    }

    #[test]
    fn test_day() {
        assert_eq!(Done(&[][..], 1),    day(b"01"));
        assert_eq!(Done(&[][..], 12),   day(b"12"));
        assert_eq!(Done(&[][..], 20),   day(b"20"));
        assert_eq!(Done(&[][..], 28),   day(b"28"));
        assert_eq!(Done(&[][..], 30),   day(b"30"));
        assert_eq!(Done(&[][..], 31),   day(b"31"));
        assert_eq!(Done(&b"-"[..], 31), day(b"31-"));

        assert!(day(b"00").is_err());
        assert!(day(b"32").is_err());
    }

    #[test]
    fn test_hour() {
        assert_eq!(Done(&[][..], 0),  hour(b"00"));
        assert_eq!(Done(&[][..], 1),  hour(b"01"));
        assert_eq!(Done(&[][..], 6),  hour(b"06"));
        assert_eq!(Done(&[][..], 12), hour(b"12"));
        assert_eq!(Done(&[][..], 13), hour(b"13"));
        assert_eq!(Done(&[][..], 20), hour(b"20"));
        assert_eq!(Done(&[][..], 24), hour(b"24"));

        assert!(hour(b"25").is_err());
        assert!(hour(b"30").is_err());
        assert!(hour(b"ab").is_err());
    }

    #[test]
    fn test_minute() {
        assert_eq!(Done(&[][..], 0),  minute(b"00"));
        assert_eq!(Done(&[][..], 1),  minute(b"01"));
        assert_eq!(Done(&[][..], 30), minute(b"30"));
        assert_eq!(Done(&[][..], 59), minute(b"59"));

        assert!(minute(b"60").is_err());
        assert!(minute(b"61").is_err());
        assert!(minute(b"ab").is_err());
    }

    #[test]
    fn test_second() {
        assert_eq!(Done(&[][..], 0),  second(b"00"));
        assert_eq!(Done(&[][..], 1),  second(b"01"));
        assert_eq!(Done(&[][..], 30), second(b"30"));
        assert_eq!(Done(&[][..], 59), second(b"59"));
        assert_eq!(Done(&[][..], 60), second(b"60"));

        assert!(second(b"61").is_err());
        assert!(second(b"ab").is_err());
    }

}
<|endoftext|>


<commit_before>struct GbPrinter {
    status: u8,
    state: u32,
    data: [u8; 0x280*9],
    packet: [u8; 0x400],
    count: usize,
    datacount: usize,
    datasize: usize,
    result: u8,
}

impl GbPrinter {
    fn new() -> GbPrinter {
        GbPrinter {
            status: 0,
            state: 0,
            data: [0; 0x280*9],
            packet: [0; 0x400],
            count: 0,
            datacount: 0,
            datasize: 0,
            result: 0,
        }
    }

    fn check_crc(&self) -> bool {
        let mut crc = 0;
        for i in 2..(6 + self.datasize) {
            crc += self.packet[i] as u16;
        }

        let msgcrc = self.packet[6 + self.datasize] as u16
            + ((self.packet[7 + self.datasize] as u16) << 8);

        crc == msgcrc
    }

    fn reset(&mut self) {
        self.state = 0;
        self.datasize = 0;
        self.datacount = 0;
        self.count = 0;
        self.status = 0;
        self.result = 0;
    }

    fn show(&self) {
        unimplemented!();
    }

    fn receive(&mut self) {
        if self.packet[3] != 0 {
            let mut dataidx = 6;
            let mut destidx = self.datacount;
            let mut len = 0;

            while len < self.datasize {
                let control = self.packet[dataidx];
                dataidx += 1;

                if control & 0x80 != 0 {
                    let curlen = ((control & 0x7F) + 2) as usize;
                    for i in 0..curlen {
                        self.data[destidx + i] = self.packet[dataidx];
                    }
                    dataidx += 1;
                    len += curlen;
                    destidx += curlen;
                }
                else {
                    let curlen = (control + 1) as usize;
                    for i in 0..curlen {
                        self.data[destidx + i] = self.packet[dataidx + i];
                    }
                    destidx += curlen;
                    dataidx += curlen;
                    len += curlen as usize;
                }
            }
        }
        else {
            for i in 0..self.datasize {
                self.data[self.datacount + i] = self.packet[6 + i];
            }
            self.datacount += self.datasize;
        }
    }

    fn command(&mut self) {
        match self.packet[2] {
            0x01 => {
                self.datacount = 0;
                self.status = 0;
            },
            0x02 => {
                self.show();
            },
            0x04 => {
                self.receive();
            },
            _ => (),
        }
    }

    fn send(&mut self, v: u8) -> u8 {
        self.packet[self.count] = v;
        self.count += 1;

        match self.state {
            0 => {
                self.count = 0;
                if v == 0x88 {
                    self.packet[self.count] = v;
                    self.count += 1;
                    self.state = 1;
                }
                else {
                    self.reset();
                }
            },
            1 => {
                if v == 0x33 {
                    self.packet[self.count] = v;
                    self.count += 1;
                    self.state = 2;
                }
                else {
                    self.reset();
                }
            },
            2 => {
                self.packet[self.count] = v;
                self.count += 1;
                if self.count == 6 {
                    self.state = 3;
                    self.datasize = self.packet[4] as usize + ((self.packet[5] as usize) << 8);
                }
            },
            3 => {
                if self.datasize != 0 {
                    self.packet[self.count] = v;
                    self.count += 1;
                    if self.count == self.datasize + 6 {
                        self.state = 4;
                    }
                }
                else {
                    self.state = 4;
                    return self.send(v);
                }
            },
            4 => {
                self.packet[self.count] = v;
                self.count += 1;
                self.state = 5;
            },
            5 => {
                self.packet[self.count] = v;
                self.count += 1;
                if self.check_crc() {
                    self.command();
                }
                self.state = 6;
            },
            6 => {
                self.packet[self.count] = v;
                self.count += 1;
                self.result = 0x81;
                self.state = 7;
            },
            7 => {
                self.packet[self.count] = v;
                self.count += 1;
                self.result = self.status;
                self.state = 0;
                self.count = 1;
            },
            _ => {
                self.reset()
            },
        }
        self.result
    }
}
<commit_msg>Update (and fix) printer state machine<commit_after>struct GbPrinter {
    status: u8,
    state: u32,
    data: [u8; 0x280*9],
    packet: [u8; 0x400],
    count: usize,
    datacount: usize,
    datasize: usize,
    result: u8,
}

impl GbPrinter {
    fn new() -> GbPrinter {
        GbPrinter {
            status: 0,
            state: 0,
            data: [0; 0x280*9],
            packet: [0; 0x400],
            count: 0,
            datacount: 0,
            datasize: 0,
            result: 0,
        }
    }

    fn check_crc(&self) -> bool {
        let mut crc = 0;
        for i in 2..(6 + self.datasize) {
            crc += self.packet[i] as u16;
        }

        let msgcrc = self.packet[6 + self.datasize] as u16
            + ((self.packet[7 + self.datasize] as u16) << 8);

        crc == msgcrc
    }

    fn reset(&mut self) {
        self.state = 0;
        self.datasize = 0;
        self.datacount = 0;
        self.count = 0;
        self.status = 0;
        self.result = 0;
    }

    fn show(&self) {
        unimplemented!();
    }

    fn receive(&mut self) {
        if self.packet[3] != 0 {
            let mut dataidx = 6;
            let mut destidx = self.datacount;
            let mut len = 0;

            while len < self.datasize {
                let control = self.packet[dataidx];
                dataidx += 1;

                if control & 0x80 != 0 {
                    let curlen = ((control & 0x7F) + 2) as usize;
                    for i in 0..curlen {
                        self.data[destidx + i] = self.packet[dataidx];
                    }
                    dataidx += 1;
                    len += curlen;
                    destidx += curlen;
                }
                else {
                    let curlen = (control + 1) as usize;
                    for i in 0..curlen {
                        self.data[destidx + i] = self.packet[dataidx + i];
                    }
                    destidx += curlen;
                    dataidx += curlen;
                    len += curlen as usize;
                }
            }
        }
        else {
            for i in 0..self.datasize {
                self.data[self.datacount + i] = self.packet[6 + i];
            }
            self.datacount += self.datasize;
        }
    }

    fn command(&mut self) {
        match self.packet[2] {
            0x01 => {
                self.datacount = 0;
                self.status = 0;
            },
            0x02 => {
                self.show();
            },
            0x04 => {
                self.receive();
            },
            _ => (),
        }
    }

    fn send(&mut self, v: u8) -> u8 {
        self.packet[self.count] = v;
        self.count += 1;

        match self.state {
            0 => {
                if v == 0x88 {
                    self.state = 1;
                }
                else {
                    self.reset();
                }
            },
            1 => {
                if v == 0x33 {
                    self.state = 2;
                }
                else {
                    self.reset();
                }
            },
            2 => {
                if self.count == 6 {
                    self.datasize = self.packet[4] as usize + ((self.packet[5] as usize) << 8);
                    if self.datasize > 0 {
                        self.state = 3;
                    }
                    else {
                        self.state = 4;
                    }
                }
            },
            3 => {
                if self.count == self.datasize + 6 {
                    self.state = 4;
                }
            },
            4 => {
                self.state = 5;
            },
            5 => {
                if self.check_crc() {
                    self.command();
                }
                self.state = 6;
            },
            6 => {
                self.result = 0x81;
                self.state = 7;
            },
            7 => {
                self.result = self.status;
                self.state = 0;
                self.count = 0;
            },
            _ => {
                self.reset()
            },
        }
        self.result
    }
}
<|endoftext|>


<commit_before>use dispatcher::response::ResponseSender;
use context::ContextMap;

pub struct SharedData<'a> {
    pub responder: &'a mut ResponseSender,
    pub map: &'a mut ContextMap,
}

impl<'a> SharedData<'a> {
    pub fn new(map: &'a mut ContextMap, responder: &'a mut ResponseSender) -> SharedData<'a> {
        SharedData { map: map, responder: responder }
    }
}

pub trait EventHandler<T: Event, D> {
    fn handle_event(&mut self, event: T, shared_data: &mut D);
    fn handle(&self) -> T::Handle;
}

pub trait EventDemultiplexer {
    type Event: Event;
    fn select(&mut self) -> Option<Self::Event>;
}

pub trait Reactor<D> {
    type Event: Event;
    fn handle_events(&mut self);
    fn register_handler(&mut self, handler: Box<EventHandler<Self::Event, D>>);
    fn remove_handler_by_handle(&mut self,
                                 handler: &<<Self as Reactor<D>>::Event as Event>::Handle);
}

pub trait Event {
    type Handle;
    fn handle(&self) -> Self::Handle;
}
<commit_msg>Reactor: use higher-ranked lifetimes and SharedData<commit_after>use dispatcher::response::ResponseSender;
use context::ContextMap;

pub struct SharedData<'a> {
    pub responder: &'a mut ResponseSender,
    pub map: &'a mut ContextMap,
}

impl<'a> SharedData<'a> {
    pub fn new(map: &'a mut ContextMap, responder: &'a mut ResponseSender) -> SharedData<'a> {
        SharedData { map: map, responder: responder }
    }
}

pub trait EventHandler<T: Event, D> {
    fn handle_event(&mut self, event: T, shared_data: &mut D);
    fn handle(&self) -> T::Handle;
}

pub trait EventDemultiplexer {
    type Event: Event;
    fn select(&mut self) -> Option<Self::Event>;
}

pub trait Reactor {
    type Event: Event;
    fn handle_events(&mut self);
    fn register_handler(&mut self, handler: Box<for<'a> EventHandler<Self::Event, SharedData<'a>>>);
    fn remove_handler_by_handle(&mut self,
                                 handler: &<<Self as Reactor>::Event as Event>::Handle);
}

pub trait Event {
    type Handle;
    fn handle(&self) -> Self::Handle;
}
<|endoftext|>