<commit_before>// Copyright 2014-2015 Sam Doshi (sam@metal-fish.co.uk)
// Copyright 2013-2014 Philippe Delrieu (philippe.delrieu@free.fr)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.
#![feature(core, std_misc)]

extern crate libc;

use std::ptr;
use libc::c_char;

mod ffi;

// Types
// -----
/// Used by PortMidi to refer to a Midi device
pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

// Errors
// ------
#[derive(Copy, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize
}

fn from_pm_error(pm_error: ffi::PmError) -> PortMidiResult<()> {
    match pm_error {
        ffi::PmError::PmNoError => Ok(()),
        ffi::PmError::PmGotData => Ok(()),
        ffi::PmError::PmHostError => Err(PortMidiError::HostError),
        ffi::PmError::PmInvalidDeviceId => Err(PortMidiError::InvalidDeviceId),
        ffi::PmError::PmInsufficientMemory => Err(PortMidiError::InsufficientMemory),
        ffi::PmError::PmBufferTooSmall => Err(PortMidiError::BufferTooSmall),
        ffi::PmError::PmBufferOverflow => Err(PortMidiError::BufferOverflow),
        ffi::PmError::PmBadPtr => Err(PortMidiError::BadPtr),
        ffi::PmError::PmBadData => Err(PortMidiError::BadData),
        ffi::PmError::PmInternalError => Err(PortMidiError::InternalError),
        ffi::PmError::PmBufferMaxSize => Err(PortMidiError::BufferMaxSize),
    }
}

// Global fns
// ----------
/// `initialize` initalizes the underlying PortMidi C library, call this
/// before using the library.
///
/// Once initialized, PortMidi will no longer pickup any new Midi devices that are
/// connected, i.e. it does not support hot plugging.
pub fn initialize() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Initialize()
    })
}

/// `terminate` terminates the underlying PortMidi C library, call this
/// after using the library.
pub fn terminate() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Terminate()
    })
}

/// Return the number of devices. This number will not change during the lifetime
/// of the program.
pub fn count_devices() -> PortMidiDeviceId {
    unsafe {
        ffi::Pm_CountDevices()
    }
}

/// Gets the `PortMidiDeviceId` for the default input, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_input_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultInputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

/// Gets the `PortMidiDeviceId` for the default output, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_output_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultOutputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

// DeviceInfo
// ----------
/// Represents what we know about a device
#[derive(Clone, Debug)]
pub struct DeviceInfo {
    /// The `PortMidiDeviceId` used with `OutputPort::new` and `InputPort::new`
    pub device_id: PortMidiDeviceId,
    /// The name of the device
    pub name: String,
    /// Is the device an input
    pub input: bool,
    /// Is the device an output
    pub output: bool
}

impl DeviceInfo {
    fn wrap(device_id: PortMidiDeviceId, device_info: *const ffi::PmDeviceInfo) -> DeviceInfo {
        let name = unsafe {
            let bytes = std::ffi::CStr::from_ptr((*device_info).name).to_bytes();
            std::str::from_utf8_unchecked(bytes).to_string()
        };
        let input = unsafe { (*device_info).input };
        let output = unsafe { (*device_info).output };

        DeviceInfo {
            device_id: device_id,
            name: name,
            input: input > 0,
            output: output > 0
        }
    }
}

/// Returns a `DeviceInfo` with information about a device, or `None` if
/// it does not exist
pub fn get_device_info(device_id: PortMidiDeviceId) -> Option<DeviceInfo> {
    let info = unsafe { ffi::Pm_GetDeviceInfo(device_id) };
    if info.is_null() {
        None
    }
    else {
        Some(DeviceInfo::wrap(device_id, info))
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
///
/// TODO: should we use u8?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: i8,
    pub data1: i8,
    pub data2: i8,
}

impl MidiMessage {
    fn wrap(cmessage : ffi::PmMessage) -> MidiMessage {
        MidiMessage {
            status:  ((cmessage) & 0xFF) as i8,
            data1 : (((cmessage) >> 8) & 0xFF) as i8,
            data2 : (((cmessage) >> 16) & 0xFF) as i8,
        }
    }

    fn unwrap(&self) -> ffi::PmMessage {
        ((((self.data2 as i32) << 16) & 0xFF0000) |
          (((self.data1 as i32) << 8) & 0xFF00) |
          ((self.status as i32) & 0xFF)) as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub  struct MidiEvent {
    pub message : MidiMessage,
    pub timestamp : ffi::PmTimestamp,
}

impl MidiEvent {
    fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message:  MidiMessage::wrap(event.message),
            timestamp : event.timestamp,
        }
    }

    fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: self.message.unwrap(),
            timestamp: self.timestamp,
        }
    }
}

// Input
// -----
/// Representation of an input midi port
#[allow(missing_copy_implementations)]
pub struct InputPort {
    pm_stream : *const ffi::PortMidiStream,
    input_device : ffi::PmDeviceId,
    buffer_size : i32,
}

impl InputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(input_device : PortMidiDeviceId, buffer_size: i32) -> InputPort {
        InputPort {
            pm_stream : ptr::null(),
            input_device : input_device,
            buffer_size : buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenInput(&self.pm_stream, self.input_device, ptr::null(),
                              self.buffer_size, ptr::null(), ptr::null())
        })
    }

    /// Reads a single `MidiEvent` if one is avaible
    ///
    /// A `Result` of `None` means no event was available.
    ///
    /// See the PortMidi documentation for information on how it deals with input
    /// overflows
    pub fn read(&mut self) -> PortMidiResult<Option<MidiEvent>> {
        use std::num::FromPrimitive;
        //get one note a the time
        let mut event = ffi::PmEvent { message : 0, timestamp : 0 };
        let no_of_notes = unsafe { ffi::Pm_Read(self.pm_stream, &mut event, 1) };
        match no_of_notes {
            y if y == 0 => Ok(None),
            y if y > 0 => Ok(Some(MidiEvent::wrap(event))),
            _ => {
                // if it's negative it's an error, convert it
                let maybe_pm_error: Option<ffi::PmError> = FromPrimitive::from_i32(no_of_notes);
                if let Some(pm_error) = maybe_pm_error {
                    from_pm_error(pm_error).map(|_| None)
                }
                else {
                    // what should we do, if we can't convert the error no?
                    // should we panic?
                    Ok(None)
                }
            }
        }
    }

    /// `poll` tests if there is input available, either returing a bool or an error
    pub fn poll(&self) -> PortMidiResult<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.pm_stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            other => from_pm_error(other).map(|_| false)
        }
    }

    /// Closes the input, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Output
// ------
/// Representation of an output midi port
#[allow(missing_copy_implementations)]
pub struct OutputPort {
    pm_stream: *const ffi::PortMidiStream,
    output_device: ffi::PmDeviceId,
    buffer_size: i32,
}

