<commit_before><commit_msg>Rollup merge of #37610 - oldmanmike:unary-and-binary-tests, r=michaelwoerister<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.

// This test case tests the incremental compilation hash (ICH) implementation
// for unary and binary expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Z force-overflow-checks=off

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change constant operand of negation -----------------------------------------
#[cfg(cfail1)]
pub fn const_negation() -> i32 {
    -10
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn const_negation() -> i32 {
    -1
}

// Change constant operand of bitwise not --------------------------------------
#[cfg(cfail1)]
pub fn const_bitwise_not() -> i32 {
    !100
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn const_bitwise_not() -> i32 {
    !99
}

// Change variable operand of negation -----------------------------------------
#[cfg(cfail1)]
pub fn var_negation(x: i32, y: i32) -> i32 {
    -x
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn var_negation(x: i32, y: i32) -> i32 {
    -y
}

// Change variable operand of bitwise not --------------------------------------
#[cfg(cfail1)]
pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
    !x
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
    !y
}

// Change variable operand of deref --------------------------------------------
#[cfg(cfail1)]
pub fn var_deref(x: &i32, y: &i32) -> i32 {
    *x
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn var_deref(x: &i32, y: &i32) -> i32 {
    *y
}

// Change first constant operand of addition -----------------------------------
#[cfg(cfail1)]
pub fn first_const_add() -> i32 {
    1 + 3
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn first_const_add() -> i32 {
    2 + 3
}

// Change second constant operand of addition -----------------------------------
#[cfg(cfail1)]
pub fn second_const_add() -> i32 {
    1 + 2
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn second_const_add() -> i32 {
    1 + 3
}

// Change first variable operand of addition -----------------------------------
#[cfg(cfail1)]
pub fn first_var_add(a: i32, b: i32) -> i32 {
    a + 2
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn first_var_add(a: i32, b: i32) -> i32 {
    b + 2
}

// Change second variable operand of addition ----------------------------------
#[cfg(cfail1)]
pub fn second_var_add(a: i32, b: i32) -> i32 {
    1 + a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn second_var_add(a: i32, b: i32) -> i32 {
    1 + b
}

// Change operator from + to - -------------------------------------------------
#[cfg(cfail1)]
pub fn plus_to_minus(a: i32) -> i32 {
    1 + a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn plus_to_minus(a: i32) -> i32 {
    1 - a
}

// Change operator from + to * -------------------------------------------------
#[cfg(cfail1)]
pub fn plus_to_mult(a: i32) -> i32 {
    1 + a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn plus_to_mult(a: i32) -> i32 {
    1 * a
}

// Change operator from + to / -------------------------------------------------
#[cfg(cfail1)]
pub fn plus_to_div(a: i32) -> i32 {
    1 + a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn plus_to_div(a: i32) -> i32 {
    1 / a
}

// Change operator from + to % -------------------------------------------------
#[cfg(cfail1)]
pub fn plus_to_mod(a: i32) -> i32 {
    1 + a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn plus_to_mod(a: i32) -> i32 {
    1 % a
}

// Change operator from && to || -----------------------------------------------
#[cfg(cfail1)]
pub fn and_to_or(a: bool, b: bool) -> bool {
    a && b
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn and_to_or(a: bool, b: bool) -> bool {
    a || b
}

// Change operator from & to | -------------------------------------------------
#[cfg(cfail1)]
pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
    1 & a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
    1 | a
}

// Change operator from & to ^ -------------------------------------------------
#[cfg(cfail1)]
pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
    1 & a
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
    1 ^ a
}

// Change operator from & to << ------------------------------------------------
#[cfg(cfail1)]
pub fn bitwise_and_to_lshift(a: i32) -> i32 {
    a & 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn bitwise_and_to_lshift(a: i32) -> i32 {
    a << 1
}

// Change operator from & to >> ------------------------------------------------
#[cfg(cfail1)]
pub fn bitwise_and_to_rshift(a: i32) -> i32 {
    a & 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn bitwise_and_to_rshift(a: i32) -> i32 {
    a >> 1
}

// Change operator from == to != -----------------------------------------------
#[cfg(cfail1)]
pub fn eq_to_uneq(a: i32) -> bool {
    a == 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn eq_to_uneq(a: i32) -> bool {
    a != 1
}

// Change operator from == to < ------------------------------------------------
#[cfg(cfail1)]
pub fn eq_to_lt(a: i32) -> bool {
    a == 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn eq_to_lt(a: i32) -> bool {
    a < 1
}

// Change operator from == to > ------------------------------------------------
#[cfg(cfail1)]
pub fn eq_to_gt(a: i32) -> bool {
    a == 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn eq_to_gt(a: i32) -> bool {
    a > 1
}

// Change operator from == to <= -----------------------------------------------
#[cfg(cfail1)]
pub fn eq_to_le(a: i32) -> bool {
    a == 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn eq_to_le(a: i32) -> bool {
    a <= 1
}

// Change operator from == to >= -----------------------------------------------
#[cfg(cfail1)]
pub fn eq_to_ge(a: i32) -> bool {
    a == 1
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn eq_to_ge(a: i32) -> bool {
    a >= 1
}

// Change type in cast expression ----------------------------------------------
#[cfg(cfail1)]
pub fn type_cast(a: u8) -> u64 {
    let b = a as i32;
    let c = b as u64;
    c
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn type_cast(a: u8) -> u64 {
    let b = a as u32;
    let c = b as u64;
    c
}

// Change value in cast expression ---------------------------------------------
#[cfg(cfail1)]
pub fn value_cast(a: u32) -> i32 {
    1 as i32
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn value_cast(a: u32) -> i32 {
    2 as i32
}

// Change l-value in assignment ------------------------------------------------
#[cfg(cfail1)]
pub fn lvalue() -> i32 {
    let mut x = 10;
    let mut y = 11;
    x = 9;
    x
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn lvalue() -> i32 {
    let mut x = 10;
    let mut y = 11;
    y = 9;
    x
}

// Change r-value in assignment ------------------------------------------------
#[cfg(cfail1)]
pub fn rvalue() -> i32 {
    let mut x = 10;
    x = 9;
    x
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn rvalue() -> i32 {
    let mut x = 10;
    x = 8;
    x
}

// Change index into slice -----------------------------------------------------
#[cfg(cfail1)]
pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
    s[i]
}

#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfails2")]
#[rustc_clean(label="Hir", cfg="cfails3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
    s[j]
}
<|endoftext|>


<commit_before><commit_msg>Add wordcount<commit_after>#![feature(phase)]
#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
use std::collections::BTreeMap;
use std::io;
use std::ascii::AsciiExt;

fn main() {
    let re = regex!(r"[^a-z']+");
    let mut counts = BTreeMap::new();
    for line in io::stdin().lock().lines() {
        let raw_word = line.unwrap().to_ascii_lower();
        for word in re.split(&*raw_word) {
            if word.len() > 0 {
                let num_items = match counts.get(word) {
                    Some(x) => *x,
                    None    => 0i
                };
                counts.insert(String::from_str(word), num_items + 1);
            }
        }
    }
    for (key, value) in counts.iter() {
        println!("{} {}", key, value);
    }
}
<|endoftext|>


<commit_before><commit_msg>updated to work with rust nightly<commit_after><|endoftext|>


<commit_before><commit_msg>sync: Introduce new wrapper types for locking<commit_after>// Copyright 2012-2014 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.

//! Wrappers for safe, shared, mutable memory between tasks
//!
//! The wrappers in this module build on the primitives from `sync::raw` to
//! provide safe interfaces around using the primitive locks. These primitives
//! implement a technique called "poisoning" where when a task failed with a
//! held lock, all future attempts to use the lock will fail.
//!
//! For example, if two tasks are contending on a mutex and one of them fails
//! after grabbing the lock, the second task will immediately fail because the
//! lock is now poisoned.

use std::task;
use std::ty::Unsafe;

use raw;

/****************************************************************************
 * Poisoning helpers
 ****************************************************************************/

struct PoisonOnFail<'a> {
    flag: &'a mut bool,
    failed: bool,
}

impl<'a> PoisonOnFail<'a> {
    fn check(flag: bool, name: &str) {
        if flag {
            fail!("Poisoned {} - another task failed inside!", name);
        }
    }

    fn new<'a>(flag: &'a mut bool, name: &str) -> PoisonOnFail<'a> {
        PoisonOnFail::check(*flag, name);
        PoisonOnFail {
            flag: flag,
            failed: task::failing()
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for PoisonOnFail<'a> {
    fn drop(&mut self) {
        if !self.failed && task::failing() {
            *self.flag = true;
        }
    }
}

/****************************************************************************
 * Condvar
 ****************************************************************************/

enum Inner<'a> {
    InnerMutex(raw::MutexGuard<'a>),
    InnerRWLock(raw::RWLockWriteGuard<'a>),
}

impl<'b> Inner<'b> {
    fn cond<'a>(&'a self) -> &'a raw::Condvar<'b> {
        match *self {
            InnerMutex(ref m) => &m.cond,
            InnerRWLock(ref m) => &m.cond,
        }
    }
}

/// A condition variable, a mechanism for unlock-and-descheduling and
/// signaling, for use with the lock types.
pub struct Condvar<'a> {
    priv name: &'static str,
    // n.b. Inner must be after PoisonOnFail because we must set the poison flag
    //      *inside* the mutex, and struct fields are destroyed top-to-bottom
    //      (destroy the lock guard last).
    priv poison: PoisonOnFail<'a>,
    priv inner: Inner<'a>,
}

impl<'a> Condvar<'a> {
    /// Atomically exit the associated lock and block until a signal is sent.
    ///
    /// wait() is equivalent to wait_on(0).
    ///
    /// # Failure
    ///
    /// A task which is killed while waiting on a condition variable will wake
    /// up, fail, and unlock the associated lock as it unwinds.
    #[inline]
    pub fn wait(&self) { self.wait_on(0) }

    /// Atomically exit the associated lock and block on a specified condvar
    /// until a signal is sent on that same condvar.
    ///
    /// The associated lock must have been initialised with an appropriate
    /// number of condvars. The condvar_id must be between 0 and num_condvars-1
    /// or else this call will fail.
    #[inline]
    pub fn wait_on(&self, condvar_id: uint) {
        assert!(!*self.poison.flag);
        self.inner.cond().wait_on(condvar_id);
        // This is why we need to wrap sync::condvar.
        PoisonOnFail::check(*self.poison.flag, self.name);
    }

    /// Wake up a blocked task. Returns false if there was no blocked task.
    #[inline]
    pub fn signal(&self) -> bool { self.signal_on(0) }

    /// Wake up a blocked task on a specified condvar (as
    /// sync::cond.signal_on). Returns false if there was no blocked task.
    #[inline]
    pub fn signal_on(&self, condvar_id: uint) -> bool {
        assert!(!*self.poison.flag);
        self.inner.cond().signal_on(condvar_id)
    }

    /// Wake up all blocked tasks. Returns the number of tasks woken.
    #[inline]
    pub fn broadcast(&self) -> uint { self.broadcast_on(0) }

    /// Wake up all blocked tasks on a specified condvar (as
    /// sync::cond.broadcast_on). Returns the number of tasks woken.
    #[inline]
    pub fn broadcast_on(&self, condvar_id: uint) -> uint {
        assert!(!*self.poison.flag);
        self.inner.cond().broadcast_on(condvar_id)
    }
}

/****************************************************************************
 * Mutex
 ****************************************************************************/

/// A wrapper type which provides synchronized access to the underlying data, of
/// type `T`. A mutex always provides exclusive access, and concurrent requests
/// will block while the mutex is already locked.
///
/// # Example
///
/// ```
/// use sync::{Mutex, Arc};
///
/// let mutex = Arc::new(Mutex::new(1));
/// let mutex2 = mutex.clone();
///
/// spawn(proc() {
///     let mut val = mutex2.lock();
///     *val += 1;
///     val.cond.signal();
/// });
///
/// let mut value = mutex.lock();
/// while *value != 2 {
///     value.cond.wait();
/// }
/// ```
pub struct Mutex<T> {
    priv lock: raw::Mutex,
    priv failed: Unsafe<bool>,
    priv data: Unsafe<T>,
}

/// An guard which is created by locking a mutex. Through this guard the
/// underlying data can be accessed.
pub struct MutexGuard<'a, T> {
    priv data: &'a mut T,
    /// Inner condition variable connected to the locked mutex that this guard
    /// was created from. This can be used for atomic-unlock-and-deschedule.
    cond: Condvar<'a>,
}

impl<T: Send> Mutex<T> {
    /// Creates a new mutex to protect the user-supplied data.
    pub fn new(user_data: T) -> Mutex<T> {
        Mutex::new_with_condvars(user_data, 1)
    }

    /// Create a new mutex, with a specified number of associated condvars.
    ///
    /// This will allow calling wait_on/signal_on/broadcast_on with condvar IDs
    /// between 0 and num_condvars-1. (If num_condvars is 0, lock_cond will be
    /// allowed but any operations on the condvar will fail.)
    pub fn new_with_condvars(user_data: T, num_condvars: uint) -> Mutex<T> {
        Mutex {
            lock: raw::Mutex::new_with_condvars(num_condvars),
            failed: Unsafe::new(false),
            data: Unsafe::new(user_data),
        }
    }

    /// Access the underlying mutable data with mutual exclusion from other
    /// tasks. The returned value is an RAII guard which will unlock the mutex
    /// when dropped. All concurrent tasks attempting to lock the mutex will
    /// block while the returned value is still alive.
    ///
    /// # Failure
    ///
    /// Failing while inside the Mutex will unlock the Mutex while unwinding, so
    /// that other tasks won't block forever. It will also poison the Mutex:
    /// any tasks that subsequently try to access it (including those already
    /// blocked on the mutex) will also fail immediately.
    #[inline]
    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
        let guard = self.lock.lock();

        // These two accesses are safe because we're guranteed at this point
        // that we have exclusive access to this mutex. We are indeed able to
        // promote ourselves from &Mutex to `&mut T`
        let poison = unsafe { &mut *self.failed.get() };
        let data = unsafe { &mut *self.data.get() };

        MutexGuard {
            data: data,
            cond: Condvar {
                name: "Mutex",
                poison: PoisonOnFail::new(poison, "Mutex"),
                inner: InnerMutex(guard),
            },
        }
    }
}

// FIXME(#13042): these should both have T: Send
impl<'a, T> Deref<T> for MutexGuard<'a, T> {
    fn deref<'a>(&'a self) -> &'a T { &*self.data }
}
impl<'a, T> DerefMut<T> for MutexGuard<'a, T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self.data }
}

/****************************************************************************
 * R/W lock protected lock
 ****************************************************************************/

/// A dual-mode reader-writer lock. The data can be accessed mutably or
/// immutably, and immutably-accessing tasks may run concurrently.
///
/// # Example
///
/// ```
/// use sync::{RWLock, Arc};
///
/// let lock1 = Arc::new(RWLock::new(1));
/// let lock2 = lock1.clone();
///
/// spawn(proc() {
///     let mut val = lock2.write();
///     *val = 3;
///     let val = val.downgrade();
///     println!("{}", *val);
/// });
///
/// let val = lock1.read();
/// println!("{}", *val);
/// ```
pub struct RWLock<T> {
    priv lock: raw::RWLock,
    priv failed: Unsafe<bool>,
    priv data: Unsafe<T>,
}

/// A guard which is created by locking an rwlock in write mode. Through this
/// guard the underlying data can be accessed.
pub struct RWLockWriteGuard<'a, T> {
    priv data: &'a mut T,
    /// Inner condition variable that can be used to sleep on the write mode of
    /// this rwlock.
    cond: Condvar<'a>,
}

/// A guard which is created by locking an rwlock in read mode. Through this
/// guard the underlying data can be accessed.
pub struct RWLockReadGuard<'a, T> {
    priv data: &'a T,
    priv guard: raw::RWLockReadGuard<'a>,
}

impl<T: Send + Share> RWLock<T> {
    /// Create a reader/writer lock with the supplied data.
    pub fn new(user_data: T) -> RWLock<T> {
        RWLock::new_with_condvars(user_data, 1)
    }

    /// Create a reader/writer lock with the supplied data and a specified number
    /// of condvars (as sync::RWLock::new_with_condvars).
    pub fn new_with_condvars(user_data: T, num_condvars: uint) -> RWLock<T> {
        RWLock {
            lock: raw::RWLock::new_with_condvars(num_condvars),
            failed: Unsafe::new(false),
            data: Unsafe::new(user_data),
        }
    }

    /// Access the underlying data mutably. Locks the rwlock in write mode;
    /// other readers and writers will block.
    ///
    /// # Failure
    ///
    /// Failing while inside the lock will unlock the lock while unwinding, so
    /// that other tasks won't block forever. As Mutex.lock, it will also poison
    /// the lock, so subsequent readers and writers will both also fail.
    #[inline]
    pub fn write<'a>(&'a self) -> RWLockWriteGuard<'a, T> {
        let guard = self.lock.write();

        // These two accesses are safe because we're guranteed at this point
        // that we have exclusive access to this rwlock. We are indeed able to
        // promote ourselves from &RWLock to `&mut T`
        let poison = unsafe { &mut *self.failed.get() };
        let data = unsafe { &mut *self.data.get() };

        RWLockWriteGuard {
            data: data,
            cond: Condvar {
                name: "RWLock",
                poison: PoisonOnFail::new(poison, "RWLock"),
                inner: InnerRWLock(guard),
            },
        }
    }

    /// Access the underlying data immutably. May run concurrently with other
    /// reading tasks.
    ///
    /// # Failure
    ///
    /// Failing will unlock the lock while unwinding. However, unlike all other
    /// access modes, this will not poison the lock.
    pub fn read<'a>(&'a self) -> RWLockReadGuard<'a, T> {
        let guard = self.lock.read();
        PoisonOnFail::check(unsafe { *self.failed.get() }, "RWLock");
        RWLockReadGuard {
            guard: guard,
            data: unsafe { &*self.data.get() },
        }
    }
}

impl<'a, T: Send + Share> RWLockWriteGuard<'a, T> {
    /// Consumes this write lock token, returning a new read lock token.
    ///
    /// This will allow pending readers to come into the lock.
    pub fn downgrade(self) -> RWLockReadGuard<'a, T> {
        let RWLockWriteGuard { data, cond } = self;
        // convert the data to read-only explicitly
        let data = &*data;
        let guard = match cond.inner {
            InnerMutex(..) => unreachable!(),
            InnerRWLock(guard) => guard.downgrade()
        };
        RWLockReadGuard { guard: guard, data: data }
    }
}

// FIXME(#13042): these should all have T: Send + Share
impl<'a, T> Deref<T> for RWLockReadGuard<'a, T> {
    fn deref<'a>(&'a self) -> &'a T { self.data }
}
impl<'a, T> Deref<T> for RWLockWriteGuard<'a, T> {
    fn deref<'a>(&'a self) -> &'a T { &*self.data }
}
impl<'a, T> DerefMut<T> for RWLockWriteGuard<'a, T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self.data }
}

/****************************************************************************
 * Barrier
 ****************************************************************************/

/// A barrier enables multiple tasks to synchronize the beginning
/// of some computation.
///
/// ```rust
/// use sync::{Arc, Barrier};
///
/// let barrier = Arc::new(Barrier::new(10));
/// for _ in range(0, 10) {
///     let c = barrier.clone();
///     // The same messages will be printed together.
///     // You will NOT see any interleaving.
///     spawn(proc() {
///         println!("before wait");
///         c.wait();
///         println!("after wait");
///     });
/// }
/// ```
pub struct Barrier {
    priv lock: Mutex<BarrierState>,
    priv num_tasks: uint,
}

// The inner state of a double barrier
struct BarrierState {
    count: uint,
    generation_id: uint,
}

impl Barrier {
    /// Create a new barrier that can block a given number of tasks.
    pub fn new(num_tasks: uint) -> Barrier {
        Barrier {
            lock: Mutex::new(BarrierState {
                count: 0,
                generation_id: 0,
            }),
            num_tasks: num_tasks,
        }
    }

    /// Block the current task until a certain number of tasks is waiting.
    pub fn wait(&self) {
        let mut lock = self.lock.lock();
        let local_gen = lock.generation_id;
        lock.count += 1;
        if lock.count < self.num_tasks {
            // We need a while loop to guard against spurious wakeups.
            // http://en.wikipedia.org/wiki/Spurious_wakeup
            while local_gen == lock.generation_id &&
                  lock.count < self.num_tasks {
                lock.cond.wait();
            }
        } else {
            lock.count = 0;
            lock.generation_id += 1;
            lock.cond.broadcast();
        }
    }
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use std::comm::Empty;
    use std::task;

    use arc::Arc;
    use super::{Mutex, Barrier, RWLock};

    #[test]
    fn test_mutex_arc_condvar() {
        let arc = Arc::new(Mutex::new(false));
        let arc2 = arc.clone();
        let (tx, rx) = channel();
        task::spawn(proc() {
            // wait until parent gets in
            rx.recv();
            let mut lock = arc2.lock();
            *lock = true;
            lock.cond.signal();
        });

        let lock = arc.lock();
        tx.send(());
        assert!(!*lock);
        while !*lock {
            lock.cond.wait();
        }
    }

    #[test] #[should_fail]
    fn test_arc_condvar_poison() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let (tx, rx) = channel();

        spawn(proc() {
            rx.recv();
            let lock = arc2.lock();
            lock.cond.signal();
            // Parent should fail when it wakes up.
            fail!();
        });

        let lock = arc.lock();
        tx.send(());
        while *lock == 1 {
            lock.cond.wait();
        }
    }

    #[test] #[should_fail]
    fn test_mutex_arc_poison() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.lock();
            assert_eq!(*lock, 2);
        });
        let lock = arc.lock();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlaying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        task::spawn(proc() {
            let lock = arc2.lock();
            let lock2 = lock.deref().lock();
            assert_eq!(*lock2, 1);
        });
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1i));
        let arc2 = arc.clone();
        let _ = task::try::<()>(proc() {
            struct Unwinder {
                i: Arc<Mutex<int>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    let mut lock = self.i.lock();
                    *lock += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            fail!();
        });
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test] #[should_fail]
    fn test_rw_arc_poison_wr() {
        let arc = Arc::new(RWLock::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.write();
            assert_eq!(*lock, 2);
        });
        let lock = arc.read();
        assert_eq!(*lock, 1);
    }
    #[test] #[should_fail]
    fn test_rw_arc_poison_ww() {
        let arc = Arc::new(RWLock::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.write();
            assert_eq!(*lock, 2);
        });
        let lock = arc.write();
        assert_eq!(*lock, 1);
    }
    #[test]
    fn test_rw_arc_no_poison_rr() {
        let arc = Arc::new(RWLock::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.read();
            assert_eq!(*lock, 2);
        });
        let lock = arc.read();
        assert_eq!(*lock, 1);
    }
    #[test]
    fn test_rw_arc_no_poison_rw() {
        let arc = Arc::new(RWLock::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.read();
            assert_eq!(*lock, 2);
        });
        let lock = arc.write();
        assert_eq!(*lock, 1);
    }
    #[test]
    fn test_rw_arc_no_poison_dr() {
        let arc = Arc::new(RWLock::new(1));
        let arc2 = arc.clone();
        let _ = task::try(proc() {
            let lock = arc2.write().downgrade();
            assert_eq!(*lock, 2);
        });
        let lock = arc.write();
        assert_eq!(*lock, 1);
    }

    #[test]
    fn test_rw_arc() {
        let arc = Arc::new(RWLock::new(0));
        let arc2 = arc.clone();
        let (tx, rx) = channel();

        task::spawn(proc() {
            let mut lock = arc2.write();
            for _ in range(0, 10) {
                let tmp = *lock;
                *lock = -1;
                task::deschedule();
                *lock = tmp + 1;
            }
            tx.send(());
        });

        // Readers try to catch the writer in the act
        let mut children = Vec::new();
        for _ in range(0, 5) {
            let arc3 = arc.clone();
            let mut builder = task::task();
            children.push(builder.future_result());
            builder.spawn(proc() {
                let lock = arc3.read();
                assert!(*lock >= 0);
            });
        }

        // Wait for children to pass their asserts
        for r in children.mut_iter() {
            assert!(r.recv().is_ok());
        }

        // Wait for writer to finish
        rx.recv();
        let lock = arc.read();
        assert_eq!(*lock, 10);
    }

    #[test]
    fn test_rw_arc_access_in_unwind() {
        let arc = Arc::new(RWLock::new(1i));
        let arc2 = arc.clone();
        let _ = task::try::<()>(proc() {
            struct Unwinder {
                i: Arc<RWLock<int>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    let mut lock = self.i.write();
                    *lock += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            fail!();
        });
        let lock = arc.read();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_rw_downgrade() {
        // (1) A downgrader gets in write mode and does cond.wait.
        // (2) A writer gets in write mode, sets state to 42, and does signal.
        // (3) Downgrader wakes, sets state to 31337.
        // (4) tells writer and all other readers to contend as it downgrades.
        // (5) Writer attempts to set state back to 42, while downgraded task
        //     and all reader tasks assert that it's 31337.
        let arc = Arc::new(RWLock::new(0));

        // Reader tasks
        let mut reader_convos = Vec::new();
        for _ in range(0, 10) {
            let ((tx1, rx1), (tx2, rx2)) = (channel(), channel());
            reader_convos.push((tx1, rx2));
            let arcn = arc.clone();
            task::spawn(proc() {
                rx1.recv(); // wait for downgrader to give go-ahead
                let lock = arcn.read();
                assert_eq!(*lock, 31337);
                tx2.send(());
            });
        }

        // Writer task
        let arc2 = arc.clone();
        let ((tx1, rx1), (tx2, rx2)) = (channel(), channel());
        task::spawn(proc() {
            rx1.recv();
            {
                let mut lock = arc2.write();
                assert_eq!(*lock, 0);
                *lock = 42;
                lock.cond.signal();
            }
            rx1.recv();
            {
                let mut lock = arc2.write();
                // This shouldn't happen until after the downgrade read
                // section, and all other readers, finish.
                assert_eq!(*lock, 31337);
                *lock = 42;
            }
            tx2.send(());
        });

        // Downgrader (us)
        let mut lock = arc.write();
        tx1.send(()); // send to another writer who will wake us up
        while *lock == 0 {
            lock.cond.wait();
        }
        assert_eq!(*lock, 42);
        *lock = 31337;
        // send to other readers
        for &(ref mut rc, _) in reader_convos.mut_iter() {
            rc.send(())
        }
        let lock = lock.downgrade();
        // complete handshake with other readers
        for &(_, ref mut rp) in reader_convos.mut_iter() {
            rp.recv()
        }
        tx1.send(()); // tell writer to try again
        assert_eq!(*lock, 31337);
        drop(lock);

        rx2.recv(); // complete handshake with writer
    }

    #[cfg(test)]
    fn test_rw_write_cond_downgrade_read_race_helper() {
        // Tests that when a downgrader hands off the "reader cloud" lock
        // because of a contending reader, a writer can't race to get it
        // instead, which would result in readers_and_writers. This tests
        // the raw module rather than this one, but it's here because an
        // rwarc gives us extra shared state to help check for the race.
        let x = Arc::new(RWLock::new(true));
        let (tx, rx) = channel();

        // writer task
        let xw = x.clone();
        task::spawn(proc() {
            let mut lock = xw.write();
            tx.send(()); // tell downgrader it's ok to go
            lock.cond.wait();
            // The core of the test is here: the condvar reacquire path
            // must involve order_lock, so that it cannot race with a reader
            // trying to receive the "reader cloud lock hand-off".
            *lock = false;
        });

        rx.recv(); // wait for writer to get in

        let lock = x.write();
        assert!(*lock);
        // make writer contend in the cond-reacquire path
        lock.cond.signal();
        // make a reader task to trigger the "reader cloud lock" handoff
        let xr = x.clone();
        let (tx, rx) = channel();
        task::spawn(proc() {
            tx.send(());
            drop(xr.read());
        });
        rx.recv(); // wait for reader task to exist

        let lock = lock.downgrade();
        // if writer mistakenly got in, make sure it mutates state
        // before we assert on it
        for _ in range(0, 5) { task::deschedule(); }
        // make sure writer didn't get in.
        assert!(*lock);
    }
    #[test]
    fn test_rw_write_cond_downgrade_read_race() {
        // Ideally the above test case would have deschedule statements in it
        // that helped to expose the race nearly 100% of the time... but adding
        // deschedules in the intuitively-right locations made it even less
        // likely, and I wasn't sure why :( . This is a mediocre "next best"
        // option.
        for _ in range(0, 8) {
            test_rw_write_cond_downgrade_read_race_helper();
        }
    }

    /************************************************************************
     * Barrier tests
     ************************************************************************/
    #[test]
    fn test_barrier() {
        let barrier = Arc::new(Barrier::new(10));
        let (tx, rx) = channel();

        for _ in range(0, 9) {
            let c = barrier.clone();
            let tx = tx.clone();
            spawn(proc() {
                c.wait();
                tx.send(true);
            });
        }

        // At this point, all spawned tasks should be blocked,
        // so we shouldn't get anything from the port
        assert!(match rx.try_recv() {
            Empty => true,
            _ => false,
        });

        barrier.wait();
        // Now, the barrier is cleared and we should get data.
        for _ in range(0, 9) {
            rx.recv();
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>Rollup merge of #63129 - Centril:subslice-pat-statdyn, r=oli-obk<commit_after>// This test comprehensively checks the passing static and dynamic semantics
// of subslice patterns `..`, `x @ ..`, `ref x @ ..`, and `ref mut @ ..`
// in slice patterns `[$($pat), $(,)?]` .

// run-pass

#![feature(slice_patterns)]

#![allow(unreachable_patterns)]

use std::convert::identity;

#[derive(PartialEq, Debug, Clone)]
struct N(u8);

macro_rules! n {
    ($($e:expr),* $(,)?) => {
        [$(N($e)),*]
    }
}

macro_rules! c {
    ($inp:expr, $typ:ty, $out:expr $(,)?) => {
        assert_eq!($out, identity::<$typ>($inp));
    }
}

macro_rules! m {
    ($e:expr, $p:pat => $b:expr) => {
        match $e {
            $p => $b,
            _ => panic!(),
        }
    }
}

fn main() {
    slices();
    arrays();
}

fn slices() {
    // Matching slices using `ref` patterns:
    let mut v = vec![N(0), N(1), N(2), N(3), N(4)];
    let mut vc = (0..=4).collect::<Vec<u8>>();

    let [..] = v[..]; // Always matches.
    m!(v[..], [N(0), ref sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3]));
    m!(v[..], [N(0), ref sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4]));
    m!(v[..], [ref sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3]));
    m!(v[..], [ref sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N]));
    m!(v[..], [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N], &n![] as &[N]));
    m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4)));

    // Matching slices using `ref mut` patterns:
    let [..] = v[..]; // Always matches.
    m!(v[..], [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3]));
    m!(v[..], [N(0), ref mut sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4]));
    m!(v[..], [ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3]));
    m!(v[..], [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N]));
    m!(v[..], [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N]));
    m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4)));

    // Matching slices using default binding modes (&):
    let [..] = &v[..]; // Always matches.
    m!(&v[..], [N(0), sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3]));
    m!(&v[..], [N(0), sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4]));
    m!(&v[..], [sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3]));
    m!(&v[..], [sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N]));
    m!(&v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &[N], &n![] as &[N]));
    m!(&vc[..], [x, .., y] => c!((x, y), (&u8, &u8), (&0, &4)));

    // Matching slices using default binding modes (&mut):
    let [..] = &mut v[..]; // Always matches.
    m!(&mut v[..], [N(0), sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3]));
    m!(&mut v[..], [N(0), sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4]));
    m!(&mut v[..], [sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3]));
    m!(&mut v[..], [sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N]));
    m!(&mut v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N]));
    m!(&mut vc[..], [x, .., y] => c!((x, y), (&mut u8, &mut u8), (&mut 0, &mut 4)));
}

