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

use libc::{
    c_int, pthread_kill, pthread_sigmask, pthread_t, sigaction, sigaddset, sigemptyset, siginfo_t,
    sigismember, sigpending, sigset_t, sigtimedwait, timespec, EAGAIN, EINTR, EINVAL, SA_RESTART,
    SIG_BLOCK, SIG_UNBLOCK,
};

use std::fmt::{self, Display};
use std::io;
use std::mem;
use std::os::unix::thread::JoinHandleExt;
use std::ptr::{null, null_mut};
use std::result;
use std::thread::JoinHandle;

use crate::{errno, errno_result};

#[derive(Debug)]
pub enum Error {
    /// Couldn't create a sigset.
    CreateSigset(errno::Error),
    /// The wrapped signal has already been blocked.
    SignalAlreadyBlocked(c_int),
    /// Failed to check if the requested signal is in the blocked set already.
    CompareBlockedSignals(errno::Error),
    /// The signal could not be blocked.
    BlockSignal(errno::Error),
    /// The signal mask could not be retrieved.
    RetrieveSignalMask(i32),
    /// The signal could not be unblocked.
    UnblockSignal(errno::Error),
    /// Failed to wait for given signal.
    ClearWaitPending(errno::Error),
    /// Failed to get pending signals.
    ClearGetPending(errno::Error),
    /// Failed to check if given signal is in the set of pending signals.
    ClearCheckPending(errno::Error),
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            CreateSigset(e) => write!(f, "couldn't create a sigset: {}", e),
            SignalAlreadyBlocked(num) => write!(f, "signal {} already blocked", num),
            CompareBlockedSignals(e) => write!(
                f,
                "failed to check whether requested signal is in the blocked set: {}",
                e,
            ),
            BlockSignal(e) => write!(f, "signal could not be blocked: {}", e),
            RetrieveSignalMask(errno) => write!(
                f,
                "failed to retrieve signal mask: {}",
                io::Error::from_raw_os_error(*errno),
            ),
            UnblockSignal(e) => write!(f, "signal could not be unblocked: {}", e),
            ClearWaitPending(e) => write!(f, "failed to wait for given signal: {}", e),
            ClearGetPending(e) => write!(f, "failed to get pending signals: {}", e),
            ClearCheckPending(e) => write!(
                f,
                "failed to check whether given signal is in the pending set: {}",
                e,
            ),
        }
    }
}

pub type SignalResult<T> = result::Result<T, Error>;

#[link(name = "c")]
extern "C" {
    fn __libc_current_sigrtmin() -> c_int;
    fn __libc_current_sigrtmax() -> c_int;
}

/// Returns the minimum (inclusive) real-time signal number.
#[allow(non_snake_case)]
pub fn SIGRTMIN() -> c_int {
    unsafe { __libc_current_sigrtmin() }
}

/// Returns the maximum (inclusive) real-time signal number.
#[allow(non_snake_case)]
pub fn SIGRTMAX() -> c_int {
    unsafe { __libc_current_sigrtmax() }
}

fn valid_signal_num(num: c_int) -> bool {
    num >= SIGRTMIN() && num <= SIGRTMAX()
}

/// Registers `handler` as the signal handler of signum `num`.
///
/// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
///
/// This is considered unsafe because the given handler will be called asynchronously, interrupting
/// whatever the thread was doing and therefore must only do async-signal-safe operations.
pub unsafe fn register_signal_handler(
    num: c_int,
    handler: extern "C" fn() -> (),
) -> errno::Result<()> {
    if !valid_signal_num(num) {
        return Err(errno::Error::new(EINVAL));
    }

    let mut sigact: sigaction = mem::zeroed();
    sigact.sa_flags = SA_RESTART;
    sigact.sa_sigaction = handler as *const () as usize;

    let ret = sigaction(num, &sigact, null_mut());
    if ret < 0 {
        return errno_result();
    }

    Ok(())
}

/// Creates `sigset` from an array of signal numbers.
///
/// This is a helper function used when we want to manipulate signals.
pub fn create_sigset(signals: &[c_int]) -> errno::Result<sigset_t> {
    // sigset will actually be initialized by sigemptyset below.
    let mut sigset: sigset_t = unsafe { mem::zeroed() };

    // Safe - return value is checked.
    let ret = unsafe { sigemptyset(&mut sigset) };
    if ret < 0 {
        return errno_result();
    }

    for signal in signals {
        // Safe - return value is checked.
        let ret = unsafe { sigaddset(&mut sigset, *signal) };
        if ret < 0 {
            return errno_result();
        }
    }

    Ok(sigset)
}

/// Retrieves the signal mask of the current thread as a vector of c_ints.
pub fn get_blocked_signals() -> SignalResult<Vec<c_int>> {
    let mut mask = Vec::new();

    // Safe - return values are checked.
    unsafe {
        let mut old_sigset: sigset_t = mem::zeroed();
        let ret = pthread_sigmask(SIG_BLOCK, null(), &mut old_sigset as *mut sigset_t);
        if ret < 0 {
            return Err(Error::RetrieveSignalMask(ret));
        }

        for num in 0..=SIGRTMAX() {
            if sigismember(&old_sigset, num) > 0 {
                mask.push(num);
            }
        }
    }

    Ok(mask)
}

/// Masks given signal.
///
/// If signal is already blocked the call will fail with Error::SignalAlreadyBlocked
/// result.
pub fn block_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    // Safe - return values are checked.
    unsafe {
        let mut old_sigset: sigset_t = mem::zeroed();
        let ret = pthread_sigmask(SIG_BLOCK, &sigset, &mut old_sigset as *mut sigset_t);
        if ret < 0 {
            return Err(Error::BlockSignal(errno::Error::last()));
        }
        let ret = sigismember(&old_sigset, num);
        if ret < 0 {
            return Err(Error::CompareBlockedSignals(errno::Error::last()));
        } else if ret > 0 {
            return Err(Error::SignalAlreadyBlocked(num));
        }
    }
    Ok(())
}

/// Unmasks given signal.
pub fn unblock_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    // Safe - return value is checked.
    let ret = unsafe { pthread_sigmask(SIG_UNBLOCK, &sigset, null_mut()) };
    if ret < 0 {
        return Err(Error::UnblockSignal(errno::Error::last()));
    }
    Ok(())
}

/// Clears pending signal.
pub fn clear_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    while {
        // This is safe as we are rigorously checking return values
        // of libc calls.
        unsafe {
            let mut siginfo: siginfo_t = mem::zeroed();
            let ts = timespec {
                tv_sec: 0,
                tv_nsec: 0,
            };
            // Attempt to consume one instance of pending signal. If signal
            // is not pending, the call will fail with EAGAIN or EINTR.
            let ret = sigtimedwait(&sigset, &mut siginfo, &ts);
            if ret < 0 {
                let e = errno::Error::last();
                match e.errno() {
                    EAGAIN | EINTR => {}
                    _ => {
                        return Err(Error::ClearWaitPending(errno::Error::last()));
                    }
                }
            }

            // This sigset will be actually filled with `sigpending` call.
            let mut chkset: sigset_t = mem::zeroed();
            // See if more instances of the signal are pending.
            let ret = sigpending(&mut chkset);
            if ret < 0 {
                return Err(Error::ClearGetPending(errno::Error::last()));
            }

            let ret = sigismember(&chkset, num);
            if ret < 0 {
                return Err(Error::ClearCheckPending(errno::Error::last()));
            }

            // This is do-while loop condition.
            ret != 0
        }
    } {}

    Ok(())
}

/// Trait for threads that can be signalled via `pthread_kill`.
///
/// Note that this is only useful for signals between SIGRTMIN and SIGRTMAX because these are
/// guaranteed to not be used by the C runtime.
///
/// This is marked unsafe because the implementation of this trait must guarantee that the returned
/// pthread_t is valid and has a lifetime at least that of the trait object.
pub unsafe trait Killable {
    fn pthread_handle(&self) -> pthread_t;

    /// Sends the signal `num` to this killable thread.
    ///
    /// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
    fn kill(&self, num: c_int) -> errno::Result<()> {
        if !valid_signal_num(num) {
            return Err(errno::Error::new(EINVAL));
        }

        // Safe because we ensure we are using a valid pthread handle, a valid signal number, and
        // check the return result.
        let ret = unsafe { pthread_kill(self.pthread_handle(), num) };
        if ret < 0 {
            return errno_result();
        }
        Ok(())
    }
}

// Safe because we fulfill our contract of returning a genuine pthread handle.
unsafe impl<T> Killable for JoinHandle<T> {
    fn pthread_handle(&self) -> pthread_t {
        self.as_pthread_t()
    }
}
<commit_msg>sys_util: drop redundant empty return type<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use libc::{
    c_int, pthread_kill, pthread_sigmask, pthread_t, sigaction, sigaddset, sigemptyset, siginfo_t,
    sigismember, sigpending, sigset_t, sigtimedwait, timespec, EAGAIN, EINTR, EINVAL, SA_RESTART,
    SIG_BLOCK, SIG_UNBLOCK,
};

use std::fmt::{self, Display};
use std::io;
use std::mem;
use std::os::unix::thread::JoinHandleExt;
use std::ptr::{null, null_mut};
use std::result;
use std::thread::JoinHandle;

use crate::{errno, errno_result};

