<commit_before>use crate::utils;
use crate::utils::sugg::Sugg;
use crate::utils::{match_type, paths, span_lint_and_sugg};
use if_chain::if_chain;

use rustc_errors::Applicability;
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use std::marker::PhantomData;

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of  `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a simple
    /// expression) or `Option::map_or_else` (if the else bit is a longer
    /// block).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an if let expression.
    ///
    /// **Known problems:**
    /// This lint uses whether the block is just an expression or if it has
    /// more statements to decide whether to use `Option::map_or` or
    /// `Option::map_or_else`. If you have a single expression which calls
    /// an expensive function, then it would be more efficient to use
    /// `Option::map_or_else`, but this lint would suggest `Option::map_or`.
    ///
    /// Also, this lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function;
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    style,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind {
        path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT)
    } else {
        false
    }
}

/// A struct containing information about occurences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
    wrap_braces: bool,
}

struct ReturnBreakContinueVisitor<'tcx> {
    seen_return_break_continue: bool,
    phantom_data: PhantomData<&'tcx bool>,
}
impl<'tcx> ReturnBreakContinueVisitor<'tcx> {
    fn new() -> ReturnBreakContinueVisitor<'tcx> {
        ReturnBreakContinueVisitor {
            seen_return_break_continue: false,
            phantom_data: PhantomData,
        }
    }
}
impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> {
    type Map = Map<'tcx>;
    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
        if self.seen_return_break_continue {
            // No need to look farther if we've already seen one of them
            return;
        }
        match &ex.kind {
            ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => {
                self.seen_return_break_continue = true;
            },
            // Something special could be done here to handle while or for loop
            // desugaring, as this will detect a break if there's a while loop
            // or a for loop inside the expression.
            _ => {
                rustc_hir::intravisit::walk_expr(self, ex);
            },
        }
    }
}

fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool {
    let mut recursive_visitor: ReturnBreakContinueVisitor<'tcx> = ReturnBreakContinueVisitor::new();
    recursive_visitor.visit_expr(expression);
    recursive_visitor.seen_return_break_continue
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(&expr)
        } else {
            Some(&arm.body)
        }
    } else {
        None
    }
}

/// If this is the else body of an if/else expression, then we need to wrap
/// it in curcly braces. Otherwise, we don't.
fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
        if let Some(Expr {
            kind:
                ExprKind::Match(
                    _,
                    arms,
                    MatchSource::IfDesugar {
                        contains_else_clause: true,
                    }
                    | MatchSource::IfLetDesugar {
                        contains_else_clause: true,
                    },
                ),
            ..
        }) = parent.expr
        {
            expr.hir_id == arms[1].body.hir_id
        } else {
            false
        }
    })
}

fn format_option_in_sugg(
    cx: &LateContext<'_, '_>,
    cond_expr: &Expr<'_>,
    parens_around_option: bool,
    as_ref: bool,
    as_mut: bool,
) -> String {
    format!(
        "{}{}{}{}",
        if parens_around_option { "(" } else { "" },
        Sugg::hir(cx, cond_expr, ".."),
        if parens_around_option { ")" } else { "" },
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if utils::match_qpath(struct_qpath, &paths::OPTION_SOME);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue(arms[0].body);
        if !contains_return_break_continue(arms[1].body);
        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = match &none_body.kind {
                ExprKind::Block(..) => "map_or_else",
                _ => "map_or",
            };
            let capture_name = id.name.to_ident_string();
            let wrap_braces = should_wrap_in_braces(cx, expr);
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let parens_around_option = match &cond_expr.kind {
                // Put parens around the option expression if not doing so might
                // mess up the order of operations.
                ExprKind::Call(..)
                        | ExprKind::MethodCall(..)
                        | ExprKind::Loop(..)
                        | ExprKind::Match(..)
                        | ExprKind::Block(..)
                        | ExprKind::Field(..)
                        | ExprKind::Path(_)
                        | ExprKind::Unary(UnOp::UnDeref, _)
                        | ExprKind::AddrOf(..)
                    => false,
                _ => true,
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::UnDeref, expr)|ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, parens_around_option, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
                wrap_braces,
            })
        } else {
            None
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}{}.{}({}, {}){}",
                    if detection.wrap_braces { "{ " } else { "" },
                    detection.option,
                    detection.method_sugg,
                    detection.none_expr,
                    detection.some_expr,
                    if detection.wrap_braces { " }" } else { "" },
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}
<commit_msg>Refactoring pt. 2<commit_after>use crate::utils;
use crate::utils::sugg::Sugg;
use crate::utils::{match_type, paths, span_lint_and_sugg};
use if_chain::if_chain;

use rustc_errors::Applicability;
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use std::marker::PhantomData;

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of  `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a simple
    /// expression) or `Option::map_or_else` (if the else bit is a longer
    /// block).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an if let expression.
    ///
    /// **Known problems:**
    /// This lint uses whether the block is just an expression or if it has
    /// more statements to decide whether to use `Option::map_or` or
    /// `Option::map_or_else`. If you have a single expression which calls
    /// an expensive function, then it would be more efficient to use
    /// `Option::map_or_else`, but this lint would suggest `Option::map_or`.
    ///
    /// Also, this lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function;
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    style,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind {
        path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT)
    } else {
        false
    }
}

/// A struct containing information about occurences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
    wrap_braces: bool,
}

struct ReturnBreakContinueVisitor<'tcx> {
    seen_return_break_continue: bool,
    phantom_data: PhantomData<&'tcx bool>,
}
impl<'tcx> ReturnBreakContinueVisitor<'tcx> {
    fn new() -> ReturnBreakContinueVisitor<'tcx> {
        ReturnBreakContinueVisitor {
            seen_return_break_continue: false,
            phantom_data: PhantomData,
        }
    }
}
impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> {
    type Map = Map<'tcx>;
    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
        if self.seen_return_break_continue {
            // No need to look farther if we've already seen one of them
            return;
        }
        match &ex.kind {
            ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => {
                self.seen_return_break_continue = true;
            },
            // Something special could be done here to handle while or for loop
            // desugaring, as this will detect a break if there's a while loop
            // or a for loop inside the expression.
            _ => {
                rustc_hir::intravisit::walk_expr(self, ex);
            },
        }
    }
}

fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool {
    let mut recursive_visitor: ReturnBreakContinueVisitor<'tcx> = ReturnBreakContinueVisitor::new();
    recursive_visitor.visit_expr(expression);
    recursive_visitor.seen_return_break_continue
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(&expr)
        } else {
            Some(&arm.body)
        }
    } else {
        None
    }
}

/// If this is the else body of an if/else expression, then we need to wrap
/// it in curcly braces. Otherwise, we don't.
fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
        if let Some(Expr {
            kind:
                ExprKind::Match(
                    _,
                    arms,
                    MatchSource::IfDesugar {
                        contains_else_clause: true,
                    }
                    | MatchSource::IfLetDesugar {
                        contains_else_clause: true,
                    },
                ),
            ..
        }) = parent.expr
        {
            expr.hir_id == arms[1].body.hir_id
        } else {
            false
        }
    })
}

fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
    format!(
        "{}{}",
        Sugg::hir(cx, cond_expr, "..").maybe_par(),
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if utils::match_qpath(struct_qpath, &paths::OPTION_SOME);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue(arms[0].body);
        if !contains_return_break_continue(arms[1].body);
        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = match &none_body.kind {
                ExprKind::Block(..) => "map_or_else",
                _ => "map_or",
            };
            let capture_name = id.name.to_ident_string();
            let wrap_braces = should_wrap_in_braces(cx, expr);
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::UnDeref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
                wrap_braces,
            })
        } else {
            None
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}{}.{}({}, {}){}",
                    if detection.wrap_braces { "{ " } else { "" },
                    detection.option,
                    detection.method_sugg,
                    detection.none_expr,
                    detection.some_expr,
                    if detection.wrap_braces { " }" } else { "" },
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}
<|endoftext|>


