<commit_before>use crate::consts::{constant, Constant};
use if_chain::if_chain;
use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
use std::cmp::Ordering;

use crate::utils::sugg::Sugg;
use crate::utils::{get_parent_expr, is_integer_const, snippet, snippet_opt, span_lint, span_lint_and_then};
use crate::utils::{higher, SpanlessEq};

declare_clippy_lint! {
    /// **What it does:** Checks for zipping a collection with the range of
    /// `0.._.len()`.
    ///
    /// **Why is this bad?** The code is better expressed with `.enumerate()`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = vec![1];
    /// x.iter().zip(0..x.len());
    /// ```
    /// Could be written as
    /// ```rust
    /// # let x = vec![1];
    /// x.iter().enumerate();
    /// ```
    pub RANGE_ZIP_WITH_LEN,
    complexity,
    "zipping iterator with a range when `enumerate()` would do"
}

declare_clippy_lint! {
    /// **What it does:** Checks for exclusive ranges where 1 is added to the
    /// upper bound, e.g., `x..(y+1)`.
    ///
    /// **Why is this bad?** The code is more readable with an inclusive range
    /// like `x..=y`.
    ///
    /// **Known problems:** Will add unnecessary pair of parentheses when the
    /// expression is not wrapped in a pair but starts with a opening parenthesis
    /// and ends with a closing one.
    /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
    ///
    /// Also in many cases, inclusive ranges are still slower to run than
    /// exclusive ranges, because they essentially add an extra branch that
    /// LLVM may fail to hoist out of the loop.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// for x..(y+1) { .. }
    /// ```
    /// Could be written as
    /// ```rust,ignore
    /// for x..=y { .. }
    /// ```
    pub RANGE_PLUS_ONE,
    pedantic,
    "`x..(y+1)` reads better as `x..=y`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for inclusive ranges where 1 is subtracted from
    /// the upper bound, e.g., `x..=(y-1)`.
    ///
    /// **Why is this bad?** The code is more readable with an exclusive range
    /// like `x..y`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// for x..=(y-1) { .. }
    /// ```
    /// Could be written as
    /// ```rust,ignore
    /// for x..y { .. }
    /// ```
    pub RANGE_MINUS_ONE,
    complexity,
    "`x..=(y-1)` reads better as `x..y`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for range expressions `x..y` where both `x` and `y`
    /// are constant and `x` is greater or equal to `y`.
    ///
    /// **Why is this bad?** Empty ranges yield no values so iterating them is a no-op.
    /// Moreover, trying to use a reversed range to index a slice will panic at run-time.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,no_run
    /// fn main() {
    ///     (10..=0).for_each(|x| println!("{}", x));
    ///
    ///     let arr = [1, 2, 3, 4, 5];
    ///     let sub = &arr[3..1];
    /// }
    /// ```
    /// Use instead:
    /// ```rust
    /// fn main() {
    ///     (0..=10).rev().for_each(|x| println!("{}", x));
    ///
    ///     let arr = [1, 2, 3, 4, 5];
    ///     let sub = &arr[1..3];
    /// }
    /// ```
    pub REVERSED_EMPTY_RANGES,
    correctness,
    "reversing the limits of range expressions, resulting in empty ranges"
}

declare_lint_pass!(Ranges => [
    RANGE_ZIP_WITH_LEN,
    RANGE_PLUS_ONE,
    RANGE_MINUS_ONE,
    REVERSED_EMPTY_RANGES,
]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
            let name = path.ident.as_str();
            if name == "zip" && args.len() == 2 {
                let iter = &args[0].kind;
                let zip_arg = &args[1];
                if_chain! {
                    // `.iter()` call
                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
                    if iter_path.ident.name == sym!(iter);
                    // range expression in `.zip()` call: `0..x.len()`
                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
                    if is_integer_const(cx, start, 0);
                    // `.len()` call
                    if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.kind;
                    if len_path.ident.name == sym!(len) && len_args.len() == 1;
                    // `.iter()` and `.len()` called on same `Path`
                    if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;
                    if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].kind;
                    if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
                     then {
                         span_lint(cx,
                                   RANGE_ZIP_WITH_LEN,
                                   expr.span,
                                   &format!("It is more idiomatic to use `{}.iter().enumerate()`",
                                            snippet(cx, iter_args[0].span, "_")));
                    }
                }
            }
        }

        check_exclusive_range_plus_one(cx, expr);
        check_inclusive_range_minus_one(cx, expr);
        check_reversed_empty_range(cx, expr);
    }
}

// exclusive range plus one: `x..(y+1)`
fn check_exclusive_range_plus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let Some(higher::Range {
            start,
            end: Some(end),
            limits: RangeLimits::HalfOpen
        }) = higher::range(cx, expr);
        if let Some(y) = y_plus_one(cx, end);
        then {
            let span = if expr.span.from_expansion() {
                expr.span
                    .ctxt()
                    .outer_expn_data()
                    .call_site
            } else {
                expr.span
            };
            span_lint_and_then(
                cx,
                RANGE_PLUS_ONE,
                span,
                "an inclusive range would be more readable",
                |diag| {
                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
                    let end = Sugg::hir(cx, y, "y");
                    if let Some(is_wrapped) = &snippet_opt(cx, span) {
                        if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
                            diag.span_suggestion(
                                span,
                                "use",
                                format!("({}..={})", start, end),
                                Applicability::MaybeIncorrect,
                            );
                        } else {
                            diag.span_suggestion(
                                span,
                                "use",
                                format!("{}..={}", start, end),
                                Applicability::MachineApplicable, // snippet
                            );
                        }
                    }
                },
            );
        }
    }
}

// inclusive range minus one: `x..=(y-1)`
fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
        if let Some(y) = y_minus_one(cx, end);
        then {
            span_lint_and_then(
                cx,
                RANGE_MINUS_ONE,
                expr.span,
                "an exclusive range would be more readable",
                |diag| {
                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
                    let end = Sugg::hir(cx, y, "y");
                    diag.span_suggestion(
                        expr.span,
                        "use",
                        format!("{}..{}", start, end),
                        Applicability::MachineApplicable, // snippet
                    );
                },
            );
        }
    }
}

fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
        matches!(
            get_parent_expr(cx, expr),
            Some(Expr {
                kind: ExprKind::Index(..),
                ..
            })
        )
    }

    fn is_for_loop_arg(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
        let mut cur_expr = expr;
        while let Some(parent_expr) = get_parent_expr(cx, cur_expr) {
            match higher::for_loop(parent_expr) {
                Some((_, args, _)) if args.hir_id == expr.hir_id => return true,
                _ => cur_expr = parent_expr,
            }
        }

        false
    }

    fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
        match limits {
            RangeLimits::HalfOpen => ordering != Ordering::Less,
            RangeLimits::Closed => ordering == Ordering::Greater,
        }
    }

    if_chain! {
        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(cx, expr);
        let ty = cx.tables.expr_ty(start);
        if let ty::Int(_) | ty::Uint(_) = ty.kind;
        if let Some((start_idx, _)) = constant(cx, cx.tables, start);
        if let Some((end_idx, _)) = constant(cx, cx.tables, end);
        if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
        if is_empty_range(limits, ordering);
        then {
            if inside_indexing_expr(cx, expr) {
                // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
                if ordering != Ordering::Equal {
                    span_lint(
                        cx,
                        REVERSED_EMPTY_RANGES,
                        expr.span,
                        "this range is reversed and using it to index a slice will panic at run-time",
                    );
                }
            // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
            } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) {
                span_lint_and_then(
                    cx,
                    REVERSED_EMPTY_RANGES,
                    expr.span,
                    "this range is empty so it will yield no values",
                    |diag| {
                        if ordering != Ordering::Equal {
                            let start_snippet = snippet(cx, start.span, "_");
                            let end_snippet = snippet(cx, end.span, "_");
                            let dots = match limits {
                                RangeLimits::HalfOpen => "..",
                                RangeLimits::Closed => "..="
                            };

                            diag.span_suggestion(
                                expr.span,
                                "consider using the following if you are attempting to iterate over this \
                                 range in reverse",
                                format!("({}{}{}).rev()", end_snippet, dots, start_snippet),
                                Applicability::MaybeIncorrect,
                            );
                        }
                    },
                );
            }
        }
    }
}

fn y_plus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
    match expr.kind {
        ExprKind::Binary(
            Spanned {
                node: BinOpKind::Add, ..
            },
            ref lhs,
            ref rhs,
        ) => {
            if is_integer_const(cx, lhs, 1) {
                Some(rhs)
            } else if is_integer_const(cx, rhs, 1) {
                Some(lhs)
            } else {
                None
            }
        },
        _ => None,
    }
}

fn y_minus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
    match expr.kind {
        ExprKind::Binary(
            Spanned {
                node: BinOpKind::Sub, ..
            },
            ref lhs,
            ref rhs,
        ) if is_integer_const(cx, rhs, 1) => Some(lhs),
        _ => None,
    }
}
<commit_msg>Remove unnecessary lifetime parameter<commit_after>use crate::consts::{constant, Constant};
use if_chain::if_chain;
use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
use std::cmp::Ordering;

use crate::utils::sugg::Sugg;
use crate::utils::{get_parent_expr, is_integer_const, snippet, snippet_opt, span_lint, span_lint_and_then};
use crate::utils::{higher, SpanlessEq};

declare_clippy_lint! {
    /// **What it does:** Checks for zipping a collection with the range of
    /// `0.._.len()`.
    ///
    /// **Why is this bad?** The code is better expressed with `.enumerate()`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = vec![1];
    /// x.iter().zip(0..x.len());
    /// ```
    /// Could be written as
    /// ```rust
    /// # let x = vec![1];
    /// x.iter().enumerate();
    /// ```
    pub RANGE_ZIP_WITH_LEN,
    complexity,
    "zipping iterator with a range when `enumerate()` would do"
}

declare_clippy_lint! {
    /// **What it does:** Checks for exclusive ranges where 1 is added to the
    /// upper bound, e.g., `x..(y+1)`.
    ///
    /// **Why is this bad?** The code is more readable with an inclusive range
    /// like `x..=y`.
    ///
    /// **Known problems:** Will add unnecessary pair of parentheses when the
    /// expression is not wrapped in a pair but starts with a opening parenthesis
    /// and ends with a closing one.
    /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
    ///
    /// Also in many cases, inclusive ranges are still slower to run than
    /// exclusive ranges, because they essentially add an extra branch that
    /// LLVM may fail to hoist out of the loop.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// for x..(y+1) { .. }
    /// ```
    /// Could be written as
    /// ```rust,ignore
    /// for x..=y { .. }
    /// ```
    pub RANGE_PLUS_ONE,
    pedantic,
    "`x..(y+1)` reads better as `x..=y`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for inclusive ranges where 1 is subtracted from
    /// the upper bound, e.g., `x..=(y-1)`.
    ///
    /// **Why is this bad?** The code is more readable with an exclusive range
    /// like `x..y`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// for x..=(y-1) { .. }
    /// ```
    /// Could be written as
    /// ```rust,ignore
    /// for x..y { .. }
    /// ```
    pub RANGE_MINUS_ONE,
    complexity,
    "`x..=(y-1)` reads better as `x..y`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for range expressions `x..y` where both `x` and `y`
    /// are constant and `x` is greater or equal to `y`.
    ///
    /// **Why is this bad?** Empty ranges yield no values so iterating them is a no-op.
    /// Moreover, trying to use a reversed range to index a slice will panic at run-time.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,no_run
    /// fn main() {
    ///     (10..=0).for_each(|x| println!("{}", x));
    ///
    ///     let arr = [1, 2, 3, 4, 5];
    ///     let sub = &arr[3..1];
    /// }
    /// ```
    /// Use instead:
    /// ```rust
    /// fn main() {
    ///     (0..=10).rev().for_each(|x| println!("{}", x));
    ///
    ///     let arr = [1, 2, 3, 4, 5];
    ///     let sub = &arr[1..3];
    /// }
    /// ```
    pub REVERSED_EMPTY_RANGES,
    correctness,
    "reversing the limits of range expressions, resulting in empty ranges"
}