#[derive(Debug)]
pub enum Error {
    /// Couldn't create a sigset.
    CreateSigset(errno::Error),
    /// The wrapped signal has already been blocked.
    SignalAlreadyBlocked(c_int),
    /// Failed to check if the requested signal is in the blocked set already.
    CompareBlockedSignals(errno::Error),
    /// The signal could not be blocked.
    BlockSignal(errno::Error),
    /// The signal mask could not be retrieved.
    RetrieveSignalMask(i32),
    /// The signal could not be unblocked.
    UnblockSignal(errno::Error),
    /// Failed to wait for given signal.
    ClearWaitPending(errno::Error),
    /// Failed to get pending signals.
    ClearGetPending(errno::Error),
    /// Failed to check if given signal is in the set of pending signals.
    ClearCheckPending(errno::Error),
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            CreateSigset(e) => write!(f, "couldn't create a sigset: {}", e),
            SignalAlreadyBlocked(num) => write!(f, "signal {} already blocked", num),
            CompareBlockedSignals(e) => write!(
                f,
                "failed to check whether requested signal is in the blocked set: {}",
                e,
            ),
            BlockSignal(e) => write!(f, "signal could not be blocked: {}", e),
            RetrieveSignalMask(errno) => write!(
                f,
                "failed to retrieve signal mask: {}",
                io::Error::from_raw_os_error(*errno),
            ),
            UnblockSignal(e) => write!(f, "signal could not be unblocked: {}", e),
            ClearWaitPending(e) => write!(f, "failed to wait for given signal: {}", e),
            ClearGetPending(e) => write!(f, "failed to get pending signals: {}", e),
            ClearCheckPending(e) => write!(
                f,
                "failed to check whether given signal is in the pending set: {}",
                e,
            ),
        }
    }
}

pub type SignalResult<T> = result::Result<T, Error>;

#[link(name = "c")]
extern "C" {
    fn __libc_current_sigrtmin() -> c_int;
    fn __libc_current_sigrtmax() -> c_int;
}

/// Returns the minimum (inclusive) real-time signal number.
#[allow(non_snake_case)]
pub fn SIGRTMIN() -> c_int {
    unsafe { __libc_current_sigrtmin() }
}

/// Returns the maximum (inclusive) real-time signal number.
#[allow(non_snake_case)]
pub fn SIGRTMAX() -> c_int {
    unsafe { __libc_current_sigrtmax() }
}

fn valid_signal_num(num: c_int) -> bool {
    num >= SIGRTMIN() && num <= SIGRTMAX()
}

/// Registers `handler` as the signal handler of signum `num`.
///
/// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
///
/// This is considered unsafe because the given handler will be called asynchronously, interrupting
/// whatever the thread was doing and therefore must only do async-signal-safe operations.
pub unsafe fn register_signal_handler(num: c_int, handler: extern "C" fn()) -> errno::Result<()> {
    if !valid_signal_num(num) {
        return Err(errno::Error::new(EINVAL));
    }

    let mut sigact: sigaction = mem::zeroed();
    sigact.sa_flags = SA_RESTART;
    sigact.sa_sigaction = handler as *const () as usize;

    let ret = sigaction(num, &sigact, null_mut());
    if ret < 0 {
        return errno_result();
    }

    Ok(())
}

/// Creates `sigset` from an array of signal numbers.
///
/// This is a helper function used when we want to manipulate signals.
pub fn create_sigset(signals: &[c_int]) -> errno::Result<sigset_t> {
    // sigset will actually be initialized by sigemptyset below.
    let mut sigset: sigset_t = unsafe { mem::zeroed() };

    // Safe - return value is checked.
    let ret = unsafe { sigemptyset(&mut sigset) };
    if ret < 0 {
        return errno_result();
    }

    for signal in signals {
        // Safe - return value is checked.
        let ret = unsafe { sigaddset(&mut sigset, *signal) };
        if ret < 0 {
            return errno_result();
        }
    }

    Ok(sigset)
}

/// Retrieves the signal mask of the current thread as a vector of c_ints.
pub fn get_blocked_signals() -> SignalResult<Vec<c_int>> {
    let mut mask = Vec::new();

    // Safe - return values are checked.
    unsafe {
        let mut old_sigset: sigset_t = mem::zeroed();
        let ret = pthread_sigmask(SIG_BLOCK, null(), &mut old_sigset as *mut sigset_t);
        if ret < 0 {
            return Err(Error::RetrieveSignalMask(ret));
        }

        for num in 0..=SIGRTMAX() {
            if sigismember(&old_sigset, num) > 0 {
                mask.push(num);
            }
        }
    }

    Ok(mask)
}

/// Masks given signal.
///
/// If signal is already blocked the call will fail with Error::SignalAlreadyBlocked
/// result.
pub fn block_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    // Safe - return values are checked.
    unsafe {
        let mut old_sigset: sigset_t = mem::zeroed();
        let ret = pthread_sigmask(SIG_BLOCK, &sigset, &mut old_sigset as *mut sigset_t);
        if ret < 0 {
            return Err(Error::BlockSignal(errno::Error::last()));
        }
        let ret = sigismember(&old_sigset, num);
        if ret < 0 {
            return Err(Error::CompareBlockedSignals(errno::Error::last()));
        } else if ret > 0 {
            return Err(Error::SignalAlreadyBlocked(num));
        }
    }
    Ok(())
}

/// Unmasks given signal.
pub fn unblock_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    // Safe - return value is checked.
    let ret = unsafe { pthread_sigmask(SIG_UNBLOCK, &sigset, null_mut()) };
    if ret < 0 {
        return Err(Error::UnblockSignal(errno::Error::last()));
    }
    Ok(())
}

/// Clears pending signal.
pub fn clear_signal(num: c_int) -> SignalResult<()> {
    let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;

    while {
        // This is safe as we are rigorously checking return values
        // of libc calls.
        unsafe {
            let mut siginfo: siginfo_t = mem::zeroed();
            let ts = timespec {
                tv_sec: 0,
                tv_nsec: 0,
            };
            // Attempt to consume one instance of pending signal. If signal
            // is not pending, the call will fail with EAGAIN or EINTR.
            let ret = sigtimedwait(&sigset, &mut siginfo, &ts);
            if ret < 0 {
                let e = errno::Error::last();
                match e.errno() {
                    EAGAIN | EINTR => {}
                    _ => {
                        return Err(Error::ClearWaitPending(errno::Error::last()));
                    }
                }
            }

            // This sigset will be actually filled with `sigpending` call.
            let mut chkset: sigset_t = mem::zeroed();
            // See if more instances of the signal are pending.
            let ret = sigpending(&mut chkset);
            if ret < 0 {
                return Err(Error::ClearGetPending(errno::Error::last()));
            }

            let ret = sigismember(&chkset, num);
            if ret < 0 {
                return Err(Error::ClearCheckPending(errno::Error::last()));
            }

            // This is do-while loop condition.
            ret != 0
        }
    } {}

    Ok(())
}

/// Trait for threads that can be signalled via `pthread_kill`.
///
/// Note that this is only useful for signals between SIGRTMIN and SIGRTMAX because these are
/// guaranteed to not be used by the C runtime.
///
/// This is marked unsafe because the implementation of this trait must guarantee that the returned
/// pthread_t is valid and has a lifetime at least that of the trait object.
pub unsafe trait Killable {
    fn pthread_handle(&self) -> pthread_t;

    /// Sends the signal `num` to this killable thread.
    ///
    /// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
    fn kill(&self, num: c_int) -> errno::Result<()> {
        if !valid_signal_num(num) {
            return Err(errno::Error::new(EINVAL));
        }

        // Safe because we ensure we are using a valid pthread handle, a valid signal number, and
        // check the return result.
        let ret = unsafe { pthread_kill(self.pthread_handle(), num) };
        if ret < 0 {
            return errno_result();
        }
        Ok(())
    }
}

// Safe because we fulfill our contract of returning a genuine pthread handle.
unsafe impl<T> Killable for JoinHandle<T> {
    fn pthread_handle(&self) -> pthread_t {
        self.as_pthread_t()
    }
}
<|endoftext|>


<commit_before>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            unsafe {
                asm!(r#"
                    # Read eflags into $0 and copy into $1:
                    pushfd
                    pop     $0
                    mov     $1, $0
                    # Flip 21st bit:
                    xor     $0, 0x200000
                    # Set eflags:
                    push    $0
                    popfd
                    # Read eflags again, if cpuid is available
                    # the 21st bit will be flipped, otherwise it
                    # it will have the same value as the original in $1:
                    pushfd
                    pop     $0
                    # Xor'ing with the original eflags should have the
                    # 21st bit set to true if cpuid is available and zero
                    # otherwise. All other bits have not been modified and
                    # are zero:
                    xor     $0, $1
                    "#
                     : "=r"(result), "=r"(_temp)
                     :
                     : "cc", "memory"
                     : "intel");
            }
            // Therefore, if result is 0, the bit was not modified and cpuid is
            // not available. If cpuid is available, the bit was modified and
            // result != 0.
            result != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use coresimd::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<commit_msg>remove unnecesary unsafe block<commit_after>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            asm!(r#"
                 # Read eflags into $0 and copy into $1:
                 pushfd
                 pop     $0
                 mov     $1, $0
                 # Flip 21st bit:
                 xor     $0, 0x200000
                 # Set eflags:
                 push    $0
                 popfd
                 # Read eflags again, if cpuid is available
                 # the 21st bit will be flipped, otherwise it
                 # it will have the same value as the original in $1:
                 pushfd
                 pop     $0
                 # Xor'ing with the original eflags should have the
                 # 21st bit set to true if cpuid is available and zero
                 # otherwise. All other bits have not been modified and
                 # are zero:
                 xor     $0, $1
                 "#
                 : "=r"(result), "=r"(_temp)
                 :
                 : "cc", "memory"
                 : "intel");
            // Therefore, if result is 0, the bit was not modified and cpuid is
            // not available. If cpuid is available, the bit was modified and
            // result != 0.
            result != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use coresimd::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate rouille;