impl OutputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(output_device: PortMidiDeviceId, buffer_size: i32) -> OutputPort {
        OutputPort {
            pm_stream: ptr::null(),
            output_device: output_device,
            buffer_size: buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenOutput(&self.pm_stream, self.output_device, ptr::null(),
                               self.buffer_size, ptr::null(), ptr::null(), 0)
        })
    }

    /// Terminates outgoing messages immediately
    ///
    /// The caller should immediately close the output port, this may
    /// result in transmission of a partial midi message. Note, not all platforms
    /// support abort.
    pub fn abort(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Abort(self.pm_stream)
        })
    }

    /// Closes the midi stream, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /// Write a single `MidiEvent`
    pub fn write_event(&mut self, midi_event: MidiEvent) -> PortMidiResult<()> {
        let event = midi_event.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_Write(self.pm_stream, &event, 1)
        })
    }

    /// Write a single `MidiMessage` immediately
    pub fn write_message(&mut self, midi_message: MidiMessage) -> PortMidiResult<()> {
        let message = midi_message.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_WriteShort(self.pm_stream, 0, message)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool  {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Old code
// --------
/**  Translate portmidi error number into human readable message.
*    These strings are constants (set at compile time) so client has
*    no need to allocate storage
*/
pub fn get_error_text(error_code: ffi::PmError) -> String {
    unsafe {
        let error_text = ffi::Pm_GetErrorText(error_code);
        let bytes = std::ffi::CStr::from_ptr(error_text).to_bytes();
        std::str::from_utf8_unchecked(bytes).to_string()
    }
}

/**  Translate portmidi host error into human readable message.
     These strings are computed at run time, so client has to allocate storage.
     After this routine executes, the host error is cleared.
*/
pub fn get_host_error_text(msg: *const c_char, len: i32) {
    unsafe {
        ffi::Pm_GetHostErrorText(msg, len);
    }
}

pub const HDRLENGTH: i32 = 50;
pub const PM_HOST_ERROR_MSG_LEN: i32 = 256;

<commit_msg>switch MidiMessage from i8 to u8<commit_after>// Copyright 2014-2015 Sam Doshi (sam@metal-fish.co.uk)
// Copyright 2013-2014 Philippe Delrieu (philippe.delrieu@free.fr)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.
#![feature(core, std_misc)]

extern crate libc;

use std::ptr;
use libc::c_char;

mod ffi;

// Types
// -----
/// Used by PortMidi to refer to a Midi device
pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

// Errors
// ------
#[derive(Copy, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize
}

fn from_pm_error(pm_error: ffi::PmError) -> PortMidiResult<()> {
    match pm_error {
        ffi::PmError::PmNoError => Ok(()),
        ffi::PmError::PmGotData => Ok(()),
        ffi::PmError::PmHostError => Err(PortMidiError::HostError),
        ffi::PmError::PmInvalidDeviceId => Err(PortMidiError::InvalidDeviceId),
        ffi::PmError::PmInsufficientMemory => Err(PortMidiError::InsufficientMemory),
        ffi::PmError::PmBufferTooSmall => Err(PortMidiError::BufferTooSmall),
        ffi::PmError::PmBufferOverflow => Err(PortMidiError::BufferOverflow),
        ffi::PmError::PmBadPtr => Err(PortMidiError::BadPtr),
        ffi::PmError::PmBadData => Err(PortMidiError::BadData),
        ffi::PmError::PmInternalError => Err(PortMidiError::InternalError),
        ffi::PmError::PmBufferMaxSize => Err(PortMidiError::BufferMaxSize),
    }
}

// Global fns
// ----------
/// `initialize` initalizes the underlying PortMidi C library, call this
/// before using the library.
///
/// Once initialized, PortMidi will no longer pickup any new Midi devices that are
/// connected, i.e. it does not support hot plugging.
pub fn initialize() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Initialize()
    })
}

/// `terminate` terminates the underlying PortMidi C library, call this
/// after using the library.
pub fn terminate() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Terminate()
    })
}

/// Return the number of devices. This number will not change during the lifetime
/// of the program.
pub fn count_devices() -> PortMidiDeviceId {
    unsafe {
        ffi::Pm_CountDevices()
    }
}

/// Gets the `PortMidiDeviceId` for the default input, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_input_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultInputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

/// Gets the `PortMidiDeviceId` for the default output, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_output_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultOutputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

// DeviceInfo
// ----------
/// Represents what we know about a device
#[derive(Clone, Debug)]
pub struct DeviceInfo {
    /// The `PortMidiDeviceId` used with `OutputPort::new` and `InputPort::new`
    pub device_id: PortMidiDeviceId,
    /// The name of the device
    pub name: String,
    /// Is the device an input
    pub input: bool,
    /// Is the device an output
    pub output: bool
}

impl DeviceInfo {
    fn wrap(device_id: PortMidiDeviceId, device_info: *const ffi::PmDeviceInfo) -> DeviceInfo {
        let name = unsafe {
            let bytes = std::ffi::CStr::from_ptr((*device_info).name).to_bytes();
            std::str::from_utf8_unchecked(bytes).to_string()
        };
        let input = unsafe { (*device_info).input };
        let output = unsafe { (*device_info).output };

        DeviceInfo {
            device_id: device_id,
            name: name,
            input: input > 0,
            output: output > 0
        }
    }
}

/// Returns a `DeviceInfo` with information about a device, or `None` if
/// it does not exist
pub fn get_device_info(device_id: PortMidiDeviceId) -> Option<DeviceInfo> {
    let info = unsafe { ffi::Pm_GetDeviceInfo(device_id) };
    if info.is_null() {
        None
    }
    else {
        Some(DeviceInfo::wrap(device_id, info))
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}

impl MidiMessage {
    fn wrap(cmessage : ffi::PmMessage) -> MidiMessage {
        MidiMessage {
            status:  ((cmessage) & 0xFF) as u8,
            data1 : (((cmessage) >> 8) & 0xFF) as u8,
            data2 : (((cmessage) >> 16) & 0xFF) as u8,
        }
    }

    fn unwrap(&self) -> ffi::PmMessage {
        ((((self.data2 as i32) << 16) & 0xFF0000) |
          (((self.data1 as i32) << 8) & 0xFF00) |
          ((self.status as i32) & 0xFF)) as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message : MidiMessage,
    pub timestamp : ffi::PmTimestamp,
}

impl MidiEvent {
    fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message:  MidiMessage::wrap(event.message),
            timestamp : event.timestamp,
        }
    }

    fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: self.message.unwrap(),
            timestamp: self.timestamp,
        }
    }
}

// Input
// -----
/// Representation of an input midi port
#[allow(missing_copy_implementations)]
pub struct InputPort {
    pm_stream : *const ffi::PortMidiStream,
    input_device : ffi::PmDeviceId,
    buffer_size : i32,
}

impl InputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(input_device : PortMidiDeviceId, buffer_size: i32) -> InputPort {
        InputPort {
            pm_stream : ptr::null(),
            input_device : input_device,
            buffer_size : buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenInput(&self.pm_stream, self.input_device, ptr::null(),
                              self.buffer_size, ptr::null(), ptr::null())
        })
    }

    /// Reads a single `MidiEvent` if one is avaible
    ///
    /// A `Result` of `None` means no event was available.
    ///
    /// See the PortMidi documentation for information on how it deals with input
    /// overflows
    pub fn read(&mut self) -> PortMidiResult<Option<MidiEvent>> {
        use std::num::FromPrimitive;
        //get one note a the time
        let mut event = ffi::PmEvent { message : 0, timestamp : 0 };
        let no_of_notes = unsafe { ffi::Pm_Read(self.pm_stream, &mut event, 1) };
        match no_of_notes {
            y if y == 0 => Ok(None),
            y if y > 0 => Ok(Some(MidiEvent::wrap(event))),
            _ => {
                // if it's negative it's an error, convert it
                let maybe_pm_error: Option<ffi::PmError> = FromPrimitive::from_i32(no_of_notes);
                if let Some(pm_error) = maybe_pm_error {
                    from_pm_error(pm_error).map(|_| None)
                }
                else {
                    // what should we do, if we can't convert the error no?
                    // should we panic?
                    Ok(None)
                }
            }
        }
    }

    /// `poll` tests if there is input available, either returing a bool or an error
    pub fn poll(&self) -> PortMidiResult<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.pm_stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            other => from_pm_error(other).map(|_| false)
        }
    }

    /// Closes the input, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Output
// ------
/// Representation of an output midi port
#[allow(missing_copy_implementations)]
pub struct OutputPort {
    pm_stream: *const ffi::PortMidiStream,
    output_device: ffi::PmDeviceId,
    buffer_size: i32,
}

