<commit_before>use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty};
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_tool_lint, lint_array};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use syntax::ast::{Lit, LitKind, Name};
use syntax::source_map::{Span, Spanned};

declare_clippy_lint! {
    /// **What it does:** Checks for getting the length of something via `.len()`
    /// just to compare to zero, and suggests using `.is_empty()` where applicable.
    ///
    /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
    /// than calculating their length. Notably, for slices, getting the length
    /// requires a subtraction whereas `.is_empty()` is just a comparison. So it is
    /// good to get into the habit of using `.is_empty()`, and having it is cheap.
    /// Besides, it makes the intent clearer than a manual comparison.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// if x.len() == 0 {
    ///     ..
    /// }
    /// if y.len() != 0 {
    ///     ..
    /// }
    /// ```
    /// instead use
    /// ```ignore
    /// if x.is_empty() {
    ///     ..
    /// }
    /// if !y.is_empty() {
    ///     ..
    /// }
    /// ```
    pub LEN_ZERO,
    style,
    "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead"
}

declare_clippy_lint! {
    /// **What it does:** Checks for items that implement `.len()` but not
    /// `.is_empty()`.
    ///
    /// **Why is this bad?** It is good custom to have both methods, because for
    /// some data structures, asking about the length will be a costly operation,
    /// whereas `.is_empty()` can usually answer in constant time. Also it used to
    /// lead to false positives on the [`len_zero`](#len_zero) lint – currently that
    /// lint will ignore such entities.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl X {
    ///     pub fn len(&self) -> usize {
    ///         ..
    ///     }
    /// }
    /// ```
    pub LEN_WITHOUT_IS_EMPTY,
    style,
    "traits or impls with a public `len` method but no corresponding `is_empty` method"
}

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

impl LintPass for LenZero {
    fn get_lints(&self) -> LintArray {
        lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY)
    }

    fn name(&self) -> &'static str {
        "LenZero"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro(item.span) {
            return;
        }

        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
            ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
            _ => (),
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if in_macro(expr.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
            match cmp {
                BinOpKind::Eq => {
                    check_cmp(cx, expr.span, left, right, "", 0); // len == 0
                    check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
                },
                BinOpKind::Ne => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
                },
                BinOpKind::Gt => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
                    check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
                },
                BinOpKind::Lt => {
                    check_cmp(cx, expr.span, left, right, "", 1); // len < 1
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
                },
                BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
                BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
                _ => (),
            }
        }
    }
}

fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
        item.ident.name == name
            && if let AssociatedItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id_from_hir_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    // fill the set with current and super traits
    fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_, '_>) {
        if set.insert(traitt) {
            for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
                fill_trait_set(supertrait, set, cx);
            }
        }
    }

    if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
        let mut current_and_super_traits = FxHashSet::default();
        let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id);
        fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);

        let is_empty_method_found = current_and_super_traits
            .iter()
            .flat_map(|&i| cx.tcx.associated_items(i))
            .any(|i| {
                i.kind == ty::AssociatedKind::Method
                    && i.method_has_self_argument
                    && i.ident.name == "is_empty"
                    && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
            });

        if !is_empty_method_found {
            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                visited_trait.span,
                &format!(
                    "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
                    visited_trait.ident.name
                ),
            );
        }
    }
}

fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
        item.ident.name == name
            && if let AssociatedItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id_from_hir_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
        if cx
            .access_levels
            .is_exported(is_empty.id.hir_id)
        {
            return;
        } else {
            "a private"
        }
    } else {
        "no corresponding"
    };

    if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
        if cx.access_levels.is_exported(i.id.hir_id) {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
            let ty = cx.tcx.type_of(def_id);

            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                item.span,
                &format!(
                    "item `{}` has a public `len` method but {} `is_empty` method",
                    ty, is_empty
                ),
            );
        }
    }
}

fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
    if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
        // check if we are in an is_empty() method
        if let Some(name) = get_item_name(cx, method) {
            if name == "is_empty" {
                return;
            }
        }

        check_len(cx, span, method_path.ident.name, args, lit, op, compare_to)
    }
}

fn check_len(
    cx: &LateContext<'_, '_>,
    span: Span,
    method_name: Name,
    args: &[Expr],
    lit: &Lit,
    op: &str,
    compare_to: u32,
) {
    if let Spanned {
        node: LitKind::Int(lit, _),
        ..
    } = *lit
    {
        // check if length is compared to the specified number
        if lit != u128::from(compare_to) {
            return;
        }

        if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                LEN_ZERO,
                span,
                &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
                "using `is_empty` is clearer and more explicit",
                format!(
                    "{}{}.is_empty()",
                    op,
                    snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
                ),
                applicability,
            );
        }
    }
}

/// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    /// Gets an `AssociatedItem` and return true if it matches `is_empty(self)`.
    fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool {
        if let ty::AssociatedKind::Method = item.kind {
            if item.ident.name == "is_empty" {
                let sig = cx.tcx.fn_sig(item.def_id);
                let ty = sig.skip_binder();
                ty.inputs().len() == 1
            } else {
                false
            }
        } else {
            false
        }
    }

    /// Checks the inherent impl's items for an `is_empty(self)` method.
    fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
        cx.tcx
            .inherent_impls(id)
            .iter()
            .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item)))
    }

    let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
    match ty.sty {
        ty::Dynamic(ref tt, ..) => {
            if let Some(principal) = tt.principal() {
                cx.tcx
                    .associated_items(principal.def_id())
                    .any(|item| is_is_empty(cx, &item))
            } else {
                false
            }
        },
        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
        ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
        ty::Array(..) | ty::Slice(..) | ty::Str => true,
        _ => false,
    }
}
<commit_msg>run cargo fmt<commit_after>use crate::utils::{get_item_name, in_macro, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty};
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_tool_lint, lint_array};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use syntax::ast::{Lit, LitKind, Name};
use syntax::source_map::{Span, Spanned};

declare_clippy_lint! {
    /// **What it does:** Checks for getting the length of something via `.len()`
    /// just to compare to zero, and suggests using `.is_empty()` where applicable.
    ///
    /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
    /// than calculating their length. Notably, for slices, getting the length
    /// requires a subtraction whereas `.is_empty()` is just a comparison. So it is
    /// good to get into the habit of using `.is_empty()`, and having it is cheap.
    /// Besides, it makes the intent clearer than a manual comparison.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// if x.len() == 0 {
    ///     ..
    /// }
    /// if y.len() != 0 {
    ///     ..
    /// }
    /// ```
    /// instead use
    /// ```ignore
    /// if x.is_empty() {
    ///     ..
    /// }
    /// if !y.is_empty() {
    ///     ..
    /// }
    /// ```
    pub LEN_ZERO,
    style,
    "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead"
}

declare_clippy_lint! {
    /// **What it does:** Checks for items that implement `.len()` but not
    /// `.is_empty()`.
    ///
    /// **Why is this bad?** It is good custom to have both methods, because for
    /// some data structures, asking about the length will be a costly operation,
    /// whereas `.is_empty()` can usually answer in constant time. Also it used to
    /// lead to false positives on the [`len_zero`](#len_zero) lint – currently that
    /// lint will ignore such entities.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl X {
    ///     pub fn len(&self) -> usize {
    ///         ..
    ///     }
    /// }
    /// ```
    pub LEN_WITHOUT_IS_EMPTY,
    style,
    "traits or impls with a public `len` method but no corresponding `is_empty` method"
}

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

