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

use super::constants::*;
use super::evdev::{grab_evdev, ungrab_evdev};
use super::virtio_input_event;
use super::InputError;
use super::Result;
use data_model::DataInit;
use std::collections::VecDeque;
use std::io::Read;
use std::io::Write;
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, RawFd};

#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct input_event {
    timestamp_fields: [u64; 2],
    pub type_: u16,
    pub code: u16,
    pub value: u32,
}
// Safe because it only has data and has no implicit padding.
unsafe impl DataInit for input_event {}

impl input_event {
    const EVENT_SIZE: usize = size_of::<input_event>();

    fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
        input_event {
            timestamp_fields: [0, 0],
            type_: other.type_.into(),
            code: other.code.into(),
            value: other.value.into(),
        }
    }
}

/// Encapsulates a socket or device node into an abstract event source, providing a common
/// interface.
/// It supports read and write operations to provide and accept events just like an event device
/// node would, except that it handles virtio_input_event instead of input_event structures.
/// It's necessary to call receive_events() before events are available for read.
pub trait EventSource: Read + Write + AsRawFd {
    /// Perform any necessary initialization before receiving and sending events from/to the source.
    fn init(&mut self) -> Result<()> {
        Ok(())
    }
    /// Perform any necessary cleanup when the device will no longer be used.
    fn finalize(&mut self) -> Result<()> {
        Ok(())
    }

    /// Receive events from the source, filters them and stores them in a queue for future
    /// consumption by reading from this object. Returns the number of new non filtered events
    /// received. This function may block waiting for events to be available.
    fn receive_events(&mut self) -> Result<usize>;
    /// Returns the number of received events that have not been filtered or consumed yet.
    fn available_events_count(&self) -> usize;
}

// Try to read 16 events at a time to match what the linux guest driver does.
const READ_BUFFER_SIZE: usize = 16 * size_of::<input_event>();

// The read buffer needs to be aligned to the alignment of input_event, which is aligned as u64
#[repr(align(8))]
pub struct ReadBuffer {
    buffer: [u8; READ_BUFFER_SIZE],
}

/// Encapsulates implementation details common to all kinds of event sources.
pub struct EventSourceImpl<T> {
    source: T,
    queue: VecDeque<virtio_input_event>,
    read_buffer: ReadBuffer,
    // The read index accounts for incomplete events read previously.
    read_idx: usize,
}

// Reads input events from the source.
// Events are originally read as input_event structs and converted to virtio_input_event internally.
impl<T: Read> EventSourceImpl<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let mut bytes = 0usize;
        for evt_slice in buf.chunks_exact_mut(virtio_input_event::EVENT_SIZE) {
            match self.queue.pop_front() {
                None => {
                    break;
                }
                Some(evt) => {
                    evt_slice.copy_from_slice(evt.as_slice());
                    bytes += evt_slice.len();
                }
            }
        }
        Ok(bytes)
    }
}

// Writes input events to the source.
// Events come as virtio_input_event structs and are converted to input_event internally.
impl<T: Write> EventSourceImpl<T> {
    fn write<F: Fn(&virtio_input_event) -> bool>(
        &mut self,
        buf: &[u8],
        event_filter: F,
    ) -> std::io::Result<usize> {
        for evt_slice in buf.chunks_exact(virtio_input_event::EVENT_SIZE) {
            // Don't use from_slice() here, the buffer is not guaranteed to be properly aligned.
            let mut vio_evt = virtio_input_event::new(0, 0, 0);
            vio_evt.as_mut_slice().copy_from_slice(evt_slice);
            if !event_filter(&vio_evt) {
                continue;
            }
            let evt = input_event::from_virtio_input_event(&vio_evt);
            self.source.write_all(evt.as_slice())?;
        }

        let len = buf.len() - buf.len() % virtio_input_event::EVENT_SIZE;
        Ok(len)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.source.flush()
    }
}

impl<T: AsRawFd> EventSourceImpl<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.source.as_raw_fd()
    }
}

impl<T> EventSourceImpl<T>
where
    T: Read + Write + AsRawFd,
{
    // Receive events from the source and store them in a queue, unless they should be filtered out.
    fn receive_events<F: Fn(&input_event) -> bool>(&mut self, event_filter: F) -> Result<usize> {
        let read = self
            .source
            .read(&mut self.read_buffer.buffer[self.read_idx..])
            .map_err(|e| InputError::EventsReadError(e))?;
        let buff_size = read + self.read_idx;

        for evt_slice in self
            .read_buffer
            .buffer
            .chunks_exact(input_event::EVENT_SIZE)
        {
            let input_evt = match input_event::from_slice(evt_slice) {
                Some(x) => x,
                None => {
                    // This shouldn't happen because all slices (even the last one) are guaranteed
                    // to have the correct size and be properly aligned.
                    error!(
                        "Failed converting a slice of sice {} to input_event",
                        evt_slice.len()
                    );
                    // Skipping the event here effectively means no events will be received, because
                    // if from_slice fails once it will fail always.
                    continue;
                }
            };
            if !event_filter(&input_evt) {
                continue;
            }
            let vio_evt = virtio_input_event::from_input_event(input_evt);
            self.queue.push_back(vio_evt);
        }

        let remainder = buff_size % input_event::EVENT_SIZE;
        // If there is an incomplete event at the end of the buffer, it needs to be moved to the
        // beginning and the next read operation must write right after it.
        if remainder != 0 {
            warn!("read incomplete event from source");
            // The copy should only happen if there is at least one complete event in the buffer,
            // otherwise source and destination would be the same.
            if buff_size != remainder {
                let (des, src) = self.read_buffer.buffer.split_at_mut(buff_size - remainder);
                des[..remainder].copy_from_slice(src);
            }
        }
        self.read_idx = remainder;

        let received_events = buff_size / input_event::EVENT_SIZE;

        Ok(received_events)
    }

    fn available_events(&self) -> usize {
        self.queue.len()
    }

    fn new(source: T) -> EventSourceImpl<T> {
        EventSourceImpl {
            source,
            queue: VecDeque::new(),
            read_buffer: ReadBuffer {
                buffer: [0u8; READ_BUFFER_SIZE],
            },
            read_idx: 0,
        }
    }
}