impl OutputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(output_device: PortMidiDeviceId, buffer_size: i32) -> OutputPort {
        OutputPort {
            pm_stream: ptr::null(),
            output_device: output_device,
            buffer_size: buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenOutput(&self.pm_stream, self.output_device, ptr::null(),
                               self.buffer_size, ptr::null(), ptr::null(), 0)
        })
    }

    /// Terminates outgoing messages immediately
    ///
    /// The caller should immediately close the output port, this may
    /// result in transmission of a partial midi message. Note, not all platforms
    /// support abort.
    pub fn abort(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Abort(self.pm_stream)
        })
    }

    /// Closes the midi stream, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /// Write a single `MidiEvent`
    pub fn write_event(&mut self, midi_event: MidiEvent) -> PortMidiResult<()> {
        let event = midi_event.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_Write(self.pm_stream, &event, 1)
        })
    }

    /// Write a single `MidiMessage` immediately
    pub fn write_message(&mut self, midi_message: MidiMessage) -> PortMidiResult<()> {
        let message = midi_message.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_WriteShort(self.pm_stream, 0, message)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool  {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Old code
// --------
/**  Translate portmidi error number into human readable message.
*    These strings are constants (set at compile time) so client has
*    no need to allocate storage
*/
pub fn get_error_text(error_code: ffi::PmError) -> String {
    unsafe {
        let error_text = ffi::Pm_GetErrorText(error_code);
        let bytes = std::ffi::CStr::from_ptr(error_text).to_bytes();
        std::str::from_utf8_unchecked(bytes).to_string()
    }
}

/**  Translate portmidi host error into human readable message.
     These strings are computed at run time, so client has to allocate storage.
     After this routine executes, the host error is cleared.
*/
pub fn get_host_error_text(msg: *const c_char, len: i32) {
    unsafe {
        ffi::Pm_GetHostErrorText(msg, len);
    }
}

pub const HDRLENGTH: i32 = 50;
pub const PM_HOST_ERROR_MSG_LEN: i32 = 256;

<|endoftext|>


<commit_before><commit_msg>Optimized implementation for fields of width<=4<commit_after><|endoftext|>


<commit_before><commit_msg>add channel registration command<commit_after><|endoftext|>


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

use {LinkerFlavor, PanicStrategy};
use target::{LinkArgs, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        // We want to be able to strip as much executable code as possible
        // from the linker command line, and this flag indicates to the
        // linker that it can avoid linking in dynamic libraries that don't
        // actually satisfy any symbols up to that point (as with many other
        // resolutions the linker does). This option only applies to all
        // following libraries so we're sure to pass it as one of the first
        // arguments.
        "-Wl,--as-needed".to_string(),

        // Always enable NX protection when it is available
        "-Wl,-z,noexecstack".to_string()
    ]);

    TargetOptions {
        pre_link_args: args,
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: None,
        linker_is_gnu: true,
        has_elf_tls: true,
        panic_strategy: PanicStrategy::Abort,
        .. Default::default()
    }
}
<commit_msg>Enable unwinding panics on Redox<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use LinkerFlavor;
use target::{LinkArgs, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        // We want to be able to strip as much executable code as possible
        // from the linker command line, and this flag indicates to the
        // linker that it can avoid linking in dynamic libraries that don't
        // actually satisfy any symbols up to that point (as with many other
        // resolutions the linker does). This option only applies to all
        // following libraries so we're sure to pass it as one of the first
        // arguments.
        "-Wl,--as-needed".to_string(),

        // Always enable NX protection when it is available
        "-Wl,-z,noexecstack".to_string()
    ]);

    TargetOptions {
        pre_link_args: args,
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: None,
        linker_is_gnu: true,
        has_elf_tls: true,
        .. Default::default()
    }
}
<|endoftext|>


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

use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
use ast::{tt_delim};
use ast;
use codemap::{Span, Spanned, dummy_sp};
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
use ext::base::{NormalTT, SyntaxExpanderTTTrait};
use ext::base;
use ext::tt::macro_parser::{error};
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
use parse::lexer::{new_tt_reader, reader};
use parse::parser::Parser;
use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_str};
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
use print;

struct ParserAnyMacro {
    parser: @Parser,
}

impl AnyMacro for ParserAnyMacro {
    fn make_expr(&self) -> @ast::Expr {
        self.parser.parse_expr()
    }
    fn make_item(&self) -> Option<@ast::item> {
        self.parser.parse_item(~[])     // no attrs
    }
    fn make_stmt(&self) -> @ast::Stmt {
        self.parser.parse_stmt(~[])     // no attrs
    }
}

struct MacroRulesSyntaxExpanderTTFun {
    name: Ident,
    lhses: @~[@named_match],
    rhses: @~[@named_match],
}

impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
    fn expand(&self,
              cx: @ExtCtxt,
              sp: Span,
              arg: &[ast::token_tree],
              _: ast::SyntaxContext)
              -> MacResult {
        generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
    }
}

// Given `lhses` and `rhses`, this is the new macro we create
fn generic_extension(cx: @ExtCtxt,
                     sp: Span,
                     name: Ident,
                     arg: &[ast::token_tree],
                     lhses: &[@named_match],
                     rhses: &[@named_match])
                     -> MacResult {
    if cx.trace_macros() {
        println!("{}! \\{ {} \\}",
                  cx.str_of(name),
                  print::pprust::tt_to_str(
                      &ast::tt_delim(@mut arg.to_owned()),
                      get_ident_interner()));
    }

    // Which arm's failure should we report? (the one furthest along)
    let mut best_fail_spot = dummy_sp();
    let mut best_fail_msg = ~"internal error: ran no matchers";

    let s_d = cx.parse_sess().span_diagnostic;

    for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
        match *lhs {
          @matched_nonterminal(nt_matchers(ref mtcs)) => {
            // `none` is because we're not interpolating
            let arg_rdr = new_tt_reader(
                s_d,
                None,
                arg.to_owned()
            ) as @mut reader;
            match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
              success(named_matches) => {
                let rhs = match rhses[i] {
                    // okay, what's your transcriber?
                    @matched_nonterminal(nt_tt(@ref tt)) => {
                        match (*tt) {
                            // cut off delimiters; don't parse 'em
                            tt_delim(ref tts) => {
                                (*tts).slice(1u,(*tts).len()-1u).to_owned()
                            }
                            _ => cx.span_fatal(
                                sp, "macro rhs must be delimited")
                        }
                    },
                    _ => cx.span_bug(sp, "bad thing in rhs")
                };
                // rhs has holes ( `$id` and `$(...)` that need filled)
                let trncbr = new_tt_reader(s_d, Some(named_matches),
                                           rhs);
                let p = @Parser(cx.parse_sess(),
                                cx.cfg(),
                                trncbr as @mut reader);

                // Let the context choose how to interpret the result.
                // Weird, but useful for X-macros.
                return MRAny(@ParserAnyMacro {
                    parser: p,
                } as @AnyMacro)
              }
              failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                best_fail_spot = sp;
                best_fail_msg = (*msg).clone();
              },
              error(sp, ref msg) => cx.span_fatal(sp, (*msg))
            }
          }
          _ => cx.bug("non-matcher found in parsed lhses")
        }
    }
    cx.span_fatal(best_fail_spot, best_fail_msg);
}

