<commit_before>/* Copyright 2016 The encode_unicode Developers
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Boilerplatey error types

extern crate core;
use self::core::fmt::{self,Display,Formatter};
use self::core::ops::RangeInclusive;
#[cfg(feature="std")]
use std::error::Error;

macro_rules! description {($err:ty, $desc:expr) => {
    #[cfg(not(feature="std"))]
    impl $err {
        #[allow(missing_docs)]
        pub fn description(&self) -> &'static str {
            ($desc)(self)
        }
    }
    #[cfg(feature="std")]
    impl Error for $err {
        fn description(&self) -> &'static str {
            ($desc)(self)
        }
    }
    impl Display for $err {
        fn fmt(&self,  fmtr: &mut Formatter) -> fmt::Result {
            write!(fmtr, "{}", self.description())
        }
    }
}}

macro_rules! single_cause {(#[$doc1:meta] #[$doc2:meta] $err:ident => $desc:expr) => {
    // Rust 1.15 doesn't understand $(#[$doc:meta])* $:ident
    #[$doc1]
    #[$doc2]
    #[derive(Clone,Copy, Debug, PartialEq,Eq)]
    pub struct $err;
    description!{$err, |_| $desc }
}}

single_cause!{
    /// Cannot tell whether an `u16` needs an extra unit,
    /// because it's a trailing surrogate itself.
    InvalidUtf16FirstUnit => "is a trailing surrogate"
}

single_cause!{
    /// Cannot create an `Utf8Char` or `Utf16Char` from the first codepoint of a str,
    /// because there are none.
    EmptyStrError => "is empty"
}

single_cause!{
    /// Cannot create an `Utf8Char` from a standalone `u8`
    /// that is not an ASCII character.
    NonAsciiError => "is not an ASCII character"
}

single_cause!{
    /// Cannot create an `Utf16Char` from a standalone `u16` that is not a
    /// codepoint in the basic multilingual plane, but part of a suurrogate pair.
    NonBmpError => "is not a codepoint in the basic multilingual plane"
}

macro_rules! simple {(#[$tydoc:meta] $err:ident  {
                          $($(#[$vardoc:meta])* ::$variant:ident => $string:expr),+,
                      } ) => {
    #[$tydoc]
    #[derive(Clone,Copy, Debug, PartialEq,Eq)]
    pub enum $err {
        $($(#[$vardoc])* $variant),*
    }
    description!{$err, |e: &$err| match *e {$($err::$variant=>$string),*} }
}}

simple!{/// Reasons why an `u32` is not a valid UTF codepoint.
    InvalidCodepoint {
        /// It's reserved for UTF-16 surrogate pairs."
        ::Utf16Reserved => "is reserved for UTF-16 surrogate pairs",
        /// It's higher than the highest codepoint (which is 0x10ffff).
        ::TooHigh => "is higher than the highest codepoint",
    }}
use self::InvalidCodepoint::*;
impl InvalidCodepoint {
    /// Get the range of values for which this error would be given.
    pub fn error_range(self) -> RangeInclusive<u32> {match self {
        Utf16Reserved => 0xd8_00..=0xdf_ff,
        TooHigh => 0x00_10_ff_ff..=0xff_ff_ff_ff,
    }}
}

simple!{/// Reasons why a `[u16; 2]` doesn't form a valid UTF-16 codepoint.
    InvalidUtf16Array {
        /// The first unit is a trailing/low surrogate, which is never valid.
        FirstIsTrailingSurrogate => "the first unit is a trailing surrogate, which is never valid",
        /// The second unit is needed, but is not a trailing surrogate.
        SecondIsNotTrailingSurrogate => "the second unit is needed but is not a trailing surrogate",
    }}

simple!{/// Reasons why one or two `u16`s are not valid UTF-16, in sinking precedence.
    InvalidUtf16Tuple {
        /// The first unit is a trailing surrogate, which is never valid.
        ::FirstIsTrailingSurrogate => "the first unit is a trailing surrogate, which is never valid",
        /// You provided a second unit, but the first one stands on its own.
        ::SuperfluousSecond => "the second unit is superfluous",
        /// The first and only unit requires a second unit.
        ::MissingSecond => "the first unit requires a second unit",
        /// The second unit is needed and was provided, but is not a trailing surrogate.
        ::SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate",
    }}

simple!{/// Reasons why a slice of `u16`s doesn't start with valid UTF-16.
    InvalidUtf16Slice {
        /// The slice is empty.
        ::EmptySlice => "the slice is empty",
        /// The first unit is a trailing surrogate.
        ::FirstIsTrailingSurrogate => "the first unit is a trailing surrogate",
        /// The first and only unit requires a second unit.
        ::MissingSecond => "the first and only unit requires a second one",
        /// The first unit requires a second one, but it's not a trailing surrogate.
        ::SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate",
    }}

simple!{/// Types of invalid sequences encountered by `Utf16CharParser`.
    Utf16PairError {
        /// A trailing surrogate was not preceeded by a leading surrogate.
        ::UnexpectedTrailingSurrogate => "a trailing surrogate was not preceeded by a leading surrogate",
        /// A leading surrogate was followed by an unit that was not a trailing surrogate.
        ::UnmatchedLeadingSurrogate => "a leading surrogate was followed by an unit that was not a trailing surrogate",
        /// A trailing surrogate was expected when the end was reached.
        ::Incomplete => "a trailing surrogate was expected when the end was reached",
    }}

simple!{/// Reasons why `Utf8Char::from_str()` or `Utf16Char::from_str()` failed.
    FromStrError {
        /// `Utf8Char` or `Utf16Char` cannot store more than a single codepoint.
        ::MultipleCodepoints => "has more than one codepoint",
        /// `Utf8Char` or `Utf16Char` cannot be empty.
        ::Empty => "is empty",
    }}

simple!{/// Reasons why a byte is not the start of a UTF-8 codepoint.
    InvalidUtf8FirstByte {
        /// Sequences cannot be longer than 4 bytes. Is given for values >= 240.
        ::TooLongSequence => "is greater than 247 (UTF-8 sequences cannot be longer than four bytes)",
        /// This byte belongs to a previous sequence. Is given for values between 128 and 192 (exclusive).
        ::ContinuationByte => "is a continuation of a previous sequence",
    }}
use self::InvalidUtf8FirstByte::*;

macro_rules! complex {
($err:ty
 {$($sub:ty => $to:expr,)*}
 {$($desc:pat => $string:expr),+,}
 => $use_cause:expr =>
 {$($cause:pat => $result:expr),+,} $(#[$sourcedoc:meta])*
) => {
    $(impl From<$sub> for $err {
          fn from(error: $sub) -> $err {
              $to(error)
          }
      })*
    #[cfg(not(feature="std"))]
    impl $err {
        #[allow(missing_docs)]
        pub fn description(&self) -> &'static str {
            match *self{ $($desc => $string,)* }
        }
        /// A hack to avoid two Display impls
        fn cause(&self) -> Option<&Display> {None}
    }
    #[cfg(feature="std")]
    impl Error for $err {
        fn description(&self) -> &'static str {
            match *self{ $($desc => $string,)* }
        }
        $(#[$sourcedoc])*
        fn source(&self) -> Option<&(dyn Error+'static)> {
            match *self{ $($cause => $result,)* }
        }
        $(#[$sourcedoc])*
        fn cause(&self) -> Option<&dyn Error> {
            self.source()
        }
    }
    impl Display for $err {
        fn fmt(&self,  fmtr: &mut Formatter) -> fmt::Result {
            match (self.source(), $use_cause) {
                (Some(d),true) => write!(fmtr, "{}: {}", self.description(), d),
                        _      => write!(fmtr, "{}", self.description()),
            }
        }
    }
}}

/// Reasons why a byte sequence is not valid UTF-8, excluding invalid codepoint.
/// In sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8 {
    /// Something is wrong with the first byte.
    FirstByte(InvalidUtf8FirstByte),
    /// The byte at index 1...3 should be a continuation byte,
    /// but dosesn't fit the pattern 0b10xx_xxxx.
    NotAContinuationByte(usize),
    /// There are too many leading zeros: it could be a byte shorter.
    ///
    /// [Decoding this could allow someone to input otherwise prohibited
    /// characters and sequences, such as "../"](https://tools.ietf.org/html/rfc3629#section-10).
    Overlong,
}
use self::InvalidUtf8::*;
complex!{InvalidUtf8 {
        InvalidUtf8FirstByte => FirstByte,
    } {
        FirstByte(TooLongSequence) => "the first byte is greater than 239 (UTF-8 sequences cannot be longer than four bytes)",
        FirstByte(ContinuationByte) => "the first byte is a continuation of a previous sequence",
        Overlong => "the sequence contains too many zeros and could be shorter",
        NotAContinuationByte(_) => "the sequence is too short",
    } => false => {
        FirstByte(ref cause) => Some(cause),
        _ => None,
    }/// Returns `Some` if the error is a `InvalidUtf8FirstByte`.
}

/// Reasons why a byte array is not valid UTF-8, in sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8Array {
    /// Not a valid UTF-8 sequence.
    Utf8(InvalidUtf8),
    /// Not a valid unicode codepoint.
    Codepoint(InvalidCodepoint),
}
complex!{InvalidUtf8Array {
        InvalidUtf8 => InvalidUtf8Array::Utf8,
        InvalidCodepoint => InvalidUtf8Array::Codepoint,
    } {
        InvalidUtf8Array::Utf8(_) => "the sequence is invalid UTF-8",
        InvalidUtf8Array::Codepoint(_) => "the encoded codepoint is invalid",
    } => true => {
        InvalidUtf8Array::Utf8(ref u) => Some(u),
        InvalidUtf8Array::Codepoint(ref c) => Some(c),
    }/// Always returns `Some`.
}

/// Reasons why a byte slice is not valid UTF-8, in sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8Slice {
    /// Something is certainly wrong with the first byte.
    Utf8(InvalidUtf8),
    /// The encoded codepoint is invalid:
    Codepoint(InvalidCodepoint),
    /// The slice is too short; n bytes was required.
    TooShort(usize),
}
complex!{InvalidUtf8Slice {
        InvalidUtf8 => InvalidUtf8Slice::Utf8,
        InvalidCodepoint => InvalidUtf8Slice::Codepoint,
    } {
        InvalidUtf8Slice::Utf8(_) => "the sequence is invalid UTF-8",
        InvalidUtf8Slice::Codepoint(_) => "the encoded codepoint is invalid",
        InvalidUtf8Slice::TooShort(1) => "the slice is empty",
        InvalidUtf8Slice::TooShort(_) => "the slice is shorter than the sequence",
    } => true => {
        InvalidUtf8Slice::Utf8(ref u) => Some(u),
        InvalidUtf8Slice::Codepoint(ref c) => Some(c),
        InvalidUtf8Slice::TooShort(_) => None,
    }
}
<commit_msg>Error update part 1 - Use newer macro features<commit_after>/* Copyright 2016 The encode_unicode Developers
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Boilerplatey error types

extern crate core;
use self::core::fmt::{self,Display,Formatter};
use self::core::ops::RangeInclusive;
#[cfg(feature="std")]
use std::error::Error;

macro_rules! description {($err:ty, $desc:expr) => {
    #[cfg(not(feature="std"))]
    impl $err {
        #[allow(missing_docs)]
        pub fn description(&self) -> &'static str {
            ($desc)(self)
        }
    }
    #[cfg(feature="std")]
    impl Error for $err {
        fn description(&self) -> &'static str {
            ($desc)(self)
        }
    }
    impl Display for $err {
        fn fmt(&self,  fmtr: &mut Formatter) -> fmt::Result {
            write!(fmtr, "{}", self.description())
        }
    }
}}

macro_rules! single_cause {($(#[$doc:meta])* $err:ident => $desc:expr) => {
    $(#[$doc])*
    #[derive(Clone,Copy, Debug, PartialEq,Eq)]
    pub struct $err;
    description!{$err, |_| $desc }
}}

single_cause!{
    /// Cannot tell whether an `u16` needs an extra unit,
    /// because it's a trailing surrogate itself.
    InvalidUtf16FirstUnit => "is a trailing surrogate"
}

single_cause!{
    /// Cannot create an `Utf8Char` or `Utf16Char` from the first codepoint of a str,
    /// because there are none.
    EmptyStrError => "is empty"
}

single_cause!{
    /// Cannot create an `Utf8Char` from a standalone `u8`
    /// that is not an ASCII character.
    NonAsciiError => "is not an ASCII character"
}

single_cause!{
    /// Cannot create an `Utf16Char` from a standalone `u16` that is not a
    /// codepoint in the basic multilingual plane, but part of a suurrogate pair.
    NonBmpError => "is not a codepoint in the basic multilingual plane"
}

macro_rules! simple {($(#[$tydoc:meta])* $err:ident {
                          $( $(#[$vardoc:meta])* $variant:ident => $string:expr, )+
                      } ) => {
    $(#[$tydoc])*
    #[derive(Clone,Copy, Debug, PartialEq,Eq)]
    pub enum $err {
        $( $(#[$vardoc])* $variant, )*
    }
    description!{$err, |e: &$err| match *e {$($err::$variant => $string),*} }
}}

simple!{
    /// Reasons why an `u32` is not a valid Unicode codepoint. The enum values are not stable
    InvalidCodepoint {
        /// It's reserved for UTF-16 surrogate pairs."
        Utf16Reserved => "is reserved for UTF-16 surrogate pairs",
        /// It's higher than the highest codepoint (which is 0x10ffff).
        TooHigh => "is higher than the highest codepoint",
    }}
use self::InvalidCodepoint::*;
impl InvalidCodepoint {
    /// Get the range of values for which this error would be given.
    pub fn error_range(self) -> RangeInclusive<u32> {match self {
        Utf16Reserved => 0xd8_00..=0xdf_ff,
        TooHigh => 0x00_10_ff_ff..=0xff_ff_ff_ff,
    }}
}

simple!{/// Reasons why a `[u16; 2]` doesn't form a valid UTF-16 codepoint.
    InvalidUtf16Array {
        /// The first unit is a trailing/low surrogate, which is never valid.
        FirstIsTrailingSurrogate => "the first unit is a trailing surrogate, which is never valid",
        /// The second unit is needed, but is not a trailing surrogate.
        SecondIsNotTrailingSurrogate => "the second unit is needed but is not a trailing surrogate",
    }}

simple!{/// Reasons why one or two `u16`s are not valid UTF-16, in sinking precedence.
    InvalidUtf16Tuple {
        /// The first unit is a trailing/low surrogate, which is never valid.
        FirstIsTrailingSurrogate => "the first unit is a trailing / low surrogate, which is never valid",
        /// You provided a second unit, but the first one stands on its own.
        SuperfluousSecond => "the second unit is superfluous",
        /// The first and only unit requires a second unit.
        MissingSecond => "the first unit requires a second unit",
        /// The second unit is needed and was provided, but is not a trailing surrogate.
        SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate",
    }}

simple!{/// Reasons why a slice of `u16`s doesn't start with valid UTF-16.
    InvalidUtf16Slice {
        /// The slice is empty.
        EmptySlice => "the slice is empty",
        /// The first unit is a trailing surrogate.
        FirstIsTrailingSurrogate => "the first unit is a trailing surrogate",
        /// The first and only unit requires a second unit.
        MissingSecond => "the first and only unit requires a second one",
        /// The first unit requires a second one, but it's not a trailing surrogate.
        SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate",
    }}

simple!{/// Types of invalid sequences encountered by `Utf16CharDecoder`.
    Utf16PairError {
        /// A trailing surrogate was not preceeded by a leading surrogate.
        UnexpectedTrailingSurrogate => "a trailing surrogate was not preceeded by a leading surrogate",
        /// A leading surrogate was followed by an unit that was not a trailing surrogate.
        UnmatchedLeadingSurrogate => "a leading surrogate was followed by an unit that was not a trailing surrogate",
        /// A trailing surrogate was expected when the end was reached.
        Incomplete => "a trailing surrogate was expected when the end was reached",
    }}

simple!{/// Reasons why `Utf8Char::from_str()` or `Utf16Char::from_str()` failed.
    FromStrError {
        /// `Utf8Char` or `Utf16Char` cannot store more than a single codepoint.
        MultipleCodepoints => "has more than one codepoint",
        /// `Utf8Char` or `Utf16Char` cannot be empty.
        Empty => "is empty",
    }}

simple!{/// Reasons why a byte is not the start of a UTF-8 codepoint.
    InvalidUtf8FirstByte {
        /// Sequences cannot be longer than 4 bytes. Is given for values >= 240.
        TooLongSequence => "is greater than 247 (UTF-8 sequences cannot be longer than four bytes)",
        /// This byte belongs to a previous sequence. Is given for values between 128 and 192 (exclusive).
        ContinuationByte => "is a continuation of a previous sequence",
    }}
use self::InvalidUtf8FirstByte::*;

macro_rules! complex {
($err:ty
 {$($sub:ty => $to:expr,)*}
 {$($desc:pat => $string:expr),+,}
 => $use_cause:expr =>
 {$($cause:pat => $result:expr),+,} $(#[$sourcedoc:meta])*
) => {
    $(impl From<$sub> for $err {
          fn from(error: $sub) -> $err {
              $to(error)
          }
      })*
    #[cfg(not(feature="std"))]
    impl $err {
        #[allow(missing_docs)]
        pub fn description(&self) -> &'static str {
            match *self{ $($desc => $string,)* }
        }
        /// A hack to avoid two Display impls
        fn cause(&self) -> Option<&Display> {None}
    }
    #[cfg(feature="std")]
    impl Error for $err {
        fn description(&self) -> &'static str {
            match *self{ $($desc => $string,)* }
        }
        $(#[$sourcedoc])*
        fn source(&self) -> Option<&(dyn Error+'static)> {
            match *self{ $($cause => $result,)* }
        }
        $(#[$sourcedoc])*
        fn cause(&self) -> Option<&dyn Error> {
            self.source()
        }
    }
    impl Display for $err {
        fn fmt(&self,  fmtr: &mut Formatter) -> fmt::Result {
            match (self.source(), $use_cause) {
                (Some(d),true) => write!(fmtr, "{}: {}", self.description(), d),
                        _      => write!(fmtr, "{}", self.description()),
            }
        }
    }
}}

/// Reasons why a byte sequence is not valid UTF-8, excluding invalid codepoint.
/// In sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8 {
    /// Something is wrong with the first byte.
    FirstByte(InvalidUtf8FirstByte),
    /// The byte at index 1...3 should be a continuation byte,
    /// but dosesn't fit the pattern 0b10xx_xxxx.
    NotAContinuationByte(usize),
    /// There are too many leading zeros: it could be a byte shorter.
    ///
    /// [Decoding this could allow someone to input otherwise prohibited
    /// characters and sequences, such as "../"](https://tools.ietf.org/html/rfc3629#section-10).
    Overlong,
}
use self::InvalidUtf8::*;
complex!{InvalidUtf8 {
        InvalidUtf8FirstByte => FirstByte,
    } {
        FirstByte(TooLongSequence) => "the first byte is greater than 239 (UTF-8 sequences cannot be longer than four bytes)",
        FirstByte(ContinuationByte) => "the first byte is a continuation of a previous sequence",
        Overlong => "the sequence contains too many zeros and could be shorter",
        NotAContinuationByte(_) => "the sequence is too short",
    } => false => {
        FirstByte(ref cause) => Some(cause),
        _ => None,
    }/// Returns `Some` if the error is a `InvalidUtf8FirstByte`.
}

/// Reasons why a byte array is not valid UTF-8, in sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8Array {
    /// Not a valid UTF-8 sequence.
    Utf8(InvalidUtf8),
    /// Not a valid unicode codepoint.
    Codepoint(InvalidCodepoint),
}
complex!{InvalidUtf8Array {
        InvalidUtf8 => InvalidUtf8Array::Utf8,
        InvalidCodepoint => InvalidUtf8Array::Codepoint,
    } {
        InvalidUtf8Array::Utf8(_) => "the sequence is invalid UTF-8",
        InvalidUtf8Array::Codepoint(_) => "the encoded codepoint is invalid",
    } => true => {
        InvalidUtf8Array::Utf8(ref u) => Some(u),
        InvalidUtf8Array::Codepoint(ref c) => Some(c),
    }/// Always returns `Some`.
}

/// Reasons why a byte slice is not valid UTF-8, in sinking precedence.
#[derive(Clone,Copy, Debug, PartialEq,Eq)]
pub enum InvalidUtf8Slice {
    /// Something is certainly wrong with the first byte.
    Utf8(InvalidUtf8),
    /// The encoded codepoint is invalid:
    Codepoint(InvalidCodepoint),
    /// The slice is too short; n bytes was required.
    TooShort(usize),
}
complex!{InvalidUtf8Slice {
        InvalidUtf8 => InvalidUtf8Slice::Utf8,
        InvalidCodepoint => InvalidUtf8Slice::Codepoint,
    } {
        InvalidUtf8Slice::Utf8(_) => "the sequence is invalid UTF-8",
        InvalidUtf8Slice::Codepoint(_) => "the encoded codepoint is invalid",
        InvalidUtf8Slice::TooShort(1) => "the slice is empty",
        InvalidUtf8Slice::TooShort(_) => "the slice is shorter than the sequence",
    } => true => {
        InvalidUtf8Slice::Utf8(ref u) => Some(u),
        InvalidUtf8Slice::Codepoint(ref c) => Some(c),
        InvalidUtf8Slice::TooShort(_) => None,
    }
}
<|endoftext|>


<commit_before>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use mem::Mem;

use std::mem::{transmute, size_of};

pub struct Kernel {
    pub id: ll::Kernel,
}

impl Drop for Kernel {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseKernel(self.id))
                .ok().expect("error releasing kernel")
        };
    }
}

impl Clone for Kernel {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainKernel(self.id))
                .ok().expect("error retaining kernel")
        };
        Kernel{
            id: self.id,
        }
    }
}

unsafe impl Send for Kernel { }

impl Kernel {
    pub fn new(id: ll::Kernel) -> Kernel {
        Kernel{
            id: id,
        }
    }

    pub fn bind_scalar<T: Sized>(self: &mut Self, index: u32, val: &T) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<T>() as size_t, transmute(val))));
        }
        Ok(())
    }

    pub fn bind(self: &mut Self, index: u32, buf: &Mem) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<ll::Mem>() as size_t, transmute(&buf.id))));
        }
        Ok(())
    }

    pub fn bind_mut(self: &mut Self, index: u32, buf: &mut Mem) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<ll::Mem>() as size_t, transmute(&buf.id))));
        }
        Ok(())
    }
}

<commit_msg>added null buffer arguments<commit_after>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use mem::Mem;

use std::ptr;
use std::mem::{transmute, size_of};

pub struct Kernel {
    pub id: ll::Kernel,
}

impl Drop for Kernel {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseKernel(self.id))
                .ok().expect("error releasing kernel")
        };
    }
}

impl Clone for Kernel {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainKernel(self.id))
                .ok().expect("error retaining kernel")
        };
        Kernel{
            id: self.id,
        }
    }
}

unsafe impl Send for Kernel { }

impl Kernel {
    pub fn new(id: ll::Kernel) -> Kernel {
        Kernel{
            id: id,
        }
    }

    pub fn bind_null(self: &mut Self, index: u32) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<ll::Mem>() as size_t, ptr::null_mut())));
        }
        Ok(())
    }

    pub fn bind_scalar<T: Sized>(self: &mut Self, index: u32, val: &T) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<T>() as size_t, transmute(val))));
        }
        Ok(())
    }

    pub fn bind(self: &mut Self, index: u32, buf: &Mem) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<ll::Mem>() as size_t, transmute(&buf.id))));
        }
        Ok(())
    }

    pub fn bind_mut(self: &mut Self, index: u32, buf: &mut Mem) -> Result<(), Error> {
        unsafe {
            try!(Error::check(ll::clSetKernelArg(self.id, index, size_of::<ll::Mem>() as size_t, transmute(&buf.id))));
        }
        Ok(())
    }
}

<|endoftext|>


<commit_before>//! Memory layout of matrices

use lapacke;
use ndarray::*;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MatrixLayout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl MatrixLayout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            MatrixLayout::C((row, lda)) => (row, lda),
            MatrixLayout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> MatrixLayout {
        match *self {
            MatrixLayout::C(_) => MatrixLayout::C((row, col)),
            MatrixLayout::F(_) => MatrixLayout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            MatrixLayout::C((_, lda)) | MatrixLayout::F((_, lda)) => lda,
        }
    }

    pub fn len(&self) -> LEN {
        match *self {
            MatrixLayout::C((row, _)) => row,
            MatrixLayout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> lapacke::Layout {
        match *self {
            MatrixLayout::C(_) => lapacke::Layout::RowMajor,
            MatrixLayout::F(_) => lapacke::Layout::ColumnMajor,
        }
    }

    pub fn same_order(&self, other: &MatrixLayout) -> bool {
        self.lapacke_layout() == other.lapacke_layout()
    }

    pub fn as_shape(&self) -> Shape<Ix2> {
        match *self {
            MatrixLayout::C((row, col)) => (row as usize, col as usize).into_shape(),
            MatrixLayout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
        }
    }

    pub fn toggle_order(&self) -> Self {
        match *self {
            MatrixLayout::C((row, col)) => MatrixLayout::F((col, row)),
            MatrixLayout::F((col, row)) => MatrixLayout::C((row, col)),
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<MatrixLayout>;
    fn square_layout(&self) -> Result<MatrixLayout>;
    /// Returns Ok iff the matrix is square (without computing the layout).
    fn ensure_square(&self) -> Result<()>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
where
    S: Data<Elem = A>,
{
    type Elem = A;

    fn layout(&self) -> Result<MatrixLayout> {
        let shape = self.shape();
        let strides = self.strides();
        if shape[0] == strides[1] as usize {
            return Ok(MatrixLayout::F((self.cols() as i32, self.rows() as i32)));
        }
        if shape[1] == strides[0] as usize {
            return Ok(MatrixLayout::C((self.rows() as i32, self.cols() as i32)));
        }
        Err(LinalgError::InvalidStride {
            s0: strides[0],
            s1: strides[1],
        })
    }

    fn square_layout(&self) -> Result<MatrixLayout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(LinalgError::NotSquare { rows: n, cols: m })
        }
    }

    fn ensure_square(&self) -> Result<()> {
        if self.is_square() {
            Ok(())
        } else {
            Err(LinalgError::NotSquare {
                rows: self.rows() as i32,
                cols: self.cols() as i32,
            })
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self
            .as_slice_memory_order()
            .ok_or_else(|| LinalgError::MemoryNotCont)?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
where
    S: DataMut<Elem = A>,
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self
            .as_slice_memory_order_mut()
            .ok_or_else(|| LinalgError::MemoryNotCont)?)
    }
}
<commit_msg>Check LDA is zero<commit_after>//! Memory layout of matrices

use lapacke;
use ndarray::*;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MatrixLayout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl MatrixLayout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            MatrixLayout::C((row, lda)) => (row, lda),
            MatrixLayout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> MatrixLayout {
        match *self {
            MatrixLayout::C(_) => MatrixLayout::C((row, col)),
            MatrixLayout::F(_) => MatrixLayout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        std::cmp::max(
            1,
            match *self {
                MatrixLayout::C((_, lda)) | MatrixLayout::F((_, lda)) => lda,
            },
        )
    }

    pub fn len(&self) -> LEN {
        match *self {
            MatrixLayout::C((row, _)) => row,
            MatrixLayout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> lapacke::Layout {
        match *self {
            MatrixLayout::C(_) => lapacke::Layout::RowMajor,
            MatrixLayout::F(_) => lapacke::Layout::ColumnMajor,
        }
    }

    pub fn same_order(&self, other: &MatrixLayout) -> bool {
        self.lapacke_layout() == other.lapacke_layout()
    }

    pub fn as_shape(&self) -> Shape<Ix2> {
        match *self {
            MatrixLayout::C((row, col)) => (row as usize, col as usize).into_shape(),
            MatrixLayout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
        }
    }

    pub fn toggle_order(&self) -> Self {
        match *self {
            MatrixLayout::C((row, col)) => MatrixLayout::F((col, row)),
            MatrixLayout::F((col, row)) => MatrixLayout::C((row, col)),
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<MatrixLayout>;
    fn square_layout(&self) -> Result<MatrixLayout>;
    /// Returns Ok iff the matrix is square (without computing the layout).
    fn ensure_square(&self) -> Result<()>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
where
    S: Data<Elem = A>,
{
    type Elem = A;

    fn layout(&self) -> Result<MatrixLayout> {
        let shape = self.shape();
        let strides = self.strides();
        if shape[0] == strides[1] as usize {
            return Ok(MatrixLayout::F((self.cols() as i32, self.rows() as i32)));
        }
        if shape[1] == strides[0] as usize {
            return Ok(MatrixLayout::C((self.rows() as i32, self.cols() as i32)));
        }
        Err(LinalgError::InvalidStride {
            s0: strides[0],
            s1: strides[1],
        })
    }

    fn square_layout(&self) -> Result<MatrixLayout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(LinalgError::NotSquare { rows: n, cols: m })
        }
    }

    fn ensure_square(&self) -> Result<()> {
        if self.is_square() {
            Ok(())
        } else {
            Err(LinalgError::NotSquare {
                rows: self.rows() as i32,
                cols: self.cols() as i32,
            })
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self
            .as_slice_memory_order()
            .ok_or_else(|| LinalgError::MemoryNotCont)?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
where
    S: DataMut<Elem = A>,
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self
            .as_slice_memory_order_mut()
            .ok_or_else(|| LinalgError::MemoryNotCont)?)
    }
}
<|endoftext|>


<commit_before>use hir::Semantics;
use ide_db::RootDatabase;
use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Name, Pat};
use syntax::T;

use crate::{AssistContext, AssistId, AssistKind, Assists};

/// Gets a list of binders in a pattern, and whether they are mut.
fn binders_in_pat(
    acc: &mut Vec<(Name, bool)>,
    pat: &Pat,
    sem: &Semantics<RootDatabase>,
) -> Option<()> {
    use Pat::*;
    match pat {
        IdentPat(p) => {
            let ident = p.name()?;
            let ismut = p.ref_token().is_none() && p.mut_token().is_some();
            // check for const reference
            if !(p.is_simple_ident() && sem.resolve_bind_pat_to_const(p).is_some()) {
                acc.push((ident, ismut));
            }
            if let Some(inner) = p.pat() {
                binders_in_pat(acc, &inner, sem)?;
            }
            Some(())
        }
        BoxPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(()),
        OrPat(p) => {
            for p in p.pats() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        ParenPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        RangePat(p) => {
            if let Some(st) = p.start() {
                binders_in_pat(acc, &st, sem)?
            }
            if let Some(ed) = p.end() {
                binders_in_pat(acc, &ed, sem)?
            }
            Some(())
        }
        RecordPat(p) => {
            for f in p.record_pat_field_list()?.fields() {
                let pat = f.pat()?;
                binders_in_pat(acc, &pat, sem)?;
            }
            Some(())
        }
        RefPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        SlicePat(p) => {
            for p in p.pats() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        TuplePat(p) => {
            for p in p.fields() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        TupleStructPat(p) => {
            for p in p.fields() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        // don't support macro pat yet
        MacroPat(_) => None,
    }
}

fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String {
    let vars = binders
        .iter()
        .map(
            |(ident, ismut)| {
                if *ismut && addmut {
                    format!("mut {}", ident)
                } else {
                    ident.to_string()
                }
            },
        )
        .collect::<Vec<_>>()
        .join(", ");
    if binders.is_empty() {
        String::from("{}")
    } else if binders.len() == 1 {
        vars
    } else {
        format!("({})", vars)
    }
}

// Assist: convert_let_else_to_match
//
// Converts let-else statement to let statement and match expression.
//
// ```
// fn main() {
//     let Ok(mut x) = f() else$0 { return };
// }
// ```
// ->
// ```
// fn main() {
//     let mut x = match f() {
//         Ok(x) => x,
//         _ => return,
//     };
// }
// ```
pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    // should focus on else token to trigger
    let else_token = ctx.find_token_syntax_at_offset(T![else])?;
    let let_stmt = LetStmt::cast(else_token.parent()?.parent()?)?;
    let let_else_block = let_stmt.let_else()?.block_expr()?;
    let let_init = let_stmt.initializer()?;
    if let_stmt.ty().is_some() {
        // don't support let with type annotation
        return None;
    }
    let pat = let_stmt.pat()?;
    let mut binders = Vec::new();
    binders_in_pat(&mut binders, &pat, &ctx.sema)?;

    let target = let_stmt.syntax().text_range();
    acc.add(
        AssistId("convert_let_else_to_match", AssistKind::RefactorRewrite),
        "Convert let-else to let and match",
        target,
        |edit| {
            let indent_level = let_stmt.indent_level().0 as usize;
            let indent = "    ".repeat(indent_level);
            let indent1 = "    ".repeat(indent_level + 1);

            let binders_str = binders_to_str(&binders, false);
            let binders_str_mut = binders_to_str(&binders, true);

            let init_expr = let_init.syntax().text();
            let mut pat_no_mut = pat.syntax().text().to_string();
            // remove the mut from the pattern
            for (b, ismut) in binders.iter() {
                if *ismut {
                    pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string());
                }
            }

            let only_expr = let_else_block.statements().next().is_none();
            let branch2 = match &let_else_block.tail_expr() {
                Some(tail) if only_expr => format!("{},", tail.syntax().text()),
                _ => let_else_block.syntax().text().to_string(),
            };
            let replace = if binders.is_empty() {
                format!(
                    "match {init_expr} {{
{indent1}{pat_no_mut} => {binders_str}
{indent1}_ => {branch2}
{indent}}}"
                )
            } else {
                format!(
                    "let {binders_str_mut} = match {init_expr} {{
{indent1}{pat_no_mut} => {binders_str},
{indent1}_ => {branch2}
{indent}}};"
                )
            };
            edit.replace(target, replace);
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn convert_let_else_to_match_no_type_let() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let 1: u32 = v.iter().sum() else$0 { return };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_on_else() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(x) = f() else {$0 return };
}
            "#,
        );
    }

    #[test]
    fn convert_let_else_to_match_no_macropat() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let m!() = g() else$0 { return };
}
            "#,
        );
    }

    #[test]
    fn convert_let_else_to_match_target() {
        check_assist_target(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(x) = f() else$0 { continue };
}",
            "let Ok(x) = f() else { continue };",
        );
    }

    #[test]
    fn convert_let_else_to_match_basic() {
        check_assist(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(x) = f() else$0 { continue };
}",
            r"
fn main() {
    let x = match f() {
        Ok(x) => x,
        _ => continue,
    };
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_const_ref() {
        check_assist(
            convert_let_else_to_match,
            r"
enum Option<T> {
    Some(T),
    None,
}
use Option::*;
fn main() {
    let None = f() el$0se { continue };
}",
            r"
enum Option<T> {
    Some(T),
    None,
}
use Option::*;
fn main() {
    match f() {
        None => {}
        _ => continue,
    }
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_const_ref_const() {
        check_assist(
            convert_let_else_to_match,
            r"
const NEG1: i32 = -1;
fn main() {
    let NEG1 = f() el$0se { continue };
}",
            r"
const NEG1: i32 = -1;
fn main() {
    match f() {
        NEG1 => {}
        _ => continue,
    }
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_mut() {
        check_assist(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(mut x) = f() el$0se { continue };
}",
            r"
fn main() {
    let mut x = match f() {
        Ok(x) => x,
        _ => continue,
    };
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_multi_binders() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let ControlFlow::Break((x, "tag", y, ..)) = f() else$0 { g(); return };
}"#,
            r#"
fn main() {
    let (x, y) = match f() {
        ControlFlow::Break((x, "tag", y, ..)) => (x, y),
        _ => { g(); return }
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_slice() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [one, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (one, other) = match f() {
        [one, 1001, other] => (one, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_struct() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [Struct { inner: Some(it) }, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (it, other) = match f() {
        [Struct { inner: Some(it) }, 1001, other] => (it, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_struct_ident_pat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [Struct { inner }, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (inner, other) = match f() {
        [Struct { inner }, 1001, other] => (inner, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_no_binder() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let (8 | 9) = f() else$0 { panic!() };
}"#,
            r#"
fn main() {
    match f() {
        (8 | 9) => {}
        _ => panic!(),
    }
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_range() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let 1.. = f() e$0lse { return };
}"#,
            r#"
fn main() {
    match f() {
        1.. => {}
        _ => return,
    }
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_refpat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(&mut x) = f(&mut 0) else$0 { return };
}"#,
            r#"
fn main() {
    let x = match f(&mut 0) {
        Ok(&mut x) => x,
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_refmut() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(ref mut x) = f() else$0 { return };
}"#,
            r#"
fn main() {
    let x = match f() {
        Ok(ref mut x) => x,
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_atpat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let out @ Ok(ins) = f() else$0 { return };
}"#,
            r#"
fn main() {
    let (out, ins) = match f() {
        out @ Ok(ins) => (out, ins),
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_complex_init() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let v = vec![1, 2, 3];
    let &[mut x, y, ..] = &v.iter().collect::<Vec<_>>()[..] else$0 { return };
}"#,
            r#"
fn main() {
    let v = vec![1, 2, 3];
    let (mut x, y) = match &v.iter().collect::<Vec<_>>()[..] {
        &[x, y, ..] => (x, y),
        _ => return,
    };
}"#,
        );
    }
}
<commit_msg>Simplify const reference check<commit_after>use hir::Semantics;
use ide_db::RootDatabase;
use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Name, Pat};
use syntax::T;

use crate::{AssistContext, AssistId, AssistKind, Assists};

/// Gets a list of binders in a pattern, and whether they are mut.
fn binders_in_pat(
    acc: &mut Vec<(Name, bool)>,
    pat: &Pat,
    sem: &Semantics<RootDatabase>,
) -> Option<()> {
    use Pat::*;
    match pat {
        IdentPat(p) => {
            let ident = p.name()?;
            let ismut = p.ref_token().is_none() && p.mut_token().is_some();
            // check for const reference
            if sem.resolve_bind_pat_to_const(p).is_none() {
                acc.push((ident, ismut));
            }
            if let Some(inner) = p.pat() {
                binders_in_pat(acc, &inner, sem)?;
            }
            Some(())
        }
        BoxPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(()),
        OrPat(p) => {
            for p in p.pats() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        ParenPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        RangePat(p) => {
            if let Some(st) = p.start() {
                binders_in_pat(acc, &st, sem)?
            }
            if let Some(ed) = p.end() {
                binders_in_pat(acc, &ed, sem)?
            }
            Some(())
        }
        RecordPat(p) => {
            for f in p.record_pat_field_list()?.fields() {
                let pat = f.pat()?;
                binders_in_pat(acc, &pat, sem)?;
            }
            Some(())
        }
        RefPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
        SlicePat(p) => {
            for p in p.pats() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        TuplePat(p) => {
            for p in p.fields() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        TupleStructPat(p) => {
            for p in p.fields() {
                binders_in_pat(acc, &p, sem)?;
            }
            Some(())
        }
        // don't support macro pat yet
        MacroPat(_) => None,
    }
}

fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String {
    let vars = binders
        .iter()
        .map(
            |(ident, ismut)| {
                if *ismut && addmut {
                    format!("mut {}", ident)
                } else {
                    ident.to_string()
                }
            },
        )
        .collect::<Vec<_>>()
        .join(", ");
    if binders.is_empty() {
        String::from("{}")
    } else if binders.len() == 1 {
        vars
    } else {
        format!("({})", vars)
    }
}

// Assist: convert_let_else_to_match
//
// Converts let-else statement to let statement and match expression.
//
// ```
// fn main() {
//     let Ok(mut x) = f() else$0 { return };
// }
// ```
// ->
// ```
// fn main() {
//     let mut x = match f() {
//         Ok(x) => x,
//         _ => return,
//     };
// }
// ```
pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    // should focus on else token to trigger
    let else_token = ctx.find_token_syntax_at_offset(T![else])?;
    let let_stmt = LetStmt::cast(else_token.parent()?.parent()?)?;
    let let_else_block = let_stmt.let_else()?.block_expr()?;
    let let_init = let_stmt.initializer()?;
    if let_stmt.ty().is_some() {
        // don't support let with type annotation
        return None;
    }
    let pat = let_stmt.pat()?;
    let mut binders = Vec::new();
    binders_in_pat(&mut binders, &pat, &ctx.sema)?;

    let target = let_stmt.syntax().text_range();
    acc.add(
        AssistId("convert_let_else_to_match", AssistKind::RefactorRewrite),
        "Convert let-else to let and match",
        target,
        |edit| {
            let indent_level = let_stmt.indent_level().0 as usize;
            let indent = "    ".repeat(indent_level);
            let indent1 = "    ".repeat(indent_level + 1);

            let binders_str = binders_to_str(&binders, false);
            let binders_str_mut = binders_to_str(&binders, true);

            let init_expr = let_init.syntax().text();
            let mut pat_no_mut = pat.syntax().text().to_string();
            // remove the mut from the pattern
            for (b, ismut) in binders.iter() {
                if *ismut {
                    pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string());
                }
            }

            let only_expr = let_else_block.statements().next().is_none();
            let branch2 = match &let_else_block.tail_expr() {
                Some(tail) if only_expr => format!("{},", tail.syntax().text()),
                _ => let_else_block.syntax().text().to_string(),
            };
            let replace = if binders.is_empty() {
                format!(
                    "match {init_expr} {{
{indent1}{pat_no_mut} => {binders_str}
{indent1}_ => {branch2}
{indent}}}"
                )
            } else {
                format!(
                    "let {binders_str_mut} = match {init_expr} {{
{indent1}{pat_no_mut} => {binders_str},
{indent1}_ => {branch2}
{indent}}};"
                )
            };
            edit.replace(target, replace);
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn convert_let_else_to_match_no_type_let() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let 1: u32 = v.iter().sum() else$0 { return };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_on_else() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(x) = f() else {$0 return };
}
            "#,
        );
    }

    #[test]
    fn convert_let_else_to_match_no_macropat() {
        check_assist_not_applicable(
            convert_let_else_to_match,
            r#"
fn main() {
    let m!() = g() else$0 { return };
}
            "#,
        );
    }

    #[test]
    fn convert_let_else_to_match_target() {
        check_assist_target(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(x) = f() else$0 { continue };
}",
            "let Ok(x) = f() else { continue };",
        );
    }

    #[test]
    fn convert_let_else_to_match_basic() {
        check_assist(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(x) = f() else$0 { continue };
}",
            r"
fn main() {
    let x = match f() {
        Ok(x) => x,
        _ => continue,
    };
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_const_ref() {
        check_assist(
            convert_let_else_to_match,
            r"
enum Option<T> {
    Some(T),
    None,
}
use Option::*;
fn main() {
    let None = f() el$0se { continue };
}",
            r"
enum Option<T> {
    Some(T),
    None,
}
use Option::*;
fn main() {
    match f() {
        None => {}
        _ => continue,
    }
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_const_ref_const() {
        check_assist(
            convert_let_else_to_match,
            r"
const NEG1: i32 = -1;
fn main() {
    let NEG1 = f() el$0se { continue };
}",
            r"
const NEG1: i32 = -1;
fn main() {
    match f() {
        NEG1 => {}
        _ => continue,
    }
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_mut() {
        check_assist(
            convert_let_else_to_match,
            r"
fn main() {
    let Ok(mut x) = f() el$0se { continue };
}",
            r"
fn main() {
    let mut x = match f() {
        Ok(x) => x,
        _ => continue,
    };
}",
        );
    }

    #[test]
    fn convert_let_else_to_match_multi_binders() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let ControlFlow::Break((x, "tag", y, ..)) = f() else$0 { g(); return };
}"#,
            r#"
fn main() {
    let (x, y) = match f() {
        ControlFlow::Break((x, "tag", y, ..)) => (x, y),
        _ => { g(); return }
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_slice() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [one, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (one, other) = match f() {
        [one, 1001, other] => (one, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_struct() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [Struct { inner: Some(it) }, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (it, other) = match f() {
        [Struct { inner: Some(it) }, 1001, other] => (it, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_struct_ident_pat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let [Struct { inner }, 1001, other] = f() else$0 { break };
}"#,
            r#"
fn main() {
    let (inner, other) = match f() {
        [Struct { inner }, 1001, other] => (inner, other),
        _ => break,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_no_binder() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let (8 | 9) = f() else$0 { panic!() };
}"#,
            r#"
fn main() {
    match f() {
        (8 | 9) => {}
        _ => panic!(),
    }
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_range() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let 1.. = f() e$0lse { return };
}"#,
            r#"
fn main() {
    match f() {
        1.. => {}
        _ => return,
    }
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_refpat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(&mut x) = f(&mut 0) else$0 { return };
}"#,
            r#"
fn main() {
    let x = match f(&mut 0) {
        Ok(&mut x) => x,
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_refmut() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let Ok(ref mut x) = f() else$0 { return };
}"#,
            r#"
fn main() {
    let x = match f() {
        Ok(ref mut x) => x,
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_atpat() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let out @ Ok(ins) = f() else$0 { return };
}"#,
            r#"
fn main() {
    let (out, ins) = match f() {
        out @ Ok(ins) => (out, ins),
        _ => return,
    };
}"#,
        );
    }

    #[test]
    fn convert_let_else_to_match_complex_init() {
        check_assist(
            convert_let_else_to_match,
            r#"
fn main() {
    let v = vec![1, 2, 3];
    let &[mut x, y, ..] = &v.iter().collect::<Vec<_>>()[..] else$0 { return };
}"#,
            r#"
fn main() {
    let v = vec![1, 2, 3];
    let (mut x, y) = match &v.iter().collect::<Vec<_>>()[..] {
        &[x, y, ..] => (x, y),
        _ => return,
    };
}"#,
        );
    }
}
<|endoftext|>


<commit_before>extern crate specinfra;

use specinfra::backend;

#[test]
#[cfg(any(target_os="macos", target_os="linux"))]
fn file_resource() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/etc/passwd");

    assert_eq!(file.mode().unwrap(), 0o644);
    assert_eq!(file.is_file().unwrap(), true);
    assert_eq!(file.exist().unwrap(), true);
    assert_eq!(file.is_directory().unwrap(), false);
    assert_eq!(file.is_block_device().unwrap(), false);
    assert_eq!(file.is_character_device().unwrap(), false);
    assert_eq!(file.is_pipe().unwrap(), false);
    assert_eq!(file.is_socket().unwrap(), false);
    assert_eq!(file.is_symlink().unwrap(), false);
    assert_eq!(file.contents().unwrap().contains("root"), true);
    assert_eq!(file.owner().unwrap(), "root");

    let group = file.group().unwrap();
    assert!(group == "root" || group == "wheel");

    assert_eq!(file.is_readable().unwrap(), true);
    assert_eq!(file.is_readable_by_owner().unwrap(), true);
    assert_eq!(file.is_readable_by_group().unwrap(), true);
    assert_eq!(file.is_readable_by_others().unwrap(), true);
    assert_eq!(file.is_readable_by_user("root").unwrap(), true);

    assert_eq!(file.is_writable().unwrap(), true);
    assert_eq!(file.is_writable_by_owner().unwrap(), true);
    assert_eq!(file.is_writable_by_group().unwrap(), false);
    assert_eq!(file.is_writable_by_others().unwrap(), false);
    assert_eq!(file.is_writable_by_user("root").unwrap(), true);

    assert_eq!(file.md5sum().unwrap().len(), 32);
    assert_eq!(file.sha256sum().unwrap().len(), 64);

    assert!(file.size().unwrap() > 0);
}

#[test]
#[cfg(target_os="macos")]
fn file_link() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/etc");

    assert_eq!(file.linked_to().unwrap(), "private/etc");
}

#[test]
#[cfg(target_os="linux")]
fn file_link() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/var/lock");

    assert_eq!(file.linked_to().unwrap(), "/run/lock");
}
<commit_msg>Add test to check file does not exist<commit_after>extern crate specinfra;

use specinfra::backend;

#[test]
#[cfg(any(target_os="macos", target_os="linux"))]
fn file_resource() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/etc/passwd");

    assert_eq!(file.mode().unwrap(), 0o644);
    assert_eq!(file.is_file().unwrap(), true);
    assert_eq!(file.exist().unwrap(), true);
    assert_eq!(file.is_directory().unwrap(), false);
    assert_eq!(file.is_block_device().unwrap(), false);
    assert_eq!(file.is_character_device().unwrap(), false);
    assert_eq!(file.is_pipe().unwrap(), false);
    assert_eq!(file.is_socket().unwrap(), false);
    assert_eq!(file.is_symlink().unwrap(), false);
    assert_eq!(file.contents().unwrap().contains("root"), true);
    assert_eq!(file.owner().unwrap(), "root");

    let group = file.group().unwrap();
    assert!(group == "root" || group == "wheel");

    assert_eq!(file.is_readable().unwrap(), true);
    assert_eq!(file.is_readable_by_owner().unwrap(), true);
    assert_eq!(file.is_readable_by_group().unwrap(), true);
    assert_eq!(file.is_readable_by_others().unwrap(), true);
    assert_eq!(file.is_readable_by_user("root").unwrap(), true);

    assert_eq!(file.is_writable().unwrap(), true);
    assert_eq!(file.is_writable_by_owner().unwrap(), true);
    assert_eq!(file.is_writable_by_group().unwrap(), false);
    assert_eq!(file.is_writable_by_others().unwrap(), false);
    assert_eq!(file.is_writable_by_user("root").unwrap(), true);

    assert_eq!(file.md5sum().unwrap().len(), 32);
    assert_eq!(file.sha256sum().unwrap().len(), 64);

    assert!(file.size().unwrap() > 0);
}

#[test]
fn file_not_exist() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("file_does_not_exist");

    assert_eq!(file.exist().unwrap(), false);
}

#[test]
#[cfg(target_os="macos")]
fn file_link() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/etc");

    assert_eq!(file.linked_to().unwrap(), "private/etc");
}

#[test]
#[cfg(target_os="linux")]
fn file_link() {
    let b = backend::direct::Direct::new();
    let s = specinfra::new(&b).unwrap();
    let file = s.file("/var/lock");

    assert_eq!(file.linked_to().unwrap(), "/run/lock");
}
<|endoftext|>


<commit_before>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::Ord;
use stream::HasNext;
use parse_error::ParseError;
use parse_success::ParseSuccess;

pub type ParseResult<S, T> = Result<ParseSuccess<S, T>, ParseError<S>>;

pub struct ParseState<S, T>
{
  /// Even in case of success, we keep error information in case we
  /// fail later. Think about parsing "abaa" with `"ab"* r2`, if `r2`
  /// directly fails, it is better to report an error such as:
  /// `expected "ab" but got "aa"` since the input partially matches "ab".
  pub error: ParseError<S>,
  pub success: Option<ParseSuccess<S, T>>
}

impl<S, T> ParseState<S, T> where
 S: Clone
{
  #[inline]
  pub fn success(stream: S, data: T) -> ParseState<S, T> {
    ParseState {
      error: ParseError::empty(stream.clone()),
      success: Some(ParseSuccess::new(stream, data))
    }
  }

  #[inline]
  pub fn stream(&self) -> S {
    self.assert_success("stream");
    self.success.as_ref().unwrap().stream.clone()
  }
}

impl<S, T> ParseState<S, T>
{
  #[inline]
  pub fn from_error(error: ParseError<S>) -> ParseState<S, T> {
    ParseState {
      error: error,
      success: None
    }
  }

  #[inline]
  pub fn error(stream: S, expect: &'static str) -> ParseState<S, T> {
    ParseState::from_error(ParseError::unique(stream, expect))
  }

  #[inline]
  pub fn empty_error(stream: S) -> ParseState<S, T> {
    ParseState {
      error: ParseError::empty(stream),
      success: None
    }
  }

  #[inline]
  pub fn map<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(ParseSuccess<S, T>) -> ParseSuccess<S, U>
  {
    ParseState {
      error: self.error,
      success: self.success.map(op)
    }
  }

  #[inline]
  pub fn map_data<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(T) -> U
  {
    ParseState {
      error: self.error,
      success: self.success.map(|success| success.map(op))
    }
  }

  #[inline]
  pub fn or_else<F>(self, op: F) -> ParseState<S, T> where
   F: FnOnce(ParseError<S>) -> ParseState<S, T>
  {
    match &self.success {
      &Some(_) => self,
      &None => op(self.error)
    }
  }

  #[inline]
  pub fn map_or_else<U, D, F>(self, default: D, f: F) -> ParseState<S, U> where
   D: FnOnce() -> ParseSuccess<S, U>,
   F: FnOnce(ParseSuccess<S, T>) -> ParseSuccess<S, U>
  {
    ParseState {
      error: self.error,
      success: Some(self.success.map_or_else(default, f))
    }
  }

  #[inline]
  pub fn to_error(mut self) -> ParseState<S, T> {
    self.success = None;
    self
  }

  pub fn into_result(self) -> ParseResult<S, T> {
    match self.success {
      Some(success) => {
        Ok(success)
      },
      None => {
        Err(self.error)
      }
    }
  }

  pub fn is_successful(&self) -> bool {
    self.success.is_some()
  }

  fn assert_success(&self, from: &str) {
    debug_assert!(self.is_successful(),
      "`{}`: `self` is required to be in a successful state.", from);
  }
}

impl<S, T> ParseState<S, T> where
 S: HasNext
{
  #[inline]
  pub fn has_successor(&self) -> bool {
    self.success.as_ref().map_or(false, |success| success.stream.has_next())
  }
}

impl<S, T> ParseState<S, T> where
 S: Eq
{
  pub fn stream_eq(&self, other: &S) -> bool {
    self.success.as_ref().map_or(false, |success| &success.stream == other)
  }
}

impl<S, T> ParseState<S, T> where
 S: Ord
{
  #[inline]
  pub fn and_then<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(ParseSuccess<S, T>) -> ParseState<S, U>
  {
    match self.success {
      Some(success) => {
        op(success).join(self.error)
      }
      None => ParseState::from_error(self.error)
    }
  }

  #[inline]
  pub fn or_else_join<F>(self, op: F) -> ParseState<S, T> where
   F: FnOnce() -> ParseState<S, T>
  {
    self.or_else(|err| op().join(err))
  }

  #[inline]
  pub fn join(mut self, error: ParseError<S>) -> ParseState<S, T> {
    self.error = self.error.join(error);
    self
  }
}

impl<S> ParseState<S, ()> where
 S: Clone
{
  #[inline]
  pub fn stateless(stream: S) -> ParseState<S, ()> {
    ParseState::success(stream, ())
  }
}

impl<S> ParseState<S, ()>
{
  #[inline]
  pub fn or_stateless(self, stream: S) -> ParseState<S, ()> {
    ParseState {
      error: self.error,
      success: self.success.or(Some(ParseSuccess::stateless(stream)))
    }
  }

  #[inline]
  pub fn merge_success(&mut self, other: ParseSuccess<S, ()>)
  {
    self.assert_success("ParseState<S, ()>::merge_success");
    self.success = Some(other);
  }
}

impl<S, T> ParseState<S, Vec<T>>
{
  #[inline]
  pub fn merge_success(&mut self, other: ParseSuccess<S, T>)
  {
    self.assert_success("ParseState<S, Vec<T>>::merge_success");
    let success = self.success.as_mut().unwrap();
    success.data.push(other.data);
    success.stream = other.stream;
  }
}
<commit_msg>[Runtime] Add unwrap_data convenience function.<commit_after>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::Ord;
use stream::HasNext;
use parse_error::ParseError;
use parse_success::ParseSuccess;

pub type ParseResult<S, T> = Result<ParseSuccess<S, T>, ParseError<S>>;

pub struct ParseState<S, T>
{
  /// Even in case of success, we keep error information in case we
  /// fail later. Think about parsing "abaa" with `"ab"* r2`, if `r2`
  /// directly fails, it is better to report an error such as:
  /// `expected "ab" but got "aa"` since the input partially matches "ab".
  pub error: ParseError<S>,
  pub success: Option<ParseSuccess<S, T>>
}

impl<S, T> ParseState<S, T> where
 S: Clone
{
  #[inline]
  pub fn success(stream: S, data: T) -> ParseState<S, T> {
    ParseState {
      error: ParseError::empty(stream.clone()),
      success: Some(ParseSuccess::new(stream, data))
    }
  }

  #[inline]
  pub fn stream(&self) -> S {
    self.assert_success("stream");
    self.success.as_ref().unwrap().stream.clone()
  }
}

impl<S, T> ParseState<S, T>
{
  #[inline]
  pub fn from_error(error: ParseError<S>) -> ParseState<S, T> {
    ParseState {
      error: error,
      success: None
    }
  }

  #[inline]
  pub fn error(stream: S, expect: &'static str) -> ParseState<S, T> {
    ParseState::from_error(ParseError::unique(stream, expect))
  }

  #[inline]
  pub fn empty_error(stream: S) -> ParseState<S, T> {
    ParseState {
      error: ParseError::empty(stream),
      success: None
    }
  }

  #[inline]
  pub fn map<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(ParseSuccess<S, T>) -> ParseSuccess<S, U>
  {
    ParseState {
      error: self.error,
      success: self.success.map(op)
    }
  }

  #[inline]
  pub fn map_data<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(T) -> U
  {
    ParseState {
      error: self.error,
      success: self.success.map(|success| success.map(op))
    }
  }

  #[inline]
  pub fn or_else<F>(self, op: F) -> ParseState<S, T> where
   F: FnOnce(ParseError<S>) -> ParseState<S, T>
  {
    match &self.success {
      &Some(_) => self,
      &None => op(self.error)
    }
  }

  #[inline]
  pub fn map_or_else<U, D, F>(self, default: D, f: F) -> ParseState<S, U> where
   D: FnOnce() -> ParseSuccess<S, U>,
   F: FnOnce(ParseSuccess<S, T>) -> ParseSuccess<S, U>
  {
    ParseState {
      error: self.error,
      success: Some(self.success.map_or_else(default, f))
    }
  }

  #[inline]
  pub fn to_error(mut self) -> ParseState<S, T> {
    self.success = None;
    self
  }

  pub fn into_result(self) -> ParseResult<S, T> {
    match self.success {
      Some(success) => {
        Ok(success)
      },
      None => {
        Err(self.error)
      }
    }
  }

  #[inline]
  pub fn unwrap_data(self) -> T {
    self.assert_success("ParseState::unwrap_data");
    self.success.unwrap().data
  }

  #[inline]
  pub fn is_successful(&self) -> bool {
    self.success.is_some()
  }

  #[inline(always)]
  fn assert_success(&self, from: &str) {
    debug_assert!(self.is_successful(),
      "`{}`: `self` is required to be in a successful state.", from);
  }
}

impl<S, T> ParseState<S, T> where
 S: HasNext
{
  #[inline]
  pub fn has_successor(&self) -> bool {
    self.success.as_ref().map_or(false, |success| success.stream.has_next())
  }
}

impl<S, T> ParseState<S, T> where
 S: Eq
{
  pub fn stream_eq(&self, other: &S) -> bool {
    self.success.as_ref().map_or(false, |success| &success.stream == other)
  }
}

impl<S, T> ParseState<S, T> where
 S: Ord
{
  #[inline]
  pub fn and_then<U, F>(self, op: F) -> ParseState<S, U> where
   F: FnOnce(ParseSuccess<S, T>) -> ParseState<S, U>
  {
    match self.success {
      Some(success) => {
        op(success).join(self.error)
      }
      None => ParseState::from_error(self.error)
    }
  }

  #[inline]
  pub fn or_else_join<F>(self, op: F) -> ParseState<S, T> where
   F: FnOnce() -> ParseState<S, T>
  {
    self.or_else(|err| op().join(err))
  }

  #[inline]
  pub fn join(mut self, error: ParseError<S>) -> ParseState<S, T> {
    self.error = self.error.join(error);
    self
  }
}

impl<S> ParseState<S, ()> where
 S: Clone
{
  #[inline]
  pub fn stateless(stream: S) -> ParseState<S, ()> {
    ParseState::success(stream, ())
  }
}

impl<S> ParseState<S, ()>
{
  #[inline]
  pub fn or_stateless(self, stream: S) -> ParseState<S, ()> {
    ParseState {
      error: self.error,
      success: self.success.or(Some(ParseSuccess::stateless(stream)))
    }
  }

  #[inline]
  pub fn merge_success(&mut self, other: ParseSuccess<S, ()>)
  {
    self.assert_success("ParseState<S, ()>::merge_success");
    self.success = Some(other);
  }
}

impl<S, T> ParseState<S, Vec<T>>
{
  #[inline]
  pub fn merge_success(&mut self, other: ParseSuccess<S, T>)
  {
    self.assert_success("ParseState<S, Vec<T>>::merge_success");
    let success = self.success.as_mut().unwrap();
    success.data.push(other.data);
    success.stream = other.stream;
  }
}
<|endoftext|>


<commit_before>#![crate_name = "bob_test"]
#![crate_type = "lib"]

mod bob;

#[test]
#[ignore]
fn test_statement() {
    assert_eq!("Whatever.", bob::reply("Tom-ay-to, tom-aaaah-to."));
}

#[test]
#[ignore]
fn test_shouting() {
    assert_eq!("Woah, chill out!", bob::reply("WATCH OUT!"));
}

#[test]
#[ignore]
fn test_exclaiming() {
    assert_eq!("Whatever.", bob::reply("Let's go make out behind the gym!"));
}

#[test]
#[ignore]
fn test_asking() {
    assert_eq!("Sure.", bob::reply("Does this cryogenic chamber make me look fat?"));
}

#[test]
#[ignore]
fn test_shout_numbers() {
    assert_eq!("Woah, chill out!", bob::reply("1, 2, 3 GO!"));
}

#[test]
#[ignore]
fn test_shout_weird_characters() {
    assert_eq!("Woah, chill out!", bob::reply("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
}

#[test]
#[ignore]
fn test_shout_without_punctuation() {
    assert_eq!("Woah, chill out!", bob::reply("I HATE YOU"));
}

#[test]
#[ignore]
fn test_shout_without_question_mark() {
    assert_eq!("Whatever.", bob::reply("Ending with ? means a question."));
}

#[test]
#[ignore]
fn test_silent_treatment() {
    assert_eq!("Fine. Be that way!", bob::reply(""));
}

<commit_msg>Update bob_test.rs<commit_after>#![crate_name = "bob_test"]
#![crate_type = "lib"]

mod bob;

#[test]
#[ignore]
fn test_statement() {
    assert_eq!("Whatever.", bob::reply("Tom-ay-to, tom-aaaah-to."));
}

#[test]
#[ignore]
fn test_shouting() {
    assert_eq!("Whoa, chill out!", bob::reply("WATCH OUT!"));
}

#[test]
#[ignore]
fn test_exclaiming() {
    assert_eq!("Whatever.", bob::reply("Let's go make out behind the gym!"));
}

#[test]
#[ignore]
fn test_asking() {
    assert_eq!("Sure.", bob::reply("Does this cryogenic chamber make me look fat?"));
}

#[test]
#[ignore]
fn test_shout_numbers() {
    assert_eq!("Whoa, chill out!", bob::reply("1, 2, 3 GO!"));
}

#[test]
#[ignore]
fn test_shout_weird_characters() {
    assert_eq!("Whoa, chill out!", bob::reply("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
}

#[test]
#[ignore]
fn test_shout_without_punctuation() {
    assert_eq!("Whoa, chill out!", bob::reply("I HATE YOU"));
}

#[test]
#[ignore]
fn test_shout_without_question_mark() {
    assert_eq!("Whatever.", bob::reply("Ending with ? means a question."));
}

#[test]
#[ignore]
fn test_silent_treatment() {
    assert_eq!("Fine. Be that way!", bob::reply(""));
}

<|endoftext|>


<commit_before>#![feature(collections)]

extern crate opencl;

use opencl::mem::CLBuffer;
use std::fmt;

fn main()
{
    let ker = include_str!("demo.ocl");
    println!("ker {}", ker);

    let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7];
    let vec_b = vec![-7isize, -6, 5, -4, 0, -1, 2, 3];

    let ref platform = opencl::hl::get_platforms()[0];
    let devices = platform.get_devices();
    let ctx = opencl::hl::Context::create_context(&devices[..]);
    let queues: Vec<opencl::hl::CommandQueue> = devices.iter()
        .map(|d| ctx.create_command_queue(d)).collect();

    for (device, queue) in devices.iter().zip(queues.iter()) {
        println!("{}", device.name());

        let a: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);
        let b: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);
        let c: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_WRITE_ONLY);

        queue.write(&a, &&vec_a[..], ());
        queue.write(&b, &&vec_b[..], ());

        let program = ctx.create_program_from_source(ker);
        program.build(&device).ok().expect("Couldn't build program.");

        let kernel = program.create_kernel("vector_add");

        kernel.set_arg(0, &a);
        kernel.set_arg(1, &b);
        kernel.set_arg(2, &c);

        let event = queue.enqueue_async_kernel(&kernel, vec_a.len(), None, ());

        let vec_c: Vec<isize> = queue.get(&c, &event);

        println!("  {}", string_from_slice(&vec_a[..]));
        println!("+ {}", string_from_slice(&vec_b[..]));
        println!("= {}", string_from_slice(&vec_c[..]));
    }
}

fn string_from_slice<T: fmt::Display>(slice: &[T]) -> String {
    let mut st = String::from_str("[");
    let mut first = true;

    for i in slice.iter() {
        if !first {
            st.push_str(", ");
        }
        else {
            first = false;
        }
        st.push_str(&*i.to_string())
    }

    st.push_str("]");
    return st
}
<commit_msg>changed multidevice demo to test CommandQueue::device<commit_after>#![feature(collections)]

extern crate opencl;

use opencl::mem::CLBuffer;
use std::fmt;

fn main()
{
    let ker = include_str!("demo.ocl");
    println!("ker {}", ker);

    let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7];
    let vec_b = vec![-7isize, -6, 5, -4, 0, -1, 2, 3];

    let ref platform = opencl::hl::get_platforms()[0];
    let devices = platform.get_devices();
    let ctx = opencl::hl::Context::create_context(&devices[..]);
    let queues: Vec<opencl::hl::CommandQueue> = devices.iter()
        .map(|d| ctx.create_command_queue(d)).collect();

    for (device, queue) in devices.iter().zip(queues.iter()) {
        println!("{}", queue.device().name());

        let a: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);
        let b: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);
        let c: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_WRITE_ONLY);

        queue.write(&a, &&vec_a[..], ());
        queue.write(&b, &&vec_b[..], ());

        let program = ctx.create_program_from_source(ker);
        program.build(&device).ok().expect("Couldn't build program.");

        let kernel = program.create_kernel("vector_add");

        kernel.set_arg(0, &a);
        kernel.set_arg(1, &b);
        kernel.set_arg(2, &c);

        let event = queue.enqueue_async_kernel(&kernel, vec_a.len(), None, ());

        let vec_c: Vec<isize> = queue.get(&c, &event);

        println!("  {}", string_from_slice(&vec_a[..]));
        println!("+ {}", string_from_slice(&vec_b[..]));
        println!("= {}", string_from_slice(&vec_c[..]));
    }
}

fn string_from_slice<T: fmt::Display>(slice: &[T]) -> String {
    let mut st = String::from_str("[");
    let mut first = true;

    for i in slice.iter() {
        if !first {
            st.push_str(", ");
        }
        else {
            first = false;
        }
        st.push_str(&*i.to_string())
    }

    st.push_str("]");
    return st
}
<|endoftext|>


<commit_before>use hir::def_id::DefId;
use hir::HirId;
use rustc_ast::Mutability;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty::Ty;
use rustc_session::lint::builtin::FUTURE_PRELUDE_COLLISION;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;

use crate::check::{
    method::probe::{self, Pick},
    FnCtxt,
};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
    pub(super) fn lint_dot_call_from_2018(
        &self,
        self_ty: Ty<'tcx>,
        segment: &hir::PathSegment<'_>,
        span: Span,
        call_expr: &'tcx hir::Expr<'tcx>,
        self_expr: &'tcx hir::Expr<'tcx>,
        pick: &Pick<'tcx>,
        args: &'tcx [hir::Expr<'tcx>],
    ) {
        debug!(
            "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
            segment.ident, self_ty, call_expr, self_expr
        );

        // Rust 2021 and later is already using the new prelude
        if span.rust_2021() {
            return;
        }

        // These are the method names that were added to prelude in Rust 2021
        if !matches!(segment.ident.name, sym::try_into) {
            return;
        }

        // No need to lint if method came from std/core, as that will now be in the prelude
        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
            return;
        }

        self.tcx.struct_span_lint_hir(
            FUTURE_PRELUDE_COLLISION,
            call_expr.hir_id,
            call_expr.span,
            |lint| {
                let sp = call_expr.span;
                let trait_name =
                    self.trait_path_or_bare_name(call_expr.hir_id, pick.item.container.id());

                let mut lint = lint.build(&format!(
                    "trait method `{}` will become ambiguous in Rust 2021",
                    segment.ident.name
                ));

                if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span) {
                    let derefs = "*".repeat(pick.autoderefs);

                    let autoref = match pick.autoref_or_ptr_adjustment {
                        Some(probe::AutorefOrPtrAdjustment::Autoref {
                            mutbl: Mutability::Mut,
                            ..
                        }) => "&mut ",
                        Some(probe::AutorefOrPtrAdjustment::Autoref {
                            mutbl: Mutability::Not,
                            ..
                        }) => "&",
                        Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
                    };
                    let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
                        pick.autoref_or_ptr_adjustment
                    {
                        format!("{}{} as *const _", derefs, self_expr)
                    } else {
                        format!("{}{}{}", autoref, derefs, self_expr)
                    };
                    let args = args
                        .iter()
                        .skip(1)
                        .map(|arg| {
                            format!(
                                ", {}",
                                self.sess().source_map().span_to_snippet(arg.span).unwrap()
                            )
                        })
                        .collect::<String>();

                    lint.span_suggestion(
                        sp,
                        "disambiguate the associated function",
                        format!(
                            "{}::{}({}{})",
                            trait_name, segment.ident.name, self_adjusted, args
                        ),
                        Applicability::MachineApplicable,
                    );
                } else {
                    lint.span_help(
                        sp,
                        &format!(
                            "disambiguate the associated function with `{}::{}(...)`",
                            trait_name, segment.ident,
                        ),
                    );
                }

                lint.emit();
            },
        );
    }

    pub(super) fn lint_fully_qualified_call_from_2018(
        &self,
        span: Span,
        method_name: Ident,
        self_ty: Ty<'tcx>,
        self_ty_span: Span,
        expr_id: hir::HirId,
        pick: &Pick<'tcx>,
    ) {
        // Rust 2021 and later is already using the new prelude
        if span.rust_2021() {
            return;
        }

        // These are the fully qualified methods added to prelude in Rust 2021
        if !matches!(method_name.name, sym::try_into | sym::try_from | sym::from_iter) {
            return;
        }

        // No need to lint if method came from std/core, as that will now be in the prelude
        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
            return;
        }

        // No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
        // since such methods take precedence over trait methods.
        if matches!(pick.kind, probe::PickKind::InherentImplPick) {
            return;
        }

        self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
            // "type" refers to either a type or, more likely, a trait from which
            // the associated function or method is from.
            let trait_path = self.trait_path_or_bare_name(expr_id, pick.item.container.id());
            let trait_generics = self.tcx.generics_of(pick.item.container.id());

            let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
            let trait_name = if parameter_count == 0 {
                trait_path
            } else {
                format!(
                    "{}<{}>",
                    trait_path,
                    std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
                )
            };

            let mut lint = lint.build(&format!(
                "trait-associated function `{}` will become ambiguous in Rust 2021",
                method_name.name
            ));

            let self_ty = self
                .sess()
                .source_map()
                .span_to_snippet(self_ty_span)
                .unwrap_or_else(|_| self_ty.to_string());

            lint.span_suggestion(
                span,
                "disambiguate the associated function",
                format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
                Applicability::MachineApplicable,
            );

            lint.emit();
        });
    }

    fn trait_path_or_bare_name(&self, expr_hir_id: HirId, trait_def_id: DefId) -> String {
        self.trait_path(expr_hir_id, trait_def_id).unwrap_or_else(|| {
            let key = self.tcx.def_key(trait_def_id);
            format!("{}", key.disambiguated_data.data)
        })
    }

    fn trait_path(&self, expr_hir_id: HirId, trait_def_id: DefId) -> Option<String> {
        let applicable_traits = self.tcx.in_scope_traits(expr_hir_id)?;
        let applicable_trait = applicable_traits.iter().find(|t| t.def_id == trait_def_id)?;
        if applicable_trait.import_ids.is_empty() {
            // The trait was declared within the module, we only need to use its name.
            return None;
        }

        for &import_id in &applicable_trait.import_ids {
            let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
            let item = self.tcx.hir().expect_item(hir_id);
            debug!(?item, ?import_id, "import_id");
        }

        return None;
    }
}
<commit_msg>WIP: identify the case where we need to serialize path<commit_after>use hir::def_id::DefId;
use hir::HirId;
use hir::ItemKind;
use rustc_ast::Mutability;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty::Ty;
use rustc_session::lint::builtin::FUTURE_PRELUDE_COLLISION;
use rustc_span::symbol::kw::Underscore;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;

use crate::check::{
    method::probe::{self, Pick},
    FnCtxt,
};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
    pub(super) fn lint_dot_call_from_2018(
        &self,
        self_ty: Ty<'tcx>,
        segment: &hir::PathSegment<'_>,
        span: Span,
        call_expr: &'tcx hir::Expr<'tcx>,
        self_expr: &'tcx hir::Expr<'tcx>,
        pick: &Pick<'tcx>,
        args: &'tcx [hir::Expr<'tcx>],
    ) {
        debug!(
            "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
            segment.ident, self_ty, call_expr, self_expr
        );

        // Rust 2021 and later is already using the new prelude
        if span.rust_2021() {
            return;
        }

        // These are the method names that were added to prelude in Rust 2021
        if !matches!(segment.ident.name, sym::try_into) {
            return;
        }

        // No need to lint if method came from std/core, as that will now be in the prelude
        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
            return;
        }

        self.tcx.struct_span_lint_hir(
            FUTURE_PRELUDE_COLLISION,
            call_expr.hir_id,
            call_expr.span,
            |lint| {
                let sp = call_expr.span;
                let trait_name =
                    self.trait_path_or_bare_name(span, call_expr.hir_id, pick.item.container.id());

                let mut lint = lint.build(&format!(
                    "trait method `{}` will become ambiguous in Rust 2021",
                    segment.ident.name
                ));

                if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span) {
                    let derefs = "*".repeat(pick.autoderefs);

                    let autoref = match pick.autoref_or_ptr_adjustment {
                        Some(probe::AutorefOrPtrAdjustment::Autoref {
                            mutbl: Mutability::Mut,
                            ..
                        }) => "&mut ",
                        Some(probe::AutorefOrPtrAdjustment::Autoref {
                            mutbl: Mutability::Not,
                            ..
                        }) => "&",
                        Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
                    };
                    let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
                        pick.autoref_or_ptr_adjustment
                    {
                        format!("{}{} as *const _", derefs, self_expr)
                    } else {
                        format!("{}{}{}", autoref, derefs, self_expr)
                    };
                    let args = args
                        .iter()
                        .skip(1)
                        .map(|arg| {
                            format!(
                                ", {}",
                                self.sess().source_map().span_to_snippet(arg.span).unwrap()
                            )
                        })
                        .collect::<String>();

                    lint.span_suggestion(
                        sp,
                        "disambiguate the associated function",
                        format!(
                            "{}::{}({}{})",
                            trait_name, segment.ident.name, self_adjusted, args
                        ),
                        Applicability::MachineApplicable,
                    );
                } else {
                    lint.span_help(
                        sp,
                        &format!(
                            "disambiguate the associated function with `{}::{}(...)`",
                            trait_name, segment.ident,
                        ),
                    );
                }

                lint.emit();
            },
        );
    }

    pub(super) fn lint_fully_qualified_call_from_2018(
        &self,
        span: Span,
        method_name: Ident,
        self_ty: Ty<'tcx>,
        self_ty_span: Span,
        expr_id: hir::HirId,
        pick: &Pick<'tcx>,
    ) {
        // Rust 2021 and later is already using the new prelude
        if span.rust_2021() {
            return;
        }

        // These are the fully qualified methods added to prelude in Rust 2021
        if !matches!(method_name.name, sym::try_into | sym::try_from | sym::from_iter) {
            return;
        }

        // No need to lint if method came from std/core, as that will now be in the prelude
        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
            return;
        }

        // No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
        // since such methods take precedence over trait methods.
        if matches!(pick.kind, probe::PickKind::InherentImplPick) {
            return;
        }

        self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
            // "type" refers to either a type or, more likely, a trait from which
            // the associated function or method is from.
            let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
            let trait_generics = self.tcx.generics_of(pick.item.container.id());

            let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
            let trait_name = if parameter_count == 0 {
                trait_path
            } else {
                format!(
                    "{}<{}>",
                    trait_path,
                    std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
                )
            };

            let mut lint = lint.build(&format!(
                "trait-associated function `{}` will become ambiguous in Rust 2021",
                method_name.name
            ));

            let self_ty = self
                .sess()
                .source_map()
                .span_to_snippet(self_ty_span)
                .unwrap_or_else(|_| self_ty.to_string());

            lint.span_suggestion(
                span,
                "disambiguate the associated function",
                format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
                Applicability::MachineApplicable,
            );

            lint.emit();
        });
    }

    fn trait_path_or_bare_name(
        &self,
        span: Span,
        expr_hir_id: HirId,
        trait_def_id: DefId,
    ) -> String {
        self.trait_path(span, expr_hir_id, trait_def_id).unwrap_or_else(|| {
            let key = self.tcx.def_key(trait_def_id);
            format!("{}", key.disambiguated_data.data)
        })
    }

    fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Option<String> {
        let applicable_traits = self.tcx.in_scope_traits(expr_hir_id)?;
        let applicable_trait = applicable_traits.iter().find(|t| t.def_id == trait_def_id)?;
        if applicable_trait.import_ids.is_empty() {
            // The trait was declared within the module, we only need to use its name.
            return None;
        }

        let import_items: Vec<_> = applicable_trait
            .import_ids
            .iter()
            .map(|&import_id| {
                let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
                self.tcx.hir().expect_item(hir_id)
            })
            .collect();

        // Find an identifier with which this trait was imported (note that `_` doesn't count).
        let any_id = import_items
            .iter()
            .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
            .next();
        if let Some(any_id) = any_id {
            return Some(format!("{}", any_id));
        }

        // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick,
        // so just take the first one.
        match import_items[0].kind {
            ItemKind::Use(path, _) => {
                // FIXME: serialize path into something readable like a::b, there must be a fn for this
                debug!("no name for trait, found import of path: {:?}", path);
                return None;
            }
            _ => {
                span_bug!(span, "unexpected item kind, expected a use: {:?}", import_items[0].kind);
            }
        }
    }
}
<|endoftext|>