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

use syntax::{ast, ptr};
use syntax::codemap::Span;
use syntax::parse::classify;

use codemap::SpanUtils;
use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr};
use items::{span_hi_for_arg, span_lo_for_arg};
use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting,
            ListTactic, Separator, SeparatorPlace, SeparatorTactic};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use utils::{last_line_width, left_most_sub_expr, stmt_expr};

// This module is pretty messy because of the rules around closures and blocks:
// FIXME - the below is probably no longer true in full.
//   * if there is a return type, then there must be braces,
//   * given a closure with braces, whether that is parsed to give an inner block
//     or not depends on if there is a return type and if there are statements
//     in that block,
//   * if the first expression in the body ends with a block (i.e., is a
//     statement without needing a semi-colon), then adding or removing braces
//     can change whether it is treated as an expression or statement.

pub fn rewrite_closure(
    capture: ast::CaptureBy,
    fn_decl: &ast::FnDecl,
    body: &ast::Expr,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    debug!("rewrite_closure {:?}", body);

    let (prefix, extra_offset) =
        rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?;
    // 1 = space between `|...|` and body.
    let body_shape = shape.offset_left(extra_offset)?;

    if let ast::ExprKind::Block(ref block) = body.node {
        // The body of the closure is an empty block.
        if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) {
            return Some(format!("{} {{}}", prefix));
        }

        let result = match fn_decl.output {
            ast::FunctionRetTy::Default(_) => {
                try_rewrite_without_block(body, &prefix, context, shape, body_shape)
            }
            _ => None,
        };

        result.or_else(|| {
            // Either we require a block, or tried without and failed.
            rewrite_closure_block(block, &prefix, context, body_shape)
        })
    } else {
        rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
            // The closure originally had a non-block expression, but we can't fit on
            // one line, so we'll insert a block.
            rewrite_closure_with_block(body, &prefix, context, body_shape)
        })
    }
}

fn try_rewrite_without_block(
    expr: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
    body_shape: Shape,
) -> Option<String> {
    let expr = get_inner_expr(expr, prefix, context);

    if is_block_closure_forced(context, expr) {
        rewrite_closure_with_block(expr, prefix, context, shape)
    } else {
        rewrite_closure_expr(expr, prefix, context, body_shape)
    }
}

fn get_inner_expr<'a>(
    expr: &'a ast::Expr,
    prefix: &str,
    context: &RewriteContext,
) -> &'a ast::Expr {
    if let ast::ExprKind::Block(ref block) = expr.node {
        if !needs_block(block, prefix, context) {
            // block.stmts.len() == 1
            if let Some(expr) = stmt_expr(&block.stmts[0]) {
                return get_inner_expr(expr, prefix, context);
            }
        }
    }

    expr
}

// Figure out if a block is necessary.
fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool {
    is_unsafe_block(block) || block.stmts.len() > 1
        || block_contains_comment(block, context.codemap) || prefix.contains('\n')
}

// Rewrite closure with a single expression wrapping its body with block.
fn rewrite_closure_with_block(
    body: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let left_most = left_most_sub_expr(body);
    let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most);
    if veto_block {
        return None;
    }

    let block = ast::Block {
        stmts: vec![
            ast::Stmt {
                id: ast::NodeId::new(0),
                node: ast::StmtKind::Expr(ptr::P(body.clone())),
                span: body.span,
            },
        ],
        id: ast::NodeId::new(0),
        rules: ast::BlockCheckMode::Default,
        span: body.span,
    };
    let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?;
    Some(format!("{} {}", prefix, block))
}

// Rewrite closure with a single expression without wrapping its body with block.
fn rewrite_closure_expr(
    expr: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let mut rewrite = expr.rewrite(context, shape);
    rewrite = rewrite.and_then(|rw| {
        if context.config.force_multiline_blocks() && rw.contains('\n') {
            None
        } else {
            Some(rw)
        }
    });
    rewrite.map(|rw| format!("{} {}", prefix, rw))
}

// Rewrite closure whose body is block.
fn rewrite_closure_block(
    block: &ast::Block,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let block_shape = shape.block();
    let block_str = block.rewrite(context, block_shape)?;
    Some(format!("{} {}", prefix, block_str))
}