// this procedure performs the expansion of the
// macro_rules! macro. It parses the RHS and adds
// an extension to the current context.
pub fn add_new_extension(cx: @ExtCtxt,
                         sp: Span,
                         name: Ident,
                         arg: ~[ast::token_tree],
                         _: ast::SyntaxContext)
                         -> base::MacResult {
    // these spans won't matter, anyways
    fn ms(m: matcher_) -> matcher {
        Spanned {
            node: m.clone(),
            span: dummy_sp()
        }
    }

    let lhs_nm =  gensym_ident("lhs");
    let rhs_nm =  gensym_ident("rhs");

    // The pattern that macro_rules matches.
    // The grammar for macro_rules! is:
    // $( $lhs:mtcs => $rhs:tt );+
    // ...quasiquoting this would be nice.
    let argument_gram = ~[
        ms(match_seq(~[
            ms(match_nonterminal(lhs_nm, special_idents::matchers, 0u)),
            ms(match_tok(FAT_ARROW)),
            ms(match_nonterminal(rhs_nm, special_idents::tt, 1u)),
        ], Some(SEMI), false, 0u, 2u)),
        //to phase into semicolon-termination instead of
        //semicolon-separation
        ms(match_seq(~[ms(match_tok(SEMI))], None, true, 2u, 2u))];

    // Parse the macro_rules! invocation (`none` is for no interpolations):
    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                   None,
                                   arg.clone());
    let argument_map = parse_or_else(cx.parse_sess(),
                                     cx.cfg(),
                                     arg_reader as @mut reader,
                                     argument_gram);

    // Extract the arguments:
    let lhses = match *argument_map.get(&lhs_nm) {
        @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
        _ => cx.span_bug(sp, "wrong-structured lhs")
    };

    let rhses = match *argument_map.get(&rhs_nm) {
      @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
      _ => cx.span_bug(sp, "wrong-structured rhs")
    };

    // Given `lhses` and `rhses`, this is the new macro we create
    fn generic_extension(cx: @ExtCtxt,
                         sp: Span,
                         name: Ident,
                         arg: &[ast::token_tree],
                         lhses: &[@named_match],
                         rhses: &[@named_match])
                         -> MacResult {
        if cx.trace_macros() {
            println!("{}! \\{ {} \\}",
                      cx.str_of(name),
                      print::pprust::tt_to_str(
                          &ast::tt_delim(@mut arg.to_owned()),
                          get_ident_interner()));
        }

        // Which arm's failure should we report? (the one furthest along)
        let mut best_fail_spot = dummy_sp();
        let mut best_fail_msg = ~"internal error: ran no matchers";

        let s_d = cx.parse_sess().span_diagnostic;

        for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
            match *lhs {
              @matched_nonterminal(nt_matchers(ref mtcs)) => {
                // `none` is because we're not interpolating
                let arg_rdr = new_tt_reader(
                    s_d,
                    None,
                    arg.to_owned()
                ) as @mut reader;
                match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
                  success(named_matches) => {
                    let rhs = match rhses[i] {
                        // okay, what's your transcriber?
                        @matched_nonterminal(nt_tt(@ref tt)) => {
                            match (*tt) {
                                // cut off delimiters; don't parse 'em
                                tt_delim(ref tts) => {
                                    (*tts).slice(1u,(*tts).len()-1u).to_owned()
                                }
                                _ => cx.span_fatal(
                                    sp, "macro rhs must be delimited")
                            }
                        },
                        _ => cx.span_bug(sp, "bad thing in rhs")
                    };
                    // rhs has holes ( `$id` and `$(...)` that need filled)
                    let trncbr = new_tt_reader(s_d, Some(named_matches),
                                               rhs);
                    let p = @Parser(cx.parse_sess(),
                                    cx.cfg(),
                                    trncbr as @mut reader);

                    // Let the context choose how to interpret the result.
                    // Weird, but useful for X-macros.
                    return MRAny(@ParserAnyMacro {
                        parser: p
                    } as @AnyMacro);
                  }
                  failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                    best_fail_spot = sp;
                    best_fail_msg = (*msg).clone();
                  },
                  error(sp, ref msg) => cx.span_fatal(sp, (*msg))
                }
              }
              _ => cx.bug("non-matcher found in parsed lhses")
            }
        }
        cx.span_fatal(best_fail_spot, best_fail_msg);
    }

    let exp = @MacroRulesSyntaxExpanderTTFun {
        name: name,
        lhses: lhses,
        rhses: rhses,
    } as @SyntaxExpanderTTTrait;

    return MRDef(MacroDef {
        name: ident_to_str(&name),
        ext: NormalTT(exp, Some(sp))
    });
}
<commit_msg>syntax: remove some dead code.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
use ast::{tt_delim};
use ast;
use codemap::{Span, Spanned, dummy_sp};
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
use ext::base::{NormalTT, SyntaxExpanderTTTrait};
use ext::base;
use ext::tt::macro_parser::{error};
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
use parse::lexer::{new_tt_reader, reader};
use parse::parser::Parser;
use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_str};
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
use print;

struct ParserAnyMacro {
    parser: @Parser,
}

impl AnyMacro for ParserAnyMacro {
    fn make_expr(&self) -> @ast::Expr {
        self.parser.parse_expr()
    }
    fn make_item(&self) -> Option<@ast::item> {
        self.parser.parse_item(~[])     // no attrs
    }
    fn make_stmt(&self) -> @ast::Stmt {
        self.parser.parse_stmt(~[])     // no attrs
    }
}

struct MacroRulesSyntaxExpanderTTFun {
    name: Ident,
    lhses: @~[@named_match],
    rhses: @~[@named_match],
}

impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
    fn expand(&self,
              cx: @ExtCtxt,
              sp: Span,
              arg: &[ast::token_tree],
              _: ast::SyntaxContext)
              -> MacResult {
        generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
    }
}

// Given `lhses` and `rhses`, this is the new macro we create
fn generic_extension(cx: @ExtCtxt,
                     sp: Span,
                     name: Ident,
                     arg: &[ast::token_tree],
                     lhses: &[@named_match],
                     rhses: &[@named_match])
                     -> MacResult {
    if cx.trace_macros() {
        println!("{}! \\{ {} \\}",
                  cx.str_of(name),
                  print::pprust::tt_to_str(
                      &ast::tt_delim(@mut arg.to_owned()),
                      get_ident_interner()));
    }

    // Which arm's failure should we report? (the one furthest along)
    let mut best_fail_spot = dummy_sp();
    let mut best_fail_msg = ~"internal error: ran no matchers";

    let s_d = cx.parse_sess().span_diagnostic;

    for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
        match *lhs {
          @matched_nonterminal(nt_matchers(ref mtcs)) => {
            // `none` is because we're not interpolating
            let arg_rdr = new_tt_reader(
                s_d,
                None,
                arg.to_owned()
            ) as @mut reader;
            match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
              success(named_matches) => {
                let rhs = match rhses[i] {
                    // okay, what's your transcriber?
                    @matched_nonterminal(nt_tt(@ref tt)) => {
                        match (*tt) {
                            // cut off delimiters; don't parse 'em
                            tt_delim(ref tts) => {
                                (*tts).slice(1u,(*tts).len()-1u).to_owned()
                            }
                            _ => cx.span_fatal(
                                sp, "macro rhs must be delimited")
                        }
                    },
                    _ => cx.span_bug(sp, "bad thing in rhs")
                };
                // rhs has holes ( `$id` and `$(...)` that need filled)
                let trncbr = new_tt_reader(s_d, Some(named_matches),
                                           rhs);
                let p = @Parser(cx.parse_sess(),
                                cx.cfg(),
                                trncbr as @mut reader);

                // Let the context choose how to interpret the result.
                // Weird, but useful for X-macros.
                return MRAny(@ParserAnyMacro {
                    parser: p,
                } as @AnyMacro)
              }
              failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                best_fail_spot = sp;
                best_fail_msg = (*msg).clone();
              },
              error(sp, ref msg) => cx.span_fatal(sp, (*msg))
            }
          }
          _ => cx.bug("non-matcher found in parsed lhses")
        }
    }
    cx.span_fatal(best_fail_spot, best_fail_msg);
}

// this procedure performs the expansion of the
// macro_rules! macro. It parses the RHS and adds
// an extension to the current context.
pub fn add_new_extension(cx: @ExtCtxt,
                         sp: Span,
                         name: Ident,
                         arg: ~[ast::token_tree],
                         _: ast::SyntaxContext)
                         -> base::MacResult {
    // these spans won't matter, anyways
    fn ms(m: matcher_) -> matcher {
        Spanned {
            node: m.clone(),
            span: dummy_sp()
        }
    }

    let lhs_nm =  gensym_ident("lhs");
    let rhs_nm =  gensym_ident("rhs");

    // The pattern that macro_rules matches.
    // The grammar for macro_rules! is:
    // $( $lhs:mtcs => $rhs:tt );+
    // ...quasiquoting this would be nice.
    let argument_gram = ~[
        ms(match_seq(~[
            ms(match_nonterminal(lhs_nm, special_idents::matchers, 0u)),
            ms(match_tok(FAT_ARROW)),
            ms(match_nonterminal(rhs_nm, special_idents::tt, 1u)),
        ], Some(SEMI), false, 0u, 2u)),
        //to phase into semicolon-termination instead of
        //semicolon-separation
        ms(match_seq(~[ms(match_tok(SEMI))], None, true, 2u, 2u))];

    // Parse the macro_rules! invocation (`none` is for no interpolations):
    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                   None,
                                   arg.clone());
    let argument_map = parse_or_else(cx.parse_sess(),
                                     cx.cfg(),
                                     arg_reader as @mut reader,
                                     argument_gram);

    // Extract the arguments:
    let lhses = match *argument_map.get(&lhs_nm) {
        @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
        _ => cx.span_bug(sp, "wrong-structured lhs")
    };

    let rhses = match *argument_map.get(&rhs_nm) {
      @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
      _ => cx.span_bug(sp, "wrong-structured rhs")
    };

    let exp = @MacroRulesSyntaxExpanderTTFun {
        name: name,
        lhses: lhses,
        rhses: rhses,
    } as @SyntaxExpanderTTTrait;

    return MRDef(MacroDef {
        name: ident_to_str(&name),
        ext: NormalTT(exp, Some(sp))
    });
}
<|endoftext|>