<commit_before>use hash_map::HashMap;
use std::borrow::Borrow;
use std::hash::{BuildHasher, Hash};
use std::ptr;

use FailedAllocationError;

#[cfg(target_pointer_width = "32")]
const CANARY: usize = 0x42cafe99;
#[cfg(target_pointer_width = "64")]
const CANARY: usize = 0x42cafe9942cafe99;

#[cfg(target_pointer_width = "32")]
const POISON: usize = 0xdeadbeef;
#[cfg(target_pointer_width = "64")]
const POISON: usize = 0xdeadbeefdeadbeef;

#[derive(Clone, Debug)]
enum JournalEntry {
    Insert(usize),
    GOIW(usize),
    Remove(usize),
    DidClear(usize),
}

#[derive(Clone, Debug)]
pub struct DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    map: HashMap<K, (usize, V), S>,
    journal: Vec<JournalEntry>,
    readonly: bool,
}

impl<K: Hash + Eq, V, S: BuildHasher> DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    #[inline(always)]
    pub fn inner(&self) -> &HashMap<K, (usize, V), S> {
        &self.map
    }

    #[inline(never)]
    pub fn begin_mutation(&mut self) {
        self.map.verify();
        assert!(self.readonly);
        self.readonly = false;
        self.verify();
    }

    #[inline(never)]
    pub fn end_mutation(&mut self) {
        self.map.verify();
        assert!(!self.readonly);
        self.readonly = true;
        self.verify();
    }

    fn verify(&self) {
        let mut position = 0;
        let mut count = 0;
        let mut bad_canary = None;
        for (_,v) in self.map.iter() {
            let canary_ref = &v.0;
            position += 1;
            if *canary_ref == CANARY {
                continue;
            }
            count += 1;
            bad_canary = Some((*canary_ref, canary_ref, position));
        }
        if let Some(c) = bad_canary {
            self.report_corruption(c.0, c.1, c.2, count);
        }
    }

    #[inline(always)]
    pub fn with_hasher(hash_builder: S) -> Self {
        Self {
            map: HashMap::<K, (usize, V), S>::with_hasher(hash_builder),
            journal: Vec::new(),
            readonly: true,
        }
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.map.len()
    }

    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    #[inline(always)]
    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        self.map.contains_key(k)
    }

    #[inline(always)]
    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        self.map.get(k).map(|v| &v.1)
    }

    #[inline(always)]
    pub fn try_get_or_insert_with<F: FnOnce() -> V>(
        &mut self,
        key: K,
        default: F
    ) -> Result<&mut V, FailedAllocationError> {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::GOIW(self.map.make_hash(&key).inspect()));
        let entry = self.map.try_entry(key)?;
        Ok(&mut entry.or_insert_with(|| (CANARY, default())).1)
    }

    #[inline(always)]
    pub fn try_insert(&mut self, k: K, v: V) -> Result<Option<V>, FailedAllocationError> {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::Insert(self.map.make_hash(&k).inspect()));
        let old = self.map.try_insert(k, (CANARY, v))?;
        Ok(old.map(|x| x.1))
    }

    #[inline(always)]
    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::Remove(self.map.make_hash(k).inspect()));
        if let Some(v) = self.map.get_mut(k) {
            unsafe { ptr::write_volatile(&mut v.0, POISON); }
        }
        self.map.remove(k).map(|x| x.1)
    }

    #[inline(always)]
    pub fn clear(&mut self) where K: 'static, V: 'static  {
        // We handle scoped mutations for the caller here, since callsites that
        // invoke clear() don't benefit from the coalescing we do around insertion.
        self.begin_mutation();
        self.journal.clear();
        self.journal.push(JournalEntry::DidClear(self.map.raw_capacity()));
        self.map.clear();
        self.end_mutation();
    }

    #[inline(never)]
    fn report_corruption(
        &self,
        canary: usize,
        canary_addr: *const usize,
        position: usize,
        count: usize,
    ) {
        use ::std::ffi::CString;
        let key = b"HashMapJournal\0";
        let value = CString::new(format!("{:?}", self.journal)).unwrap();
        unsafe {
            Gecko_AnnotateCrashReport(
                key.as_ptr() as *const ::std::os::raw::c_char,
                value.as_ptr(),
            );
        }
        panic!(
            concat!("HashMap Corruption (sz={}, cap={}, pairsz={}, cnry={:#x}, count={}, ",
                    "last_pos={}, base_addr={:?}, cnry_addr={:?}, jrnl_len={})"),
            self.map.len(),
            self.map.raw_capacity(),
            ::std::mem::size_of::<(K, (usize, V))>(),
            canary,
            count,
            position,
            self.map.raw_buffer(),
            canary_addr,
            self.journal.len(),
        );
    }
}

impl<K, V, S> PartialEq for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          V: PartialEq,
          S: BuildHasher
{
    fn eq(&self, other: &Self) -> bool {
        self.map.eq(&other.map)
    }
}

impl<K, V, S> Eq for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          V: Eq,
          S: BuildHasher
{
}

impl<K, V, S> Default for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher + Default
{
    fn default() -> Self {
        Self {
            map: HashMap::default(),
            journal: Vec::new(),
            readonly: true,
        }
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> Drop for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    fn drop(&mut self) {
        self.map.verify();
        debug_assert!(self.readonly, "Dropped while mutating");
        self.verify();
    }
}

extern "C" {
    pub fn Gecko_AnnotateCrashReport(key_str: *const ::std::os::raw::c_char,
                                     value_str: *const ::std::os::raw::c_char);
}
<commit_msg>Revert "Correct the position and record count of broken canary"<commit_after>use hash_map::HashMap;
use std::borrow::Borrow;
use std::hash::{BuildHasher, Hash};
use std::ptr;

use FailedAllocationError;

#[cfg(target_pointer_width = "32")]
const CANARY: usize = 0x42cafe99;
#[cfg(target_pointer_width = "64")]
const CANARY: usize = 0x42cafe9942cafe99;

#[cfg(target_pointer_width = "32")]
const POISON: usize = 0xdeadbeef;
#[cfg(target_pointer_width = "64")]
const POISON: usize = 0xdeadbeefdeadbeef;

#[derive(Clone, Debug)]
enum JournalEntry {
    Insert(usize),
    GOIW(usize),
    Remove(usize),
    DidClear(usize),
}

#[derive(Clone, Debug)]
pub struct DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    map: HashMap<K, (usize, V), S>,
    journal: Vec<JournalEntry>,
    readonly: bool,
}