// Return type is (prefix, extra_offset)
fn rewrite_closure_fn_decl(
    capture: ast::CaptureBy,
    fn_decl: &ast::FnDecl,
    body: &ast::Expr,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<(String, usize)> {
    let mover = if capture == ast::CaptureBy::Value {
        "move "
    } else {
        ""
    };
    // 4 = "|| {".len(), which is overconservative when the closure consists of
    // a single expression.
    let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?;

    // 1 = |
    let argument_offset = nested_shape.indent + 1;
    let arg_shape = nested_shape.offset_left(1)?.visual_indent(0);
    let ret_str = fn_decl.output.rewrite(context, arg_shape)?;

    let arg_items = itemize_list(
        context.codemap,
        fn_decl.inputs.iter(),
        "|",
        ",",
        |arg| span_lo_for_arg(arg),
        |arg| span_hi_for_arg(context, arg),
        |arg| arg.rewrite(context, arg_shape),
        context.codemap.span_after(span, "|"),
        body.span.lo(),
        false,
    );
    let item_vec = arg_items.collect::<Vec<_>>();
    // 1 = space between arguments and return type.
    let horizontal_budget = nested_shape
        .width
        .checked_sub(ret_str.len() + 1)
        .unwrap_or(0);
    let tactic = definitive_tactic(
        &item_vec,
        ListTactic::HorizontalVertical,
        Separator::Comma,
        horizontal_budget,
    );
    let arg_shape = match tactic {
        DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?,
        _ => arg_shape,
    };

    let fmt = ListFormatting {
        tactic: tactic,
        separator: ",",
        trailing_separator: SeparatorTactic::Never,
        separator_place: SeparatorPlace::Back,
        shape: arg_shape,
        ends_with_newline: false,
        preserve_newline: true,
        config: context.config,
    };
    let list_str = write_list(&item_vec, &fmt)?;
    let mut prefix = format!("{}|{}|", mover, list_str);

    if !ret_str.is_empty() {
        if prefix.contains('\n') {
            prefix.push('\n');
            prefix.push_str(&argument_offset.to_string(context.config));
        } else {
            prefix.push(' ');
        }
        prefix.push_str(&ret_str);
    }
    // 1 = space between `|...|` and body.
    let extra_offset = last_line_width(&prefix) + 1;

    Some((prefix, extra_offset))
}

// Rewriting closure which is placed at the end of the function call's arg.
// Returns `None` if the reformatted closure 'looks bad'.
pub fn rewrite_last_closure(
    context: &RewriteContext,
    expr: &ast::Expr,
    shape: Shape,
) -> Option<String> {
    if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node {
        let body = match body.node {
            ast::ExprKind::Block(ref block)
                if !is_unsafe_block(block) && is_simple_block(block, context.codemap) =>
            {
                stmt_expr(&block.stmts[0]).unwrap_or(body)
            }
            _ => body,
        };
        let (prefix, extra_offset) =
            rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?;
        // If the closure goes multi line before its body, do not overflow the closure.
        if prefix.contains('\n') {
            return None;
        }

        let body_shape = shape.offset_left(extra_offset)?;

        // We force to use block for the body of the closure for certain kinds of expressions.
        if is_block_closure_forced(context, body) {
            return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then(
                |body_str| {
                    // If the expression can fit in a single line, we need not force block closure.
                    if body_str.lines().count() <= 7 {
                        match rewrite_closure_expr(body, &prefix, context, shape) {
                            Some(ref single_line_body_str)
                                if !single_line_body_str.contains('\n') =>
                            {
                                Some(single_line_body_str.clone())
                            }
                            _ => Some(body_str),
                        }
                    } else {
                        Some(body_str)
                    }
                },
            );
        }

        // When overflowing the closure which consists of a single control flow expression,
        // force to use block if its condition uses multi line.
        let is_multi_lined_cond = rewrite_cond(context, body, body_shape)
            .map(|cond| cond.contains('\n') || cond.len() > body_shape.width)
            .unwrap_or(false);
        if is_multi_lined_cond {
            return rewrite_closure_with_block(body, &prefix, context, body_shape);
        }

        // Seems fine, just format the closure in usual manner.
        return expr.rewrite(context, shape);
    }
    None
}

/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`.
pub fn args_have_many_closure<T>(args: &[&T]) -> bool
where
    T: ToExpr,
{
    args.iter()
        .filter(|arg| {
            arg.to_expr()
                .map(|e| match e.node {
                    ast::ExprKind::Closure(..) => true,
                    _ => false,
                })
                .unwrap_or(false)
        })
        .count() > 1
}

fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool {
    // If we are inside macro, we do not want to add or remove block from closure body.
    if context.inside_macro {
        false
    } else {
        is_block_closure_forced_inner(expr)
    }
}

fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool {
    match expr.node {
        ast::ExprKind::If(..)
        | ast::ExprKind::IfLet(..)
        | ast::ExprKind::Loop(..)
        | ast::ExprKind::While(..)
        | ast::ExprKind::WhileLet(..)
        | ast::ExprKind::ForLoop(..) => true,
        ast::ExprKind::AddrOf(_, ref expr)
        | ast::ExprKind::Box(ref expr)
        | ast::ExprKind::Try(ref expr)
        | ast::ExprKind::Unary(_, ref expr)
        | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr),
        _ => false,
    }
}
<commit_msg>Allow struct to be multi-lined in closure's body without block<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::{ast, ptr};
use syntax::codemap::Span;
use syntax::parse::classify;

use codemap::SpanUtils;
use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr};
use items::{span_hi_for_arg, span_lo_for_arg};
use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting,
            ListTactic, Separator, SeparatorPlace, SeparatorTactic};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use utils::{last_line_width, left_most_sub_expr, stmt_expr};

// This module is pretty messy because of the rules around closures and blocks:
// FIXME - the below is probably no longer true in full.
//   * if there is a return type, then there must be braces,
//   * given a closure with braces, whether that is parsed to give an inner block
//     or not depends on if there is a return type and if there are statements
//     in that block,
//   * if the first expression in the body ends with a block (i.e., is a
//     statement without needing a semi-colon), then adding or removing braces
//     can change whether it is treated as an expression or statement.

pub fn rewrite_closure(
    capture: ast::CaptureBy,
    fn_decl: &ast::FnDecl,
    body: &ast::Expr,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    debug!("rewrite_closure {:?}", body);

    let (prefix, extra_offset) =
        rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?;
    // 1 = space between `|...|` and body.
    let body_shape = shape.offset_left(extra_offset)?;

    if let ast::ExprKind::Block(ref block) = body.node {
        // The body of the closure is an empty block.
        if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) {
            return Some(format!("{} {{}}", prefix));
        }

        let result = match fn_decl.output {
            ast::FunctionRetTy::Default(_) => {
                try_rewrite_without_block(body, &prefix, context, shape, body_shape)
            }
            _ => None,
        };

        result.or_else(|| {
            // Either we require a block, or tried without and failed.
            rewrite_closure_block(block, &prefix, context, body_shape)
        })
    } else {
        rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
            // The closure originally had a non-block expression, but we can't fit on
            // one line, so we'll insert a block.
            rewrite_closure_with_block(body, &prefix, context, body_shape)
        })
    }
}

fn try_rewrite_without_block(
    expr: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
    body_shape: Shape,
) -> Option<String> {
    let expr = get_inner_expr(expr, prefix, context);

    if is_block_closure_forced(context, expr) {
        rewrite_closure_with_block(expr, prefix, context, shape)
    } else {
        rewrite_closure_expr(expr, prefix, context, body_shape)
    }
}

fn get_inner_expr<'a>(
    expr: &'a ast::Expr,
    prefix: &str,
    context: &RewriteContext,
) -> &'a ast::Expr {
    if let ast::ExprKind::Block(ref block) = expr.node {
        if !needs_block(block, prefix, context) {
            // block.stmts.len() == 1
            if let Some(expr) = stmt_expr(&block.stmts[0]) {
                return get_inner_expr(expr, prefix, context);
            }
        }
    }

    expr
}

// Figure out if a block is necessary.
fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool {
    is_unsafe_block(block) || block.stmts.len() > 1
        || block_contains_comment(block, context.codemap) || prefix.contains('\n')
}

// Rewrite closure with a single expression wrapping its body with block.
fn rewrite_closure_with_block(
    body: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let left_most = left_most_sub_expr(body);
    let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most);
    if veto_block {
        return None;
    }

    let block = ast::Block {
        stmts: vec![
            ast::Stmt {
                id: ast::NodeId::new(0),
                node: ast::StmtKind::Expr(ptr::P(body.clone())),
                span: body.span,
            },
        ],
        id: ast::NodeId::new(0),
        rules: ast::BlockCheckMode::Default,
        span: body.span,
    };
    let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?;
    Some(format!("{} {}", prefix, block))
}

// Rewrite closure with a single expression without wrapping its body with block.
fn rewrite_closure_expr(
    expr: &ast::Expr,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    fn allow_multi_line(expr: &ast::Expr) -> bool {
        match expr.node {
            ast::ExprKind::Match(..)
            | ast::ExprKind::Block(..)
            | ast::ExprKind::Catch(..)
            | ast::ExprKind::Loop(..)
            | ast::ExprKind::Struct(..) => true,

            ast::ExprKind::AddrOf(_, ref expr)
            | ast::ExprKind::Box(ref expr)
            | ast::ExprKind::Try(ref expr)
            | ast::ExprKind::Unary(_, ref expr)
            | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr),

            _ => false,
        }
    }

    // When rewriting closure's body without block, we require it to fit in a single line
    // unless it is a block-like expression or we are inside macro call.
    let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro)
        || context.config.force_multiline_blocks();
    expr.rewrite(context, shape)
        .and_then(|rw| {
            if veto_multiline && rw.contains('\n') {
                None
            } else {
                Some(rw)
            }
        })
        .map(|rw| format!("{} {}", prefix, rw))
}

// Rewrite closure whose body is block.
fn rewrite_closure_block(
    block: &ast::Block,
    prefix: &str,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let block_shape = shape.block();
    let block_str = block.rewrite(context, block_shape)?;
    Some(format!("{} {}", prefix, block_str))
}

// Return type is (prefix, extra_offset)
fn rewrite_closure_fn_decl(
    capture: ast::CaptureBy,
    fn_decl: &ast::FnDecl,
    body: &ast::Expr,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<(String, usize)> {
    let mover = if capture == ast::CaptureBy::Value {
        "move "
    } else {
        ""
    };
    // 4 = "|| {".len(), which is overconservative when the closure consists of
    // a single expression.
    let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?;

    // 1 = |
    let argument_offset = nested_shape.indent + 1;
    let arg_shape = nested_shape.offset_left(1)?.visual_indent(0);
    let ret_str = fn_decl.output.rewrite(context, arg_shape)?;

    let arg_items = itemize_list(
        context.codemap,
        fn_decl.inputs.iter(),
        "|",
        ",",
        |arg| span_lo_for_arg(arg),
        |arg| span_hi_for_arg(context, arg),
        |arg| arg.rewrite(context, arg_shape),
        context.codemap.span_after(span, "|"),
        body.span.lo(),
        false,
    );
    let item_vec = arg_items.collect::<Vec<_>>();
    // 1 = space between arguments and return type.
    let horizontal_budget = nested_shape
        .width
        .checked_sub(ret_str.len() + 1)
        .unwrap_or(0);
    let tactic = definitive_tactic(
        &item_vec,
        ListTactic::HorizontalVertical,
        Separator::Comma,
        horizontal_budget,
    );
    let arg_shape = match tactic {
        DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?,
        _ => arg_shape,
    };

    let fmt = ListFormatting {
        tactic: tactic,
        separator: ",",
        trailing_separator: SeparatorTactic::Never,
        separator_place: SeparatorPlace::Back,
        shape: arg_shape,
        ends_with_newline: false,
        preserve_newline: true,
        config: context.config,
    };
    let list_str = write_list(&item_vec, &fmt)?;
    let mut prefix = format!("{}|{}|", mover, list_str);

    if !ret_str.is_empty() {
        if prefix.contains('\n') {
            prefix.push('\n');
            prefix.push_str(&argument_offset.to_string(context.config));
        } else {
            prefix.push(' ');
        }
        prefix.push_str(&ret_str);
    }
    // 1 = space between `|...|` and body.
    let extra_offset = last_line_width(&prefix) + 1;

    Some((prefix, extra_offset))
}

// Rewriting closure which is placed at the end of the function call's arg.
// Returns `None` if the reformatted closure 'looks bad'.
pub fn rewrite_last_closure(
    context: &RewriteContext,
    expr: &ast::Expr,
    shape: Shape,
) -> Option<String> {
    if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node {
        let body = match body.node {
            ast::ExprKind::Block(ref block)
                if !is_unsafe_block(block) && is_simple_block(block, context.codemap) =>
            {
                stmt_expr(&block.stmts[0]).unwrap_or(body)
            }
            _ => body,
        };
        let (prefix, extra_offset) =
            rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?;
        // If the closure goes multi line before its body, do not overflow the closure.
        if prefix.contains('\n') {
            return None;
        }

        let body_shape = shape.offset_left(extra_offset)?;

        // We force to use block for the body of the closure for certain kinds of expressions.
        if is_block_closure_forced(context, body) {
            return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then(
                |body_str| {
                    // If the expression can fit in a single line, we need not force block closure.
                    if body_str.lines().count() <= 7 {
                        match rewrite_closure_expr(body, &prefix, context, shape) {
                            Some(ref single_line_body_str)
                                if !single_line_body_str.contains('\n') =>
                            {
                                Some(single_line_body_str.clone())
                            }
                            _ => Some(body_str),
                        }
                    } else {
                        Some(body_str)
                    }
                },
            );
        }

        // When overflowing the closure which consists of a single control flow expression,
        // force to use block if its condition uses multi line.
        let is_multi_lined_cond = rewrite_cond(context, body, body_shape)
            .map(|cond| cond.contains('\n') || cond.len() > body_shape.width)
            .unwrap_or(false);
        if is_multi_lined_cond {
            return rewrite_closure_with_block(body, &prefix, context, body_shape);
        }

        // Seems fine, just format the closure in usual manner.
        return expr.rewrite(context, shape);
    }
    None
}

/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`.
pub fn args_have_many_closure<T>(args: &[&T]) -> bool
where
    T: ToExpr,
{
    args.iter()
        .filter(|arg| {
            arg.to_expr()
                .map(|e| match e.node {
                    ast::ExprKind::Closure(..) => true,
                    _ => false,
                })
                .unwrap_or(false)
        })
        .count() > 1
}

fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool {
    // If we are inside macro, we do not want to add or remove block from closure body.
    if context.inside_macro {
        false
    } else {
        is_block_closure_forced_inner(expr)
    }
}

fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool {
    match expr.node {
        ast::ExprKind::If(..)
        | ast::ExprKind::IfLet(..)
        | ast::ExprKind::While(..)
        | ast::ExprKind::WhileLet(..)
        | ast::ExprKind::ForLoop(..) => true,
        ast::ExprKind::AddrOf(_, ref expr)
        | ast::ExprKind::Box(ref expr)
        | ast::ExprKind::Try(ref expr)
        | ast::ExprKind::Unary(_, ref expr)
        | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr),
        _ => false,
    }
}
<|endoftext|>


<commit_before>//! This crate provides Serde's two derive macros.
//!
//! ```edition2018
//! # use serde_derive::{Serialize, Deserialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html