<commit_before><commit_msg>05 - alias<commit_after>// `NanoSecond` is a new name for `u64`
type NanoSecond = u64;
type Inch = u64;

// Types must have CamelCase names, or the compiler will raise a warning.
// The exception to this rule are the primitive types: uint, f32, etc.
// Use an attribute to silence warning.
#[allow(non_camel_case_types)]
type uint64_t = u64;

fn main() {
    // `NanoSecond` = `Inch` = `uint64_t` = `u64`
    let nanoseconds: NanoSecond = 5 as uint64_t;
    let inches: Inch = 2 as uint64_t;

    // Note that type aliases *don't* provide any extra type safety, because
    // aliases are *not* new types
    println!("{} nanoseconds + {} inches = {} unit?",
             nanoseconds,
             inches,
             nanoseconds + inches);
}
<|endoftext|>


<commit_before><commit_msg>test: Make issue-2590 conform to the spirit of the test better<commit_after><|endoftext|>


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

use x = m::f; //~ ERROR failed to resolve imports

mod m {
}

fn main() {
}
<commit_msg>actually fix failing test<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use x = m::f; //~ ERROR failed to resolve import

mod m {
}

fn main() {
}
<|endoftext|>


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

use rustc::traits::{Normalized, ObligationCause};
use rustc::traits::query::NoSolution;
use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
use rustc::util::common::CellUsizeExt;

crate fn normalize_ty_after_erasing_regions<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Ty<'tcx> {
    let ParamEnvAnd { param_env, value } = goal;
    tcx.sess.perf_stats.normalize_ty_after_erasing_regions.increment();
    tcx.infer_ctxt().enter(|infcx| {
        let cause = ObligationCause::dummy();
        match infcx.at(&cause, param_env).normalize(&value) {
            Ok(Normalized { value: normalized_value, obligations: _ }) => {
                //                                   ^^^^^^^^^^^
                //                   We don't care about the `obligations`,
                //                   they are always only region relations,
                //                   and we are about to erase those anyway.
                let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value);
                let normalized_value = infcx.tcx.erase_regions(&normalized_value);
                tcx.lift_to_global(&normalized_value).unwrap()
            }
            Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
        }
    })
}
<commit_msg>add a debug assertion that only outlives-oblig. result from norm.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::traits::{Normalized, ObligationCause};
use rustc::traits::query::NoSolution;
use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use rustc::util::common::CellUsizeExt;

crate fn normalize_ty_after_erasing_regions<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Ty<'tcx> {
    let ParamEnvAnd { param_env, value } = goal;
    tcx.sess
        .perf_stats
        .normalize_ty_after_erasing_regions
        .increment();
    tcx.infer_ctxt().enter(|infcx| {
        let cause = ObligationCause::dummy();
        match infcx.at(&cause, param_env).normalize(&value) {
            Ok(Normalized {
                value: normalized_value,
                obligations: normalized_obligations,
            }) => {
                // We don't care about the `obligations`; they are
                // always only region relations, and we are about to
                // erase those anyway:
                debug_assert_eq!(
                    normalized_obligations
                        .iter()
                        .find(|p| not_outlives_predicate(&p.predicate)),
                    None,
                );

                let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value);
                let normalized_value = infcx.tcx.erase_regions(&normalized_value);
                tcx.lift_to_global(&normalized_value).unwrap()
            }
            Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
        }
    })
}

fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool {
    match p {
        ty::Predicate::RegionOutlives(..) | ty::Predicate::TypeOutlives(..) => false,
        ty::Predicate::Trait(..)
        | ty::Predicate::Projection(..)
        | ty::Predicate::WellFormed(..)
        | ty::Predicate::ObjectSafe(..)
        | ty::Predicate::ClosureKind(..)
        | ty::Predicate::Subtype(..)
        | ty::Predicate::ConstEvaluatable(..) => true,
    }
}
<|endoftext|>


<commit_before><commit_msg>rust version<commit_after><|endoftext|>


<commit_before>use mio::*;
use mio::tcp::*;
use mio::buf::{ByteBuf, MutByteBuf, SliceBuf};
use mio::util::Slab;
use std::io;
use super::localhost;

const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

struct EchoConn {
    sock: TcpStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet
}

impl EchoConn {
    fn new(sock: TcpStream) -> EchoConn {
        EchoConn {
            sock: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            token: None,
            interest: EventSet::hup()
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        let mut buf = self.buf.take().unwrap();

        match self.sock.try_write_buf(&mut buf) {
            Ok(None) => {
                debug!("client flushing buf; WOULDBLOCK");

                self.buf = Some(buf);
                self.interest.insert(EventSet::writable());
            }
            Ok(Some(r)) => {
                debug!("CONN : we wrote {} bytes!", r);

                self.mut_buf = Some(buf.flip());

                self.interest.insert(EventSet::readable());
                self.interest.remove(EventSet::writable());
            }
            Err(e) => debug!("not implemented; client err={:?}", e),
        }

        event_loop.reregister(&self.sock, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap();

        match self.sock.try_read_buf(&mut buf) {
            Ok(None) => {
                panic!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                debug!("CONN : we read {} bytes!", r);
                self.interest.remove(EventSet::readable());
                self.interest.insert(EventSet::writable());
            }
            Err(e) => {
                debug!("not implemented; client err={:?}", e);
                self.interest.remove(EventSet::readable());
            }

        };

        // prepare to provide this to writable
        self.buf = Some(buf.flip());
        event_loop.reregister(&self.sock, self.token.unwrap(), self.interest, PollOpt::edge())
    }
}

struct EchoServer {
    sock: TcpListener,
    conns: Slab<EchoConn>
}

impl EchoServer {
    fn accept(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("server accepting socket");

        let sock = self.sock.accept().unwrap().unwrap();
        let conn = EchoConn::new(sock,);
        let tok = self.conns.insert(conn)
            .ok().expect("could not add connectiont o slab");

        // Register the connection
        self.conns[tok].token = Some(tok);
        event_loop.register_opt(&self.conns[tok].sock, tok, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
            .ok().expect("could not register socket with event loop");

        Ok(())
    }

    fn conn_readable(&mut self, event_loop: &mut EventLoop<Echo>, tok: Token) -> io::Result<()> {
        debug!("server conn readable; tok={:?}", tok);
        self.conn(tok).readable(event_loop)
    }

    fn conn_writable(&mut self, event_loop: &mut EventLoop<Echo>, tok: Token) -> io::Result<()> {
        debug!("server conn writable; tok={:?}", tok);
        self.conn(tok).writable(event_loop)
    }

    fn conn<'a>(&'a mut self, tok: Token) -> &'a mut EchoConn {
        &mut self.conns[tok]
    }
}

struct EchoClient {
    sock: TcpStream,
    msgs: Vec<&'static str>,
    tx: SliceBuf<'static>,
    rx: SliceBuf<'static>,
    mut_buf: Option<MutByteBuf>,
    token: Token,
    interest: EventSet
}

// Sends a message and expects to receive the same exact message, one at a time
impl EchoClient {
    fn new(sock: TcpStream, tok: Token,  mut msgs: Vec<&'static str>) -> EchoClient {
        let curr = msgs.remove(0);

        EchoClient {
            sock: sock,
            msgs: msgs,
            tx: SliceBuf::wrap(curr.as_bytes()),
            rx: SliceBuf::wrap(curr.as_bytes()),
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            token: tok,
            interest: EventSet::none()
        }
    }

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("client socket readable");

        let mut buf = self.mut_buf.take().unwrap();

        match self.sock.try_read_buf(&mut buf) {
            Ok(None) => {
                panic!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                debug!("CLIENT : We read {} bytes!", r);
            }
            Err(e) => {
                panic!("not implemented; client err={:?}", e);
            }
        };

        // prepare for reading
        let mut buf = buf.flip();

        while buf.has_remaining() {
            let actual = buf.read_byte().unwrap();
            let expect = self.rx.read_byte().unwrap();

            assert!(actual == expect, "actual={}; expect={}", actual, expect);
        }

        self.mut_buf = Some(buf.flip());

        self.interest.remove(EventSet::readable());

        if !self.rx.has_remaining() {
            self.next_msg(event_loop).unwrap();
        }

        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("client socket writable");