use std::io;

fn main() {
    rouille::start_server("localhost:8000", move |request| {
        let _entry = rouille::LogEntry::start(io::stdout(), request);

        if let Ok(r) = rouille::match_assets(request, "examples") {
            return r;
        }

        let response = router!(request,
            GET (/) => (|| {
                Ok(rouille::Response::redirect("/hello/world"))
            }),

            GET (/hello/world) => (|| {
                println!("hello world");
                Ok(rouille::Response::text("hello world"))
            }),

            GET (/{id}) => (|id: u32| {
                println!("u32 {:?}", id);
                Err(rouille::RouteError::WrongInput)
            }),

            GET (/{id}) => (|id: String| {
                println!("String {:?}", id);
                Ok(rouille::Response::text(format!("hello, {}", id)))
            }),

            _ => || Err(rouille::RouteError::NoRouteFound)
        );

        response.unwrap_or_else(|err| rouille::Response::from_error(&err))
    });
}
<commit_msg>Add a "/panic" route in the hello world example<commit_after>#[macro_use]
extern crate rouille;

use std::io;

fn main() {
    rouille::start_server("localhost:8000", move |request| {
        let _entry = rouille::LogEntry::start(io::stdout(), request);

        if let Ok(r) = rouille::match_assets(request, "examples") {
            return r;
        }

        let response = router!(request,
            GET (/) => (|| {
                Ok(rouille::Response::redirect("/hello/world"))
            }),

            GET (/hello/world) => (|| {
                println!("hello world");
                Ok(rouille::Response::text("hello world"))
            }),

            GET (/panic) => (|| {
                panic!("Oops!")
            }),

            GET (/{id}) => (|id: u32| {
                println!("u32 {:?}", id);
                Err(rouille::RouteError::WrongInput)
            }),

            GET (/{id}) => (|id: String| {
                println!("String {:?}", id);
                Ok(rouille::Response::text(format!("hello, {}", id)))
            }),

            _ => || Err(rouille::RouteError::NoRouteFound)
        );

        response.unwrap_or_else(|err| rouille::Response::from_error(&err))
    });
}
<|endoftext|>


<commit_before>/*
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let issues = gl.issues(issues::Listing::new()).unwrap();
    println!("issues: {:?}", issues);

    let listing = issues::Listing::new().state(issues::ListingState::Opened).clone();
    let opened_issues = gl.issues(listing).unwrap();
    println!("opened_issues: {:?}", opened_issues);

    let listing = issues::Listing::new().state(issues::ListingState::Closed).clone();
    let closed_issues = gl.issues(listing).unwrap();
    println!("closed_issues: {:?}", closed_issues);

    let listing = issues::single::Listing::new(142, 739);
    let issue = gl.issue(listing).unwrap();
    println!("issue: {:?}", issue);

    let listing = issues::group::Listing::new(21).state(issues::ListingState::Closed).clone();
    let group_issues = gl.group_issues(listing).unwrap();
    println!("group_issues: {:?}", group_issues);

    let listing = issues::project::Listing::new(142).state(issues::ListingState::Closed).clone();
    let project_issues = gl.project_issues(listing).unwrap();
    println!("project_issues: {:?}", project_issues);
}
*/

fn main() {
    println!("Merge requests disabled until API stabilizes. See projects instead.");
}
<commit_msg>Adapt `list_issues` example to new API.<commit_after>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let issues = gl.issues().list();
    println!("issues: {:?}", issues);

    let opened_issues = gl.issues().state(issues::State::Opened).list();
    println!("opened_issues: {:?}", opened_issues);

    let closed_issues = gl.issues().state(issues::State::Closed).list();
    println!("closed_issues: {:?}", closed_issues);

//     let listing = issues::single::Listing::new(142, 739);
//     let issue = gl.issue(listing).unwrap();
//     println!("issue: {:?}", issue);
//
//     let listing = issues::group::Listing::new(21).state(issues::ListingState::Closed).clone();
//     let group_issues = gl.group_issues(listing).unwrap();
//     println!("group_issues: {:?}", group_issues);
//
//     let listing = issues::project::Listing::new(142).state(issues::ListingState::Closed).clone();
//     let project_issues = gl.project_issues(listing).unwrap();
//     println!("project_issues: {:?}", project_issues);
}
<|endoftext|>


<commit_before>extern crate git2;

use git2::*;
use std::path::Path;
use scratch::Scratch;
use super::Hooks;
use super::RepoHost;
use super::ReviewUploadResult;

pub struct CentralGit
{
    branch: String,
}

impl CentralGit
{
    pub fn new(branch: &str) -> Self
    {
        CentralGit { branch: branch.to_string() }
    }
}

pub fn module_ref(module: &str, branch: &str) -> String
{
    format!("refs/centralgit/{}/##{}##", module, branch)
}

impl Hooks for CentralGit
{
    fn branch(&self) -> &str
    {
        return &self.branch;
    }

    fn review_upload(&self,
                     scratch: &Scratch,
                     host: &RepoHost,
                     newrev: Object,
                     module: &str)
        -> ReviewUploadResult
    {
        debug!(".\n\n==== Doing review upload for module {}", &module);

        let new = newrev.id();

        let (walk, initial) = if let Some(old) = scratch.tracking(host, &module, &self.branch()) {

            let old = old.id();

            if old == new {
                return ReviewUploadResult::NoChanges;
            }

            match scratch.repo.graph_descendant_of(new, old) {
                Err(_) | Ok(false) => return ReviewUploadResult::RejectNoFF,
                Ok(true) => (),
            }

            debug!("==== walking commits from {} to {}", old, new);

            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            let range = format!("{}..{}", old, new);
            walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
            walk.hide(old).expect("walk: can't hide");
            (walk, false)
        }
        else {
            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            walk.push(new).expect("walk: can't push");
            (walk, true)
        };

        let mut current =
            scratch.tracking(host, host.central(), &self.branch).expect("no central tracking").id();

        for rev in walk {
            let rev = rev.expect("walk: invalid rev");

            debug!("==== walking commit {}", rev);

            let module_commit = scratch.repo
                .find_commit(rev)
                .expect("walk: object is not actually a commit");

            if module_commit.parents().count() > 1 {
                // TODO: also do this check on pushes to cenral refs/for/branch
                // TODO: invectigate the possibility of allowing merge commits
                return ReviewUploadResult::RejectMerge;
            }

            if module != host.central() {
                debug!("==== Rewriting commit {}", rev);

                let tree = module_commit.tree().expect("walk: commit has no tree");
                let parent =
                    scratch.repo.find_commit(current).expect("walk: current object is no commit");

                let new_tree = scratch.replace_subtree(Path::new(module),
                                                       tree.id(),
                                                       &parent.tree()
                                                           .expect("walk: parent has no tree"));

                current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
            }
        }

        if module != host.central() {
            return ReviewUploadResult::Uploaded(current, initial);
        }
        else {
            return ReviewUploadResult::Central;
        }
    }

    fn pre_create_project(&self, scratch: &Scratch, rev: Oid, project: &str)
    {
        if let Ok(_) = scratch.repo.refname_to_id(&module_ref(project, &self.branch())) {
            debug!("=== module ref for {} already exists", project);
        }
        else {
            if let Some(commit) = scratch.split_subdir(&project, rev) {
                scratch.repo
                    .reference(&module_ref(project, &self.branch()),
                               commit,
                               true,
                               "subtree_split")
                    .expect("can't create reference");
            }
            else {
                debug!("=== subdir empty: {}", project);
            }
        }
    }

    fn project_created(&self, scratch: &Scratch, host: &RepoHost, _project: &str)
    {
        if let Some(rev) = scratch.tracking(host, host.central(), &self.branch()) {
            self.central_submit(scratch, host, rev);
        }
    }

    fn central_submit(&self, scratch: &Scratch, host: &RepoHost, newrev: Object)
    {
        debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

        let central_commit = newrev.as_commit().expect("could not get commit from obj");
        let central_tree = central_commit.tree().expect("commit has no tree");

        for module in host.projects() {
            if module == host.central() {
                continue;
            }
            debug!("");
            debug!("==== fetching tracking branch for module: {}", &module);
            match scratch.tracking(host, &module, &self.branch()) {
                Some(_) => (),
                None => {
                    debug!("====    no tracking branch for module {} => project does not exist \
                            or is empty",
                           &module);
                    debug!("====    initializing with subdir history");

                    self.pre_create_project(scratch, newrev.id(), &module);
                }
            };

            let module_commit_obj = if let Ok(rev) = scratch.repo
                .revparse_single(&module_ref(&module, &self.branch())) {
                debug!("=== OK module ref : {}", module);
                rev
            }
            else {
                debug!("=== NO module ref : {}", module);
                continue;
            };

            let parents = vec![module_commit_obj.as_commit()
                                   .expect("could not get commit from obj")];

            debug!("==== checking for changes in module: {:?}", module);

            // new tree is sub-tree of complete central tree
            let old_tree_id = if let Ok(tree) = parents[0].tree() {
                tree.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
                tree_entry.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            // if sha1's are equal the content is equal
            if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
                let new_tree =
                    scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
                debug!("====    commit changes module => make commit on module");
                let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
                scratch.repo
                    .reference(&module_ref(&module, &self.branch()),
                               module_commit,
                               true,
                               "rewrite")
                    .expect("can't create reference");
            }
            else {
                debug!("====    commit does not change module => skipping");
            }
        }

        for module in host.projects() {
            if let Ok(module_commit) = scratch.repo
                .refname_to_id(&module_ref(&module, &self.branch())) {
                let output = scratch.push(host,
                                          module_commit,
                                          &module,
                                          &format!("refs/heads/{}", self.branch()));
                debug!("{}", output);
            }
        }
    }
}
<commit_msg>change module-ref to be collision free<commit_after>extern crate git2;