declare_lint_pass!(Ranges => [
    RANGE_ZIP_WITH_LEN,
    RANGE_PLUS_ONE,
    RANGE_MINUS_ONE,
    REVERSED_EMPTY_RANGES,
]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
            let name = path.ident.as_str();
            if name == "zip" && args.len() == 2 {
                let iter = &args[0].kind;
                let zip_arg = &args[1];
                if_chain! {
                    // `.iter()` call
                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
                    if iter_path.ident.name == sym!(iter);
                    // range expression in `.zip()` call: `0..x.len()`
                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
                    if is_integer_const(cx, start, 0);
                    // `.len()` call
                    if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.kind;
                    if len_path.ident.name == sym!(len) && len_args.len() == 1;
                    // `.iter()` and `.len()` called on same `Path`
                    if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;
                    if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].kind;
                    if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
                     then {
                         span_lint(cx,
                                   RANGE_ZIP_WITH_LEN,
                                   expr.span,
                                   &format!("It is more idiomatic to use `{}.iter().enumerate()`",
                                            snippet(cx, iter_args[0].span, "_")));
                    }
                }
            }
        }

        check_exclusive_range_plus_one(cx, expr);
        check_inclusive_range_minus_one(cx, expr);
        check_reversed_empty_range(cx, expr);
    }
}

// exclusive range plus one: `x..(y+1)`
fn check_exclusive_range_plus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let Some(higher::Range {
            start,
            end: Some(end),
            limits: RangeLimits::HalfOpen
        }) = higher::range(cx, expr);
        if let Some(y) = y_plus_one(cx, end);
        then {
            let span = if expr.span.from_expansion() {
                expr.span
                    .ctxt()
                    .outer_expn_data()
                    .call_site
            } else {
                expr.span
            };
            span_lint_and_then(
                cx,
                RANGE_PLUS_ONE,
                span,
                "an inclusive range would be more readable",
                |diag| {
                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
                    let end = Sugg::hir(cx, y, "y");
                    if let Some(is_wrapped) = &snippet_opt(cx, span) {
                        if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
                            diag.span_suggestion(
                                span,
                                "use",
                                format!("({}..={})", start, end),
                                Applicability::MaybeIncorrect,
                            );
                        } else {
                            diag.span_suggestion(
                                span,
                                "use",
                                format!("{}..={}", start, end),
                                Applicability::MachineApplicable, // snippet
                            );
                        }
                    }
                },
            );
        }
    }
}

// inclusive range minus one: `x..=(y-1)`
fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
        if let Some(y) = y_minus_one(cx, end);
        then {
            span_lint_and_then(
                cx,
                RANGE_MINUS_ONE,
                expr.span,
                "an exclusive range would be more readable",
                |diag| {
                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
                    let end = Sugg::hir(cx, y, "y");
                    diag.span_suggestion(
                        expr.span,
                        "use",
                        format!("{}..{}", start, end),
                        Applicability::MachineApplicable, // snippet
                    );
                },
            );
        }
    }
}

fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
        matches!(
            get_parent_expr(cx, expr),
            Some(Expr {
                kind: ExprKind::Index(..),
                ..
            })
        )
    }

    fn is_for_loop_arg(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
        let mut cur_expr = expr;
        while let Some(parent_expr) = get_parent_expr(cx, cur_expr) {
            match higher::for_loop(parent_expr) {
                Some((_, args, _)) if args.hir_id == expr.hir_id => return true,
                _ => cur_expr = parent_expr,
            }
        }

        false
    }

    fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
        match limits {
            RangeLimits::HalfOpen => ordering != Ordering::Less,
            RangeLimits::Closed => ordering == Ordering::Greater,
        }
    }

    if_chain! {
        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(cx, expr);
        let ty = cx.tables.expr_ty(start);
        if let ty::Int(_) | ty::Uint(_) = ty.kind;
        if let Some((start_idx, _)) = constant(cx, cx.tables, start);
        if let Some((end_idx, _)) = constant(cx, cx.tables, end);
        if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
        if is_empty_range(limits, ordering);
        then {
            if inside_indexing_expr(cx, expr) {
                // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
                if ordering != Ordering::Equal {
                    span_lint(
                        cx,
                        REVERSED_EMPTY_RANGES,
                        expr.span,
                        "this range is reversed and using it to index a slice will panic at run-time",
                    );
                }
            // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
            } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) {
                span_lint_and_then(
                    cx,
                    REVERSED_EMPTY_RANGES,
                    expr.span,
                    "this range is empty so it will yield no values",
                    |diag| {
                        if ordering != Ordering::Equal {
                            let start_snippet = snippet(cx, start.span, "_");
                            let end_snippet = snippet(cx, end.span, "_");
                            let dots = match limits {
                                RangeLimits::HalfOpen => "..",
                                RangeLimits::Closed => "..="
                            };

                            diag.span_suggestion(
                                expr.span,
                                "consider using the following if you are attempting to iterate over this \
                                 range in reverse",
                                format!("({}{}{}).rev()", end_snippet, dots, start_snippet),
                                Applicability::MaybeIncorrect,
                            );
                        }
                    },
                );
            }
        }
    }
}

fn y_plus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
    match expr.kind {
        ExprKind::Binary(
            Spanned {
                node: BinOpKind::Add, ..
            },
            ref lhs,
            ref rhs,
        ) => {
            if is_integer_const(cx, lhs, 1) {
                Some(rhs)
            } else if is_integer_const(cx, rhs, 1) {
                Some(lhs)
            } else {
                None
            }
        },
        _ => None,
    }
}

