<commit_before>// Copyright (c) 2017 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::time::Duration;

use buffer::BufferAccess;
use command_buffer::submit::SubmitAnyBuilder;
use command_buffer::submit::SubmitCommandBufferBuilder;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::ImageAccess;
use image::ImageLayout;
use sync::AccessCheckError;
use sync::AccessFlagBits;
use sync::FlushError;
use sync::Fence;
use sync::GpuFuture;
use sync::PipelineStages;

/// Builds a new fence signal future.
#[inline]
pub fn then_signal_fence<F>(future: F, behavior: FenceSignalFutureBehavior) -> FenceSignalFuture<F>
    where F: GpuFuture
{
    let device = future.device().clone();

    assert!(future.queue().is_some());        // TODO: document

    let fence = Fence::new(device.clone()).unwrap();
    FenceSignalFuture {
        device: device,
        state: Mutex::new(FenceSignalFutureState::Pending(future, fence)),
        behavior: behavior,
    }
}

/// Describes the behavior of the future if you submit something after it.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FenceSignalFutureBehavior {
    /// Continue execution on the same queue.
    Continue,
    /// Wait for the fence to be signalled before submitting any further operation.
    Block {
        /// How long to block the current thread.
        timeout: Option<Duration>
    },
}

/// Represents a fence being signaled after a previous event.
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
pub struct FenceSignalFuture<F> where F: GpuFuture {
    // Current state. See the docs of `FenceSignalFutureState`.
    state: Mutex<FenceSignalFutureState<F>>,
    // The device of the future.
    device: Arc<Device>,
    behavior: FenceSignalFutureBehavior,
}

// This future can be in three different states: pending (ie. newly-created), submitted (ie. the
// command that submits the fence has been submitted), or cleaned (ie. the previous future has
// been dropped).
enum FenceSignalFutureState<F> {
    // Newly-created. Not submitted yet.
    Pending(F, Fence),

    // Partially submitted to the queue. Only happens in situations where submitting requires two
    // steps, and when the first step succeeded while the second step failed.
    //
    // Note that if there's ever a submit operation that needs three steps we will need to rework
    // this code, as it was designed for two-step operations only.
    PartiallyFlushed(F, Fence),

    // Submitted to the queue.
    Flushed(F, Fence),

    // The submission is finished. The previous future and the fence have been cleaned.
    Cleaned,

    // A function panicked while the state was being modified. Should never happen.
    Poisonned,
}

impl<F> FenceSignalFuture<F> where F: GpuFuture {
    // Implementation of `cleanup_finished`, but takes a `&self` instead of a `&mut self`.
    // This is an external function so that we can also call it from an `Arc<FenceSignalFuture>`.
    #[inline]
    fn cleanup_finished_impl(&self) {
        let mut state = self.state.lock().unwrap();

        match *state {
            FenceSignalFutureState::Flushed(ref mut prev, ref fence) => {
                match fence.wait(Some(Duration::from_secs(0))) {
                    Ok(()) => unsafe {
                        prev.signal_finished()
                    },
                    Err(_) => {
                        prev.cleanup_finished();
                        return
                    },
                }
            },
            FenceSignalFutureState::Pending(ref mut prev, _) => {
                prev.cleanup_finished();
                return;
            },
            FenceSignalFutureState::PartiallyFlushed(ref mut prev, _) => {
                prev.cleanup_finished();
                return;
            },
            _ => return,
        };

        // This code can only be reached if we're already flushed and waiting on the fence
        // succeeded.
        *state = FenceSignalFutureState::Cleaned;
    }