use git2::*;
use std::path::Path;
use scratch::Scratch;
use super::Hooks;
use super::RepoHost;
use super::ReviewUploadResult;

pub struct CentralGit
{
    branch: String,
}

impl CentralGit
{
    pub fn new(branch: &str) -> Self
    {
        CentralGit { branch: branch.to_string() }
    }
}

pub fn module_ref(module: &str, branch: &str) -> String
{
    format!("refs/{}/{}/refs/heads/{}",
            "centralgit_0ee845b3_9c3f_41ee_9149_9e98a65ecf35",
            module,
            branch)
}

impl Hooks for CentralGit
{
    fn branch(&self) -> &str
    {
        return &self.branch;
    }

    fn review_upload(&self,
                     scratch: &Scratch,
                     host: &RepoHost,
                     newrev: Object,
                     module: &str)
        -> ReviewUploadResult
    {
        debug!(".\n\n==== Doing review upload for module {}", &module);

        let new = newrev.id();

        let (walk, initial) = if let Some(old) = scratch.tracking(host, &module, &self.branch()) {

            let old = old.id();

            if old == new {
                return ReviewUploadResult::NoChanges;
            }

            match scratch.repo.graph_descendant_of(new, old) {
                Err(_) | Ok(false) => return ReviewUploadResult::RejectNoFF,
                Ok(true) => (),
            }

            debug!("==== walking commits from {} to {}", old, new);

            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            let range = format!("{}..{}", old, new);
            walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
            walk.hide(old).expect("walk: can't hide");
            (walk, false)
        }
        else {
            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            walk.push(new).expect("walk: can't push");
            (walk, true)
        };

        let mut current =
            scratch.tracking(host, host.central(), &self.branch).expect("no central tracking").id();

        for rev in walk {
            let rev = rev.expect("walk: invalid rev");

            debug!("==== walking commit {}", rev);

            let module_commit = scratch.repo
                .find_commit(rev)
                .expect("walk: object is not actually a commit");

            if module_commit.parents().count() > 1 {
                // TODO: also do this check on pushes to cenral refs/for/branch
                // TODO: invectigate the possibility of allowing merge commits
                return ReviewUploadResult::RejectMerge;
            }

            if module != host.central() {
                debug!("==== Rewriting commit {}", rev);

                let tree = module_commit.tree().expect("walk: commit has no tree");
                let parent =
                    scratch.repo.find_commit(current).expect("walk: current object is no commit");

                let new_tree = scratch.replace_subtree(Path::new(module),
                                                       tree.id(),
                                                       &parent.tree()
                                                           .expect("walk: parent has no tree"));

                current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
            }
        }

        if module != host.central() {
            return ReviewUploadResult::Uploaded(current, initial);
        }
        else {
            return ReviewUploadResult::Central;
        }
    }

    fn pre_create_project(&self, scratch: &Scratch, rev: Oid, project: &str)
    {
        if let Ok(_) = scratch.repo.refname_to_id(&module_ref(project, &self.branch())) {
            debug!("=== module ref for {} already exists", project);
        }
        else {
            if let Some(commit) = scratch.split_subdir(&project, rev) {
                scratch.repo
                    .reference(&module_ref(project, &self.branch()),
                               commit,
                               true,
                               "subtree_split")
                    .expect("can't create reference");
            }
            else {
                debug!("=== subdir empty: {}", project);
            }
        }
    }

    fn project_created(&self, scratch: &Scratch, host: &RepoHost, _project: &str)
    {
        if let Some(rev) = scratch.tracking(host, host.central(), &self.branch()) {
            self.central_submit(scratch, host, rev);
        }
    }