fn arrays() {
    let mut v = n![0, 1, 2, 3, 4];
    let vc = [0, 1, 2, 3, 4];

    // Matching arrays by value:
    m!(v.clone(), [N(0), sub @ .., N(4)] => c!(sub, [N; 3], n![1, 2, 3]));
    m!(v.clone(), [N(0), sub @ ..] => c!(sub, [N; 4], n![1, 2, 3, 4]));
    m!(v.clone(), [sub @ .., N(4)] => c!(sub, [N; 4], n![0, 1, 2, 3]));
    m!(v.clone(), [sub @ .., _, _, _, _, _] => c!(sub, [N; 0], n![] as [N; 0]));
    m!(v.clone(), [_, _, _, _, _, sub @ ..] => c!(sub, [N; 0], n![] as [N; 0]));
    m!(v.clone(), [x, .., y] => c!((x, y), (N, N), (N(0), N(4))));
    m!(v.clone(), [..] => ());

    // Matching arrays by ref patterns:
    m!(v, [N(0), ref sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3]));
    m!(v, [N(0), ref sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4]));
    m!(v, [ref sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3]));
    m!(v, [ref sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0]));
    m!(v, [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0]));
    m!(vc, [x, .., y] => c!((x, y), (u8, u8), (0, 4)));

    // Matching arrays by ref mut patterns:
    m!(v, [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3]));
    m!(v, [N(0), ref mut sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4]));
    m!(v, [ref mut sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3]));
    m!(v, [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0]));
    m!(v, [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0]));

    // Matching arrays by default binding modes (&):
    m!(&v, [N(0), sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3]));
    m!(&v, [N(0), sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4]));
    m!(&v, [sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3]));
    m!(&v, [sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0]));
    m!(&v, [_, _, _, _, _, sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0]));
    m!(&v, [..] => ());
    m!(&v, [x, .., y] => c!((x, y), (&N, &N), (&N(0), &N(4))));

    // Matching arrays by default binding modes (&mut):
    m!(&mut v, [N(0), sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3]));
    m!(&mut v, [N(0), sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4]));
    m!(&mut v, [sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3]));
    m!(&mut v, [sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0]));
    m!(&mut v, [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0]));
    m!(&mut v, [..] => ());
    m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4))));
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io;
use std::sync::{Arc, Mutex};
use term::{Terminal, TerminfoTerminal, color};
use hamcrest::{assert_that};