#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.125")]
#![allow(unknown_lints, bare_trait_objects)]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints
#![allow(
    clippy::cognitive_complexity,
    clippy::enum_variant_names,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
    clippy::manual_map,
    clippy::match_like_matches_macro,
    clippy::needless_pass_by_value,
    clippy::too_many_arguments,
    clippy::trivially_copy_pass_by_ref,
    clippy::used_underscore_binding,
    clippy::wildcard_in_or_patterns,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
    clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![allow(
    clippy::cast_possible_truncation,
    clippy::checked_conversions,
    clippy::doc_markdown,
    clippy::enum_glob_use,
    clippy::filter_map,
    clippy::indexing_slicing,
    clippy::items_after_statements,
    clippy::let_underscore_drop,
    clippy::map_err_ignore,
    clippy::match_same_arms,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
    clippy::match_wildcard_for_single_variants,
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::option_if_let_else,
    clippy::similar_names,
    clippy::single_match_else,
    clippy::struct_excessive_bools,
    clippy::too_many_lines,
    clippy::unseparated_literal_suffix,
    clippy::unused_self,
    clippy::use_self,
    clippy::wildcard_imports
)]

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

extern crate proc_macro;
extern crate proc_macro2;

mod internals;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[macro_use]
mod bound;
#[macro_use]
mod fragment;

mod de;
mod dummy;
mod pretend;
mod ser;
mod try;

#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
    let mut input = parse_macro_input!(input as DeriveInput);
    ser::expand_derive_serialize(&mut input)
        .unwrap_or_else(to_compile_errors)
        .into()
}

#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
    let mut input = parse_macro_input!(input as DeriveInput);
    de::expand_derive_deserialize(&mut input)
        .unwrap_or_else(to_compile_errors)
        .into()
}

fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
    let compile_errors = errors.iter().map(syn::Error::to_compile_error);
    quote!(#(#compile_errors)*)
}
<commit_msg>Ignore poor suggestion from branches_sharing_code lint<commit_after>//! This crate provides Serde's two derive macros.
//!
//! ```edition2018
//! # use serde_derive::{Serialize, Deserialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html

#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.125")]
#![allow(unknown_lints, bare_trait_objects)]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints
#![allow(
    // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
    clippy::branches_sharing_code,
    clippy::cognitive_complexity,
    clippy::enum_variant_names,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
    clippy::manual_map,
    clippy::match_like_matches_macro,
    clippy::needless_pass_by_value,
    clippy::too_many_arguments,
    clippy::trivially_copy_pass_by_ref,
    clippy::used_underscore_binding,
    clippy::wildcard_in_or_patterns,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
    clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![allow(
    clippy::cast_possible_truncation,
    clippy::checked_conversions,
    clippy::doc_markdown,
    clippy::enum_glob_use,
    clippy::filter_map,
    clippy::indexing_slicing,
    clippy::items_after_statements,
    clippy::let_underscore_drop,
    clippy::map_err_ignore,
    clippy::match_same_arms,
    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
    clippy::match_wildcard_for_single_variants,
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::option_if_let_else,
    clippy::similar_names,
    clippy::single_match_else,
    clippy::struct_excessive_bools,
    clippy::too_many_lines,
    clippy::unseparated_literal_suffix,
    clippy::unused_self,
    clippy::use_self,
    clippy::wildcard_imports
)]

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

extern crate proc_macro;
extern crate proc_macro2;

mod internals;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[macro_use]
mod bound;
#[macro_use]
mod fragment;

mod de;
mod dummy;
mod pretend;
mod ser;
mod try;

#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
    let mut input = parse_macro_input!(input as DeriveInput);
    ser::expand_derive_serialize(&mut input)
        .unwrap_or_else(to_compile_errors)
        .into()
}

#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
    let mut input = parse_macro_input!(input as DeriveInput);
    de::expand_derive_deserialize(&mut input)
        .unwrap_or_else(to_compile_errors)
        .into()
}

fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
    let compile_errors = errors.iter().map(syn::Error::to_compile_error);
    quote!(#(#compile_errors)*)
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fs::File;
use std::io::Read;
use std::ptr;
use super::glium::{ DisplayBuild, Surface };
use super::glium::backend::glutin_backend::GlutinFacade;

const MEM_SIZE: usize = 4096;
const ROM_ADDR: usize = 0x200;

#[derive(Debug, Default)]
struct Registers {
    reg_gp: [u8; 16],
    reg_i: u16,

    reg_delay: u8,
    reg_sound: u8,

    reg_pc: u16,
    reg_sp: u8,

    stack: [u16; 16]
}

impl Registers {
    fn new() -> Registers {
        let mut reg = Registers::default();
        reg.reg_pc = (ROM_ADDR as u16);
        reg
    }

    fn write_register(&mut self, target_reg: u8, data_value: u8) {
        self.reg_gp[target_reg as usize] = data_value;
        println!("Loaded value {:#x} into register V{:x}", data_value, target_reg)
    }

    fn write_register_i(&mut self, data_value: u16) {
        self.reg_i = data_value;
        println!("Loaded value {:#x} into I register", data_value);
    }

    fn read_register(&self, target_reg: u8) -> u8 {
        self.reg_gp[target_reg as usize]
    }

    fn jump_to_address(&mut self, addr: u16, jump_type: JumpType) {
        match jump_type {
            JumpType::SUBROUTINE => {
                self.stack[self.reg_sp as usize] = self.reg_pc;
                self.reg_sp += 1;
            }
            JumpType::NORMAL => {}
        }
        println!("Jumping to address {:#x}", addr);
        self.reg_pc = addr;
    }

    fn return_from_subroutine(&mut self) {
        self.reg_pc = self.stack[self.reg_sp as usize];
        self.reg_sp -= 1;
    }
}

#[derive(Default, Debug)]
struct Keypad {
    keys: [u8; 16],
}

struct Memory {
    mem: [u8; MEM_SIZE],
}

impl Memory {
    fn store_program_data(&mut self, rom: File) {
        let mut last_stored_addr = ROM_ADDR;

        for byte in rom.bytes() {
            match byte {
                Ok(b) => {
                    self.mem[last_stored_addr] = b;
                    last_stored_addr += 1;
                },
                Err(e) => panic!("Some error {:?} occurred while storing program data.", e)
            }
        }
    }

    fn display_pong_rom(&self) {
        let mut addr = ROM_ADDR;
        for i in 1..100 {
            println!("{:#x}", self.mem[addr]);
            addr += 1;
        }
    }
}

impl fmt::Debug for Memory {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TODO implement debug output for memory")
    }
}

impl Default for Memory {
    fn default() -> Memory {
        Memory {
            mem: [0u8; MEM_SIZE]
        }
    }
}

pub struct Chip8 {
    reg: Registers,
    mem: Memory,
    keys: Keypad,
    display: GlutinFacade
}

impl fmt::Debug for Chip8 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#?}{:#?}{:#?}", self.reg, self.mem, self.keys)
    }
}

impl Chip8 {
    pub fn new() -> Chip8 {
        Chip8 {
            reg: Registers::new(),
            mem: Memory::default(),
            keys: Keypad::default(),
            display: super::glium::glutin::WindowBuilder::new()
                .with_dimensions(64, 32)
                .with_title(String::from("rust8"))
                .build_glium()
                .unwrap()
        }
    }

    pub fn init_display(&mut self) {
        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);
        target.finish().unwrap();
    }

    pub fn run(&mut self) {
        loop {
            let instruction = self.read_word();
            self.process_instruction(instruction);

            for ev in self.display.poll_events() {
                match ev {
                    super::glium::glutin::Event::Closed => return,
                    _ => ()
                }
            }
        }
    }

    pub fn store_program_data(&mut self, rom: File) {
        self.mem.store_program_data(rom);
    }

    pub fn debug_pong_rom(&self) {
        self.mem.display_pong_rom();
    }

    fn read_word(&mut self) -> u16 {
        let instruction_high_order = (self.mem.mem[self.reg.reg_pc as usize] as u16) << 8;
        let instruction_low_order = self.mem.mem[(self.reg.reg_pc + 2) as usize] as u16;

        let instruction = instruction_high_order | instruction_low_order;
        println!("Instruction: {:#x}", instruction);

        self.reg.reg_pc += 4;
        instruction
    }

    fn process_instruction(&mut self, instruction: u16) {
        let op_type: u8 = ((instruction >> 12) & 0xff) as u8;

        match op_type {
            0x0 => {
                //we will ignore the 0nnn opcode used for jumping to machine code routines
                let operation = instruction & 0x00ff;
                if(operation == 0xe0) {
                    //TODO clear the display
                } else if (operation == 0xee) {
                    self.reg.return_from_subroutine();
                }
            },
            0x1 => {
                let jump_addr = instruction & 0x0fff;
                self.reg.jump_to_address(jump_addr, JumpType::NORMAL);
            },
            0x2 => {
                let subroutine_addr = instruction & 0x0fff;
                self.reg.jump_to_address(subroutine_addr, JumpType::SUBROUTINE);
            },
            0x6 => {
                let target_reg = ((instruction >> 8) & 0x0f) as u8;
                let data_value = (instruction & 0x00ff) as u8;
                self.reg.write_register(target_reg, data_value);
            },
            0x7 => {
                let target_reg = ((instruction >> 8) & 0x0f) as u8;
                let immediate_value = (instruction & 0x00ff) as u8;
                let reg_value = self.reg.read_register(target_reg);
                let data_value = immediate_value.wrapping_add(reg_value);
                println!("Addition");
                self.reg.write_register(target_reg, data_value);
            },
            0x8 => {
                let reg_one = ((instruction >> 8) & 0x0f) as u8;
                let reg_two = ((instruction >> 4) & 0x0f) as u8;
                let operation = (instruction & 0x000f) as u8;
                match operation {
                    0 => {
                        let data_value = self.reg.read_register(reg_two);
                        self.reg.write_register(reg_one, data_value);
                    },
                    1 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        let data_value = reg_one_value | reg_two_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    2 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        let data_value = reg_one_value & reg_two_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    3 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        if(reg_two_value > reg_one_value) {
                            self.reg.write_register(0x0f, 0x01);
                        }
                        let data_value = reg_two_value - reg_one_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    4 => {

                    },
                    5 => {

                    },
                    6 => {

                    },
                    7 => {

                    },
                    0xe => {

                    },
                    _ => panic!("Unrecognized opcode: {:#x}", instruction)
                }
            },
            0xa => {
                let data_value = instruction & 0x0fff;
                self.reg.write_register_i(data_value);
            },
            0xb => {
                let initial_addr = instruction & 0x0fff;
                let offset = self.reg.read_register(0) as u16;
                self.reg.jump_to_address(initial_addr + offset, JumpType::NORMAL);
            },
            0xd => {
                //TODO: display/sprites
                println!("Display operation");
            },
            0xe => {
                //TODO: input checks
                println!("Input checks");
            },
            _ => {
                println!("Chip8 status at end time: {:#?}", self);
                panic!("Unsupported op type: {:#x}", op_type)
            }
        }
    }
}

