<commit_before>// Copyright 2016 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 build::scope::BreakableScope;
use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use hair::*;
use rustc::mir::*;

impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
    /// Builds a block of MIR statements to evaluate the HAIR `expr`.
    /// If the original expression was an AST statement,
    /// (e.g. `some().code(&here());`) then `opt_stmt_span` is the
    /// span of that statement (including its semicolon, if any).
    /// Diagnostics use this span (which may be larger than that of
    /// `expr`) to identify when statement temporaries are dropped.
    pub fn stmt_expr(&mut self,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>,
                     opt_stmt_span: Option<StatementSpan>)
                     -> BlockAnd<()>
    {
        let this = self;
        let expr_span = expr.span;
        let source_info = this.source_info(expr.span);
        // Handle a number of expressions that don't need a destination at all. This
        // avoids needing a mountain of temporary `()` variables.
        let expr2 = expr.clone();
        match expr.kind {
            ExprKind::Scope {
                region_scope,
                lint_level,
                value,
            } => {
                let value = this.hir.mirror(value);
                this.in_scope((region_scope, source_info), lint_level, block, |this| {
                    this.stmt_expr(block, value, opt_stmt_span)
                })
            }
            ExprKind::Assign { lhs, rhs } => {
                let lhs = this.hir.mirror(lhs);
                let rhs = this.hir.mirror(rhs);
                let lhs_span = lhs.span;

                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].

                debug!("stmt_expr Assign block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);

                // Generate better code for things that don't need to be
                // dropped.
                if this.hir.needs_drop(lhs.ty) {
                    let rhs = unpack!(block = this.as_local_operand(block, rhs));
                    let lhs = unpack!(block = this.as_place(block, lhs));
                    unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
                } else {
                    let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                    let lhs = unpack!(block = this.as_place(block, lhs));
                    this.cfg.push_assign(block, source_info, &lhs, rhs);
                }

                this.block_context.pop();
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                let lhs = this.hir.mirror(lhs);
                let lhs_ty = lhs.ty;

                debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);

                // As above, RTL.
                let rhs = unpack!(block = this.as_local_operand(block, rhs));
                let lhs = unpack!(block = this.as_place(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                let result = unpack!(
                    block = this.build_binary_op(
                        block,
                        op,
                        expr_span,
                        lhs_ty,
                        Operand::Copy(lhs.clone()),
                        rhs
                    )
                );
                this.cfg.push_assign(block, source_info, &lhs, result);

                this.block_context.pop();
                block.unit()
            }
            ExprKind::Continue { label } => {
                let BreakableScope {
                    continue_block,
                    region_scope,
                    ..
                } = *this.find_breakable_scope(expr_span, label);
                let continue_block = continue_block
                    .expect("Attempted to continue in non-continuable breakable block");
                this.exit_scope(
                    expr_span,
                    (region_scope, source_info),
                    block,
                    continue_block,
                );
                this.cfg.start_new_block().unit()
            }
            ExprKind::Break { label, value } => {
                let (break_block, region_scope, destination) = {
                    let BreakableScope {
                        break_block,
                        region_scope,
                        ref break_destination,
                        ..
                    } = *this.find_breakable_scope(expr_span, label);
                    (break_block, region_scope, break_destination.clone())
                };
                if let Some(value) = value {
                    debug!("stmt_expr Break val block_context.push(SubExpr) : {:?}", expr2);
                    this.block_context.push(BlockFrame::SubExpr);
                    unpack!(block = this.into(&destination, block, value));
                    this.block_context.pop();
                } else {
                    this.cfg.push_assign_unit(block, source_info, &destination)
                }
                this.exit_scope(expr_span, (region_scope, source_info), block, break_block);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => {
                        debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
                        this.block_context.push(BlockFrame::SubExpr);
                        let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
                        this.block_context.pop();
                        result
                    }
                    None => {
                        this.cfg
                            .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
                        block
                    }
                };
                let region_scope = this.region_scope_of_return_scope();
                let return_block = this.return_block();
                this.exit_scope(expr_span, (region_scope, source_info), block, return_block);
                this.cfg.start_new_block().unit()
            }
            ExprKind::InlineAsm {
                asm,
                outputs,
                inputs,
            } => {
                debug!("stmt_expr InlineAsm block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);
                let outputs = outputs
                    .into_iter()
                    .map(|output| unpack!(block = this.as_place(block, output)))
                    .collect::<Vec<_>>()
                    .into_boxed_slice();
                let inputs = inputs
                    .into_iter()
                    .map(|input| {
                        (
                            input.span(),
                            unpack!(block = this.as_local_operand(block, input)),
                        )
                    }).collect::<Vec<_>>()
                    .into_boxed_slice();
                this.cfg.push(
                    block,
                    Statement {
                        source_info,
                        kind: StatementKind::InlineAsm {
                            asm: box asm.clone(),
                            outputs,
                            inputs,
                        },
                    },
                );
                this.block_context.pop();
                block.unit()
            }
            _ => {
                let expr_ty = expr.ty;
                let temp = this.temp(expr.ty.clone(), expr_span);
                unpack!(block = this.into(&temp, block, expr));

                // Attribute drops of the statement's temps to the
                // semicolon at the statement's end.
                let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
                    None => expr_span,
                    Some(StatementSpan(span)) => span,
                });

                unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
                block.unit()
            }
        }
    }
}
<commit_msg>Narrow span of temp holding the value of a Block expression to the block's tail (if present).<commit_after>// Copyright 2016 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 build::scope::BreakableScope;
use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use hair::*;
use rustc::mir::*;

impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
    /// Builds a block of MIR statements to evaluate the HAIR `expr`.
    /// If the original expression was an AST statement,
    /// (e.g. `some().code(&here());`) then `opt_stmt_span` is the
    /// span of that statement (including its semicolon, if any).
    /// Diagnostics use this span (which may be larger than that of
    /// `expr`) to identify when statement temporaries are dropped.
    pub fn stmt_expr(&mut self,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>,
                     opt_stmt_span: Option<StatementSpan>)
                     -> BlockAnd<()>
    {
        let this = self;
        let expr_span = expr.span;
        let source_info = this.source_info(expr.span);
        // Handle a number of expressions that don't need a destination at all. This
        // avoids needing a mountain of temporary `()` variables.
        let expr2 = expr.clone();
        match expr.kind {
            ExprKind::Scope {
                region_scope,
                lint_level,
                value,
            } => {
                let value = this.hir.mirror(value);
                this.in_scope((region_scope, source_info), lint_level, block, |this| {
                    this.stmt_expr(block, value, opt_stmt_span)
                })
            }
            ExprKind::Assign { lhs, rhs } => {
                let lhs = this.hir.mirror(lhs);
                let rhs = this.hir.mirror(rhs);
                let lhs_span = lhs.span;

                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].

                debug!("stmt_expr Assign block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);

                // Generate better code for things that don't need to be
                // dropped.
                if this.hir.needs_drop(lhs.ty) {
                    let rhs = unpack!(block = this.as_local_operand(block, rhs));
                    let lhs = unpack!(block = this.as_place(block, lhs));
                    unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
                } else {
                    let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                    let lhs = unpack!(block = this.as_place(block, lhs));
                    this.cfg.push_assign(block, source_info, &lhs, rhs);
                }

                this.block_context.pop();
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                let lhs = this.hir.mirror(lhs);
                let lhs_ty = lhs.ty;

                debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);

                // As above, RTL.
                let rhs = unpack!(block = this.as_local_operand(block, rhs));
                let lhs = unpack!(block = this.as_place(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                let result = unpack!(
                    block = this.build_binary_op(
                        block,
                        op,
                        expr_span,
                        lhs_ty,
                        Operand::Copy(lhs.clone()),
                        rhs
                    )
                );
                this.cfg.push_assign(block, source_info, &lhs, result);

                this.block_context.pop();
                block.unit()
            }
            ExprKind::Continue { label } => {
                let BreakableScope {
                    continue_block,
                    region_scope,
                    ..
                } = *this.find_breakable_scope(expr_span, label);
                let continue_block = continue_block
                    .expect("Attempted to continue in non-continuable breakable block");
                this.exit_scope(
                    expr_span,
                    (region_scope, source_info),
                    block,
                    continue_block,
                );
                this.cfg.start_new_block().unit()
            }
            ExprKind::Break { label, value } => {
                let (break_block, region_scope, destination) = {
                    let BreakableScope {
                        break_block,
                        region_scope,
                        ref break_destination,
                        ..
                    } = *this.find_breakable_scope(expr_span, label);
                    (break_block, region_scope, break_destination.clone())
                };
                if let Some(value) = value {
                    debug!("stmt_expr Break val block_context.push(SubExpr) : {:?}", expr2);
                    this.block_context.push(BlockFrame::SubExpr);
                    unpack!(block = this.into(&destination, block, value));
                    this.block_context.pop();
                } else {
                    this.cfg.push_assign_unit(block, source_info, &destination)
                }
                this.exit_scope(expr_span, (region_scope, source_info), block, break_block);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => {
                        debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
                        this.block_context.push(BlockFrame::SubExpr);
                        let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
                        this.block_context.pop();
                        result
                    }
                    None => {
                        this.cfg
                            .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
                        block
                    }
                };
                let region_scope = this.region_scope_of_return_scope();
                let return_block = this.return_block();
                this.exit_scope(expr_span, (region_scope, source_info), block, return_block);
                this.cfg.start_new_block().unit()
            }
            ExprKind::InlineAsm {
                asm,
                outputs,
                inputs,
            } => {
                debug!("stmt_expr InlineAsm block_context.push(SubExpr) : {:?}", expr2);
                this.block_context.push(BlockFrame::SubExpr);
                let outputs = outputs
                    .into_iter()
                    .map(|output| unpack!(block = this.as_place(block, output)))
                    .collect::<Vec<_>>()
                    .into_boxed_slice();
                let inputs = inputs
                    .into_iter()
                    .map(|input| {
                        (
                            input.span(),
                            unpack!(block = this.as_local_operand(block, input)),
                        )
                    }).collect::<Vec<_>>()
                    .into_boxed_slice();
                this.cfg.push(
                    block,
                    Statement {
                        source_info,
                        kind: StatementKind::InlineAsm {
                            asm: box asm.clone(),
                            outputs,
                            inputs,
                        },
                    },
                );
                this.block_context.pop();
                block.unit()
            }
            _ => {
                let expr_ty = expr.ty;

                // Issue #54382: When creating temp for the value of
                // expression like:
                //
                // `{ side_effects(); { let l = stuff(); the_value } }`
                //
                // it is usually better to focus on `the_value` rather
                // than the entirety of block(s) surrounding it.
                let mut temp_span = expr_span;
                if let ExprKind::Block { body } = expr.kind {
                    if let Some(tail_expr) = &body.expr {
                        let mut expr = tail_expr;
                        while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
                            if let Some(subtail_expr) = &subblock.expr {
                                expr = subtail_expr
                            } else {
                                break;
                            }
                        }
                        temp_span = expr.span;
                    }
                }

                let temp = this.temp(expr.ty.clone(), temp_span);
                unpack!(block = this.into(&temp, block, expr));

                // Attribute drops of the statement's temps to the
                // semicolon at the statement's end.
                let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
                    None => expr_span,
                    Some(StatementSpan(span)) => span,
                });

                unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
                block.unit()
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>bench: Add tests for insertion functions<commit_after>#![feature(test)]