impl LintPass for LenZero {
    fn get_lints(&self) -> LintArray {
        lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY)
    }

    fn name(&self) -> &'static str {
        "LenZero"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro(item.span) {
            return;
        }

        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
            ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
            _ => (),
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if in_macro(expr.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
            match cmp {
                BinOpKind::Eq => {
                    check_cmp(cx, expr.span, left, right, "", 0); // len == 0
                    check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
                },
                BinOpKind::Ne => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
                },
                BinOpKind::Gt => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
                    check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
                },
                BinOpKind::Lt => {
                    check_cmp(cx, expr.span, left, right, "", 1); // len < 1
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
                },
                BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
                BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
                _ => (),
            }
        }
    }
}

fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
        item.ident.name == name
            && if let AssociatedItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id_from_hir_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    // fill the set with current and super traits
    fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_, '_>) {
        if set.insert(traitt) {
            for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
                fill_trait_set(supertrait, set, cx);
            }
        }
    }

    if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
        let mut current_and_super_traits = FxHashSet::default();
        let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id);
        fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);

        let is_empty_method_found = current_and_super_traits
            .iter()
            .flat_map(|&i| cx.tcx.associated_items(i))
            .any(|i| {
                i.kind == ty::AssociatedKind::Method
                    && i.method_has_self_argument
                    && i.ident.name == "is_empty"
                    && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
            });

        if !is_empty_method_found {
            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                visited_trait.span,
                &format!(
                    "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
                    visited_trait.ident.name
                ),
            );
        }
    }
}

fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
        item.ident.name == name
            && if let AssociatedItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id_from_hir_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
        if cx.access_levels.is_exported(is_empty.id.hir_id) {
            return;
        } else {
            "a private"
        }
    } else {
        "no corresponding"
    };

    if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
        if cx.access_levels.is_exported(i.id.hir_id) {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
            let ty = cx.tcx.type_of(def_id);

            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                item.span,
                &format!(
                    "item `{}` has a public `len` method but {} `is_empty` method",
                    ty, is_empty
                ),
            );
        }
    }
}

fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
    if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
        // check if we are in an is_empty() method
        if let Some(name) = get_item_name(cx, method) {
            if name == "is_empty" {
                return;
            }
        }

        check_len(cx, span, method_path.ident.name, args, lit, op, compare_to)
    }
}

fn check_len(
    cx: &LateContext<'_, '_>,
    span: Span,
    method_name: Name,
    args: &[Expr],
    lit: &Lit,
    op: &str,
    compare_to: u32,
) {
    if let Spanned {
        node: LitKind::Int(lit, _),
        ..
    } = *lit
    {
        // check if length is compared to the specified number
        if lit != u128::from(compare_to) {
            return;
        }

        if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                LEN_ZERO,
                span,
                &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
                "using `is_empty` is clearer and more explicit",
                format!(
                    "{}{}.is_empty()",
                    op,
                    snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
                ),
                applicability,
            );
        }
    }
}

/// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    /// Gets an `AssociatedItem` and return true if it matches `is_empty(self)`.
    fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool {
        if let ty::AssociatedKind::Method = item.kind {
            if item.ident.name == "is_empty" {
                let sig = cx.tcx.fn_sig(item.def_id);
                let ty = sig.skip_binder();
                ty.inputs().len() == 1
            } else {
                false
            }
        } else {
            false
        }
    }

    /// Checks the inherent impl's items for an `is_empty(self)` method.
    fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
        cx.tcx
            .inherent_impls(id)
            .iter()
            .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item)))
    }

    let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
    match ty.sty {
        ty::Dynamic(ref tt, ..) => {
            if let Some(principal) = tt.principal() {
                cx.tcx
                    .associated_items(principal.def_id())
                    .any(|item| is_is_empty(cx, &item))
            } else {
                false
            }
        },
        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
        ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
        ty::Array(..) | ty::Slice(..) | ty::Str => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use decoders::RawImage;
use imageops::{OpBuffer,ImageOp,Pipeline};

#[derive(Copy, Clone, Debug)]
pub struct OpBaseCurve {
}

impl OpBaseCurve {
  pub fn new(_img: &RawImage) -> OpBaseCurve {
    OpBaseCurve{}
  }
}

impl ImageOp for OpBaseCurve {
  fn name(&self) -> &str {"basecurve"}
  fn run(&self, pipeline: &Pipeline, buf: &OpBuffer) -> OpBuffer {
    base(pipeline.image, buf)
  }
}

pub fn base(_: &RawImage, buf: &OpBuffer) -> OpBuffer {
  let mut buf = buf.clone();

  let xs = [0.0, 0.30, 0.5, 0.70, 1.0];
  let ys = [0.0, 0.25, 0.5, 0.75, 1.0];
  let func = SplineFunc::new(&xs, &ys);

  buf.mutate_lines(&(|line: &mut [f32], _| {
    for pix in line.chunks_mut(3) {
      pix[0] = func.interpolate(pix[0]);
      pix[1] = pix[1];
      pix[2] = pix[2];
    }
  }));

  buf
}

struct SplineFunc<'a> {
  xs: &'a [f32],
  ys: &'a [f32],
  c1s: Vec<f32>,
  c2s: Vec<f32>,
  c3s: Vec<f32>,
}

impl<'a> SplineFunc<'a> {
  // Monotone cubic interpolation code adapted from the Javascript example in Wikipedia
  fn new(xs: &'a[f32], ys: &'a[f32]) -> SplineFunc<'a> {
    if xs.len() != ys.len() { panic!("Different number of Xs and Ys for Spline"); }
    if xs.len() < 2 { panic!("Need at least 2 points for Spline"); }

	  // Get consecutive differences and slopes
    let mut dxs = Vec::new();
    let mut dys = Vec::new();
    let mut slopes = Vec::new();
    for i in 0..(xs.len()-1) {
      let dx = xs[i+1] - xs[i];
      let dy = ys[i+1] - ys[i];
      dxs.push(dx);
      dys.push(dy);
      slopes.push(dy/dx);
    }

	  // Get degree-1 coefficients
    let mut c1s = vec![slopes[0]];
    for i in 0..(dxs.len()-1) {
      let m = slopes[i];
      let next = slopes[i+1];
      if m*next <= 0.0 {
        c1s.push(0.0);
      } else {
        let dx = dxs[i];
        let dxnext = dxs[i+1];
        let common = dx + dxnext;
        c1s.push(3.0*common/((common+dxnext)/m + (common + dx)/next));
      }
    }
    c1s.push(slopes[slopes.len()-1]);

	  // Get degree-2 and degree-3 coefficients
    let mut c2s = Vec::new();
    let mut c3s = Vec::new();
    for i in 0..(c1s.len()-1) {
      let c1 = c1s[i];
      let slope = slopes[i];
      let invdx = 1.0 / dxs[i];
      let common = c1+c1s[i+1] - slope - slope;
      c2s.push((slope-c1-common)*invdx);
      c3s.push(common*invdx*invdx);
    }