enum JumpType {
    NORMAL, SUBROUTINE
}<commit_msg>open correctly sized glium window and set a color<commit_after>use std::fmt;
use std::fs::File;
use std::io::Read;
use std::ptr;
use super::glium::{ DisplayBuild, Surface };
use super::glium::backend::glutin_backend::GlutinFacade;

const MEM_SIZE: usize = 4096;
const ROM_ADDR: usize = 0x200;

#[derive(Debug, Default)]
struct Registers {
    reg_gp: [u8; 16],
    reg_i: u16,

    reg_delay: u8,
    reg_sound: u8,

    reg_pc: u16,
    reg_sp: u8,

    stack: [u16; 16]
}

impl Registers {
    fn new() -> Registers {
        let mut reg = Registers::default();
        reg.reg_pc = (ROM_ADDR as u16);
        reg
    }

    fn write_register(&mut self, target_reg: u8, data_value: u8) {
        self.reg_gp[target_reg as usize] = data_value;
        println!("Loaded value {:#x} into register V{:x}", data_value, target_reg)
    }

    fn write_register_i(&mut self, data_value: u16) {
        self.reg_i = data_value;
        println!("Loaded value {:#x} into I register", data_value);
    }

    fn read_register(&self, target_reg: u8) -> u8 {
        self.reg_gp[target_reg as usize]
    }

    fn jump_to_address(&mut self, addr: u16, jump_type: JumpType) {
        match jump_type {
            JumpType::SUBROUTINE => {
                self.stack[self.reg_sp as usize] = self.reg_pc;
                self.reg_sp += 1;
            }
            JumpType::NORMAL => {}
        }
        println!("Jumping to address {:#x}", addr);
        self.reg_pc = addr;
    }

    fn return_from_subroutine(&mut self) {
        self.reg_pc = self.stack[self.reg_sp as usize];
        self.reg_sp -= 1;
    }
}

#[derive(Default, Debug)]
struct Keypad {
    keys: [u8; 16],
}

struct Memory {
    mem: [u8; MEM_SIZE],
}

impl Memory {
    fn store_program_data(&mut self, rom: File) {
        let mut last_stored_addr = ROM_ADDR;

        for byte in rom.bytes() {
            match byte {
                Ok(b) => {
                    self.mem[last_stored_addr] = b;
                    last_stored_addr += 1;
                },
                Err(e) => panic!("Some error {:?} occurred while storing program data.", e)
            }
        }
    }

    fn load_fonts(&mut self) {
        let font_file = File::open("./font.bin");
        let mem_addr = 0x0;
        for byte in font_file.bytes() {
            match byte {
                Ok(b) => {
                    self.mem[mem_addr] = b;
                    mem_addr += 1;
                },
                Err(e) => panic!("Some error {:?} occurred while loading font data.", e)
            }
        }
    }

    fn display_pong_rom(&self) {
        let mut addr = ROM_ADDR;
        for i in 1..100 {
            println!("{:#x}", self.mem[addr]);
            addr += 1;
        }
    }
}

impl fmt::Debug for Memory {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TODO implement debug output for memory")
    }
}

impl Default for Memory {
    fn default() -> Memory {
        Memory {
            mem: [0u8; MEM_SIZE]
        }
    }
}

pub struct Chip8 {
    reg: Registers,
    mem: Memory,
    keys: Keypad,
    display: GlutinFacade
}

impl fmt::Debug for Chip8 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#?}{:#?}{:#?}", self.reg, self.mem, self.keys)
    }
}

impl Chip8 {
    pub fn new() -> Chip8 {
        Chip8 {
            reg: Registers::new(),
            mem: Memory::default(),
            keys: Keypad::default(),
            display: super::glium::glutin::WindowBuilder::new()
                .with_dimensions(64, 32)
                .with_title(String::from("rust8"))
                .build_glium()
                .unwrap()
        }
    }

    pub fn init_display(&mut self) {
        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);
        target.finish().unwrap();

        self.mem.load_fonts();
    }

    pub fn run(&mut self) {
        loop {
            let instruction = self.read_word();
            self.process_instruction(instruction);

            for ev in self.display.poll_events() {
                match ev {
                    super::glium::glutin::Event::Closed => return,
                    _ => ()
                }
            }
        }
    }

    pub fn store_program_data(&mut self, rom: File) {
        self.mem.store_program_data(rom);
    }

    pub fn debug_pong_rom(&self) {
        self.mem.display_pong_rom();
    }

    fn read_word(&mut self) -> u16 {
        let instruction_high_order = (self.mem.mem[self.reg.reg_pc as usize] as u16) << 8;
        let instruction_low_order = self.mem.mem[(self.reg.reg_pc + 2) as usize] as u16;

        let instruction = instruction_high_order | instruction_low_order;
        println!("Instruction: {:#x}", instruction);

        self.reg.reg_pc += 4;
        instruction
    }

    fn process_instruction(&mut self, instruction: u16) {
        let op_type: u8 = ((instruction >> 12) & 0xff) as u8;

        match op_type {
            0x0 => {
                //we will ignore the 0nnn opcode used for jumping to machine code routines
                let operation = instruction & 0x00ff;
                if(operation == 0xe0) {
                    //TODO clear the display
                } else if (operation == 0xee) {
                    self.reg.return_from_subroutine();
                }
            },
            0x1 => {
                let jump_addr = instruction & 0x0fff;
                self.reg.jump_to_address(jump_addr, JumpType::NORMAL);
            },
            0x2 => {
                let subroutine_addr = instruction & 0x0fff;
                self.reg.jump_to_address(subroutine_addr, JumpType::SUBROUTINE);
            },
            0x6 => {
                let target_reg = ((instruction >> 8) & 0x0f) as u8;
                let data_value = (instruction & 0x00ff) as u8;
                self.reg.write_register(target_reg, data_value);
            },
            0x7 => {
                let target_reg = ((instruction >> 8) & 0x0f) as u8;
                let immediate_value = (instruction & 0x00ff) as u8;
                let reg_value = self.reg.read_register(target_reg);
                let data_value = immediate_value.wrapping_add(reg_value);
                println!("Addition");
                self.reg.write_register(target_reg, data_value);
            },
            0x8 => {
                let reg_one = ((instruction >> 8) & 0x0f) as u8;
                let reg_two = ((instruction >> 4) & 0x0f) as u8;
                let operation = (instruction & 0x000f) as u8;
                match operation {
                    0 => {
                        let data_value = self.reg.read_register(reg_two);
                        self.reg.write_register(reg_one, data_value);
                    },
                    1 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        let data_value = reg_one_value | reg_two_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    2 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        let data_value = reg_one_value & reg_two_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    3 => {
                        let reg_one_value = self.reg.read_register(reg_one);
                        let reg_two_value = self.reg.read_register(reg_two);
                        if(reg_two_value > reg_one_value) {
                            self.reg.write_register(0x0f, 0x01);
                        }
                        let data_value = reg_two_value - reg_one_value;
                        self.reg.write_register(reg_one, data_value);
                    },
                    4 => {

                    },
                    5 => {

                    },
                    6 => {

                    },
                    7 => {

                    },
                    0xe => {

                    },
                    _ => panic!("Unrecognized opcode: {:#x}", instruction)
                }
            },
            0xa => {
                let data_value = instruction & 0x0fff;
                self.reg.write_register_i(data_value);
            },
            0xb => {
                let initial_addr = instruction & 0x0fff;
                let offset = self.reg.read_register(0) as u16;
                self.reg.jump_to_address(initial_addr + offset, JumpType::NORMAL);
            },
            0xd => {
                //TODO: display/sprites
                println!("Display operation");
            },
            0xe => {
                //TODO: input checks
                println!("Input checks");
            },
            _ => {
                println!("Chip8 status at end time: {:#?}", self);
                panic!("Unsupported op type: {:#x}", op_type)
            }
        }
    }
}

enum JumpType {
    NORMAL, SUBROUTINE
}<|endoftext|>


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

// ----------------

// This program exercises the Rust GIF decoder at
// https://github.com/image-rs/image-gif
// which is the top result for https://crates.io/search?q=gif
//
// Wuffs' C code doesn't depend on Rust per se, but this program gives some
// performance data for specific Rust GIF implementations. The equivalent Wuffs
// benchmarks (on the same test images) are run via:
//
// wuffs bench std/gif
//
// To run this program, do "cargo run --release" from the parent directory (the
// directory containing the Cargo.toml file).

// TODO: unify this program, bench-rust-gif-dot-rs, with bench-rust-gif, the
// other Rust GIF benchmark program. They are two separate programs because
// both libraries want to be named "gif", and the cargo package manager cannot
// handle duplicate names (https://github.com/rust-lang/cargo/issues/1311).

extern crate gif;
extern crate rustc_version_runtime;

use gif::SetParameter;
use std::time::Instant;

const ITERSCALE: u64 = 10;
const REPS: u64 = 5;