    // Implementation of `flush`. You must lock the state and pass the mutex guard here.
    fn flush_impl(&self, state: &mut MutexGuard<FenceSignalFutureState<F>>)
                  -> Result<(), FlushError>
    {
        unsafe {
            // In this function we temporarily replace the current state with `Poisonned` at the
            // beginning, and we take care to always put back a value into `state` before
            // returning (even in case of error).
            let old_state = mem::replace(&mut **state, FenceSignalFutureState::Poisonned);

            let (previous, fence, partially_flushed) = match old_state {
                FenceSignalFutureState::Pending(prev, fence) => {
                    (prev, fence, false)
                },
                FenceSignalFutureState::PartiallyFlushed(prev, fence) => {
                    (prev, fence, true)
                },
                other => {
                    // We were already flushed in the past, or we're already poisonned. Don't do
                    // anything.
                    **state = other;
                    return Ok(());
                },
            };

            // TODO: meh for unwrap
            let queue = previous.queue().unwrap().clone();

            // There are three possible outcomes for the flush operation: success, partial success
            // in which case `result` will contain `Err(OutcomeErr::Partial)`, or total failure
            // in which case `result` will contain `Err(OutcomeErr::Full)`.
            enum OutcomeErr<E> { Partial(E), Full(E) }
            let result = match try!(previous.build_submission()) {
                SubmitAnyBuilder::Empty => {
                    debug_assert!(!partially_flushed);
                    let mut b = SubmitCommandBufferBuilder::new();
                    b.set_fence_signal(&fence);
                    b.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::SemaphoresWait(sem) => {
                    debug_assert!(!partially_flushed);
                    let b: SubmitCommandBufferBuilder = sem.into();
                    debug_assert!(!b.has_fence());
                    b.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::CommandBuffer(mut cb_builder) => {
                    debug_assert!(!partially_flushed);
                    // The assert below could technically be a debug assertion as it is part of the
                    // safety contract of the trait. However it is easy to get this wrong if you
                    // write a custom implementation, and if so the consequences would be
                    // disastrous and hard to debug. Therefore we prefer to just use a regular
                    // assertion.
                    assert!(!cb_builder.has_fence());
                    cb_builder.set_fence_signal(&fence);
                    cb_builder.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::QueuePresent(present) => {
                    let intermediary_result = if partially_flushed {
                        Ok(())
                    } else {
                        present.submit(&queue)
                    };
                    match intermediary_result {
                        Ok(()) => {
                            let mut b = SubmitCommandBufferBuilder::new();
                            b.set_fence_signal(&fence);
                            b.submit(&queue).map_err(|err| OutcomeErr::Partial(err.into()))
                        },
                        Err(err) => {
                            Err(OutcomeErr::Full(err.into()))
                        }
                    }
                },
            };

            // Restore the state before returning.
            match result {
                Ok(()) => {
                    **state = FenceSignalFutureState::Flushed(previous, fence);
                    Ok(())
                },
                Err(OutcomeErr::Partial(err)) => {
                    **state = FenceSignalFutureState::PartiallyFlushed(previous, fence);
                    Err(err)
                },
                Err(OutcomeErr::Full(err)) => {
                    **state = FenceSignalFutureState::Pending(previous, fence);
                    Err(err)
                },
            }
        }
    }
}

impl<F> FenceSignalFutureState<F> {
    #[inline]
    fn get_prev(&self) -> Option<&F> {
        match *self {
            FenceSignalFutureState::Pending(ref prev, _) => Some(prev),
            FenceSignalFutureState::PartiallyFlushed(ref prev, _) => Some(prev),
            FenceSignalFutureState::Flushed(ref prev, _) => Some(prev),
            FenceSignalFutureState::Cleaned => None,
            FenceSignalFutureState::Poisonned => None,
        }
    }
}

unsafe impl<F> GpuFuture for FenceSignalFuture<F> where F: GpuFuture {
    #[inline]
    fn cleanup_finished(&mut self) {
        self.cleanup_finished_impl()
    }

    #[inline]
    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
        let mut state = self.state.lock().unwrap();
        try!(self.flush_impl(&mut state));

        match *state {
            FenceSignalFutureState::Flushed(_, ref fence) => {
                match self.behavior {
                    FenceSignalFutureBehavior::Block { timeout } => {
                        try!(fence.wait(timeout));
                    },
                    FenceSignalFutureBehavior::Continue => (),
                }
            },
            FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (),
            FenceSignalFutureState::Pending(_, _)  => unreachable!(),
            FenceSignalFutureState::PartiallyFlushed(_, _) => unreachable!(),
        }

        Ok(SubmitAnyBuilder::Empty)
    }

    #[inline]
    fn flush(&self) -> Result<(), FlushError> {
        let mut state = self.state.lock().unwrap();
        self.flush_impl(&mut state)
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        let state = self.state.lock().unwrap();
        match *state {
            FenceSignalFutureState::Flushed(ref prev, _) => {
                prev.signal_finished();
            },
            FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (),
            _ => unreachable!(),
        }
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        match self.behavior {
            FenceSignalFutureBehavior::Continue => {
                let state = self.state.lock().unwrap();
                if state.get_prev().is_some() {
                    false
                } else {
                    true
                }
            },
            FenceSignalFutureBehavior::Block { .. } => {
                true
            },
        }
    }

    #[inline]
    fn queue(&self) -> Option<Arc<Queue>> {
        let state = self.state.lock().unwrap();
        if let Some(prev) = state.get_prev() {
            prev.queue()
        } else {
            None
        }
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
        let state = self.state.lock().unwrap();
        if let Some(previous) = state.get_prev() {
            previous.check_buffer_access(buffer, exclusive, queue)
        } else {
            Err(AccessCheckError::Unknown)
        }
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
        let state = self.state.lock().unwrap();
        if let Some(previous) = state.get_prev() {
            previous.check_image_access(image, layout, exclusive, queue)
        } else {
            Err(AccessCheckError::Unknown)
        }
    }
}

unsafe impl<F> DeviceOwned for FenceSignalFuture<F> where F: GpuFuture {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

impl<F> Drop for FenceSignalFuture<F> where F: GpuFuture {
    fn drop(&mut self) {
        let mut state = self.state.lock().unwrap();

        // We ignore any possible error while submitting for now. Problems are handled below.
        let _ = self.flush_impl(&mut state);

        match mem::replace(&mut *state, FenceSignalFutureState::Cleaned) {
            FenceSignalFutureState::Flushed(previous, fence) => {
                // This is a normal situation. Submitting worked.
                // TODO: handle errors?
                fence.wait(None).unwrap();
                unsafe { previous.signal_finished(); }
            },
            FenceSignalFutureState::Cleaned => {
                // Also a normal situation. The user called `cleanup_finished()` before dropping.
            },
            FenceSignalFutureState::Poisonned => {
                // The previous future was already dropped and blocked the current queue.
            },
            FenceSignalFutureState::Pending(_, _) |
            FenceSignalFutureState::PartiallyFlushed(_, _) => {
                // Flushing produced an error. There's nothing more we can do except drop the
                // previous future and let it block the current queue.
            },
        }
    }
}

unsafe impl<F> GpuFuture for Arc<FenceSignalFuture<F>> where F: GpuFuture {
    #[inline]
    fn cleanup_finished(&mut self) {
        self.cleanup_finished_impl()
    }

    #[inline]
    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
        // Note that this is sound because we always return `SubmitAnyBuilder::Empty`. See the
        // documentation of `build_submission`.
        (**self).build_submission()
    }

    #[inline]
    fn flush(&self) -> Result<(), FlushError> {
        (**self).flush()
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        (**self).signal_finished()
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        (**self).queue_change_allowed()
    }

    #[inline]
    fn queue(&self) -> Option<Arc<Queue>> {
        (**self).queue()
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        (**self).check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        (**self).check_image_access(image, layout, exclusive, queue)
    }
}
<commit_msg>Add FenceSignalFuture::wait()<commit_after>// Copyright (c) 2017 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::time::Duration;

use buffer::BufferAccess;
use command_buffer::submit::SubmitAnyBuilder;
use command_buffer::submit::SubmitCommandBufferBuilder;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::ImageAccess;
use image::ImageLayout;
use sync::AccessCheckError;
use sync::AccessFlagBits;
use sync::FlushError;
use sync::Fence;
use sync::GpuFuture;
use sync::PipelineStages;

/// Builds a new fence signal future.
#[inline]
pub fn then_signal_fence<F>(future: F, behavior: FenceSignalFutureBehavior) -> FenceSignalFuture<F>
    where F: GpuFuture
{
    let device = future.device().clone();

    assert!(future.queue().is_some());        // TODO: document

    let fence = Fence::new(device.clone()).unwrap();
    FenceSignalFuture {
        device: device,
        state: Mutex::new(FenceSignalFutureState::Pending(future, fence)),
        behavior: behavior,
    }
}

/// Describes the behavior of the future if you submit something after it.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FenceSignalFutureBehavior {
    /// Continue execution on the same queue.
    Continue,
    /// Wait for the fence to be signalled before submitting any further operation.
    Block {
        /// How long to block the current thread.
        timeout: Option<Duration>
    },
}

/// Represents a fence being signaled after a previous event.
///
/// Contrary to most other future types, it is possible to block the current thread until the event
/// happens. This is done by calling the `wait()` function.
///
/// Also note that the `GpuFuture` trait is implemented on `Arc<FenceSignalFuture<_>>`.
/// This means that you can put this future in an `Arc` and keep a copy of it somewhere in order
/// to know when the execution reached that point.
///
/// ```
/// use std::sync::Arc;
/// use vulkano::sync::GpuFuture;
///
/// # let future: Box<GpuFuture> = return;
/// // Assuming you have a chain of operations, like this:
/// // let future = ...
/// //      .then_execute(foo)
/// //      .then_execute(bar)
///
/// // You can signal a fence at this point of the chain, and put the future in an `Arc`.
/// let fence_signal = Arc::new(future.then_signal_fence());
///
/// // And then continue the chain:
/// // fence_signal.clone()
/// //      .then_execute(baz)
/// //      .then_execute(qux)
///
/// // Later you can wait until you reach the point of `fence_signal`:
/// fence_signal.wait(None).unwrap();
/// ```
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
pub struct FenceSignalFuture<F> where F: GpuFuture {
    // Current state. See the docs of `FenceSignalFutureState`.
    state: Mutex<FenceSignalFutureState<F>>,
    // The device of the future.
    device: Arc<Device>,
    behavior: FenceSignalFutureBehavior,
}

// This future can be in three different states: pending (ie. newly-created), submitted (ie. the
// command that submits the fence has been submitted), or cleaned (ie. the previous future has
// been dropped).
enum FenceSignalFutureState<F> {
    // Newly-created. Not submitted yet.
    Pending(F, Fence),

    // Partially submitted to the queue. Only happens in situations where submitting requires two
    // steps, and when the first step succeeded while the second step failed.
    //
    // Note that if there's ever a submit operation that needs three steps we will need to rework
    // this code, as it was designed for two-step operations only.
    PartiallyFlushed(F, Fence),

    // Submitted to the queue.
    Flushed(F, Fence),

    // The submission is finished. The previous future and the fence have been cleaned.
    Cleaned,