impl<K: Hash + Eq, V, S: BuildHasher> DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    #[inline(always)]
    pub fn inner(&self) -> &HashMap<K, (usize, V), S> {
        &self.map
    }

    #[inline(never)]
    pub fn begin_mutation(&mut self) {
        self.map.verify();
        assert!(self.readonly);
        self.readonly = false;
        self.verify();
    }

    #[inline(never)]
    pub fn end_mutation(&mut self) {
        self.map.verify();
        assert!(!self.readonly);
        self.readonly = true;
        self.verify();
    }

    fn verify(&self) {
        let mut position = 0;
        let mut bad_canary: Option<(usize, *const usize)> = None;
        for (_,v) in self.map.iter() {
            let canary_ref = &v.0;
            if *canary_ref == CANARY {
                position += 1;
                continue;
            }
            bad_canary = Some((*canary_ref, canary_ref));
        }
        if let Some(c) = bad_canary {
            self.report_corruption(c.0, c.1, position);
        }
    }

    #[inline(always)]
    pub fn with_hasher(hash_builder: S) -> Self {
        Self {
            map: HashMap::<K, (usize, V), S>::with_hasher(hash_builder),
            journal: Vec::new(),
            readonly: true,
        }
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.map.len()
    }

    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    #[inline(always)]
    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        self.map.contains_key(k)
    }

    #[inline(always)]
    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        self.map.get(k).map(|v| &v.1)
    }

    #[inline(always)]
    pub fn try_get_or_insert_with<F: FnOnce() -> V>(
        &mut self,
        key: K,
        default: F
    ) -> Result<&mut V, FailedAllocationError> {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::GOIW(self.map.make_hash(&key).inspect()));
        let entry = self.map.try_entry(key)?;
        Ok(&mut entry.or_insert_with(|| (CANARY, default())).1)
    }

    #[inline(always)]
    pub fn try_insert(&mut self, k: K, v: V) -> Result<Option<V>, FailedAllocationError> {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::Insert(self.map.make_hash(&k).inspect()));
        let old = self.map.try_insert(k, (CANARY, v))?;
        Ok(old.map(|x| x.1))
    }

    #[inline(always)]
    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
        where K: Borrow<Q>,
              Q: Hash + Eq
    {
        assert!(!self.readonly);
        self.journal.push(JournalEntry::Remove(self.map.make_hash(k).inspect()));
        if let Some(v) = self.map.get_mut(k) {
            unsafe { ptr::write_volatile(&mut v.0, POISON); }
        }
        self.map.remove(k).map(|x| x.1)
    }

    #[inline(always)]
    pub fn clear(&mut self) where K: 'static, V: 'static  {
        // We handle scoped mutations for the caller here, since callsites that
        // invoke clear() don't benefit from the coalescing we do around insertion.
        self.begin_mutation();
        self.journal.clear();
        self.journal.push(JournalEntry::DidClear(self.map.raw_capacity()));
        self.map.clear();
        self.end_mutation();
    }

    #[inline(never)]
    fn report_corruption(
        &self,
        canary: usize,
        canary_addr: *const usize,
        position: usize
    ) {
        use ::std::ffi::CString;
        let key = b"HashMapJournal\0";
        let value = CString::new(format!("{:?}", self.journal)).unwrap();
        unsafe {
            Gecko_AnnotateCrashReport(
                key.as_ptr() as *const ::std::os::raw::c_char,
                value.as_ptr(),
            );
        }
        panic!(
            "HashMap Corruption (sz={}, cap={}, pairsz={}, cnry={:#x}, pos={}, base_addr={:?}, cnry_addr={:?}, jrnl_len={})",
            self.map.len(),
            self.map.raw_capacity(),
            ::std::mem::size_of::<(K, (usize, V))>(),
            canary,
            position,
            self.map.raw_buffer(),
            canary_addr,
            self.journal.len(),
        );
    }
}

impl<K, V, S> PartialEq for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          V: PartialEq,
          S: BuildHasher
{
    fn eq(&self, other: &Self) -> bool {
        self.map.eq(&other.map)
    }
}

impl<K, V, S> Eq for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          V: Eq,
          S: BuildHasher
{
}