        match self.sock.try_write_buf(&mut self.tx) {
            Ok(None) => {
                debug!("client flushing buf; WOULDBLOCK");
                self.interest.insert(EventSet::writable());
            }
            Ok(Some(r)) => {
                debug!("CLIENT : we wrote {} bytes!", r);
                self.interest.insert(EventSet::readable());
                self.interest.remove(EventSet::writable());
            }
            Err(e) => debug!("not implemented; client err={:?}", e)
        }

        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn next_msg(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        if self.msgs.is_empty() {
            event_loop.shutdown();
            return Ok(());
        }

        let curr = self.msgs.remove(0);

        debug!("client prepping next message");
        self.tx = SliceBuf::wrap(curr.as_bytes());
        self.rx = SliceBuf::wrap(curr.as_bytes());

        self.interest.insert(EventSet::writable());
        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct Echo {
    server: EchoServer,
    client: EchoClient,
}

impl Echo {
    fn new(srv: TcpListener, client: TcpStream, msgs: Vec<&'static str>) -> Echo {
        Echo {
            server: EchoServer {
                sock: srv,
                conns: Slab::new_starting_at(Token(2), 128)
            },
            client: EchoClient::new(client, CLIENT, msgs)
        }
    }
}

impl Handler for Echo {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Echo>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.server.accept(event_loop).unwrap(),
                CLIENT => self.client.readable(event_loop).unwrap(),
                i => self.server.conn_readable(event_loop, i).unwrap()
            }
        }

        if events.is_writable() {
            match token {
                SERVER => panic!("received writable for token 0"),
                CLIENT => self.client.writable(event_loop).unwrap(),
                _ => self.server.conn_writable(event_loop, token).unwrap()
            };
        }
    }
}