    // A function panicked while the state was being modified. Should never happen.
    Poisonned,
}

impl<F> FenceSignalFuture<F> where F: GpuFuture {
    /// Blocks the current thread until the fence is signaled by the GPU. Performs a flush if
    /// necessary.
    ///
    /// If `timeout` is `None`, then the wait is infinite. Otherwise the thread will unblock after
    /// the specified timeout has elapsed and an error will be returned.
    ///
    /// If the wait is successful, this function also cleans any resource locked by previous
    /// submissions.
    pub fn wait(&self, timeout: Option<Duration>) -> Result<(), FlushError> {
        let mut state = self.state.lock().unwrap();

        self.flush_impl(&mut state)?;

        match mem::replace(&mut *state, FenceSignalFutureState::Cleaned) {
            FenceSignalFutureState::Flushed(previous, fence) => {
                fence.wait(timeout)?;
                unsafe { previous.signal_finished(); }
                Ok(())
            },
            FenceSignalFutureState::Cleaned => Ok(()),
            _ => unreachable!()
        }
    }
}

impl<F> FenceSignalFuture<F> where F: GpuFuture {
    // Implementation of `cleanup_finished`, but takes a `&self` instead of a `&mut self`.
    // This is an external function so that we can also call it from an `Arc<FenceSignalFuture>`.
    #[inline]
    fn cleanup_finished_impl(&self) {
        let mut state = self.state.lock().unwrap();

        match *state {
            FenceSignalFutureState::Flushed(ref mut prev, ref fence) => {
                match fence.wait(Some(Duration::from_secs(0))) {
                    Ok(()) => unsafe {
                        prev.signal_finished()
                    },
                    Err(_) => {
                        prev.cleanup_finished();
                        return
                    },
                }
            },
            FenceSignalFutureState::Pending(ref mut prev, _) => {
                prev.cleanup_finished();
                return;
            },
            FenceSignalFutureState::PartiallyFlushed(ref mut prev, _) => {
                prev.cleanup_finished();
                return;
            },
            _ => return,
        };

        // This code can only be reached if we're already flushed and waiting on the fence
        // succeeded.
        *state = FenceSignalFutureState::Cleaned;
    }

    // Implementation of `flush`. You must lock the state and pass the mutex guard here.
    fn flush_impl(&self, state: &mut MutexGuard<FenceSignalFutureState<F>>)
                  -> Result<(), FlushError>
    {
        unsafe {
            // In this function we temporarily replace the current state with `Poisonned` at the
            // beginning, and we take care to always put back a value into `state` before
            // returning (even in case of error).
            let old_state = mem::replace(&mut **state, FenceSignalFutureState::Poisonned);

            let (previous, fence, partially_flushed) = match old_state {
                FenceSignalFutureState::Pending(prev, fence) => {
                    (prev, fence, false)
                },
                FenceSignalFutureState::PartiallyFlushed(prev, fence) => {
                    (prev, fence, true)
                },
                other => {
                    // We were already flushed in the past, or we're already poisonned. Don't do
                    // anything.
                    **state = other;
                    return Ok(());
                },
            };

            // TODO: meh for unwrap
            let queue = previous.queue().unwrap().clone();

            // There are three possible outcomes for the flush operation: success, partial success
            // in which case `result` will contain `Err(OutcomeErr::Partial)`, or total failure
            // in which case `result` will contain `Err(OutcomeErr::Full)`.
            enum OutcomeErr<E> { Partial(E), Full(E) }
            let result = match try!(previous.build_submission()) {
                SubmitAnyBuilder::Empty => {
                    debug_assert!(!partially_flushed);
                    let mut b = SubmitCommandBufferBuilder::new();
                    b.set_fence_signal(&fence);
                    b.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::SemaphoresWait(sem) => {
                    debug_assert!(!partially_flushed);
                    let b: SubmitCommandBufferBuilder = sem.into();
                    debug_assert!(!b.has_fence());
                    b.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::CommandBuffer(mut cb_builder) => {
                    debug_assert!(!partially_flushed);
                    // The assert below could technically be a debug assertion as it is part of the
                    // safety contract of the trait. However it is easy to get this wrong if you
                    // write a custom implementation, and if so the consequences would be
                    // disastrous and hard to debug. Therefore we prefer to just use a regular
                    // assertion.
                    assert!(!cb_builder.has_fence());
                    cb_builder.set_fence_signal(&fence);
                    cb_builder.submit(&queue).map_err(|err| OutcomeErr::Full(err.into()))
                },
                SubmitAnyBuilder::QueuePresent(present) => {
                    let intermediary_result = if partially_flushed {
                        Ok(())
                    } else {
                        present.submit(&queue)
                    };
                    match intermediary_result {
                        Ok(()) => {
                            let mut b = SubmitCommandBufferBuilder::new();
                            b.set_fence_signal(&fence);
                            b.submit(&queue).map_err(|err| OutcomeErr::Partial(err.into()))
                        },
                        Err(err) => {
                            Err(OutcomeErr::Full(err.into()))
                        }
                    }
                },
            };

            // Restore the state before returning.
            match result {
                Ok(()) => {
                    **state = FenceSignalFutureState::Flushed(previous, fence);
                    Ok(())
                },
                Err(OutcomeErr::Partial(err)) => {
                    **state = FenceSignalFutureState::PartiallyFlushed(previous, fence);
                    Err(err)
                },
                Err(OutcomeErr::Full(err)) => {
                    **state = FenceSignalFutureState::Pending(previous, fence);
                    Err(err)
                },
            }
        }
    }
}

impl<F> FenceSignalFutureState<F> {
    #[inline]
    fn get_prev(&self) -> Option<&F> {
        match *self {
            FenceSignalFutureState::Pending(ref prev, _) => Some(prev),
            FenceSignalFutureState::PartiallyFlushed(ref prev, _) => Some(prev),
            FenceSignalFutureState::Flushed(ref prev, _) => Some(prev),
            FenceSignalFutureState::Cleaned => None,
            FenceSignalFutureState::Poisonned => None,
        }
    }
}

unsafe impl<F> GpuFuture for FenceSignalFuture<F> where F: GpuFuture {
    #[inline]
    fn cleanup_finished(&mut self) {
        self.cleanup_finished_impl()
    }

    #[inline]
    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
        let mut state = self.state.lock().unwrap();
        try!(self.flush_impl(&mut state));

        match *state {
            FenceSignalFutureState::Flushed(_, ref fence) => {
                match self.behavior {
                    FenceSignalFutureBehavior::Block { timeout } => {
                        try!(fence.wait(timeout));
                    },
                    FenceSignalFutureBehavior::Continue => (),
                }
            },
            FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (),
            FenceSignalFutureState::Pending(_, _)  => unreachable!(),
            FenceSignalFutureState::PartiallyFlushed(_, _) => unreachable!(),
        }

        Ok(SubmitAnyBuilder::Empty)
    }

    #[inline]
    fn flush(&self) -> Result<(), FlushError> {
        let mut state = self.state.lock().unwrap();
        self.flush_impl(&mut state)
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        let state = self.state.lock().unwrap();
        match *state {
            FenceSignalFutureState::Flushed(ref prev, _) => {
                prev.signal_finished();
            },
            FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (),
            _ => unreachable!(),
        }
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        match self.behavior {
            FenceSignalFutureBehavior::Continue => {
                let state = self.state.lock().unwrap();
                if state.get_prev().is_some() {
                    false
                } else {
                    true
                }
            },
            FenceSignalFutureBehavior::Block { .. } => {
                true
            },
        }
    }

    #[inline]
    fn queue(&self) -> Option<Arc<Queue>> {
        let state = self.state.lock().unwrap();
        if let Some(prev) = state.get_prev() {
            prev.queue()
        } else {
            None
        }
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
        let state = self.state.lock().unwrap();
        if let Some(previous) = state.get_prev() {
            previous.check_buffer_access(buffer, exclusive, queue)
        } else {
            Err(AccessCheckError::Unknown)
        }
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
        let state = self.state.lock().unwrap();
        if let Some(previous) = state.get_prev() {
            previous.check_image_access(image, layout, exclusive, queue)
        } else {
            Err(AccessCheckError::Unknown)
        }
    }
}

unsafe impl<F> DeviceOwned for FenceSignalFuture<F> where F: GpuFuture {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

impl<F> Drop for FenceSignalFuture<F> where F: GpuFuture {
    fn drop(&mut self) {
        let mut state = self.state.lock().unwrap();

        // We ignore any possible error while submitting for now. Problems are handled below.
        let _ = self.flush_impl(&mut state);

        match mem::replace(&mut *state, FenceSignalFutureState::Cleaned) {
            FenceSignalFutureState::Flushed(previous, fence) => {
                // This is a normal situation. Submitting worked.
                // TODO: handle errors?
                fence.wait(None).unwrap();
                unsafe { previous.signal_finished(); }
            },
            FenceSignalFutureState::Cleaned => {
                // Also a normal situation. The user called `cleanup_finished()` before dropping.
            },
            FenceSignalFutureState::Poisonned => {
                // The previous future was already dropped and blocked the current queue.
            },
            FenceSignalFutureState::Pending(_, _) |
            FenceSignalFutureState::PartiallyFlushed(_, _) => {
                // Flushing produced an error. There's nothing more we can do except drop the
                // previous future and let it block the current queue.
            },
        }
    }
}

unsafe impl<F> GpuFuture for Arc<FenceSignalFuture<F>> where F: GpuFuture {
    #[inline]
    fn cleanup_finished(&mut self) {
        self.cleanup_finished_impl()
    }