    fn central_submit(&self, scratch: &Scratch, host: &RepoHost, newrev: Object)
    {
        debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

        let central_commit = newrev.as_commit().expect("could not get commit from obj");
        let central_tree = central_commit.tree().expect("commit has no tree");

        for module in host.projects() {
            if module == host.central() {
                continue;
            }
            debug!("");
            debug!("==== fetching tracking branch for module: {}", &module);
            match scratch.tracking(host, &module, &self.branch()) {
                Some(_) => (),
                None => {
                    debug!("====    no tracking branch for module {} => project does not exist \
                            or is empty",
                           &module);
                    debug!("====    initializing with subdir history");

                    self.pre_create_project(scratch, newrev.id(), &module);
                }
            };

            let module_commit_obj = if let Ok(rev) = scratch.repo
                .revparse_single(&module_ref(&module, &self.branch())) {
                debug!("=== OK module ref : {}", module);
                rev
            }
            else {
                debug!("=== NO module ref : {}", module);
                continue;
            };

            let parents = vec![module_commit_obj.as_commit()
                                   .expect("could not get commit from obj")];

            debug!("==== checking for changes in module: {:?}", module);

            // new tree is sub-tree of complete central tree
            let old_tree_id = if let Ok(tree) = parents[0].tree() {
                tree.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
                tree_entry.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            // if sha1's are equal the content is equal
            if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
                let new_tree =
                    scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
                debug!("====    commit changes module => make commit on module");
                let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
                scratch.repo
                    .reference(&module_ref(&module, &self.branch()),
                               module_commit,
                               true,
                               "rewrite")
                    .expect("can't create reference");
            }
            else {
                debug!("====    commit does not change module => skipping");
            }
        }

        for module in host.projects() {
            if let Ok(module_commit) = scratch.repo
                .refname_to_id(&module_ref(&module, &self.branch())) {
                let output = scratch.push(host,
                                          module_commit,
                                          &module,
                                          &format!("refs/heads/{}", self.branch()));
                debug!("{}", output);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! 64-bit wide vector types

use simd_llvm::*;

define_ty_doc! {
    f32x2, f32, f32 |
    /// A 64-bit vector with 2 `f32` lanes.
}
define_impl! { f32x2, f32, 2, i32x2, x0, x1 }

define_ty_doc! {
    u32x2, u32, u32 |
    /// A 64-bit vector with 2 `u32` lanes.
}
define_impl! { u32x2, u32, 2, i32x2, x0, x1 }

define_ty! { i32x2, i32, i32 }
define_impl! { i32x2, i32, 2, i32x2, x0, x1 }

define_ty! { u16x4, u16, u16, u16, u16 }
define_impl! { u16x4, u16, 4, i16x4, x0, x1, x2, x3 }

define_ty! { i16x4, i16, i16, i16, i16 }
define_impl! { i16x4, i16, 4, i16x4, x0, x1, x2, x3 }

define_ty! { u8x8, u8, u8, u8, u8, u8, u8, u8, u8 }
define_impl! { u8x8, u8, 8, i8x8, x0, x1, x2, x3, x4, x5, x6, x7 }

define_ty! { i8x8, i8, i8, i8, i8, i8, i8, i8, i8 }
define_impl! { i8x8, i8, 8, i8x8, x0, x1, x2, x3, x4, x5, x6, x7 }

// On `x86` corresponds to llvm's `x86_mmx` type.
define_ty_doc! {
    __m64, i64 |
    /// 64-bit wide integer vector type.
}

define_from!(u32x2, i32x2, u16x4, i16x4, u8x8, i8x8, __m64);
define_from!(i32x2, u32x2, u16x4, i16x4, u8x8, i8x8, __m64);
define_from!(u16x4, u32x2, i32x2, i16x4, u8x8, i8x8, __m64);
define_from!(i16x4, u32x2, i32x2, u16x4, u8x8, i8x8, __m64);
define_from!(u8x8, u32x2, i32x2, u16x4, i16x4, i8x8, __m64);
define_from!(i8x8, u32x2, i32x2, u16x4, i16x4, u8x8, __m64);
define_from!(__m64, i8x8, u32x2, i32x2, u16x4, i16x4, u8x8);

define_common_ops!(f32x2, u32x2, i32x2, u16x4, i16x4, u8x8, i8x8);
define_float_ops!(f32x2);
define_integer_ops!(
    (u32x2, u32),
    (i32x2, i32),
    (u16x4, u16),
    (i16x4, i16),
    (u8x8, u8),
    (i8x8, i8)
);
define_signed_integer_ops!(i32x2, i16x4, i8x8);
define_casts!(
    (f32x2, f64x2, as_f64x2),
    (f32x2, u32x2, as_u32x2),
    (f32x2, i32x2, as_i32x2),
    (u32x2, f32x2, as_f32x2),
    (u32x2, i32x2, as_i32x2),
    (i32x2, f32x2, as_f32x2),
    (i32x2, u32x2, as_u32x2),
    (u16x4, i16x4, as_i16x4),
    (i16x4, u16x4, as_u16x4),
    (u8x8, i8x8, as_i8x8),
    (i8x8, u8x8, as_u8x8),
    (i8x8, i16x8, as_i16x8),
    (u8x8, i16x8, as_i16x8),
    (i16x4, i32x4, as_i32x4),
    (i32x2, i64x2, as_i64x2),
    (u8x8, u16x8, as_u16x8),
    (u16x4, u32x4, as_u32x4),
    (u16x4, i32x4, as_i32x4),
    (u32x2, u64x2, as_u64x2),
    (u32x2, i64x2, as_i64x2) /* FIXME:
                              * (__m64, __m128i, as___m128i),
                              * (__m64, __m256i, as___m256i) */
);

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

    #[test]
    fn operators() {
        test_ops_si!(i8x8, i16x4, i32x2);
        test_ops_ui!(u8x8, u16x4, u32x2);
        test_ops_f!(f32x2);
    }
}
<commit_msg>remove unnecessary fixme<commit_after>//! 64-bit wide vector types

use simd_llvm::*;

define_ty_doc! {
    f32x2, f32, f32 |
    /// A 64-bit vector with 2 `f32` lanes.
}
define_impl! { f32x2, f32, 2, i32x2, x0, x1 }

define_ty_doc! {
    u32x2, u32, u32 |
    /// A 64-bit vector with 2 `u32` lanes.
}
define_impl! { u32x2, u32, 2, i32x2, x0, x1 }

define_ty! { i32x2, i32, i32 }
define_impl! { i32x2, i32, 2, i32x2, x0, x1 }

define_ty! { u16x4, u16, u16, u16, u16 }
define_impl! { u16x4, u16, 4, i16x4, x0, x1, x2, x3 }

define_ty! { i16x4, i16, i16, i16, i16 }
define_impl! { i16x4, i16, 4, i16x4, x0, x1, x2, x3 }

define_ty! { u8x8, u8, u8, u8, u8, u8, u8, u8, u8 }
define_impl! { u8x8, u8, 8, i8x8, x0, x1, x2, x3, x4, x5, x6, x7 }

define_ty! { i8x8, i8, i8, i8, i8, i8, i8, i8, i8 }
define_impl! { i8x8, i8, 8, i8x8, x0, x1, x2, x3, x4, x5, x6, x7 }

// On `x86` corresponds to llvm's `x86_mmx` type.
define_ty_doc! {
    __m64, i64 |
    /// 64-bit wide integer vector type.
}

define_from!(u32x2, i32x2, u16x4, i16x4, u8x8, i8x8, __m64);
define_from!(i32x2, u32x2, u16x4, i16x4, u8x8, i8x8, __m64);
define_from!(u16x4, u32x2, i32x2, i16x4, u8x8, i8x8, __m64);
define_from!(i16x4, u32x2, i32x2, u16x4, u8x8, i8x8, __m64);
define_from!(u8x8, u32x2, i32x2, u16x4, i16x4, i8x8, __m64);
define_from!(i8x8, u32x2, i32x2, u16x4, i16x4, u8x8, __m64);
define_from!(__m64, i8x8, u32x2, i32x2, u16x4, i16x4, u8x8);

define_common_ops!(f32x2, u32x2, i32x2, u16x4, i16x4, u8x8, i8x8);
define_float_ops!(f32x2);
define_integer_ops!(
    (u32x2, u32),
    (i32x2, i32),
    (u16x4, u16),
    (i16x4, i16),
    (u8x8, u8),
    (i8x8, i8)
);
define_signed_integer_ops!(i32x2, i16x4, i8x8);
define_casts!(
    (f32x2, f64x2, as_f64x2),
    (f32x2, u32x2, as_u32x2),
    (f32x2, i32x2, as_i32x2),
    (u32x2, f32x2, as_f32x2),
    (u32x2, i32x2, as_i32x2),
    (i32x2, f32x2, as_f32x2),
    (i32x2, u32x2, as_u32x2),
    (u16x4, i16x4, as_i16x4),
    (i16x4, u16x4, as_u16x4),
    (u8x8, i8x8, as_i8x8),
    (i8x8, u8x8, as_u8x8),
    (i8x8, i16x8, as_i16x8),
    (u8x8, i16x8, as_i16x8),
    (i16x4, i32x4, as_i32x4),
    (i32x2, i64x2, as_i64x2),
    (u8x8, u16x8, as_u16x8),
    (u16x4, u32x4, as_u32x4),
    (u16x4, i32x4, as_i32x4),
    (u32x2, u64x2, as_u64x2),
    (u32x2, i64x2, as_i64x2)
);

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

    #[test]
    fn operators() {
        test_ops_si!(i8x8, i16x4, i32x2);
        test_ops_ui!(u8x8, u16x4, u32x2);
        test_ops_f!(f32x2);
    }
}
<|endoftext|>


<commit_before>// pest. Elegant, efficient grammars
// Copyright (C) 2016  Dragoș Tiselice
//
// 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 std::iter::Peekable;
use std::str::{self, Chars};

use super::super::Input;

/// A `struct` useful for matching in-memory `String`s.
///
/// # Examples
///
/// ```
/// # use pest::Input;
/// # use pest::StringInput;
/// let mut input = StringInput::new("asdasdf");
///
/// assert!(input.match_string("asd"));
/// assert!(input.match_string("asdf"));
/// assert!(!input.match_string("nope"));
/// ```
pub struct StringInput {
    string: String,
    pos: usize
}

impl StringInput {
    /// Creates a new `StringInput` from a `&str`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::Input;
    /// # use pest::StringInput;
    /// let mut input = StringInput::new("asd");
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(string: &str) -> StringInput {
        StringInput {
            string: string.to_owned(),
            pos : 0
        }
    }
}

impl Input for StringInput {
    #[inline]
    fn len(&self) -> usize {
        self.string.len()
    }

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

    #[inline]
    fn pos(&self) -> usize {
        self.pos
    }

    #[inline]
    fn set_pos(&mut self, pos: usize) {
        self.pos = pos
    }

    #[inline]
    fn slice(&self, start: usize, end: usize) -> &str {
        &self.string[start..end]
    }

    #[inline]
    fn line_col(&self, pos: usize) -> (usize, usize) {
        fn find(chars: &mut Peekable<Chars>, pos: usize,
                current: (usize, usize)) -> (usize, usize) {
            if pos == 0 {
                current
            } else {
                match chars.next() {
                    Some('\r') => {
                        if let Some(&'\n') = chars.peek() {
                            chars.next();

                            if pos == 1 {
                                find(chars, pos - 1, (current.0 + 1, 1))
                            } else {
                                find(chars, pos - 2, (current.0 + 1, 1))
                            }
                        } else {
                            find(chars, pos - 1, (current.0 + 1, 1))
                        }
                    },
                    Some('\n') => find(chars, pos - 1, (current.0 + 1, 1)),
                    Some(_)    => find(chars, pos - 1, (current.0, current.1 + 1)),
                    None       => unreachable!()
                }
            }
        }

        if pos > self.string.len() {
            panic!("position out of bounds");
        }

        find(&mut self.string.chars().peekable(), pos, (1, 1))
    }

    #[inline]
    fn match_string(&mut self, string: &str) -> bool {
        let to = self.pos + string.len();

        if to <= self.string.len() {
            let slice = unsafe { self.string.slice_unchecked(self.pos, to) };
            let result = slice == string;

            if result {
                self.pos = to;
            }

            result
        } else {
            false
        }
    }

    #[inline]
    fn match_range(&mut self, left: char, right: char) -> bool {
        let len = left.len_utf8();

        if len != right.len_utf8() {
            panic!("ranges should have same-sized UTF-8 limits");
        }

        let to = self.pos + len;

        if to <= self.string.len() {
            if let Ok(string) = str::from_utf8(&self.string.as_bytes()[self.pos..to]) {
                let c = string.chars().next().unwrap();

                let result = left <= c && c <= right;

                if result {
                    self.pos += len;
                }

                result
            } else {
                false
            }
        } else {
            false
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::super::Input;
    use super::StringInput;

    #[test]
    fn empty() {
        let mut input = StringInput::new("");

        assert!(input.is_empty());
        assert!(input.match_string(""));
        assert!(!input.match_string("a"));
    }

    #[test]
    fn parts() {
        let mut input = StringInput::new("asdasdf");

        assert!(!input.is_empty());
        assert!(input.match_string("asd"));
        assert!(input.match_string("asdf"));
    }

    #[test]
    fn len() {
        assert_eq!(StringInput::new("asdasdf").len(), 7);
    }

    #[test]
    fn pos() {
        let mut input = StringInput::new("asdasdf");

        assert_eq!(input.pos(), 0);
        assert!(input.match_string("asd"));
        assert_eq!(input.pos(), 3);
        assert!(input.match_string("asdf"));
        assert_eq!(input.pos(), 7);

        input.set_pos(3);

        assert_eq!(input.pos(), 3);
        assert!(input.match_string("asdf"));
        assert_eq!(input.pos(), 7);
    }

    #[test]
    fn slice() {
        let input = StringInput::new("asdasdf");

        assert_eq!(input.slice(1, 3), "sd");
    }

    #[test]
    fn line_col() {
        let input = StringInput::new("a\rb\nc\r\nd");

        assert_eq!(input.line_col(0), (1, 1));
        assert_eq!(input.line_col(1), (1, 2));
        assert_eq!(input.line_col(2), (2, 1));
        assert_eq!(input.line_col(3), (2, 2));
        assert_eq!(input.line_col(4), (3, 1));
        assert_eq!(input.line_col(5), (3, 2));
        assert_eq!(input.line_col(6), (4, 1));
        assert_eq!(input.line_col(7), (4, 1));
        assert_eq!(input.line_col(8), (4, 2));
    }

    #[test]
    fn match_range() {
        let mut input = StringInput::new("bbbb");

        assert!(input.match_range('a', 'c'));
        assert!(input.match_range('b', 'b'));
        assert!(!input.match_range('a', 'a'));
        assert!(!input.match_range('c', 'c'));

        assert_eq!(input.pos(), 2);
    }
}
<commit_msg>Changed StringInput not to take ownership of the string input.<commit_after>// pest. Elegant, efficient grammars
// Copyright (C) 2016  Dragoș Tiselice
//
// 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 std::iter::Peekable;
use std::str::{self, Chars};

use super::super::Input;

/// A `struct` useful for matching in-memory `String`s.
///
/// # Examples
///
/// ```
/// # use pest::Input;
/// # use pest::StringInput;
/// let mut input = StringInput::new("asdasdf");
///
/// assert!(input.match_string("asd"));
/// assert!(input.match_string("asdf"));
/// assert!(!input.match_string("nope"));
/// ```
pub struct StringInput<'a> {
    string: &'a str,
    pos: usize
}

impl<'a> StringInput<'a> {
    /// Creates a new `StringInput` from a `&str`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::Input;
    /// # use pest::StringInput;
    /// let mut input = StringInput::new("asd");
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(string: &'a str) -> StringInput<'a> {
        StringInput {
            string: string,
            pos : 0
        }
    }
}

impl<'a> Input for StringInput<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.string.len()
    }

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

    #[inline]
    fn pos(&self) -> usize {
        self.pos
    }

    #[inline]
    fn set_pos(&mut self, pos: usize) {
        self.pos = pos
    }

    #[inline]
    fn slice(&self, start: usize, end: usize) -> &str {
        &self.string[start..end]
    }

    #[inline]
    fn line_col(&self, pos: usize) -> (usize, usize) {
        fn find(chars: &mut Peekable<Chars>, pos: usize,
                current: (usize, usize)) -> (usize, usize) {
            if pos == 0 {
                current
            } else {
                match chars.next() {
                    Some('\r') => {
                        if let Some(&'\n') = chars.peek() {
                            chars.next();

                            if pos == 1 {
                                find(chars, pos - 1, (current.0 + 1, 1))
                            } else {
                                find(chars, pos - 2, (current.0 + 1, 1))
                            }
                        } else {
                            find(chars, pos - 1, (current.0 + 1, 1))
                        }
                    },
                    Some('\n') => find(chars, pos - 1, (current.0 + 1, 1)),
                    Some(_)    => find(chars, pos - 1, (current.0, current.1 + 1)),
                    None       => unreachable!()
                }
            }
        }

        if pos > self.string.len() {
            panic!("position out of bounds");
        }

        find(&mut self.string.chars().peekable(), pos, (1, 1))
    }

    #[inline]
    fn match_string(&mut self, string: &str) -> bool {
        let to = self.pos + string.len();

        if to <= self.string.len() {
            let slice = unsafe { self.string.slice_unchecked(self.pos, to) };
            let result = slice == string;

            if result {
                self.pos = to;
            }

            result
        } else {
            false
        }
    }

    #[inline]
    fn match_range(&mut self, left: char, right: char) -> bool {
        let len = left.len_utf8();

        if len != right.len_utf8() {
            panic!("ranges should have same-sized UTF-8 limits");
        }

        let to = self.pos + len;

        if to <= self.string.len() {
            if let Ok(string) = str::from_utf8(&self.string.as_bytes()[self.pos..to]) {
                let c = string.chars().next().unwrap();

                let result = left <= c && c <= right;

                if result {
                    self.pos += len;
                }

                result
            } else {
                false
            }
        } else {
            false
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::super::Input;
    use super::StringInput;

    #[test]
    fn empty() {
        let mut input = StringInput::new("");

        assert!(input.is_empty());
        assert!(input.match_string(""));
        assert!(!input.match_string("a"));
    }

    #[test]
    fn parts() {
        let mut input = StringInput::new("asdasdf");

        assert!(!input.is_empty());
        assert!(input.match_string("asd"));
        assert!(input.match_string("asdf"));
    }

    #[test]
    fn len() {
        assert_eq!(StringInput::new("asdasdf").len(), 7);
    }

    #[test]
    fn pos() {
        let mut input = StringInput::new("asdasdf");

        assert_eq!(input.pos(), 0);
        assert!(input.match_string("asd"));
        assert_eq!(input.pos(), 3);
        assert!(input.match_string("asdf"));
        assert_eq!(input.pos(), 7);

        input.set_pos(3);

        assert_eq!(input.pos(), 3);
        assert!(input.match_string("asdf"));
        assert_eq!(input.pos(), 7);
    }

    #[test]
    fn slice() {
        let input = StringInput::new("asdasdf");

        assert_eq!(input.slice(1, 3), "sd");
    }

    #[test]
    fn line_col() {
        let input = StringInput::new("a\rb\nc\r\nd");

        assert_eq!(input.line_col(0), (1, 1));
        assert_eq!(input.line_col(1), (1, 2));
        assert_eq!(input.line_col(2), (2, 1));
        assert_eq!(input.line_col(3), (2, 2));
        assert_eq!(input.line_col(4), (3, 1));
        assert_eq!(input.line_col(5), (3, 2));
        assert_eq!(input.line_col(6), (4, 1));
        assert_eq!(input.line_col(7), (4, 1));
        assert_eq!(input.line_col(8), (4, 2));
    }

    #[test]
    fn match_range() {
        let mut input = StringInput::new("bbbb");

        assert!(input.match_range('a', 'c'));
        assert!(input.match_range('b', 'b'));
        assert!(!input.match_range('a', 'a'));
        assert!(!input.match_range('c', 'c'));

        assert_eq!(input.pos(), 2);
    }
}
<|endoftext|>


<commit_before>//! Graphics draw state.

/// Graphics draw state used for blending, clipping and stencil rendering.
#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)]
pub struct DrawState {
    /// Scissor mask to use. If set, no pixel outside of this
    /// rectangle (in screen space) will be written to as a result of rendering.
    pub scissor: Option<[u32; 4]>,
    /// Stencil test to use. If None, no stencil testing is done.
    pub stencil: Option<Stencil>,
    /// Blend function to use. If None, blending is disabled.
    pub blend: Option<Blend>,
}

impl Default for DrawState {
    fn default() -> Self {
        DrawState::new_alpha()
    }
}

impl DrawState {
    /// Uses alpha blending.
    pub fn new_alpha() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: None,
            scissor: None,
        }
    }

    /// Draws to stencil buffer with value 255.
    /// This can be used for clipping.
    pub fn new_clip() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Clip(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws inside the shape defined by stencil buffer.
    pub fn new_inside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Inside(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws outside the shape defined by stencil buffer.
    pub fn new_outside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Outside(255)),
            scissor: None,
        }
    }

    /// Sets blending.
    pub fn blend(mut self, blend: Blend) -> DrawState {
        self.blend = Some(blend);
        self
    }

    /// Sets scissor `[x, y, w, h]`.
    pub fn scissor(mut self, scissor: [u32; 4]) -> DrawState {
        self.scissor = Some(scissor);
        self
    }
}

/// The blend setting to use when drawing.
///
/// Using presets since some backends need one pipeline state object instance
/// per blending technique.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Blend {
    /// Alpha blending (allows semi-transparent pixels).
    ///
    /// ```not_rust
    /// new_dest_color = src_color * src_alpha + dest_color * (1 - src_alpha)
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Alpha,
    /// Additive blending.
    ///
    /// ```not_rust
    /// new_dest_color = src_color + dest_color
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Add,
    /// Screen blending.
    ///
    /// ```not_rust
    /// new_dest_color = src_color * src_alpha + dest_color
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Screen,
    /// Multiply color components.
    ///
    /// ```not_rust
    /// new_dest_color = src_color * dest_color
    /// new_dest_alpha = src_alpha * dest_alpha
    /// ```
    Multiply,
    /// Invert colors when rendering a white shape.
    ///
    /// ```not_rust
    /// new_dest_color = ref_color - src_color
    /// new_dest_alpha = dest_alpha
    /// ```
    ///
    /// When combining two fragments, subtract the destination color from a constant color
    /// using the source color as weight. Has an invert effect with the constant color
    /// as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert.
    /// The output alpha is same as destination alpha.
    Invert,
}