    SplineFunc {
      xs: xs,
      ys: ys,
        c1s: c1s,
      c2s: c2s,
      c3s: c3s,
    }
  }

  fn interpolate(&self, val: f32) -> f32 {
		// Anything at or beyond the last value returns the last value
    let end = self.xs[self.xs.len()-1];
    if val >= end {
      return self.ys[self.ys.len()-1];
    }

		// Search for the interval x is in, returning the corresponding y if x is one of the original xs
    let mut low: isize = 0;
    let mut mid: isize;
    let mut high: isize = (self.c3s.len() - 1) as isize;

		while low <= high {
      mid = (low+high)/2;
      let xhere = self.xs[mid as usize];
      if xhere < val { low = mid + 1; }
      else if xhere > val { high = mid - 1; }
      else { return self.ys[mid as usize] }
		}
    let i = cmp::max(0, high) as usize;

		// Interpolate
    let diff = val - self.xs[i];

    self.ys[i] + self.c1s[i]*diff + self.c2s[i]*diff*diff + self.c3s[i]*diff*diff*diff
	}
}
<commit_msg>basecurve: store all settings in the struct<commit_after>use std::cmp;
use decoders::RawImage;
use imageops::{OpBuffer,ImageOp,Pipeline};

#[derive(Clone, Debug)]
pub struct OpBaseCurve {
  xs: Vec<f32>,
  ys: Vec<f32>,
}

impl OpBaseCurve {
  pub fn new(_img: &RawImage) -> OpBaseCurve {
    OpBaseCurve{
      xs: vec![0.0, 0.30, 0.5, 0.70, 1.0],
      ys: vec![0.0, 0.25, 0.5, 0.75, 1.0],
    }
  }
}

impl ImageOp for OpBaseCurve {
  fn name(&self) -> &str {"basecurve"}
  fn run(&self, _pipeline: &Pipeline, buf: &OpBuffer) -> OpBuffer {
    let mut buf = buf.clone();
    let func = SplineFunc::new(&self.xs, &self.ys);

    buf.mutate_lines(&(|line: &mut [f32], _| {
      for pix in line.chunks_mut(3) {
        pix[0] = func.interpolate(pix[0]);
        pix[1] = pix[1];
        pix[2] = pix[2];
      }
    }));

    buf
  }
}

struct SplineFunc<'a> {
  xs: &'a [f32],
  ys: &'a [f32],
  c1s: Vec<f32>,
  c2s: Vec<f32>,
  c3s: Vec<f32>,
}

impl<'a> SplineFunc<'a> {
  // Monotone cubic interpolation code adapted from the Javascript example in Wikipedia
  fn new(xs: &'a[f32], ys: &'a[f32]) -> SplineFunc<'a> {
    if xs.len() != ys.len() { panic!("Different number of Xs and Ys for Spline"); }
    if xs.len() < 2 { panic!("Need at least 2 points for Spline"); }

	  // Get consecutive differences and slopes
    let mut dxs = Vec::new();
    let mut dys = Vec::new();
    let mut slopes = Vec::new();
    for i in 0..(xs.len()-1) {
      let dx = xs[i+1] - xs[i];
      let dy = ys[i+1] - ys[i];
      dxs.push(dx);
      dys.push(dy);
      slopes.push(dy/dx);
    }

	  // Get degree-1 coefficients
    let mut c1s = vec![slopes[0]];
    for i in 0..(dxs.len()-1) {
      let m = slopes[i];
      let next = slopes[i+1];
      if m*next <= 0.0 {
        c1s.push(0.0);
      } else {
        let dx = dxs[i];
        let dxnext = dxs[i+1];
        let common = dx + dxnext;
        c1s.push(3.0*common/((common+dxnext)/m + (common + dx)/next));
      }
    }
    c1s.push(slopes[slopes.len()-1]);

	  // Get degree-2 and degree-3 coefficients
    let mut c2s = Vec::new();
    let mut c3s = Vec::new();
    for i in 0..(c1s.len()-1) {
      let c1 = c1s[i];
      let slope = slopes[i];
      let invdx = 1.0 / dxs[i];
      let common = c1+c1s[i+1] - slope - slope;
      c2s.push((slope-c1-common)*invdx);
      c3s.push(common*invdx*invdx);
    }

    SplineFunc {
      xs: xs,
      ys: ys,
        c1s: c1s,
      c2s: c2s,
      c3s: c3s,
    }
  }

  fn interpolate(&self, val: f32) -> f32 {
		// Anything at or beyond the last value returns the last value
    let end = self.xs[self.xs.len()-1];
    if val >= end {
      return self.ys[self.ys.len()-1];
    }

		// Search for the interval x is in, returning the corresponding y if x is one of the original xs
    let mut low: isize = 0;
    let mut mid: isize;
    let mut high: isize = (self.c3s.len() - 1) as isize;

		while low <= high {
      mid = (low+high)/2;
      let xhere = self.xs[mid as usize];
      if xhere < val { low = mid + 1; }
      else if xhere > val { high = mid - 1; }
      else { return self.ys[mid as usize] }
		}
    let i = cmp::max(0, high) as usize;

		// Interpolate
    let diff = val - self.xs[i];

    self.ys[i] + self.c1s[i]*diff + self.c2s[i]*diff*diff + self.c3s[i]*diff*diff*diff
	}
}
<|endoftext|>


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

//! The trait for types that can be created from strings

use option::Option;

/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
pub trait FromStr {
    /// Parses a string `s` to return an optional value of this type. If the
    /// string is ill-formatted, the None is returned.
    fn from_str(s: &str) -> Option<Self>;
}

pub fn from_str<A: FromStr>(s: &str) -> Option<A> {
    FromStr::from_str(s)
}
<commit_msg>Add from_str docs<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The trait for types that can be created from strings

use option::Option;

/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
pub trait FromStr {
    /// Parses a string `s` to return an optional value of this type. If the
    /// string is ill-formatted, the None is returned.
    fn from_str(s: &str) -> Option<Self>;
}

/// A utility function that just calls FromStr::from_str
pub fn from_str<A: FromStr>(s: &str) -> Option<A> {
    FromStr::from_str(s)
}
<|endoftext|>


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

//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency
//! between layout and style.

use attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
use matching::{ElementSelectorFlags, MatchingContext};
use parser::SelectorImpl;
use servo_arc::NonZeroPtrMut;
use std::fmt::Debug;

/// Opaque representation of an Element, for identity comparisons. We use
/// NonZeroPtrMut to get the NonZero optimization.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct OpaqueElement(NonZeroPtrMut<()>);

impl OpaqueElement {
    /// Creates a new OpaqueElement from an arbitrarily-typed pointer.
    pub fn new<T>(ptr: *const T) -> Self {
        OpaqueElement(NonZeroPtrMut::new(ptr as *const () as *mut ()))
    }
}

pub trait Element: Sized + Clone + Debug {
    type Impl: SelectorImpl;