use cargo::core::shell::{Shell, ShellConfig};
use cargo::core::shell::ColorConfig::{Auto,Always, Never};

use support::{Tap, shell_writes};

fn setup() {
}

struct Sink(Arc<Mutex<Vec<u8>>>);

impl Write for Sink {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Write::write(&mut *self.0.lock().unwrap(), data)
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

test!(non_tty {
    let config = ShellConfig { color_config: Auto, tty: false };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });

    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..], shell_writes("Hey Alex\n"));
});

test!(color_explicitly_disabled {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Never, tty: true };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..], shell_writes("Hey Alex\n"));
});

test!(colored_shell {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Auto, tty: true };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..],
                shell_writes(colored_output("Hey Alex\n",
                                            color::RED).unwrap()));
});

test!(color_explicitly_enabled {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Always, tty: false };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..],
                shell_writes(colored_output("Hey Alex\n",
                                            color::RED).unwrap()));
});

fn colored_output(string: &str, color: color::Color) -> io::Result<String> {
    let mut term = TerminfoTerminal::new(Vec::new()).unwrap();
    try!(term.reset());
    try!(term.fg(color));
    try!(write!(&mut term, "{}", string));
    try!(term.reset());
    try!(term.flush());
    Ok(String::from_utf8_lossy(term.get_ref()).to_string())
}
<commit_msg>Add `no_term` test that ensures correct output when a `TerminfoTerminal` cannot be created.<commit_after>use std::io::prelude::*;
use std::io;
use std::sync::{Arc, Mutex};
use term::{Terminal, TerminfoTerminal, color};
use hamcrest::{assert_that};