/// Stencil buffer settings.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Stencil {
    /// Draw to stencil buffer.
    Clip(u8),
    /// Draw pixels that have stencil value.
    Inside(u8),
    /// Draw pixels that does not have stencil value.
    Outside(u8),
}
<commit_msg>Changed name to Blend::Lighter<commit_after>//! Graphics draw state.

/// Graphics draw state used for blending, clipping and stencil rendering.
#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)]
pub struct DrawState {
    /// Scissor mask to use. If set, no pixel outside of this
    /// rectangle (in screen space) will be written to as a result of rendering.
    pub scissor: Option<[u32; 4]>,
    /// Stencil test to use. If None, no stencil testing is done.
    pub stencil: Option<Stencil>,
    /// Blend function to use. If None, blending is disabled.
    pub blend: Option<Blend>,
}

impl Default for DrawState {
    fn default() -> Self {
        DrawState::new_alpha()
    }
}

impl DrawState {
    /// Uses alpha blending.
    pub fn new_alpha() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: None,
            scissor: None,
        }
    }

    /// Draws to stencil buffer with value 255.
    /// This can be used for clipping.
    pub fn new_clip() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Clip(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws inside the shape defined by stencil buffer.
    pub fn new_inside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Inside(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws outside the shape defined by stencil buffer.
    pub fn new_outside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Outside(255)),
            scissor: None,
        }
    }

    /// Sets blending.
    pub fn blend(mut self, blend: Blend) -> DrawState {
        self.blend = Some(blend);
        self
    }

    /// Sets scissor `[x, y, w, h]`.
    pub fn scissor(mut self, scissor: [u32; 4]) -> DrawState {
        self.scissor = Some(scissor);
        self
    }
}