fn y_minus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
    match expr.kind {
        ExprKind::Binary(
            Spanned {
                node: BinOpKind::Sub, ..
            },
            ref lhs,
            ref rhs,
        ) if is_integer_const(cx, rhs, 1) => Some(lhs),
        _ => None,
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// A virtio descriptor chain.
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as usize) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as usize);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as usize)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add(4 + next_used * 8);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<commit_msg>devices: virtio - Limit avail_iter iterations<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// A virtio descriptor chain.
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as usize) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as usize);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as usize)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();
        let queue_len = Wrapping(last_index) - self.next_avail;

        if queue_len.0 > queue_size {
            return AvailIter {
                mem: mem,
                desc_table: GuestAddress(0),
                avail_ring: GuestAddress(0),
                next_index: Wrapping(0),
                last_index: Wrapping(0),
                queue_size: 0,
                next_avail: &mut self.next_avail,
            };
        }

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add(4 + next_used * 8);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<|endoftext|>


<commit_before>#![allow(missing_doc)]
#![allow(dead_code)]

//! A first person camera.

use std::num::{One, Zero};
use input::{Button, Keyboard};
use input::keyboard;
use {
    input,
    Camera,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: One> FirstPersonSettings<T> {
    /// Creates new first person camera settings with defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::W),
            move_backward_button: Keyboard(keyboard::S),
            strafe_left_button: Keyboard(keyboard::A),
            strafe_right_button: Keyboard(keyboard::D),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::LShift),
            move_faster_button: Keyboard(keyboard::LCtrl),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The position of the camera.
    pub position: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FirstPerson<T> {
    /// Creates a new first person camera.
    pub fn new(
        position: [T, ..3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Zero::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: One::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let [dx, dy, dz] = self.direction;
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new(
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        );
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Updates the position.
    pub fn update(&mut self, dt: f64) {
        let cam = self.camera(dt);
        self.position = cam.position;
    }

    /// Handles game event and updates camera.
    pub fn input(&mut self, e: &input::InputEvent) {
        let &FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            input::Move(input::MouseRelative(dx, dy)) => {
                let dx: T = FromPrimitive::from_f64(dx).unwrap();
                let dy: T = FromPrimitive::from_f64(dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
            },
            input::Press(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match button {
                    x if x == settings.move_forward_button => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_button => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_button => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_button => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_button => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_button => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_button => *velocity = _2,
                    _ => {}
                }
            },
            input::Release(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match button {
                    x if x == settings.move_forward_button => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_button => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_button => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_button => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_button => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_button => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_button => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<commit_msg>Add first person setting for an esdf keyboard.<commit_after>#![allow(missing_doc)]
#![allow(dead_code)]

//! A first person camera.

use std::num::{One, Zero};
use input::{Button, Keyboard};
use input::keyboard;
use {
    input,
    Camera,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: One> FirstPersonSettings<T> {
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::W),
            move_backward_button: Keyboard(keyboard::S),
            strafe_left_button: Keyboard(keyboard::A),
            strafe_right_button: Keyboard(keyboard::D),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::LShift),
            move_faster_button: Keyboard(keyboard::LCtrl),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::E),
            move_backward_button: Keyboard(keyboard::D),
            strafe_left_button: Keyboard(keyboard::S),
            strafe_right_button: Keyboard(keyboard::F),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::Z),
            move_faster_button: Keyboard(keyboard::LShift),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The position of the camera.
    pub position: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FirstPerson<T> {
    /// Creates a new first person camera.
    pub fn new(
        position: [T, ..3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Zero::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: One::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let [dx, dy, dz] = self.direction;
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new(
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        );
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Updates the position.
    pub fn update(&mut self, dt: f64) {
        let cam = self.camera(dt);
        self.position = cam.position;
    }

    /// Handles game event and updates camera.
    pub fn input(&mut self, e: &input::InputEvent) {
        let &FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            input::Move(input::MouseRelative(dx, dy)) => {
                let dx: T = FromPrimitive::from_f64(dx).unwrap();
                let dy: T = FromPrimitive::from_f64(dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
            },
            input::Press(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match button {
                    x if x == settings.move_forward_button => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_button => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_button => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_button => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_button => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_button => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_button => *velocity = _2,
                    _ => {}
                }
            },
            input::Release(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match button {
                    x if x == settings.move_forward_button => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_button => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_button => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_button => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_button => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_button => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_button => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<|endoftext|>


<commit_before>use {analysis, Timer, TimerPhase, Color, comparison};
use time_formatter::{Delta, TimeFormatter, Accuracy};
use serde_json::{to_writer, Result};
use std::io::Write;
use std::fmt::Write as FmtWrite;
use std::borrow::Cow;
use layout::editor::settings_description::{SettingsDescription, Value, Field};

#[derive(Default, Clone)]
pub struct Component {
    settings: Settings,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Settings {
    pub comparison_override: Option<String>,
    pub drop_decimals: bool,
    pub accuracy: Accuracy,
}

impl Default for Settings {
    fn default() -> Self {
        Self {
            comparison_override: None,
            drop_decimals: true,
            accuracy: Accuracy::Tenths,
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct State {
    pub text: String,
    pub time: String,
    pub color: Color,
}

impl State {
    pub fn write_json<W>(&self, writer: W) -> Result<()>
    where
        W: Write,
    {
        to_writer(writer, self)
    }
}

impl Component {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_settings(settings: Settings) -> Self {
        Self {
            settings,
            ..Default::default()
        }
    }

    pub fn settings(&self) -> &Settings {
        &self.settings
    }

    pub fn settings_mut(&mut self) -> &mut Settings {
        &mut self.settings
    }

    pub fn name(&self) -> Cow<str> {
        self.text(
            false,
            self.settings
                .comparison_override
                .as_ref()
                .map(String::as_ref),
        )
    }

    fn text(&self, live: bool, comparison: Option<&str>) -> Cow<str> {
        let text = if live {
            "Live Segment"
        } else {
            "Previous Segment"
        };
        let mut text = Cow::from(text);
        if let Some(comparison) = comparison {
            write!(text.to_mut(), " ({})", comparison::shorten(comparison)).unwrap();
        }
        text
    }

    pub fn state(&self, timer: &Timer) -> State {
        let mut time_change = None;
        let mut live_segment = false;
        let resolved_comparison = comparison::resolve(&self.settings.comparison_override, timer);
        let comparison = comparison::or_current(resolved_comparison, timer);

        let phase = timer.current_phase();
        let method = timer.current_timing_method();
        let split_index = timer.current_split_index() as usize;
        let color = if phase != TimerPhase::NotRunning {
            if (phase == TimerPhase::Running || phase == TimerPhase::Paused) &&
                analysis::check_live_delta(timer, false, comparison, method).is_some()
            {
                live_segment = true;
            }

            if live_segment {
                time_change = analysis::live_segment_delta(timer, split_index, comparison, method);
            } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                time_change =
                    analysis::previous_segment_delta(timer, prev_split_index, comparison, method);
            }

            if let Some(time_change) = time_change {
                if live_segment {
                    analysis::split_color(
                        timer,
                        time_change.into(),
                        split_index,
                        false,
                        false,
                        comparison,
                        method,
                    )
                } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                    analysis::split_color(
                        timer,
                        time_change.into(),
                        prev_split_index,
                        false,
                        true,
                        comparison,
                        method,
                    )
                } else {
                    Color::Default
                }
            } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                analysis::split_color(
                    timer,
                    None,
                    prev_split_index,
                    true,
                    true,
                    comparison,
                    method,
                )
            } else {
                Color::Default
            }
        } else {
            Color::Default
        };

        let text = self.text(live_segment, resolved_comparison);

        State {
            text: text.into_owned(),
            time: Delta::custom(self.settings.drop_decimals, self.settings.accuracy)
                .format(time_change)
                .to_string(),
            color: color,
        }
    }

    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new(
                "Comparison".into(),
                self.settings.comparison_override.clone().into(),
            ),
            Field::new("Drop Decimals".into(), self.settings.drop_decimals.into()),
            Field::new("Accuracy".into(), self.settings.accuracy.into()),
        ])
    }

    pub fn set_value(&mut self, index: usize, value: Value) {
        match index {
            0 => self.settings.comparison_override = value.into(),
            1 => self.settings.drop_decimals = value.into(),
            2 => self.settings.accuracy = value.into(),
            _ => panic!("Unsupported Setting Index"),
        }
    }
}
<commit_msg>Add Possible Time Save to Previous Segment<commit_after>use {analysis, Timer, TimerPhase, Color, comparison};
use time_formatter::{Delta, PossibleTimeSave, TimeFormatter, Accuracy};
use serde_json::{to_writer, Result};
use std::io::Write;
use std::fmt::Write as FmtWrite;
use std::borrow::Cow;
use layout::editor::settings_description::{SettingsDescription, Value, Field};

#[derive(Default, Clone)]
pub struct Component {
    settings: Settings,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Settings {
    pub comparison_override: Option<String>,
    pub drop_decimals: bool,
    pub accuracy: Accuracy,
    pub show_possible_time_save: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Self {
            comparison_override: None,
            drop_decimals: true,
            accuracy: Accuracy::Tenths,
            show_possible_time_save: true,
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct State {
    pub text: String,
    pub time: String,
    pub color: Color,
}

impl State {
    pub fn write_json<W>(&self, writer: W) -> Result<()>
    where
        W: Write,
    {
        to_writer(writer, self)
    }
}

impl Component {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_settings(settings: Settings) -> Self {
        Self {
            settings,
            ..Default::default()
        }
    }

    pub fn settings(&self) -> &Settings {
        &self.settings
    }

    pub fn settings_mut(&mut self) -> &mut Settings {
        &mut self.settings
    }

    pub fn name(&self) -> Cow<str> {
        self.text(
            false,
            self.settings
                .comparison_override
                .as_ref()
                .map(String::as_ref),
        )
    }

    fn text(&self, live: bool, comparison: Option<&str>) -> Cow<str> {
        let text = if live {
            "Live Segment"
        } else {
            "Previous Segment"
        };
        let mut text = Cow::from(text);
        if let Some(comparison) = comparison {
            write!(text.to_mut(), " ({})", comparison::shorten(comparison)).unwrap();
        }
        text
    }

    pub fn state(&self, timer: &Timer) -> State {
        let mut time_change = None;
        let mut previous_possible = None;
        let mut live_segment = false;
        let resolved_comparison = comparison::resolve(&self.settings.comparison_override, timer);
        let comparison = comparison::or_current(resolved_comparison, timer);

        let phase = timer.current_phase();
        let method = timer.current_timing_method();
        let split_index = timer.current_split_index() as usize;
        let color = if phase != TimerPhase::NotRunning {
            if (phase == TimerPhase::Running || phase == TimerPhase::Paused) &&
                analysis::check_live_delta(timer, false, comparison, method).is_some()
            {
                live_segment = true;
            }

            if live_segment {
                time_change = analysis::live_segment_delta(timer, split_index, comparison, method);
                if self.settings.show_possible_time_save {
                    previous_possible = analysis::possible_time_save::calculate(
                        timer,
                        split_index,
                        comparison,
                        false,
                    );
                }
            } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                time_change =
                    analysis::previous_segment_delta(timer, prev_split_index, comparison, method);
                if self.settings.show_possible_time_save {
                    previous_possible = analysis::possible_time_save::calculate(
                        timer,
                        prev_split_index,
                        comparison,
                        false,
                    );
                }
            };

            if let Some(time_change) = time_change {
                if live_segment {
                    analysis::split_color(
                        timer,
                        time_change.into(),
                        split_index,
                        false,
                        false,
                        comparison,
                        method,
                    )
                } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                    analysis::split_color(
                        timer,
                        time_change.into(),
                        prev_split_index,
                        false,
                        true,
                        comparison,
                        method,
                    )
                } else {
                    Color::Default
                }
            } else if let Some(prev_split_index) = split_index.checked_sub(1) {
                analysis::split_color(
                    timer,
                    None,
                    prev_split_index,
                    true,
                    true,
                    comparison,
                    method,
                )
            } else {
                Color::Default
            }
        } else {
            Color::Default
        };

        let text = self.text(live_segment, resolved_comparison);
        let mut time = Delta::custom(self.settings.drop_decimals, self.settings.accuracy)
            .format(time_change)
            .to_string();

        if self.settings.show_possible_time_save {
            write!(
                time,
                " / {}",
                PossibleTimeSave::with_accuracy(self.settings.accuracy).format(previous_possible)
            ).unwrap();
        }

        State {
            text: text.into_owned(),
            time: time,
            color: color,
        }
    }

    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new(
                "Comparison".into(),
                self.settings.comparison_override.clone().into(),
            ),
            Field::new("Drop Decimals".into(), self.settings.drop_decimals.into()),
            Field::new("Accuracy".into(), self.settings.accuracy.into()),
            Field::new(
                "Show Possible Time Save".into(),
                self.settings.show_possible_time_save.into(),
            ),
        ])
    }

    pub fn set_value(&mut self, index: usize, value: Value) {
        match index {
            0 => self.settings.comparison_override = value.into(),
            1 => self.settings.drop_decimals = value.into(),
            2 => self.settings.accuracy = value.into(),
            3 => self.settings.show_possible_time_save = value.into(),
            _ => panic!("Unsupported Setting Index"),
        }
    }
}
<|endoftext|>


<commit_before>//! OpenTelemetry shared core date types
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use std::borrow::Cow;

/// Key used for metric `LabelSet`s and trace `Span` attributes.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Key(Cow<'static, str>);

impl Key {
    /// Create a new `Key`.
    pub fn new<S: Into<Cow<'static, str>>>(value: S) -> Self {
        Key(value.into())
    }

    /// Create a `KeyValue` pair for `bool` values.
    pub fn bool<T: Into<bool>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::Bool(value.into()),
        }
    }

    /// Create a `KeyValue` pair for `i64` values.
    pub fn i64(&self, value: i64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::I64(value),
        }
    }

    /// Create a `KeyValue` pair for `u64` values.
    pub fn u64(&self, value: u64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::U64(value),
        }
    }

    /// Create a `KeyValue` pair for `f64` values.
    pub fn f64(&self, value: f64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::F64(value),
        }
    }

    /// Create a `KeyValue` pair for `String` values.
    pub fn string<T: Into<String>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::String(value.into()),
        }
    }

    /// Create a `KeyValue` pair for byte arrays.
    pub fn bytes<T: Into<Vec<u8>>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::Bytes(value.into()),
        }
    }

    /// Returns a reference to the underlying key name
    pub fn as_str(&self) -> &str {
        self.0.as_ref()
    }
}