fn main() {
    let version = rustc_version_runtime::version();
    print!(
        "# Rust {}.{}.{}\n",
        version.major,
        version.minor,
        version.patch
    );
    print!("#\n");
    print!("# The output format, including the \"Benchmark\" prefixes, is compatible with the\n");
    print!("# https://godoc.org/golang.org/x/perf/cmd/benchstat tool. To install it, first\n");
    print!("# install Go, then run \"go get golang.org/x/perf/cmd/benchstat\".\n");

    let mut dst = vec![0u8; 64 * 1024 * 1024];

    for _ in 0..REPS {
        bench(
            "1k_bw",
            &mut dst[..],
            include_bytes!("../../../test/data/pjw-thumbnail.gif"),
            2000, // iters_unscaled
        );

        bench(
            "1k_color",
            &mut dst[..],
            include_bytes!("../../../test/data/hippopotamus.regular.gif"),
            1000, // iters_unscaled
        );

        bench(
            "10k_bgra",
            &mut dst[..],
            include_bytes!("../../../test/data/hat.gif"),
            100, // iters_unscaled
        );

        bench(
            "10k_indexed",
            &mut dst[..],
            include_bytes!("../../../test/data/hat.gif"),
            100, // iters_unscaled
        );

        bench(
            "20k",
            &mut dst[..],
            include_bytes!("../../../test/data/bricks-gray.gif"),
            50, // iters_unscaled
        );

        bench(
            "100k_artificial",
            &mut dst[..],
            include_bytes!("../../../test/data/hibiscus.primitive.gif"),
            15, // iters_unscaled
        );

        bench(
            "100k_realistic",
            &mut dst[..],
            include_bytes!("../../../test/data/hibiscus.regular.gif"),
            10, // iters_unscaled
        );

        bench(
            "1000k",
            &mut dst[..],
            include_bytes!("../../../test/data/harvesters.gif"),
            1, // iters_unscaled
        );

        bench(
            "anim_screencap",
            &mut dst[..],
            include_bytes!("../../../test/data/gifplayer-muybridge.gif"),
            1, // iters_unscaled
        );
    }
}

fn bench(
    name: &str, // Benchmark name.
    dst: &mut [u8], // Destination buffer.
    src: &[u8], // Source data.
    iters_unscaled: u64, // Base number of iterations.
) {
    let iters = iters_unscaled * ITERSCALE;
    let output_32_bit_color = name.ends_with("_bgra");
    let mut num_bytes = 0u64;

    let start = Instant::now();
    for _ in 0..iters {
        num_bytes += decode(&mut dst[..], src, output_32_bit_color);
    }
    let elapsed = start.elapsed();

    let elapsed_nanos = (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64);
    let kb_per_s: u64 = num_bytes * 1_000_000 / elapsed_nanos;
    print!(
        "Benchmarkrust_gif_decode_{:16}   {:8}   {:12} ns/op   {:3}.{:03} MB/s\n",
        name,
        iters,
        elapsed_nanos / iters,
        kb_per_s / 1_000,
        kb_per_s % 1_000
    );
}

// decode returns the number of bytes processed.
fn decode(dst: &mut [u8], src: &[u8], output_32_bit_color: bool) -> u64 {
    let mut decoder = gif::Decoder::new(src);
    if output_32_bit_color {
        decoder.set(gif::ColorOutput::RGBA);
    }

    let mut num_bytes = 0u64;
    let mut reader = decoder.read_info().unwrap();
    while let Some(_) = reader.next_frame_info().unwrap() {
        num_bytes += reader.buffer_size() as u64;
        reader.read_into_buffer(dst).unwrap();
    }
    num_bytes
}
<commit_msg>Refine script/bench-rust-gif crates.io URL<commit_after>// Copyright 2018 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// ----------------

// This program exercises the Rust GIF decoder at
// https://github.com/image-rs/image-gif
// which is the top result for https://crates.io/search?q=gif&sort=downloads
//
// Wuffs' C code doesn't depend on Rust per se, but this program gives some
// performance data for specific Rust GIF implementations. The equivalent Wuffs
// benchmarks (on the same test images) are run via:
//
// wuffs bench std/gif
//
// To run this program, do "cargo run --release" from the parent directory (the
// directory containing the Cargo.toml file).

// TODO: unify this program, bench-rust-gif-dot-rs, with bench-rust-gif, the
// other Rust GIF benchmark program. They are two separate programs because
// both libraries want to be named "gif", and the cargo package manager cannot
// handle duplicate names (https://github.com/rust-lang/cargo/issues/1311).

extern crate gif;
extern crate rustc_version_runtime;

use gif::SetParameter;
use std::time::Instant;

const ITERSCALE: u64 = 10;
const REPS: u64 = 5;

fn main() {
    let version = rustc_version_runtime::version();
    print!(
        "# Rust {}.{}.{}\n",
        version.major,
        version.minor,
        version.patch
    );
    print!("#\n");
    print!("# The output format, including the \"Benchmark\" prefixes, is compatible with the\n");
    print!("# https://godoc.org/golang.org/x/perf/cmd/benchstat tool. To install it, first\n");
    print!("# install Go, then run \"go get golang.org/x/perf/cmd/benchstat\".\n");

    let mut dst = vec![0u8; 64 * 1024 * 1024];

    for _ in 0..REPS {
        bench(
            "1k_bw",
            &mut dst[..],
            include_bytes!("../../../test/data/pjw-thumbnail.gif"),
            2000, // iters_unscaled
        );

        bench(
            "1k_color",
            &mut dst[..],
            include_bytes!("../../../test/data/hippopotamus.regular.gif"),
            1000, // iters_unscaled
        );

        bench(
            "10k_bgra",
            &mut dst[..],
            include_bytes!("../../../test/data/hat.gif"),
            100, // iters_unscaled
        );

        bench(
            "10k_indexed",
            &mut dst[..],
            include_bytes!("../../../test/data/hat.gif"),
            100, // iters_unscaled
        );

        bench(
            "20k",
            &mut dst[..],
            include_bytes!("../../../test/data/bricks-gray.gif"),
            50, // iters_unscaled
        );

        bench(
            "100k_artificial",
            &mut dst[..],
            include_bytes!("../../../test/data/hibiscus.primitive.gif"),
            15, // iters_unscaled
        );

        bench(
            "100k_realistic",
            &mut dst[..],
            include_bytes!("../../../test/data/hibiscus.regular.gif"),
            10, // iters_unscaled
        );

        bench(
            "1000k",
            &mut dst[..],
            include_bytes!("../../../test/data/harvesters.gif"),
            1, // iters_unscaled
        );

        bench(
            "anim_screencap",
            &mut dst[..],
            include_bytes!("../../../test/data/gifplayer-muybridge.gif"),
            1, // iters_unscaled
        );
    }
}

fn bench(
    name: &str, // Benchmark name.
    dst: &mut [u8], // Destination buffer.
    src: &[u8], // Source data.
    iters_unscaled: u64, // Base number of iterations.
) {
    let iters = iters_unscaled * ITERSCALE;
    let output_32_bit_color = name.ends_with("_bgra");
    let mut num_bytes = 0u64;

    let start = Instant::now();
    for _ in 0..iters {
        num_bytes += decode(&mut dst[..], src, output_32_bit_color);
    }
    let elapsed = start.elapsed();

    let elapsed_nanos = (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64);
    let kb_per_s: u64 = num_bytes * 1_000_000 / elapsed_nanos;
    print!(
        "Benchmarkrust_gif_decode_{:16}   {:8}   {:12} ns/op   {:3}.{:03} MB/s\n",
        name,
        iters,
        elapsed_nanos / iters,
        kb_per_s / 1_000,
        kb_per_s % 1_000
    );
}

// decode returns the number of bytes processed.
fn decode(dst: &mut [u8], src: &[u8], output_32_bit_color: bool) -> u64 {
    let mut decoder = gif::Decoder::new(src);
    if output_32_bit_color {
        decoder.set(gif::ColorOutput::RGBA);
    }

    let mut num_bytes = 0u64;
    let mut reader = decoder.read_info().unwrap();
    while let Some(_) = reader.next_frame_info().unwrap() {
        num_bytes += reader.buffer_size() as u64;
        reader.read_into_buffer(dst).unwrap();
    }
    num_bytes
}
<|endoftext|>


<commit_before>/*!
Find patterns utility.
 */

use std::{cmp, env};
use std::path::Path;
use std::io::{self, Write};

use pelite::pattern as pat;

const HELP_TEXT: &'static str = "\
FINDSIG <FILE> [PAT]...

  FILE - Path to the input binary to scan.
  PAT  - Any number of patterns to find.

If no patterns are provided, they are interactively read line by line from stdin.

Find documentation about the pattern syntax here:
https://docs.rs/pelite/*/pelite/pattern/fn.parse.html
";

fn main() {
	// Get args and skip the invoker
	let mut args = env::args_os();
	args.next();

	// Read the input file
	if let Some(file_path) = args.next() {
		// Path and filename of the input file
		let file_path = Path::new(&file_path);
		let file_name = file_path.file_name().expect("path does not have a file name").to_str().unwrap();

		// Map the file into memory
		let file_map = pelite::FileMap::open(&file_path).expect("cannot open the input file");

		match pelite::PeFile::from_bytes(&file_map) {
			Ok(file) => {
				process_patterns(args, &mut |pattern, save| {
					let mut matches = file.scanner().matches(pattern, file.headers().image_range());
					while matches.next(save) {
						print_match(file_name, save);
					}
				});
			}
			// Must be a valid PE file
			Err(err) => {
				panic!("Not a valid PE file: {}", err);
			},
		}
	}
	else {
		print!("{}", HELP_TEXT);
	}
}