/// Encapsulates a (unix) socket as an event source.
pub struct SocketEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> SocketEventSource<T> {
        SocketEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for SocketEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |_evt| true)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for SocketEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        grab_evdev(self)
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}

/// Encapsulates an event device node as an event source
pub struct EvdevEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> EvdevEventSource<T> {
        EvdevEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for EvdevEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |evt| {
            // Miscellaneous events produced by the device are sent back to it by the kernel input
            // subsystem, but because these events are handled by the host kernel as well as the
            // guest the device would get them twice. Which would prompt the device to send the
            // event to the guest again entering an infinite loop.
            evt.type_ != EV_MSC
        })
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for EvdevEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        grab_evdev(self)
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}
<commit_msg>Don't grab input devices created from sockets.<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::constants::*;
use super::evdev::{grab_evdev, ungrab_evdev};
use super::virtio_input_event;
use super::InputError;
use super::Result;
use data_model::DataInit;
use std::collections::VecDeque;
use std::io::Read;
use std::io::Write;
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, RawFd};

#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct input_event {
    timestamp_fields: [u64; 2],
    pub type_: u16,
    pub code: u16,
    pub value: u32,
}
// Safe because it only has data and has no implicit padding.
unsafe impl DataInit for input_event {}

impl input_event {
    const EVENT_SIZE: usize = size_of::<input_event>();

    fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
        input_event {
            timestamp_fields: [0, 0],
            type_: other.type_.into(),
            code: other.code.into(),
            value: other.value.into(),
        }
    }
}

/// Encapsulates a socket or device node into an abstract event source, providing a common
/// interface.
/// It supports read and write operations to provide and accept events just like an event device
/// node would, except that it handles virtio_input_event instead of input_event structures.
/// It's necessary to call receive_events() before events are available for read.
pub trait EventSource: Read + Write + AsRawFd {
    /// Perform any necessary initialization before receiving and sending events from/to the source.
    fn init(&mut self) -> Result<()> {
        Ok(())
    }
    /// Perform any necessary cleanup when the device will no longer be used.
    fn finalize(&mut self) -> Result<()> {
        Ok(())
    }

    /// Receive events from the source, filters them and stores them in a queue for future
    /// consumption by reading from this object. Returns the number of new non filtered events
    /// received. This function may block waiting for events to be available.
    fn receive_events(&mut self) -> Result<usize>;
    /// Returns the number of received events that have not been filtered or consumed yet.
    fn available_events_count(&self) -> usize;
}

// Try to read 16 events at a time to match what the linux guest driver does.
const READ_BUFFER_SIZE: usize = 16 * size_of::<input_event>();

// The read buffer needs to be aligned to the alignment of input_event, which is aligned as u64
#[repr(align(8))]
pub struct ReadBuffer {
    buffer: [u8; READ_BUFFER_SIZE],
}

/// Encapsulates implementation details common to all kinds of event sources.
pub struct EventSourceImpl<T> {
    source: T,
    queue: VecDeque<virtio_input_event>,
    read_buffer: ReadBuffer,
    // The read index accounts for incomplete events read previously.
    read_idx: usize,
}

// Reads input events from the source.
// Events are originally read as input_event structs and converted to virtio_input_event internally.
impl<T: Read> EventSourceImpl<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let mut bytes = 0usize;
        for evt_slice in buf.chunks_exact_mut(virtio_input_event::EVENT_SIZE) {
            match self.queue.pop_front() {
                None => {
                    break;
                }
                Some(evt) => {
                    evt_slice.copy_from_slice(evt.as_slice());
                    bytes += evt_slice.len();
                }
            }
        }
        Ok(bytes)
    }
}

// Writes input events to the source.
// Events come as virtio_input_event structs and are converted to input_event internally.
impl<T: Write> EventSourceImpl<T> {
    fn write<F: Fn(&virtio_input_event) -> bool>(
        &mut self,
        buf: &[u8],
        event_filter: F,
    ) -> std::io::Result<usize> {
        for evt_slice in buf.chunks_exact(virtio_input_event::EVENT_SIZE) {
            // Don't use from_slice() here, the buffer is not guaranteed to be properly aligned.
            let mut vio_evt = virtio_input_event::new(0, 0, 0);
            vio_evt.as_mut_slice().copy_from_slice(evt_slice);
            if !event_filter(&vio_evt) {
                continue;
            }
            let evt = input_event::from_virtio_input_event(&vio_evt);
            self.source.write_all(evt.as_slice())?;
        }

        let len = buf.len() - buf.len() % virtio_input_event::EVENT_SIZE;
        Ok(len)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.source.flush()
    }
}

impl<T: AsRawFd> EventSourceImpl<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.source.as_raw_fd()
    }
}