    /// Converts self into an opaque representation.
    fn opaque(&self) -> OpaqueElement;

    fn parent_element(&self) -> Option<Self>;

    /// The parent of a given pseudo-element, after matching a pseudo-element
    /// selector.
    ///
    /// This is guaranteed to be called in a pseudo-element.
    fn pseudo_element_originating_element(&self) -> Option<Self> {
        self.parent_element()
    }

    /// Skips non-element nodes
    fn first_child_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn last_child_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn prev_sibling_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn next_sibling_element(&self) -> Option<Self>;

    fn is_html_element_in_html_document(&self) -> bool;

    fn local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;

    /// Empty string for no namespace
    fn namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;

    fn attr_matches(&self,
                    ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
                    local_name: &<Self::Impl as SelectorImpl>::LocalName,
                    operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>)
                    -> bool;

    fn match_non_ts_pseudo_class<F>(
        &self,
        pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
        context: &mut MatchingContext<Self::Impl>,
        flags_setter: &mut F,
    ) -> bool
    where
        F: FnMut(&Self, ElementSelectorFlags);

    fn match_pseudo_element(
        &self,
        pe: &<Self::Impl as SelectorImpl>::PseudoElement,
        context: &mut MatchingContext<Self::Impl>,
    ) -> bool;

    /// Whether this element is a `link`.
    fn is_link(&self) -> bool;

    /// Returns whether the element is an HTML <slot> element.
    fn is_html_slot_element(&self) -> bool;

    /// Returns the assigned <slot> element this element is assigned to.
    ///
    /// Necessary for the `::slotted` pseudo-class.
    fn assigned_slot(&self) -> Option<Self> {
        None
    }

    fn has_id(
        &self,
        id: &<Self::Impl as SelectorImpl>::Identifier,
        case_sensitivity: CaseSensitivity,
    ) -> bool;

    fn has_class(
        &self,
        name: &<Self::Impl as SelectorImpl>::ClassName,
        case_sensitivity: CaseSensitivity,
    ) -> bool;

    /// Returns whether this element matches `:empty`.
    ///
    /// That is, whether it does not contain any child element or any non-zero-length text node.
    /// See http://dev.w3.org/csswg/selectors-3/#empty-pseudo
    fn is_empty(&self) -> bool;

    /// Returns whether this element matches `:root`,
    /// i.e. whether it is the root element of a document.
    ///
    /// Note: this can be false even if `.parent_element()` is `None`
    /// if the parent node is a `DocumentFragment`.
    fn is_root(&self) -> bool;

    /// Returns whether this element should ignore matching nth child
    /// selector.
    fn ignores_nth_child_selectors(&self) -> bool {
        false
    }

    /// Return true if we want to stop lookup ancestor of the current
    /// element while matching complex selectors with descendant/child
    /// combinator.
    fn blocks_ancestor_combinators(&self) -> bool {
        false
    }
}
<commit_msg>style: Reindent yet another function.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency
//! between layout and style.

use attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
use matching::{ElementSelectorFlags, MatchingContext};
use parser::SelectorImpl;
use servo_arc::NonZeroPtrMut;
use std::fmt::Debug;

/// Opaque representation of an Element, for identity comparisons. We use
/// NonZeroPtrMut to get the NonZero optimization.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct OpaqueElement(NonZeroPtrMut<()>);

impl OpaqueElement {
    /// Creates a new OpaqueElement from an arbitrarily-typed pointer.
    pub fn new<T>(ptr: *const T) -> Self {
        OpaqueElement(NonZeroPtrMut::new(ptr as *const () as *mut ()))
    }
}

pub trait Element: Sized + Clone + Debug {
    type Impl: SelectorImpl;

    /// Converts self into an opaque representation.
    fn opaque(&self) -> OpaqueElement;

    fn parent_element(&self) -> Option<Self>;

    /// The parent of a given pseudo-element, after matching a pseudo-element
    /// selector.
    ///
    /// This is guaranteed to be called in a pseudo-element.
    fn pseudo_element_originating_element(&self) -> Option<Self> {
        self.parent_element()
    }

    /// Skips non-element nodes
    fn first_child_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn last_child_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn prev_sibling_element(&self) -> Option<Self>;

    /// Skips non-element nodes
    fn next_sibling_element(&self) -> Option<Self>;

    fn is_html_element_in_html_document(&self) -> bool;

    fn local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;

    /// Empty string for no namespace
    fn namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;

    fn attr_matches(
        &self,
        ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
        local_name: &<Self::Impl as SelectorImpl>::LocalName,
        operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>,
    ) -> bool;

    fn match_non_ts_pseudo_class<F>(
        &self,
        pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
        context: &mut MatchingContext<Self::Impl>,
        flags_setter: &mut F,
    ) -> bool
    where
        F: FnMut(&Self, ElementSelectorFlags);

    fn match_pseudo_element(
        &self,
        pe: &<Self::Impl as SelectorImpl>::PseudoElement,
        context: &mut MatchingContext<Self::Impl>,
    ) -> bool;

    /// Whether this element is a `link`.
    fn is_link(&self) -> bool;

    /// Returns whether the element is an HTML <slot> element.
    fn is_html_slot_element(&self) -> bool;

    /// Returns the assigned <slot> element this element is assigned to.
    ///
    /// Necessary for the `::slotted` pseudo-class.
    fn assigned_slot(&self) -> Option<Self> {
        None
    }

    fn has_id(
        &self,
        id: &<Self::Impl as SelectorImpl>::Identifier,
        case_sensitivity: CaseSensitivity,
    ) -> bool;

    fn has_class(
        &self,
        name: &<Self::Impl as SelectorImpl>::ClassName,
        case_sensitivity: CaseSensitivity,
    ) -> bool;

    /// Returns whether this element matches `:empty`.
    ///
    /// That is, whether it does not contain any child element or any non-zero-length text node.
    /// See http://dev.w3.org/csswg/selectors-3/#empty-pseudo
    fn is_empty(&self) -> bool;

    /// Returns whether this element matches `:root`,
    /// i.e. whether it is the root element of a document.
    ///
    /// Note: this can be false even if `.parent_element()` is `None`
    /// if the parent node is a `DocumentFragment`.
    fn is_root(&self) -> bool;

    /// Returns whether this element should ignore matching nth child
    /// selector.
    fn ignores_nth_child_selectors(&self) -> bool {
        false
    }

    /// Return true if we want to stop lookup ancestor of the current
    /// element while matching complex selectors with descendant/child
    /// combinator.
    fn blocks_ancestor_combinators(&self) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>use std::any::TypeId;

use crate::{
    css_engine::*,
    prelude::*,
    utils::{Brush, String16, Thickness},
};

use dces::prelude::{Component, Entity, EntityComponentManager};

/// The `WidgetContainer` wraps the entity of a widget and provides access to its properties, its children properties and its parent properties.
pub struct WidgetContainer<'a> {
    ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
    current_node: Entity,
    theme: &'a ThemeValue,
}

impl<'a> WidgetContainer<'a> {
    /// Creates a new widget container for the given `entity`.
    pub fn new(
        root: Entity,
        ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
        theme: &'a ThemeValue,
    ) -> Self {
        WidgetContainer {
            ecm,
            current_node: root,
            theme,
        }
    }