extern crate test;
extern crate rle_vec;

use std::iter::FromIterator;
use std::iter::repeat;
use test::Bencher;
use rle_vec::RleVec;

#[bench]
fn rle_insert_middle_non_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    b.iter(|| {
        let zeros = repeat(0).take(10);
        let ones = repeat(1).take(10);
        let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

        let mut rle = RleVec::from_iter(iter);
        let middle_value = rle[5_000];
        rle.insert(5_000, middle_value); // ???
    })
}

#[bench]
fn rle_insert_middle_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    b.iter(|| {
        let zeros = repeat(0).take(10);
        let ones = repeat(1).take(10);
        let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

        let mut rle = RleVec::from_iter(iter);
        rle.insert(5_000, 424242); // ???
    })
}

#[bench]
fn vec_insert_middle_10_000_runs_of_10_values(b: &mut Bencher) {
    b.iter(|| {
        let zeros = repeat(0).take(10);
        let ones = repeat(1).take(10);
        let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

        let mut vec = Vec::from_iter(iter);
        let middle_value = vec[5_000];
        vec.insert(5_000, middle_value);
    })
}
<|endoftext|>


<commit_before><commit_msg>WIP cube demo update<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed job arguments expanding to empty<commit_after><|endoftext|>


<commit_before>// Copyright 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::task;
use std::rand::{task_rng, Rng};