/// The blend setting to use when drawing.
///
/// Using presets since some backends need one pipeline state object instance
/// per blending technique.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Blend {
    /// Alpha blending (allows semi-transparent pixels).
    ///
    /// ```not_rust
    /// new_dest_color = src_color * src_alpha + dest_color * (1 - src_alpha)
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Alpha,
    /// Additive blending.
    ///
    /// ```not_rust
    /// new_dest_color = src_color + dest_color
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Add,
    /// Additive blending with alpha channel.
    ///
    /// ```not_rust
    /// new_dest_color = src_color * src_alpha + dest_color
    /// new_dest_alpha = dest_alpha
    /// ```
    Lighter,
    /// Multiply color components.
    ///
    /// ```not_rust
    /// new_dest_color = src_color * dest_color
    /// new_dest_alpha = src_alpha * dest_alpha
    /// ```
    Multiply,
    /// Invert colors when rendering a white shape.
    ///
    /// ```not_rust
    /// new_dest_color = ref_color - src_color
    /// new_dest_alpha = dest_alpha
    /// ```
    ///
    /// When combining two fragments, subtract the destination color from a constant color
    /// using the source color as weight. Has an invert effect with the constant color
    /// as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert.
    /// The output alpha is same as destination alpha.
    Invert,
}

/// Stencil buffer settings.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Stencil {
    /// Draw to stencil buffer.
    Clip(u8),
    /// Draw pixels that have stencil value.
    Inside(u8),
    /// Draw pixels that does not have stencil value.
    Outside(u8),
}
<|endoftext|>


<commit_before>// Allow zero pointers for lazy_static. Otherwise clippy will complain.
#![allow(unknown_lints)]

use serde_json;
use serde_yaml;

use std::ffi;
use std::fs;
use std::io::Write;
use std::path;

use structopt::StructOpt;

#[derive(Copy, Clone, Debug, derive_more::Display, derive_more::From, derive_more::Constructor)]
#[display(fmt = "{}", msg)]
struct Error {
    msg: &'static str,
}

impl std::error::Error for Error {}