use cargo::core::shell::{Shell, ShellConfig};
use cargo::core::shell::ColorConfig::{Auto,Always, Never};

use support::{Tap, shell_writes};

fn setup() {
}

struct Sink(Arc<Mutex<Vec<u8>>>);

impl Write for Sink {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Write::write(&mut *self.0.lock().unwrap(), data)
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

test!(non_tty {
    let config = ShellConfig { color_config: Auto, tty: false };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..], shell_writes("Hey Alex\n"));
});

test!(no_term {
    let config = ShellConfig { color_config: Always, tty: false };
    let a = Arc::new(Mutex::new(Vec::new()));

    ::std::env::remove_var("TERM");
    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..], shell_writes("Hey Alex\n"));
});

test!(color_explicitly_disabled {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Never, tty: true };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..], shell_writes("Hey Alex\n"));
});

test!(colored_shell {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Auto, tty: true };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..],
                shell_writes(colored_output("Hey Alex\n",
                                            color::RED).unwrap()));
});

test!(color_explicitly_enabled {
    let term = TerminfoTerminal::new(Vec::new());
    if term.is_none() { return }

    let config = ShellConfig { color_config: Always, tty: false };
    let a = Arc::new(Mutex::new(Vec::new()));

    Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).unwrap();
    });
    let buf = a.lock().unwrap().clone();
    assert_that(&buf[..],
                shell_writes(colored_output("Hey Alex\n",
                                            color::RED).unwrap()));
});