impl<K, V, S> Default for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher + Default
{
    fn default() -> Self {
        Self {
            map: HashMap::default(),
            journal: Vec::new(),
            readonly: true,
        }
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> Drop for DiagnosticHashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher
{
    fn drop(&mut self) {
        self.map.verify();
        debug_assert!(self.readonly, "Dropped while mutating");
        self.verify();
    }
}

extern "C" {
    pub fn Gecko_AnnotateCrashReport(key_str: *const ::std::os::raw::c_char,
                                     value_str: *const ::std::os::raw::c_char);
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item=&PathBuf> {
        self.vec.iter()
    }

    pub fn unique(&self) -> Self {
        let vec = self.vec.iter().map(|x| x.to_owned())
            .collect::<IndexSet<_>>()
            .into_iter().filter(|x| x.len() > 0)
            .collect::<VecDeque<_>>();
        Self {
            vec
        }
    }

    pub fn no_version_managers(&self) -> Self {
        let vec = self.vec.clone().into_iter().filter(|x| {
            !x.ends_with(".pyenv/shims") && !x.ends_with(".rbenv/shims")
        }).collect();
        Self {
            vec
        }
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        for s in env::split_paths(input.as_ref()) {
            vec.push_back(s);
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let mut ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }
}
<commit_msg>nmk.rs: use FromIterator<commit_after>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::iter::FromIterator;
use std::path::PathBuf;

use indexmap::IndexSet;

pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item=&PathBuf> {
        self.vec.iter()
    }

    pub fn unique(&self) -> Self {
        self.vec.clone().into_iter()
            .collect::<IndexSet<_>>()
            .into_iter()
            .collect()
    }

    pub fn no_version_managers(&self) -> Self {
        let vec = self.vec.clone().into_iter().filter(|x| {
            !x.ends_with(".pyenv/shims") && !x.ends_with(".rbenv/shims")
        }).collect();
        Self {
            vec
        }
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let mut vec = VecDeque::new();
        let unparsed = input.as_ref();
        if !unparsed.is_empty() {
            for p in env::split_paths(unparsed) {
                vec.push_back(p);
            }
        }
        Self { vec }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl FromIterator<PathBuf> for PathVec {
    fn from_iter<T: IntoIterator<Item=PathBuf>>(iter: T) -> Self {
        Self {
            vec: iter.into_iter().collect()
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::from(""));
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::from(""));
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }
}
<|endoftext|>


<commit_before><commit_msg>finally fixed :)<commit_after><|endoftext|>


<commit_before>fn main() {
    let mut s = String::from("hello there!");

    // append to string

    s.push_str(" Nice to meet you!");

    println!("{}", s);

    let s1 = s.clone();

    // cloning doesn't invalidate original variable
    println!("s: {}, s1: {}", s, s1);

    let s2 = s;

    // s is no longer valid here!
    // println!("{}", s); would fail
    // To preserve we can use Copy trait

    let s_to_own = String::from("Some stuff!");
    takes_ownership(s_to_own);

    // s_to_own is no longed valid here since it was moved to func
    // println!("{}", s_to_own); fails here

    let x = 10;
    makes_copy(x);

    // x was copied to function so it's still avaialable in this scope

}

fn takes_ownership(owned_string: String) {
    println!("{}", owned_string);  // After the function ends, owned_string goes out of scope
}

fn makes_copy(copied_int: i32) {
    println!("{}", copied_int); // copied_int goes out of scope - nothing special happens
}<commit_msg>Example of giving and taking and giving ownership back<commit_after>fn main() {
    let mut s = String::from("hello there!");

    // append to string

    s.push_str(" Nice to meet you!");

    println!("{}", s);

    let s1 = s.clone();

    // cloning doesn't invalidate original variable
    println!("s: {}, s1: {}", s, s1);

    let s2 = s;

    // s is no longer valid here!
    // println!("{}", s); would fail
    // To preserve we can use Copy trait

    let s_to_own = String::from("Some stuff!");
    takes_ownership(s_to_own);

    // s_to_own is no longed valid here since it was moved to func
    // println!("{}", s_to_own); fails here

    let x = 10;
    makes_copy(x);

    // x was copied to function so it's still avaialable in this scope

    let given_s = gives_ownership();

    // ownership was transfered from inside func

    let given_back_s = takes_and_gives_back(given_s);

    // given_s is no longer valid here but given_back_s is
    println!("{}", given_back_s);
}

fn takes_ownership(owned_string: String) {
    println!("{}", owned_string);  // After the function ends, owned_string goes out of scope
}

fn makes_copy(copied_int: i32) {
    println!("{}", copied_int); // copied_int goes out of scope - nothing special happens
}

fn gives_ownership() -> String {
    let s = String::from("String inside func!");

    s
}

fn takes_and_gives_back(taken: String) -> String {
    taken
}<|endoftext|>


<commit_before>//! Handler utilities for the various shell protocols
//!
//! Wayland, via its different protocol extensions, supports different kind of
//! shells. Here a shell represent the logic associated to displaying windows and
//! arranging them on the screen.
//!
//! The shell protocols thus define what kind of interactions a client can have with
//! the compositor to properly display its contents on the screen.
//!
//! Smithay currently provides two of them:
//!
//! - The [`xdg`](xdg/index.hmtl) module provides handlers for the `xdg_shell` protocol, which is
//!   the current standard for desktop apps
//! - The [`legacy`](legacy/index.html) module provides handlers for the `wl_shell` protocol, which
//!   is now deprecated. You only need it if you want to support apps predating `xdg_shell`.

use super::Serial;
use crate::wayland::compositor;
use thiserror::Error;
use wayland_server::protocol::wl_surface::WlSurface;

pub mod legacy;
pub mod xdg;

pub mod wlr_layer;

/// Represents the possible errors returned from
/// a surface ping
#[derive(Debug, Error)]
pub enum PingError {
    /// The operation failed because the underlying surface has been destroyed
    #[error("the ping failed cause the underlying surface has been destroyed")]
    DeadSurface,
    /// There is already a pending ping
    #[error("there is already a ping pending `{0:?}`")]
    PingAlreadyPending(Serial),
}

/// Returns true if the surface is toplevel equivalent.
///
/// This is method checks if the surface roles is one of `wl_shell_surface`, `xdg_toplevel`
/// or `zxdg_toplevel`.
pub fn is_toplevel_equivalent(surface: &WlSurface) -> bool {
    // (z)xdg_toplevel and wl_shell_surface are toplevel like, so verify if the roles match.
    let role = compositor::get_role(surface);

    matches!(
        role,
        Some(xdg::XDG_TOPLEVEL_ROLE) | Some(xdg::ZXDG_TOPLEVEL_ROLE) | Some(legacy::WL_SHELL_SURFACE_ROLE)
    )
}
<commit_msg>fix xdg doc link<commit_after>//! Handler utilities for the various shell protocols
//!
//! Wayland, via its different protocol extensions, supports different kind of
//! shells. Here a shell represent the logic associated to displaying windows and
//! arranging them on the screen.
//!
//! The shell protocols thus define what kind of interactions a client can have with
//! the compositor to properly display its contents on the screen.
//!
//! Smithay currently provides two of them:
//!
//! - The [`xdg`](xdg/index.html) module provides handlers for the `xdg_shell` protocol, which is
//!   the current standard for desktop apps
//! - The [`legacy`](legacy/index.html) module provides handlers for the `wl_shell` protocol, which
//!   is now deprecated. You only need it if you want to support apps predating `xdg_shell`.

use super::Serial;
use crate::wayland::compositor;
use thiserror::Error;
use wayland_server::protocol::wl_surface::WlSurface;

pub mod legacy;
pub mod xdg;

pub mod wlr_layer;

/// Represents the possible errors returned from
/// a surface ping
#[derive(Debug, Error)]
pub enum PingError {
    /// The operation failed because the underlying surface has been destroyed
    #[error("the ping failed cause the underlying surface has been destroyed")]
    DeadSurface,
    /// There is already a pending ping
    #[error("there is already a ping pending `{0:?}`")]
    PingAlreadyPending(Serial),
}

/// Returns true if the surface is toplevel equivalent.
///
/// This is method checks if the surface roles is one of `wl_shell_surface`, `xdg_toplevel`
/// or `zxdg_toplevel`.
pub fn is_toplevel_equivalent(surface: &WlSurface) -> bool {
    // (z)xdg_toplevel and wl_shell_surface are toplevel like, so verify if the roles match.
    let role = compositor::get_role(surface);

    matches!(
        role,
        Some(xdg::XDG_TOPLEVEL_ROLE) | Some(xdg::ZXDG_TOPLEVEL_ROLE) | Some(legacy::WL_SHELL_SURFACE_ROLE)
    )
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::sync::mpsc::{channel, Sender, Receiver};

use types::{AudioDevice, MessageReceiver, Sample, Time};

/// Bundles a `MessageReceiver` with threaded message passing.
///
/// # Sending messages
///
/// Once a device is wrapped with `Messaged`, one or more `Sender`s can be
/// returned from it. These represent the send end of standard Rust channels,
/// and can be sent between threads freely.
///
/// # As an `AudioDevice`
///
/// The wrapper implements `AudioDevice` if the contained device does as well.
/// The implementation first checks for any incoming messages, then applies them
/// to the interior device. Once the messages have been handled, it calls the
/// normal `tick` function of the device.
///
/// This allows one to wrap a device in `Messaged`, move the sender to another
/// thread, then drop the `Messaged` device into a normal container, such as
/// `DeviceChain` or `DeviceGraph`. It will automatically receive and handle its
/// own messages while processing.
///
/// # Example
///
/// ```no_run
/// use std::thread;
/// use oxcable::chain::{DeviceChain, Tick};
/// use oxcable::oscillator::{Oscillator, Sine, SetFreq};
/// use oxcable::io::audio::AudioEngine;
/// use oxcable::wrappers::Messaged;
///
/// fn main() {
///     // Initialize signal chain...
///     let tx;
///     let engine = AudioEngine::with_buffer_size(256).unwrap();
///     let mut chain = DeviceChain::from({
///         let msgd = Messaged::from(Oscillator::new(Sine).freq(440.0));
///         tx = msgd.get_sender();
///         msgd
///     }).into(
///         engine.default_output(1).unwrap()
///     );
///
///     // Send the messager to a new thread. It will wait for one second, then
///     // set the oscillator to a higher frequency.
///     thread::spawn(move || {
///         thread::sleep_ms(1000);
///         tx.send(SetFreq(880.0));
///     });
///
///     // Generate two seconds of audio, then exit...
///     chain.tick_n_times(88200);
/// }
/// ```
pub struct Messaged<D> where D: MessageReceiver {
    /// The device being wrapped.
    pub device: D,
    tx: Sender<D::Msg>,
    rx: Receiver<D::Msg>,
}

impl<D> Messaged<D> where D: MessageReceiver {
    /// Return the sending half of our communication channel.
    pub fn get_sender(&self) -> Sender<D::Msg> {
        self.tx.clone()
    }
}

impl<D> From<D> for Messaged<D> where D: MessageReceiver {
    fn from(device: D) -> Self {
        let (tx, rx) = channel();
        Messaged {
            device: device,
            tx: tx,
            rx: rx,
        }
    }
}

impl<D> AudioDevice for Messaged<D> where D: AudioDevice+MessageReceiver {
    fn num_inputs(&self) -> usize {
        self.device.num_inputs()
    }

    fn num_outputs(&self) -> usize {
        self.device.num_outputs()
    }

    fn tick(&mut self, t: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        loop {
            match self.rx.try_recv() {
                Ok(msg) => self.device.handle_message(msg),
                _ => break
            }
        }
        self.device.tick(t, inputs, outputs);
    }
}

impl<D> Deref for Messaged<D> where D: AudioDevice+MessageReceiver {
    type Target = D;
    fn deref(&self) -> &D {
        &self.device
    }
}

impl<D> DerefMut for Messaged<D> where D: AudioDevice+MessageReceiver {
    fn deref_mut(&mut self) -> &mut D {
        &mut self.device
    }
}
<commit_msg>Make device field of Messaged private.<commit_after>use std::ops::{Deref, DerefMut};
use std::sync::mpsc::{channel, Sender, Receiver};

use types::{AudioDevice, MessageReceiver, Sample, Time};

/// Bundles a `MessageReceiver` with threaded message passing.
///
/// # Sending messages
///
/// Once a device is wrapped with `Messaged`, one or more `Sender`s can be
/// returned from it. These represent the send end of standard Rust channels,
/// and can be sent between threads freely.
///
/// # As an `AudioDevice`
///
/// The wrapper implements `AudioDevice` if the contained device does as well.
/// The implementation first checks for any incoming messages, then applies them
/// to the interior device. Once the messages have been handled, it calls the
/// normal `tick` function of the device.
///
/// This allows one to wrap a device in `Messaged`, move the sender to another
/// thread, then drop the `Messaged` device into a normal container, such as
/// `DeviceChain` or `DeviceGraph`. It will automatically receive and handle its
/// own messages while processing.
///
/// # Example
///
/// ```no_run
/// use std::thread;
/// use oxcable::chain::{DeviceChain, Tick};
/// use oxcable::oscillator::{Oscillator, Sine, SetFreq};
/// use oxcable::io::audio::AudioEngine;
/// use oxcable::wrappers::Messaged;
///
/// fn main() {
///     // Initialize signal chain...
///     let tx;
///     let engine = AudioEngine::with_buffer_size(256).unwrap();
///     let mut chain = DeviceChain::from({
///         let msgd = Messaged::from(Oscillator::new(Sine).freq(440.0));
///         tx = msgd.get_sender();
///         msgd
///     }).into(
///         engine.default_output(1).unwrap()
///     );
///
///     // Send the messager to a new thread. It will wait for one second, then
///     // set the oscillator to a higher frequency.
///     thread::spawn(move || {
///         thread::sleep_ms(1000);
///         tx.send(SetFreq(880.0));
///     });
///
///     // Generate two seconds of audio, then exit...
///     chain.tick_n_times(88200);
/// }
/// ```
pub struct Messaged<D> where D: MessageReceiver {
    /// The device being wrapped.
    device: D,
    tx: Sender<D::Msg>,
    rx: Receiver<D::Msg>,
}

impl<D> Messaged<D> where D: MessageReceiver {
    /// Return the sending half of our communication channel.
    pub fn get_sender(&self) -> Sender<D::Msg> {
        self.tx.clone()
    }
}

impl<D> From<D> for Messaged<D> where D: MessageReceiver {
    fn from(device: D) -> Self {
        let (tx, rx) = channel();
        Messaged {
            device: device,
            tx: tx,
            rx: rx,
        }
    }
}

impl<D> AudioDevice for Messaged<D> where D: AudioDevice+MessageReceiver {
    fn num_inputs(&self) -> usize {
        self.device.num_inputs()
    }

    fn num_outputs(&self) -> usize {
        self.device.num_outputs()
    }

    fn tick(&mut self, t: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        loop {
            match self.rx.try_recv() {
                Ok(msg) => self.device.handle_message(msg),
                _ => break
            }
        }
        self.device.tick(t, inputs, outputs);
    }
}

impl<D> Deref for Messaged<D> where D: AudioDevice+MessageReceiver {
    type Target = D;
    fn deref(&self) -> &D {
        &self.device
    }
}

impl<D> DerefMut for Messaged<D> where D: AudioDevice+MessageReceiver {
    fn deref_mut(&mut self) -> &mut D {
        &mut self.device
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io;
use std::str;

use crate::wire_format::WireType;

pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug)]
pub enum WireError {
    UnexpectedEof,
    UnexpectedWireType(WireType),
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    IncompleteMap,
    IncorrectVarint,
    Utf8Error,
    InvalidEnumValue(i32),
    OverRecursionLimit,
    TruncatedMessage,
    Other,
}

/// Generic protobuf error
#[derive(Debug)]
pub enum ProtobufError {
    /// I/O error when reading or writing
    IoError(io::Error),
    /// Malformed input
    WireError(WireError),
    /// Protocol contains a string which is not valid UTF-8 string
    Utf8(str::Utf8Error),
    /// Not all required fields of message set.
    MessageNotInitialized(&'static str),
}

impl fmt::Display for ProtobufError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl Error for ProtobufError {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &ProtobufError::IoError(ref e) => e.description(),
            &ProtobufError::WireError(ref e) => match *e {
                WireError::Utf8Error => "invalid UTF-8 sequence",
                WireError::UnexpectedWireType(..) => "unexpected wire type",
                WireError::InvalidEnumValue(..) => "invalid enum value",
                WireError::IncorrectTag(..) => "incorrect tag",
                WireError::IncorrectVarint => "incorrect varint",
                WireError::IncompleteMap => "incomplete map",
                WireError::UnexpectedEof => "unexpected EOF",
                WireError::OverRecursionLimit => "over recursion limit",
                WireError::TruncatedMessage => "truncated message",
                WireError::Other => "other error",
            },
            &ProtobufError::Utf8(ref e) => &e.description(),
            &ProtobufError::MessageNotInitialized { .. } => "not all message fields set",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ProtobufError::IoError(ref e) => Some(e),
            &ProtobufError::Utf8(ref e) => Some(e),
            &ProtobufError::WireError(..) => None,
            &ProtobufError::MessageNotInitialized { .. } => None,
        }
    }
}

impl From<io::Error> for ProtobufError {
    fn from(err: io::Error) -> Self {
        ProtobufError::IoError(err)
    }
}

impl From<str::Utf8Error> for ProtobufError {
    fn from(err: str::Utf8Error) -> Self {
        ProtobufError::Utf8(err)
    }
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<commit_msg>Rustdoc for ProtobufResult<commit_after>use std::error::Error;
use std::fmt;
use std::io;
use std::str;

use crate::wire_format::WireType;

/// `Result` alias for `ProtobufError`
pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug)]
pub enum WireError {
    UnexpectedEof,
    UnexpectedWireType(WireType),
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    IncompleteMap,
    IncorrectVarint,
    Utf8Error,
    InvalidEnumValue(i32),
    OverRecursionLimit,
    TruncatedMessage,
    Other,
}

/// Generic protobuf error
#[derive(Debug)]
pub enum ProtobufError {
    /// I/O error when reading or writing
    IoError(io::Error),
    /// Malformed input
    WireError(WireError),
    /// Protocol contains a string which is not valid UTF-8 string
    Utf8(str::Utf8Error),
    /// Not all required fields of message set.
    MessageNotInitialized(&'static str),
}

impl fmt::Display for ProtobufError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl Error for ProtobufError {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &ProtobufError::IoError(ref e) => e.description(),
            &ProtobufError::WireError(ref e) => match *e {
                WireError::Utf8Error => "invalid UTF-8 sequence",
                WireError::UnexpectedWireType(..) => "unexpected wire type",
                WireError::InvalidEnumValue(..) => "invalid enum value",
                WireError::IncorrectTag(..) => "incorrect tag",
                WireError::IncorrectVarint => "incorrect varint",
                WireError::IncompleteMap => "incomplete map",
                WireError::UnexpectedEof => "unexpected EOF",
                WireError::OverRecursionLimit => "over recursion limit",
                WireError::TruncatedMessage => "truncated message",
                WireError::Other => "other error",
            },
            &ProtobufError::Utf8(ref e) => &e.description(),
            &ProtobufError::MessageNotInitialized { .. } => "not all message fields set",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ProtobufError::IoError(ref e) => Some(e),
            &ProtobufError::Utf8(ref e) => Some(e),
            &ProtobufError::WireError(..) => None,
            &ProtobufError::MessageNotInitialized { .. } => None,
        }
    }
}