fn process_patterns(args: env::ArgsOs, f: &mut dyn FnMut(&[pat::Atom], &mut [u32])) {
	if args.len() > 0 {
		// Read from the command line args if available
		for pattern_string in args.filter_map(|pattern_string| pattern_string.into_string().ok()) {
			process_pattern(&pattern_string, f);
		}
	}
	else {
		// Read from standard input if no patterns were provided on command line
		print!("Interactive REPL, enter any pattern to find its matches.\nPress Ctrl-C to quit.\n");
		loop {
			// Print a nice REPL
			print!(">>> ");
			let _ = io::stdout().flush();
			// Read input from stdin, handle any kind of abort by detecting the lack of newline (?)
			let mut line = String::new();
			if io::stdin().read_line(&mut line).is_err() || line.len() == 0 {
				break;
			}
			// Only process non-empty lines, otherwise ask the user again
			let line = line.trim();
			if line.len() > 0 {
				process_pattern(&line, f);
			}
		}
	}
}
fn process_pattern(pattern_str: &str, f: &mut dyn FnMut(&[pat::Atom], &mut [u32])) {
	// Parse the pattern
	let pattern = match pat::parse(pattern_str) {
		Ok(pattern) => pattern,
		Err(err) => {
			eprintln!("Pattern `{}` error: {}", pattern_str, err);
			return;
		},
	};
	// Print the header followed by its matches
	println!("Pattern `{}` matches:", pattern_str);
	let mut save = [0; 32];
	let save_len = cmp::min(pat::save_len(&pattern), save.len());
	f(&pattern, &mut save[..save_len]);
}
fn print_match(file_name: &str, save: &[u32]) {
	print!("  {}!{:#010x}", file_name, save[0]);
	if save.len() > 1 {
		print!("  [");
		for i in 1..save.len() {
			print!("{}/{:#010x} ", i, save[i]);
		}
		print!("]");
	}
	println!();
}
<commit_msg>Add JSON output to findsig utility (#230)<commit_after>/*!
Find patterns utility.
 */

use std::{cmp, env};
use std::path::Path;
use std::io::{self, Write};
use std::ffi::OsStr;

use pelite::pattern as pat;

const HELP_TEXT: &'static str = "\
FINDSIG <FILE> [PAT]...

  FILE - Path to the input binary to scan.
  PAT  - Any number of patterns to find.

If no patterns are provided, they are interactively read line by line from stdin.

Find documentation about the pattern syntax here:
https://docs.rs/pelite/*/pelite/pattern/fn.parse.html
";

fn main() {
	// Get args and skip the invoker
	let mut args = env::args_os();
	args.next();

	// Read the input file and/or get json option
	let mut file_path = match args.next() {
		Some(file_path) => file_path,
		None => {
			print!("{}", HELP_TEXT);
			return;
		},
	};
	let mut json = false;
	if file_path == OsStr::new("-json") {
		json = true;
		file_path = match args.next() {
			Some(file_path) => file_path,
			None => {
				eprintln!("Missing required file path argument.");
				return;
			},
		}
	}

	// Get the patterns
	let patterns: Vec<String> = args.filter_map(|arg| arg.into_string().ok()).collect();
	if patterns.len() == 0 {
		json = false;
	}

	// Path and filename of the input file
	let file_path = Path::new(&file_path);
	let file_name = file_path.file_name().expect("path does not have a file name").to_str().unwrap();

	// Map the file into memory
	let file_map = pelite::FileMap::open(&file_path).expect("cannot open the input file");

	match pelite::PeFile::from_bytes(&file_map) {
		Ok(file) => {
			process_patterns(&patterns, json, &mut |pattern, save| {
				let mut matches = file.scanner().matches(pattern, file.headers().image_range());
				let mut first = true;
				while matches.next(save) {
					if json {
						if first { first = false; }
						else { print!(","); }
						print_json(save);
					}
					else {
						print_match(file_name, save);
					}
				}
			});
		}
		// Must be a valid PE file
		Err(err) => {
			panic!("Not a valid PE file: {}", err);
		},
	}
}

fn process_patterns(patterns: &[String], json: bool, f: &mut dyn FnMut(&[pat::Atom], &mut [u32])) {
	if patterns.len() > 0 {
		// Read from the command line args if available
		if json {
			print!("[");
		}
		let mut first = true;
		for pat in patterns {
			if first { first = false; }
			else { print!(","); }
			process_pattern(pat, json, f);
		}
		if json {
			println!("]");
		}
	}
	else {
		// Read from standard input if no patterns were provided on command line
		print!("Interactive REPL, enter any pattern to find its matches.\nPress Ctrl-C to quit.\n");
		loop {
			// Print a nice REPL
			print!(">>> ");
			let _ = io::stdout().flush();
			// Read input from stdin, handle any kind of abort by detecting the lack of newline (?)
			let mut line = String::new();
			if io::stdin().read_line(&mut line).is_err() || line.len() == 0 {
				break;
			}
			// Only process non-empty lines, otherwise ask the user again
			let line = line.trim();
			if line.len() > 0 {
				process_pattern(&line, false, f);
			}
		}
	}
}
fn process_pattern(pattern_str: &str, json: bool, f: &mut dyn FnMut(&[pat::Atom], &mut [u32])) {
	// Parse the pattern
	let pattern = match pat::parse(pattern_str) {
		Ok(pattern) => pattern,
		Err(err) => {
			eprintln!("Pattern `{}` error: {}", pattern_str, err);
			return;
		},
	};
	// Print the header followed by its matches
	if json {
		print!("{{\"pattern\":\"{}\",\"matches\":[", json_escape(pattern_str));
	}
	else {
		println!("Pattern `{}` matches:", pattern_str);
	}
	let mut save = [0; 32];
	let save_len = cmp::min(pat::save_len(&pattern), save.len());
	f(&pattern, &mut save[..save_len]);
	if json {
		print!("]}}");
	}
}
fn print_match(file_name: &str, save: &[u32]) {
	print!("  {}!{:#010x}", file_name, save[0]);
	if save.len() > 1 {
		print!("  [");
		for i in 1..save.len() {
			print!("{}/{:#010x} ", i, save[i]);
		}
		print!("]");
	}
	println!();
}
fn print_json(save: &[u32]) {
	print!("[");
	let mut first = true;
	for value in save {
		if first { first = false; }
		else { print!(","); }
		print!("{}", value);
	}
	print!("]");
}
fn json_escape(string: &str) -> String {
	let mut escaped = String::new();
	for chr in string.chars() {
		match chr {
			'\x08' => escaped.push_str("\\b"),
			'\x0C' => escaped.push_str("\\f"),
			'\n' => escaped.push_str("\\n"),
			'\r' => escaped.push_str("\\r"),
			'\t' => escaped.push_str("\\t"),
			'\"' => escaped.push_str("\\\""),
			'\\' => escaped.push_str("\\\\"),
			_ => escaped.push(chr),
		}
	}
	escaped
}
<|endoftext|>


<commit_before>// Copyright 2014-2020 Optimal Computing (NZ) Ltd.
// Licensed under the MIT license.  See LICENSE for details.

use core::{f32, f64};
#[cfg(feature = "num-traits")]
#[allow(unused_imports)]
use num_traits::float::FloatCore;
use super::Ulps;

/// A trait for approximate equality comparisons.
pub trait ApproxEq: Sized {
    /// This type type defines a margin within which two values are to be
    /// considered approximately equal. It must implement `Default` so that
    /// `approx_eq()` can be called on unknown types.
    type Margin: Copy + Default;

    /// This method tests that the `self` and `other` values are equal within `margin`
    /// of each other.
    fn approx_eq<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool;

    /// This method tests that the `self` and `other` values are not within `margin`
    /// of each other.
    fn approx_ne<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool {
        !self.approx_eq(other, margin)
    }
}

/// This type defines a margin within two `f32` values might be considered equal,
/// and is intended as the associated type for the `ApproxEq` trait.
///
/// Two tests are used to determine approximate equality.
///
/// The first test considers two values approximately equal if they differ by <=
/// `epsilon`. This will only succeed for very small numbers. Note that it may
/// succeed even if the parameters are of differing signs, straddling zero.
///
/// The second test considers how many ULPs (units of least precision, units in
/// the last place, which is the integer number of floating-point representations
/// that the parameters are separated by) different the parameters are and considers
/// them approximately equal if this is <= `ulps`. For large floating-point numbers,
/// an ULP can be a rather large gap, but this kind of comparison is necessary
/// because floating-point operations must round to the nearest representable value
/// and so larger floating-point values accumulate larger errors.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct F32Margin {
    pub epsilon: f32,
    pub ulps: i32
}
impl Default for F32Margin {
    #[inline]
    fn default() -> F32Margin {
        F32Margin {
            epsilon: f32::EPSILON,
            ulps: 4
        }
    }
}
impl F32Margin {
    #[inline]
    pub fn zero() -> F32Margin {
        F32Margin {
            epsilon: 0.0,
            ulps: 0
        }
    }
    pub fn epsilon(self, epsilon: f32) -> Self {
        F32Margin {
            epsilon: epsilon,
            ..self
        }
    }
    pub fn ulps(self, ulps: i32) -> Self {
        F32Margin {
            ulps: ulps,
            ..self
        }
    }
}
impl From<(f32, i32)> for F32Margin {
    fn from(m: (f32, i32)) -> F32Margin {
        F32Margin {
            epsilon: m.0,
            ulps: m.1
        }
    }
}

impl ApproxEq for f32 {
    type Margin = F32Margin;

    fn approx_eq<M: Into<Self::Margin>>(self, other: f32, margin: M) -> bool {
        let margin = margin.into();

        // Check for exact equality first. This is often true, and so we get the
        // performance benefit of only doing one compare in most cases.
        self==other ||

        // Perform epsilon comparison next
            ((self - other).abs() <= margin.epsilon) ||

        {
            // Perform ulps comparion last
            let diff: i32 = self.ulps(&other);
            saturating_abs_i32!(diff) <= margin.ulps
        }
    }
}