impl<T> EventSourceImpl<T>
where
    T: Read + Write + AsRawFd,
{
    // Receive events from the source and store them in a queue, unless they should be filtered out.
    fn receive_events<F: Fn(&input_event) -> bool>(&mut self, event_filter: F) -> Result<usize> {
        let read = self
            .source
            .read(&mut self.read_buffer.buffer[self.read_idx..])
            .map_err(|e| InputError::EventsReadError(e))?;
        let buff_size = read + self.read_idx;

        for evt_slice in self
            .read_buffer
            .buffer
            .chunks_exact(input_event::EVENT_SIZE)
        {
            let input_evt = match input_event::from_slice(evt_slice) {
                Some(x) => x,
                None => {
                    // This shouldn't happen because all slices (even the last one) are guaranteed
                    // to have the correct size and be properly aligned.
                    error!(
                        "Failed converting a slice of sice {} to input_event",
                        evt_slice.len()
                    );
                    // Skipping the event here effectively means no events will be received, because
                    // if from_slice fails once it will fail always.
                    continue;
                }
            };
            if !event_filter(&input_evt) {
                continue;
            }
            let vio_evt = virtio_input_event::from_input_event(input_evt);
            self.queue.push_back(vio_evt);
        }

        let remainder = buff_size % input_event::EVENT_SIZE;
        // If there is an incomplete event at the end of the buffer, it needs to be moved to the
        // beginning and the next read operation must write right after it.
        if remainder != 0 {
            warn!("read incomplete event from source");
            // The copy should only happen if there is at least one complete event in the buffer,
            // otherwise source and destination would be the same.
            if buff_size != remainder {
                let (des, src) = self.read_buffer.buffer.split_at_mut(buff_size - remainder);
                des[..remainder].copy_from_slice(src);
            }
        }
        self.read_idx = remainder;

        let received_events = buff_size / input_event::EVENT_SIZE;

        Ok(received_events)
    }

    fn available_events(&self) -> usize {
        self.queue.len()
    }

    fn new(source: T) -> EventSourceImpl<T> {
        EventSourceImpl {
            source,
            queue: VecDeque::new(),
            read_buffer: ReadBuffer {
                buffer: [0u8; READ_BUFFER_SIZE],
            },
            read_idx: 0,
        }
    }
}

/// Encapsulates a (unix) socket as an event source.
pub struct SocketEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> SocketEventSource<T> {
        SocketEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for SocketEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |_evt| true)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for SocketEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        Ok(())
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}

/// Encapsulates an event device node as an event source
pub struct EvdevEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> EvdevEventSource<T> {
        EvdevEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for EvdevEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |evt| {
            // Miscellaneous events produced by the device are sent back to it by the kernel input
            // subsystem, but because these events are handled by the host kernel as well as the
            // guest the device would get them twice. Which would prompt the device to send the
            // event to the guest again entering an infinite loop.
            evt.type_ != EV_MSC
        })
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for EvdevEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        grab_evdev(self)
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}
<|endoftext|>


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

use core::ptr::PtrExt;

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    imp::allocate(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
    imp::reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
    imp::reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
    imp::deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    imp::usable_size(size, align)
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
#[unstable]
pub fn stats_print() {
    imp::stats_print();
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
/// non-zero-size memory allocations.
pub const EMPTY: *mut () = 0x1 as *mut ();

/// The allocator for unique pointers.
#[cfg(not(test))]
#[lang="exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    if size == 0 {
        EMPTY as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() { ::oom() }
        ptr
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
    deallocate(ptr, old_size, align);
}

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(any(target_arch = "arm",
          target_arch = "mips",
          target_arch = "mipsel"))]
const MIN_ALIGN: uint = 8;
#[cfg(any(target_arch = "x86",
          target_arch = "x86_64",
          target_arch = "aarch64"))]
const MIN_ALIGN: uint = 16;

#[cfg(feature = "external_funcs")]
mod imp {
    extern {
        fn rust_allocate(size: uint, align: uint) -> *mut u8;
        fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint);
        fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8;
        fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                   align: uint) -> uint;
        fn rust_usable_size(size: uint, align: uint) -> uint;
        fn rust_stats_print();
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        rust_allocate(size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        rust_deallocate(ptr, old_size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        unsafe { rust_usable_size(size, align) }
    }

    #[inline]
    pub fn stats_print() {
        unsafe { rust_stats_print() }
    }
}

#[cfg(feature = "external_crate")]
mod imp {
    extern crate external;
    pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate};
    pub use self::external::{usable_size, stats_print};
}

#[cfg(all(not(feature = "external_funcs"), not(feature = "external_crate"), jemalloc))]
mod imp {
    use core::option::Option;
    use core::option::Option::None;
    use core::ptr::{null_mut, null};
    use core::num::Int;
    use libc::{c_char, c_int, c_void, size_t};
    use super::MIN_ALIGN;

    #[link(name = "jemalloc", kind = "static")]
    #[cfg(not(test))]
    extern {}

    extern {
        fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
        fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        fn je_nallocx(size: size_t, flags: c_int) -> size_t;
        fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
                                                                *const c_char)>,
                                 cbopaque: *mut c_void,
                                 opts: *const c_char);
    }

    // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
    #[cfg(all(not(windows), not(target_os = "android")))]
    #[link(name = "pthread")]
    extern {}

    // MALLOCX_ALIGN(a) macro
    #[inline(always)]
    fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }

    #[inline(always)]
    fn align_to_flags(align: uint) -> c_int {
        if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_mallocx(size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
                                     align: uint) -> uint {
        let flags = align_to_flags(align);
        je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        let flags = align_to_flags(align);
        je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        let flags = align_to_flags(align);
        unsafe { je_nallocx(size as size_t, flags) as uint }
    }

    pub fn stats_print() {
        unsafe {
            je_malloc_stats_print(None, null_mut(), null())
        }
    }
}