    #[inline]
    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
        // Note that this is sound because we always return `SubmitAnyBuilder::Empty`. See the
        // documentation of `build_submission`.
        (**self).build_submission()
    }

    #[inline]
    fn flush(&self) -> Result<(), FlushError> {
        (**self).flush()
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        (**self).signal_finished()
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        (**self).queue_change_allowed()
    }

    #[inline]
    fn queue(&self) -> Option<Arc<Queue>> {
        (**self).queue()
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        (**self).check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
    {
        (**self).check_image_access(image, layout, exclusive, queue)
    }
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use] extern crate log;

use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::io;
use std::path::{PathBuf, Path};
use std::process::Command;

use cargo::{execute_main_without_stdin, handle_error, shell};
use cargo::core::MultiShell;
use cargo::util::{CliError, CliResult, lev_distance, Config};

#[derive(RustcDecodable)]
struct Flags {
    flag_list: bool,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    -v, --verbose       Use verbose output
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never

Some common cargo commands are:
    build       Compile the current project
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();
    execute_main_without_stdin(execute, true, USAGE)
}

macro_rules! each_subcommand{ ($mac:ident) => ({
    $mac!(bench);
    $mac!(build);
    $mac!(clean);
    $mac!(doc);
    $mac!(fetch);
    $mac!(generate_lockfile);
    $mac!(git_checkout);
    $mac!(help);
    $mac!(locate_project);
    $mac!(login);
    $mac!(new);
    $mac!(owner);
    $mac!(package);
    $mac!(pkgid);
    $mac!(publish);
    $mac!(read_manifest);
    $mac!(run);
    $mac!(rustc);
    $mac!(search);
    $mac!(test);
    $mac!(update);
    $mac!(verify_project);
    $mac!(version);
    $mac!(yank);
}) }

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(flags.flag_verbose, flags.flag_quiet));
    try!(config.shell().set_color_config(flags.flag_color.as_ref().map(|s| &s[..])));

    init_git_transports(config);

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands().into_iter() {
            println!("    {}", command);
        };
        return Ok(None)
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbose(true);
            let args = &["cargo".to_string(), "-h".to_string()];
            let r = cargo::call_main_without_stdin(execute, config, USAGE, args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" ||
                  flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => {
            vec!["cargo".to_string(), flags.arg_args[0].clone(),
                 "-h".to_string()]
        }

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => env::args().collect(),
    };

    macro_rules! cmd{ ($name:ident) => (
        if args[1] == stringify!($name).replace("_", "-") {
            mod $name;
            config.shell().set_verbose(true);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }
    ) }
    each_subcommand!(cmd);

    execute_subcommand(&args[1], &args, &mut config.shell());
    Ok(None)
}

fn find_closest(cmd: &str) -> Option<String> {
    let cmds = list_commands();
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter().map(|c| (lev_distance(&c, cmd), c))
                                  .filter(|&(d, _)| d < 4)
                                  .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));

    if filtered.len() == 0 {
        None
    } else {
        Some(filtered[0].1.to_string())
    }
}

fn execute_subcommand(cmd: &str, args: &[String], shell: &mut MultiShell) {
    let command = match find_command(cmd) {
        Some(command) => command,
        None => {
            let msg = match find_closest(cmd) {
                Some(closest) => format!("No such subcommand\n\n\t\
                                          Did you mean `{}`?\n", closest),
                None => "No such subcommand".to_string()
            };
            return handle_error(CliError::new(&msg, 127), shell)
        }
    };
    match Command::new(&command).args(&args[1..]).status() {
        Ok(ref status) if status.success() => {}
        Ok(ref status) => {
            match status.code() {
                Some(code) => handle_error(CliError::new("", code), shell),
                None => {
                    let msg = format!("subcommand failed with: {}", status);
                    handle_error(CliError::new(&msg, 101), shell)
                }
            }
        }
        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
            handle_error(CliError::new("No such subcommand", 127), shell)
        }
        Err(err) => {
            let msg = format!("Subcommand failed to run: {}", err);
            handle_error(CliError::new(&msg, 127), shell)
        }
    }
}

/// List all runnable commands. find_command should always succeed
/// if given one of returned command.
fn list_commands() -> BTreeSet<String> {
    let command_prefix = "cargo-";
    let mut commands = BTreeSet::new();
    for dir in list_command_directory().iter() {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue
        };
        for entry in entries {
            let entry = match entry { Ok(e) => e, Err(..) => continue };
            let entry = entry.path();
            let filename = match entry.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue
            };
            if filename.starts_with(command_prefix) &&
               filename.ends_with(env::consts::EXE_SUFFIX) &&
               is_executable(&entry) {
                let command = &filename[
                    command_prefix.len()..
                    filename.len() - env::consts::EXE_SUFFIX.len()];
                commands.insert(command.to_string());
            }
        }
    }

    macro_rules! add_cmd{ ($cmd:ident) => ({
        commands.insert(stringify!($cmd).replace("_", "-"));
    }) }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable(path: &Path) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path).map(|m| {
        m.permissions().mode() & 0o001 == 0o001
    }).unwrap_or(false)
}
#[cfg(windows)]
fn is_executable(path: &Path) -> bool {
    fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
}

/// Get `Command` to run given command.
fn find_command(cmd: &str) -> Option<PathBuf> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let dirs = list_command_directory();
    let mut command_paths = dirs.iter().map(|dir| dir.join(&command_exe));
    command_paths.find(|path| fs::metadata(&path).is_ok())
}

/// List candidate locations where subcommands might be installed.
fn list_command_directory() -> Vec<PathBuf> {
    let mut dirs = vec![];
    if let Ok(mut path) = env::current_exe() {
        path.pop();
        dirs.push(path.join("../lib/cargo"));
        dirs.push(path);
    }
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>Run cargo with a large stack<commit_after>extern crate cargo;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use] extern crate log;

use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::io;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::thread::Builder;

use cargo::{execute_main_without_stdin, handle_error, shell};
use cargo::core::MultiShell;
use cargo::util::{CliError, CliResult, lev_distance, Config};

#[derive(RustcDecodable)]
struct Flags {
    flag_list: bool,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    -v, --verbose       Use verbose output
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never

Some common cargo commands are:
    build       Compile the current project
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();

    // Right now the algorithm in cargo::core::resolve is pretty recursive and
    // runs the risk of blowing the stack. Platforms tend to have different
    // stack limits by default (I just witnessed 512K on OSX and 2MB on Linux)
    // so to get a consistent experience just spawn ourselves with a large stack
    // size.
    let stack_size = env::var("CARGO_STACK_SIZE").ok()
                         .and_then(|s| s.parse().ok())
                         .unwrap_or(8 * 1024 * 1024); // 8MB
    Builder::new().stack_size(stack_size).spawn(|| {
        execute_main_without_stdin(execute, true, USAGE)
    }).unwrap().join().unwrap();
}