    /// Gets the entity of the widget.
    pub fn entity(&self) -> Entity {
        self.current_node
    }

    /// Gets the property.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn get
(&self, key: &str) -> &P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property;
        }

       let name = self.get_name();

       panic!(
       "Widget with name: {} and entity: {} does not contain property width type_id {:?} for key: {}",
       name,
       self.current_node.0,
       TypeId::of::
(),
       key
    );
    }

    /// Gets a mutable reference of the property of type `P`.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn get_mut
(&mut self, key: &str) -> &mut P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self
            .ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
        {
            return property;
        }

        panic!(
            "Entity {} does not contain property type {:?}, with key: {}",
            self.current_node.0,
            TypeId::of::
(),
            key
        );
    }

    /// Clones the property. If the property does not exists for the widget the
    /// default of the property value will be returned,
    pub fn clone_or_default
(&self, key: &str) -> P
    where
        P: Clone + Component + Default,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property.clone();
        }

        P::default()
    }

    /// Clones the property.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn clone
(&self, key: &str) -> P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property.clone();
        }

        let name = self.get_name();

        panic!(
        "Widget with name: {} and entity: {} does not contain property width type_id {:?} for key: {}",
        name,
        self.current_node.0,
        TypeId::of::
(),
        key
    );
    }

    /// Clones the property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_clone
(&self, key: &str) -> Option

    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return Some(property.clone());
        }

        None
    }

    /// Sets the property of type `P`.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn set
(&mut self, key: &str, value: P)
    where
        P: Component + Clone,
    {
        if let Ok(property) = self
            .ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
        {
            *property = value;
            return;
        }

        let name = self.get_name();

        panic!(
            "Widget with name: {} and entity: {} does not contain property width type_id {:?} for key: {}",
            name,
            self.current_node.0,
            TypeId::of::
(),
            key
        );
    }

    /// Returns `true` if the widget has a property of type `P` otherwise `false`.
    pub fn has
(&self, key: &str) -> bool
    where
        P: Clone + Component,
    {
        self.ecm
            .component_store()
            .get::
(key, self.current_node)
            .is_ok()
    }

    /// Returns a reference of a property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_get
(&self, key: &str) -> Option<&P> {
        self.ecm
            .component_store()
            .get::
(key, self.current_node)
            .ok()
    }

    /// Returns a mutable reference of a property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_get_mut
(&mut self, key: &str) -> Option<&mut P> {
        self.ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
            .ok()
    }

    /// Checks if the given value is equal to the given property.
    pub fn eq
(&self, key: &str, other: &P) -> bool {
        if let Some(value) = self.try_get::
(key) {
            return value.eq(other);
        }

        false
    }

    fn update_internal_theme_by_state(&mut self, force: bool, entity: &Entity) {
        for child in &(self.ecm.entity_store().children.clone())[&entity] {
            self.update_internal_theme_by_state(force, child);
        }

        self.current_node = *entity;

        if let Some(selector) = self.try_clone::<Selector>("selector") {
            let mut update = false;

            if let Some(focus) = self.try_clone::<bool>("focused") {
                if focus && !selector.pseudo_classes.contains("focus") {
                    add_selector_to_widget("focus", self);
                    update = true;
                } else if !focus && selector.pseudo_classes.contains("focus") {
                    remove_selector_from_widget("focus", self);
                    update = true;
                }
            }

            if let Some(selected) = self.try_clone::<bool>("selected") {
                if selected && !selector.pseudo_classes.contains("selected") {
                    add_selector_to_widget("selected", self);
                    update = true;
                } else if !selected && selector.pseudo_classes.contains("selected") {
                    remove_selector_from_widget("selected", self);
                    update = true;
                }
            }

            if let Some(pressed) = self.try_clone::<bool>("pressed") {
                if pressed && !selector.pseudo_classes.contains("active") {
                    add_selector_to_widget("active", self);
                    update = true;
                } else if !pressed && selector.pseudo_classes.contains("active") {
                    remove_selector_from_widget("active", self);
                    update = true;
                }
            }

            if let Some(enabled) = self.try_clone::<bool>("enabled") {
                if !enabled && !selector.pseudo_classes.contains("disabled") {
                    add_selector_to_widget("disabled", self);
                    update = true;
                } else if enabled && selector.pseudo_classes.contains("disabled") {
                    remove_selector_from_widget("disabled", self);
                    update = true;
                }
            }

            if let Some(text) = self.try_clone::<String16>("text") {
                if text.is_empty() && !selector.pseudo_classes.contains("empty") {
                    add_selector_to_widget("empty", self);
                    update = true;
                } else if !text.is_empty() && selector.pseudo_classes.contains("empty") {
                    remove_selector_from_widget("empty", self);
                    update = true;
                }
            }

            if let Some(expanded) = self.try_clone::<bool>("expanded") {
                if expanded && !selector.pseudo_classes.contains("expanded") {
                    add_selector_to_widget("expanded", self);
                    update = true;
                } else if !expanded && selector.pseudo_classes.contains("expanded") {
                    remove_selector_from_widget("expanded", self);
                    update = true;
                }
            }

            if update || force {
                self.update_properties_by_theme();
            }
        }
    }

    /// Updates the theme by the inner state e.g. `selected` or `pressed`.
    pub fn update_theme_by_state(&mut self, force: bool) {
        self.update_internal_theme_by_state(force, &(self.current_node.clone()));
    }

    /// Update all properties for the theme.
    pub fn update_properties_by_theme(&mut self) {
        if !self.has::<Selector>("selector") {
            return;
        }

        let selector = self.clone::<Selector>("selector");

        if !selector.dirty() {
            return;
        }

        if self.has::<Brush>("foreground") {
            if let Some(color) = self.theme.brush("color", &selector) {
                self.set::<Brush>("foreground", color);
            }
        }

        if self.has::<Brush>("background") {
            if let Some(background) = self.theme.brush("background", &selector) {
                self.set::<Brush>("background", background);
            }
        }

        if self.has::<Brush>("border_brush") {
            if let Some(border_brush) = self.theme.brush("border-color", &selector) {
                self.set::<Brush>("border_brush", border_brush);
            }
        }

        if self.has::<f64>("border_radius") {
            if let Some(radius) = self.theme.uint("border-radius", &selector) {
                self.set::<f64>("border_radius", f64::from(radius));
            }
        }

        if self.has::<f32>("opacity") {
            if let Some(opacity) = self.theme.float("opacity", &selector) {
                self.set::<f32>("opacity", opacity);
            }
        }

        if self.has::<Thickness>("border_width") {
            if let Some(border_width) = self.theme.uint("border-width", &selector) {
                self.set::<Thickness>("border_width", Thickness::from(border_width as f64));
            }
        }

        self.update_font_properties_by_theme(&selector);

        if let Some(mut padding) = self.try_clone::<Thickness>("padding") {
            if let Some(pad) = self.theme.uint("padding", &selector) {
                padding.set_thickness(pad as f64);
            }

            if let Some(left) = self.theme.uint("padding-left", &selector) {
                padding.set_left(left as f64);
            }

            if let Some(top) = self.theme.uint("padding-top", &selector) {
                padding.set_top(top as f64);
            }

            if let Some(right) = self.theme.uint("padding-right", &selector) {
                padding.set_right(right as f64);
            }

            if let Some(bottom) = self.theme.uint("padding-bottom", &selector) {
                padding.set_bottom(bottom as f64);
            }
            self.set::<Thickness>("padding", padding);
        }

        if let Some(mut constraint) = self.try_clone::<Constraint>("constraint") {
            if let Some(width) = self.theme.uint("width", &selector) {
                constraint.set_width(width as f64);
            }

            if let Some(height) = self.theme.uint("height", &selector) {
                constraint.set_height(height as f64);
            }

            if let Some(min_width) = self.theme.uint("min-width", &selector) {
                constraint.set_min_width(min_width as f64);
            }

            if let Some(min_height) = self.theme.uint("min-height", &selector) {
                constraint.set_min_height(min_height as f64);
            }

            if let Some(max_width) = self.theme.uint("max-width", &selector) {
                constraint.set_max_width(max_width as f64);
            }

            if let Some(max_height) = self.theme.uint("max-height", &selector) {
                constraint.set_max_height(max_height as f64);
            }

            self.set::<Constraint>("constraint", constraint);
        }

        if self.has::<f64>("spacing") {
            if let Some(spacing) = self.theme.uint("spacing", &selector) {
                self.set::<f64>("spacing", spacing.into());
            }
        }

        self.get_mut::<Selector>("selector").set_dirty(true);
    }

    pub fn update_font_properties_by_theme(&mut self, selector: &Selector) {
        if self.has::<f64>("font_size") {
            if let Some(size) = self.theme.uint("font-size", selector) {
                self.set::<f64>("font_size", f64::from(size));
            }
        }

        if self.has::<String>("font_family") {
            if let Some(font_family) = self.theme.string("font-family", selector) {
                self.set::<String>("font_family", font_family);
            }
        }

        if self.has::<Brush>("icon_brush") {
            if let Some(color) = self.theme.brush("icon-color", selector) {
                self.set::<Brush>("icon_brush", color);
            }
        }

        if self.has::<f64>("icon_size") {
            if let Some(size) = self.theme.uint("icon-size", selector) {
                self.set::<f64>("icon_size", f64::from(size));
            }
        }

        if self.has::<String>("icon_family") {
            if let Some(font_family) = self.theme.string("icon-family", selector) {
                self.set::<String>("icon_family", font_family);
            }
        }
    }

    fn get_name(&self) -> String {
        self
        .ecm
        .component_store()
        .get::<String>("name", self.current_node)
        .unwrap()
        .clone()
    }
}
<commit_msg>Adjusted panic msgs,  printing type names instead of their id<commit_after>use std::any::type_name;