fn load_yaml(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

fn load_json(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

fn build_context(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = if extension == ffi::OsStr::new("yaml") {
        load_yaml(path)
    } else if extension == ffi::OsStr::new("yaml") {
        load_json(path)
    } else {
        Err(Error::new("Unsupported file type"))?
    }?;

    Ok(value)
}

#[derive(StructOpt)]
struct Args {
    #[structopt(long, parse(from_os_str))]
    input: std::path::PathBuf,

    #[structopt(long, parse(from_os_str))]
    output: Option<std::path::PathBuf>,

    #[structopt(long, parse(from_os_str))]
    context: Option<std::path::PathBuf>,
}

fn run() -> Result<i32, Box<dyn std::error::Error>> {
    let args = Args::from_args();

    let parser = liquid::ParserBuilder::with_stdlib()
        .build()
        .expect("should succeed without partials");
    let template = parser.parse_file(&args.input)?;

    let data = args
        .context
        .as_ref()
        .map(|p| build_context(p.as_path()))
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Object::new);
    let output = template.render(&data)?;
    match args.output {
        Some(path) => {
            let mut out = fs::File::create(path)?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(0)
}

fn main() {
    let code = run().unwrap();
    std::process::exit(code);
}
<commit_msg>style(clippy): Fix bin<commit_after>// Allow zero pointers for lazy_static. Otherwise clippy will complain.
#![allow(unknown_lints)]

use std::ffi;
use std::fs;
use std::io::Write;
use std::path;

use structopt::StructOpt;

#[derive(Copy, Clone, Debug, derive_more::Display, derive_more::From, derive_more::Constructor)]
#[display(fmt = "{}", msg)]
struct Error {
    msg: &'static str,
}

impl std::error::Error for Error {}

fn load_yaml(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

fn load_json(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

fn build_context(path: &path::Path) -> Result<liquid::Object, Box<dyn std::error::Error>> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = match extension.to_str() {
        Some("yaml") => load_yaml(path),
        Some("json") => load_json(path),
        _ => Err(Error::new("Unsupported file type").into()),
    }?;

    Ok(value)
}

#[derive(StructOpt)]
struct Args {
    #[structopt(long, parse(from_os_str))]
    input: std::path::PathBuf,

    #[structopt(long, parse(from_os_str))]
    output: Option<std::path::PathBuf>,

    #[structopt(long, parse(from_os_str))]
    context: Option<std::path::PathBuf>,
}

fn run() -> Result<i32, Box<dyn std::error::Error>> {
    let args = Args::from_args();

    let parser = liquid::ParserBuilder::with_stdlib()
        .build()
        .expect("should succeed without partials");
    let template = parser.parse_file(&args.input)?;

    let data = args
        .context
        .as_ref()
        .map(|p| build_context(p.as_path()))
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Object::new);
    let output = template.render(&data)?;
    match args.output {
        Some(path) => {
            let mut out = fs::File::create(path)?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(0)
}

fn main() {
    let code = run().unwrap();
    std::process::exit(code);
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implements the SSA construction algorithm described in
//! "Simple and Efficient Construction of Static Single Assignment Form"

use std::collections::{HashMap, HashSet};
use super::ssa::{BBInfo, SSA, SSAMod, ValueType};

pub type VarId = usize;

pub struct PhiPlacer<'a, T: SSAMod<BBInfo = BBInfo> + 'a> {
    pub ssa: &'a mut T,
    pub variable_types: Vec<ValueType>,
    sealed_blocks: HashSet<T::ActionRef>,
    current_def: Vec<HashMap<T::ActionRef, T::ValueRef>>,
    incomplete_phis: HashMap<T::ActionRef, HashMap<VarId, T::ValueRef>>,
}

impl<'a, T: SSAMod<BBInfo=BBInfo> + 'a> PhiPlacer<'a, T> {
    pub fn new(ssa: &'a mut T) -> PhiPlacer<'a, T> {
        PhiPlacer {
            ssa: ssa,
            variable_types: Vec::new(),
            sealed_blocks: HashSet::new(),
            current_def: Vec::new(),
            incomplete_phis: HashMap::new(),
        }
    }

    pub fn add_variables(&mut self, variable_types: Vec<ValueType>) {
        for _ in &variable_types {
            self.current_def.push(HashMap::new());
        }
        self.variable_types.extend(variable_types);
    }

    pub fn write_variable(&mut self, block: T::ActionRef, variable: VarId, value: T::ValueRef) {
        assert!(!self.sealed_blocks.contains(&block));
        self.write_variable_internal(block, variable, value)
    }

    fn write_variable_internal(&mut self,
                               block: T::ActionRef,
                               variable: VarId,
                               value: T::ValueRef) {
        assert_eq!(self.ssa.get_node_data(&value).unwrap().vt,
                   self.variable_types[variable]);
        self.current_def[variable].insert(block, value);
    }

    pub fn read_variable(&mut self, block: T::ActionRef, variable: VarId) -> T::ValueRef {
        self.current_def[variable].get(&block)
            .map(|var| *var)
            .unwrap_or(self.read_variable_recursive(variable, block))
    }

    fn read_variable_recursive(&mut self, variable: VarId, block: T::ActionRef) -> T::ValueRef {
        let valtype = self.variable_types[variable];
        let val = if !self.sealed_blocks.contains(&block) {
            // Incomplete CFG
            let _val = self.ssa.add_phi(block, valtype);
            let old = self.incomplete_phis.get_mut(&block)
                .and_then(|phi| phi.insert(variable, _val));
            assert!(old.is_none());
            _val
        } else {
            let preds = self.ssa.preds_of(block);
            assert!(preds.len() > 0);
            if preds.len() == 1 {
                // Optimize the common case of one predecessor: No phi needed
                self.read_variable(preds[0], variable)
            } else {
                // Break potential cycles with operandless phi
                let _val = self.ssa.add_phi(block, valtype);
                self.write_variable_internal(block, variable, _val);
                self.add_phi_operands(block, variable, _val)
            }
        };
        self.write_variable_internal(block, variable, val);
        val
    }

    pub fn add_block(&mut self, info: BBInfo) -> T::ActionRef {
        let block = self.ssa.add_block(info);
        self.incomplete_phis.insert(block, HashMap::new());
        block
    }

    pub fn seal_block(&mut self, block: T::ActionRef) {
        let inc = self.incomplete_phis[&block].clone(); // TODO: remove clone
        for (variable, node) in inc {
            self.add_phi_operands(block, variable, node);
        }
        self.sealed_blocks.insert(block);
    }

    fn add_phi_operands(&mut self,
                        block: T::ActionRef,
                        variable: VarId,
                        phi: T::ValueRef)
                        -> T::ValueRef {
        assert!(block == self.ssa.block_of(&phi));
        // Determine operands from predecessors
        for pred in self.ssa.preds_of(block) {
            let datasource = self.read_variable(pred, variable.clone());
            self.ssa.phi_use(phi, datasource)
        }
        self.try_remove_trivial_phi(phi)
    }

    fn try_remove_trivial_phi(&mut self, phi: T::ValueRef) -> T::ValueRef {
        let undef = self.ssa.invalid_value();
        // The phi is unreachable or in the start block
        let mut same: T::ValueRef = undef;
        for op in self.ssa.args_of(phi) {
            if op == same || op == phi {
                // Unique value or self−reference
                continue;
            }
            if same != undef {
                // The phi merges at least two values: not trivial
                return phi;
            }
            same = op
        }

        if same == undef {
            let block = self.ssa.block_of(&phi);
            let valtype = self.ssa.get_node_data(&phi).ok()
                .expect("No Data associated with this node!").vt;
            same = self.ssa.add_undefined(block, valtype);
        }

        let users = self.ssa.uses_of(phi);
        // Reroute all uses of phi to same and remove phi
        self.ssa.replace(phi, same);
        // Try to recursively remove all phi users, which might have become trivial
        for use_ in users {
            if use_ == phi {
                continue;
            }
            if let Ok(_) = self.ssa.get_node_data(&use_) {
                self.try_remove_trivial_phi(use_);
            }
        }
        same
    }

    pub fn add_dynamic(&mut self) -> T::ActionRef {
        let action = self.ssa.add_dynamic();
        self.incomplete_phis.insert(action, HashMap::new());
        self.sync_register_state(action);
        action
    }

    pub fn sync_register_state(&mut self, block: T::ActionRef) {
        let rs = self.ssa.registers_at(&block);
        for var in 0..self.variable_types.len() {
            let val = self.read_variable(block, var);
            self.ssa.op_use(rs, var as u8, val);
        }
    }

// fn remove_redundant_phis(&self, phi_functions: Vec<T::ValueRef>) {
// should phi_functions be `Vec` or something else?
// let sccs = compute_phi_sccs(induced_subgraph(phi_functions));
// for scc in topological_sort(sccs) {
// processSCC(scc)
// }
// }

// fn processSCC(&self, scc) {
// if len(scc) = 1 { return } // we already handled trivial φ functions
//
// let inner = HashSet::new();
// let outerOps = HashSet::new();
//
// for phi in scc:
// isInner = True
// for operand in phi.getOperands() {
// if operand not in scc {
// outerOps.add(operand)
// isInner = False
// }
// }
// if isInner {
// inner.add(phi)
// }
//
// if len(outerOps) == 1 {
// replaceSCCByValue(scc, outerOps.pop())
// } else if len(outerOps) > 1 {
// remove_redundant_phis(inner)
// }
// }
}
<commit_msg>Fixes simple bug in read_variable<commit_after>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implements the SSA construction algorithm described in
//! "Simple and Efficient Construction of Static Single Assignment Form"

use std::collections::{HashMap, HashSet};
use super::ssa::{BBInfo, SSA, SSAMod, ValueType};

pub type VarId = usize;

pub struct PhiPlacer<'a, T: SSAMod<BBInfo = BBInfo> + 'a> {
    pub ssa: &'a mut T,
    pub variable_types: Vec<ValueType>,
    sealed_blocks: HashSet<T::ActionRef>,
    current_def: Vec<HashMap<T::ActionRef, T::ValueRef>>,
    incomplete_phis: HashMap<T::ActionRef, HashMap<VarId, T::ValueRef>>,
}

impl<'a, T: SSAMod<BBInfo=BBInfo> + 'a> PhiPlacer<'a, T> {
    pub fn new(ssa: &'a mut T) -> PhiPlacer<'a, T> {
        PhiPlacer {
            ssa: ssa,
            variable_types: Vec::new(),
            sealed_blocks: HashSet::new(),
            current_def: Vec::new(),
            incomplete_phis: HashMap::new(),
        }
    }

    pub fn add_variables(&mut self, variable_types: Vec<ValueType>) {
        for _ in &variable_types {
            self.current_def.push(HashMap::new());
        }
        self.variable_types.extend(variable_types);
    }

    pub fn write_variable(&mut self, block: T::ActionRef, variable: VarId, value: T::ValueRef) {
        assert!(!self.sealed_blocks.contains(&block));
        self.write_variable_internal(block, variable, value)
    }

    fn write_variable_internal(&mut self,
                               block: T::ActionRef,
                               variable: VarId,
                               value: T::ValueRef) {
        assert_eq!(self.ssa.get_node_data(&value).unwrap().vt,
                   self.variable_types[variable]);
        self.current_def[variable].insert(block, value);
    }

    pub fn read_variable(&mut self, block: T::ActionRef, variable: VarId) -> T::ValueRef {
        if let Some(var) = self.current_def[variable].get(&block).cloned() {
            var
        } else {
            self.read_variable_recursive(variable, block)
        }
    }

    fn read_variable_recursive(&mut self, variable: VarId, block: T::ActionRef) -> T::ValueRef {
        let valtype = self.variable_types[variable];
        let val = if !self.sealed_blocks.contains(&block) {
            // Incomplete CFG
            let _val = self.ssa.add_phi(block, valtype);
            let old = self.incomplete_phis.get_mut(&block)
                .and_then(|phi| phi.insert(variable, _val));
            assert!(old.is_none());
            _val
        } else {
            let preds = self.ssa.preds_of(block);
            if preds.len() == 1 {
                // Optimize the common case of one predecessor: No phi needed
                self.read_variable(preds[0], variable)
            } else {
                // Break potential cycles with operandless phi
                let _val = self.ssa.add_phi(block, valtype);
                self.write_variable_internal(block, variable, _val);
                self.add_phi_operands(block, variable, _val)
            }
        };
        self.write_variable_internal(block, variable, val);
        val
    }

    pub fn add_block(&mut self, info: BBInfo) -> T::ActionRef {
        let block = self.ssa.add_block(info);
        self.incomplete_phis.insert(block, HashMap::new());
        block
    }

    pub fn seal_block(&mut self, block: T::ActionRef) {
        let inc = self.incomplete_phis[&block].clone(); // TODO: remove clone
        for (variable, node) in inc {
            self.add_phi_operands(block, variable, node);
        }
        self.sealed_blocks.insert(block);
    }

    fn add_phi_operands(&mut self,
                        block: T::ActionRef,
                        variable: VarId,
                        phi: T::ValueRef)
                        -> T::ValueRef {
        assert!(block == self.ssa.block_of(&phi));
        // Determine operands from predecessors
        for pred in self.ssa.preds_of(block) {
            let datasource = self.read_variable(pred, variable.clone());
            self.ssa.phi_use(phi, datasource)
        }
        self.try_remove_trivial_phi(phi)
    }

    fn try_remove_trivial_phi(&mut self, phi: T::ValueRef) -> T::ValueRef {
        let undef = self.ssa.invalid_value();
        // The phi is unreachable or in the start block
        let mut same: T::ValueRef = undef;
        for op in self.ssa.args_of(phi) {
            if op == same || op == phi {
                // Unique value or self−reference
                continue;
            }
            if same != undef {
                // The phi merges at least two values: not trivial
                return phi;
            }
            same = op
        }

        if same == undef {
            let block = self.ssa.block_of(&phi);
            let valtype = self.ssa.get_node_data(&phi).ok()
                .expect("No Data associated with this node!").vt;
            same = self.ssa.add_undefined(block, valtype);
        }

        let users = self.ssa.uses_of(phi);
        // Reroute all uses of phi to same and remove phi
        self.ssa.replace(phi, same);
        // Try to recursively remove all phi users, which might have become trivial
        for use_ in users {
            if use_ == phi {
                continue;
            }
            if let Ok(_) = self.ssa.get_node_data(&use_) {
                self.try_remove_trivial_phi(use_);
            }
        }
        same
    }

    pub fn add_dynamic(&mut self) -> T::ActionRef {
        let action = self.ssa.add_dynamic();
        self.incomplete_phis.insert(action, HashMap::new());
        self.sync_register_state(action);
        action
    }

    pub fn sync_register_state(&mut self, block: T::ActionRef) {
        let rs = self.ssa.registers_at(&block);
        for var in 0..self.variable_types.len() {
            let val = self.read_variable(block, var);
            self.ssa.op_use(rs, var as u8, val);
        }
    }

// fn remove_redundant_phis(&self, phi_functions: Vec<T::ValueRef>) {
// should phi_functions be `Vec` or something else?
// let sccs = compute_phi_sccs(induced_subgraph(phi_functions));
// for scc in topological_sort(sccs) {
// processSCC(scc)
// }
// }

// fn processSCC(&self, scc) {
// if len(scc) = 1 { return } // we already handled trivial φ functions
//
// let inner = HashSet::new();
// let outerOps = HashSet::new();
//
// for phi in scc:
// isInner = True
// for operand in phi.getOperands() {
// if operand not in scc {
// outerOps.add(operand)
// isInner = False
// }
// }
// if isInner {
// inner.add(phi)
// }
//
// if len(outerOps) == 1 {
// replaceSCCByValue(scc, outerOps.pop())
// } else if len(outerOps) > 1 {
// remove_redundant_phis(inner)
// }
// }
}
<|endoftext|>