macro_rules! each_subcommand{ ($mac:ident) => ({
    $mac!(bench);
    $mac!(build);
    $mac!(clean);
    $mac!(doc);
    $mac!(fetch);
    $mac!(generate_lockfile);
    $mac!(git_checkout);
    $mac!(help);
    $mac!(locate_project);
    $mac!(login);
    $mac!(new);
    $mac!(owner);
    $mac!(package);
    $mac!(pkgid);
    $mac!(publish);
    $mac!(read_manifest);
    $mac!(run);
    $mac!(rustc);
    $mac!(search);
    $mac!(test);
    $mac!(update);
    $mac!(verify_project);
    $mac!(version);
    $mac!(yank);
}) }

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(flags.flag_verbose, flags.flag_quiet));
    try!(config.shell().set_color_config(flags.flag_color.as_ref().map(|s| &s[..])));

    init_git_transports(config);

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands().into_iter() {
            println!("    {}", command);
        };
        return Ok(None)
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbose(true);
            let args = &["cargo".to_string(), "-h".to_string()];
            let r = cargo::call_main_without_stdin(execute, config, USAGE, args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" ||
                  flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => {
            vec!["cargo".to_string(), flags.arg_args[0].clone(),
                 "-h".to_string()]
        }

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => env::args().collect(),
    };

    macro_rules! cmd{ ($name:ident) => (
        if args[1] == stringify!($name).replace("_", "-") {
            mod $name;
            config.shell().set_verbose(true);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }
    ) }
    each_subcommand!(cmd);

    execute_subcommand(&args[1], &args, &mut config.shell());
    Ok(None)
}

fn find_closest(cmd: &str) -> Option<String> {
    let cmds = list_commands();
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter().map(|c| (lev_distance(&c, cmd), c))
                                  .filter(|&(d, _)| d < 4)
                                  .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));

    if filtered.len() == 0 {
        None
    } else {
        Some(filtered[0].1.to_string())
    }
}

fn execute_subcommand(cmd: &str, args: &[String], shell: &mut MultiShell) {
    let command = match find_command(cmd) {
        Some(command) => command,
        None => {
            let msg = match find_closest(cmd) {
                Some(closest) => format!("No such subcommand\n\n\t\
                                          Did you mean `{}`?\n", closest),
                None => "No such subcommand".to_string()
            };
            return handle_error(CliError::new(&msg, 127), shell)
        }
    };
    match Command::new(&command).args(&args[1..]).status() {
        Ok(ref status) if status.success() => {}
        Ok(ref status) => {
            match status.code() {
                Some(code) => handle_error(CliError::new("", code), shell),
                None => {
                    let msg = format!("subcommand failed with: {}", status);
                    handle_error(CliError::new(&msg, 101), shell)
                }
            }
        }
        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
            handle_error(CliError::new("No such subcommand", 127), shell)
        }
        Err(err) => {
            let msg = format!("Subcommand failed to run: {}", err);
            handle_error(CliError::new(&msg, 127), shell)
        }
    }
}

/// List all runnable commands. find_command should always succeed
/// if given one of returned command.
fn list_commands() -> BTreeSet<String> {
    let command_prefix = "cargo-";
    let mut commands = BTreeSet::new();
    for dir in list_command_directory().iter() {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue
        };
        for entry in entries {
            let entry = match entry { Ok(e) => e, Err(..) => continue };
            let entry = entry.path();
            let filename = match entry.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue
            };
            if filename.starts_with(command_prefix) &&
               filename.ends_with(env::consts::EXE_SUFFIX) &&
               is_executable(&entry) {
                let command = &filename[
                    command_prefix.len()..
                    filename.len() - env::consts::EXE_SUFFIX.len()];
                commands.insert(command.to_string());
            }
        }
    }

    macro_rules! add_cmd{ ($cmd:ident) => ({
        commands.insert(stringify!($cmd).replace("_", "-"));
    }) }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable(path: &Path) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path).map(|m| {
        m.permissions().mode() & 0o001 == 0o001
    }).unwrap_or(false)
}
#[cfg(windows)]
fn is_executable(path: &Path) -> bool {
    fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
}

/// Get `Command` to run given command.
fn find_command(cmd: &str) -> Option<PathBuf> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let dirs = list_command_directory();
    let mut command_paths = dirs.iter().map(|dir| dir.join(&command_exe));
    command_paths.find(|path| fs::metadata(&path).is_ok())
}

/// List candidate locations where subcommands might be installed.
fn list_command_directory() -> Vec<PathBuf> {
    let mut dirs = vec![];
    if let Ok(mut path) = env::current_exe() {
        path.pop();
        dirs.push(path.join("../lib/cargo"));
        dirs.push(path);
    }
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>


<commit_before>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate hamcrest;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate serde_json;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate handlebars;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate rustc_serialize;
extern crate semver;
extern crate serde;
extern crate serde_ignored;
extern crate shell_escape;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate toml;
extern crate url;

use std::io;
use std::fmt;
use rustc_serialize::Decodable;
use serde::ser;
use docopt::Docopt;

use core::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
use core::shell::Verbosity::{Verbose};
use term::color::{BLACK};

pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};

macro_rules! bail {
    ($($fmt:tt)*) => (
        return Err(::util::human(&format_args!($($fmt)*)))
    )
}

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

pub struct CfgInfo {
    // Information about the git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    // The date that the build was performed.
    pub build_date: String,
    // The release channel we were built for.
    pub release_channel: String,
}

pub struct VersionInfo {
    pub major: String,
    pub minor: String,
    pub patch: String,
    pub pre_release: Option<String>,
    // Information that's only available when we were built with
    // configure/make, rather than cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "cargo {}.{}.{}",
               self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
                let empty = String::from("");
                write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            match cfg.commit_info {
                Some(ref ci) => {
                    write!(f, " ({} {})",
                           ci.short_commit_hash, ci.commit_date)?;
                },
                None => {
                    write!(f, " (built {})",
                           cfg.build_date)?;
                }
            }
        };
        Ok(())
    }
}

pub fn call_main_without_stdin<Flags: Decodable>(
            exec: fn(Flags, &Config) -> CliResult,
            config: &Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult
{
    let docopt = Docopt::new(usage).unwrap()
        .options_first(options_first)
        .argv(args.iter().map(|s| &s[..]))
        .help(true);

    let flags = docopt.decode().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(human(e.to_string()), code)
    })?;

    exec(flags, config)
}

pub fn print_json<T: ser::Serialize>(obj: &T) {
    let encoded = serde_json::to_string(&obj).unwrap();
    println!("{}", encoded);
}

pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell {
    enum Output {
        Stdout,
        Stderr,
    }

    let tty = isatty(Output::Stderr);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let err = Shell::create(|| Box::new(io::stderr()), config);

    let tty = isatty(Output::Stdout);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let out = Shell::create(|| Box::new(io::stdout()), config);

    return MultiShell::new(out, err, verbosity);

    #[cfg(unix)]
    fn isatty(output: Output) -> bool {
        let fd = match output {
            Output::Stdout => libc::STDOUT_FILENO,
            Output::Stderr => libc::STDERR_FILENO,
        };

        unsafe { libc::isatty(fd) != 0 }
    }
    #[cfg(windows)]
    fn isatty(output: Output) -> bool {
        extern crate kernel32;
        extern crate winapi;

        let handle = match output {
            Output::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
            Output::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        };

        unsafe {
            let handle = kernel32::GetStdHandle(handle);
            let mut out = 0;
            kernel32::GetConsoleMode(handle, &mut out) != 0
        }
    }
}