impl From<io::Error> for ProtobufError {
    fn from(err: io::Error) -> Self {
        ProtobufError::IoError(err)
    }
}

impl From<str::Utf8Error> for ProtobufError {
    fn from(err: str::Utf8Error) -> Self {
        ProtobufError::Utf8(err)
    }
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<|endoftext|>


<commit_before>#[test]
fn exitstatus_display_tests() {
    // In practice this is the same on every Unix.
    // If some weird platform turns out to be different, and this test fails, use #[cfg].
    use crate::os::unix::process::ExitStatusExt;
    use crate::process::ExitStatus;

    let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));

    t(0x0000f, "signal: 15");
    t(0x0008b, "signal: 11 (core dumped)");
    t(0x00000, "exit status: 0");
    t(0x0ff00, "exit status: 255");

    // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED.  Probably *BSD is similar.
    //   https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956
    // The purpose of this test is to test our string formatting, not our understanding of the wait
    // status magic numbers.  So restrict these to Linux.
    if cfg!(target_os = "linux") {
        t(0x0137f, "stopped (not terminated) by signal: 19");
        t(0x0ffff, "continued (WIFCONTINUED)");
    }

    // Testing "unrecognised wait status" is hard because the wait.h macros typically
    // assume that the value came from wait and isn't mad.  With the glibc I have here
    // this works:
    if cfg!(all(target_os = "linux", target_env = "gnu")) {
        t(0x000ff, "unrecognised wait status: 255 0xff");
    }
}
<commit_msg>panic tests: Command: Test that we do not unwind past fork<commit_after>use crate::os::unix::process::{CommandExt, ExitStatusExt};
use crate::panic::catch_unwind;
use crate::process::Command;