#[test]
fn f32_approx_eq_test1() {
    let f: f32 = 0.0_f32;
    let g: f32 = -0.0000000000000005551115123125783_f32;
    assert!(f != g); // Should not be directly equal
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test2() {
    let f: f32 = 0.0_f32;
    let g: f32 = -0.0_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test3() {
    let f: f32 = 0.0_f32;
    let g: f32 = 0.00000000000000001_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test4() {
    let f: f32 = 0.00001_f32;
    let g: f32 = 0.00000000000000001_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == false);
}
#[test]
fn f32_approx_eq_test5() {
    let f: f32 = 0.1_f32;
    let mut sum: f32 = 0.0_f32;
    for _ in 0_isize..10_isize { sum += f; }
    let product: f32 = f * 10.0_f32;
    assert!(sum != product); // Should not be directly equal:
    assert!(sum.approx_eq(product, (f32::EPSILON, 1)) == true);
    assert!(sum.approx_eq(product, F32Margin::zero()) == false);
}
#[test]
fn f32_approx_eq_test6() {
    let x: f32 = 1000000_f32;
    let y: f32 = 1000000.1_f32;
    assert!(x != y); // Should not be directly equal
    assert!(x.approx_eq(y, (0.0, 2)) == true); // 2 ulps does it
    // epsilon method no good here:
    assert!(x.approx_eq(y, (1000.0 * f32::EPSILON, 0)) == false);
}

/// This type defines a margin within two `f64` values might be considered equal,
/// and is intended as the associated type for the `ApproxEq` trait.
///
/// Two tests are used to determine approximate equality.
///
/// The first test considers two values approximately equal if they differ by <=
/// `epsilon`. This will only succeed for very small numbers. Note that it may
/// succeed even if the parameters are of differing signs, straddling zero.
///
/// The second test considers how many ULPs (units of least precision, units in
/// the last place, which is the integer number of floating-point representations
/// that the parameters are separated by) different the parameters are and considers
/// them approximately equal if this is <= `ulps`. For large floating-point numbers,
/// an ULP can be a rather large gap, but this kind of comparison is necessary
/// because floating-point operations must round to the nearest representable value
/// and so larger floating-point values accumulate larger errors.
#[derive(Debug, Clone, Copy)]
pub struct F64Margin {
    pub epsilon: f64,
    pub ulps: i64
}
impl Default for F64Margin {
    #[inline]
    fn default() -> F64Margin {
        F64Margin {
            epsilon: f64::EPSILON,
            ulps: 4
        }
    }
}
impl F64Margin {
    #[inline]
    pub fn zero() -> F64Margin {
        F64Margin {
            epsilon: 0.0,
            ulps: 0
        }
    }
    pub fn epsilon(self, epsilon: f64) -> Self {
        F64Margin {
            epsilon: epsilon,
            ..self
        }
    }
    pub fn ulps(self, ulps: i64) -> Self {
        F64Margin {
            ulps: ulps,
            ..self
        }
    }
}
impl From<(f64, i64)> for F64Margin {
    fn from(m: (f64, i64)) -> F64Margin {
        F64Margin {
            epsilon: m.0,
            ulps: m.1
        }
    }
}

impl ApproxEq for f64 {
    type Margin = F64Margin;

    fn approx_eq<M: Into<Self::Margin>>(self, other: f64, margin: M) -> bool {
        let margin = margin.into();

        // Check for exact equality first. This is often true, and so we get the
        // performance benefit of only doing one compare in most cases.
        self == other ||

        // Perform epsilon comparison next
            ((self - other).abs() <= margin.epsilon) ||

        {
            // Perform ulps comparion last
            let diff: i64 = self.ulps(&other);
            saturating_abs_i64!(diff) <= margin.ulps
        }
    }
}

#[test]
fn f64_approx_eq_test1() {
    let f: f64 = 0.0_f64;
    let g: f64 = -0.0000000000000005551115123125783_f64;
    assert!(f != g); // Should not be precisely equal.
    assert!(f.approx_eq(g, (3.0 * f64::EPSILON, 0)) == true); // 3e is enough.
    // ULPs test won't ever call these equal.
}
#[test]
fn f64_approx_eq_test2() {
    let f: f64 = 0.0_f64;
    let g: f64 = -0.0_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
}
#[test]
fn f64_approx_eq_test3() {
    let f: f64 = 0.0_f64;
    let g: f64 = 1e-17_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
}
#[test]
fn f64_approx_eq_test4() {
    let f: f64 = 0.00001_f64;
    let g: f64 = 0.00000000000000001_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == false);
}
#[test]
fn f64_approx_eq_test5() {
    let f: f64 = 0.1_f64;
    let mut sum: f64 = 0.0_f64;
    for _ in 0_isize..10_isize { sum += f; }
    let product: f64 = f * 10.0_f64;
    assert!(sum != product); // Should not be precisely equaly.
    assert!(sum.approx_eq(product, (f64::EPSILON, 0)) == true);
    assert!(sum.approx_eq(product, (0.0, 1)) == true);
}
#[test]
fn f64_approx_eq_test6() {
    let x: f64 = 1000000_f64;
    let y: f64 = 1000000.0000000003_f64;
    assert!(x != y); // Should not be precisely equal.
    assert!(x.approx_eq(y, (0.0, 3)) == true);
}
#[test]
fn f64_code_triggering_issue_20() {
    assert_eq!((-25.0f64).approx_eq(25.0, (0.00390625, 1)), false);
}
<commit_msg>Define ApproxEq on &[T]<commit_after>// Copyright 2014-2020 Optimal Computing (NZ) Ltd.
// Licensed under the MIT license.  See LICENSE for details.

use core::{f32, f64};
#[cfg(feature = "num-traits")]
#[allow(unused_imports)]
use num_traits::float::FloatCore;
use super::Ulps;

/// A trait for approximate equality comparisons.
pub trait ApproxEq: Sized {
    /// This type type defines a margin within which two values are to be
    /// considered approximately equal. It must implement `Default` so that
    /// `approx_eq()` can be called on unknown types.
    type Margin: Copy + Default;

    /// This method tests that the `self` and `other` values are equal within `margin`
    /// of each other.
    fn approx_eq<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool;

    /// This method tests that the `self` and `other` values are not within `margin`
    /// of each other.
    fn approx_ne<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool {
        !self.approx_eq(other, margin)
    }
}

/// This type defines a margin within two `f32` values might be considered equal,
/// and is intended as the associated type for the `ApproxEq` trait.
///
/// Two tests are used to determine approximate equality.
///
/// The first test considers two values approximately equal if they differ by <=
/// `epsilon`. This will only succeed for very small numbers. Note that it may
/// succeed even if the parameters are of differing signs, straddling zero.
///
/// The second test considers how many ULPs (units of least precision, units in
/// the last place, which is the integer number of floating-point representations
/// that the parameters are separated by) different the parameters are and considers
/// them approximately equal if this is <= `ulps`. For large floating-point numbers,
/// an ULP can be a rather large gap, but this kind of comparison is necessary
/// because floating-point operations must round to the nearest representable value
/// and so larger floating-point values accumulate larger errors.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct F32Margin {
    pub epsilon: f32,
    pub ulps: i32
}
impl Default for F32Margin {
    #[inline]
    fn default() -> F32Margin {
        F32Margin {
            epsilon: f32::EPSILON,
            ulps: 4
        }
    }
}
impl F32Margin {
    #[inline]
    pub fn zero() -> F32Margin {
        F32Margin {
            epsilon: 0.0,
            ulps: 0
        }
    }
    pub fn epsilon(self, epsilon: f32) -> Self {
        F32Margin {
            epsilon: epsilon,
            ..self
        }
    }
    pub fn ulps(self, ulps: i32) -> Self {
        F32Margin {
            ulps: ulps,
            ..self
        }
    }
}
impl From<(f32, i32)> for F32Margin {
    fn from(m: (f32, i32)) -> F32Margin {
        F32Margin {
            epsilon: m.0,
            ulps: m.1
        }
    }
}

impl ApproxEq for f32 {
    type Margin = F32Margin;

    fn approx_eq<M: Into<Self::Margin>>(self, other: f32, margin: M) -> bool {
        let margin = margin.into();

        // Check for exact equality first. This is often true, and so we get the
        // performance benefit of only doing one compare in most cases.
        self==other ||

        // Perform epsilon comparison next
            ((self - other).abs() <= margin.epsilon) ||

        {
            // Perform ulps comparion last
            let diff: i32 = self.ulps(&other);
            saturating_abs_i32!(diff) <= margin.ulps
        }
    }
}