use crate::{
    css_engine::*,
    prelude::*,
    utils::{Brush, String16, Thickness},
};

use dces::prelude::{Component, Entity, EntityComponentManager};

/// The `WidgetContainer` wraps the entity of a widget and provides access to its properties, its children properties and its parent properties.
pub struct WidgetContainer<'a> {
    ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
    current_node: Entity,
    theme: &'a ThemeValue,
}

impl<'a> WidgetContainer<'a> {
    /// Creates a new widget container for the given `entity`.
    pub fn new(
        root: Entity,
        ecm: &'a mut EntityComponentManager<Tree, StringComponentStore>,
        theme: &'a ThemeValue,
    ) -> Self {
        WidgetContainer {
            ecm,
            current_node: root,
            theme,
        }
    }

    /// Gets the entity of the widget.
    pub fn entity(&self) -> Entity {
        self.current_node
    }

    /// Gets the property.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn get
(&self, key: &str) -> &P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property;
        }

        let name = self.get_name();

        panic!(
        "Widget: {} with entity: {} does not contain property with type {:?} for key: {}",
        name,
        self.current_node.0,
        type_name::
(),
        key
    );
    }

    /// Gets a mutable reference of the property of type `P`.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn get_mut
(&mut self, key: &str) -> &mut P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self
            .ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
        {
            return property;
        }

        panic!(
            "Entity {} does not contain property type {:?}, with key: {}",
            self.current_node.0,
            type_name::
(),
            key
        );
    }

    /// Clones the property. If the property does not exists for the widget the
    /// default of the property value will be returned,
    pub fn clone_or_default
(&self, key: &str) -> P
    where
        P: Clone + Component + Default,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property.clone();
        }

        P::default()
    }

    /// Clones the property.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn clone
(&self, key: &str) -> P
    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return property.clone();
        }

        let name = self.get_name();

        panic!(
        "Widget: {} with entity: {} does not contain property with type {:?} for key: {}",
        name,
        self.current_node.0,
        type_name::
(),
        key
    );
    }

    /// Clones the property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_clone
(&self, key: &str) -> Option

    where
        P: Clone + Component,
    {
        if let Ok(property) = self.ecm.component_store().get::
(key, self.current_node) {
            return Some(property.clone());
        }

        None
    }

    /// Sets the property of type `P`.
    ///
    /// # Panics
    ///
    /// Panics if the widget does not contains the property.
    pub fn set
(&mut self, key: &str, value: P)
    where
        P: Component + Clone,
    {
        if let Ok(property) = self
            .ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
        {
            *property = value;
            return;
        }

        let name = self.get_name();

        panic!(
            "Widget: {} with entity: {} does not contain property with type {:?} for key: {}",
            name,
            self.current_node.0,
            type_name::
(),
            key
        );
    }

    /// Returns `true` if the widget has a property of type `P` otherwise `false`.
    pub fn has
(&self, key: &str) -> bool
    where
        P: Clone + Component,
    {
        self.ecm
            .component_store()
            .get::
(key, self.current_node)
            .is_ok()
    }

    /// Returns a reference of a property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_get
(&self, key: &str) -> Option<&P> {
        self.ecm
            .component_store()
            .get::
(key, self.current_node)
            .ok()
    }

    /// Returns a mutable reference of a property of type `P` from the given widget entity. If the entity does
    /// not exists or it doesn't have a component of type `P` `None` will be returned.
    pub fn try_get_mut
(&mut self, key: &str) -> Option<&mut P> {
        self.ecm
            .component_store_mut()
            .get_mut::
(key, self.current_node)
            .ok()
    }

    /// Checks if the given value is equal to the given property.
    pub fn eq
