<commit_before>//! A channel for sending a single message between asynchronous tasks.

use futures_core::future::Future;
use futures_core::task::{Context, Poll, Waker};
use std::pin::Pin;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
use std::error::Error;
use std::fmt;

use crate::lock::Lock;

/// A future for a value that will be provided by another asynchronous task.
///
/// This is created by the [`channel`] function.
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct Receiver<T> {
    inner: Arc<Inner<T>>,
}

/// A means of transmitting a single value to another task.
///
/// This is created by the [`channel`] function.
#[derive(Debug)]
pub struct Sender<T> {
    inner: Arc<Inner<T>>,
}

// The channels do not ever project Pin to the inner T
impl<T> Unpin for Receiver<T> {}
impl<T> Unpin for Sender<T> {}

/// Internal state of the `Receiver`/`Sender` pair above. This is all used as
/// the internal synchronization between the two for send/recv operations.
#[derive(Debug)]
struct Inner<T> {
    /// Indicates whether this oneshot is complete yet. This is filled in both
    /// by `Sender::drop` and by `Receiver::drop`, and both sides interpret it
    /// appropriately.
    ///
    /// For `Receiver`, if this is `true`, then it's guaranteed that `data` is
    /// unlocked and ready to be inspected.
    ///
    /// For `Sender` if this is `true` then the oneshot has gone away and it
    /// can return ready from `poll_cancel`.
    complete: AtomicBool,

    /// The actual data being transferred as part of this `Receiver`. This is
    /// filled in by `Sender::complete` and read by `Receiver::poll`.
    ///
    /// Note that this is protected by `Lock`, but it is in theory safe to
    /// replace with an `UnsafeCell` as it's actually protected by `complete`
    /// above. I wouldn't recommend doing this, however, unless someone is
    /// supremely confident in the various atomic orderings here and there.
    data: Lock<Option<T>>,

    /// Field to store the task which is blocked in `Receiver::poll`.
    ///
    /// This is filled in when a oneshot is polled but not ready yet. Note that
    /// the `Lock` here, unlike in `data` above, is important to resolve races.
    /// Both the `Receiver` and the `Sender` halves understand that if they
    /// can't acquire the lock then some important interference is happening.
    rx_task: Lock<Option<Waker>>,

    /// Like `rx_task` above, except for the task blocked in
    /// `Sender::poll_cancel`. Additionally, `Lock` cannot be `UnsafeCell`.
    tx_task: Lock<Option<Waker>>,
}

/// Creates a new one-shot channel for sending values across asynchronous tasks.
///
/// This function is similar to Rust's channel constructor found in the standard
/// library. Two halves are returned, the first of which is a `Sender` handle,
/// used to signal the end of a computation and provide its value. The second
/// half is a `Receiver` which implements the `Future` trait, resolving to the
/// value that was given to the `Sender` handle.
///
/// Each half can be separately owned and sent across tasks.
///
/// # Examples
///
/// ```
/// use futures::channel::oneshot;
/// use futures::future::FutureExt;
/// use std::thread;
///
/// let (sender, receiver) = oneshot::channel::<i32>();
///
/// # let t =
/// thread::spawn(|| {
///     let future = receiver.map(|i| {
///         println!("got: {:?}", i);
///     });
///     // ...
/// # return future;
/// });
///
/// sender.send(3).unwrap();
/// # futures::executor::block_on(t.join().unwrap());
/// ```
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let inner = Arc::new(Inner::new());
    let receiver = Receiver {
        inner: inner.clone(),
    };
    let sender = Sender {
        inner,
    };
    (sender, receiver)
}

impl<T> Inner<T> {
    fn new() -> Inner<T> {
        Inner {
            complete: AtomicBool::new(false),
            data: Lock::new(None),
            rx_task: Lock::new(None),
            tx_task: Lock::new(None),
        }
    }

    fn send(&self, t: T) -> Result<(), T> {
        if self.complete.load(SeqCst) {
            return Err(t)
        }

        // Note that this lock acquisition may fail if the receiver
        // is closed and sets the `complete` flag to true, whereupon
        // the receiver may call `poll()`.
        if let Some(mut slot) = self.data.try_lock() {
            assert!(slot.is_none());
            *slot = Some(t);
            drop(slot);

            // If the receiver called `close()` between the check at the
            // start of the function, and the lock being released, then
            // the receiver may not be around to receive it, so try to
            // pull it back out.
            if self.complete.load(SeqCst) {
                // If lock acquisition fails, then receiver is actually
                // receiving it, so we're good.
                if let Some(mut slot) = self.data.try_lock() {
                    if let Some(t) = slot.take() {
                        return Err(t);
                    }
                }
            }
            Ok(())
        } else {
            // Must have been closed
            Err(t)
        }
    }