impl From<&'static str> for Key {
    /// Convert a `&str` to a `Key`.
    fn from(key_str: &'static str) -> Self {
        Key(Cow::from(key_str))
    }
}

impl Into<String> for Key {
    /// Converts `Key` instances into `String`.
    fn into(self) -> String {
        self.0.to_string()
    }
}

/// Value types for use in `KeyValue` pairs.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// bool values
    Bool(bool),
    /// i64 values
    I64(i64),
    /// u64 values
    U64(u64),
    /// f64 values
    F64(f64),
    /// String values
    String(String),
    /// Byte array values
    Bytes(Vec<u8>),
}

macro_rules! from_values {
   (
        $(
            ($t:ty, $val:expr);
        )+
    ) => {
        $(
            impl From<$t> for Value {
                fn from(t: $t) -> Self {
                    $val(t)
                }
            }
        )+
    }
}

from_values!(
    (bool, Value::Bool);
    (i64, Value::I64);
    (u64, Value::U64);
    (f64, Value::F64);
    (String, Value::String);
    (Vec<u8>, Value::Bytes);
);

impl From<&str> for Value {
    /// Convenience method for creating a `Value` form a `&str`.
    fn from(value_str: &str) -> Self {
        Value::String(value_str.to_string())
    }
}

impl Into<String> for Value {
    /// Convert `Value` types to `String` for use by exporters that only use
    /// `String` values.
    fn into(self) -> String {
        match self {
            Value::Bool(value) => value.to_string(),
            Value::I64(value) => value.to_string(),
            Value::U64(value) => value.to_string(),
            Value::F64(value) => value.to_string(),
            Value::String(value) => value,
            Value::Bytes(value) => String::from_utf8(value).unwrap_or_else(|_| String::new()),
        }
    }
}