#[cfg(all(not(feature = "external_funcs"), not(feature = "external_crate"), not(jemalloc), unix))]
mod imp {
    use core::cmp;
    use core::ptr;
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn posix_memalign(memptr: *mut *mut libc::c_void,
                          align: libc::size_t,
                          size: libc::size_t) -> libc::c_int;
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as libc::size_t) as *mut u8
        } else {
            let mut out = 0 as *mut libc::c_void;
            let ret = posix_memalign(&mut out,
                                     align as libc::size_t,
                                     size as libc::size_t);
            if ret != 0 {
                ptr::null_mut()
            } else {
                out as *mut u8
            }
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
        } else {
            let new_ptr = allocate(size, align);
            ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
            deallocate(ptr, old_size, align);
            new_ptr
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(all(not(feature = "external_funcs"), not(feature = "external_crate"), not(jemalloc), windows))]
mod imp {
    use libc::{c_void, size_t};
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
        fn _aligned_realloc(block: *mut c_void, size: size_t,
                            align: size_t) -> *mut c_void;
        fn _aligned_free(ptr: *mut c_void);
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as size_t) as *mut u8
        } else {
            _aligned_malloc(size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8
        } else {
            _aligned_realloc(ptr as *mut c_void, size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
        if align <= MIN_ALIGN {
            libc::free(ptr as *mut libc::c_void)
        } else {
            _aligned_free(ptr as *mut c_void)
        }
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(test)]
mod test {
    extern crate test;
    use self::test::Bencher;
    use core::ptr::PtrExt;
    use heap;

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() { ::oom() }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10i
        })
    }
}
<commit_msg>Shorten cfg line lengths in liballoc<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::ptr::PtrExt;

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    imp::allocate(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
    imp::reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
    imp::reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
    imp::deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    imp::usable_size(size, align)
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
#[unstable]
pub fn stats_print() {
    imp::stats_print();
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
/// non-zero-size memory allocations.
pub const EMPTY: *mut () = 0x1 as *mut ();

/// The allocator for unique pointers.
#[cfg(not(test))]
#[lang="exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    if size == 0 {
        EMPTY as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() { ::oom() }
        ptr
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
    deallocate(ptr, old_size, align);
}

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(any(target_arch = "arm",
          target_arch = "mips",
          target_arch = "mipsel"))]
const MIN_ALIGN: uint = 8;
#[cfg(any(target_arch = "x86",
          target_arch = "x86_64",
          target_arch = "aarch64"))]
const MIN_ALIGN: uint = 16;

#[cfg(feature = "external_funcs")]
mod imp {
    extern {
        fn rust_allocate(size: uint, align: uint) -> *mut u8;
        fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint);
        fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8;
        fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                   align: uint) -> uint;
        fn rust_usable_size(size: uint, align: uint) -> uint;
        fn rust_stats_print();
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        rust_allocate(size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        rust_deallocate(ptr, old_size, align)
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
                                     align: uint) -> uint {
        rust_reallocate_inplace(ptr, old_size, size, align)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        unsafe { rust_usable_size(size, align) }
    }

    #[inline]
    pub fn stats_print() {
        unsafe { rust_stats_print() }
    }
}

#[cfg(feature = "external_crate")]
mod imp {
    extern crate external;
    pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate};
    pub use self::external::{usable_size, stats_print};
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          jemalloc))]
mod imp {
    use core::option::Option;
    use core::option::Option::None;
    use core::ptr::{null_mut, null};
    use core::num::Int;
    use libc::{c_char, c_int, c_void, size_t};
    use super::MIN_ALIGN;

    #[link(name = "jemalloc", kind = "static")]
    #[cfg(not(test))]
    extern {}

    extern {
        fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
        fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        fn je_nallocx(size: size_t, flags: c_int) -> size_t;
        fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
                                                                *const c_char)>,
                                 cbopaque: *mut c_void,
                                 opts: *const c_char);
    }

    // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
    #[cfg(all(not(windows), not(target_os = "android")))]
    #[link(name = "pthread")]
    extern {}

    // MALLOCX_ALIGN(a) macro
    #[inline(always)]
    fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }

    #[inline(always)]
    fn align_to_flags(align: uint) -> c_int {
        if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_mallocx(size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        let flags = align_to_flags(align);
        je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8
    }

    #[inline]
    pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
                                     align: uint) -> uint {
        let flags = align_to_flags(align);
        je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
        let flags = align_to_flags(align);
        je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
    }

    #[inline]
    pub fn usable_size(size: uint, align: uint) -> uint {
        let flags = align_to_flags(align);
        unsafe { je_nallocx(size as size_t, flags) as uint }
    }

    pub fn stats_print() {
        unsafe {
            je_malloc_stats_print(None, null_mut(), null())
        }
    }
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          unix))]
mod imp {
    use core::cmp;
    use core::ptr;
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn posix_memalign(memptr: *mut *mut libc::c_void,
                          align: libc::size_t,
                          size: libc::size_t) -> libc::c_int;
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as libc::size_t) as *mut u8
        } else {
            let mut out = 0 as *mut libc::c_void;
            let ret = posix_memalign(&mut out,
                                     align as libc::size_t,
                                     size as libc::size_t);
            if ret != 0 {
                ptr::null_mut()
            } else {
                out as *mut u8
            }
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
        } else {
            let new_ptr = allocate(size, align);
            ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
            deallocate(ptr, old_size, align);
            new_ptr
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(all(not(feature = "external_funcs"),
          not(feature = "external_crate"),
          not(jemalloc),
          windows))]
mod imp {
    use libc::{c_void, size_t};
    use libc;
    use super::MIN_ALIGN;

    extern {
        fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
        fn _aligned_realloc(block: *mut c_void, size: size_t,
                            align: size_t) -> *mut c_void;
        fn _aligned_free(ptr: *mut c_void);
    }