const MAX_LEN: uint = 20;
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
static mut clone_count: uint = 0;

#[deriving(Rand, PartialEq, PartialOrd, Eq, Ord)]
struct DropCounter { x: uint, clone_num: uint }

impl Clone for DropCounter {
    fn clone(&self) -> DropCounter {
        let num = unsafe { clone_count };
        unsafe { clone_count += 1; }
        DropCounter {
            x: self.x,
            clone_num: num
        }
    }
}

impl Drop for DropCounter {
    fn drop(&mut self) {
        unsafe {
            // Rand creates some with arbitrary clone_nums
            if self.clone_num < MAX_LEN {
                drop_counts[self.clone_num] += 1;
            }
        }
    }
}

pub fn main() {
    // len can't go above 64.
    for len in range(2u, MAX_LEN) {
        for _ in range(0i, 10) {
            let main = task_rng().gen_iter::<DropCounter>()
                                 .take(len)
                                 .collect::<Vec<DropCounter>>();

            // work out the total number of comparisons required to sort
            // this array...
            let mut count = 0;
            main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });

            // ... and then fail on each and every single one.
            for fail_countdown in range(0i, count) {
                // refresh the counters.
                unsafe {
                    drop_counts = [0, .. MAX_LEN];
                    clone_count = 0;
                }

                let v = main.clone();

                task::try(proc() {
                        let mut v = v;
                        let mut fail_countdown = fail_countdown;
                        v.as_mut_slice().sort_by(|a, b| {
                                if fail_countdown == 0 {
                                    fail!()
                                }
                                fail_countdown -= 1;
                                a.cmp(b)
                            })
                    });

                // check that the number of things dropped is exactly
                // what we expect (i.e. the contents of `v`).
                unsafe {
                    for (i, &c) in drop_counts.iter().enumerate() {
                        let expected = if i < len {1} else {0};
                        assert!(c == expected,
                                "found drop count == {} for i == {}, len == {}",
                                c, i, len);
                    }
                }
            }
        }
    }
}
<commit_msg>auto merge of #18031 : huonw/rust/adjust-vec-sort-test, r=alexcrichton<commit_after>// Copyright 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::task;
use std::sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
use std::rand::{task_rng, Rng, Rand};

const REPEATS: uint = 5;
const MAX_LEN: uint = 32;
static drop_counts: [AtomicUint, .. MAX_LEN] =
    // FIXME #5244: AtomicUint is not Copy.
    [
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,

        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
        INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
     ];

static creation_count: AtomicUint = INIT_ATOMIC_UINT;

#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
struct DropCounter { x: uint, creation_id: uint }

impl Rand for DropCounter {
    fn rand<R: Rng>(rng: &mut R) -> DropCounter {
        // (we're not using this concurrently, so Relaxed is fine.)
        let num = creation_count.fetch_add(1, Relaxed);
        DropCounter {
            x: rng.gen(),
            creation_id: num
        }
    }
}

impl Drop for DropCounter {
    fn drop(&mut self) {
        drop_counts[self.creation_id].fetch_add(1, Relaxed);
    }
}