pub fn exit_with_error(err: CliError, shell: &mut MultiShell) -> ! {
    debug!("exit_with_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.get_verbose() != Verbose;

    if let Some(error) = error {
        let _ignored_result = if hide {
            shell.error("An unknown error occurred")
        } else if fatal {
            shell.error(&error)
        } else {
            shell.say(&error, BLACK)
        };

        if !handle_cause(&error, shell) || hide {
            let _ = shell.err().say("\nTo learn more, run the command again \
                                     with --verbose.".to_string(), BLACK);
        }
    }

    std::process::exit(exit_code)
}

pub fn handle_error(err: &CargoError, shell: &mut MultiShell) {
    debug!("handle_error; err={:?}", err);

    let _ignored_result = shell.error(err);
    handle_cause(err, shell);
}

fn handle_cause(mut cargo_err: &CargoError, shell: &mut MultiShell) -> bool {
    let verbose = shell.get_verbose();
    let mut err;
    loop {
        cargo_err = match cargo_err.cargo_cause() {
            Some(cause) => cause,
            None => { err = cargo_err.cause(); break }
        };
        if verbose != Verbose && !cargo_err.is_human() { return false }
        print(cargo_err.to_string(), shell);
    }
    loop {
        let cause = match err { Some(err) => err, None => return true };
        if verbose != Verbose { return false }
        print(cause.to_string(), shell);
        err = cause.cause();
    }

    fn print(error: String, shell: &mut MultiShell) {
        let _ = shell.err().say("\nCaused by:", BLACK);
        let _ = shell.err().say(format!("  {}", error), BLACK);
    }
}

pub fn version() -> VersionInfo {
    macro_rules! env_str {
        ($name:expr) => { env!($name).to_string() }
    }
    macro_rules! option_env_str {
        ($name:expr) => { option_env!($name).map(|s| s.to_string()) }
    }
    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info =
                option_env!("CFG_COMMIT_HASH").map(|s| {
                    CommitInfo {
                        commit_hash: s.to_string(),
                        short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                        commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
                    }
                });
            VersionInfo {
                major: option_env_str!("CFG_VERSION_MAJOR").unwrap(),
                minor: option_env_str!("CFG_VERSION_MINOR").unwrap(),
                patch: option_env_str!("CFG_VERSION_PATCH").unwrap(),
                pre_release: option_env_str!("CFG_PRERELEASE_VERSION"),
                cfg_info: Some(CfgInfo {
                    build_date: option_env_str!("CFG_BUILD_DATE").unwrap(),
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info: commit_info,
                }),
            }
        },
        // We are being compiled by Cargo itself.
        None => {
            VersionInfo {
                major: env_str!("CARGO_PKG_VERSION_MAJOR"),
                minor: env_str!("CARGO_PKG_VERSION_MINOR"),
                patch: env_str!("CARGO_PKG_VERSION_PATCH"),
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: None,
            }
        }
    }
}
<commit_msg>Prefer CARGO_PKG_* in version info<commit_after>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate hamcrest;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate serde_json;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate handlebars;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate rustc_serialize;
extern crate semver;
extern crate serde;
extern crate serde_ignored;
extern crate shell_escape;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate toml;
extern crate url;

use std::io;
use std::fmt;
use rustc_serialize::Decodable;
use serde::ser;
use docopt::Docopt;

use core::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
use core::shell::Verbosity::{Verbose};
use term::color::{BLACK};

pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};

macro_rules! bail {
    ($($fmt:tt)*) => (
        return Err(::util::human(&format_args!($($fmt)*)))
    )
}

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

pub struct CfgInfo {
    // Information about the git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    // The date that the build was performed.
    pub build_date: String,
    // The release channel we were built for.
    pub release_channel: String,
}

pub struct VersionInfo {
    pub major: String,
    pub minor: String,
    pub patch: String,
    pub pre_release: Option<String>,
    // Information that's only available when we were built with
    // configure/make, rather than cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "cargo {}.{}.{}",
               self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
                let empty = String::from("");
                write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            match cfg.commit_info {
                Some(ref ci) => {
                    write!(f, " ({} {})",
                           ci.short_commit_hash, ci.commit_date)?;
                },
                None => {
                    write!(f, " (built {})",
                           cfg.build_date)?;
                }
            }
        };
        Ok(())
    }
}

pub fn call_main_without_stdin<Flags: Decodable>(
            exec: fn(Flags, &Config) -> CliResult,
            config: &Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult
{
    let docopt = Docopt::new(usage).unwrap()
        .options_first(options_first)
        .argv(args.iter().map(|s| &s[..]))
        .help(true);

    let flags = docopt.decode().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(human(e.to_string()), code)
    })?;

    exec(flags, config)
}

pub fn print_json<T: ser::Serialize>(obj: &T) {
    let encoded = serde_json::to_string(&obj).unwrap();
    println!("{}", encoded);
}

pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell {
    enum Output {
        Stdout,
        Stderr,
    }

    let tty = isatty(Output::Stderr);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let err = Shell::create(|| Box::new(io::stderr()), config);

    let tty = isatty(Output::Stdout);

    let config = ShellConfig { color_config: color_config, tty: tty };
    let out = Shell::create(|| Box::new(io::stdout()), config);

    return MultiShell::new(out, err, verbosity);

    #[cfg(unix)]
    fn isatty(output: Output) -> bool {
        let fd = match output {
            Output::Stdout => libc::STDOUT_FILENO,
            Output::Stderr => libc::STDERR_FILENO,
        };

        unsafe { libc::isatty(fd) != 0 }
    }
    #[cfg(windows)]
    fn isatty(output: Output) -> bool {
        extern crate kernel32;
        extern crate winapi;

        let handle = match output {
            Output::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
            Output::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        };

        unsafe {
            let handle = kernel32::GetStdHandle(handle);
            let mut out = 0;
            kernel32::GetConsoleMode(handle, &mut out) != 0
        }
    }
}

pub fn exit_with_error(err: CliError, shell: &mut MultiShell) -> ! {
    debug!("exit_with_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.get_verbose() != Verbose;

    if let Some(error) = error {
        let _ignored_result = if hide {
            shell.error("An unknown error occurred")
        } else if fatal {
            shell.error(&error)
        } else {
            shell.say(&error, BLACK)
        };

        if !handle_cause(&error, shell) || hide {
            let _ = shell.err().say("\nTo learn more, run the command again \
                                     with --verbose.".to_string(), BLACK);
        }
    }

    std::process::exit(exit_code)
}

pub fn handle_error(err: &CargoError, shell: &mut MultiShell) {
    debug!("handle_error; err={:?}", err);

    let _ignored_result = shell.error(err);
    handle_cause(err, shell);
}

fn handle_cause(mut cargo_err: &CargoError, shell: &mut MultiShell) -> bool {
    let verbose = shell.get_verbose();
    let mut err;
    loop {
        cargo_err = match cargo_err.cargo_cause() {
            Some(cause) => cause,
            None => { err = cargo_err.cause(); break }
        };
        if verbose != Verbose && !cargo_err.is_human() { return false }
        print(cargo_err.to_string(), shell);
    }
    loop {
        let cause = match err { Some(err) => err, None => return true };
        if verbose != Verbose { return false }
        print(cause.to_string(), shell);
        err = cause.cause();
    }

    fn print(error: String, shell: &mut MultiShell) {
        let _ = shell.err().say("\nCaused by:", BLACK);
        let _ = shell.err().say(format!("  {}", error), BLACK);
    }
}

pub fn version() -> VersionInfo {
    macro_rules! env_str {
        ($name:expr) => { env!($name).to_string() }
    }
    macro_rules! option_env_str {
        ($name:expr) => { option_env!($name).map(|s| s.to_string()) }
    }
    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info =
                option_env!("CFG_COMMIT_HASH").map(|s| {
                    CommitInfo {
                        commit_hash: s.to_string(),
                        short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                        commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
                    }
                });
            VersionInfo {
                major: env_str!("CARGO_PKG_VERSION_MAJOR"),
                minor: env_str!("CARGO_PKG_VERSION_MINOR"),
                patch: env_str!("CARGO_PKG_VERSION_PATCH"),
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: Some(CfgInfo {
                    build_date: option_env_str!("CFG_BUILD_DATE").unwrap(),
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info: commit_info,
                }),
            }
        },
        // We are being compiled by Cargo itself.
        None => {
            VersionInfo {
                major: env_str!("CARGO_PKG_VERSION_MAJOR"),
                minor: env_str!("CARGO_PKG_VERSION_MINOR"),
                patch: env_str!("CARGO_PKG_VERSION_PATCH"),
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: None,
            }
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "comm"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

use getopts::Options;
use std::cmp::Ordering;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Read, stdin, Stdin};
use std::path::Path;

static NAME: &'static str = "comm";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn mkdelim(col: usize, opts: &getopts::Matches) -> String {
    let mut s = String::new();
    let delim = match opts.opt_str("output-delimiter") {
        Some(d) => d.clone(),
        None => "\t".to_string(),
    };

    if col > 1 && !opts.opt_present("1") {
        s.push_str(delim.as_ref());
    }
    if col > 2 && !opts.opt_present("2") {
        s.push_str(delim.as_ref());
    }

    s
}