    #[inline]
    pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as size_t) as *mut u8
        } else {
            _aligned_malloc(size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8
        } else {
            _aligned_realloc(ptr as *mut c_void, size as size_t, align as size_t) as *mut u8
        }
    }

    #[inline]
    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
                                     _align: uint) -> uint {
        old_size
    }

    #[inline]
    pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
        if align <= MIN_ALIGN {
            libc::free(ptr as *mut libc::c_void)
        } else {
            _aligned_free(ptr as *mut c_void)
        }
    }

    #[inline]
    pub fn usable_size(size: uint, _align: uint) -> uint {
        size
    }

    pub fn stats_print() {}
}

#[cfg(test)]
mod test {
    extern crate test;
    use self::test::Bencher;
    use core::ptr::PtrExt;
    use heap;

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() { ::oom() }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10i
        })
    }
}
<|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.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use convert::{AsRef, AsMut};
use default::Default;
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Copy, Sized, Unsize};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
pub trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<commit_msg>Auto merge of #28538 - alevy:make_fixedsizearray_unsafe, r=alexcrichton<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.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use convert::{AsRef, AsMut};
use default::Default;
use fmt;
use hash::{Hash, self};
use iter::IntoIterator;
use marker::{Copy, Sized, Unsize};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<|endoftext|>


<commit_before>use RealNumber;
use std::result;
use std::sync::{Arc, Mutex};
use super::Identifier;
use super::super::{
    Domain, NumberSpace, ToSliceMut, DspVec, ErrorReason, RededicateOps,
	Buffer, Owner, TimeOrFrequencyData, RealOrComplexData, Vector,
	DataDomain
};
use super::operations_enum::*;

const ARGUMENT1: usize = 0;
const ARGUMENT2: usize = 1;

/// An operation on one data vector which has been prepared in
/// advance.
///
/// The type arguments can be read like a function definition: TI1 -> TO1
#[derive(Clone)]
pub struct PreparedOperation1<T, NI, DI, NO, DO>
    where T: RealNumber,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {
    number_space_in: NI,
	domain_in: DI,
	number_space_out: NO,
	domain_out: DO,
    ops: Vec<Operation<T>>
}

/// Executes the prepared operations to convert `S`to `D`,
pub trait PreparedOperation1Exec<B, S, D> {
    /// Executes the prepared operations to convert `S`to `D`,
    fn exec(&self, buffer: &mut B, source: S) -> result::Result<D, (ErrorReason, D)>;
}

/// Prepares an operation with one input and one output.
pub fn prepare32_1<N, D>(number_space: N, domain: D)
    -> PreparedOperation1<f32, N, D, N, D>
    where
        N: NumberSpace,
		D: Domain {
    PreparedOperation1
         {
			number_space_in: number_space.clone(),
 			domain_in: domain.clone(),
 			number_space_out: number_space,
 			domain_out: domain,
            ops: Vec::new()
         }
}

/// Prepares an operation with one input and one output.
pub fn prepare64_1<N, D>(number_space: N, domain: D)
    -> PreparedOperation1<f64, N, D, N, D>
    where
        N: NumberSpace,
		D: Domain {
    PreparedOperation1
         {
			number_space_in: number_space.clone(),
 			domain_in: domain.clone(),
 			number_space_out: number_space,
 			domain_out: domain,
            ops: Vec::new()
         }
}

/// An operation on two data vectors which has been prepared in
/// advance.
///
/// The type arguments can be read like a function definition: (TI1, TI2) -> (TO1, TO2)
#[derive(Clone)]
pub struct PreparedOperation2<T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
    where T: RealNumber,
		NI1: NumberSpace, DI1: Domain, NI2: NumberSpace, DI2: Domain,
		NO1: NumberSpace, DO1: Domain, NO2: NumberSpace, DO2: Domain {
	number_space_in1: NI1,
	domain_in1: DI1,
	number_space_in2: NI2,
	domain_in2: DI2,
	number_space_out1: NO1,
	domain_out1: DO1,
	number_space_out2: NO2,
	domain_out2: DO2,
    ops: Vec<Operation<T>>,
    swap: bool
}
/*
/// A multi operation which holds a vector and records all changes
/// which need to be done to the vectors. By calling `get` on the struct
/// all operations will be executed in one run.
pub struct MultiOperation1<S, T, NI, DI, NO, DO>
    where T: RealNumber, S: ToSlice<T>,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {
    a: DspVec<S, T, NI, DI>,
    prepared_ops: PreparedOperation1<S, T, NI, DI, NO, DO>
}

/// A multi operation which holds two vectors and records all changes
/// which need to be done to the vectors. By calling `get` on the struct
/// all operations will be executed in one run.
pub struct MultiOperation2<S, T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
    where T: RealNumber, S: ToSlice<T>,
		NI1: NumberSpace, DI1: Domain, NI2: NumberSpace, DI2: Domain,
		NO1: NumberSpace, DO1: Domain, NO2: NumberSpace, DO2: Domain {
    a: DspVec<S, T, NI2, DI1>,
    b: DspVec<S, T, NI2, DI2>,
    prepared_ops: PreparedOperation2<S, T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
}
*/
/// An operation which can be prepared in advance and operates on one
/// input and produces one output
impl<T, NI, DI, NO, DO> PreparedOperation1<T, NI, DI, NO, DO>
	where T: RealNumber + 'static,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {

	/// Extends the operation to operate on one more vector.
	pub fn extend<NI2, DI2>(self, number_space: NI2, domain: DI2)
			-> PreparedOperation2<T, NI, DI, NI2, DI2, NO, DO, NI2, DI2>
		where NI2: NumberSpace, DI2: Domain {
		PreparedOperation2
		{
			number_space_in1: self.number_space_in,
			domain_in1: self.domain_in,
			number_space_in2: number_space.clone(),
			domain_in2: domain.clone(),
			number_space_out1: self.number_space_out,
			domain_out1: self.domain_out,
			number_space_out2: number_space,
			domain_out2: domain,
			ops: self.ops,
			swap: false
		}
	}

	/// Adds new operations which will be executed with the next call to `exec`
	///
	/// As a background: The function `operation` will be executed immediately. It only operated on `Identifier` types and these serve as
	/// placeholder for vectors. Every operation done to an `Identifier`
	/// is recorded and will be executed on vectors if `exec` is called.
	pub fn add_ops<F, NT, DT>(self, operation: F)
		-> PreparedOperation1<T, NI, DI, NT, DT>
		where F: Fn(Identifier<T, NO, DO>) -> Identifier<T, NT, DT>,
		      DT: Domain,
			  NT: NumberSpace

	{
		let mut ops = self.ops;
		let (new_ops, domain_new, number_space_new) =
		{
			let counter = Arc::new(Mutex::new(0));
			let t1 = Identifier
				{
				    arg: ARGUMENT1,
				    ops: Vec::new(),
				    counter: counter,
				    domain: self.domain_out.clone(),
				    number_space: self.number_space_out.clone()
				};

			let r1 = operation(t1);
			(r1.ops, r1.domain, r1.number_space)
		};
		for v in new_ops {
			ops.push(v.1);
		}

		PreparedOperation1
		{
			domain_in: self.domain_in,
			number_space_in: self.number_space_in,
			domain_out: domain_new,
			number_space_out: number_space_new,
			ops: ops
		}
	}
}