/// `KeyValue` pairs are used by `LabelSet`s and `Span` attributes.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct KeyValue {
    /// Dimension or event key
    pub key: Key,
    /// Dimension or event value
    pub value: Value,
}

impl KeyValue {
    /// Create a new `KeyValue` pair.
    pub fn new<K, V>(key: K, value: V) -> Self
    where
        K: Into<Key>,
        V: Into<Value>,
    {
        KeyValue {
            key: key.into(),
            value: value.into(),
        }
    }
}

/// Units denote underlying data units tracked by `Meter`s.
#[derive(Default, Debug)]
pub struct Unit(String);

impl Unit {
    /// Create a new `Unit` from an `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        Unit(value.into())
    }

    /// View unit as &str
    pub fn as_str(&self) -> &str {
        &self.0
    }
}
<commit_msg>Fix api/core comment typo (#100)<commit_after>//! OpenTelemetry shared core date types
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use std::borrow::Cow;

/// Key used for metric `LabelSet`s and trace `Span` attributes.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Key(Cow<'static, str>);

impl Key {
    /// Create a new `Key`.
    pub fn new<S: Into<Cow<'static, str>>>(value: S) -> Self {
        Key(value.into())
    }

    /// Create a `KeyValue` pair for `bool` values.
    pub fn bool<T: Into<bool>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::Bool(value.into()),
        }
    }

    /// Create a `KeyValue` pair for `i64` values.
    pub fn i64(&self, value: i64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::I64(value),
        }
    }

    /// Create a `KeyValue` pair for `u64` values.
    pub fn u64(&self, value: u64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::U64(value),
        }
    }

    /// Create a `KeyValue` pair for `f64` values.
    pub fn f64(&self, value: f64) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::F64(value),
        }
    }

    /// Create a `KeyValue` pair for `String` values.
    pub fn string<T: Into<String>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::String(value.into()),
        }
    }

    /// Create a `KeyValue` pair for byte arrays.
    pub fn bytes<T: Into<Vec<u8>>>(&self, value: T) -> KeyValue {
        KeyValue {
            key: self.clone(),
            value: Value::Bytes(value.into()),
        }
    }

    /// Returns a reference to the underlying key name
    pub fn as_str(&self) -> &str {
        self.0.as_ref()
    }
}