fn ensure_nl(line: &mut String) {
    match line.chars().last() {
        Some('\n') => (),
        _ => line.push_str("\n")
    }
}

enum LineReader {
    Stdin(Stdin),
    FileIn(BufReader<File>)
}

impl LineReader {
    fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
        match self {
            &mut LineReader::Stdin(ref mut r)  => r.read_line(buf),
            &mut LineReader::FileIn(ref mut r) => r.read_line(buf),
        }
    }
}

fn comm(a: &mut LineReader, b: &mut LineReader, opts: &getopts::Matches) {

    let delim : Vec<String> = (0 .. 4).map(|col| mkdelim(col, opts)).collect();

    let mut ra = &mut String::new();
    let mut na = a.read_line(ra);
    let mut rb = &mut String::new();
    let mut nb = b.read_line(rb);

    while na.is_ok() || nb.is_ok() {
        let ord = match (na.is_ok(), nb.is_ok()) {
            (false, true)  => Ordering::Greater,
            (true , false) => Ordering::Less,
            (true , true) => match(&na, &nb) {
                (&Ok(0), &Ok(0)) => break,
                (&Ok(0), _) => Ordering::Greater,
                (_, &Ok(0)) => Ordering::Less,
                _ =>  ra.cmp(&rb),
            },
            _ => unreachable!(),
        };

        match ord {
            Ordering::Less => {
                if !opts.opt_present("1") {
                    ensure_nl(ra);
                    print!("{}{}", delim[1], ra);
                }
                na = a.read_line(ra);
            },
            Ordering::Greater => {
                if !opts.opt_present("2") {
                    ensure_nl(rb);
                    print!("{}{}", delim[2], rb);
                }
                nb = b.read_line(rb);
            },
            Ordering::Equal => {
                if !opts.opt_present("3") {
                    ensure_nl(ra);
                    print!("{}{}", delim[3], ra);
                }
                na = a.read_line(ra);
                nb = b.read_line(rb);
            }
        }
    }
}

fn open_file(name: &str) -> io::Result<LineReader> {
    match name {
        "-" => Ok(LineReader::Stdin(stdin())),
        _  => {
            let f = try!(File::open(&Path::new(name)));
            Ok(LineReader::FileIn(BufReader::new(f)))
        }
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();
    opts.optflag("1", "", "suppress column 1 (lines uniq to FILE1)");
    opts.optflag("2", "", "suppress column 2 (lines uniq to FILE2)");
    opts.optflag("3", "", "suppress column 3 (lines that appear in both files)");
    opts.optopt("", "output-delimiter", "separate columns with STR", "STR");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.len() != 2 {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS] FILE1 FILE2

Compare sorted files line by line.", NAME, VERSION);

        print!("{}", opts.usage(&msg));

        if matches.free.len() != 2 {
            return 1;
        }
        return 0;
    }

    let mut f1 = open_file(matches.free[0].as_ref()).unwrap();
    let mut f2 = open_file(matches.free[1].as_ref()).unwrap();

    comm(&mut f1, &mut f2, &matches);

    0
}

#[allow(dead_code)]
fn main() {
    std::process::exit(uumain(std::env::args().collect()));
}
<commit_msg>comm: clear buffers between read_line calls<commit_after>#![crate_name = "comm"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

use getopts::Options;
use std::cmp::Ordering;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Read, stdin, Stdin};
use std::path::Path;

static NAME: &'static str = "comm";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn mkdelim(col: usize, opts: &getopts::Matches) -> String {
    let mut s = String::new();
    let delim = match opts.opt_str("output-delimiter") {
        Some(d) => d.clone(),
        None => "\t".to_string(),
    };

    if col > 1 && !opts.opt_present("1") {
        s.push_str(delim.as_ref());
    }
    if col > 2 && !opts.opt_present("2") {
        s.push_str(delim.as_ref());
    }

    s
}

fn ensure_nl(line: &mut String) {
    match line.chars().last() {
        Some('\n') => (),
        _ => line.push_str("\n")
    }
}

enum LineReader {
    Stdin(Stdin),
    FileIn(BufReader<File>)
}

impl LineReader {
    fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
        match self {
            &mut LineReader::Stdin(ref mut r)  => r.read_line(buf),
            &mut LineReader::FileIn(ref mut r) => r.read_line(buf),
        }
    }
}

fn comm(a: &mut LineReader, b: &mut LineReader, opts: &getopts::Matches) {

    let delim : Vec<String> = (0 .. 4).map(|col| mkdelim(col, opts)).collect();

    let mut ra = &mut String::new();
    let mut na = a.read_line(ra);
    let mut rb = &mut String::new();
    let mut nb = b.read_line(rb);

    while na.is_ok() || nb.is_ok() {
        let ord = match (na.is_ok(), nb.is_ok()) {
            (false, true)  => Ordering::Greater,
            (true , false) => Ordering::Less,
            (true , true) => match(&na, &nb) {
                (&Ok(0), &Ok(0)) => break,
                (&Ok(0), _) => Ordering::Greater,
                (_, &Ok(0)) => Ordering::Less,
                _ =>  ra.cmp(&rb),
            },
            _ => unreachable!(),
        };

        match ord {
            Ordering::Less => {
                if !opts.opt_present("1") {
                    ensure_nl(ra);
                    print!("{}{}", delim[1], ra);
                }
                ra.clear();
                na = a.read_line(ra);
            },
            Ordering::Greater => {
                if !opts.opt_present("2") {
                    ensure_nl(rb);
                    print!("{}{}", delim[2], rb);
                }
                rb.clear();
                nb = b.read_line(rb);
            },
            Ordering::Equal => {
                if !opts.opt_present("3") {
                    ensure_nl(ra);
                    print!("{}{}", delim[3], ra);
                }
                ra.clear();
                rb.clear();
                na = a.read_line(ra);
                nb = b.read_line(rb);
            }
        }
    }
}

fn open_file(name: &str) -> io::Result<LineReader> {
    match name {
        "-" => Ok(LineReader::Stdin(stdin())),
        _  => {
            let f = try!(File::open(&Path::new(name)));
            Ok(LineReader::FileIn(BufReader::new(f)))
        }
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();
    opts.optflag("1", "", "suppress column 1 (lines uniq to FILE1)");
    opts.optflag("2", "", "suppress column 2 (lines uniq to FILE2)");
    opts.optflag("3", "", "suppress column 3 (lines that appear in both files)");
    opts.optopt("", "output-delimiter", "separate columns with STR", "STR");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.len() != 2 {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS] FILE1 FILE2

Compare sorted files line by line.", NAME, VERSION);

        print!("{}", opts.usage(&msg));

        if matches.free.len() != 2 {
            return 1;
        }
        return 0;
    }

    let mut f1 = open_file(matches.free[0].as_ref()).unwrap();
    let mut f2 = open_file(matches.free[1].as_ref()).unwrap();

    comm(&mut f1, &mut f2, &matches);

    0
}