impl<T, S, B, NI, DI, NO, DO> PreparedOperation1Exec<B, DspVec<S, T, NI, DI>, DspVec<S, T, NO, DO>> for PreparedOperation1<T, NI, DI, NO, DO>
	where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
        DspVec<S, T, NO, DO>: RededicateOps<DspVec<S, T, NI, DI>>,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain,
        B: Buffer<S, T> {

	/// Executes all recorded operations on the input vectors.
	fn exec(&self, buffer: &mut B, a: DspVec<S, T, NI, DI>) -> result::Result<DspVec<S, T, NO, DO>, (ErrorReason, DspVec<S, T, NO, DO>)> {
		let mut vec = Vec::new();
		let domain = a.domain.clone();
		let number_space = a.number_space.clone();
		let gen = DspVec {
				delta: a.delta,
				domain: TimeOrFrequencyData { domain_current: a.domain() },
				number_space: RealOrComplexData { is_complex_current: a.is_complex() },
				valid_len: a.valid_len,
				multicore_settings: a.multicore_settings,
				data: a.data
		};
		vec.push(gen);

		// at this point we would execute all ops and cast the result to the right types
		let result = DspVec::<S, T, RealOrComplexData, TimeOrFrequencyData>::perform_operations(buffer, vec, &self.ops);

		match result {
			Err((reason, mut vec)) => {
				let a = vec.pop().unwrap();
				let is_complex = a.is_complex();
				let result_domain = a.domain();
				let mut a = DspVec {
						data: a.data,
						delta: a.delta,
						domain: domain,
						number_space: number_space,
						valid_len: a.valid_len,
						multicore_settings: a.multicore_settings
				};

				if is_complex {
					a.number_space.to_complex();
				} else {
					a.number_space.to_real();
				}

				if result_domain == DataDomain::Time {
					a.domain.to_time();
				} else {
					a.domain.to_freq();
				}

				Err((
					reason,
					DspVec::<S, T, NO, DO>::rededicate_from(a)))
			},
			Ok(mut vec) => {
				let a = vec.pop().unwrap();
				let is_complex = a.is_complex();
				let result_domain = a.domain();
				let mut a = DspVec {
						data: a.data,
						delta: a.delta,
						domain: domain,
						number_space: number_space,
						valid_len: a.valid_len,
						multicore_settings: a.multicore_settings
				};

				if is_complex {
					a.number_space.to_complex();
				} else {
					a.number_space.to_real();
				}

				if result_domain == DataDomain::Time {
					a.domain.to_time();
				} else {
					a.domain.to_freq();
				}

				// Convert back
				Ok(DspVec::<S, T, NO, DO>::rededicate_from(a))
			}
		}

	}
}

impl<T, S, B, N, D> PreparedOperation1Exec<B, DspVec<S, T, N, D>, DspVec<S, T, N, D>> for PreparedOperation1<T, N, D, N, D>
	where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
		N: NumberSpace, D: Domain,
        B: Buffer<S, T> {

	/// Executes all recorded operations on the input vectors.
	fn exec(&self, buffer: &mut B, a: DspVec<S, T, N, D>) -> result::Result<DspVec<S, T, N, D>, (ErrorReason, DspVec<S, T, N, D>)> {
		let mut vec = Vec::new();
		let domain = a.domain.clone();
		let number_space = a.number_space.clone();
		let gen = DspVec {
				delta: a.delta,
				domain: TimeOrFrequencyData { domain_current: a.domain() },
				number_space: RealOrComplexData { is_complex_current: a.is_complex() },
				valid_len: a.valid_len,
				multicore_settings: a.multicore_settings,
				data: a.data
		};
		vec.push(gen);

		// at this point we would execute all ops and cast the result to the right types
		let result = DspVec::<S, T, RealOrComplexData, TimeOrFrequencyData>::perform_operations(buffer, vec, &self.ops);

		match result {
			Err((reason, mut vec)) => {
				let a = vec.pop().unwrap();
				let is_complex = a.is_complex();
				let result_domain = a.domain();
				let mut a = DspVec {
						data: a.data,
						delta: a.delta,
						domain: domain,
						number_space: number_space,
						valid_len: a.valid_len,
						multicore_settings: a.multicore_settings
				};

				if is_complex {
					a.number_space.to_complex();
				} else {
					a.number_space.to_real();
				}

				if result_domain == DataDomain::Time {
					a.domain.to_time();
				} else {
					a.domain.to_freq();
				}

				Err((
					reason,
					a))
			},
			Ok(mut vec) => {
				let a = vec.pop().unwrap();
				let is_complex = a.is_complex();
				let result_domain = a.domain();
				let mut a = DspVec {
						data: a.data,
						delta: a.delta,
						domain: domain,
						number_space: number_space,
						valid_len: a.valid_len,
						multicore_settings: a.multicore_settings
				};

				if is_complex {
					a.number_space.to_complex();
				} else {
					a.number_space.to_real();
				}

				if result_domain == DataDomain::Time {
					a.domain.to_time();
				} else {
					a.domain.to_freq();
				}

				// Convert back
				Ok(a)
			}
		}

	}
}
<commit_msg>Removed code duplication<commit_after>use RealNumber;
use std::result;
use std::sync::{Arc, Mutex};
use super::Identifier;
use super::super::{
    Domain, NumberSpace, ToSliceMut, DspVec, ErrorReason, RededicateOps,
	Buffer, Owner, TimeOrFrequencyData, RealOrComplexData, Vector,
	DataDomain
};
use super::operations_enum::*;