impl From<&'static str> for Key {
    /// Convert a `&str` to a `Key`.
    fn from(key_str: &'static str) -> Self {
        Key(Cow::from(key_str))
    }
}

impl Into<String> for Key {
    /// Converts `Key` instances into `String`.
    fn into(self) -> String {
        self.0.to_string()
    }
}

/// Value types for use in `KeyValue` pairs.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// bool values
    Bool(bool),
    /// i64 values
    I64(i64),
    /// u64 values
    U64(u64),
    /// f64 values
    F64(f64),
    /// String values
    String(String),
    /// Byte array values
    Bytes(Vec<u8>),
}

macro_rules! from_values {
   (
        $(
            ($t:ty, $val:expr);
        )+
    ) => {
        $(
            impl From<$t> for Value {
                fn from(t: $t) -> Self {
                    $val(t)
                }
            }
        )+
    }
}

from_values!(
    (bool, Value::Bool);
    (i64, Value::I64);
    (u64, Value::U64);
    (f64, Value::F64);
    (String, Value::String);
    (Vec<u8>, Value::Bytes);
);

impl From<&str> for Value {
    /// Convenience method for creating a `Value` from a `&str`.
    fn from(value_str: &str) -> Self {
        Value::String(value_str.to_string())
    }
}

impl Into<String> for Value {
    /// Convert `Value` types to `String` for use by exporters that only use
    /// `String` values.
    fn into(self) -> String {
        match self {
            Value::Bool(value) => value.to_string(),
            Value::I64(value) => value.to_string(),
            Value::U64(value) => value.to_string(),
            Value::F64(value) => value.to_string(),
            Value::String(value) => value,
            Value::Bytes(value) => String::from_utf8(value).unwrap_or_else(|_| String::new()),
        }
    }
}

/// `KeyValue` pairs are used by `LabelSet`s and `Span` attributes.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct KeyValue {
    /// Dimension or event key
    pub key: Key,
    /// Dimension or event value
    pub value: Value,
}

impl KeyValue {
    /// Create a new `KeyValue` pair.
    pub fn new<K, V>(key: K, value: V) -> Self
    where
        K: Into<Key>,
        V: Into<Value>,
    {
        KeyValue {
            key: key.into(),
            value: value.into(),
        }
    }
}

/// Units denote underlying data units tracked by `Meter`s.
#[derive(Default, Debug)]
pub struct Unit(String);

impl Unit {
    /// Create a new `Unit` from an `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        Unit(value.into())
    }

    /// View unit as &str
    pub fn as_str(&self) -> &str {
        &self.0
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Architecture-specific implementation

// 64-bit x86_64 (long mode)
#[cfg(target_arch="x86_64")] mod x86_64;
#[cfg(target_arch="x86_64")] pub use self::x86_64::{ cpu, drivers };

// 32-bit x86 (protected mode)
// TODO: NYI
#[cfg(target_arch = "x86")] mod x86;
#[cfg(target_arch = "x86")] pub use self::x86::{ cpu, drivers };

// ARM v7
// TODO: NYI
#[cfg(target_arch = "armv7")] mod armv7;
#[cfg(target_arch = "armv7")] pub use self::x86::{ cpu, drivers };
<commit_msg>[kernel] arch module reexports everything now<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Architecture-specific implementation

// 64-bit x86_64 (long mode)
#[cfg(target_arch="x86_64")] mod x86_64;
#[cfg(target_arch="x86_64")] pub use self::x86_64::*;

// 32-bit x86 (protected mode)
// TODO: NYI
#[cfg(target_arch = "x86")] mod x86;
#[cfg(target_arch = "x86")] pub use self::x86::*;

// ARM v7
// TODO: NYI
#[cfg(target_arch = "armv7")] mod armv7;
#[cfg(target_arch = "armv7")] pub use self::x86::*;
<|endoftext|>


<commit_before>trait Trait {}

fn foo<X: Trait>(t: X) {}

impl<'a> Trait for &'a i32 {}

trait Foo {
    fn f(&self);
}

trait Bar {
    fn f(&self);
}

struct Baz;

impl Foo for Baz {
    fn f(&self) { println!("Baz’s impl of Foo"); }
}

//impl Bar for Baz {
//    fn f(&self) { println!("Baz’s impl of Bar"); }
//}
//
//impl Baz {
//    fn f(&self) { println!("Baz's impl"); }
//}

fn main() {
    let t: &mut i32 = &mut 0;
    foo(t as &i32);

    let b = Baz;
    b.f();
}<commit_msg>test for Sized marker: can be used for compile time assert<commit_after>trait Trait {}

fn foo<X: Trait>(_: X) {}

impl<'a> Trait for &'a i32 {}

trait Foo {
    fn f(&self);
}

trait Bar {
    fn f(&self);
}

struct Baz;

impl Foo for Baz {
    fn f(&self) { println!("Baz’s impl of Foo"); }
}

//impl Bar for Baz {
//    fn f(&self) { println!("Baz’s impl of Bar"); }
//}
//
//impl Baz {
//    fn f(&self) { println!("Baz's impl"); }
//}

const CONSTANT_STRING: &'static str = "This is a constant string";

const CONSTANT_ARRAY: &'static [u8] = &[0u8; 128];

fn assert_same_type<'a, 'b, T: ?Sized>(_: &'a T, _: &'b T) {}

fn main() {
    let another_string = "This string is local to the main function";

    assert_same_type(CONSTANT_STRING, another_string);

    println!("size of constant string:{}", std::mem::size_of_val(CONSTANT_STRING));
    println!("size of another  string:{}", std::mem::size_of_val(another_string));

    let another_array = &[1u8; 64];

    println!("size of constant array:{}", std::mem::size_of_val(CONSTANT_ARRAY));
    println!("size of another  array:{}", std::mem::size_of_val(another_array));

    assert_same_type(CONSTANT_ARRAY, another_array);

    let t: &mut i32 = &mut 0;
    foo(t as &i32);

    let b = Baz;
    b.f();
}<|endoftext|>


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

//! Various macro helpers.

/// A macro to parse an identifier, or return an `UnexpectedIndent` error
/// otherwise.
///
/// FIXME(emilio): The fact that `UnexpectedIdent` is a `SelectorParseError`
/// doesn't make a lot of sense to me.
macro_rules! try_match_ident_ignore_ascii_case {
    ($ident:expr, $( $match_body:tt )*) => {
        let __ident = $ident;
        (match_ignore_ascii_case! { &*__ident,
            $( $match_body )*
            _ => Err(()),
        })
        .map_err(|()| {
            ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident.clone()).into()
        })
    }
}