#[test]
fn f32_approx_eq_test1() {
    let f: f32 = 0.0_f32;
    let g: f32 = -0.0000000000000005551115123125783_f32;
    assert!(f != g); // Should not be directly equal
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test2() {
    let f: f32 = 0.0_f32;
    let g: f32 = -0.0_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test3() {
    let f: f32 = 0.0_f32;
    let g: f32 = 0.00000000000000001_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
}
#[test]
fn f32_approx_eq_test4() {
    let f: f32 = 0.00001_f32;
    let g: f32 = 0.00000000000000001_f32;
    assert!(f.approx_eq(g, (f32::EPSILON, 0)) == false);
}
#[test]
fn f32_approx_eq_test5() {
    let f: f32 = 0.1_f32;
    let mut sum: f32 = 0.0_f32;
    for _ in 0_isize..10_isize { sum += f; }
    let product: f32 = f * 10.0_f32;
    assert!(sum != product); // Should not be directly equal:
    assert!(sum.approx_eq(product, (f32::EPSILON, 1)) == true);
    assert!(sum.approx_eq(product, F32Margin::zero()) == false);
}
#[test]
fn f32_approx_eq_test6() {
    let x: f32 = 1000000_f32;
    let y: f32 = 1000000.1_f32;
    assert!(x != y); // Should not be directly equal
    assert!(x.approx_eq(y, (0.0, 2)) == true); // 2 ulps does it
    // epsilon method no good here:
    assert!(x.approx_eq(y, (1000.0 * f32::EPSILON, 0)) == false);
}

/// This type defines a margin within two `f64` values might be considered equal,
/// and is intended as the associated type for the `ApproxEq` trait.
///
/// Two tests are used to determine approximate equality.
///
/// The first test considers two values approximately equal if they differ by <=
/// `epsilon`. This will only succeed for very small numbers. Note that it may
/// succeed even if the parameters are of differing signs, straddling zero.
///
/// The second test considers how many ULPs (units of least precision, units in
/// the last place, which is the integer number of floating-point representations
/// that the parameters are separated by) different the parameters are and considers
/// them approximately equal if this is <= `ulps`. For large floating-point numbers,
/// an ULP can be a rather large gap, but this kind of comparison is necessary
/// because floating-point operations must round to the nearest representable value
/// and so larger floating-point values accumulate larger errors.
#[derive(Debug, Clone, Copy)]
pub struct F64Margin {
    pub epsilon: f64,
    pub ulps: i64
}
impl Default for F64Margin {
    #[inline]
    fn default() -> F64Margin {
        F64Margin {
            epsilon: f64::EPSILON,
            ulps: 4
        }
    }
}
impl F64Margin {
    #[inline]
    pub fn zero() -> F64Margin {
        F64Margin {
            epsilon: 0.0,
            ulps: 0
        }
    }
    pub fn epsilon(self, epsilon: f64) -> Self {
        F64Margin {
            epsilon: epsilon,
            ..self
        }
    }
    pub fn ulps(self, ulps: i64) -> Self {
        F64Margin {
            ulps: ulps,
            ..self
        }
    }
}
impl From<(f64, i64)> for F64Margin {
    fn from(m: (f64, i64)) -> F64Margin {
        F64Margin {
            epsilon: m.0,
            ulps: m.1
        }
    }
}

impl ApproxEq for f64 {
    type Margin = F64Margin;

    fn approx_eq<M: Into<Self::Margin>>(self, other: f64, margin: M) -> bool {
        let margin = margin.into();

        // Check for exact equality first. This is often true, and so we get the
        // performance benefit of only doing one compare in most cases.
        self == other ||

        // Perform epsilon comparison next
            ((self - other).abs() <= margin.epsilon) ||

        {
            // Perform ulps comparion last
            let diff: i64 = self.ulps(&other);
            saturating_abs_i64!(diff) <= margin.ulps
        }
    }
}

#[test]
fn f64_approx_eq_test1() {
    let f: f64 = 0.0_f64;
    let g: f64 = -0.0000000000000005551115123125783_f64;
    assert!(f != g); // Should not be precisely equal.
    assert!(f.approx_eq(g, (3.0 * f64::EPSILON, 0)) == true); // 3e is enough.
    // ULPs test won't ever call these equal.
}
#[test]
fn f64_approx_eq_test2() {
    let f: f64 = 0.0_f64;
    let g: f64 = -0.0_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
}
#[test]
fn f64_approx_eq_test3() {
    let f: f64 = 0.0_f64;
    let g: f64 = 1e-17_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
}
#[test]
fn f64_approx_eq_test4() {
    let f: f64 = 0.00001_f64;
    let g: f64 = 0.00000000000000001_f64;
    assert!(f.approx_eq(g, (f64::EPSILON, 0)) == false);
}
#[test]
fn f64_approx_eq_test5() {
    let f: f64 = 0.1_f64;
    let mut sum: f64 = 0.0_f64;
    for _ in 0_isize..10_isize { sum += f; }
    let product: f64 = f * 10.0_f64;
    assert!(sum != product); // Should not be precisely equaly.
    assert!(sum.approx_eq(product, (f64::EPSILON, 0)) == true);
    assert!(sum.approx_eq(product, (0.0, 1)) == true);
}
#[test]
fn f64_approx_eq_test6() {
    let x: f64 = 1000000_f64;
    let y: f64 = 1000000.0000000003_f64;
    assert!(x != y); // Should not be precisely equal.
    assert!(x.approx_eq(y, (0.0, 3)) == true);
}
#[test]
fn f64_code_triggering_issue_20() {
    assert_eq!((-25.0f64).approx_eq(25.0, (0.00390625, 1)), false);
}

impl<T> ApproxEq for &[T]
where T: Copy + ApproxEq {
    type Margin = <T as ApproxEq>::Margin;

    fn approx_eq<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool {
        let margin = margin.into();
        if self.len() != other.len() { return false; }
        self.iter().zip(other.iter()).all(|(a,b)| {
            a.approx_eq(*b, margin)
        })
    }
}

#[test]
fn test_slices() {
    assert!( [1.33, 2.4, 2.5].approx_eq(&[1.33, 2.4, 2.5], (0.0, 0_i64)) );
    assert!( !  [1.33, 2.4, 2.6].approx_eq(&[1.33, 2.4, 2.5], (0.0, 0_i64)) );
    assert!( !  [1.33, 2.4].approx_eq(&[1.33, 2.4, 2.5], (0.0, 0_i64)) );
    assert!( !  [1.33, 2.4, 2.5].approx_eq(&[1.33, 2.4], (0.0, 0_i64)) );
}

<|endoftext|>


<commit_before>use std::io::Read;
use std::cell::RefCell;

use hyper::Client;
use hyper::header::Connection;
use hyper::header::{Headers, Authorization, Bearer};
use super::region::Region;
use super::auth::Token;

/// a commercetools client
pub struct CtpClient {
    api_url: String,
    auth_url: String,
    project_key: String,
    client_id: String,
    client_secret: String,
    client: Client,
    token: RefCell<Option<Token>>,
}

impl CtpClient {
    /// Returns a commercetools client for the given arguments
    ///
    /// # Arguments
    ///
    /// * `region` - the world region the client should use
    /// * `project_key` - project key
    /// * `client_id` - client id
    /// * `client_secret` - client secret
    ///
    /// # Examples
    ///
    /// ```
    /// use commercetools::region::Region;
    /// use commercetools::client::CtpClient;
    ///
    /// let client = CtpClient::new(&Region::Europe, "my project key", "my client id", "my client secret");
    /// ```
    pub fn new(region: &Region, project_key: &str, client_id: &str, client_secret: &str) -> CtpClient {
        CtpClient {
            api_url: region.api_url().to_string(),
            auth_url: region.auth_url().to_string(),
            project_key: project_key.to_string(),
            client_id: client_id.to_string(),
            client_secret: client_secret.to_string(),
            client: Client::new(),
            token: RefCell::new(None),
        }
    }

    pub fn get_token(&self) -> String {
        let mut cache = self.token.borrow_mut();
        if cache.is_some() {
            let token = cache.as_ref().unwrap();
            if token.is_valid() {
                return token.access_token.clone();
            }
        }

        let new_token = super::auth::retrieve_token(&self.client,
                                                    &self.auth_url,
                                                    &self.project_key,
                                                    &self.client_id,
                                                    &self.client_secret)
            .unwrap();

        *cache = Some(new_token.clone());
        new_token.access_token
    }

    pub fn request(&self, uri: &str) -> String {
        let client = &self.client;

        let access_token = self.get_token();

        let mut headers = Headers::new();
        headers.set(Authorization(Bearer { token: access_token }));

        let uri = format!("{}/{}{}", self.api_url, self.project_key, uri);
        let mut projets_res = client.get(&uri)
            .header(Connection::close())
            .headers(headers)
            .send()
            .unwrap();

        let mut body = String::new();
        projets_res.read_to_string(&mut body).unwrap();
        body
    }
}
<commit_msg>add todo about inefficient string cloning<commit_after>use std::io::Read;
use std::cell::RefCell;

use hyper::Client;
use hyper::header::Connection;
use hyper::header::{Headers, Authorization, Bearer};
use super::region::Region;
use super::auth::Token;

/// a commercetools client
pub struct CtpClient {
    api_url: String,
    auth_url: String,
    project_key: String,
    client_id: String,
    client_secret: String,
    client: Client,
    token: RefCell<Option<Token>>,
}

impl CtpClient {
    /// Returns a commercetools client for the given arguments
    ///
    /// # Arguments
    ///
    /// * `region` - the world region the client should use
    /// * `project_key` - project key
    /// * `client_id` - client id
    /// * `client_secret` - client secret
    ///
    /// # Examples
    ///
    /// ```
    /// use commercetools::region::Region;
    /// use commercetools::client::CtpClient;
    ///
    /// let client = CtpClient::new(&Region::Europe, "my project key", "my client id", "my client secret");
    /// ```
    pub fn new(region: &Region, project_key: &str, client_id: &str, client_secret: &str) -> CtpClient {
        CtpClient {
            api_url: region.api_url().to_string(),
            auth_url: region.auth_url().to_string(),
            project_key: project_key.to_string(),
            client_id: client_id.to_string(),
            client_secret: client_secret.to_string(),
            client: Client::new(),
            token: RefCell::new(None),
        }
    }

    // TODO (YaSi): avoid cloning the String on each call
    // return &str?
    // or use [borrow.Cow](https://doc.rust-lang.org/std/borrow/enum.Cow.html)?
    pub fn get_token(&self) -> String {
        let mut cache = self.token.borrow_mut();
        if cache.is_some() {
            let token = cache.as_ref().unwrap();
            if token.is_valid() {
                return token.access_token.clone();
            }
        }

        let new_token = super::auth::retrieve_token(&self.client,
                                                    &self.auth_url,
                                                    &self.project_key,
                                                    &self.client_id,
                                                    &self.client_secret)
            .unwrap();

        *cache = Some(new_token.clone());
        new_token.access_token
    }

    pub fn request(&self, uri: &str) -> String {
        let client = &self.client;

        let access_token = self.get_token();

        let mut headers = Headers::new();
        headers.set(Authorization(Bearer { token: access_token }));

        let uri = format!("{}/{}{}", self.api_url, self.project_key, uri);
        let mut projets_res = client.get(&uri)
            .header(Connection::close())
            .headers(headers)
            .send()
            .unwrap();

        let mut body = String::new();
        projets_res.read_to_string(&mut body).unwrap();
        body
    }
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use std::path::PathBuf;

pub const ROOT: &'static str = "/opt/bldr";
pub const PACKAGE_HOME: &'static str = "/opt/bldr/pkgs";
pub const SERVICE_HOME: &'static str = "/opt/bldr/svc";
pub const SOURCE_CACHE: &'static str = "/opt/bldr/cache/src";
pub const PACKAGE_CACHE: &'static str = "/opt/bldr/cache/pkgs";
pub const GPG_CACHE: &'static str = "/opt/bldr/cache/gpg";
pub const KEY_CACHE: &'static str = "/opt/bldr/cache/keys";

pub fn service_path(service_name: &str) -> PathBuf {
    PathBuf::from(SERVICE_HOME).join(service_name)
}
<commit_msg>Use `HAB_ROOT_PATH` for root of Habitat file system.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use std::path::PathBuf;

pub const ROOT_PATH: &'static str = "/opt/bldr";
pub const PACKAGE_HOME: &'static str = "/opt/bldr/pkgs";
pub const SERVICE_HOME: &'static str = "/opt/bldr/svc";
pub const SOURCE_CACHE: &'static str = "/opt/bldr/cache/src";
pub const PACKAGE_CACHE: &'static str = "/opt/bldr/cache/pkgs";
pub const GPG_CACHE: &'static str = "/opt/bldr/cache/gpg";
pub const KEY_CACHE: &'static str = "/opt/bldr/cache/keys";

pub fn service_path(service_name: &str) -> PathBuf {
    PathBuf::from(SERVICE_HOME).join(service_name)
}
<|endoftext|>