#[test]
pub fn test_echo_server() {
    debug!("Starting TEST_ECHO_SERVER");
    let mut event_loop = EventLoop::new().unwrap();

    let addr = localhost();
    let srv = TcpListener::bind(&addr).unwrap();

    info!("listen for connections");
    event_loop.register_opt(&srv, SERVER, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    let (sock, _) = TcpSocket::v4().unwrap()
        .connect(&addr).unwrap();

    // Connect to the server
    event_loop.register_opt(&sock, CLIENT, EventSet::writable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    // Start the event loop
    event_loop.run(&mut Echo::new(srv, sock, vec!["foo", "bar"])).unwrap();
}
<commit_msg>Fix typo<commit_after>use mio::*;
use mio::tcp::*;
use mio::buf::{ByteBuf, MutByteBuf, SliceBuf};
use mio::util::Slab;
use std::io;
use super::localhost;

const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

struct EchoConn {
    sock: TcpStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet
}

impl EchoConn {
    fn new(sock: TcpStream) -> EchoConn {
        EchoConn {
            sock: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            token: None,
            interest: EventSet::hup()
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        let mut buf = self.buf.take().unwrap();

        match self.sock.try_write_buf(&mut buf) {
            Ok(None) => {
                debug!("client flushing buf; WOULDBLOCK");

                self.buf = Some(buf);
                self.interest.insert(EventSet::writable());
            }
            Ok(Some(r)) => {
                debug!("CONN : we wrote {} bytes!", r);

                self.mut_buf = Some(buf.flip());

                self.interest.insert(EventSet::readable());
                self.interest.remove(EventSet::writable());
            }
            Err(e) => debug!("not implemented; client err={:?}", e),
        }

        event_loop.reregister(&self.sock, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap();

        match self.sock.try_read_buf(&mut buf) {
            Ok(None) => {
                panic!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                debug!("CONN : we read {} bytes!", r);
                self.interest.remove(EventSet::readable());
                self.interest.insert(EventSet::writable());
            }
            Err(e) => {
                debug!("not implemented; client err={:?}", e);
                self.interest.remove(EventSet::readable());
            }

        };

        // prepare to provide this to writable
        self.buf = Some(buf.flip());
        event_loop.reregister(&self.sock, self.token.unwrap(), self.interest, PollOpt::edge())
    }
}

struct EchoServer {
    sock: TcpListener,
    conns: Slab<EchoConn>
}

impl EchoServer {
    fn accept(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("server accepting socket");

        let sock = self.sock.accept().unwrap().unwrap();
        let conn = EchoConn::new(sock,);
        let tok = self.conns.insert(conn)
            .ok().expect("could not add connection to slab");

        // Register the connection
        self.conns[tok].token = Some(tok);
        event_loop.register_opt(&self.conns[tok].sock, tok, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
            .ok().expect("could not register socket with event loop");

        Ok(())
    }

    fn conn_readable(&mut self, event_loop: &mut EventLoop<Echo>, tok: Token) -> io::Result<()> {
        debug!("server conn readable; tok={:?}", tok);
        self.conn(tok).readable(event_loop)
    }

    fn conn_writable(&mut self, event_loop: &mut EventLoop<Echo>, tok: Token) -> io::Result<()> {
        debug!("server conn writable; tok={:?}", tok);
        self.conn(tok).writable(event_loop)
    }

    fn conn<'a>(&'a mut self, tok: Token) -> &'a mut EchoConn {
        &mut self.conns[tok]
    }
}

struct EchoClient {
    sock: TcpStream,
    msgs: Vec<&'static str>,
    tx: SliceBuf<'static>,
    rx: SliceBuf<'static>,
    mut_buf: Option<MutByteBuf>,
    token: Token,
    interest: EventSet
}

// Sends a message and expects to receive the same exact message, one at a time
impl EchoClient {
    fn new(sock: TcpStream, tok: Token,  mut msgs: Vec<&'static str>) -> EchoClient {
        let curr = msgs.remove(0);

        EchoClient {
            sock: sock,
            msgs: msgs,
            tx: SliceBuf::wrap(curr.as_bytes()),
            rx: SliceBuf::wrap(curr.as_bytes()),
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            token: tok,
            interest: EventSet::none()
        }
    }

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("client socket readable");

        let mut buf = self.mut_buf.take().unwrap();

        match self.sock.try_read_buf(&mut buf) {
            Ok(None) => {
                panic!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                debug!("CLIENT : We read {} bytes!", r);
            }
            Err(e) => {
                panic!("not implemented; client err={:?}", e);
            }
        };

        // prepare for reading
        let mut buf = buf.flip();

        while buf.has_remaining() {
            let actual = buf.read_byte().unwrap();
            let expect = self.rx.read_byte().unwrap();

            assert!(actual == expect, "actual={}; expect={}", actual, expect);
        }

        self.mut_buf = Some(buf.flip());

        self.interest.remove(EventSet::readable());

        if !self.rx.has_remaining() {
            self.next_msg(event_loop).unwrap();
        }

        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        debug!("client socket writable");

        match self.sock.try_write_buf(&mut self.tx) {
            Ok(None) => {
                debug!("client flushing buf; WOULDBLOCK");
                self.interest.insert(EventSet::writable());
            }
            Ok(Some(r)) => {
                debug!("CLIENT : we wrote {} bytes!", r);
                self.interest.insert(EventSet::readable());
                self.interest.remove(EventSet::writable());
            }
            Err(e) => debug!("not implemented; client err={:?}", e)
        }

        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn next_msg(&mut self, event_loop: &mut EventLoop<Echo>) -> io::Result<()> {
        if self.msgs.is_empty() {
            event_loop.shutdown();
            return Ok(());
        }

        let curr = self.msgs.remove(0);

        debug!("client prepping next message");
        self.tx = SliceBuf::wrap(curr.as_bytes());
        self.rx = SliceBuf::wrap(curr.as_bytes());

        self.interest.insert(EventSet::writable());
        event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct Echo {
    server: EchoServer,
    client: EchoClient,
}

impl Echo {
    fn new(srv: TcpListener, client: TcpStream, msgs: Vec<&'static str>) -> Echo {
        Echo {
            server: EchoServer {
                sock: srv,
                conns: Slab::new_starting_at(Token(2), 128)
            },
            client: EchoClient::new(client, CLIENT, msgs)
        }
    }
}

impl Handler for Echo {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Echo>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.server.accept(event_loop).unwrap(),
                CLIENT => self.client.readable(event_loop).unwrap(),
                i => self.server.conn_readable(event_loop, i).unwrap()
            }
        }

        if events.is_writable() {
            match token {
                SERVER => panic!("received writable for token 0"),
                CLIENT => self.client.writable(event_loop).unwrap(),
                _ => self.server.conn_writable(event_loop, token).unwrap()
            };
        }
    }
}

#[test]
pub fn test_echo_server() {
    debug!("Starting TEST_ECHO_SERVER");
    let mut event_loop = EventLoop::new().unwrap();

    let addr = localhost();
    let srv = TcpListener::bind(&addr).unwrap();

    info!("listen for connections");
    event_loop.register_opt(&srv, SERVER, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    let (sock, _) = TcpSocket::v4().unwrap()
        .connect(&addr).unwrap();

    // Connect to the server
    event_loop.register_opt(&sock, CLIENT, EventSet::writable(), PollOpt::edge() | PollOpt::oneshot()).unwrap();

    // Start the event loop
    event_loop.run(&mut Echo::new(srv, sock, vec!["foo", "bar"])).unwrap();
}
<|endoftext|>


<commit_before><commit_msg>Check-in new threadpool<commit_after>//! A thread pool for running blocking functions asynchronously.

use std::sync::atomic::{AtomicU64, Ordering};
use std::thread;
use std::time::Duration;

use crossbeam::channel::{bounded, Receiver, Sender};
use lazy_static::lazy_static;

use super::Promise;

const MAX_THREADS: u64 = 10_000;

static DYNAMIC_THREAD_COUNT: AtomicU64 = AtomicU64::new(0);

struct Pool {
    sender: Sender<Box<FnOnce() + Send + 'static>>,
    receiver: Receiver<Box<FnOnce() + Send + 'static>>,
}

lazy_static! {
    static ref POOL: Pool = {
        for _ in 0..2 {
            thread::Builder::new()
                .name("async-blocking-driver".to_string())
                .spawn(|| {
                    for task in &POOL.receiver {
                        (task)()
                    }
                })
                .expect("cannot start a thread driving blocking tasks");
        }

        // We want to use an unbuffered channel here to help
        // us drive our dynamic control. In effect, the
        // kernel's scheduler becomes the queue, reducing
        // the number of buffers that work must flow through
        // before being acted on by a core. This helps keep
        // latency snappy in the overall async system by
        // reducing bufferbloat.
        let (sender, receiver) = bounded(0);
        Pool { sender, receiver }
    };
}

// Create up to MAX_THREADS dynamic blocking task worker threads.
// Dynamic threads will terminate themselves if they don't
// receive any work after one second.
fn maybe_create_another_blocking_thread() {
    // We use a `Relaxed` atomic operation because
    // it's just a heuristic, and would not lose correctness
    // even if it's random.
    let workers = DYNAMIC_THREAD_COUNT.load(Ordering::Relaxed);
    if workers >= MAX_THREADS {
        return;
    }

    thread::Builder::new()
        .name("async-blocking-driver-dynamic".to_string())
        .spawn(|| {
            let wait_limit = Duration::from_secs(1);

            DYNAMIC_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
            while let Ok(task) = POOL.receiver.recv_timeout(wait_limit) {
                (task)();
            }
            DYNAMIC_THREAD_COUNT.fetch_sub(1, Ordering::Relaxed);
        })
        .expect("cannot start a dynamic thread driving blocking tasks");
}

/// Spawns a blocking task.
///
/// The task will be spawned onto a thread pool specifically dedicated to blocking tasks.
pub fn spawn<F, R>(work: F) -> Promise<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    let (promise_filler, promise) = Promise::pair();
    let task = move || {
        let result = (work)();
        promise_filler.fill(result);
    };
    let first_try_result = POOL.sender.try_send(Box::new(task));
    match first_try_result {
        Ok(()) => {
            // NICEEEE
        }
        Err(crossbeam::channel::TrySendError::Full(task)) => {
            // We were not able to send to the channel without
            // blocking. Try to spin up another thread and then
            // retry sending while blocking.
            maybe_create_another_blocking_thread();
            POOL.sender.send(task).unwrap()
        }
        Err(crossbeam::channel::TrySendError::Disconnected(_)) => {
            panic!(
                "unable to send to blocking threadpool \
                 due to receiver disconnection"
            );
        }
    }
    promise
}
<|endoftext|>


<commit_before><commit_msg>Impl PartialEq for Intention<commit_after><|endoftext|>


<commit_before><commit_msg>Add test to exercise InvalidUndefBytes<commit_after>// error-pattern: reading uninitialized memory

use std::alloc::{alloc, dealloc, Layout};
use std::slice::from_raw_parts;

fn main() {
    let layout = Layout::from_size_align(32, 8).unwrap();
    unsafe {
        let ptr = alloc(layout);
        *ptr = 0x41;
        *ptr.add(1) = 0x42;
        *ptr.add(2) = 0x43;
        *ptr.add(3) = 0x44;
        *ptr.add(16) = 0x00;
        let slice1 = from_raw_parts(ptr, 16);
        let slice2 = from_raw_parts(ptr.add(16), 16);
        drop(slice1.cmp(slice2));
        dealloc(ptr, layout);
    }
}
<|endoftext|>


<commit_before>//! Tests for the -Zrustdoc-map feature.

use cargo_test_support::registry::Package;
use cargo_test_support::{is_nightly, paths, project, Project};

fn basic_project() -> Project {
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<bar::Straw> {
                    None
                }
            "#,
        )
        .build()
}

#[cargo_test]
fn ignores_on_stable() {
    // Requires -Zrustdoc-map to use.
    let p = basic_project();
    p.cargo("doc -v --no-deps")
        .with_stderr_does_not_contain("[..]--extern-html-root-url[..]")
        .run();
}

#[cargo_test]
fn simple() {
    // Basic test that it works with crates.io.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    let p = basic_project();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]bar=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn std_docs() {
    // Mapping std docs somewhere else.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    // For local developers, skip this test if docs aren't installed.
    let docs = std::path::Path::new(&paths::sysroot()).join("share/doc/rust/html");
    if !docs.exists() {
        if cargo::util::is_ci() {
            panic!("std docs are not installed, check that the rust-docs component is installed");
        } else {
            eprintln!(
                "documentation not found at {}, \
                skipping test (run `rustdoc component add rust-docs` to install",
                docs.display()
            );
            return;
        }
    }
    let p = basic_project();
    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map]
            std = "local"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--crate-name foo [..]std=file://[..]")
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"share/doc/rust/html/core/option/enum.Option.html""#));

    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map]
            std = "https://example.com/rust/"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]std=https://example.com/rust/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://example.com/rust/core/option/enum.Option.html""#));
}

#[cargo_test]
fn renamed_dep() {
    // Handles renamed dependencies.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                groovy = { version = "1.0", package = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<groovy::Straw> {
                    None
                }
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]bar=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn lib_name() {
    // Handles lib name != package name.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "bar"
                version = "1.0.0"

                [lib]
                name = "rumpelstiltskin"
            "#,
        )
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"

                [dependencies]
                bar = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<rumpelstiltskin::Straw> {
                    None
                }
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]rumpelstiltskin=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/rumpelstiltskin/struct.Straw.html""#));
}