fn colored_output(string: &str, color: color::Color) -> io::Result<String> {
    let mut term = TerminfoTerminal::new(Vec::new()).unwrap();
    try!(term.reset());
    try!(term.fg(color));
    try!(write!(&mut term, "{}", string));
    try!(term.reset());
    try!(term.flush());
    Ok(String::from_utf8_lossy(term.get_ref()).to_string())
}
<|endoftext|>


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

use cssparser::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
pub fn log_css_error(location: SourceLocation, message: &str) {
    // TODO eventually this will got into a "web console" or something.
    if silence_errors.get().is_none() {
        info!("{:u}:{:u} {:s}", location.line, location.column, message)
    }
}

local_data_key!(silence_errors: ())

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(()));
    let result = f();
    silence_errors.replace(None);
    result
}
<commit_msg>Optimize CSS error logging: check log level before task-local silencing.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
pub fn log_css_error(location: SourceLocation, message: &str) {
    // Check this first as it’s cheaper than local_data.
    if log_enabled!(::log::INFO) {
        if silence_errors.get().is_none() {
            // TODO eventually this will got into a "web console" or something.
            info!("{:u}:{:u} {:s}", location.line, location.column, message)
        }
    }
}

local_data_key!(silence_errors: ())

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(()));
    let result = f();
    silence_errors.replace(None);
    result
}
<|endoftext|>


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