#[test]
fn exitstatus_display_tests() {
    // In practice this is the same on every Unix.
    // If some weird platform turns out to be different, and this test fails, use #[cfg].
    use crate::os::unix::process::ExitStatusExt;
    use crate::process::ExitStatus;

    let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));

    t(0x0000f, "signal: 15");
    t(0x0008b, "signal: 11 (core dumped)");
    t(0x00000, "exit status: 0");
    t(0x0ff00, "exit status: 255");

    // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED.  Probably *BSD is similar.
    //   https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956
    // The purpose of this test is to test our string formatting, not our understanding of the wait
    // status magic numbers.  So restrict these to Linux.
    if cfg!(target_os = "linux") {
        t(0x0137f, "stopped (not terminated) by signal: 19");
        t(0x0ffff, "continued (WIFCONTINUED)");
    }

    // Testing "unrecognised wait status" is hard because the wait.h macros typically
    // assume that the value came from wait and isn't mad.  With the glibc I have here
    // this works:
    if cfg!(all(target_os = "linux", target_env = "gnu")) {
        t(0x000ff, "unrecognised wait status: 255 0xff");
    }
}

#[test]
fn test_command_fork_no_unwind() {
    let got = catch_unwind(|| {
        let mut c = Command::new("echo");
        c.arg("hi");
        unsafe {
            c.pre_exec(|| panic!("{}", "crash now!"));
        }
        let st = c.status().expect("failed to get command status");
        dbg!(st);
        st
    });
    dbg!(&got);
    let status = got.expect("panic unexpectedly propagated");
    dbg!(status);
    let signal = status.signal().expect("expected child process to die of signal");
    assert!(signal == libc::SIGABRT || signal == libc::SIGILL);
}
<|endoftext|>


<commit_before>use std::io;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::mem;
use std::collections::HashSet;

use clap::{App, Arg, ArgMatches};
use hyper::method::Method;
use mime;
use multipart::client::Multipart;
use serde_json;
use walkdir::{WalkDir, Iter as WalkDirIter};
use zip;

use CliResult;
use utils::{TempFile, get_org_and_project, get_sha1_checksum};
use macho::is_macho_file;
use commands::Config;

const BATCH_SIZE : usize = 15;

#[derive(Debug, Deserialize)]
struct DSymFile {
    uuid: String,
    #[serde(rename="objectName")]
    object_name: String,
    #[serde(rename="cpuName")]
    cpu_name: String,
}

#[derive(Deserialize)]
struct MissingChecksumsResponse {
    missing: HashSet<String>,
}

struct LocalFile {
    path: PathBuf,
    arc_name: String,
    checksum: String,
}

struct BatchIter {
    path: PathBuf,
    wd_iter: WalkDirIter,
    batch: Vec<LocalFile>,
}

impl BatchIter {
    pub fn new<P: AsRef<Path>>(path: P) -> BatchIter {
        BatchIter {
            path: path.as_ref().to_path_buf(),
            wd_iter: WalkDir::new(&path).into_iter(),
            batch: vec![],
        }
    }
}

impl Iterator for BatchIter {
    type Item = CliResult<Vec<LocalFile>>;

    fn next(&mut self) -> Option<CliResult<Vec<LocalFile>>> {
        loop {
            if let Some(dent_res) = self.wd_iter.next() {
                let dent = iter_try!(dent_res);
                let md = iter_try!(dent.metadata());
                if md.is_file() && is_macho_file(dent.path()) {
                    let name = Path::new("DebugSymbols")
                        .join(dent.path().strip_prefix(&self.path).unwrap());
                    println!("  {}", name.display());
                    self.batch.push(LocalFile {
                        path: dent.path().to_path_buf(),
                        arc_name: name.to_string_lossy().into_owned(),
                        checksum: iter_try!(get_sha1_checksum(dent.path())),
                    });
                    if self.batch.len() > BATCH_SIZE {
                        break;
                    }
                }
            } else {
                break;
            }
        }
        if self.batch.len() == 0 {
            None
        } else {
            Some(Ok(mem::replace(&mut self.batch, vec![])))
        }
    }
}

fn find_missing_files(config: &Config, files: Vec<LocalFile>, api_path: &str)
    -> CliResult<Vec<LocalFile>>
{
    let mut url = format!("{}unknown/?", api_path);
    for (idx, ref file) in files.iter().enumerate() {
        if idx > 0 {
            url.push('&');
        }
        url.push_str("checksums=");
        url.push_str(&file.checksum);
    }
    let mut resp = config.api_request(Method::Get, &url)?;

    // This happens if the sentry installation we're connecting to does not
    // have that endpoint.  In that case just continue.  Any other HTTP
    // failure is ignored here too which is okay since we will try to upload
    // next step anyways.
    if !resp.status.is_success() {
        return Ok(files);
    }

    let state : MissingChecksumsResponse = serde_json::from_reader(&mut resp)?;
    let mut rv = vec![];
    for file in files.into_iter() {
        if state.missing.contains(&file.checksum) {
            rv.push(file)
        }
    }
    Ok(rv)
}

fn zip_up(files: &[LocalFile]) -> CliResult<TempFile> {
    println!("  Uploading a batch of missing files ...");
    let tf = TempFile::new()?;
    let mut zip = zip::ZipWriter::new(tf.open());
    for ref file in files {
        println!("    {}", file.arc_name);
        zip.start_file(file.arc_name.clone(),
            zip::CompressionMethod::Deflated)?;
        io::copy(&mut File::open(file.path.clone())?, &mut zip)?;
    }
    Ok(tf)
}