const ARGUMENT1: usize = 0;
const ARGUMENT2: usize = 1;

/// An operation on one data vector which has been prepared in
/// advance.
///
/// The type arguments can be read like a function definition: TI1 -> TO1
#[derive(Clone)]
pub struct PreparedOperation1<T, NI, DI, NO, DO>
    where T: RealNumber,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {
    number_space_in: NI,
	domain_in: DI,
	number_space_out: NO,
	domain_out: DO,
    ops: Vec<Operation<T>>
}

/// Executes the prepared operations to convert `S`to `D`,
pub trait PreparedOperation1Exec<B, S, D> {
    /// Executes the prepared operations to convert `S`to `D`,
    fn exec(&self, buffer: &mut B, source: S) -> result::Result<D, (ErrorReason, D)>;
}

/// Prepares an operation with one input and one output.
pub fn prepare32_1<N, D>(number_space: N, domain: D)
    -> PreparedOperation1<f32, N, D, N, D>
    where
        N: NumberSpace,
		D: Domain {
    PreparedOperation1
         {
			number_space_in: number_space.clone(),
 			domain_in: domain.clone(),
 			number_space_out: number_space,
 			domain_out: domain,
            ops: Vec::new()
         }
}

/// Prepares an operation with one input and one output.
pub fn prepare64_1<N, D>(number_space: N, domain: D)
    -> PreparedOperation1<f64, N, D, N, D>
    where
        N: NumberSpace,
		D: Domain {
    PreparedOperation1
         {
			number_space_in: number_space.clone(),
 			domain_in: domain.clone(),
 			number_space_out: number_space,
 			domain_out: domain,
            ops: Vec::new()
         }
}

/// An operation on two data vectors which has been prepared in
/// advance.
///
/// The type arguments can be read like a function definition: (TI1, TI2) -> (TO1, TO2)
#[derive(Clone)]
pub struct PreparedOperation2<T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
    where T: RealNumber,
		NI1: NumberSpace, DI1: Domain, NI2: NumberSpace, DI2: Domain,
		NO1: NumberSpace, DO1: Domain, NO2: NumberSpace, DO2: Domain {
	number_space_in1: NI1,
	domain_in1: DI1,
	number_space_in2: NI2,
	domain_in2: DI2,
	number_space_out1: NO1,
	domain_out1: DO1,
	number_space_out2: NO2,
	domain_out2: DO2,
    ops: Vec<Operation<T>>,
    swap: bool
}
/*
/// A multi operation which holds a vector and records all changes
/// which need to be done to the vectors. By calling `get` on the struct
/// all operations will be executed in one run.
pub struct MultiOperation1<S, T, NI, DI, NO, DO>
    where T: RealNumber, S: ToSlice<T>,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {
    a: DspVec<S, T, NI, DI>,
    prepared_ops: PreparedOperation1<S, T, NI, DI, NO, DO>
}

/// A multi operation which holds two vectors and records all changes
/// which need to be done to the vectors. By calling `get` on the struct
/// all operations will be executed in one run.
pub struct MultiOperation2<S, T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
    where T: RealNumber, S: ToSlice<T>,
		NI1: NumberSpace, DI1: Domain, NI2: NumberSpace, DI2: Domain,
		NO1: NumberSpace, DO1: Domain, NO2: NumberSpace, DO2: Domain {
    a: DspVec<S, T, NI2, DI1>,
    b: DspVec<S, T, NI2, DI2>,
    prepared_ops: PreparedOperation2<S, T, NI1, DI1, NI2, DI2, NO1, DO1, NO2, DO2>
}
*/
/// An operation which can be prepared in advance and operates on one
/// input and produces one output
impl<T, NI, DI, NO, DO> PreparedOperation1<T, NI, DI, NO, DO>
	where T: RealNumber + 'static,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain {

	/// Extends the operation to operate on one more vector.
	pub fn extend<NI2, DI2>(self, number_space: NI2, domain: DI2)
			-> PreparedOperation2<T, NI, DI, NI2, DI2, NO, DO, NI2, DI2>
		where NI2: NumberSpace, DI2: Domain {
		PreparedOperation2
		{
			number_space_in1: self.number_space_in,
			domain_in1: self.domain_in,
			number_space_in2: number_space.clone(),
			domain_in2: domain.clone(),
			number_space_out1: self.number_space_out,
			domain_out1: self.domain_out,
			number_space_out2: number_space,
			domain_out2: domain,
			ops: self.ops,
			swap: false
		}
	}

	/// Adds new operations which will be executed with the next call to `exec`
	///
	/// As a background: The function `operation` will be executed immediately. It only operated on `Identifier` types and these serve as
	/// placeholder for vectors. Every operation done to an `Identifier`
	/// is recorded and will be executed on vectors if `exec` is called.
	pub fn add_ops<F, NT, DT>(self, operation: F)
		-> PreparedOperation1<T, NI, DI, NT, DT>
		where F: Fn(Identifier<T, NO, DO>) -> Identifier<T, NT, DT>,
		      DT: Domain,
			  NT: NumberSpace

	{
		let mut ops = self.ops;
		let (new_ops, domain_new, number_space_new) =
		{
			let counter = Arc::new(Mutex::new(0));
			let t1 = Identifier
				{
				    arg: ARGUMENT1,
				    ops: Vec::new(),
				    counter: counter,
				    domain: self.domain_out.clone(),
				    number_space: self.number_space_out.clone()
				};

			let r1 = operation(t1);
			(r1.ops, r1.domain, r1.number_space)
		};
		for v in new_ops {
			ops.push(v.1);
		}

		PreparedOperation1
		{
			domain_in: self.domain_in,
			number_space_in: self.number_space_in,
			domain_out: domain_new,
			number_space_out: number_space_new,
			ops: ops
		}
	}
}