use cssparser::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

// FIXME: go back to `()` instead of `bool` after upgrading Rust
// past 898669c4e203ae91e2048fb6c0f8591c867bccc6
// Using bool is a work-around for https://github.com/mozilla/rust/issues/13322
local_data_key!(silence_errors: bool)

pub fn log_css_error(location: SourceLocation, message: &str) {
    // TODO eventually this will got into a "web console" or something.
    if silence_errors.get().is_none() {
        error!("{:u}:{:u} {:s}", location.line, location.column, message)
    }
}

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(true));
    let result = f();
    silence_errors.replace(None);
    result
}
<commit_msg>auto merge of #2445 : SimonSapin/servo/css-warnings, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
pub fn log_css_error(location: SourceLocation, message: &str) {
    // Check this first as it’s cheaper than local_data.
    if log_enabled!(::log::INFO) {
        if silence_errors.get().is_none() {
            // TODO eventually this will got into a "web console" or something.
            info!("{:u}:{:u} {:s}", location.line, location.column, message)
        }
    }
}

local_data_key!(silence_errors: ())

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(()));
    let result = f();
    silence_errors.replace(None);
    result
}
<|endoftext|>


<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.

//! Android ABI-compatibility module
//!
//! The ABI of Android has changed quite a bit over time, and libstd attempts to
//! be both forwards and backwards compatible as much as possible. We want to
//! always work with the most recent version of Android, but we also want to
//! work with older versions of Android for whenever projects need to.
//!
//! Our current minimum supported Android version is `android-9`, e.g. Android
//! with API level 9. We then in theory want to work on that and all future
//! versions of Android!
//!
//! Some of the detection here is done at runtime via `dlopen` and
//! introspection. Other times no detection is performed at all and we just
//! provide a fallback implementation as some versions of Android we support
//! don't have the function.
//!
//! You'll find more details below about why each compatibility shim is needed.

#![cfg(target_os = "android")]

use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
use libc::{ftruncate, pread, pwrite};

use convert::TryInto;
use io;
use super::{cvt, cvt_r};

// The `log2` and `log2f` functions apparently appeared in android-18, or at
// least you can see they're not present in the android-17 header [1] and they
// are present in android-18 [2].
//
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-17/arch-arm/usr/include/math.h
// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-18/arch-arm/usr/include/math.h
//
// Note that these shims are likely less precise than directly calling `log2`,
// but hopefully that should be enough for now...
//
// Note that mathematically, for any arbitrary `y`:
//
//      log_2(x) = log_y(x) / log_y(2)
//               = log_y(x) / (1 / log_2(y))
//               = log_y(x) * log_2(y)
//
// Hence because `ln` (log_e) is available on all Android we just choose `y = e`
// and get:
//
//      log_2(x) = ln(x) * log_2(e)

#[cfg(not(test))]
pub fn log2f32(f: f32) -> f32 {
    f.ln() * ::f32::consts::LOG2_E
}

#[cfg(not(test))]
pub fn log2f64(f: f64) -> f64 {
    f.ln() * ::f64::consts::LOG2_E
}

// Back in the day [1] the `signal` function was just an inline wrapper
// around `bsd_signal`, but starting in API level android-20 the `signal`
// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was
// removed [3].
//
// Basically this means that if we want to be binary compatible with multiple
// Android releases (oldest being 9 and newest being 21) then we need to check
// for both symbols and not actually link against either.
//
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-18/arch-arm/usr/include/signal.h
// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental
//                                       /platforms/android-20/arch-arm
//                                       /usr/include/signal.h
// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms
//                                       /android-21/arch-arm/usr/include/signal.h
pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
    weak!(fn signal(c_int, sighandler_t) -> sighandler_t);
    weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t);

    let f = signal.get().or_else(|| bsd_signal.get());
    let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
    f(signum, handler)
}