macro_rules! define_numbered_css_keyword_enum {
    ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
        define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
    };
    ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
        #[allow(non_camel_case_types, missing_docs)]
        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
        pub enum $name {
            $( $variant = $value ),+
        }

        impl $crate::parser::Parse for $name {
            #[allow(missing_docs)]
            fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
                             input: &mut ::cssparser::Parser<'i, 't>)
                             -> Result<$name, ::style_traits::ParseError<'i>> {
                try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                    $( $css => Ok($name::$variant), )+
                }
            }
        }

        impl ::style_traits::values::ToCss for $name {
            fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
                where W: ::std::fmt::Write,
            {
                match *self {
                    $( $name::$variant => dest.write_str($css) ),+
                }
            }
        }
    }
}

/// A macro for implementing `ComputedValueAsSpecified`, and `Parse` traits for
/// the enums defined using `define_css_keyword_enum` macro.
///
/// NOTE: We should either move `Parse` trait to `style_traits`
/// or `define_css_keyword_enum` macro to this crate, but that
/// may involve significant cleanup in both the crates.
macro_rules! add_impls_for_keyword_enum {
    ($name:ident) => {
        impl $crate::parser::Parse for $name {
            #[inline]
            fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
                             input: &mut ::cssparser::Parser<'i, 't>)
                             -> Result<Self, ::style_traits::ParseError<'i>> {
                $name::parse(input)
            }
        }

        impl $crate::values::computed::ComputedValueAsSpecified for $name {}
    };
}

macro_rules! define_keyword_type {
    ($name: ident, $css: expr) => {
        #[allow(missing_docs)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq)]
        #[derive(ToAnimatedZero, ToCss)]
        pub struct $name;

        impl fmt::Debug for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str($css)
            }
        }

        impl $crate::parser::Parse for $name {
            fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
                             input: &mut ::cssparser::Parser<'i, 't>)
                             -> Result<$name, ::style_traits::ParseError<'i>> {
                input.expect_ident_matching($css).map(|_| $name).map_err(|e| e.into())
            }
        }

        impl $crate::values::computed::ComputedValueAsSpecified for $name {}
        impl $crate::values::animated::AnimatedValueAsComputed for $name {}
    };
}
<commit_msg>style: Minor reformatting in macros.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Various macro helpers.

/// A macro to parse an identifier, or return an `UnexpectedIndent` error
/// otherwise.
///
/// FIXME(emilio): The fact that `UnexpectedIdent` is a `SelectorParseError`
/// doesn't make a lot of sense to me.
macro_rules! try_match_ident_ignore_ascii_case {
    ($ident:expr, $( $match_body:tt )*) => {
        let __ident = $ident;
        (match_ignore_ascii_case! { &*__ident,
            $( $match_body )*
            _ => Err(()),
        })
        .map_err(|()| {
            ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident.clone()).into()
        })
    }
}

macro_rules! define_numbered_css_keyword_enum {
    ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
        define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
    };
    ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
        #[allow(non_camel_case_types, missing_docs)]
        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
        pub enum $name {
            $( $variant = $value ),+
        }

        impl $crate::parser::Parse for $name {
            fn parse<'i, 't>(
                _context: &$crate::parser::ParserContext,
                input: &mut ::cssparser::Parser<'i, 't>,
            ) -> Result<$name, ::style_traits::ParseError<'i>> {
                try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                    $( $css => Ok($name::$variant), )+
                }
            }
        }

        impl ::style_traits::values::ToCss for $name {
            fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
            where
                W: ::std::fmt::Write,
            {
                match *self {
                    $( $name::$variant => dest.write_str($css) ),+
                }
            }
        }
    }
}

/// A macro for implementing `ComputedValueAsSpecified`, and `Parse` traits for
/// the enums defined using `define_css_keyword_enum` macro.
///
/// NOTE: We should either move `Parse` trait to `style_traits`
/// or `define_css_keyword_enum` macro to this crate, but that
/// may involve significant cleanup in both the crates.
macro_rules! add_impls_for_keyword_enum {
    ($name:ident) => {
        impl $crate::parser::Parse for $name {
            #[inline]
            fn parse<'i, 't>(
                _context: &$crate::parser::ParserContext,
                input: &mut ::cssparser::Parser<'i, 't>,
            ) -> Result<Self, ::style_traits::ParseError<'i>> {
                $name::parse(input)
            }
        }

        impl $crate::values::computed::ComputedValueAsSpecified for $name {}
    };
}

macro_rules! define_keyword_type {
    ($name: ident, $css: expr) => {
        #[allow(missing_docs)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq)]
        #[derive(ToAnimatedZero, ToCss)]
        pub struct $name;

        impl fmt::Debug for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str($css)
            }
        }

        impl $crate::parser::Parse for $name {
            fn parse<'i, 't>(
                _context: &$crate::parser::ParserContext,
                input: &mut ::cssparser::Parser<'i, 't>
            ) -> Result<$name, ::style_traits::ParseError<'i>> {
                input.expect_ident_matching($css).map(|_| $name).map_err(|e| e.into())
            }
        }

        impl $crate::values::computed::ComputedValueAsSpecified for $name {}
        impl $crate::values::animated::AnimatedValueAsComputed for $name {}
    };
}
<|endoftext|>