    fn poll_cancel(&self, cx: &mut Context<'_>) -> Poll<()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone. This flag is set both in our destructor and the oneshot
        // destructor, but our destructor hasn't run yet so if it's set then the
        // oneshot is gone.
        if self.complete.load(SeqCst) {
            return Poll::Ready(())
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Receiver` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the
        // `Receiver` may have been dropped. The first thing it does is set the
        // flag, and if it fails to acquire the lock it assumes that we'll see
        // the flag later on. So... we then try to see the flag later on!
        let handle = cx.waker().clone();
        match self.tx_task.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Poll::Ready(()),
        }
        if self.complete.load(SeqCst) {
            Poll::Ready(())
        } else {
            Poll::Pending
        }
    }

    fn is_canceled(&self) -> bool {
        self.complete.load(SeqCst)
    }

    fn drop_tx(&self) {
        // Flag that we're a completed `Sender` and try to wake up a receiver.
        // Whether or not we actually stored any data will get picked up and
        // translated to either an item or cancellation.
        //
        // Note that if we fail to acquire the `rx_task` lock then that means
        // we're in one of two situations:
        //
        // 1. The receiver is trying to block in `poll`
        // 2. The receiver is being dropped
        //
        // In the first case it'll check the `complete` flag after it's done
        // blocking to see if it succeeded. In the latter case we don't need to
        // wake up anyone anyway. So in both cases it's ok to ignore the `None`
        // case of `try_lock` and bail out.
        //
        // The first case crucially depends on `Lock` using `SeqCst` ordering
        // under the hood. If it instead used `Release` / `Acquire` ordering,
        // then it would not necessarily synchronize with `inner.complete`
        // and deadlock might be possible, as was observed in
        // https://github.com/rust-lang-nursery/futures-rs/pull/219.
        self.complete.store(true, SeqCst);

        if let Some(mut slot) = self.rx_task.try_lock() {
            if let Some(task) = slot.take() {
                drop(slot);
                task.wake();
            }
        }

        // If we registered a task for cancel notification drop it to reduce
        // spurious wakeups
        if let Some(mut slot) = self.tx_task.try_lock() {
            drop(slot.take());
        }
    }

    fn close_rx(&self) {
        // Flag our completion and then attempt to wake up the sender if it's
        // blocked. See comments in `drop` below for more info
        self.complete.store(true, SeqCst);
        if let Some(mut handle) = self.tx_task.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.wake()
            }
        }
    }

    fn try_recv(&self) -> Result<Option<T>, Canceled> {
        // If we're complete, either `::close_rx` or `::drop_tx` was called.
        // We can assume a successful send if data is present.
        if self.complete.load(SeqCst) {
            if let Some(mut slot) = self.data.try_lock() {
                if let Some(data) = slot.take() {
                    return Ok(Some(data));
                }
            }
            Err(Canceled)
        } else {
            Ok(None)
        }
    }

    fn recv(&self, cx: &mut Context<'_>) -> Poll<Result<T, Canceled>> {
        // Check to see if some data has arrived. If it hasn't then we need to
        // block our task.
        //
        // Note that the acquisition of the `rx_task` lock might fail below, but
        // the only situation where this can happen is during `Sender::drop`
        // when we are indeed completed already. If that's happening then we
        // know we're completed so keep going.
        let done = if self.complete.load(SeqCst) {
            true
        } else {
            let task = cx.waker().clone();
            match self.rx_task.try_lock() {
                Some(mut slot) => { *slot = Some(task); false },
                None => true,
            }
        };

        // If we're `done` via one of the paths above, then look at the data and
        // figure out what the answer is. If, however, we stored `rx_task`
        // successfully above we need to check again if we're completed in case
        // a message was sent while `rx_task` was locked and couldn't notify us
        // otherwise.
        //
        // If we're not done, and we're not complete, though, then we've
        // successfully blocked our task and we return `Pending`.
        if done || self.complete.load(SeqCst) {
            // If taking the lock fails, the sender will realise that the we're
            // `done` when it checks the `complete` flag on the way out, and
            // will treat the send as a failure.
            if let Some(mut slot) = self.data.try_lock() {
                if let Some(data) = slot.take() {
                    return Poll::Ready(Ok(data));
                }
            }
            Poll::Ready(Err(Canceled))
        } else {
            Poll::Pending
        }
    }

    fn drop_rx(&self) {
        // Indicate to the `Sender` that we're done, so any future calls to
        // `poll_cancel` are weeded out.
        self.complete.store(true, SeqCst);

        // If we've blocked a task then there's no need for it to stick around,
        // so we need to drop it. If this lock acquisition fails, though, then
        // it's just because our `Sender` is trying to take the task, so we
        // let them take care of that.
        if let Some(mut slot) = self.rx_task.try_lock() {
            let task = slot.take();
            drop(slot);
            drop(task);
        }

        // Finally, if our `Sender` wants to get notified of us going away, it
        // would have stored something in `tx_task`. Here we try to peel that
        // out and unpark it.
        //
        // Note that the `try_lock` here may fail, but only if the `Sender` is
        // in the process of filling in the task. If that happens then we
        // already flagged `complete` and they'll pick that up above.
        if let Some(mut handle) = self.tx_task.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.wake()
            }
        }
    }
}

impl<T> Sender<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// [`Receiver`](Receiver), that the value provided is the result of the
    /// computation this represents.
    ///
    /// If the value is successfully enqueued for the remote end to receive,
    /// then `Ok(())` is returned. If the receiving end was dropped before
    /// this function was called, however, then `Err` is returned with the value
    /// provided.
    pub fn send(self, t: T) -> Result<(), T> {
        self.inner.send(t)
    }

    /// Polls this `Sender` half to detect whether its associated
    /// [`Receiver`](Receiver) with has been dropped.
    ///
    /// # Return values
    ///
    /// If `Ok(Ready)` is returned then the associated `Receiver` has been
    /// dropped, which means any work required for sending should be canceled.
    ///
    /// If `Ok(Pending)` is returned then the associated `Receiver` is still
    /// alive and may be able to receive a message if sent. The current task,
    /// however, is scheduled to receive a notification if the corresponding
    /// `Receiver` goes away.
    pub fn poll_cancel(&mut self, cx: &mut Context<'_>) -> Poll<()> {
        self.inner.poll_cancel(cx)
    }

    /// Tests to see whether this `Sender`'s corresponding `Receiver`
    /// has been dropped.
    ///
    /// Unlike [`poll_cancel`](Sender::poll_cancel), this function does not
    /// enqueue a task for wakeup upon cancellation, but merely reports the
    /// current state, which may be subject to concurrent modification.
    pub fn is_canceled(&self) -> bool {
        self.inner.is_canceled()
    }
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        self.inner.drop_tx()
    }
}

/// Error returned from a [`Receiver`](Receiver) when the corresponding
/// [`Sender`](Sender) is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "oneshot canceled")
    }
}

impl Error for Canceled {
    fn description(&self) -> &str {
        "oneshot canceled"
    }
}

impl<T> Receiver<T> {
    /// Gracefully close this receiver, preventing any subsequent attempts to
    /// send to it.
    ///
    /// Any `send` operation which happens after this method returns is
    /// guaranteed to fail. After calling this method, you can use
    /// [`Receiver::poll`](Future::poll) to determine whether a
    /// message had previously been sent.
    pub fn close(&mut self) {
        self.inner.close_rx()
    }

    /// Attempts to receive a message outside of the context of a task.
    ///
    /// Does not schedule a task wakeup or have any other side effects.
    ///
    /// A return value of `None` must be considered immediately stale (out of
    /// date) unless [`close`](Receiver::close) has been called first.
    ///
    /// Returns an error if the sender was dropped.
    pub fn try_recv(&mut self) -> Result<Option<T>, Canceled> {
        self.inner.try_recv()
    }
}

impl<T> Future for Receiver<T> {
    type Output = Result<T, Canceled>;

    fn poll(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<T, Canceled>> {
        self.inner.recv(cx)
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        self.inner.drop_rx()
    }
}
<commit_msg>futures_channel<commit_after>//! A channel for sending a single message between asynchronous tasks.

use futures_core::future::Future;
use futures_core::task::{Context, Poll, Waker};
use std::pin::Pin;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
use std::error::Error;
use std::fmt;

use crate::lock::Lock;

/// A future for a value that will be provided by another asynchronous task.
///
/// This is created by the [`channel`] function.
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct Receiver<T> {
    inner: Arc<Inner<T>>,
}

/// A means of transmitting a single value to another task.
///
/// This is created by the [`channel`] function.
#[derive(Debug)]
pub struct Sender<T> {
    inner: Arc<Inner<T>>,
}

// The channels do not ever project Pin to the inner T
impl<T> Unpin for Receiver<T> {}
impl<T> Unpin for Sender<T> {}

/// Internal state of the `Receiver`/`Sender` pair above. This is all used as
/// the internal synchronization between the two for send/recv operations.
#[derive(Debug)]
struct Inner<T> {
    /// Indicates whether this oneshot is complete yet. This is filled in both
    /// by `Sender::drop` and by `Receiver::drop`, and both sides interpret it
    /// appropriately.
    ///
    /// For `Receiver`, if this is `true`, then it's guaranteed that `data` is
    /// unlocked and ready to be inspected.
    ///
    /// For `Sender` if this is `true` then the oneshot has gone away and it
    /// can return ready from `poll_cancel`.
    complete: AtomicBool,

    /// The actual data being transferred as part of this `Receiver`. This is
    /// filled in by `Sender::complete` and read by `Receiver::poll`.
    ///
    /// Note that this is protected by `Lock`, but it is in theory safe to
    /// replace with an `UnsafeCell` as it's actually protected by `complete`
    /// above. I wouldn't recommend doing this, however, unless someone is
    /// supremely confident in the various atomic orderings here and there.
    data: Lock<Option<T>>,

    /// Field to store the task which is blocked in `Receiver::poll`.
    ///
    /// This is filled in when a oneshot is polled but not ready yet. Note that
    /// the `Lock` here, unlike in `data` above, is important to resolve races.
    /// Both the `Receiver` and the `Sender` halves understand that if they
    /// can't acquire the lock then some important interference is happening.
    rx_task: Lock<Option<Waker>>,

    /// Like `rx_task` above, except for the task blocked in
    /// `Sender::poll_cancel`. Additionally, `Lock` cannot be `UnsafeCell`.
    tx_task: Lock<Option<Waker>>,
}

/// Creates a new one-shot channel for sending values across asynchronous tasks.
///
/// This function is similar to Rust's channel constructor found in the standard
/// library. Two halves are returned, the first of which is a `Sender` handle,
/// used to signal the end of a computation and provide its value. The second
/// half is a `Receiver` which implements the `Future` trait, resolving to the
/// value that was given to the `Sender` handle.
///
/// Each half can be separately owned and sent across tasks.
///
/// # Examples
///
/// ```
/// use futures::channel::oneshot;
/// use futures::future::FutureExt;
/// use std::thread;
///
/// let (sender, receiver) = oneshot::channel::<i32>();
///
/// # let t =
/// thread::spawn(|| {
///     let future = receiver.map(|i| {
///         println!("got: {:?}", i);
///     });
///     // ...
/// # return future;
/// });
///
/// sender.send(3).unwrap();
/// # futures::executor::block_on(t.join().unwrap());
/// ```
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let inner = Arc::new(Inner::new());
    let receiver = Receiver {
        inner: inner.clone(),
    };
    let sender = Sender {
        inner,
    };
    (sender, receiver)
}

impl<T> Inner<T> {
    fn new() -> Inner<T> {
        Inner {
            complete: AtomicBool::new(false),
            data: Lock::new(None),
            rx_task: Lock::new(None),
            tx_task: Lock::new(None),
        }
    }

    fn send(&self, t: T) -> Result<(), T> {
        if self.complete.load(SeqCst) {
            return Err(t)
        }

        // Note that this lock acquisition may fail if the receiver
        // is closed and sets the `complete` flag to true, whereupon
        // the receiver may call `poll()`.
        if let Some(mut slot) = self.data.try_lock() {
            assert!(slot.is_none());
            *slot = Some(t);
            drop(slot);

            // If the receiver called `close()` between the check at the
            // start of the function, and the lock being released, then
            // the receiver may not be around to receive it, so try to
            // pull it back out.
            if self.complete.load(SeqCst) {
                // If lock acquisition fails, then receiver is actually
                // receiving it, so we're good.
                if let Some(mut slot) = self.data.try_lock() {
                    if let Some(t) = slot.take() {
                        return Err(t);
                    }
                }
            }
            Ok(())
        } else {
            // Must have been closed
            Err(t)
        }
    }

    fn poll_cancel(&self, cx: &mut Context<'_>) -> Poll<()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone. This flag is set both in our destructor and the oneshot
        // destructor, but our destructor hasn't run yet so if it's set then the
        // oneshot is gone.
        if self.complete.load(SeqCst) {
            return Poll::Ready(())
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Receiver` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the
        // `Receiver` may have been dropped. The first thing it does is set the
        // flag, and if it fails to acquire the lock it assumes that we'll see
        // the flag later on. So... we then try to see the flag later on!
        let handle = cx.waker().clone();
        match self.tx_task.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Poll::Ready(()),
        }
        if self.complete.load(SeqCst) {
            Poll::Ready(())
        } else {
            Poll::Pending
        }
    }

    fn is_canceled(&self) -> bool {
        self.complete.load(SeqCst)
    }

    fn drop_tx(&self) {
        // Flag that we're a completed `Sender` and try to wake up a receiver.
        // Whether or not we actually stored any data will get picked up and
        // translated to either an item or cancellation.
        //
        // Note that if we fail to acquire the `rx_task` lock then that means
        // we're in one of two situations:
        //
        // 1. The receiver is trying to block in `poll`
        // 2. The receiver is being dropped
        //
        // In the first case it'll check the `complete` flag after it's done
        // blocking to see if it succeeded. In the latter case we don't need to
        // wake up anyone anyway. So in both cases it's ok to ignore the `None`
        // case of `try_lock` and bail out.
        //
        // The first case crucially depends on `Lock` using `SeqCst` ordering
        // under the hood. If it instead used `Release` / `Acquire` ordering,
        // then it would not necessarily synchronize with `inner.complete`
        // and deadlock might be possible, as was observed in
        // https://github.com/rust-lang-nursery/futures-rs/pull/219.
        self.complete.store(true, SeqCst);

        if let Some(mut slot) = self.rx_task.try_lock() {
            if let Some(task) = slot.take() {
                drop(slot);
                task.wake();
            }
        }

        // If we registered a task for cancel notification drop it to reduce
        // spurious wakeups
        if let Some(mut slot) = self.tx_task.try_lock() {
            drop(slot.take());
        }
    }

    fn close_rx(&self) {
        // Flag our completion and then attempt to wake up the sender if it's
        // blocked. See comments in `drop` below for more info
        self.complete.store(true, SeqCst);
        if let Some(mut handle) = self.tx_task.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.wake()
            }
        }
    }

    fn try_recv(&self) -> Result<Option<T>, Canceled> {
        // If we're complete, either `::close_rx` or `::drop_tx` was called.
        // We can assume a successful send if data is present.
        if self.complete.load(SeqCst) {
            if let Some(mut slot) = self.data.try_lock() {
                if let Some(data) = slot.take() {
                    return Ok(Some(data));
                }
            }
            Err(Canceled)
        } else {
            Ok(None)
        }
    }

    fn recv(&self, cx: &mut Context<'_>) -> Poll<Result<T, Canceled>> {
        // Check to see if some data has arrived. If it hasn't then we need to
        // block our task.
        //
        // Note that the acquisition of the `rx_task` lock might fail below, but
        // the only situation where this can happen is during `Sender::drop`
        // when we are indeed completed already. If that's happening then we
        // know we're completed so keep going.
        let done = if self.complete.load(SeqCst) {
            true
        } else {
            let task = cx.waker().clone();
            match self.rx_task.try_lock() {
                Some(mut slot) => { *slot = Some(task); false },
                None => true,
            }
        };

        // If we're `done` via one of the paths above, then look at the data and
        // figure out what the answer is. If, however, we stored `rx_task`
        // successfully above we need to check again if we're completed in case
        // a message was sent while `rx_task` was locked and couldn't notify us
        // otherwise.
        //
        // If we're not done, and we're not complete, though, then we've
        // successfully blocked our task and we return `Pending`.
        if done || self.complete.load(SeqCst) {
            // If taking the lock fails, the sender will realise that the we're
            // `done` when it checks the `complete` flag on the way out, and
            // will treat the send as a failure.
            if let Some(mut slot) = self.data.try_lock() {
                if let Some(data) = slot.take() {
                    return Poll::Ready(Ok(data));
                }
            }
            Poll::Ready(Err(Canceled))
        } else {
            Poll::Pending
        }
    }

    fn drop_rx(&self) {
        // Indicate to the `Sender` that we're done, so any future calls to
        // `poll_cancel` are weeded out.
        self.complete.store(true, SeqCst);

        // If we've blocked a task then there's no need for it to stick around,
        // so we need to drop it. If this lock acquisition fails, though, then
        // it's just because our `Sender` is trying to take the task, so we
        // let them take care of that.
        if let Some(mut slot) = self.rx_task.try_lock() {
            let task = slot.take();
            drop(slot);
            drop(task);
        }

        // Finally, if our `Sender` wants to get notified of us going away, it
        // would have stored something in `tx_task`. Here we try to peel that
        // out and unpark it.
        //
        // Note that the `try_lock` here may fail, but only if the `Sender` is
        // in the process of filling in the task. If that happens then we
        // already flagged `complete` and they'll pick that up above.
        if let Some(mut handle) = self.tx_task.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.wake()
            }
        }
    }
}

impl<T> Sender<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// [`Receiver`](Receiver), that the value provided is the result of the
    /// computation this represents.
    ///
    /// If the value is successfully enqueued for the remote end to receive,
    /// then `Ok(())` is returned. If the receiving end was dropped before
    /// this function was called, however, then `Err` is returned with the value
    /// provided.
    pub fn send(self, t: T) -> Result<(), T> {
        self.inner.send(t)
    }

    /// Polls this `Sender` half to detect whether its associated
    /// [`Receiver`](Receiver) with has been dropped.
    ///
    /// # Return values
    ///
    /// If `Ok(Ready)` is returned then the associated `Receiver` has been
    /// dropped, which means any work required for sending should be canceled.
    ///
    /// If `Ok(Pending)` is returned then the associated `Receiver` is still
    /// alive and may be able to receive a message if sent. The current task,
    /// however, is scheduled to receive a notification if the corresponding
    /// `Receiver` goes away.
    pub fn poll_cancel(&mut self, cx: &mut Context<'_>) -> Poll<()> {
        self.inner.poll_cancel(cx)
    }

    /// Tests to see whether this `Sender`'s corresponding `Receiver`
    /// has been dropped.
    ///
    /// Unlike [`poll_cancel`](Sender::poll_cancel), this function does not
    /// enqueue a task for wakeup upon cancellation, but merely reports the
    /// current state, which may be subject to concurrent modification.
    pub fn is_canceled(&self) -> bool {
        self.inner.is_canceled()
    }
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        self.inner.drop_tx()
    }
}

/// Error returned from a [`Receiver`](Receiver) when the corresponding
/// [`Sender`](Sender) is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "oneshot canceled")
    }
}

impl Error for Canceled {
    fn description(&self) -> &str {
        "oneshot canceled"
    }
}

impl<T> Receiver<T> {
    /// Gracefully close this receiver, preventing any subsequent attempts to
    /// send to it.
    ///
    /// Any `send` operation which happens after this method returns is
    /// guaranteed to fail. After calling this method, you can use
    /// [`Receiver::poll`](core::future::Future::poll) to determine whether a
    /// message had previously been sent.
    pub fn close(&mut self) {
        self.inner.close_rx()
    }

    /// Attempts to receive a message outside of the context of a task.
    ///
    /// Does not schedule a task wakeup or have any other side effects.
    ///
    /// A return value of `None` must be considered immediately stale (out of
    /// date) unless [`close`](Receiver::close) has been called first.
    ///
    /// Returns an error if the sender was dropped.
    pub fn try_recv(&mut self) -> Result<Option<T>, Canceled> {
        self.inner.try_recv()
    }
}

impl<T> Future for Receiver<T> {
    type Output = Result<T, Canceled>;

    fn poll(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<T, Canceled>> {
        self.inner.recv(cx)
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        self.inner.drop_rx()
    }
}
<|endoftext|>


<commit_before>extern crate gcc;
#[cfg(feature = "bindgen")]
extern crate libbindgen;

#[cfg(not(feature = "bindgen"))]
use std::fs;
use std::env;
use std::path::Path;

#[cfg(feature = "bindgen")]
fn generate_binding(out_file: &Path) {
    let _ = libbindgen::builder()
        .clang_arg("-xc++")
        .clang_arg("--std=c++11")
        .clang_arg(if cfg!(feature = "sse42") {
            "-msse4.2"
        } else {
            "-march=native"
        })
        .header("src/fasthash.hpp")
        .no_unstable_rust()
        .disable_name_namespacing()
        .hide_type(".*PCCP.*")
        .whitelisted_function("^CityHash.*")
        .whitelisted_function("^farmhash.*")
        .whitelisted_function("^lookup3.*")
        .whitelisted_function("^metrohash.*")
        .whitelisted_function("^mum_hash.*")
        .whitelisted_function("^MurmurHash.*")
        .whitelisted_function("^SpookyHasher.*")
        .whitelisted_function("^t1ha.*")
        .whitelisted_function("^XXH.*")
        .link_static("fasthash")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");
}

#[cfg(not(feature = "bindgen"))]
fn generate_binding(out_file: &Path) {
    let suffix = if cfg!(target_os = "macos") {
        "macos"
    } else {
        "linux"
    };

    fs::copy(format!("src/fasthash_{}.rs", suffix), out_file).expect("fail to copy bindings");
}

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    generate_binding(&out_file);

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
}
<commit_msg>force to link gcc on linux<commit_after>extern crate gcc;
#[cfg(feature = "bindgen")]
extern crate libbindgen;

#[cfg(not(feature = "bindgen"))]
use std::fs;
use std::env;
use std::path::Path;

#[cfg(feature = "bindgen")]
fn generate_binding(out_file: &Path) {
    let _ = libbindgen::builder()
        .clang_arg("-xc++")
        .clang_arg("--std=c++11")
        .clang_arg(if cfg!(feature = "sse42") {
            "-msse4.2"
        } else {
            "-march=native"
        })
        .header("src/fasthash.hpp")
        .no_unstable_rust()
        .disable_name_namespacing()
        .hide_type(".*PCCP.*")
        .whitelisted_function("^CityHash.*")
        .whitelisted_function("^farmhash.*")
        .whitelisted_function("^lookup3.*")
        .whitelisted_function("^metrohash.*")
        .whitelisted_function("^mum_hash.*")
        .whitelisted_function("^MurmurHash.*")
        .whitelisted_function("^SpookyHasher.*")
        .whitelisted_function("^t1ha.*")
        .whitelisted_function("^XXH.*")
        .link_static("fasthash")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");
}

#[cfg(not(feature = "bindgen"))]
fn generate_binding(out_file: &Path) {
    let suffix = if cfg!(target_os = "macos") {
        "macos"
    } else {
        "linux"
    };

    fs::copy(format!("src/fasthash_{}.rs", suffix), out_file).expect("fail to copy bindings");
}

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    generate_binding(&out_file);

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
        println!("cargo:rustc-link-lib=dylib=gcc");
    }
}
<|endoftext|>


<commit_before>
//extern mod sqlite;
use core::result;
use core::io;
use core::path;

struct Price {
    date: ~str,
    close: ~str
}

fn load(filename: &str) -> ~[~str] {

    let fres = io::file_reader(~path::Path(filename));
    let f = result::unwrap(fres);

    return f.read_lines();
}

fn parse(lines: ~[~str]) -> ~[Price] {

    let mut date = ~"";
    let mut close = ~"";
    let mut i = 0;
    let mut prices: ~[Price] = ~[];

    for lines.each |&line| {

        i = 0;
        for line.each_split_char(',') |piece| {
            if i == 0 {
                date = piece.to_str();
            } else if i == 4 {
                close = piece.to_str();
            }
            i += 1;

            prices += [Price{date: date.to_str(), close: close.to_str()}]
        }
    }

    return prices;
}

fn main() {

    let lines = load("vt.csv");
    //println(fmt!("%?", lines));

    let prices = parse(lines);
    println(fmt!("%?", prices));

    /*
    let database =
        match sqlite::open("test.db") {
            Ok(db) => db,
            Err(e) => {
                println(fmt!("Error opening test.db: %?", e));
                return;
            }
        };
    let mut r = database.exec("CREATE TABLE gk_test (name text, age int)");
    println(fmt!("Create OK? %?", r.is_ok()));

    r = database.exec("INSERT INTO gk_test VALUES ('Graham', 36)");
    println(fmt!("Insert OK? %?", r.is_ok()));
    */
}
<commit_msg>Prices are getting in the database. Started on max/min<commit_after>
extern mod sqlite;

use core::result;
use core::io;
use core::path;
use core::clone;
use core::to_str;

struct Price {
    date: ~str,
    close: ~str
}

impl clone::Clone for Price {
    fn clone(&self) -> Price {
        Price{date: self.date.clone(), close: self.close.clone()}
    }
}
impl to_str::ToStr for Price {
    fn to_str(&self) -> ~str {
        fmt!("%s: %s", self.date, self.close)
    }
}

fn load(filename: &str) -> ~[~str] {

    let fres = io::file_reader(~path::Path(filename));
    let f = result::unwrap(fres);
    return f.read_lines();
}

fn parse(lines: &[~str]) -> ~[Price] {

    let mut date = ~"";
    let mut close = ~"";
    let mut i = 0;
    let mut prices: ~[Price] = ~[];

    for lines.each |&line| {

        i = 0;
        for line.each_split_char(',') |piece| {
            if i == 0 {
                date = piece.to_str();
            } else if i == 4 {
                close = piece.to_str();
            }
            i += 1;
        }
        prices += [Price{date: date.clone(), close: close.clone()}]
    }

    return prices;
}

struct DB {
    filename: ~str,
    database: sqlite::Database
}

impl DB {

    fn open(name: &str) -> Result<DB, ~str> {

        match sqlite::open(name) {
            // Here 'name' is borrowed. Calling .to_str() makes a new
            // owned string, which the object will hold.
            Ok(db) => Ok(DB{filename: name.to_str(), database: db}),
            Err(e) => {
                println(fmt!("Error opening test.db: %?", e));
                Err(e.to_str())
            }
        }
    }

    fn create(&self) -> Result<sqlite::ResultCode, sqlite::ResultCode>  {
        self.database.exec("CREATE TABLE prices (date text, price real)")
    }

    fn write_price(&self, date: ~str, price: float) {
        let res = self.database.exec(fmt!(
            "INSERT INTO prices VALUES ('%s', %f)", date, price));
        if ! res.is_ok() {
            println(fmt!("INSERT error: %s", res.unwrap_err().to_str()));
        }
    }

    fn max_price(&self) -> ~Price {
        return ~Price{date:~"TODO", close:~"TODO"};
        /*
        let st: sqlite::Cursor = self.database.prepare("SELECT date, price FROM prices ORDER BY price DESC LIMIT 1", &None).unwrap();
        st.step_row();
        let date = st.get_text(0);
        let price = st.get_num(1);
        return ~Price{date:date, close:fmt!("%f", price)}
        */
    }

    fn min_price(&self) -> ~Price {
        return ~Price{date:~"TODO", close:~"TODO"};
    }
}

fn save(prices: ~[Price]) {
    println("Start save");

    let res = DB::open("test.db");
    if ! res.is_ok() {
        return;
    }
    let db = res.unwrap();

    println("Opened");

    match db.create() {
        Err(code) => { println(fmt!("Error creating tables: %s",
                                    code.to_str())); return; }
        _ => {}
    };

    println("Created");

    let mut val: float = 0.0;
    for prices.each |&price| {
        println(price.to_str());

        val = float::from_str(price.close).unwrap();
        db.write_price(price.date.to_str(), val);
    }

}

fn cmd_init() {
    let all_lines: ~[~str] = load("vt.csv");

    // 'tail' because the first line is the column headers, which we
    // don't want.
    let lines: &[~str] = all_lines.tail();

    let prices: ~[Price] = parse(lines);
    println(fmt!("%?", prices));

    save(prices);
}

fn cmd_max() {

    let res = DB::open("test.db");
    if ! res.is_ok() {
        return;
    }
    let db = res.unwrap();

    println(db.max_price().to_str());
}

fn cmd_min() {
    let res = DB::open("test.db");
    if ! res.is_ok() {
        return;
    }
    let db = res.unwrap();

    println(db.min_price().to_str());
}

fn main() {

    static USAGE: &'static str = "Usage: highlow init|max|min";

    let args: &[~str] = os::args();
    if args.len() != 2 {
        println(USAGE);
        return;
    }

    let cmd: ~str = args[1].clone();

    match cmd {
        ~"init" => cmd_init(),
        ~"max" => cmd_max(),
        ~"min" => cmd_min(),
        other => println(fmt!("Invalid cmd: %s", other))
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

extern crate regex;

use std::io::prelude::*;
use std::fs::File;
use std::error::Error;
use std::collections::HashMap;
use regex::Regex;

#[derive(Debug)]
struct Bot {
    low: Option<usize>,
    high: Option<usize>,
    instruction: Option<Instruction>,
}

impl Bot {
    fn new() -> Bot {
        Bot {
            low: None,
            high: None,
            instruction: None,
        }
    }
    fn set_instruction(&mut self, instruction: Instruction) {
        self.instruction = Some(instruction);
    }
    fn take(&mut self, val: usize) {
        if self.low.is_none() {
            self.low = Some(val)
        } else if self.high.is_none() {
            let old_low = self.low.unwrap();
            if old_low < val {
                self.high = Some(val);
            } else {
                self.low = Some(val);
                self.high = Some(old_low);
            }
        }
    }
    fn ready(&self) -> bool {
        self.high.is_some() && self.low.is_some() && self.instruction.is_some()
    }
    fn act(&self) -> (Transfer, Transfer) {
        let low = self.low.expect("Called act on non-ready bot!");
        let high = self.high.expect("Called act on non-ready bot!");
        let instruction = self.instruction.as_ref().expect("Called act on non-ready bot!");
        (Transfer::new(low, instruction.low), Transfer::new(high, instruction.high))
    }
}

#[derive(Debug)]
struct Instruction {
    id: usize,
    low: Destination,
    high: Destination,
}

#[derive(Debug, Clone, Copy)]
enum Destination {
    Bot(usize),
    Output(usize),
}

impl std::fmt::Display for Destination {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            Destination::Bot(id) => write!(f, "bot {}", id),
            Destination::Output(id) => write!(f, "output {}", id),
        }
    }
}

#[derive(Debug)]
struct Transfer {
    value: usize,
    destination: Destination,
}

impl Transfer {
    fn new(value: usize, destination: Destination) -> Transfer {
        Transfer {
            value: value,
            destination: destination,
        }
    }
}

#[derive(Debug)]
struct AssemblyLine {
    bots: HashMap<usize, Bot>,
    output: HashMap<usize, usize>,
}

impl AssemblyLine {
    fn new() -> AssemblyLine {
        AssemblyLine {
            bots: HashMap::new(),
            output: HashMap::new(),
        }
    }
    fn run(&mut self) {
        let mut ready_stack: Vec<_> = self.bots
            .iter()
            .filter(|&(_, bot)| bot.ready())
            .map(|(id, _)| id)
            .cloned()
            .collect();
        while let Some(actor_id) = ready_stack.pop() {
            let (low_transfer, high_transfer) = self.bots
                .get(&actor_id)
                .expect(&format!("Actor {} does not exist", actor_id))
                .act();
            println!("bot {} sends {} to {} and {} to {}",
                     actor_id,
                     low_transfer.value,
                     low_transfer.destination,
                     high_transfer.value,
                     high_transfer.destination);
            for transfer in &[low_transfer, high_transfer] {
                self.transfer(transfer);
                if let Destination::Bot(id) = transfer.destination {
                    if self.bots[&id].ready() {
                        ready_stack.push(id);
                    }
                }
            }
        }
    }
    fn transfer(&mut self, &Transfer { value, ref destination }: &Transfer) {
        match *destination {
            Destination::Output(id) => {
                self.output.insert(id, value);
            }
            Destination::Bot(id) => self.bots.get_mut(&id).unwrap().take(value),
        }
    }
}

impl std::str::FromStr for AssemblyLine {
    type Err = BadInstruction;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        fn read_destination(s: &str) -> Destination {
            let (dest_type, id) = s.split_at(s.find(' ').unwrap());
            if dest_type == "bot" {
                Destination::Bot(id.trim().parse().expect(&format!("Bad id: {}", id)))
            } else {
                Destination::Output(id.trim().parse().expect(&format!("Bad id: {}", id)))
            }
        }
        let destination_re = r"(?:bot|output) \d+";
        let initialize_re = Regex::new(&format!(r"value (?P<val>\d+) goes to (?P<dest>{})",
                                                destination_re))
            .unwrap();
        let instruction_re = Regex::new(&format!(
            r"bot (?P<id>\d+) gives low to (?P<low>{}) and high to (?P<high>{})",
            destination_re, destination_re))
            .unwrap();
        let mut assembly_line = AssemblyLine::new();
        for line in s.lines() {
            if let Some(caps) = initialize_re.captures(line.trim()) {
                let val = caps["val"].parse().unwrap();
                let dest = read_destination(&caps["dest"]);
                match dest {
                    Destination::Bot(id) => {
                        assembly_line.bots.entry(id).or_insert_with(Bot::new).take(val);
                    }
                    Destination::Output(id) => {
                        assembly_line.output.insert(id, val);
                    }
                }
            } else if let Some(caps) = instruction_re.captures(line.trim()) {
                let id = caps["id"].parse().unwrap();
                let low_dest = read_destination(&caps["low"]);
                let high_dest = read_destination(&caps["high"]);
                assembly_line.bots
                    .entry(id)
                    .or_insert_with(Bot::new)
                    .set_instruction(Instruction {
                        id: id,
                        low: low_dest,
                        high: high_dest,
                    });
            } else {
                return Err(BadInstruction { bad_line: line.into() });
            }
        }
        Ok(assembly_line)
    }
}

#[derive(Debug)]
struct BadInstruction {
    bad_line: String,
}

impl std::fmt::Display for BadInstruction {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "Bad line: {}", self.bad_line)
    }
}

impl Error for BadInstruction {
    fn description(&self) -> &str {
        "Invalid line"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 10")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("instructions")
            .index(1)
            .short("f")
            .long("instructions")
            .help("instructions to run. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("instructions");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let mut assembly_line = match input.parse::<AssemblyLine>() {
        Ok(line) => line,
        Err(e) => panic!("Error: {}", e),
    };
    assembly_line.run();
}
<commit_msg>Day 10 part 2<commit_after>#[macro_use]
extern crate clap;

extern crate regex;

use std::io::prelude::*;
use std::fs::File;
use std::error::Error;
use std::collections::BTreeMap;
use regex::Regex;

#[derive(Debug)]
struct Bot {
    low: Option<usize>,
    high: Option<usize>,
    instruction: Option<Instruction>,
}

impl Bot {
    fn new() -> Bot {
        Bot {
            low: None,
            high: None,
            instruction: None,
        }
    }
    fn set_instruction(&mut self, instruction: Instruction) {
        self.instruction = Some(instruction);
    }
    fn take(&mut self, val: usize) {
        if self.low.is_none() {
            self.low = Some(val)
        } else if self.high.is_none() {
            let old_low = self.low.unwrap();
            if old_low < val {
                self.high = Some(val);
            } else {
                self.low = Some(val);
                self.high = Some(old_low);
            }
        }
    }
    fn ready(&self) -> bool {
        self.high.is_some() && self.low.is_some() && self.instruction.is_some()
    }
    fn act(&self) -> (Transfer, Transfer) {
        let low = self.low.expect("Called act on non-ready bot!");
        let high = self.high.expect("Called act on non-ready bot!");
        let instruction = self.instruction.as_ref().expect("Called act on non-ready bot!");
        (Transfer::new(low, instruction.low), Transfer::new(high, instruction.high))
    }
}

#[derive(Debug)]
struct Instruction {
    id: usize,
    low: Destination,
    high: Destination,
}

#[derive(Debug, Clone, Copy)]
enum Destination {
    Bot(usize),
    Output(usize),
}

impl std::fmt::Display for Destination {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            Destination::Bot(id) => write!(f, "bot {}", id),
            Destination::Output(id) => write!(f, "output {}", id),
        }
    }
}

#[derive(Debug)]
struct Transfer {
    value: usize,
    destination: Destination,
}

impl Transfer {
    fn new(value: usize, destination: Destination) -> Transfer {
        Transfer {
            value: value,
            destination: destination,
        }
    }
}

#[derive(Debug)]
struct AssemblyLine {
    bots: BTreeMap<usize, Bot>,
    output: BTreeMap<usize, usize>,
}

impl AssemblyLine {
    fn new() -> AssemblyLine {
        AssemblyLine {
            bots: BTreeMap::new(),
            output: BTreeMap::new(),
        }
    }
    fn run(&mut self) {
        let mut ready_stack: Vec<_> = self.bots
            .iter()
            .filter(|&(_, bot)| bot.ready())
            .map(|(id, _)| id)
            .cloned()
            .collect();
        while let Some(actor_id) = ready_stack.pop() {
            let (low_transfer, high_transfer) = self.bots
                .get(&actor_id)
                .expect(&format!("Actor {} does not exist", actor_id))
                .act();
            println!("bot {} sends {} to {} and {} to {}",
                     actor_id,
                     low_transfer.value,
                     low_transfer.destination,
                     high_transfer.value,
                     high_transfer.destination);
            for transfer in &[low_transfer, high_transfer] {
                self.transfer(transfer);
                if let Destination::Bot(id) = transfer.destination {
                    if self.bots[&id].ready() {
                        ready_stack.push(id);
                    }
                }
            }
        }
        println!("Outputs:");
        for (id, val) in &self.output {
            println!("    {}: {}", id, val);
        }
    }
    fn transfer(&mut self, &Transfer { value, ref destination }: &Transfer) {
        match *destination {
            Destination::Output(id) => {
                self.output.insert(id, value);
            }
            Destination::Bot(id) => self.bots.get_mut(&id).unwrap().take(value),
        }
    }
}

impl std::str::FromStr for AssemblyLine {
    type Err = BadInstruction;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        fn read_destination(s: &str) -> Destination {
            let (dest_type, id) = s.split_at(s.find(' ').unwrap());
            if dest_type == "bot" {
                Destination::Bot(id.trim().parse().expect(&format!("Bad id: {}", id)))
            } else {
                Destination::Output(id.trim().parse().expect(&format!("Bad id: {}", id)))
            }
        }
        let destination_re = r"(?:bot|output) \d+";
        let initialize_re = Regex::new(&format!(r"value (?P<val>\d+) goes to (?P<dest>{})",
                                                destination_re))
            .unwrap();
        let instruction_re = Regex::new(&format!(
            r"bot (?P<id>\d+) gives low to (?P<low>{}) and high to (?P<high>{})",
            destination_re, destination_re))
            .unwrap();
        let mut assembly_line = AssemblyLine::new();
        for line in s.lines() {
            if let Some(caps) = initialize_re.captures(line.trim()) {
                let val = caps["val"].parse().unwrap();
                let dest = read_destination(&caps["dest"]);
                match dest {
                    Destination::Bot(id) => {
                        assembly_line.bots.entry(id).or_insert_with(Bot::new).take(val);
                    }
                    Destination::Output(id) => {
                        assembly_line.output.insert(id, val);
                    }
                }
            } else if let Some(caps) = instruction_re.captures(line.trim()) {
                let id = caps["id"].parse().unwrap();
                let low_dest = read_destination(&caps["low"]);
                let high_dest = read_destination(&caps["high"]);
                assembly_line.bots
                    .entry(id)
                    .or_insert_with(Bot::new)
                    .set_instruction(Instruction {
                        id: id,
                        low: low_dest,
                        high: high_dest,
                    });
            } else {
                return Err(BadInstruction { bad_line: line.into() });
            }
        }
        Ok(assembly_line)
    }
}

#[derive(Debug)]
struct BadInstruction {
    bad_line: String,
}

impl std::fmt::Display for BadInstruction {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "Bad line: {}", self.bad_line)
    }
}

impl Error for BadInstruction {
    fn description(&self) -> &str {
        "Invalid line"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 10")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("instructions")
            .index(1)
            .short("f")
            .long("instructions")
            .help("instructions to run. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("instructions");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let mut assembly_line = match input.parse::<AssemblyLine>() {
        Ok(line) => line,
        Err(e) => panic!("Error: {}", e),
    };
    assembly_line.run();
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate rustc_serialize;

use rosxmlrpc;
use self::rustc_serialize::Encodable;
use std;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::sync::Mutex;
use std::error::Error as ErrorTrait;
use self::libc::getpid;

pub struct Slave {
    server: rosxmlrpc::Server,
    req: Mutex<Receiver<(String, rosxmlrpc::serde::Decoder)>>,
    res: Mutex<Sender<Vec<u8>>>,
    subscriptions: Vec<(String, String)>,
    publications: Vec<(String, String)>,
}

struct SlaveHandler {
    req: Mutex<Sender<(String, rosxmlrpc::serde::Decoder)>>,
    res: Mutex<Receiver<Vec<u8>>>,
}

type SerdeResult<T> = Result<T, Error>;

impl Slave {
    pub fn new(server_uri: &str) -> Result<Slave, Error> {
        let (tx_req, rx_req) = mpsc::channel();
        let (tx_res, rx_res) = mpsc::channel();
        let server = try!(rosxmlrpc::Server::new(server_uri,
                                                 SlaveHandler {
                                                     req: Mutex::new(tx_req),
                                                     res: Mutex::new(rx_res),
                                                 }));
        Ok(Slave {
            server: server,
            subscriptions: vec![],
            publications: vec![],
            req: Mutex::new(rx_req),
            res: Mutex::new(tx_res),
        })
    }

    pub fn uri(&self) -> &str {
        return &self.server.uri;
    }

    fn encode_response<T: Encodable>(&self, response: SerdeResult<T>, message: &str) {
        let mut body = Vec::<u8>::new();
        {
            let mut res = rosxmlrpc::serde::Encoder::new(&mut body);
            res.start_response().unwrap();
            match response {
                    Ok(value) => (1i32, message, value).encode(&mut res),
                    Err(err) => (-1i32, err.description(), 0).encode(&mut res),
                }
                .unwrap();
            res.end_response().unwrap();
        }
        self.res.lock().unwrap().send(body).unwrap();
    }

    fn param_update(&self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        let key = try!(req.decode_request_parameter::<String>());
        let value = try!(req.decode_request_parameter::<String>());
        if caller_id != "" && key != "" && value != "" {
            println!("{} {} {}", caller_id, key, value);
            Ok(0)
        } else {
            Err(Error::Protocol("Emtpy strings given".to_owned()))
        }
    }

    fn get_pid(&self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(unsafe { getpid() })
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn shutdown(&mut self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            self.server.shutdown().unwrap();
            Ok(0)
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn get_publications(&self,
                        req: &mut rosxmlrpc::serde::Decoder)
                        -> SerdeResult<&[(String, String)]> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(&self.publications)
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn get_subscriptions(&self,
                         req: &mut rosxmlrpc::serde::Decoder)
                         -> SerdeResult<&[(String, String)]> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(&self.subscriptions)
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn handle_call(&mut self, method_name: &str, req: &mut rosxmlrpc::serde::Decoder) {
        println!("HANDLING METHOD: {}", method_name);
        match method_name {
            "getBusStats" => unimplemented!(),
            "getBusInfo" => unimplemented!(),
            "getMasterUri" => unimplemented!(),
            "shutdown" => {
                let data = self.shutdown(req);
                self.encode_response(data, "Shutdown");
            }
            "getPid" => {
                self.encode_response(self.get_pid(req), "PID");
            }
            "getSubscriptions" => {
                self.encode_response(self.get_subscriptions(req), "List of subscriptions");
            }
            "getPublications" => {
                self.encode_response(self.get_publications(req), "List of publications");
            }
            "paramUpdate" => {
                self.encode_response(self.param_update(req), "Parameter updated");
            }
            "publisherUpdate" => unimplemented!(),
            "requestTopic" => unimplemented!(),
            _ => {}
        }
    }

    pub fn handle_calls(&mut self) {
        loop {
            let recv = self.req.lock().unwrap().recv();
            match recv {
                Err(_) => return,
                Ok((method_name, mut req)) => self.handle_call(&method_name, &mut req),
            }
        }
    }

    pub fn handle_call_queue(&mut self) -> mpsc::TryRecvError {
        loop {
            let recv = self.req.lock().unwrap().try_recv();
            match recv {
                Err(err) => return err,
                Ok((method_name, mut req)) => self.handle_call(&method_name, &mut req),
            }
        }
    }
}

impl rosxmlrpc::server::XmlRpcServer for SlaveHandler {
    fn handle(&self, method_name: &str, _: usize, req: rosxmlrpc::serde::Decoder) -> Vec<u8> {
        println!("CALLED METHOD: {}", method_name);
        self.req.lock().unwrap().send((method_name.to_owned(), req)).unwrap();
        self.res.lock().unwrap().recv().unwrap()
    }
}

#[derive(Debug)]
pub enum Error {
    Deserialization(rosxmlrpc::serde::decoder::Error),
    Protocol(String),
    Serialization(rosxmlrpc::serde::encoder::Error),
    XmlRpc(rosxmlrpc::error::Error),
}

impl From<rosxmlrpc::serde::decoder::Error> for Error {
    fn from(err: rosxmlrpc::serde::decoder::Error) -> Error {
        Error::Deserialization(err)
    }
}

impl From<rosxmlrpc::serde::encoder::Error> for Error {
    fn from(err: rosxmlrpc::serde::encoder::Error) -> Error {
        Error::Serialization(err)
    }
}

impl From<rosxmlrpc::error::Error> for Error {
    fn from(err: rosxmlrpc::error::Error) -> Error {
        Error::XmlRpc(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Deserialization(ref err) => write!(f, "Deserialization error: {}", err),
            Error::Protocol(ref err) => write!(f, "Protocol error: {}", err),
            Error::Serialization(ref err) => write!(f, "Serialization error: {}", err),
            Error::XmlRpc(ref err) => write!(f, "XML RPC error: {}", err),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Deserialization(ref err) => err.description(),
            Error::Protocol(ref err) => &err,
            Error::Serialization(ref err) => err.description(),
            Error::XmlRpc(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Deserialization(ref err) => Some(err),
            Error::Protocol(..) => None,
            Error::Serialization(ref err) => Some(err),
            Error::XmlRpc(ref err) => Some(err),
        }
    }
}
<commit_msg>Handle errors that can be handled<commit_after>extern crate libc;
extern crate rustc_serialize;

use rosxmlrpc;
use self::rustc_serialize::Encodable;
use std;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::sync::Mutex;
use std::error::Error as ErrorTrait;
use self::libc::getpid;

pub struct Slave {
    server: rosxmlrpc::Server,
    req: Mutex<Receiver<(String, rosxmlrpc::serde::Decoder)>>,
    res: Mutex<Sender<Vec<u8>>>,
    subscriptions: Vec<(String, String)>,
    publications: Vec<(String, String)>,
}

struct SlaveHandler {
    req: Mutex<Sender<(String, rosxmlrpc::serde::Decoder)>>,
    res: Mutex<Receiver<Vec<u8>>>,
}

type SerdeResult<T> = Result<T, Error>;

impl Slave {
    pub fn new(server_uri: &str) -> Result<Slave, Error> {
        let (tx_req, rx_req) = mpsc::channel();
        let (tx_res, rx_res) = mpsc::channel();
        let server = try!(rosxmlrpc::Server::new(server_uri,
                                                 SlaveHandler {
                                                     req: Mutex::new(tx_req),
                                                     res: Mutex::new(rx_res),
                                                 }));
        Ok(Slave {
            server: server,
            subscriptions: vec![],
            publications: vec![],
            req: Mutex::new(rx_req),
            res: Mutex::new(tx_res),
        })
    }

    pub fn uri(&self) -> &str {
        return &self.server.uri;
    }

    fn encode_response<T: Encodable>(&self,
                                     response: SerdeResult<T>,
                                     message: &str)
                                     -> SerdeResult<()> {
        let mut body = Vec::<u8>::new();
        {
            let mut res = rosxmlrpc::serde::Encoder::new(&mut body);
            try!(res.start_response());
            try!(match response {
                Ok(value) => (1i32, message, value).encode(&mut res),
                Err(err) => (-1i32, err.description(), 0).encode(&mut res),
            });
            try!(res.end_response());
        }
        self.res.lock().unwrap().send(body).unwrap();
        Ok(())
    }

    fn param_update(&self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        let key = try!(req.decode_request_parameter::<String>());
        let value = try!(req.decode_request_parameter::<String>());
        if caller_id != "" && key != "" && value != "" {
            println!("{} {} {}", caller_id, key, value);
            Ok(0)
        } else {
            Err(Error::Protocol("Emtpy strings given".to_owned()))
        }
    }

    fn get_pid(&self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(unsafe { getpid() })
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn shutdown(&mut self, req: &mut rosxmlrpc::serde::Decoder) -> SerdeResult<i32> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            match self.server.shutdown() {
                Ok(()) => Ok(0),
                Err(_) => Err(Error::Critical("Failed to shutdown server".to_owned())),
            }
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn get_publications(&self,
                        req: &mut rosxmlrpc::serde::Decoder)
                        -> SerdeResult<&[(String, String)]> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(&self.publications)
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn get_subscriptions(&self,
                         req: &mut rosxmlrpc::serde::Decoder)
                         -> SerdeResult<&[(String, String)]> {
        let caller_id = try!(req.decode_request_parameter::<String>());
        if caller_id != "" {
            Ok(&self.subscriptions)
        } else {
            Err(Error::Protocol("Empty strings given".to_owned()))
        }
    }

    fn handle_call(&mut self,
                   method_name: &str,
                   req: &mut rosxmlrpc::serde::Decoder)
                   -> SerdeResult<()> {
        println!("HANDLING METHOD: {}", method_name);
        match method_name {
            "getBusStats" => unimplemented!(),
            "getBusInfo" => unimplemented!(),
            "getMasterUri" => unimplemented!(),
            "shutdown" => {
                let data = self.shutdown(req);
                self.encode_response(data, "Shutdown")
            }
            "getPid" => self.encode_response(self.get_pid(req), "PID"),
            "getSubscriptions" => {
                self.encode_response(self.get_subscriptions(req), "List of subscriptions")
            }
            "getPublications" => {
                self.encode_response(self.get_publications(req), "List of publications")
            }
            "paramUpdate" => self.encode_response(self.param_update(req), "Parameter updated"),
            "publisherUpdate" => unimplemented!(),
            "requestTopic" => unimplemented!(),
            name => {
                self.encode_response::<i32>(Err(Error::Protocol(format!("Unimplemented method: \
                                                                         {}",
                                                                        name))),
                                            "")
            }
        }
    }

    pub fn handle_calls(&mut self) -> Result<(), String> {
        loop {
            let recv = self.req.lock().unwrap().recv();
            match recv {
                Err(_) => return Ok(()),
                Ok((method_name, mut req)) => {
                    if let Err(err) = self.handle_call(&method_name, &mut req) {
                        match err {
                            Error::Critical(msg) => {
                                return Err(msg);
                            }
                            _ => {
                                println!("{}", err);
                            }
                        }
                    }
                }
            }
        }
    }

    pub fn handle_call_queue(&mut self) -> Result<mpsc::TryRecvError, Error> {
        loop {
            let recv = self.req.lock().unwrap().try_recv();
            match recv {
                Err(err) => return Ok(err),
                Ok((method_name, mut req)) => try!(self.handle_call(&method_name, &mut req)),
            }
        }
    }
}

impl rosxmlrpc::server::XmlRpcServer for SlaveHandler {
    fn handle(&self, method_name: &str, _: usize, req: rosxmlrpc::serde::Decoder) -> Vec<u8> {
        println!("CALLED METHOD: {}", method_name);
        self.req.lock().unwrap().send((method_name.to_owned(), req)).unwrap();
        self.res.lock().unwrap().recv().unwrap()
    }
}

#[derive(Debug)]
pub enum Error {
    Deserialization(rosxmlrpc::serde::decoder::Error),
    Protocol(String),
    Critical(String),
    Serialization(rosxmlrpc::serde::encoder::Error),
    XmlRpc(rosxmlrpc::error::Error),
}

impl From<rosxmlrpc::serde::decoder::Error> for Error {
    fn from(err: rosxmlrpc::serde::decoder::Error) -> Error {
        Error::Deserialization(err)
    }
}

impl From<rosxmlrpc::serde::encoder::Error> for Error {
    fn from(err: rosxmlrpc::serde::encoder::Error) -> Error {
        Error::Serialization(err)
    }
}

impl From<rosxmlrpc::error::Error> for Error {
    fn from(err: rosxmlrpc::error::Error) -> Error {
        Error::XmlRpc(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Deserialization(ref err) => write!(f, "Deserialization error: {}", err),
            Error::Protocol(ref err) => write!(f, "Protocol error: {}", err),
            Error::Critical(ref err) => write!(f, "Critical error: {}", err),
            Error::Serialization(ref err) => write!(f, "Serialization error: {}", err),
            Error::XmlRpc(ref err) => write!(f, "XML RPC error: {}", err),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Deserialization(ref err) => err.description(),
            Error::Protocol(ref err) => &err,
            Error::Critical(ref err) => &err,
            Error::Serialization(ref err) => err.description(),
            Error::XmlRpc(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Deserialization(ref err) => Some(err),
            Error::Protocol(..) => None,
            Error::Critical(..) => None,
            Error::Serialization(ref err) => Some(err),
            Error::XmlRpc(ref err) => Some(err),
        }
    }
}
<|endoftext|>


<commit_before>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn add_transition(&mut self, id0: int, c: char, id1: int)
	{
		self.states[id0].add_transition(c, id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}
	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t, id) = (self.states[curr[i]].transitions[j]).clone();
					if t == c
					{
						next.push(id);
					}
					else if t == '%'
					{
						curr.push(id);
						l += 1;
					}
				}
				i += 1;
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else // the NFA has eaten all of the characters
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t , id) = (self.states[curr[i]].transitions[j]).clone();
					if t == '%'
					{
						next.push(id);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone, Eq)]
struct State
{
	accept: bool,
	transitions: ~[(char, int)]
}

impl State
{
	pub fn new(b: bool)	->	State
	{
		State { accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("matching=%? transitions={", self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, c: char, id: int )
	{
		self.transitions.push((c, id));
	}
}

fn generate(lang: &[char], len: uint)	->	~[~str]
{
	let mut set = ~[];
	if len == 0 { return ~[~""]; }
	if len == 1
	{
		for i in range(0, lang.len())
		{
			set.push(lang[i].to_str());
		}
		return set;
	}
	for i in range(0, lang.len())
	{
		let s = generate(lang, len-1);
		for j in range(0, s.len())
		{
			set.push(lang[i].to_str() + s[j].clone());
		}
	}
	return set;
}

fn main()
{
	let test = std::os::args()[1];
	let lang = ['a', 'b'];
	let len = 4u;
	let mut strings = ~[];
	for i in range(0, len+1)
	{
		let s = generate(lang, i);
		for j in range(0,s.len())
		{
			strings.push(s[j].clone());
		}
	}
	let mut nfa = NFA::new();
	let mut parenthesis: ~[int] = ~[];
	let mut j = -1;
	let mut escaped = false;
	let mut special = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		if c == '\\'
		{
			escaped = true;
		}
		else if c == '(' && !escaped
		{
			parenthesis.push(j+1);
		}
		else if c == ')' && !escaped
		{
			special = true;
		}
		else if c == '*' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			// link curr to place
			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, place);
				}
			}

			// add epsilon transition to skip this state
			nfa.add_transition(place, '%', j+1);

		}
		else if c == '+' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, place);
				}
			}
		}
		else if c == '?' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			// add epsilon transition
			nfa.add_transition(place, '%', j+1);
		}
		else if c == '.' && !escaped
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// unconditional jump
			for i in range(0, lang.len())
			{
				nfa.add_transition(j, lang[i], j+1);
			}
		}
		else
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// link with next
			nfa.add_transition(j, c, j+1);
			escaped = false;
		}

		nfa.print();
	}
	// make the last state true
	let state = State::new(true);
	nfa.add_state(state);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}

}
<commit_msg>fixed bug with parenthesis<commit_after>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn add_transition(&mut self, id0: int, c: char, id1: int)
	{
		self.states[id0].add_transition(c, id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}
	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t, id) = (self.states[curr[i]].transitions[j]).clone();
					if t == c
					{
						next.push(id);
					}
					else if t == '%'
					{
						curr.push(id);
						l += 1;
					}
				}
				i += 1;
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else // the NFA has eaten all of the characters
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t , id) = (self.states[curr[i]].transitions[j]).clone();
					if t == '%'
					{
						next.push(id);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone, Eq)]
struct State
{
	accept: bool,
	transitions: ~[(char, int)]
}

impl State
{
	pub fn new(b: bool)	->	State
	{
		State { accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("matching=%? transitions={", self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, c: char, id: int )
	{
		self.transitions.push((c, id));
	}
}

fn generate(lang: &[char], len: uint)	->	~[~str]
{
	let mut set = ~[];
	if len == 0 { return ~[~""]; }
	if len == 1
	{
		for i in range(0, lang.len())
		{
			set.push(lang[i].to_str());
		}
		return set;
	}
	for i in range(0, lang.len())
	{
		let s = generate(lang, len-1);
		for j in range(0, s.len())
		{
			set.push(lang[i].to_str() + s[j].clone());
		}
	}
	return set;
}

fn main()
{
	let test = std::os::args()[1];
	let lang = ['a', 'b'];
	let len = 4u;
	let mut strings = ~[];
	for i in range(0, len+1)
	{
		let s = generate(lang, i);
		for j in range(0,s.len())
		{
			strings.push(s[j].clone());
		}
	}
	let mut nfa = NFA::new();
	let mut parenthesis: ~[int] = ~[];
	let mut j = -1;
	let mut escaped = false;
	let mut special = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		println(fmt!("on %c", c));
		if c == '\\'
		{
			escaped = true;
			special = false;
		}
		else if c == '(' && !escaped
		{
			parenthesis.push(j+1);
			special = false;
		}
		else if c == ')' && !escaped
		{
			if special { parenthesis.pop(); }
			else { special = true; }
		}
		else if c == '*' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			// link curr to place
			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, place);
				}
			}

			// add epsilon transition to skip this state
			nfa.add_transition(place, '%', j+1);

		}
		else if c == '+' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, place);
				}
			}
		}
		else if c == '?' && !escaped
		{
			let mut place = j;
			if special
			{
				place = parenthesis.pop();
				special = false;
			}

			// add epsilon transition
			nfa.add_transition(place, '%', j+1);
		}
		else if c == '.' && !escaped
		{
			if special
			{
				parenthesis.pop();
				special = false;
			}
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// unconditional jump
			for i in range(0, lang.len())
			{
				nfa.add_transition(j, lang[i], j+1);
			}
		}
		else
		{
			if special
			{
				parenthesis.pop();
				special = false;
			}

			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// link with next
			nfa.add_transition(j, c, j+1);
			escaped = false;
		}

		nfa.print();
	}
	// make the last state true
	let state = State::new(true);
	nfa.add_state(state);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}

}
<|endoftext|>