fn upload_dsyms(files: &[LocalFile], config: &Config,
                api_path: &str) -> CliResult<Vec<DSymFile>> {
    let tf = zip_up(files)?;
    let req = config.prepare_api_request(Method::Post, api_path)?;
    let mut mp = Multipart::from_request_sized(req)?;
    try!(mp.write_stream("file", &mut tf.open(), Some("archive.zip"),
        "application/zip".parse::<mime::Mime>().ok()));
    let mut resp = mp.send()?;
    if !resp.status.is_success() {
        fail!(resp);
    }
    Ok(serde_json::from_reader(&mut resp)?)
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("uploads debug symbols to a project")
        .arg(Arg::with_name("org")
             .value_name("ORG")
             .long("org")
             .short("o")
             .help("The organization slug"))
        .arg(Arg::with_name("project")
             .value_name("PROJECT")
             .long("project")
             .short("p")
             .help("The project slug"))
        .arg(Arg::with_name("global")
             .long("global")
             .short("g")
             .help("Uploads the dsyms globally. This can only be done \
                    with super admin access for the Sentry installation"))
        .arg(Arg::with_name("path")
             .value_name("PATH")
             .help("The path to the debug symbols")
             .required(true)
             .index(1))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> CliResult<()> {
    let path = matches.value_of("path").unwrap();
    let api_path = if matches.is_present("global") {
        "/system/global-dsyms/".to_owned()
    } else {
        let (org, project) = get_org_and_project(matches)?;
        format!("/projects/{}/{}/files/dsyms/", org, project)
    };

    println!("Uploading symbols from {}...", path);

    for batch_res in BatchIter::new(path) {
        let missing = find_missing_files(config, batch_res?, &api_path)?;
        if missing.len() == 0 {
            continue;
        }
        println!("Detected missing files");
        let rv = upload_dsyms(&missing, config, &api_path)?;
        if rv.len() > 0 {
            println!("  Accepted debug symbols:");
            for df in rv {
                println!("    {} ({}; {})", df.uuid, df.object_name, df.cpu_name);
            }
        }
    }

    Ok(())
}
<commit_msg>Added support for automatically discovering symbols from the environment variable DWARF_DSYM_FOLDER_PATH<commit_after>use std::io;
use std::fs;
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::mem;
use std::ffi::OsStr;
use std::collections::HashSet;

use clap::{App, Arg, ArgMatches};
use hyper::method::Method;
use mime;
use multipart::client::Multipart;
use serde_json;
use walkdir::{WalkDir, Iter as WalkDirIter};
use zip;

use CliResult;
use utils::{TempFile, get_org_and_project, get_sha1_checksum};
use macho::is_macho_file;
use commands::Config;

const BATCH_SIZE : usize = 15;

#[derive(Debug, Deserialize)]
struct DSymFile {
    uuid: String,
    #[serde(rename="objectName")]
    object_name: String,
    #[serde(rename="cpuName")]
    cpu_name: String,
}

#[derive(Deserialize)]
struct MissingChecksumsResponse {
    missing: HashSet<String>,
}

struct LocalFile {
    path: PathBuf,
    arc_name: String,
    checksum: String,
}

struct BatchIter {
    path: PathBuf,
    wd_iter: WalkDirIter,
    batch: Vec<LocalFile>,
}

impl BatchIter {
    pub fn new<P: AsRef<Path>>(path: P) -> BatchIter {
        BatchIter {
            path: path.as_ref().to_path_buf(),
            wd_iter: WalkDir::new(&path).into_iter(),
            batch: vec![],
        }
    }
}

impl Iterator for BatchIter {
    type Item = CliResult<Vec<LocalFile>>;

    fn next(&mut self) -> Option<CliResult<Vec<LocalFile>>> {
        loop {
            if let Some(dent_res) = self.wd_iter.next() {
                let dent = iter_try!(dent_res);
                let md = iter_try!(dent.metadata());
                if md.is_file() && is_macho_file(dent.path()) {
                    let name = Path::new("DebugSymbols")
                        .join(dent.path().strip_prefix(&self.path).unwrap());
                    println!("  {}", name.display());
                    self.batch.push(LocalFile {
                        path: dent.path().to_path_buf(),
                        arc_name: name.to_string_lossy().into_owned(),
                        checksum: iter_try!(get_sha1_checksum(dent.path())),
                    });
                    if self.batch.len() > BATCH_SIZE {
                        break;
                    }
                }
            } else {
                break;
            }
        }
        if self.batch.len() == 0 {
            None
        } else {
            Some(Ok(mem::replace(&mut self.batch, vec![])))
        }
    }
}

fn find_missing_files(config: &Config, files: Vec<LocalFile>, api_path: &str)
    -> CliResult<Vec<LocalFile>>
{
    let mut url = format!("{}unknown/?", api_path);
    for (idx, ref file) in files.iter().enumerate() {
        if idx > 0 {
            url.push('&');
        }
        url.push_str("checksums=");
        url.push_str(&file.checksum);
    }
    let mut resp = config.api_request(Method::Get, &url)?;

    // This happens if the sentry installation we're connecting to does not
    // have that endpoint.  In that case just continue.  Any other HTTP
    // failure is ignored here too which is okay since we will try to upload
    // next step anyways.
    if !resp.status.is_success() {
        return Ok(files);
    }

    let state : MissingChecksumsResponse = serde_json::from_reader(&mut resp)?;
    let mut rv = vec![];
    for file in files.into_iter() {
        if state.missing.contains(&file.checksum) {
            rv.push(file)
        }
    }
    Ok(rv)
}

fn zip_up(files: &[LocalFile]) -> CliResult<TempFile> {
    println!("  Uploading a batch of missing files ...");
    let tf = TempFile::new()?;
    let mut zip = zip::ZipWriter::new(tf.open());
    for ref file in files {
        println!("    {}", file.arc_name);
        zip.start_file(file.arc_name.clone(),
            zip::CompressionMethod::Deflated)?;
        io::copy(&mut File::open(file.path.clone())?, &mut zip)?;
    }
    Ok(tf)
}

fn upload_dsyms(files: &[LocalFile], config: &Config,
                api_path: &str) -> CliResult<Vec<DSymFile>> {
    let tf = zip_up(files)?;
    let req = config.prepare_api_request(Method::Post, api_path)?;
    let mut mp = Multipart::from_request_sized(req)?;
    try!(mp.write_stream("file", &mut tf.open(), Some("archive.zip"),
        "application/zip".parse::<mime::Mime>().ok()));
    let mut resp = mp.send()?;
    if !resp.status.is_success() {
        fail!(resp);
    }
    Ok(serde_json::from_reader(&mut resp)?)
}

fn get_paths_from_env() -> CliResult<Vec<PathBuf>> {
    let mut rv = vec![];
    if let Some(base_path) = env::var_os("DWARF_DSYM_FOLDER_PATH") {
        for entry in fs::read_dir(base_path)? {
            let entry = entry?;
            if entry.path().extension() == Some(OsStr::new("dSYM")) &&
                fs::metadata(entry.path())?.is_dir() {
                rv.push(entry.path().to_path_buf());
            }
        }
    }
    Ok(rv)
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("uploads debug symbols to a project")
        .arg(Arg::with_name("org")
             .value_name("ORG")
             .long("org")
             .short("o")
             .help("The organization slug"))
        .arg(Arg::with_name("project")
             .value_name("PROJECT")
             .long("project")
             .short("p")
             .help("The project slug"))
        .arg(Arg::with_name("global")
             .long("global")
             .short("g")
             .help("Uploads the dsyms globally. This can only be done \
                    with super admin access for the Sentry installation"))
        .arg(Arg::with_name("paths")
             .value_name("PATH")
             .help("The path to the debug symbols")
             .multiple(true)
             .index(1))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> CliResult<()> {
    let paths = match matches.values_of("paths") {
        Some(paths) => paths.map(|x| PathBuf::from(x)).collect(),
        None => get_paths_from_env()?,
    };
    let api_path = if matches.is_present("global") {
        "/system/global-dsyms/".to_owned()
    } else {
        let (org, project) = get_org_and_project(matches)?;
        format!("/projects/{}/{}/files/dsyms/", org, project)
    };

    println!("Uploading symbols");
    if paths.len() == 0 {
        println!("Warning: no paths were provided.");
    }

    for path in paths {
        println!("Finding symbols in {}...", path.display());
        for batch_res in BatchIter::new(path) {
            let missing = find_missing_files(config, batch_res?, &api_path)?;
            if missing.len() == 0 {
                continue;
            }
            println!("Detected missing files");
            let rv = upload_dsyms(&missing, config, &api_path)?;
            if rv.len() > 0 {
                println!("  Accepted debug symbols:");
                for df in rv {
                    println!("    {} ({}; {})", df.uuid, df.object_name, df.cpu_name);
                }
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>// xfail-test reading from os::args()[1] - bogus!

use std::cast::transmute;
use std::from_str::FromStr;
use std::libc::{STDOUT_FILENO, c_int, fdopen, fputc};
use std::os;

static ITER: uint = 50;
static LIMIT: f64 = 2.0;

fn main() {
    unsafe {
        let w: i32 = FromStr::from_str(os::args()[1]).unwrap();
        let h = w;
        let mut byte_acc: i8 = 0;
        let mut bit_num: i32 = 0;

        println!("P4\n{} {}", w, h);

        let mode = "w";
        let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));

        for y in range(0i32, h) {
            let y = y as f64;
            for x in range(0i32, w) {
                let mut Zr = 0f64;
                let mut Zi = 0f64;
                let mut Tr = 0f64;
                let mut Ti = 0f64;
                let Cr = 2.0 * (x as f64) / (w as f64) - 1.5;
                let Ci = 2.0 * (y as f64) / (h as f64) - 1.0;

                for _ in range(0i32, ITER as i32) {
                    if Tr + Ti > LIMIT * LIMIT {
                        break;
                    }

                    Zi = 2.0*Zr*Zi + Ci;
                    Zr = Tr - Ti + Cr;
                    Tr = Zr * Zr;
                    Ti = Zi * Zi;
                }

                byte_acc <<= 1;
                if Tr + Ti <= LIMIT * LIMIT {
                    byte_acc |= 1;
                }

                bit_num += 1;

                if bit_num == 8 {
                    fputc(byte_acc as c_int, stdout);
                    byte_acc = 0;
                    bit_num = 0;
                } else if x == w - 1 {
                    byte_acc <<= 8 - w%8;
                    fputc(byte_acc as c_int, stdout);
                    byte_acc = 0;
                    bit_num = 0;
                }
            }
        }
    }
}
<commit_msg>resurect shootout-mandelbrot.rs<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::buffered::BufferedWriter;

struct DummyWriter;
impl Writer for DummyWriter {
    fn write(&mut self, _: &[u8]) {}
}

static ITER: int = 50;
static LIMIT: f64 = 2.0;

fn main() {
    let args = std::os::args();
    let (w, mut out) = if args.len() < 2 {
        println("Test mode: do not dump the image.");
        (1000, ~DummyWriter as ~Writer)
    } else {
        (from_str(args[1]).unwrap(),
         ~BufferedWriter::new(std::io::stdout()) as ~Writer)
    };
    let h = w;
    let mut byte_acc = 0i8;
    let mut bit_num = 0;

    writeln!(out, "P4\n{} {}", w, h);

    for y in range(0, h) {
        let y = y as f64;
        for x in range(0, w) {
            let mut z_r = 0f64;
            let mut z_i = 0f64;
            let mut t_r = 0f64;
            let mut t_i = 0f64;
            let c_r = 2.0 * (x as f64) / (w as f64) - 1.5;
            let c_i = 2.0 * (y as f64) / (h as f64) - 1.0;

            for _ in range(0, ITER) {
                if t_r + t_i > LIMIT * LIMIT {
                    break;
                }

                z_i = 2.0 * z_r * z_i + c_i;
                z_r = t_r - t_i + c_r;
                t_r = z_r * z_r;
                t_i = z_i * z_i;
            }

            byte_acc <<= 1;
            if t_r + t_i <= LIMIT * LIMIT {
                byte_acc |= 1;
            }

            bit_num += 1;

            if bit_num == 8 {
                out.write_i8(byte_acc);
                byte_acc = 0;
                bit_num = 0;
            } else if x == w - 1 {
                byte_acc <<= 8 - w % 8;
                out.write_i8(byte_acc);
                byte_acc = 0;
                bit_num = 0;
            }
        }
    }

    out.flush();
}
<|endoftext|>


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

// aux-build:lang-item-public.rs
// ignore-android
// ignore-windows #13361

#![feature(lang_items, start, no_std)]
#![no_std]

extern crate "lang-item-public" as lang_lib;

#[cfg(target_os = "linux")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "android")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "freebsd")]
#[link(name = "execinfo")]
extern {}

#[cfg(target_os = "freebsd")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "dragonfly")]
#[link(name = "c")]
extern {}

#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
#[link(name = "c")]
extern {}

#[cfg(target_os = "macos")]
#[link(name = "System")]
extern {}

#[start]
fn main(_: int, _: *const *const u8) -> int {
    1 % 1
}
<commit_msg>Rollup merge of #22624 - vadimcn:iss-13361, r=alexcrichton<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:lang-item-public.rs
// ignore-android

#![feature(lang_items, start, no_std)]
#![no_std]

extern crate "lang-item-public" as lang_lib;

#[cfg(target_os = "linux")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "android")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "freebsd")]
#[link(name = "execinfo")]
extern {}

#[cfg(target_os = "freebsd")]
#[link(name = "c")]
extern {}

#[cfg(target_os = "dragonfly")]
#[link(name = "c")]
extern {}

#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
#[link(name = "c")]
extern {}

#[cfg(target_os = "macos")]
#[link(name = "System")]
extern {}

#[start]
fn main(_: int, _: *const *const u8) -> int {
    1 % 1
}
<|endoftext|>


<commit_before><commit_msg>Remove unused variable warning<commit_after><|endoftext|>


<commit_before>pub fn main() {
    let x = [1];
    match x {
        [_, _, _, _, _, .._] => ::core::util::unreachable(),
        [.._, _, _, _, _] => ::core::util::unreachable(),
        [_, .._, _, _] => ::core::util::unreachable(),
        [_, _] => ::core::util::unreachable(),
        [a] => {
            fail_unless!(a == 1);
        }
        [] => ::core::util::unreachable()
    }
}
<commit_msg>Add one more test for vector destructuring<commit_after>fn a() {
    let x = [1];
    match x {
        [_, _, _, _, _, .._] => ::core::util::unreachable(),
        [.._, _, _, _, _] => ::core::util::unreachable(),
        [_, .._, _, _] => ::core::util::unreachable(),
        [_, _] => ::core::util::unreachable(),
        [a] => {
            fail_unless!(a == 1);
        }
        [] => ::core::util::unreachable()
    }
}

fn b() {
    let x = [1, 2, 3];
    match x {
        [a, b, ..c] => {
            fail_unless!(a == 1);
            fail_unless!(b == 2);
            fail_unless!(c == &[3]);
        }
        _ => fail!()
    }
    match x {
        [..a, b, c] => {
            fail_unless!(a == &[1]);
            fail_unless!(b == 2);
            fail_unless!(c == 3);
        }
        _ => fail!()
    }
    match x {
        [a, ..b, c] => {
            fail_unless!(a == 1);
            fail_unless!(b == &[2]);
            fail_unless!(c == 3);
        }
        _ => fail!()
    }
    match x {
        [a, b, c] => {
            fail_unless!(a == 1);
            fail_unless!(b == 2);
            fail_unless!(c == 3);
        }
        _ => fail!()
    }
}

pub fn main() {
    a();
    b();
}
<|endoftext|>