#[allow(dead_code)]
fn main() {
    std::process::exit(uumain(std::env::args().collect()));
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::f64;
use std::ops::{ Add, Sub, Mul, Div };

use core::Angle;

#[derive(Clone, Copy, Debug)]
/// Vector struct, implements vector operations
pub struct Vec2<T>(pub T, pub T)
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug;

impl<T> Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {
  /// Get x component
  pub fn x(&self) -> T { self.0 }
  /// Get y component
  pub fn y(&self) -> T { self.1 }
  /// Get norm (i.e. complex absolute value)
  pub fn norm(&self) -> T {
    self.x() * self.x() + self.y() * self.y()
  }
}

// Question for the blue_deref: Why implement this for f32 and f64 and not just Float
impl Vec2<f32> {
  /// Convert polar form to Vec2
  pub fn from_magnitude(magnitude: f32, direction: Angle<f32>) -> Vec2<f32> {
    Vec2(
      f32::cos(direction.as_radians()) * magnitude,
      f32::sin(direction.as_radians()) * magnitude
    )
  }
}

impl Vec2<f64> {
  pub fn from_magnitude(magnitude: f64, direction: Angle<f64>) -> Vec2<f64> {
    Vec2(
      f64::cos(direction.as_radians()) * magnitude,
      f64::sin(direction.as_radians()) * magnitude
    )
  }
}

impl<T> Add for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn add(self, other: Vec2<T>) -> Self::Output {
    Vec2(self.0 + other.0, self.1 + other.1)
  }
}

impl<T> Sub for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn sub(self, other: Vec2<T>) -> Self::Output {
    Vec2(self.0 - other.0, self.1 - other.1)
  }
}

impl<T> Mul<T> for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn mul(self, other: T) -> Self::Output {
    Vec2(self.0 * other, self.1 * other)
  }
}

impl<T> Div<T> for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn div(self, other: T) -> Self::Output {
    Vec2(self.0 / other, self.1 / other)
  }
}
<commit_msg>Change vector * scalar mul/div param to `scalar`<commit_after>use std::fmt::Debug;
use std::f64;
use std::ops::{ Add, Sub, Mul, Div };

use core::Angle;

#[derive(Clone, Copy, Debug)]
/// Vector struct, implements vector operations
pub struct Vec2<T>(pub T, pub T)
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug;

impl<T> Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {
  /// Get x component
  pub fn x(&self) -> T { self.0 }
  /// Get y component
  pub fn y(&self) -> T { self.1 }
  /// Get norm (i.e. complex absolute value)
  pub fn norm(&self) -> T {
    self.x() * self.x() + self.y() * self.y()
  }
}

// Question for the blue_deref: Why implement this for f32 and f64 and not just Float
impl Vec2<f32> {
  /// Convert polar form to Vec2
  pub fn from_magnitude(magnitude: f32, direction: Angle<f32>) -> Vec2<f32> {
    Vec2(
      f32::cos(direction.as_radians()) * magnitude,
      f32::sin(direction.as_radians()) * magnitude
    )
  }
}

impl Vec2<f64> {
  pub fn from_magnitude(magnitude: f64, direction: Angle<f64>) -> Vec2<f64> {
    Vec2(
      f64::cos(direction.as_radians()) * magnitude,
      f64::sin(direction.as_radians()) * magnitude
    )
  }
}

impl<T> Add for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn add(self, other: Vec2<T>) -> Self::Output {
    Vec2(self.0 + other.0, self.1 + other.1)
  }
}

impl<T> Sub for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn sub(self, other: Vec2<T>) -> Self::Output {
    Vec2(self.0 - other.0, self.1 - other.1)
  }
}

impl<T> Mul<T> for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn mul(self, scalar: T) -> Self::Output {
    Vec2(self.0 * scalar, self.1 * scalar)
  }
}

impl<T> Div<T> for Vec2<T>
  where T: Add<Output=T>
         + Sub<Output=T>
         + Mul<Output=T>
         + Div<Output=T>
         + Clone + Copy + Debug {

  type Output = Vec2<T>;

  fn div(self, scalar: T) -> Self::Output {
    Vec2(self.0 / scalar, self.1 / scalar)
  }
}
<|endoftext|>


<commit_before>// check-pass

// From https://github.com/rust-lang/rust/issues/72476

trait A {
    type Projection;
}

impl A for () {
    type Projection = bool;
    // using () instead of bool here does compile though
}

struct Next<T: A>(T::Projection);

fn f(item: Next<()>) {
    match item {
        Next(true) => {}
        Next(false) => {}
    }
}

fn main() {}
<commit_msg>Remove out-of-date comment<commit_after>// check-pass

// From https://github.com/rust-lang/rust/issues/72476

trait A {
    type Projection;
}

impl A for () {
    type Projection = bool;
}

struct Next<T: A>(T::Projection);

fn f(item: Next<()>) {
    match item {
        Next(true) => {}
        Next(false) => {}
    }
}

fn main() {}
<|endoftext|>


<commit_before>peg_file! streamql("streamql.rustpeg");

use self::streamql::{statement, ParseError};

fn parse_statement(query: &str) -> Result<Statement, ParseError> {
    statement(query)
}

#[derive(Debug)]
pub enum Statement {
    Insert(InsertStatement),
    CreateStream,
    DropStream,
    UseDatabase,
    Select,
    Subscribe,
}

#[derive(Debug)]
pub struct InsertStatement {
    stream: String
}

impl InsertStatement {
    pub fn new(stream: String) -> InsertStatement {
        InsertStatement{stream: stream}
    }
}

#[cfg(test)]
mod tests {
    use super::parse_statement;
    use super::Statement;
    use super::streamql::int_value;

    #[test]
    fn test_basic_insert() {
        let result = parse_statement("INSERT INTO test set k=1;").unwrap();

        if let Statement::Insert(x) = result {
            assert_eq!(x.stream, String::from("test"));
        } else {
            panic!("")
        }
    }

    #[test]
    fn test_int_parsing() {
        let tmp = int_value("42").unwrap();

    }
}

<commit_msg>another test for insert parsing<commit_after>peg_file! streamql("streamql.rustpeg");

use self::streamql::{statement, ParseError};

fn parse_statement(query: &str) -> Result<Statement, ParseError> {
    statement(query)
}

#[derive(Debug)]
pub enum Statement {
    Insert(InsertStatement),
    CreateStream,
    DropStream,
    UseDatabase,
    Select,
    Subscribe,
}

#[derive(Debug)]
pub struct InsertStatement {
    stream: String
}

impl InsertStatement {
    pub fn new(stream: String) -> InsertStatement {
        InsertStatement{stream: stream}
    }
}

#[cfg(test)]
mod tests {
    use super::parse_statement;
    use super::Statement;
    use super::streamql::int_value;

    #[test]
    fn test_basic_insert() {
        let result = parse_statement("INSERT INTO test set k=1;").unwrap();

        if let Statement::Insert(x) = result {
            assert_eq!(x.stream, String::from("test"));
        } else {
            panic!("")
        }
        let x = "INSERT INTO test set k=1, v=2;";
        let result = parse_statement(x).unwrap();
    }

    #[test]

    #[test]
    fn test_int_parsing() {
        let tmp = int_value("42").unwrap();

    }
}

<|endoftext|>