(&self, key: &str, other: &P) -> bool {
        if let Some(value) = self.try_get::
(key) {
            return value.eq(other);
        }

        false
    }

    fn update_internal_theme_by_state(&mut self, force: bool, entity: &Entity) {
        for child in &(self.ecm.entity_store().children.clone())[&entity] {
            self.update_internal_theme_by_state(force, child);
        }

        self.current_node = *entity;

        if let Some(selector) = self.try_clone::<Selector>("selector") {
            let mut update = false;

            if let Some(focus) = self.try_clone::<bool>("focused") {
                if focus && !selector.pseudo_classes.contains("focus") {
                    add_selector_to_widget("focus", self);
                    update = true;
                } else if !focus && selector.pseudo_classes.contains("focus") {
                    remove_selector_from_widget("focus", self);
                    update = true;
                }
            }

            if let Some(selected) = self.try_clone::<bool>("selected") {
                if selected && !selector.pseudo_classes.contains("selected") {
                    add_selector_to_widget("selected", self);
                    update = true;
                } else if !selected && selector.pseudo_classes.contains("selected") {
                    remove_selector_from_widget("selected", self);
                    update = true;
                }
            }

            if let Some(pressed) = self.try_clone::<bool>("pressed") {
                if pressed && !selector.pseudo_classes.contains("active") {
                    add_selector_to_widget("active", self);
                    update = true;
                } else if !pressed && selector.pseudo_classes.contains("active") {
                    remove_selector_from_widget("active", self);
                    update = true;
                }
            }

            if let Some(enabled) = self.try_clone::<bool>("enabled") {
                if !enabled && !selector.pseudo_classes.contains("disabled") {
                    add_selector_to_widget("disabled", self);
                    update = true;
                } else if enabled && selector.pseudo_classes.contains("disabled") {
                    remove_selector_from_widget("disabled", self);
                    update = true;
                }
            }

            if let Some(text) = self.try_clone::<String16>("text") {
                if text.is_empty() && !selector.pseudo_classes.contains("empty") {
                    add_selector_to_widget("empty", self);
                    update = true;
                } else if !text.is_empty() && selector.pseudo_classes.contains("empty") {
                    remove_selector_from_widget("empty", self);
                    update = true;
                }
            }

            if let Some(expanded) = self.try_clone::<bool>("expanded") {
                if expanded && !selector.pseudo_classes.contains("expanded") {
                    add_selector_to_widget("expanded", self);
                    update = true;
                } else if !expanded && selector.pseudo_classes.contains("expanded") {
                    remove_selector_from_widget("expanded", self);
                    update = true;
                }
            }

            if update || force {
                self.update_properties_by_theme();
            }
        }
    }

    /// Updates the theme by the inner state e.g. `selected` or `pressed`.
    pub fn update_theme_by_state(&mut self, force: bool) {
        self.update_internal_theme_by_state(force, &(self.current_node.clone()));
    }

    /// Update all properties for the theme.
    pub fn update_properties_by_theme(&mut self) {
        if !self.has::<Selector>("selector") {
            return;
        }

        let selector = self.clone::<Selector>("selector");

        if !selector.dirty() {
            return;
        }

        if self.has::<Brush>("foreground") {
            if let Some(color) = self.theme.brush("color", &selector) {
                self.set::<Brush>("foreground", color);
            }
        }

        if self.has::<Brush>("background") {
            if let Some(background) = self.theme.brush("background", &selector) {
                self.set::<Brush>("background", background);
            }
        }

        if self.has::<Brush>("border_brush") {
            if let Some(border_brush) = self.theme.brush("border-color", &selector) {
                self.set::<Brush>("border_brush", border_brush);
            }
        }

        if self.has::<f64>("border_radius") {
            if let Some(radius) = self.theme.uint("border-radius", &selector) {
                self.set::<f64>("border_radius", f64::from(radius));
            }
        }

        if self.has::<f32>("opacity") {
            if let Some(opacity) = self.theme.float("opacity", &selector) {
                self.set::<f32>("opacity", opacity);
            }
        }

        if self.has::<Thickness>("border_width") {
            if let Some(border_width) = self.theme.uint("border-width", &selector) {
                self.set::<Thickness>("border_width", Thickness::from(border_width as f64));
            }
        }

        self.update_font_properties_by_theme(&selector);

        if let Some(mut padding) = self.try_clone::<Thickness>("padding") {
            if let Some(pad) = self.theme.uint("padding", &selector) {
                padding.set_thickness(pad as f64);
            }

            if let Some(left) = self.theme.uint("padding-left", &selector) {
                padding.set_left(left as f64);
            }

            if let Some(top) = self.theme.uint("padding-top", &selector) {
                padding.set_top(top as f64);
            }

            if let Some(right) = self.theme.uint("padding-right", &selector) {
                padding.set_right(right as f64);
            }

            if let Some(bottom) = self.theme.uint("padding-bottom", &selector) {
                padding.set_bottom(bottom as f64);
            }
            self.set::<Thickness>("padding", padding);
        }

        if let Some(mut constraint) = self.try_clone::<Constraint>("constraint") {
            if let Some(width) = self.theme.uint("width", &selector) {
                constraint.set_width(width as f64);
            }

            if let Some(height) = self.theme.uint("height", &selector) {
                constraint.set_height(height as f64);
            }

            if let Some(min_width) = self.theme.uint("min-width", &selector) {
                constraint.set_min_width(min_width as f64);
            }

            if let Some(min_height) = self.theme.uint("min-height", &selector) {
                constraint.set_min_height(min_height as f64);
            }

            if let Some(max_width) = self.theme.uint("max-width", &selector) {
                constraint.set_max_width(max_width as f64);
            }

            if let Some(max_height) = self.theme.uint("max-height", &selector) {
                constraint.set_max_height(max_height as f64);
            }

            self.set::<Constraint>("constraint", constraint);
        }

        if self.has::<f64>("spacing") {
            if let Some(spacing) = self.theme.uint("spacing", &selector) {
                self.set::<f64>("spacing", spacing.into());
            }
        }

        self.get_mut::<Selector>("selector").set_dirty(true);
    }

    pub fn update_font_properties_by_theme(&mut self, selector: &Selector) {
        if self.has::<f64>("font_size") {
            if let Some(size) = self.theme.uint("font-size", selector) {
                self.set::<f64>("font_size", f64::from(size));
            }
        }

        if self.has::<String>("font_family") {
            if let Some(font_family) = self.theme.string("font-family", selector) {
                self.set::<String>("font_family", font_family);
            }
        }

        if self.has::<Brush>("icon_brush") {
            if let Some(color) = self.theme.brush("icon-color", selector) {
                self.set::<Brush>("icon_brush", color);
            }
        }

        if self.has::<f64>("icon_size") {
            if let Some(size) = self.theme.uint("icon-size", selector) {
                self.set::<f64>("icon_size", f64::from(size));
            }
        }

        if self.has::<String>("icon_family") {
            if let Some(font_family) = self.theme.string("icon-family", selector) {
                self.set::<String>("icon_family", font_family);
            }
        }
    }

    fn get_name(&self) -> String {
        if self.has::<String>("name") {
            self
            .ecm
            .component_store()
            .get::<String>("name", self.current_node)
            .unwrap()
            .clone()
        } else {
            String::from("unknown")
        }
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;
use libimagutil::debug_result::*;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime;

pub struct CreateHook {
    storepath: PathBuf,

    runtime: Runtime,

    position: HookPosition,
}

impl CreateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> CreateHook {
        CreateHook {
            runtime: Runtime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for CreateHook {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for CreateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for CreateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for CreateHook {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;

        debug!("[GIT CREATE HOOK]: {:?}", id);

        debug!("[GIT CREATE HOOK]: Ensuring branch checkout");
        try!(self
             .runtime
             .ensure_cfg_branch_is_checked_out()
             .map_err(Box::new)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));
        debug!("[GIT CREATE HOOK]: Branch checked out");

        self.runtime
            .config_value_or_err()
            .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't get Value object from config")
            .and_then(|cfg| {
                debug!("[GIT CREATE HOOK]: Getting repository");
                self.runtime
                    .repository()
                    .map(|r| (r, cfg))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Repository")
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg)| {
                repo.signature()
                    .map(|s| (repo, cfg, s))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Signature")
                    .map_err_into(GHEK::RepositorySignatureFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig)| {
                repo.index()
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Index")
                    .and_then(|mut idx| idx.write_tree().map(|t| (idx, t)))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't write Tree")
                    .and_then(|(idx, tree_id)| repo.find_tree(tree_id).map(|t| (idx, t)))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't find Tree")
                    .map(|(idx, tree)| (repo, cfg, sig, idx, tree))
                    .map_err_into(GHEK::RepositoryIndexFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, mut idx, tree)| {
                idx.add_path(id)
                    .map(|_| (repo, cfg, sig, idx, tree))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't add Path")
                    .map_dbg_err(|_| format!("\tpath = {:?}", id))
                    .map_dbg_err(|e| format!("\terr  = {:?}", e))
                    .map_err_into(GHEK::RepositoryPathAddingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, idx, tree)| {
                repo.head()
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch HEAD")
                    .map_err_into(GHEK::RepositoryHeadFetchingError)
                    .map(|h| h.target())
                    .and_then(|oid| {
                        match oid {
                            Some(oid) => {
                                repo.find_commit(oid)
                                    .map(|c| Some(c))
                                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't find commit")
                                    .map_dbg_err(|_| format!("\toid = {:?}", oid))
                                    .map_err_into(GHEK::RepositoryCommitFindingError)
                            },
                            None => Ok(None),
                        }
                    })
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
                    .map(|parent| (repo, cfg, sig, idx, tree, parent))
            })
            .and_then(|(repo, cfg, sig, idx, tree, opt_parent)| {
                let (msg, parents) = match opt_parent {
                    None    => (String::from("Initial commit"), vec![]),
                    Some(p) => (commit_message(&cfg, StoreAction::Create), vec![p]),
                };

                let parents = parents.iter().collect::<Vec<_>>();
                repo.commit(Some("HEAD"), &sig, &sig, &msg[..], &tree, &parents)
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't commit")
                    .map_err_into(GHEK::RepositoryCommittingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .map(|_| ())
    }

}

<commit_msg>use Runtime as GRuntime, for clearness<commit_after>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;
use libimagutil::debug_result::*;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime as GRuntime;

pub struct CreateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl CreateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> CreateHook {
        CreateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for CreateHook {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for CreateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for CreateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for CreateHook {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;

        debug!("[GIT CREATE HOOK]: {:?}", id);

        debug!("[GIT CREATE HOOK]: Ensuring branch checkout");
        try!(self
             .runtime
             .ensure_cfg_branch_is_checked_out()
             .map_err(Box::new)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));
        debug!("[GIT CREATE HOOK]: Branch checked out");

        self.runtime
            .config_value_or_err()
            .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't get Value object from config")
            .and_then(|cfg| {
                debug!("[GIT CREATE HOOK]: Getting repository");
                self.runtime
                    .repository()
                    .map(|r| (r, cfg))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Repository")
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg)| {
                repo.signature()
                    .map(|s| (repo, cfg, s))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Signature")
                    .map_err_into(GHEK::RepositorySignatureFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig)| {
                repo.index()
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Index")
                    .and_then(|mut idx| idx.write_tree().map(|t| (idx, t)))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't write Tree")
                    .and_then(|(idx, tree_id)| repo.find_tree(tree_id).map(|t| (idx, t)))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't find Tree")
                    .map(|(idx, tree)| (repo, cfg, sig, idx, tree))
                    .map_err_into(GHEK::RepositoryIndexFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, mut idx, tree)| {
                idx.add_path(id)
                    .map(|_| (repo, cfg, sig, idx, tree))
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't add Path")
                    .map_dbg_err(|_| format!("\tpath = {:?}", id))
                    .map_dbg_err(|e| format!("\terr  = {:?}", e))
                    .map_err_into(GHEK::RepositoryPathAddingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, idx, tree)| {
                repo.head()
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch HEAD")
                    .map_err_into(GHEK::RepositoryHeadFetchingError)
                    .map(|h| h.target())
                    .and_then(|oid| {
                        match oid {
                            Some(oid) => {
                                repo.find_commit(oid)
                                    .map(|c| Some(c))
                                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't find commit")
                                    .map_dbg_err(|_| format!("\toid = {:?}", oid))
                                    .map_err_into(GHEK::RepositoryCommitFindingError)
                            },
                            None => Ok(None),
                        }
                    })
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
                    .map(|parent| (repo, cfg, sig, idx, tree, parent))
            })
            .and_then(|(repo, cfg, sig, idx, tree, opt_parent)| {
                let (msg, parents) = match opt_parent {
                    None    => (String::from("Initial commit"), vec![]),
                    Some(p) => (commit_message(&cfg, StoreAction::Create), vec![p]),
                };

                let parents = parents.iter().collect::<Vec<_>>();
                repo.commit(Some("HEAD"), &sig, &sig, &msg[..], &tree, &parents)
                    .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't commit")
                    .map_err_into(GHEK::RepositoryCommittingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .map(|_| ())
    }

}

<|endoftext|>


<commit_before>use std::mem;

/// Lots of thanks to reem and Sharp for help with this from the #rust channel

#[derive(Show,PartialEq)]
struct Node<T> {
    pub payload: T,
    next: Option<Box<Node<T>>>,
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    pub fn new(payload: T) -> Node<T> {
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }
}

pub struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[cfg(test)]
mod tests {
    use super::*;

}
<commit_msg>Added `next` function<commit_after>use std::mem;

/// Lots of thanks to reem and Sharp for help with this from the #rust channel

#[derive(Show,PartialEq)]
struct Node<T> {
    pub payload: T,
    next: Option<Box<Node<T>>>,
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    pub fn new(payload: T) -> Node<T> {
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    pub fn next(&mut self) -> Option<&mut T> {
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None    => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

pub struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[cfg(test)]
mod tests {
    use super::*;

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{Enum, EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        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,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn values_rev_collect() {
    assert_eq!(
        vec![3, 2, 1],
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .values()
            .rev()
            .cloned()
            .collect::<Vec<_>>()
    );
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Enum<V> for X {
    type Array = [V; 1];
    const POSSIBLE_VALUES: usize = 1;

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}
<commit_msg>Add a test for getting values len<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{Enum, EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        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,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn values_rev_collect() {
    assert_eq!(
        vec![3, 2, 1],
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .values()
            .rev()
            .cloned()
            .collect::<Vec<_>>()
    );
}

#[test]
fn values_len() {
    assert_eq!(enum_map! { false => 0, true => 1 }.values().len(), 2);
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Enum<V> for X {
    type Array = [V; 1];
    const POSSIBLE_VALUES: usize = 1;

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}
<|endoftext|>