// The `ftruncate64` symbol apparently appeared in android-12, so we do some
// dynamic detection to see if we can figure out whether `ftruncate64` exists.
//
// If it doesn't we just fall back to `ftruncate`, generating an error for
// too-large values.
#[cfg(target_pointer_width = "32")]
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
    weak!(fn ftruncate64(c_int, i64) -> c_int);

    unsafe {
        match ftruncate64.get() {
            Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
            None => {
                if size > i32::max_value() as u64 {
                    Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "cannot truncate >2GB"))
                } else {
                    cvt_r(|| ftruncate(fd, size as i32)).map(|_| ())
                }
            }
        }
    }
}

#[cfg(target_pointer_width = "64")]
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
    unsafe {
        cvt_r(|| ftruncate(fd, size as i64)).map(|_| ())
    }
}

#[cfg(target_pointer_width = "32")]
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
        if let Ok(o) = offset.try_into() {
            cvt(pread(fd, buf, count, o))
        } else {
            Err(io::Error::new(io::ErrorKind::InvalidInput,
                               "cannot pread >2GB"))
        }
    })
}

#[cfg(target_pointer_width = "32")]
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
        if let Ok(o) = offset.try_into() {
            cvt(pwrite(fd, buf, count, o))
        } else {
            Err(io::Error::new(io::ErrorKind::InvalidInput,
                               "cannot pwrite >2GB"))
        }
    })
}

#[cfg(target_pointer_width = "64")]
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    cvt(pread(fd, buf, count, offset))
}

#[cfg(target_pointer_width = "64")]
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    cvt(pwrite(fd, buf, count, offset))
}
<commit_msg>Android: Fix unused-imports warning<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.

//! Android ABI-compatibility module
//!
//! The ABI of Android has changed quite a bit over time, and libstd attempts to
//! be both forwards and backwards compatible as much as possible. We want to
//! always work with the most recent version of Android, but we also want to
//! work with older versions of Android for whenever projects need to.
//!
//! Our current minimum supported Android version is `android-9`, e.g. Android
//! with API level 9. We then in theory want to work on that and all future
//! versions of Android!
//!
//! Some of the detection here is done at runtime via `dlopen` and
//! introspection. Other times no detection is performed at all and we just
//! provide a fallback implementation as some versions of Android we support
//! don't have the function.
//!
//! You'll find more details below about why each compatibility shim is needed.

#![cfg(target_os = "android")]

use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
use libc::{ftruncate, pread, pwrite};

use io;
use super::{cvt, cvt_r};

// The `log2` and `log2f` functions apparently appeared in android-18, or at
// least you can see they're not present in the android-17 header [1] and they
// are present in android-18 [2].
//
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-17/arch-arm/usr/include/math.h
// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-18/arch-arm/usr/include/math.h
//
// Note that these shims are likely less precise than directly calling `log2`,
// but hopefully that should be enough for now...
//
// Note that mathematically, for any arbitrary `y`:
//
//      log_2(x) = log_y(x) / log_y(2)
//               = log_y(x) / (1 / log_2(y))
//               = log_y(x) * log_2(y)
//
// Hence because `ln` (log_e) is available on all Android we just choose `y = e`
// and get:
//
//      log_2(x) = ln(x) * log_2(e)

#[cfg(not(test))]
pub fn log2f32(f: f32) -> f32 {
    f.ln() * ::f32::consts::LOG2_E
}

#[cfg(not(test))]
pub fn log2f64(f: f64) -> f64 {
    f.ln() * ::f64::consts::LOG2_E
}

// Back in the day [1] the `signal` function was just an inline wrapper
// around `bsd_signal`, but starting in API level android-20 the `signal`
// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was
// removed [3].
//
// Basically this means that if we want to be binary compatible with multiple
// Android releases (oldest being 9 and newest being 21) then we need to check
// for both symbols and not actually link against either.
//
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
//                                       /android-18/arch-arm/usr/include/signal.h
// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental
//                                       /platforms/android-20/arch-arm
//                                       /usr/include/signal.h
// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms
//                                       /android-21/arch-arm/usr/include/signal.h
pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
    weak!(fn signal(c_int, sighandler_t) -> sighandler_t);
    weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t);

    let f = signal.get().or_else(|| bsd_signal.get());
    let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
    f(signum, handler)
}

// The `ftruncate64` symbol apparently appeared in android-12, so we do some
// dynamic detection to see if we can figure out whether `ftruncate64` exists.
//
// If it doesn't we just fall back to `ftruncate`, generating an error for
// too-large values.
#[cfg(target_pointer_width = "32")]
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
    weak!(fn ftruncate64(c_int, i64) -> c_int);

    unsafe {
        match ftruncate64.get() {
            Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
            None => {
                if size > i32::max_value() as u64 {
                    Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "cannot truncate >2GB"))
                } else {
                    cvt_r(|| ftruncate(fd, size as i32)).map(|_| ())
                }
            }
        }
    }
}

#[cfg(target_pointer_width = "64")]
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
    unsafe {
        cvt_r(|| ftruncate(fd, size as i64)).map(|_| ())
    }
}

#[cfg(target_pointer_width = "32")]
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    use convert::TryInto;
    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
        if let Ok(o) = offset.try_into() {
            cvt(pread(fd, buf, count, o))
        } else {
            Err(io::Error::new(io::ErrorKind::InvalidInput,
                               "cannot pread >2GB"))
        }
    })
}

#[cfg(target_pointer_width = "32")]
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    use convert::TryInto;
    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
        if let Ok(o) = offset.try_into() {
            cvt(pwrite(fd, buf, count, o))
        } else {
            Err(io::Error::new(io::ErrorKind::InvalidInput,
                               "cannot pwrite >2GB"))
        }
    })
}

#[cfg(target_pointer_width = "64")]
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    cvt(pread(fd, buf, count, offset))
}

#[cfg(target_pointer_width = "64")]
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
    -> io::Result<ssize_t>
{
    cvt(pwrite(fd, buf, count, offset))
}
<|endoftext|>


<commit_before><commit_msg>Add URL parsing example<commit_after>// Demonstrates parsing the LDAP URL and using the results
// for performing a Search.

use ldap3::result::Result;
use ldap3::{get_url_params, LdapConn, SearchEntry};
use url::Url;

fn main() -> Result<()> {
    let url = Url::parse(
        "ldap://localhost:2389/ou=Places,dc=example,dc=org?l??(&(l=ma*)(objectClass=locality))",
    )?;
    let params = get_url_params(&url)?;
    let mut ldap = LdapConn::from_url(&url)?;
    let (rs, _res) = ldap
        .search(
            params.base.as_ref(),
            params.scope,
            params.filter.as_ref(),
            params.attrs,
        )?
        .success()?;
    for entry in rs {
        println!("{:?}", SearchEntry::construct(entry));
    }
    Ok(ldap.unbind()?)
}
<|endoftext|>