#[cargo_test]
fn alt_registry() {
    // Supports other registry names.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .alternative(true)
        .file(
            "src/lib.rs",
            r#"
                extern crate baz;
                pub struct Queen;
                pub use baz::King;
            "#,
        )
        .registry_dep("baz", "1.0")
        .publish();
    Package::new("baz", "1.0.0")
        .alternative(true)
        .file("src/lib.rs", "pub struct King;")
        .publish();
    Package::new("grimm", "1.0.0")
        .file("src/lib.rs", "pub struct Gold;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = { version = "1.0", registry="alternative" }
                grimm = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn queen() -> bar::Queen { bar::Queen }
                pub fn king() -> bar::King { bar::King }
                pub fn gold() -> grimm::Gold { grimm::Gold }
            "#,
        )
        .file(
            ".cargo/config",
            r#"
                [doc.extern-map.registries]
                alternative = "https://example.com/{pkg_name}/{version}/"
                crates-io = "https://docs.rs/"
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo \
            [..]bar=https://example.com/bar/1.0.0/[..]grimm=https://docs.rs/grimm/1.0.0/[..]",
        )
        .run();
    let queen = p.read_file("target/doc/foo/fn.queen.html");
    assert!(queen.contains(r#"href="https://example.com/bar/1.0.0/bar/struct.Queen.html""#));
    // The king example fails to link. Rustdoc seems to want the origin crate
    // name (baz) for re-exports. There are many issues in the issue tracker
    // for rustdoc re-exports, so I'm not sure, but I think this is maybe a
    // rustdoc issue. Alternatively, Cargo could provide mappings for all
    // transitive dependencies to fix this.
    let king = p.read_file("target/doc/foo/fn.king.html");
    assert!(king.contains(r#"-> King"#));

    let gold = p.read_file("target/doc/foo/fn.gold.html");
    assert!(gold.contains(r#"href="https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html""#));
}

#[cargo_test]
fn multiple_versions() {
    // What happens when there are multiple versions.
    // NOTE: This is currently broken behavior. Rustdoc does not provide a way
    // to match renamed dependencies.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Spin;")
        .publish();
    Package::new("bar", "2.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = "1.0"
                bar2 = {version="2.0", package="bar"}
            "#,
        )
        .file(
            "src/lib.rs",
            "
                pub fn fn1() -> bar::Spin {bar::Spin}
                pub fn fn2() -> bar2::Straw {bar2::Straw}
            ",
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo \
            [..]bar=https://docs.rs/bar/1.0.0/[..]bar=https://docs.rs/bar/2.0.0/[..]",
        )
        .run();
    let fn1 = p.read_file("target/doc/foo/fn.fn1.html");
    // This should be 1.0.0, rustdoc seems to use the last entry when there
    // are duplicates.
    assert!(fn1.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Spin.html""#));
    let fn2 = p.read_file("target/doc/foo/fn.fn2.html");
    assert!(fn2.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn rebuilds_when_changing() {
    // Make sure it rebuilds if the map changes.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    let p = basic_project();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[..]--extern-html-root-url[..]")
        .run();

    // This also tests that the map for docs.rs can be overridden.
    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map.registries]
            crates-io = "https://example.com/"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--extern-html-root-url 'bar=https://example.com/bar/1.0.0/[..]' [..]",
        )
        .run();
}
<commit_msg>Fix inconsistency with quoting<commit_after>//! Tests for the -Zrustdoc-map feature.

use cargo_test_support::registry::Package;
use cargo_test_support::{is_nightly, paths, project, Project};

fn basic_project() -> Project {
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<bar::Straw> {
                    None
                }
            "#,
        )
        .build()
}

#[cargo_test]
fn ignores_on_stable() {
    // Requires -Zrustdoc-map to use.
    let p = basic_project();
    p.cargo("doc -v --no-deps")
        .with_stderr_does_not_contain("[..]--extern-html-root-url[..]")
        .run();
}

#[cargo_test]
fn simple() {
    // Basic test that it works with crates.io.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    let p = basic_project();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]bar=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn std_docs() {
    // Mapping std docs somewhere else.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    // For local developers, skip this test if docs aren't installed.
    let docs = std::path::Path::new(&paths::sysroot()).join("share/doc/rust/html");
    if !docs.exists() {
        if cargo::util::is_ci() {
            panic!("std docs are not installed, check that the rust-docs component is installed");
        } else {
            eprintln!(
                "documentation not found at {}, \
                skipping test (run `rustdoc component add rust-docs` to install",
                docs.display()
            );
            return;
        }
    }
    let p = basic_project();
    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map]
            std = "local"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--crate-name foo [..]std=file://[..]")
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"share/doc/rust/html/core/option/enum.Option.html""#));

    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map]
            std = "https://example.com/rust/"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]std=https://example.com/rust/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://example.com/rust/core/option/enum.Option.html""#));
}

#[cargo_test]
fn renamed_dep() {
    // Handles renamed dependencies.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                groovy = { version = "1.0", package = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<groovy::Straw> {
                    None
                }
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]bar=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn lib_name() {
    // Handles lib name != package name.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "bar"
                version = "1.0.0"

                [lib]
                name = "rumpelstiltskin"
            "#,
        )
        .file("src/lib.rs", "pub struct Straw;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"

                [dependencies]
                bar = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn myfun() -> Option<rumpelstiltskin::Straw> {
                    None
                }
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo [..]rumpelstiltskin=https://docs.rs/bar/1.0.0/[..]",
        )
        .run();
    let myfun = p.read_file("target/doc/foo/fn.myfun.html");
    assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/rumpelstiltskin/struct.Straw.html""#));
}

#[cargo_test]
fn alt_registry() {
    // Supports other registry names.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .alternative(true)
        .file(
            "src/lib.rs",
            r#"
                extern crate baz;
                pub struct Queen;
                pub use baz::King;
            "#,
        )
        .registry_dep("baz", "1.0")
        .publish();
    Package::new("baz", "1.0.0")
        .alternative(true)
        .file("src/lib.rs", "pub struct King;")
        .publish();
    Package::new("grimm", "1.0.0")
        .file("src/lib.rs", "pub struct Gold;")
        .publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = { version = "1.0", registry="alternative" }
                grimm = "1.0"
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                pub fn queen() -> bar::Queen { bar::Queen }
                pub fn king() -> bar::King { bar::King }
                pub fn gold() -> grimm::Gold { grimm::Gold }
            "#,
        )
        .file(
            ".cargo/config",
            r#"
                [doc.extern-map.registries]
                alternative = "https://example.com/{pkg_name}/{version}/"
                crates-io = "https://docs.rs/"
            "#,
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo \
            [..]bar=https://example.com/bar/1.0.0/[..]grimm=https://docs.rs/grimm/1.0.0/[..]",
        )
        .run();
    let queen = p.read_file("target/doc/foo/fn.queen.html");
    assert!(queen.contains(r#"href="https://example.com/bar/1.0.0/bar/struct.Queen.html""#));
    // The king example fails to link. Rustdoc seems to want the origin crate
    // name (baz) for re-exports. There are many issues in the issue tracker
    // for rustdoc re-exports, so I'm not sure, but I think this is maybe a
    // rustdoc issue. Alternatively, Cargo could provide mappings for all
    // transitive dependencies to fix this.
    let king = p.read_file("target/doc/foo/fn.king.html");
    assert!(king.contains(r#"-> King"#));

    let gold = p.read_file("target/doc/foo/fn.gold.html");
    assert!(gold.contains(r#"href="https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html""#));
}

#[cargo_test]
fn multiple_versions() {
    // What happens when there are multiple versions.
    // NOTE: This is currently broken behavior. Rustdoc does not provide a way
    // to match renamed dependencies.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    Package::new("bar", "1.0.0")
        .file("src/lib.rs", "pub struct Spin;")
        .publish();
    Package::new("bar", "2.0.0")
        .file("src/lib.rs", "pub struct Straw;")
        .publish();
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [dependencies]
                bar = "1.0"
                bar2 = {version="2.0", package="bar"}
            "#,
        )
        .file(
            "src/lib.rs",
            "
                pub fn fn1() -> bar::Spin {bar::Spin}
                pub fn fn2() -> bar2::Straw {bar2::Straw}
            ",
        )
        .build();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--crate-name foo \
            [..]bar=https://docs.rs/bar/1.0.0/[..]bar=https://docs.rs/bar/2.0.0/[..]",
        )
        .run();
    let fn1 = p.read_file("target/doc/foo/fn.fn1.html");
    // This should be 1.0.0, rustdoc seems to use the last entry when there
    // are duplicates.
    assert!(fn1.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Spin.html""#));
    let fn2 = p.read_file("target/doc/foo/fn.fn2.html");
    assert!(fn2.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Straw.html""#));
}

#[cargo_test]
fn rebuilds_when_changing() {
    // Make sure it rebuilds if the map changes.
    if !is_nightly() {
        // --extern-html-root-url is unstable
        return;
    }
    let p = basic_project();
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[..]--extern-html-root-url[..]")
        .run();

    // This also tests that the map for docs.rs can be overridden.
    p.change_file(
        ".cargo/config",
        r#"
            [doc.extern-map.registries]
            crates-io = "https://example.com/"
        "#,
    );
    p.cargo("doc -v --no-deps -Zrustdoc-map")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(
            "[RUNNING] `rustdoc [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..]",
        )
        .run();
}
<|endoftext|>