pub fn main() {
    assert!(MAX_LEN <= std::uint::BITS);
    // len can't go above 64.
    for len in range(2, MAX_LEN) {
        for _ in range(0, REPEATS) {
            // reset the count for these new DropCounters, so their
            // IDs start from 0.
            creation_count.store(0, Relaxed);

            let main = task_rng().gen_iter::<DropCounter>()
                                 .take(len)
                                 .collect::<Vec<DropCounter>>();

            // work out the total number of comparisons required to sort
            // this array...
            let mut count = 0;
            main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });

            // ... and then fail on each and every single one.
            for fail_countdown in range(0i, count) {
                // refresh the counters.
                for c in drop_counts.iter() {
                    c.store(0, Relaxed);
                }

                let v = main.clone();

                let _ = task::try(proc() {
                        let mut v = v;
                        let mut fail_countdown = fail_countdown;
                        v.as_mut_slice().sort_by(|a, b| {
                                if fail_countdown == 0 {
                                    fail!()
                                }
                                fail_countdown -= 1;
                                a.cmp(b)
                            })
                    });

                // check that the number of things dropped is exactly
                // what we expect (i.e. the contents of `v`).
                for (i, c) in drop_counts.iter().enumerate().take(len) {
                    let count = c.load(Relaxed);
                    assert!(count == 1,
                            "found drop count == {} for i == {}, len == {}",
                            count, i, len);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 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::rand::{task_rng, Rng};

static MAX_LEN: uint = 20;
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
static mut clone_count: uint = 0;

#[deriving(Rand, Ord, TotalEq, TotalOrd)]
struct DropCounter { x: uint, clone_num: uint }

impl Clone for DropCounter {
    fn clone(&self) -> DropCounter {
        let num = unsafe { clone_count };
        unsafe { clone_count += 1; }
        DropCounter {
            x: self.x,
            clone_num: num
        }
    }
}

impl Drop for DropCounter {
    fn drop(&mut self) {
        unsafe {
            // Rand creates some with arbitrary clone_nums
            if self.clone_num < MAX_LEN {
                drop_counts[self.clone_num] += 1;
            }
        }
    }
}

pub fn main() {
    // len can't go above 64.
    for len in range(2u, MAX_LEN) {
        for _ in range(0, 10) {
            let main = task_rng().gen_vec::<DropCounter>(len);

            // work out the total number of comparisons required to sort
            // this array...
            let mut count = 0;
            main.clone().sort_by(|a, b| { count += 1; a.cmp(b) });

            // ... and then fail on each and every single one.
            for fail_countdown in range(0, count) {
                // refresh the counters.
                unsafe {
                    drop_counts = [0, .. MAX_LEN];
                    clone_count = 0;
                }

                let v = main.clone();

                std::task::try(proc() {
                        let mut v = v;
                        let mut fail_countdown = fail_countdown;
                        v.sort_by(|a, b| {
                                if fail_countdown == 0 {
                                    fail!()
                                }
                                fail_countdown -= 1;
                                a.cmp(b)
                            })
                    });

                // check that the number of things dropped is exactly
                // what we expect (i.e. the contents of `v`).
                unsafe {
                    for (i, &c) in drop_counts.iter().enumerate() {
                        let expected = if i < len {1} else {0};
                        assert!(c == expected,
                                "found drop count == {} for i == {}, len == {}",
                                c, i, len);
                    }
                }
            }
        }
    }
}
<commit_msg>fix check-fast tests.<commit_after>// Copyright 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::task;
use std::rand::{task_rng, Rng};

static MAX_LEN: uint = 20;
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
static mut clone_count: uint = 0;

#[deriving(Rand, Ord, TotalEq, TotalOrd)]
struct DropCounter { x: uint, clone_num: uint }

impl Clone for DropCounter {
    fn clone(&self) -> DropCounter {
        let num = unsafe { clone_count };
        unsafe { clone_count += 1; }
        DropCounter {
            x: self.x,
            clone_num: num
        }
    }
}

impl Drop for DropCounter {
    fn drop(&mut self) {
        unsafe {
            // Rand creates some with arbitrary clone_nums
            if self.clone_num < MAX_LEN {
                drop_counts[self.clone_num] += 1;
            }
        }
    }
}

pub fn main() {
    // len can't go above 64.
    for len in range(2u, MAX_LEN) {
        for _ in range(0, 10) {
            let main = task_rng().gen_vec::<DropCounter>(len);

            // work out the total number of comparisons required to sort
            // this array...
            let mut count = 0;
            main.clone().sort_by(|a, b| { count += 1; a.cmp(b) });

            // ... and then fail on each and every single one.
            for fail_countdown in range(0, count) {
                // refresh the counters.
                unsafe {
                    drop_counts = [0, .. MAX_LEN];
                    clone_count = 0;
                }

                let v = main.clone();

                task::try(proc() {
                        let mut v = v;
                        let mut fail_countdown = fail_countdown;
                        v.sort_by(|a, b| {
                                if fail_countdown == 0 {
                                    fail!()
                                }
                                fail_countdown -= 1;
                                a.cmp(b)
                            })
                    });

                // check that the number of things dropped is exactly
                // what we expect (i.e. the contents of `v`).
                unsafe {
                    for (i, &c) in drop_counts.iter().enumerate() {
                        let expected = if i < len {1} else {0};
                        assert!(c == expected,
                                "found drop count == {} for i == {}, len == {}",
                                c, i, len);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Added a check for vertices to polygon collision<commit_after><|endoftext|>


<commit_before><commit_msg>Switched to making the shapes PartialEq, because they use floats<commit_after><|endoftext|>


<commit_before>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn;
export spawn_notify;
export spawn_joinable;

native "rust" mod rustrt {
    fn task_sleep(time_in_us: uint);
    fn task_yield();
    fn task_join(t: task_id) -> int;
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    type rust_chan;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);
    fn start_task(id: task_id, closure: *u8);
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret sys::unsupervise(); }

fn pin() { rustrt::pin_task(); }

fn unpin() { rustrt::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt::set_min_stack(stack_size); }

fn spawn<~T>(-data: T, f: fn(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify<~T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable<~T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>isolate those funcs in task that can run on the c stack<commit_after>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn;
export spawn_notify;
export spawn_joinable;

native "rust" mod rustrt {                           // C Stack?
    fn task_sleep(time_in_us: uint);                 // No
    fn task_yield();                                 // No
    fn start_task(id: task_id, closure: *u8);        // No
    fn task_join(t: task_id) -> int;                 // Refactor
}

native "c-stack-cdecl" mod rustrt2 = "rustrt" {
    fn pin_task();                                   // Yes
    fn unpin_task();                                 // Yes
    fn get_task_id() -> task_id;                     // Yes

    fn set_min_stack(stack_size: uint);              // Yes

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);   // Yes
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt2::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt2::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret sys::unsupervise(); }

fn pin() { rustrt2::pin_task(); }

fn unpin() { rustrt2::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt2::set_min_stack(stack_size); }

fn spawn<~T>(-data: T, f: fn(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify<~T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable<~T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt2::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt2::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt2::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before><commit_msg>split out marks into its own struct, fixed a few bugs, added a new method to editor and nixed the defaults impl<commit_after><|endoftext|>


<commit_before><commit_msg>Return the digest instead of printing it<commit_after><|endoftext|>


<commit_before><commit_msg>Add `util` module<commit_after>//! Set of utility functions.

/// Absolute difference between two `f64`.
pub fn range(a: f64, b: f64) -> f64 {
  ((a) - (b)).abs()
}

/// Generates a `(f64,f64)` tuple with the smaller value first.
pub fn min_max(a: f64, b: f64) -> (f64, f64) {
  if a >= b { (b, a) } else { (a, b) }
}
<|endoftext|>


<commit_before><commit_msg>add all current imag binaries to the shell-completion script<commit_after><|endoftext|>


<commit_before><commit_msg>Fix(syncfile): it should close the file handle after fully reading the data<commit_after><|endoftext|>


<commit_before><commit_msg>Chapter 15: fin<commit_after><|endoftext|>


<commit_before><commit_msg>add tests for glsl versions<commit_after>extern crate glium;

use glium::{Version, Api};

macro_rules! assert_versions {
    ( $api:path, $gl_major:expr, $gl_minor:expr => $glsl_major:expr, $glsl_minor:expr) => {
        assert_eq!(
            Version($api, $gl_major, $gl_minor).get_glsl_version(),
            Version($api, $glsl_major, $glsl_minor)
                );
    }
}

#[test]
fn valid_gl_versions() {
    // irregular versions
    assert_versions!(Api::Gl, 2, 0 => 1, 1);
    assert_versions!(Api::Gl, 2, 1 => 1, 2);
    assert_versions!(Api::Gl, 3, 0 => 1, 3);
    assert_versions!(Api::Gl, 3, 1 => 1, 4);
    assert_versions!(Api::Gl, 3, 2 => 1, 5);

    // test a few regular versions
    assert_versions!(Api::Gl, 3, 3 => 3, 3);
    assert_versions!(Api::Gl, 4, 0 => 4, 0);
    assert_versions!(Api::Gl, 4, 5 => 4, 5);
}

#[test]
fn valid_gles_versions() {
    // only irregular version
    assert_versions!(Api::GlEs, 2, 0 => 1, 0);

    // some regular versions
    assert_versions!(Api::GlEs, 3, 0 => 3, 0);
    assert_versions!(Api::GlEs, 3, 1 => 3, 1);
}

#[test]
#[should_fail]
fn invalid_gl_version() {
   Version(Api::Gl, 1, 0).get_glsl_version();
}

#[test]
#[should_fail]
fn invalid_gles_version() {
   Version(Api::GlEs, 1, 0).get_glsl_version();
}
<|endoftext|>


<commit_before><commit_msg>examples/disassemble.rs: add example to disassemble an eBPF program<commit_after>// Copyright 2017 Quentin Monnet <quentin.monnet@6wind.com>
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate rbpf;
use rbpf::disassembler;

fn main() {
    let prog = vec![
        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x79, 0x12, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x79, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xbf, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x07, 0x03, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
        0x2d, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x69, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x55, 0x02, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
        0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x55, 0x02, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00,
        0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x79, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xbf, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x57, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
        0x15, 0x02, 0x08, 0x00, 0x99, 0x99, 0x00, 0x00,
        0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x5f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
        0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x99, 0x99,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x1d, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ];
    disassembler::disassemble(&prog);
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open("/dev/urandom"));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use mem;
    use libc::c_long;
    use sys::os::errno;
    use rand::Rng;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    extern "C" {
        fn syscall(number: c_long, ...) -> c_long;
    }

    const NR_GETENTROPY: libc::c_long = 7;

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    syscall(NR_GETENTROPY, s.as_mut_ptr(), s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    #[cfg(stage0)] use prelude::v1::*;

    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    use io;
    use mem;
    use rand::Rng;
    use sys::c;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: c::HCRYPTPROV
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
                                        c::PROV_RSA_FULL,
                                        c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
            };

            if ret == 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
                                  v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                c::CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

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

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in 0..20 {
            let (tx, rx) = channel();
            txs.push(tx);

            thread::spawn(move|| {
                // wait until all the threads are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                thread::yield_now();
                let mut v = [0; 1000];

                for _ in 0..100 {
                    r.next_u32();
                    thread::yield_now();
                    r.next_u64();
                    thread::yield_now();
                    r.fill_bytes(&mut v);
                    thread::yield_now();
                }
            });
        }

        // start all the threads
        for tx in &txs {
            tx.send(()).unwrap();
        }
    }
}
<commit_msg>Fix build by removing needless type prefix<commit_after>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open("/dev/urandom"));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use mem;
    use libc::c_long;
    use sys::os::errno;
    use rand::Rng;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    extern "C" {
        fn syscall(number: c_long, ...) -> c_long;
    }

    const NR_GETENTROPY: c_long = 7;

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    syscall(NR_GETENTROPY, s.as_mut_ptr(), s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    #[cfg(stage0)] use prelude::v1::*;

    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    use io;
    use mem;
    use rand::Rng;
    use sys::c;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: c::HCRYPTPROV
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
                                        c::PROV_RSA_FULL,
                                        c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
            };

            if ret == 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
                                  v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                c::CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

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

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in 0..20 {
            let (tx, rx) = channel();
            txs.push(tx);

            thread::spawn(move|| {
                // wait until all the threads are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                thread::yield_now();
                let mut v = [0; 1000];

                for _ in 0..100 {
                    r.next_u32();
                    thread::yield_now();
                    r.next_u64();
                    thread::yield_now();
                    r.fill_bytes(&mut v);
                    thread::yield_now();
                }
            });
        }

        // start all the threads
        for tx in &txs {
            tx.send(()).unwrap();
        }
    }
}
<|endoftext|>