<commit_before><commit_msg>i can't understand this yet<commit_after><|endoftext|>


<commit_before><commit_msg>Add tests for `if let`<commit_after>// Copyright 2014 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.

pub fn main() {
    let x = Some(3i);
    if let Some(y) = x {
        assert_eq!(y, 3i);
    } else {
        fail!("if-let failed");
    }
    let mut worked = false;
    if let Some(_) = x {
        worked = true;
    }
    assert!(worked);
    let clause: uint;
    if let None = Some("test") {
        clause = 1;
    } else if 4u > 5 {
        clause = 2;
    } else if let Ok(()) = Err::<(),&'static str>("test") {
        clause = 3;
    } else {
        clause = 4;
    }
    assert_eq!(clause, 4u);

    if 3i > 4 {
        fail!("bad math");
    } else if let 1 = 2i {
        fail!("bad pattern match");
    }

    enum Foo {
        One,
        Two(uint),
        Three(String, int)
    }

    let foo = Three("three".to_string(), 42i);
    if let One = foo {
        fail!("bad pattern match");
    } else if let Two(_x) = foo {
        fail!("bad pattern match");
    } else if let Three(s, _) = foo {
        assert_eq!(s.as_slice(), "three");
    } else {
        fail!("bad else");
    }

    if false {
        fail!("wat");
    } else if let a@Two(_) = Two(42u) {
        if let Two(b) = a {
            assert_eq!(b, 42u);
        } else {
            fail!("fail in nested if-let");
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>add event.rs<commit_after><|endoftext|>


<commit_before><commit_msg>refactoring<commit_after><|endoftext|>


<commit_before><commit_msg>Tests - Add a test that checks the inliner behavior around Copy values<commit_after>// compile-flags: --test

#![feature(asm)]

#[test]
fn inlined_copy_args()
{
    #[inline(always)]
    fn inline_fn(mut v: u8) {
        v = 2;
        asm!("" : : "r" (v) : /*clobber*/ : "volatile");
    }
    let v = 1;
    inline_fn(v);
    assert_eq!(v, 1);
}
<|endoftext|>


<commit_before><commit_msg>Better Builtin Map Macro Syntax<commit_after><|endoftext|>


<commit_before><commit_msg>add StatusCode for CTAPI status values<commit_after>use std::cmp::Ordering;
use std::fmt;

pub enum StatusCode {
    // 0
    Ok,
    // -1
    ErrInvalid,
    // -8
    ErrCt,
    // -10
    ErrTrans,
    // -11
    ErrMemory,
    // -127
    ErrHost,
    // -18
    ErrHtsi,
}

impl StatusCode {
    pub fn to_i8(&self) -> i8 {
        match *self {
            StatusCode::Ok => 0,
            StatusCode::ErrInvalid => -1,
            StatusCode::ErrCt => -8,
            StatusCode::ErrTrans => -10,
            StatusCode::ErrMemory => -11,
            StatusCode::ErrHost => -127,
            StatusCode::ErrHtsi => -128,
        }
    }

    pub fn from_i8(n: i8) -> Option<StatusCode> {
        match n {
            0 => Some(StatusCode::Ok),
            -1 => Some(StatusCode::ErrInvalid),
            -8 => Some(StatusCode::ErrCt),
            -10 => Some(StatusCode::ErrTrans),
            -11 => Some(StatusCode::ErrMemory),
            -127 => Some(StatusCode::ErrHost),
            -128 => Some(StatusCode::ErrHtsi),
            _ => None,
        }
    }
}

impl fmt::Display for StatusCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_i8())
    }
}

impl PartialEq for StatusCode {
    #[inline]
    fn eq(&self, other: &StatusCode) -> bool {
        self.to_i8() == other.to_i8()
    }
}

impl PartialOrd for StatusCode {
    #[inline]
    fn partial_cmp(&self, other: &StatusCode) -> Option<Ordering> {
        self.to_i8().partial_cmp(&(other.to_i8()))
    }
}

impl From<StatusCode> for i8 {
    fn from(code: StatusCode) -> i8 {
        code.to_i8()
    }
}
<|endoftext|>


<commit_before><commit_msg>Day 14 solution<commit_after>// advent14.rs
// reindeer races

#[macro_use] extern crate scan_fmt;

use std::io;

fn main() {
    let mut reindeers = Vec::new();
    loop {
        let mut input = String::new();
        let result = io::stdin().read_line(&mut input);
        match result {
            Ok(byte_count) => if byte_count == 0 { break; },
            Err(_) => {
                println!("error reading from stdin");
                break;
            }
        }

        let (s, on, off) = scan_fmt!(
            &input,
            "{*} can fly {} km/s for {} seconds, but then must rest for {} seconds.",
            u32,
            u32,
            u32);
        reindeers.push(Reindeer{speed: s.unwrap(), on_time: on.unwrap(), off_time: off.unwrap()});
    }

    const RACE_TIME: u32 = 2503;

    let max = calc_max_distance(&reindeers, RACE_TIME);
    println!("{} km", max);

    // part 2
    // unspecified what happens when two reindeer are tied: I'm guessing they both get the point
    let max2 = reindeers.iter()
        .map(|r| (1..RACE_TIME)
             .map(|t| if calc_distance(r, t) == calc_max_distance(&reindeers, t) {1} else {0})
             .fold(0, |acc, x| acc + x))
        .max().unwrap();

    println!("{} points", max2);
}

struct Reindeer {
    speed: u32,
    on_time: u32,
    off_time: u32,
}

fn calc_distance(reindeer: &Reindeer, duration: u32) -> u32 {
    let cycle_time = reindeer.on_time + reindeer.off_time;
    let cycles = duration / cycle_time;
    let remainder = duration % cycle_time;

    reindeer.speed * (cycles * reindeer.on_time + std::cmp::min(reindeer.on_time, remainder))
}

fn calc_max_distance(reindeers: &Vec<Reindeer>, duration: u32) -> u32 {
    reindeers.iter().map(|r| calc_distance(r, duration)).max().unwrap()
}

#[test]
fn test_calc_distance() {
    let comet = Reindeer {speed: 14, on_time: 10, off_time: 127};
    let dancer = Reindeer {speed: 16, on_time: 11, off_time: 162};

    assert_eq!(14, calc_distance(&comet, 1));
    assert_eq!(16, calc_distance(&dancer, 1));
    assert_eq!(140, calc_distance(&comet, 10));
    assert_eq!(160, calc_distance(&dancer, 10));
    assert_eq!(140, calc_distance(&comet, 11));
    assert_eq!(176, calc_distance(&dancer, 11));
    assert_eq!(1120, calc_distance(&comet, 1000));
    assert_eq!(1056, calc_distance(&dancer, 1000));
}

#[test]
fn test_calc_max_distance() {
    let v = vec![Reindeer {speed: 14, on_time: 10, off_time: 127},
        Reindeer {speed: 16, on_time: 11, off_time: 162}];

    assert_eq!(1120, calc_max_distance(&v, 1000));
}

<|endoftext|>


<commit_before><commit_msg>Fix Colossal build to use the new Wyvern shader and render target creation<commit_after><|endoftext|>