fn generic_vector_from_any_vector<S, T, N, D>(vec: DspVec<S, T, N, D>) -> (N, D, DspVec<S, T, RealOrComplexData, TimeOrFrequencyData>)
    where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
        N: NumberSpace, D: Domain {
    let domain = vec.domain.clone();
    let number_space = vec.number_space.clone();
    let gen = DspVec {
            delta: vec.delta,
            domain: TimeOrFrequencyData { domain_current: vec.domain() },
            number_space: RealOrComplexData { is_complex_current: vec.is_complex() },
            valid_len: vec.valid_len,
            multicore_settings: vec.multicore_settings,
            data: vec.data
    };
    (number_space, domain, gen)
}

fn generic_vector_back_to_vector<S, T, N, D>(number_space: N, domain: D, vec: DspVec<S, T, RealOrComplexData, TimeOrFrequencyData>) -> DspVec<S, T, N, D>
    where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
        N: NumberSpace, D: Domain {
    let is_complex = vec.is_complex();
    let result_domain = vec.domain();
    let mut vec = DspVec {
            data: vec.data,
            delta: vec.delta,
            domain: domain,
            number_space: number_space,
            valid_len: vec.valid_len,
            multicore_settings: vec.multicore_settings
    };

    if is_complex {
        vec.number_space.to_complex();
    } else {
        vec.number_space.to_real();
    }

    if result_domain == DataDomain::Time {
        vec.domain.to_time();
    } else {
        vec.domain.to_freq();
    }

    vec
}

impl<T, S, B, NI, DI, NO, DO> PreparedOperation1Exec<B, DspVec<S, T, NI, DI>, DspVec<S, T, NO, DO>> for PreparedOperation1<T, NI, DI, NO, DO>
	where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
        DspVec<S, T, NO, DO>: RededicateOps<DspVec<S, T, NI, DI>>,
		NI: NumberSpace, DI: Domain,
		NO: NumberSpace, DO: Domain,
        B: Buffer<S, T> {
	/// Executes all recorded operations on the input vectors.
	fn exec(&self, buffer: &mut B, a: DspVec<S, T, NI, DI>) -> result::Result<DspVec<S, T, NO, DO>, (ErrorReason, DspVec<S, T, NO, DO>)> {
		let mut vec = Vec::new();
		let (number_space, domain, gen) = generic_vector_from_any_vector(a);
		vec.push(gen);

		// at this point we would execute all ops and cast the result to the right types
		let result = DspVec::<S, T, RealOrComplexData, TimeOrFrequencyData>::perform_operations(buffer, vec, &self.ops);

		match result {
			Err((reason, mut vec)) => {
				let a = vec.pop().unwrap();
				let a = generic_vector_back_to_vector(number_space, domain, a);
				Err((
					reason,
					DspVec::<S, T, NO, DO>::rededicate_from(a)))
			},
			Ok(mut vec) => {
				let a = vec.pop().unwrap();
				let a = generic_vector_back_to_vector(number_space, domain, a);
				// Convert back
				Ok(DspVec::<S, T, NO, DO>::rededicate_from(a))
			}
		}
	}
}

impl<T, S, B, N, D> PreparedOperation1Exec<B, DspVec<S, T, N, D>, DspVec<S, T, N, D>> for PreparedOperation1<T, N, D, N, D>
	where T: RealNumber + 'static,
        S: ToSliceMut<T> + Owner,
		N: NumberSpace, D: Domain,
        B: Buffer<S, T> {
	/// Executes all recorded operations on the input vectors.
	fn exec(&self, buffer: &mut B, a: DspVec<S, T, N, D>) -> result::Result<DspVec<S, T, N, D>, (ErrorReason, DspVec<S, T, N, D>)> {
		let mut vec = Vec::new();
		let (number_space, domain, gen) = generic_vector_from_any_vector(a);
		vec.push(gen);

		// at this point we would execute all ops and cast the result to the right types
		let result = DspVec::<S, T, RealOrComplexData, TimeOrFrequencyData>::perform_operations(buffer, vec, &self.ops);

		match result {
			Err((reason, mut vec)) => {
				let a = vec.pop().unwrap();
				let a = generic_vector_back_to_vector(number_space, domain, a);
				Err((reason, a))
			},
			Ok(mut vec) => {
                let a = vec.pop().unwrap();
				let a = generic_vector_back_to_vector(number_space, domain, a);
				// Convert back
				Ok(a)
			}
		}
	}
}
<|endoftext|>


<commit_before>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, gen: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<commit_msg>takas<commit_after>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, gen: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in gen.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<|endoftext|>