<commit_before>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](::client) and [Servers](::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - The [`Payload`](Payload) trait the describes all possible bodies. hyper
//!   allows any body type that implements `Payload`, allowing applications to
//!   have fine-grained control over their streaming.
//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`,
//!  and returned by hyper as a "receive stream" (so, for server requests and
//!  client responses). It is also a decent default implementation if you don't
//!  have very custom needs of your send streams.
use std::borrow::Cow;
use std::fmt;

use bytes::{Buf, Bytes};
use futures::{Async, Future, Poll, Stream};
use futures::sync::{mpsc, oneshot};
use h2;
use http::HeaderMap;

use common::Never;
pub use chunk::Chunk;

type BodySender = mpsc::Sender<Result<Chunk, ::Error>>;

/// This trait represents a streaming body of a `Request` or `Response`.
///
/// The built-in implementation of this trait is [`Body`](Body), in case you
/// don't need to customize a send stream for your own application.
pub trait Payload: Send + 'static {
    /// A buffer of bytes representing a single chunk of a body.
    type Data: Buf + Send;

    /// The error type of this stream.
    type Error: Into<Box<::std::error::Error + Send + Sync>>;

    /// Poll for a `Data` buffer.
    ///
    /// Similar to `Stream::poll_next`, this yields `Some(Data)` until
    /// the body ends, when it yields `None`.
    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>;

    /// Poll for an optional **single** `HeaderMap` of trailers.
    ///
    /// This should **only** be called after `poll_data` has ended.
    ///
    /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2.
    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        Ok(Async::Ready(None))
    }

    /// A hint that the `Body` is complete, and doesn't need to be polled more.
    ///
    /// This can be useful to determine if the there is any body or trailers
    /// without having to poll. An empty `Body` could return `true` and hyper
    /// would be able to know that only the headers need to be sent. Or, it can
    /// also be checked after each `poll_data` call, to allow hyper to try to
    /// end the underlying stream with the last chunk, instead of needing to
    /// send an extra `DATA` frame just to mark the stream as finished.
    ///
    /// As a hint, it is used to try to optimize, and thus is OK for a default
    /// implementation to return `false`.
    fn is_end_stream(&self) -> bool {
        false
    }

    /// Return a length of the total bytes that will be streamed, if known.
    ///
    /// If an exact size of bytes is known, this would allow hyper to send a
    /// `Content-Length` header automatically, not needing to fall back to
    /// `Transfer-Encoding: chunked`.
    ///
    /// This does not need to be kept updated after polls, it will only be
    /// called once to create the headers.
    fn content_length(&self) -> Option<u64> {
        None
    }
}

impl<E: Payload> Payload for Box<E> {
    type Data = E::Data;
    type Error = E::Error;

    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
        (**self).poll_data()
    }

    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        (**self).poll_trailers()
    }

    fn is_end_stream(&self) -> bool {
        (**self).is_end_stream()
    }

    fn content_length(&self) -> Option<u64> {
        (**self).content_length()
    }
}

/// A stream of `Chunk`s, used when receiving bodies.
///
/// A good default `Payload` to use in many applications.
///
/// Also implements `futures::Stream`, so stream combinators may be used.
#[must_use = "streams do nothing unless polled"]
pub struct Body {
    kind: Kind,
    /// Allow the client to pass a future to delay the `Body` from returning
    /// EOF. This allows the `Client` to try to put the idle connection
    /// back into the pool before the body is "finished".
    ///
    /// The reason for this is so that creating a new request after finishing
    /// streaming the body of a response could sometimes result in creating
    /// a brand new connection, since the pool didn't know about the idle
    /// connection yet.
    delayed_eof: Option<DelayEof>,
}

enum Kind {
    Chan {
        _close_tx: oneshot::Sender<()>,
        rx: mpsc::Receiver<Result<Chunk, ::Error>>,
    },
    H2(h2::RecvStream),
    Wrapped(Box<Stream<Item=Chunk, Error=Box<::std::error::Error + Send + Sync>> + Send>),
    Once(Option<Chunk>),
    Empty,
}

type DelayEofUntil = oneshot::Receiver<Never>;

enum DelayEof {
    /// Initial state, stream hasn't seen EOF yet.
    NotEof(DelayEofUntil),
    /// Transitions to this state once we've seen `poll` try to
    /// return EOF (`None`). This future is then polled, and
    /// when it completes, the Body finally returns EOF (`None`).
    Eof(DelayEofUntil),
}

/// A sender half used with `Body::channel()`.
///
/// Useful when wanting to stream chunks from another thread. See
/// [`Body::channel`](Body::channel) for more.
#[must_use = "Sender does nothing unless sent on"]
#[derive(Debug)]
pub struct Sender {
    close_rx: oneshot::Receiver<()>,
    tx: BodySender,
}

impl Body {
    /// Create an empty `Body` stream.
    ///
    /// # Example
    ///
    /// ```
    /// use hyper::{Body, Request};
    ///
    /// // create a `GET /` request
    /// let get = Request::new(Body::empty());
    /// ```
    #[inline]
    pub fn empty() -> Body {
        Body::new(Kind::Empty)
    }

    /// Create a `Body` stream with an associated sender half.
    ///
    /// Useful when wanting to stream chunks from another thread.
    #[inline]
    pub fn channel() -> (Sender, Body) {
        let (tx, rx) = mpsc::channel(0);
        let (close_tx, close_rx) = oneshot::channel();

        let tx = Sender {
            close_rx: close_rx,
            tx: tx,
        };
        let rx = Body::new(Kind::Chan {
            _close_tx: close_tx,
            rx: rx,
        });

        (tx, rx)
    }

    /// Wrap a futures `Stream` in a box inside `Body`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate hyper;
    /// # use hyper::Body;
    /// # fn main() {
    /// let chunks = vec![
    ///     "hello",
    ///     " ",
    ///     "world",
    /// ];
    ///
    /// let stream = futures::stream::iter_ok::<_, ::std::io::Error>(chunks);
    ///
    /// let body = Body::wrap_stream(stream);
    /// # }
    /// ```
    pub fn wrap_stream<S>(stream: S) -> Body
    where
        S: Stream + Send + 'static,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        Chunk: From<S::Item>,
    {
        let mapped = stream
            .map(Chunk::from)
            .map_err(Into::into);
        Body::new(Kind::Wrapped(Box::new(mapped)))
    }

    fn new(kind: Kind) -> Body {
        Body {
            kind: kind,
            delayed_eof: None,
        }
    }

    pub(crate) fn h2(recv: h2::RecvStream) -> Self {
        Body::new(Kind::H2(recv))
    }

    pub(crate) fn delayed_eof(&mut self, fut: DelayEofUntil) {
        self.delayed_eof = Some(DelayEof::NotEof(fut));
    }

    fn poll_eof(&mut self) -> Poll<Option<Chunk>, ::Error> {
        match self.delayed_eof.take() {
            Some(DelayEof::NotEof(mut delay)) => {
                match self.poll_inner() {
                    ok @ Ok(Async::Ready(Some(..))) |
                    ok @ Ok(Async::NotReady) => {
                        self.delayed_eof = Some(DelayEof::NotEof(delay));
                        ok
                    },
                    Ok(Async::Ready(None)) => match delay.poll() {
                        Ok(Async::Ready(never)) => match never {},
                        Ok(Async::NotReady) => {
                            self.delayed_eof = Some(DelayEof::Eof(delay));
                            Ok(Async::NotReady)
                        },
                        Err(_done) => {
                            Ok(Async::Ready(None))
                        },
                    },
                    Err(e) => Err(e),
                }
            },
            Some(DelayEof::Eof(mut delay)) => {
                match delay.poll() {
                    Ok(Async::Ready(never)) => match never {},
                    Ok(Async::NotReady) => {
                        self.delayed_eof = Some(DelayEof::Eof(delay));
                        Ok(Async::NotReady)
                    },
                    Err(_done) => {
                        Ok(Async::Ready(None))
                    },
                }
            },
            None => self.poll_inner(),
        }
    }

    fn poll_inner(&mut self) -> Poll<Option<Chunk>, ::Error> {
        match self.kind {
            Kind::Chan { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") {
                Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))),
                Async::Ready(Some(Err(err))) => Err(err),
                Async::Ready(None) => Ok(Async::Ready(None)),
                Async::NotReady => Ok(Async::NotReady),
            },
            Kind::H2(ref mut h2) => {
                h2.poll()
                    .map(|async| {
                        async.map(|opt| {
                            opt.map(|bytes| {
                                Chunk::h2(bytes, h2.release_capacity())
                            })
                        })
                    })
                    .map_err(::Error::new_body)
            },
            Kind::Wrapped(ref mut s) => s.poll().map_err(::Error::new_body),
            Kind::Once(ref mut val) => Ok(Async::Ready(val.take())),
            Kind::Empty => Ok(Async::Ready(None)),
        }
    }
}

impl Default for Body {
    /// Returns [`Body::empty()`](Body::empty).
    #[inline]
    fn default() -> Body {
        Body::empty()
    }
}

impl Payload for Body {
    type Data = Chunk;
    type Error = ::Error;

    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
        self.poll_eof()
    }

    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        match self.kind {
            Kind::H2(ref mut h2) => h2.poll_trailers().map_err(::Error::new_h2),
            _ => Ok(Async::Ready(None)),
        }
    }

    fn is_end_stream(&self) -> bool {
        match self.kind {
            Kind::Chan { .. } => false,
            Kind::H2(ref h2) => h2.is_end_stream(),
            Kind::Wrapped(..) => false,
            Kind::Once(ref val) => val.is_none(),
            Kind::Empty => true
        }
    }

    fn content_length(&self) -> Option<u64> {
        match self.kind {
            Kind::Chan { .. } => None,
            Kind::H2(..) => None,
            Kind::Wrapped(..) => None,
            Kind::Once(Some(ref val)) => Some(val.len() as u64),
            Kind::Once(None) => None,
            Kind::Empty => Some(0)
        }
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.poll_data()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body")
            .finish()
    }
}

impl Sender {
    /// Check to see if this `Sender` can send more data.
    pub fn poll_ready(&mut self) -> Poll<(), ::Error> {
        match self.close_rx.poll() {
            Ok(Async::Ready(())) | Err(_) => return Err(::Error::new_closed()),
            Ok(Async::NotReady) => (),
        }

        self.tx.poll_ready().map_err(|_| ::Error::new_closed())
    }

    /// Sends data on this channel.
    ///
    /// This should be called after `poll_ready` indicated the channel
    /// could accept another `Chunk`.
    ///
    /// Returns `Err(Chunk)` if the channel could not (currently) accept
    /// another `Chunk`.
    pub fn send_data(&mut self, chunk: Chunk) -> Result<(), Chunk> {
        self.tx.try_send(Ok(chunk))
            .map_err(|err| err.into_inner().expect("just sent Ok"))
    }

    pub(crate) fn send_error(&mut self, err: ::Error) {
        let _ = self.tx.try_send(Err(err));
    }
}

impl From<Chunk> for Body {
    #[inline]
    fn from(chunk: Chunk) -> Body {
        if chunk.is_empty() {
            Body::empty()
        } else {
            Body::new(Kind::Once(Some(chunk)))
        }
    }
}

impl
    From<Box<Stream<Item = Chunk, Error = Box<::std::error::Error + Send + Sync>> + Send + 'static>>
    for Body
{
    #[inline]
    fn from(
        stream: Box<
            Stream<Item = Chunk, Error = Box<::std::error::Error + Send + Sync>> + Send + 'static,
        >,
    ) -> Body {
        Body::new(Kind::Wrapped(stream))
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from (bytes: Bytes) -> Body {
        Body::from(Chunk::from(bytes))
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from (vec: Vec<u8>) -> Body {
        Body::from(Chunk::from(vec))
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from (slice: &'static [u8]) -> Body {
        Body::from(Chunk::from(slice))
    }
}

impl From<Cow<'static, [u8]>> for Body {
    #[inline]
    fn from (cow: Cow<'static, [u8]>) -> Body {
        match cow {
            Cow::Borrowed(b) => Body::from(b),
            Cow::Owned(o) => Body::from(o)
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from (s: String) -> Body {
        Body::from(Chunk::from(s.into_bytes()))
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(slice: &'static str) -> Body {
        Body::from(Chunk::from(slice.as_bytes()))
    }
}

impl From<Cow<'static, str>> for Body {
    #[inline]
    fn from(cow: Cow<'static, str>) -> Body {
        match cow {
            Cow::Borrowed(b) => Body::from(b),
            Cow::Owned(o) => Body::from(o)
        }
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

#[test]
fn test_body_stream_concat() {
    use futures::{Stream, Future};

    let body = Body::from("hello world");

    let total = body
        .concat2()
        .wait()
        .unwrap();
    assert_eq!(total.as_ref(), b"hello world");
}

<commit_msg>refactor(body): combine Empty and Once variants for Body<commit_after>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](::client) and [Servers](::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - The [`Payload`](Payload) trait the describes all possible bodies. hyper
//!   allows any body type that implements `Payload`, allowing applications to
//!   have fine-grained control over their streaming.
//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`,
//!  and returned by hyper as a "receive stream" (so, for server requests and
//!  client responses). It is also a decent default implementation if you don't
//!  have very custom needs of your send streams.
use std::borrow::Cow;
use std::fmt;

use bytes::{Buf, Bytes};
use futures::{Async, Future, Poll, Stream};
use futures::sync::{mpsc, oneshot};
use h2;
use http::HeaderMap;

use common::Never;
pub use chunk::Chunk;

type BodySender = mpsc::Sender<Result<Chunk, ::Error>>;

/// This trait represents a streaming body of a `Request` or `Response`.
///
/// The built-in implementation of this trait is [`Body`](Body), in case you
/// don't need to customize a send stream for your own application.
pub trait Payload: Send + 'static {
    /// A buffer of bytes representing a single chunk of a body.
    type Data: Buf + Send;

    /// The error type of this stream.
    type Error: Into<Box<::std::error::Error + Send + Sync>>;

    /// Poll for a `Data` buffer.
    ///
    /// Similar to `Stream::poll_next`, this yields `Some(Data)` until
    /// the body ends, when it yields `None`.
    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>;

    /// Poll for an optional **single** `HeaderMap` of trailers.
    ///
    /// This should **only** be called after `poll_data` has ended.
    ///
    /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2.
    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        Ok(Async::Ready(None))
    }

    /// A hint that the `Body` is complete, and doesn't need to be polled more.
    ///
    /// This can be useful to determine if the there is any body or trailers
    /// without having to poll. An empty `Body` could return `true` and hyper
    /// would be able to know that only the headers need to be sent. Or, it can
    /// also be checked after each `poll_data` call, to allow hyper to try to
    /// end the underlying stream with the last chunk, instead of needing to
    /// send an extra `DATA` frame just to mark the stream as finished.
    ///
    /// As a hint, it is used to try to optimize, and thus is OK for a default
    /// implementation to return `false`.
    fn is_end_stream(&self) -> bool {
        false
    }

    /// Return a length of the total bytes that will be streamed, if known.
    ///
    /// If an exact size of bytes is known, this would allow hyper to send a
    /// `Content-Length` header automatically, not needing to fall back to
    /// `Transfer-Encoding: chunked`.
    ///
    /// This does not need to be kept updated after polls, it will only be
    /// called once to create the headers.
    fn content_length(&self) -> Option<u64> {
        None
    }
}

impl<E: Payload> Payload for Box<E> {
    type Data = E::Data;
    type Error = E::Error;

    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
        (**self).poll_data()
    }

    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        (**self).poll_trailers()
    }

    fn is_end_stream(&self) -> bool {
        (**self).is_end_stream()
    }

    fn content_length(&self) -> Option<u64> {
        (**self).content_length()
    }
}

/// A stream of `Chunk`s, used when receiving bodies.
///
/// A good default `Payload` to use in many applications.
///
/// Also implements `futures::Stream`, so stream combinators may be used.
#[must_use = "streams do nothing unless polled"]
pub struct Body {
    kind: Kind,
    /// Allow the client to pass a future to delay the `Body` from returning
    /// EOF. This allows the `Client` to try to put the idle connection
    /// back into the pool before the body is "finished".
    ///
    /// The reason for this is so that creating a new request after finishing
    /// streaming the body of a response could sometimes result in creating
    /// a brand new connection, since the pool didn't know about the idle
    /// connection yet.
    delayed_eof: Option<DelayEof>,
}

enum Kind {
    Once(Option<Chunk>),
    Chan {
        _close_tx: oneshot::Sender<()>,
        rx: mpsc::Receiver<Result<Chunk, ::Error>>,
    },
    H2(h2::RecvStream),
    Wrapped(Box<Stream<Item=Chunk, Error=Box<::std::error::Error + Send + Sync>> + Send>),
}

type DelayEofUntil = oneshot::Receiver<Never>;

enum DelayEof {
    /// Initial state, stream hasn't seen EOF yet.
    NotEof(DelayEofUntil),
    /// Transitions to this state once we've seen `poll` try to
    /// return EOF (`None`). This future is then polled, and
    /// when it completes, the Body finally returns EOF (`None`).
    Eof(DelayEofUntil),
}

/// A sender half used with `Body::channel()`.
///
/// Useful when wanting to stream chunks from another thread. See
/// [`Body::channel`](Body::channel) for more.
#[must_use = "Sender does nothing unless sent on"]
#[derive(Debug)]
pub struct Sender {
    close_rx: oneshot::Receiver<()>,
    tx: BodySender,
}

impl Body {
    /// Create an empty `Body` stream.
    ///
    /// # Example
    ///
    /// ```
    /// use hyper::{Body, Request};
    ///
    /// // create a `GET /` request
    /// let get = Request::new(Body::empty());
    /// ```
    #[inline]
    pub fn empty() -> Body {
        Body::new(Kind::Once(None))
    }

    /// Create a `Body` stream with an associated sender half.
    ///
    /// Useful when wanting to stream chunks from another thread.
    #[inline]
    pub fn channel() -> (Sender, Body) {
        let (tx, rx) = mpsc::channel(0);
        let (close_tx, close_rx) = oneshot::channel();

        let tx = Sender {
            close_rx: close_rx,
            tx: tx,
        };
        let rx = Body::new(Kind::Chan {
            _close_tx: close_tx,
            rx: rx,
        });

        (tx, rx)
    }

    /// Wrap a futures `Stream` in a box inside `Body`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate hyper;
    /// # use hyper::Body;
    /// # fn main() {
    /// let chunks = vec![
    ///     "hello",
    ///     " ",
    ///     "world",
    /// ];
    ///
    /// let stream = futures::stream::iter_ok::<_, ::std::io::Error>(chunks);
    ///
    /// let body = Body::wrap_stream(stream);
    /// # }
    /// ```
    pub fn wrap_stream<S>(stream: S) -> Body
    where
        S: Stream + Send + 'static,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        Chunk: From<S::Item>,
    {
        let mapped = stream
            .map(Chunk::from)
            .map_err(Into::into);
        Body::new(Kind::Wrapped(Box::new(mapped)))
    }

    fn new(kind: Kind) -> Body {
        Body {
            kind: kind,
            delayed_eof: None,
        }
    }

    pub(crate) fn h2(recv: h2::RecvStream) -> Self {
        Body::new(Kind::H2(recv))
    }

    pub(crate) fn delayed_eof(&mut self, fut: DelayEofUntil) {
        self.delayed_eof = Some(DelayEof::NotEof(fut));
    }

    fn poll_eof(&mut self) -> Poll<Option<Chunk>, ::Error> {
        match self.delayed_eof.take() {
            Some(DelayEof::NotEof(mut delay)) => {
                match self.poll_inner() {
                    ok @ Ok(Async::Ready(Some(..))) |
                    ok @ Ok(Async::NotReady) => {
                        self.delayed_eof = Some(DelayEof::NotEof(delay));
                        ok
                    },
                    Ok(Async::Ready(None)) => match delay.poll() {
                        Ok(Async::Ready(never)) => match never {},
                        Ok(Async::NotReady) => {
                            self.delayed_eof = Some(DelayEof::Eof(delay));
                            Ok(Async::NotReady)
                        },
                        Err(_done) => {
                            Ok(Async::Ready(None))
                        },
                    },
                    Err(e) => Err(e),
                }
            },
            Some(DelayEof::Eof(mut delay)) => {
                match delay.poll() {
                    Ok(Async::Ready(never)) => match never {},
                    Ok(Async::NotReady) => {
                        self.delayed_eof = Some(DelayEof::Eof(delay));
                        Ok(Async::NotReady)
                    },
                    Err(_done) => {
                        Ok(Async::Ready(None))
                    },
                }
            },
            None => self.poll_inner(),
        }
    }

    fn poll_inner(&mut self) -> Poll<Option<Chunk>, ::Error> {
        match self.kind {
            Kind::Once(ref mut val) => Ok(Async::Ready(val.take())),
            Kind::Chan { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") {
                Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))),
                Async::Ready(Some(Err(err))) => Err(err),
                Async::Ready(None) => Ok(Async::Ready(None)),
                Async::NotReady => Ok(Async::NotReady),
            },
            Kind::H2(ref mut h2) => {
                h2.poll()
                    .map(|async| {
                        async.map(|opt| {
                            opt.map(|bytes| {
                                Chunk::h2(bytes, h2.release_capacity())
                            })
                        })
                    })
                    .map_err(::Error::new_body)
            },
            Kind::Wrapped(ref mut s) => s.poll().map_err(::Error::new_body),
        }
    }
}

impl Default for Body {
    /// Returns [`Body::empty()`](Body::empty).
    #[inline]
    fn default() -> Body {
        Body::empty()
    }
}

impl Payload for Body {
    type Data = Chunk;
    type Error = ::Error;

    fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
        self.poll_eof()
    }

    fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
        match self.kind {
            Kind::H2(ref mut h2) => h2.poll_trailers().map_err(::Error::new_h2),
            _ => Ok(Async::Ready(None)),
        }
    }

    fn is_end_stream(&self) -> bool {
        match self.kind {
            Kind::Once(ref val) => val.is_none(),
            Kind::Chan { .. } => false,
            Kind::H2(ref h2) => h2.is_end_stream(),
            Kind::Wrapped(..) => false,
        }
    }

    fn content_length(&self) -> Option<u64> {
        match self.kind {
            Kind::Once(Some(ref val)) => Some(val.len() as u64),
            Kind::Once(None) => Some(0),
            Kind::Chan { .. } => None,
            Kind::H2(..) => None,
            Kind::Wrapped(..) => None,
        }
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.poll_data()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body")
            .finish()
    }
}

impl Sender {
    /// Check to see if this `Sender` can send more data.
    pub fn poll_ready(&mut self) -> Poll<(), ::Error> {
        match self.close_rx.poll() {
            Ok(Async::Ready(())) | Err(_) => return Err(::Error::new_closed()),
            Ok(Async::NotReady) => (),
        }

        self.tx.poll_ready().map_err(|_| ::Error::new_closed())
    }

    /// Sends data on this channel.
    ///
    /// This should be called after `poll_ready` indicated the channel
    /// could accept another `Chunk`.
    ///
    /// Returns `Err(Chunk)` if the channel could not (currently) accept
    /// another `Chunk`.
    pub fn send_data(&mut self, chunk: Chunk) -> Result<(), Chunk> {
        self.tx.try_send(Ok(chunk))
            .map_err(|err| err.into_inner().expect("just sent Ok"))
    }

    pub(crate) fn send_error(&mut self, err: ::Error) {
        let _ = self.tx.try_send(Err(err));
    }
}

impl From<Chunk> for Body {
    #[inline]
    fn from(chunk: Chunk) -> Body {
        if chunk.is_empty() {
            Body::empty()
        } else {
            Body::new(Kind::Once(Some(chunk)))
        }
    }
}

impl
    From<Box<Stream<Item = Chunk, Error = Box<::std::error::Error + Send + Sync>> + Send + 'static>>
    for Body
{
    #[inline]
    fn from(
        stream: Box<
            Stream<Item = Chunk, Error = Box<::std::error::Error + Send + Sync>> + Send + 'static,
        >,
    ) -> Body {
        Body::new(Kind::Wrapped(stream))
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from (bytes: Bytes) -> Body {
        Body::from(Chunk::from(bytes))
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from (vec: Vec<u8>) -> Body {
        Body::from(Chunk::from(vec))
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from (slice: &'static [u8]) -> Body {
        Body::from(Chunk::from(slice))
    }
}

impl From<Cow<'static, [u8]>> for Body {
    #[inline]
    fn from (cow: Cow<'static, [u8]>) -> Body {
        match cow {
            Cow::Borrowed(b) => Body::from(b),
            Cow::Owned(o) => Body::from(o)
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from (s: String) -> Body {
        Body::from(Chunk::from(s.into_bytes()))
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(slice: &'static str) -> Body {
        Body::from(Chunk::from(slice.as_bytes()))
    }
}

impl From<Cow<'static, str>> for Body {
    #[inline]
    fn from(cow: Cow<'static, str>) -> Body {
        match cow {
            Cow::Borrowed(b) => Body::from(b),
            Cow::Owned(o) => Body::from(o)
        }
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

#[test]
fn test_body_stream_concat() {
    use futures::{Stream, Future};

    let body = Body::from("hello world");

    let total = body
        .concat2()
        .wait()
        .unwrap();
    assert_eq!(total.as_ref(), b"hello world");
}

<|endoftext|>


<commit_before>/*
 * CMOS IO handling
 */

use vm;

use std::rc::Rc;
use std::cell::RefCell;
use time;

const CMOS_SELECT_PORT: u16     = 0x70;
const CMOS_DATA_PORT: u16       = 0x71;
const CMOS_TOTAL_REGS: u8       = 128;  // Total number of byte registers we emulate
const CMOS_DEFAULT_SELECTOR: u8 = 0xD;  // Default selected register

/*
 * Handled registers:
 * 0x00      Seconds
 * 0x02      Minutes
 * 0x04      Hours
 * 0x06      Weekday
 * 0x07      Day of Month
 * 0x08      Month
 * 0x09      Year
 * 0x32      Century (maybe)
 * 0x0A      Status Register A
 * 0x0B      Status Register B
 * 0x0D      Status Register D
 *
 * Current limitations:
 * - No BCD format, only binary mode
 * - No 12 hour support, only 24
 * - No interrupt generation
 * - RTC updates on every register access which can lead to unstable time readings in guests
 */
struct CMOS
{
    selector: u8,
    nmi_bit: bool, // TODO: this bit should be owned by vm/vcpu
    host_time: time::Tm,    // Real host time during last update
    time: time::Tm,         // Time we are emulating
}

impl CMOS
{
    fn new() -> CMOS
    {
        CMOS {
            selector: CMOS_DEFAULT_SELECTOR,
            nmi_bit: false,
            host_time: time::empty_tm(),
            time: time::empty_tm(),
        }
    }

    fn nmi_mask(&self) -> u8
    {
        if self.nmi_bit {
            return 0x80;
        } else {
            return 0;
        }
    }

    fn read_selector(&mut self) -> u8
    {
        self.selector | self.nmi_mask()
    }

    fn write_selector(&mut self, val: u8)
    {
        self.selector = val & 0x7F;
        self.nmi_bit = (val & 0x80) != 0;
    }

    // Returns current selector value and resets it to default
    fn reset_selector(&mut self) -> u8
    {
        let val = self.selector;
        self.selector = CMOS_DEFAULT_SELECTOR;
        return val;
    }

    fn read_reg(&mut self) -> u8
    {
        // Adjust emulated time by computing elapsed duration since last time
        // Then add this duration to time we emulate
        let now = time::now();
        let delta = now - self.host_time; // Ok if negative

        self.time = self.time + delta;
        self.host_time = now;

        return match self.reset_selector() {
            // RTC
            // TODO: BCD?
            0x00 => self.time.tm_sec,
            0x02 => self.time.tm_min,
            0x04 => self.time.tm_hour,
            0x06 => self.time.tm_wday + 1, // CMOS wday starts from 1
            0x07 => self.time.tm_mday,
            0x08 => self.time.tm_mon,
            0x09 => self.time.tm_year % 100,
            0x32 => self.time.tm_year / 100,

            // Status
            0x0A => 0b00100110, // Default read only values, update bit always cleared
            0x0B => 0b00000110, // TODO: allow BCD and hour formats
            0x0D => 0b10000000,

            // Unsupported
            _ => 0,
        } as u8;
    }

    fn write_reg(&mut self, val: u8)
    {
        let v32 = val as i32;
        match self.reset_selector() {
            // RTC
            // TODO: BCD?
            0x00 => self.time.tm_sec    = v32,
            0x02 => self.time.tm_min    = v32,
            0x04 => self.time.tm_hour   = v32,
            0x06 => self.time.tm_wday   = v32 - 1, // CMOS wday starts from 1
            0x07 => self.time.tm_mday   = v32,
            0x08 => self.time.tm_mon    = v32,
            0x09 => self.time.tm_year   = self.time.tm_year / 100 * 100 + v32,
            0x32 => self.time.tm_year   = v32 * 100 + self.time.tm_year % 100,

            // Unsupported
            _ => (),
        };
    }
}

// Test initial state
#[test] fn cmos_test_default()
{
    let cmos = CMOS::new();

    assert!(cmos.selector == CMOS_DEFAULT_SELECTOR);
    assert!(cmos.nmi_bit == false);
    assert!(cmos.host_time == time::empty_tm());
    assert!(cmos.time == time::empty_tm());
}

// Check that NMI bit is propogated to selector value
#[test] fn cmos_test_nmi_bit()
{
    let mut cmos = CMOS::new();

    let mut sel = cmos.read_selector();
    assert!(sel & 0x80 == 0);

    cmos.write_selector(sel | 0x80);
    sel = cmos.read_selector();
    assert!(sel & 0x80 != 0);

    cmos.write_selector(sel & 0x7F);
    sel = cmos.read_selector();
    assert!(sel & 0x80 == 0);
}

// TODO: MOAR TESTS

///////////////////////////////////////////////////////////////////////////////

struct CMOSDev
{
    cmos: RefCell<CMOS>,
}

impl vm::io_handler for CMOSDev
{
    fn io_read(&self, port: u16, size: u8) -> vm::IoOperandType
    {
        let mut cmos = self.cmos.borrow_mut();

        assert!(size == 1);
        assert!(cmos.selector < CMOS_TOTAL_REGS);

        match port {
            CMOS_SELECT_PORT => {
                return vm::IoOperandType::byte(cmos.read_selector());
            },

            CMOS_DATA_PORT => {
                return vm::IoOperandType::byte(cmos.read_reg());
            }

            _ => {
                panic!();
            }
        }
    }

    fn io_write(&self, port: u16, data: vm::IoOperandType)
    {
        let mut cmos = self.cmos.borrow_mut();
        let val: u8 = data.unwrap_byte();

        assert!(cmos.selector < CMOS_TOTAL_REGS);

        match port {
            CMOS_SELECT_PORT => {
                cmos.write_selector(val);
            }

            CMOS_DATA_PORT => {
                cmos.write_reg(val);
            }

            _ => {
                panic!();
            }
        }
    }
}

pub fn init(vm: &mut vm::vm)
{
	let dev = Rc::new(CMOSDev {
        cmos: RefCell::new(CMOS::new()),
    });

    vm::register_io_region(vm, dev.clone(), CMOS_SELECT_PORT, 1);
    vm::register_io_region(vm, dev.clone(), CMOS_DATA_PORT, 1);
}

<commit_msg>CMOS: added BCD emulation and tests<commit_after>/*
 * CMOS IO handling
 */

use vm;

use std::rc::Rc;
use std::cell::RefCell;
use time;

const CMOS_SELECT_PORT: u16     = 0x70;
const CMOS_DATA_PORT: u16       = 0x71;
const CMOS_TOTAL_REGS: u8       = 128;  // Total number of byte registers we emulate
const CMOS_DEFAULT_SELECTOR: u8 = 0xD;  // Default selected register

/*
 * Handled registers:
 * 0x00      Seconds
 * 0x02      Minutes
 * 0x04      Hours
 * 0x06      Weekday
 * 0x07      Day of Month
 * 0x08      Month
 * 0x09      Year
 * 0x32      Century (maybe)
 * 0x0A      Status Register A
 * 0x0B      Status Register B
 * 0x0D      Status Register D
 *
 * Current limitations:
 * - No BCD format, only binary mode
 * - No 12 hour support, only 24
 * - No interrupt generation
 * - RTC updates on every register access which can lead to unstable time readings in guests
 */
struct CMOS
{
    selector: u8,
    sta: u8,
    stb: u8,
    nmi_bit: bool,          // TODO: this bit should be owned by vm/vcpu
    host_time: time::Tm,    // Real host time during last update
    time: time::Tm,         // Time we are emulating
}

impl CMOS
{
    fn new() -> CMOS
    {
        CMOS {
            selector: CMOS_DEFAULT_SELECTOR,
            sta: 0b00100110,
            stb: 0b00000110,
            nmi_bit: false,
            host_time: time::empty_tm(),
            time: time::empty_tm(),
        }
    }

    fn nmi_mask(&self) -> u8
    {
        if self.nmi_bit {
            return 0x80;
        } else {
            return 0;
        }
    }

    fn read_selector(&mut self) -> u8
    {
        self.selector | self.nmi_mask()
    }

    fn write_selector(&mut self, val: u8)
    {
        self.selector = val & 0x7F;
        self.nmi_bit = (val & 0x80) != 0;
    }

    // Returns current selector value and resets it to default
    fn reset_selector(&mut self) -> u8
    {
        let val = self.selector;
        self.selector = CMOS_DEFAULT_SELECTOR;
        return val;
    }

    fn to_rtc_format(&self, val: i32) -> u8
    {
        if (self.stb & 0x04) == 0 {
            // BCD format needed
            assert!(val < 100);
            let lo = (val % 10) as u8;
            let hi = (val / 10) as u8;
            return lo | (hi << 4);
        } else {
            return val as u8;
        }
    }

    fn from_rtc_format(&self, val: u8) -> i32
    {
        if (self.stb & 0x04) == 0 {
            // BCD format needed
            let lo = (val & 0xF) as i32;
            let hi = (val >> 4) as i32;
            return lo + hi;
        } else {
            return val as i32;
        }
    }

    fn read_reg(&mut self) -> u8
    {
        // Adjust emulated time by computing elapsed duration since last time
        // Then add this duration to time we emulate
        let now = time::now();
        let delta = now - self.host_time; // Ok if negative

        self.time = self.time + delta;
        self.host_time = now;

        return match self.reset_selector() {
            // RTC
            0x00 => self.to_rtc_format(self.time.tm_sec),
            0x02 => self.to_rtc_format(self.time.tm_min),
            0x04 => self.to_rtc_format(self.time.tm_hour),
            0x06 => self.to_rtc_format(self.time.tm_wday + 1), // CMOS wday starts from 1
            0x07 => self.to_rtc_format(self.time.tm_mday),
            0x08 => self.to_rtc_format(self.time.tm_mon),
            0x09 => self.to_rtc_format(self.time.tm_year % 100),
            0x32 => self.to_rtc_format(self.time.tm_year / 100),

            // Status
            0x0A => self.sta,
            0x0B => self.stb,

            // Unsupported
            _ => 0,
        } as u8;
    }

    fn write_reg(&mut self, val: u8)
    {
        match self.reset_selector() {
            // RTC
            0x00 => self.time.tm_sec    = self.from_rtc_format(val),
            0x02 => self.time.tm_min    = self.from_rtc_format(val),
            0x04 => self.time.tm_hour   = self.from_rtc_format(val),
            0x06 => self.time.tm_wday   = self.from_rtc_format(val) - 1, // CMOS wday starts from 1
            0x07 => self.time.tm_mday   = self.from_rtc_format(val),
            0x08 => self.time.tm_mon    = self.from_rtc_format(val),
            0x09 => self.time.tm_year   = self.from_rtc_format(val) + self.time.tm_year / 100 * 100,
            0x32 => self.time.tm_year   = self.from_rtc_format(val) * 100 + self.time.tm_year % 100,

            // Status
            0x0A => self.sta = val,
            0x0B => self.stb = val,

            // Unsupported
            _ => (),
        };
    }
}

#[cfg(test)]
mod cmos_test {

    use super::CMOS;
    use time;

    fn read_reg(cmos: &mut CMOS, reg: u8) -> u8
    {
        let sel = (cmos.read_selector() & 0x80) | reg;
        cmos.write_selector(sel);
        return cmos.read_reg();
    }

    fn write_reg(cmos: &mut CMOS, reg: u8, val: u8)
    {
        let sel = (cmos.read_selector() & 0x80) | reg;
        cmos.write_selector(sel);
        cmos.write_reg(val);
    }

    fn read_rtc_reg(cmos: &mut CMOS, is_bcd: bool, reg: u8) -> u8
    {
        let mut val = read_reg(cmos, reg);

        if is_bcd {
            let lo = val & 0xF;
            let hi = val >> 4;
            val = hi * 10 + lo;
        }

        return val;

    }

    fn set_bcd(cmos: &mut CMOS, is_bcd: bool)
    {
        let stb = read_reg(cmos, 0x0b);
        if is_bcd {
            write_reg(cmos, 0x0b, stb | 0x04u8);
        } else {
            write_reg(cmos, 0x0b, stb & !0x04u8);
        }
    }

    // Test initial state
    #[test] fn default()
    {
        let cmos = CMOS::new();

        assert!(cmos.selector == super::CMOS_DEFAULT_SELECTOR);
        assert!(cmos.nmi_bit == false);
        assert!(cmos.host_time == time::empty_tm());
        assert!(cmos.time == time::empty_tm());
    }

    // Check that NMI bit is propogated to selector value
    #[test] fn nmi_bit()
    {
        let mut cmos = CMOS::new();

        let mut sel = cmos.read_selector();
        assert!(sel & 0x80 == 0);

        cmos.write_selector(sel | 0x80);
        sel = cmos.read_selector();
        assert!(sel & 0x80 != 0);

        cmos.write_selector(sel & 0x7F);
        sel = cmos.read_selector();
        assert!(sel & 0x80 == 0);
    }

    fn rtc_to_tm(cmos: &mut CMOS) -> time::Tm
    {
        let is_bcd = (read_reg(cmos, 0x0b) & 0x04) == 0;

        let mut tm: time::Tm = time::empty_tm();
        tm.tm_sec = read_rtc_reg(cmos, is_bcd, 0x00) as i32;
        tm.tm_min = read_rtc_reg(cmos, is_bcd, 0x02) as i32;
        tm.tm_hour = read_rtc_reg(cmos, is_bcd, 0x04) as i32;
        tm.tm_wday = read_rtc_reg(cmos, is_bcd, 0x06) as i32;
        tm.tm_mday = read_rtc_reg(cmos, is_bcd, 0x07) as i32;
        tm.tm_mon = read_rtc_reg(cmos, is_bcd, 0x08) as i32;
        tm.tm_year = (read_rtc_reg(cmos, is_bcd, 0x32) as i32) * 100 + (read_rtc_reg(cmos, is_bcd, 0x09) as i32);

        return tm;
    }

    fn rtc_test_common(cmos: &mut CMOS)
    {
        // Time reported by rtc should be within sane distance from now
        let now = time::now();
        let t = rtc_to_tm(cmos);
        assert!((t - now).num_seconds() <= 1);

        // Check that eventually rtc will report a monotonic increase in time
        loop {
            let tm1 = rtc_to_tm(cmos);
            let tm2 = rtc_to_tm(cmos);
            if tm2 > tm1 {
                break;
            }
        }
    }

    #[test] fn rtc()
    {
        let mut cmos = CMOS::new();

        set_bcd(&mut cmos, true);
        rtc_test_common(&mut cmos);

        set_bcd(&mut cmos, false);
        rtc_test_common(&mut cmos);
    }
}

// TODO: MOAR TESTS

///////////////////////////////////////////////////////////////////////////////

struct CMOSDev
{
    cmos: RefCell<CMOS>,
}

impl vm::io_handler for CMOSDev
{
    fn io_read(&self, port: u16, size: u8) -> vm::IoOperandType
    {
        let mut cmos = self.cmos.borrow_mut();

        assert!(size == 1);
        assert!(cmos.selector < CMOS_TOTAL_REGS);

        match port {
            CMOS_SELECT_PORT => {
                return vm::IoOperandType::byte(cmos.read_selector());
            },

            CMOS_DATA_PORT => {
                return vm::IoOperandType::byte(cmos.read_reg());
            }

            _ => {
                panic!();
            }
        }
    }

    fn io_write(&self, port: u16, data: vm::IoOperandType)
    {
        let mut cmos = self.cmos.borrow_mut();
        let val: u8 = data.unwrap_byte();

        assert!(cmos.selector < CMOS_TOTAL_REGS);

        match port {
            CMOS_SELECT_PORT => {
                cmos.write_selector(val);
            }

            CMOS_DATA_PORT => {
                cmos.write_reg(val);
            }

            _ => {
                panic!();
            }
        }
    }
}

pub fn init(vm: &mut vm::vm)
{
	let dev = Rc::new(CMOSDev {
        cmos: RefCell::new(CMOS::new()),
    });

    vm::register_io_region(vm, dev.clone(), CMOS_SELECT_PORT, 1);
    vm::register_io_region(vm, dev.clone(), CMOS_DATA_PORT, 1);
}

<|endoftext|>


<commit_before>extern crate sdl2;
extern crate native;

use sdl2::video::{Window, PosCentered, OpenGL};
use sdl2::event::{QuitEvent, NoEvent, poll_event};

#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, main)
}

#[main]
fn main() {
    // start sdl2 with everything
    sdl2::init(sdl2::InitEverything);

    // Create a window and show it
    let window  = match Window::new("eg01", PosCentered, PosCentered, 640, 480, OpenGL) {
        Ok(window) => window,
        Err(err)   => fail!(format!("failed to create window: {}", err))
    };
    window.show();

    // loop until we receive a QuitEvent
    'event : loop {
        // poll_event returns the most recent event or NoEvent if nothing has happened
        match poll_event() {
            QuitEvent(_) => break 'event,
            NoEvent      => continue,
            // print the event to the console
            event        => println!("event: {}", event),
        }
    }

    sdl2::quit();
}

<commit_msg>Fix eg02 title<commit_after>extern crate sdl2;
extern crate native;

use sdl2::video::{Window, PosCentered, OpenGL};
use sdl2::event::{QuitEvent, NoEvent, poll_event};

#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, main)
}

#[main]
fn main() {
    // start sdl2 with everything
    sdl2::init(sdl2::InitEverything);

    // Create a window and show it
    let window  = match Window::new("eg02", PosCentered, PosCentered, 640, 480, OpenGL) {
        Ok(window) => window,
        Err(err)   => fail!(format!("failed to create window: {}", err))
    };
    window.show();

    // loop until we receive a QuitEvent
    'event : loop {
        // poll_event returns the most recent event or NoEvent if nothing has happened
        match poll_event() {
            QuitEvent(_) => break 'event,
            NoEvent      => continue,
            // print the event to the console
            event        => println!("event: {}", event),
        }
    }

    sdl2::quit();
}

<|endoftext|>


<commit_before>use parser::Node;

struct Eval;

impl Eval {
    pub fn new() -> Self {
        Eval {}
    }

    fn calc_integer<F>(&self, f: &F, args: &[Node], node: &Node) -> Node
        where F: Fn(i64, i64) -> i64 {

        Node::Integer(
            args.iter().fold(None, |a, x| match x {
                &Node::Integer(i) => match a {
                    Some(aa) => Some(f(aa, i)),
                    None => Some(i)
                },
                // TODO: Don't copy
                &Node::List(_) => match &self.eval(x.clone()) {
                    &Node::Integer(i) => match a {
                        Some(aa) => Some(f(aa, i)),
                        None => Some(i)
                    },
                    _ => panic!("{:?} takes only an integer, but got {:?}", node, x),
                },
                _ => panic!("{:?} takes only an integer, but got {:?}", node, x)
            }
        ).unwrap_or(0))
    }

    fn car(&self, args: &[Node], node: &Node) -> Node {
        if args.len() == 1 {
            if let &Node::QuotedList(ref xs) = &args[0] {
                return match xs.split_first() {
                    // TODO: Don't copy
                    Some((hd, _)) => hd.clone(),
                    None => Node::List(vec![])
                }
            }
        }

        panic!("`car` takes only a quoted list, but got {:?}", args);
    }

    fn cdr(&self, args: &[Node], node: &Node) -> Node {
        if args.len() == 1 {
            if let &Node::QuotedList(ref xs) = &args[0] {
                return match xs.split_first() {
                    // TODO: Don't copy
                    Some((_, tl)) => Node::QuotedList(tl.to_vec()),
                    None => Node::List(vec![])
                }
            }
        }

        panic!("`car` takes only a quoted list, but got {:?}", args);
    }

    pub fn eval(&self, node: Node) -> Node {
        match node {
            Node::Integer(_) => node,
            Node::Keyword(_) => panic!("Unexpected node: {:?}", node),
            Node::List(ref xs) => {
                let (hd, tl) = xs.split_first().unwrap();
                match hd {
                    &Node::Keyword(ref kwd) =>
                        match kwd.as_str() {
                            "+" => self.calc_integer(&|a, i| a + i, tl, &node),
                            "-" => self.calc_integer(&|a, i| a - i, tl, &node),
                            "*" => self.calc_integer(&|a, i| a * i, tl, &node),
                            "/" => self.calc_integer(&|a, i| a / i, tl, &node),
                            "car" => self.car(tl, &node),
                            "cdr" => self.cdr(tl, &node),
                            _ => panic!("Unexpected node: {:?}", node),
                        },
                    _ => panic!("Unexpected node: {:?}", node),
                }
            },
            Node::QuotedList(x) => Node::List(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Eval;
    use parser::Node;

    #[test]
    fn eval() {
        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                Node::List(
                    vec![
                        Node::Keyword(String::from("+")),
                        Node::Integer(2),
                        Node::Integer(40),
                    ]
                )
            )
        );

        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                Node::List(
                    vec![
                        Node::Keyword(String::from("*")),
                        Node::Integer(6),
                        Node::List(
                            vec![
                                Node::Keyword(String::from("-")),
                                Node::Integer(42),
                                Node::Integer(35),
                            ]
                        ),
                    ]
                )
            )
        );

        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                Node::List(
                    vec![
                        Node::Keyword(String::from("car")),
                        Node::QuotedList(
                            vec![
                                Node::Integer(42),
                                Node::Integer(-123),
                                Node::Integer(0),
                            ]
                        ),
                    ]
                )
            )
        );

        assert_eq!(
            Node::QuotedList(
                vec![
                    Node::Integer(4),
                    Node::Integer(2),
                ]
            ),
            Eval::new().eval(
                Node::List(
                    vec![
                        Node::Keyword(String::from("cdr")),
                        Node::QuotedList(
                            vec![
                                Node::Integer(0),
                                Node::Integer(4),
                                Node::Integer(2),
                            ]
                        ),
                    ]
                )
            )
        );
    }
}
<commit_msg>Add `setq`<commit_after>use std::collections::HashMap;
use parser::Node;

struct Eval;

impl Eval {
    pub fn new() -> Self {
        Eval {}
    }

    fn calc_integer<F>(&self, env: &mut HashMap<String, Node>, f: &F, args: &[Node], node: &Node) -> Node
        where F: Fn(i64, i64) -> i64 {

        Node::Integer(
            args.iter().fold(None, |a, x| match x {
                &Node::Integer(i) => match a {
                    Some(aa) => Some(f(aa, i)),
                    None => Some(i)
                },
                // TODO: Don't copy
                &Node::List(_) => match &self.eval(env, x.clone()) {
                    &Node::Integer(i) => match a {
                        Some(aa) => Some(f(aa, i)),
                        None => Some(i)
                    },
                    _ => panic!("{:?} takes only an integer, but got {:?}", node, x),
                },
                // TODO: Don't copy
                &Node::Keyword(_) => match &self.eval(env, x.clone()) {
                    &Node::Integer(i) => match a {
                        Some(aa) => Some(f(aa, i)),
                        None => Some(i)
                    },
                    _ => panic!("{:?} takes only an integer, but got {:?}", node, x),
                },
                _ => panic!("{:?} takes only an integer, but got {:?}", node, x)
            }
        ).unwrap_or(0))
    }

    fn car(&self, env: &mut HashMap<String, Node>, args: &[Node], node: &Node) -> Node {
        if args.len() == 1 {
            if let &Node::QuotedList(ref xs) = &args[0] {
                return match xs.split_first() {
                    // TODO: Don't copy
                    Some((hd, _)) => hd.clone(),
                    None => Node::List(vec![])
                }
            }
        }

        panic!("`car` takes only a quoted list, but got {:?}", args);
    }

    fn cdr(&self, env: &mut HashMap<String, Node>, args: &[Node], node: &Node) -> Node {
        if args.len() == 1 {
            if let &Node::QuotedList(ref xs) = &args[0] {
                return match xs.split_first() {
                    // TODO: Don't copy
                    Some((_, tl)) => Node::QuotedList(tl.to_vec()),
                    None => Node::List(vec![])
                }
            }
        }

        panic!("`cdr` takes only a quoted list, but got {:?}", args);
    }

    fn setq(&self, env: &mut HashMap<String, Node>, args: &[Node], node: &Node) -> Node {
        if args.len() % 2 == 0 {
            let mut key = None;
            for arg in args {
                if let Some(k) = key {
                    // TODO: Don't copy
                    env.insert(k, arg.clone());
                    key = None;
                }
                else {
                    if let &Node::Keyword(ref k) = arg {
                        // TODO: Don't copy
                        key = Some(k.clone())
                    }
                    else {
                        panic!("`setq` accepts only Node::Keyword as a key, but got {:?}", arg);
                    }
                }
            }
        }

        panic!("`setq` takes only key value pairs, but got {:?}", args);
    }
    pub fn eval(&self, env: &mut HashMap<String, Node>, node: Node) -> Node {
        match node {
            Node::Integer(_) => node,
            Node::Keyword(kwd) => {
                // TODO: Don't copy
                let cloned_env = env.clone();
                let x = cloned_env.get(&kwd).unwrap();
                self.eval(env, x.clone())
            }
            Node::List(ref xs) => {
                let (hd, tl) = xs.split_first().unwrap();
                match hd {
                    &Node::Keyword(ref kwd) =>
                        match kwd.as_str() {
                            "+" => self.calc_integer(env, &|a, i| a + i, tl, &node),
                            "-" => self.calc_integer(env, &|a, i| a - i, tl, &node),
                            "*" => self.calc_integer(env, &|a, i| a * i, tl, &node),
                            "/" => self.calc_integer(env, &|a, i| a / i, tl, &node),
                            "car" => self.car(env, tl, &node),
                            "cdr" => self.cdr(env, tl, &node),
                            "setq" => self.setq(env, tl, &node),
                            kwd => {
                                // TODO: Don't copy
                                let cloned_env = env.clone();
                                let x = cloned_env.get(kwd).unwrap();
                                self.eval(env, x.clone())
                            },
                        },
                    _ => panic!("Unexpected node: {:?}", node),
                }
            },
            Node::QuotedList(x) => Node::List(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use super::Eval;
    use parser::Node;

    #[test]
    fn eval() {
        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                &mut HashMap::new(),
                Node::List(
                    vec![
                        Node::Keyword(String::from("+")),
                        Node::Integer(2),
                        Node::Integer(40),
                    ]
                )
            )
        );

        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                &mut HashMap::new(),
                Node::List(
                    vec![
                        Node::Keyword(String::from("*")),
                        Node::Integer(6),
                        Node::List(
                            vec![
                                Node::Keyword(String::from("-")),
                                Node::Integer(42),
                                Node::Integer(35),
                            ]
                        ),
                    ]
                )
            )
        );

        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                &mut HashMap::new(),
                Node::List(
                    vec![
                        Node::Keyword(String::from("car")),
                        Node::QuotedList(
                            vec![
                                Node::Integer(42),
                                Node::Integer(-123),
                                Node::Integer(0),
                            ]
                        ),
                    ]
                )
            )
        );

        assert_eq!(
            Node::QuotedList(
                vec![
                    Node::Integer(4),
                    Node::Integer(2),
                ]
            ),
            Eval::new().eval(
                &mut HashMap::new(),
                Node::List(
                    vec![
                        Node::Keyword(String::from("cdr")),
                        Node::QuotedList(
                            vec![
                                Node::Integer(0),
                                Node::Integer(4),
                                Node::Integer(2),
                            ]
                        ),
                    ]
                )
            )
        );

        let env = &mut HashMap::new();
        env.insert(String::from("x"), Node::Integer(40));
        assert_eq!(
            Node::Integer(42),
            Eval::new().eval(
                env,
                Node::List(
                    vec![
                        Node::Keyword(String::from("+")),
                        Node::Integer(2),
                        Node::Keyword(String::from("x"))
                    ]
                )
            )
        );
    }
}
<|endoftext|>


<commit_before>use parser::{parse};
use ast::Expr::*;
use ast::UnOp::*;
use ast::BinOp::*;
use ast::Dec::*;
use ast::*;

fn subst(e: Expr, x: Expr, v: Expr) -> Expr {
  let sub = |e1: Expr| subst(e1.clone(), x.clone(), v.clone());

  match (e.clone(), x.clone()) {
    (Var(ref s1), Var(ref s2)) if s1 == s2 => v.clone(),
    (FnCall(v1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();

      FnCall(Box::new(sub(*v1)), xs2)
    },
    (Var(_), _) => e,
    (Int(_), _) => e,
    (Bool(_), _) => e,
    (Addr(_), _) => e,
    (Scope(e1, a), _) => Scope(Box::new(sub(*e1)), a),
    (Bop(op, e1, e2), _) => {
      Bop(
        op,
        Box::new(sub(*e1)),
        Box::new(sub(*e2))
      )
    },
    (Uop(op, e1), _) => Uop(op, Box::new(sub(*e1))),
    (Ternary(e1, e2, e3), _) => {
      Ternary(
        Box::new(sub(*e1)),
        Box::new(sub(*e2)),
        Box::new(sub(*e3))
      )
    },
    (Decl(d, y, e1, e2), _) => {
      let e2s = if *y == x {
        *e2
      } else {
        sub(*e2)
      };

      Decl(
        d,
        Box::new(*y),
        Box::new(sub(*e1)),
        Box::new(e2s)
      )
    },
    (Func(name, e1, xs), _) => {
      match xs.iter().find(|y| **y == x) {
        Some(_) => e,
        None if name == Some(Box::new(x.clone())) => e,
        None => Func(name, Box::new(sub(*e1)), xs)
      }
    }
  }
}

pub fn step(state: &mut State) -> &mut State {
  let st_step = |s: &mut State, e1: &Expr| {
    step(s.with(e1.clone())).expr.clone()
  };

  debug!("step(e) : {:?}", state.expr);
  debug!("step(state) : {:?}", state.mem);
  let e1 = match state.expr.clone() {
    Addr(addr) => {
      state.get(addr)
    },
    /**
     * Values are ineligible for step
     */
    Int(_) | Bool(_) | Func(_, _, _) | Var(_) => {
      debug!("stepping on a value {:?}", state.expr);
      panic!("stepping on a value");
    },
    /**
     * Base cases
     */
    Uop(Not, ref e1) if e1.is_bool() => {
      Bool(!e1.to_bool())
    },
    Uop(Neg, ref e1) if e1.is_int() => {
      Int(-1 * e1.to_int())
    },
    Bop(And, ref e1, ref e2) if e1.is_bool() && e2.is_bool() => {
      Bool(e1.to_bool() && e2.to_bool())
    },
    Bop(Or, ref e1, ref e2) if e1.is_bool() && e2.is_bool() => {
      Bool(e1.to_bool() || e2.to_bool())
    },
    Bop(Eq, ref e1, ref e2) if e1.is_value() && e2.is_value() => {
      Bool(*e1 == *e2)
    },
    Bop(Ne, ref e1, ref e2) if e1.is_value() && e2.is_value() => {
      Bool(*e1 != *e2)
    },
    Bop(Mod, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      let n1 = e1.to_int();
      let n2 = e2.to_int();

      // rust % gives the remainder, not modulus
      let result = ((n1 % n2) + n2) % n2;

      Int(result)
    },
    Bop(Lt, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() < e2.to_int())
    },
    Bop(Gt, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() > e2.to_int())
    },
    Bop(Leq, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() <= e2.to_int())
    },
    Bop(Geq, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() >= e2.to_int())
    },
    Bop(Plus, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() + e2.to_int())
    },
    Bop(Minus, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() - e2.to_int())
    },
    Bop(Times, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() * e2.to_int())
    },
    Bop(Div, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() / e2.to_int())
    },
    Bop(Seq, ref v1, ref e2) if v1.is_value() => {
      *e2.clone()
    },
    Bop(Assign, ref v1, ref v2) if v1.is_addr() && v2.is_value() => {
      let addr = v1.to_addr();
      state.assign(addr.clone(), *v2.clone());
      debug!("done assigning {:?}", state.mem);
      *v2.clone()
    },
    Ternary(ref v1, ref e2, ref e3) if v1.is_value() => {
      match v1.to_bool() {
        true => *e2.clone(),
        false => *e3.clone(),
      }
    },
    Decl(DConst, ref x, ref v1, ref e2) if v1.is_value() => {
      subst(*e2.clone(), *x.clone(), *v1.clone())
    },
    Decl(DVar, ref x, ref v1, ref e2) if v1.is_value() => {
      debug!("allocing {:?}", v1);
      let addr = state.alloc(*v1.clone());
      let scope = Scope(Box::new(*e2.clone()), addr);
      subst(scope, *x.clone(), Expr::Addr(addr))
    },
    Scope(ref v1, addr) if v1.is_value() => {
      state.free(addr);
      *v1.clone()
    },
    // TODO: check that all of es are values
    FnCall(ref v1, ref es) if v1.is_func() => {
      match **v1 {
        Func(ref name, ref e1, ref xs) => {
          // sub the params
          let exp = xs.iter().zip(es.iter())
            .fold(*e1.clone(), |exp, (xn, en)| subst(exp, xn.clone(), en.clone()));

          // sub the fn body for named functions
          match *name {
            None => exp,
            Some(ref s) => subst(exp, *s.clone(), *v1.clone())
          }
        },
        _ => {
          debug!("expected a Func, got {:?}", v1);
          panic!()
        },
      }
    },
    /**
     * Search Cases
     */
    Bop(ref op, ref v1, ref e2) if v1.is_value() => {
      Bop(
        op.clone(),
        Box::new(*v1.clone()),
        Box::new(st_step(state, e2))
      )
    },
    Bop(Assign, ref v1, ref e2) if v1.is_addr() => {
      Bop(
        Assign,
        Box::new(*v1.clone()),
        Box::new(st_step(state, e2))
      )
    },
    Bop(op, e1, e2) => {
      Bop(op, Box::new(st_step(state, &*e1)), e2)
    },
    Scope(e1, addr) => {
      Scope(Box::new(st_step(state, &*e1)), addr)
    },
    Uop(op, e1) => {
      Uop(op, Box::new(st_step(state, &*e1)))
    },
    Ternary(e1, e2, e3) => {
      Ternary(Box::new(st_step(state, &*e1)), e2, e3)
    },
    /*
     * TODO: should there be a case like this?
    Decl(ref dt, ref addr, ref v1, ref e2) if v1.is_value() => {
      Decl(
        dt.clone(),
        Box::new(*addr.clone()),
        Box::new(*v1.clone()),
        Box::new(st_step(state, e2))
      )
    },
    */
    Decl(dt, addr, e1, e2) => {
      Decl(dt, Box::new(*addr.clone()), Box::new(st_step(state, &*e1)), e2)
    },
    /*
     * TODO: should there be a case like this?
    FnCall(ref v1, ref mut args) if v1.is_value() => {
      let mut found_first = true;

      for x in args.iter_mut() {
        if x.is_value() && found_first == true {
          found_first = false;
          *x = st_step(state, x);
        }
      }

      FnCall(Box::new(*v1.clone()), args.clone())
    }
    */
    FnCall(e1, args) => {
      FnCall(Box::new(st_step(state, &*e1)), args)
    }
  };

  debug!("returning with mem {:?}" , state.mem);
  debug!("returning with e {:?}" , state.expr);
  state.with(e1)
}

pub fn boxx(input: &str) -> Expr {
  let mut state = State::from(parse(input));

  let mut num_iterations = 0;

  loop {
    num_iterations += 1;
    if state.expr.is_value() {
      debug!("--- iterations: {}", num_iterations);
      return state.expr
    } else {
      step(&mut state);
    }
  }
}
<commit_msg>incremental step on nonvalue fn args<commit_after>use parser::{parse};
use ast::Expr::*;
use ast::UnOp::*;
use ast::BinOp::*;
use ast::Dec::*;
use ast::*;

fn all<I, F>(iter: I, f: F) -> bool where I: IntoIterator, F: FnMut(I::Item) -> bool {
  iter.into_iter().all(f)
}

fn subst(e: Expr, x: Expr, v: Expr) -> Expr {
  let sub = |e1: Expr| subst(e1.clone(), x.clone(), v.clone());

  match (e.clone(), x.clone()) {
    (Var(ref s1), Var(ref s2)) if s1 == s2 => v.clone(),
    (FnCall(v1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();

      FnCall(Box::new(sub(*v1)), xs2)
    },
    (Var(_), _) => e,
    (Int(_), _) => e,
    (Bool(_), _) => e,
    (Addr(_), _) => e,
    (Scope(e1, a), _) => Scope(Box::new(sub(*e1)), a),
    (Bop(op, e1, e2), _) => {
      Bop(
        op,
        Box::new(sub(*e1)),
        Box::new(sub(*e2))
      )
    },
    (Uop(op, e1), _) => Uop(op, Box::new(sub(*e1))),
    (Ternary(e1, e2, e3), _) => {
      Ternary(
        Box::new(sub(*e1)),
        Box::new(sub(*e2)),
        Box::new(sub(*e3))
      )
    },
    (Decl(d, y, e1, e2), _) => {
      let e2s = if *y == x {
        *e2
      } else {
        sub(*e2)
      };

      Decl(
        d,
        Box::new(*y),
        Box::new(sub(*e1)),
        Box::new(e2s)
      )
    },
    (Func(name, e1, xs), _) => {
      match xs.iter().find(|y| **y == x) {
        Some(_) => e,
        None if name == Some(Box::new(x.clone())) => e,
        None => Func(name, Box::new(sub(*e1)), xs)
      }
    }
  }
}

pub fn step(state: &mut State) -> &mut State {
  let st_step = |s: &mut State, e1: &Expr| {
    step(s.with(e1.clone())).expr.clone()
  };

  debug!("step(e) : {:?}", state.expr);
  debug!("step(state) : {:?}", state.mem);
  let e1 = match state.expr.clone() {
    Addr(addr) => {
      state.get(addr)
    },
    /**
     * Values are ineligible for step
     */
    Int(_) | Bool(_) | Func(_, _, _) | Var(_) => {
      debug!("stepping on a value {:?}", state.expr);
      panic!("stepping on a value");
    },
    /**
     * Base cases
     */
    Uop(Not, ref e1) if e1.is_bool() => {
      Bool(!e1.to_bool())
    },
    Uop(Neg, ref e1) if e1.is_int() => {
      Int(-1 * e1.to_int())
    },
    Bop(And, ref e1, ref e2) if e1.is_bool() && e2.is_bool() => {
      Bool(e1.to_bool() && e2.to_bool())
    },
    Bop(Or, ref e1, ref e2) if e1.is_bool() && e2.is_bool() => {
      Bool(e1.to_bool() || e2.to_bool())
    },
    Bop(Eq, ref e1, ref e2) if e1.is_value() && e2.is_value() => {
      Bool(*e1 == *e2)
    },
    Bop(Ne, ref e1, ref e2) if e1.is_value() && e2.is_value() => {
      Bool(*e1 != *e2)
    },
    Bop(Mod, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      let n1 = e1.to_int();
      let n2 = e2.to_int();

      // rust % gives the remainder, not modulus
      let result = ((n1 % n2) + n2) % n2;

      Int(result)
    },
    Bop(Lt, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() < e2.to_int())
    },
    Bop(Gt, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() > e2.to_int())
    },
    Bop(Leq, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() <= e2.to_int())
    },
    Bop(Geq, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Bool(e1.to_int() >= e2.to_int())
    },
    Bop(Plus, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() + e2.to_int())
    },
    Bop(Minus, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() - e2.to_int())
    },
    Bop(Times, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() * e2.to_int())
    },
    Bop(Div, ref e1, ref e2) if e1.is_int() && e2.is_int() => {
      Int(e1.to_int() / e2.to_int())
    },
    Bop(Seq, ref v1, ref e2) if v1.is_value() => {
      *e2.clone()
    },
    Bop(Assign, ref v1, ref v2) if v1.is_addr() && v2.is_value() => {
      let addr = v1.to_addr();
      state.assign(addr.clone(), *v2.clone());
      debug!("done assigning {:?}", state.mem);
      *v2.clone()
    },
    Ternary(ref v1, ref e2, ref e3) if v1.is_value() => {
      match v1.to_bool() {
        true => *e2.clone(),
        false => *e3.clone(),
      }
    },
    Decl(DConst, ref x, ref v1, ref e2) if v1.is_value() => {
      subst(*e2.clone(), *x.clone(), *v1.clone())
    },
    Decl(DVar, ref x, ref v1, ref e2) if v1.is_value() => {
      debug!("allocing {:?}", v1);
      let addr = state.alloc(*v1.clone());
      let scope = Scope(Box::new(*e2.clone()), addr);
      subst(scope, *x.clone(), Expr::Addr(addr))
    },
    Scope(ref v1, addr) if v1.is_value() => {
      state.free(addr);
      *v1.clone()
    },
    // TODO: check that all of es are values
    FnCall(ref v1, ref es) if v1.is_func() && all(es.iter(), |v| v.is_value()) => {
      match **v1 {
        Func(ref name, ref e1, ref xs) => {
          // sub the params
          let exp = xs.iter().zip(es.iter())
            .fold(*e1.clone(), |exp, (xn, en)| subst(exp, xn.clone(), en.clone()));

          // sub the fn body for named functions
          match *name {
            None => exp,
            Some(ref s) => subst(exp, *s.clone(), *v1.clone())
          }
        },
        _ => {
          debug!("expected a Func, got {:?}", v1);
          panic!()
        },
      }
    },
    /**
     * Search Cases
     */
    Bop(ref op, ref v1, ref e2) if v1.is_value() => {
      Bop(
        op.clone(),
        Box::new(*v1.clone()),
        Box::new(st_step(state, e2))
      )
    },
    Bop(Assign, ref v1, ref e2) if v1.is_addr() => {
      Bop(
        Assign,
        Box::new(*v1.clone()),
        Box::new(st_step(state, e2))
      )
    },
    Bop(op, e1, e2) => {
      Bop(op, Box::new(st_step(state, &*e1)), e2)
    },
    Scope(e1, addr) => {
      Scope(Box::new(st_step(state, &*e1)), addr)
    },
    Uop(op, e1) => {
      Uop(op, Box::new(st_step(state, &*e1)))
    },
    Ternary(e1, e2, e3) => {
      Ternary(Box::new(st_step(state, &*e1)), e2, e3)
    },
    Decl(dt, addr, e1, e2) => {
      Decl(dt, Box::new(*addr.clone()), Box::new(st_step(state, &*e1)), e2)
    },
    FnCall(ref v1, ref args) if v1.is_value() => {
      let mut found_nonvalue = false;

      let args2 = args.iter().map(|e| {
        if !found_nonvalue && !e.is_value() {
          found_nonvalue = true;
          st_step(state, e)
        } else {
          e.clone()
        }
      }).collect();

      FnCall(v1.clone(), args2)
    },
    FnCall(e1, args) => {
      FnCall(Box::new(st_step(state, &*e1)), args)
    },
  };

  debug!("returning with mem {:?}" , state.mem);
  debug!("returning with e {:?}" , state.expr);
  state.with(e1)
}

pub fn boxx(input: &str) -> Expr {
  let mut state = State::from(parse(input));

  let mut num_iterations = 0;

  loop {
    num_iterations += 1;
    if state.expr.is_value() {
      debug!("--- iterations: {}", num_iterations);
      return state.expr
    } else {
      step(&mut state);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Helper for common requirements when producing/parsing JSON

use serde::{Serialize, Serializer};
use serde::ser::MapVisitor;

// TODO: this contains Serde related functions, there are old rustc_serialize helpers
// elsewhere, they should be deleted or moved/updated here.

/// To tell Serde to skip various fields
pub trait ShouldSkip {
    fn should_skip(&self) -> bool;
}

/// To indicate whether an optional field should be skipped if None
impl<T> ShouldSkip for Option<T> {
    fn should_skip(&self) -> bool {
        self.is_none()
    }
}

/// No outer options
#[derive(Debug)]
pub struct NoOuter;

impl Serialize for NoOuter {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        // No-op
        Ok(())
    }
}

/// A recurring theme in ElasticSearch is for JSON to be `{"variable": {..map of options..}`
#[derive(Debug)]
pub struct FieldBased<F, I, O> {
    pub field: F,
    pub inner: I,
    pub outer: O
}

impl<F, I, O> FieldBased<F, I, O> {
    pub fn new(field: F, inner: I, outer: O) -> Self {
        FieldBased {
            field: field,
            inner: inner,
            outer: outer
        }
    }
}

impl<F, I, O> Serialize for FieldBased<F, I, O>
    where F: Serialize,
          I: Serialize,
          O: Serialize {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        serializer.serialize_struct("FieldBasedQuery", FieldBasedMapVisitor {
            fbq: self,
            state: 0
        })
    }
}

struct FieldBasedMapVisitor<'a, F: 'a, I: 'a, O: 'a> {
    fbq: &'a FieldBased<F, I, O>,
    state: u8
}

impl<'a, F, I, O> MapVisitor for FieldBasedMapVisitor<'a, F, I, O>
    where F: Serialize,
          I: Serialize,
          O: Serialize {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: Serializer {

        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_map_elt(&self.fbq.field, &self.fbq.inner))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(self.fbq.outer.serialize(serializer))))
            },
            _ => {
                Ok(None)
            }
        }
    }
}

/// Macro to allow access to the inner object, assumes FieldBased is wrapped in a newtype
macro_rules! add_inner_field {
    ($n:ident, $f:ident, $t:ty) => (
        pub fn $n<T: Into<$t>>(mut self, val: T) -> Self {
            self.0.inner.$f = Some(val.into());
            self
        }
    );
}

#[cfg(test)]
pub mod tests {
    use serde_json;

    use super::{FieldBased, NoOuter};

    #[derive(Serialize)]
    struct TestOptions {
        opt_a: i64,
        opt_b: f64
    }

    #[derive(Serialize)]
    struct TestStruct(FieldBased<String, TestOptions, NoOuter>);

    impl TestStruct {
        fn new(key: String, options: TestOptions) -> TestStruct {
            TestStruct(FieldBased::new(key, options, NoOuter))
        }
    }

    #[test]
    fn test_simple_field_based() {
        let t = TestStruct::new("key".to_owned(),
                                TestOptions {opt_a: 4i64, opt_b: 3.0f64});
        let s = serde_json::to_string(&t).unwrap();
        assert_eq!("", s);
    }
}
<commit_msg>Field-based JSON objects<commit_after>/*
 * Copyright 2016 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Helper for common requirements when producing/parsing JSON

use serde::{Serialize, Serializer};
use serde::ser::MapVisitor;

// TODO: this contains Serde related functions, there are old rustc_serialize helpers
// elsewhere, they should be deleted or moved/updated here.

/// To tell Serde to skip various fields
pub trait ShouldSkip {
    fn should_skip(&self) -> bool;
}

/// To indicate whether an optional field should be skipped if None
impl<T> ShouldSkip for Option<T> {
    fn should_skip(&self) -> bool {
        self.is_none()
    }
}

/// No outer options
#[derive(Debug)]
pub struct NoOuter;

impl Serialize for NoOuter {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        // No-op
        Ok(())
    }
}

/// A recurring theme in ElasticSearch is for JSON to be `{"variable": {..map of options..}`
#[derive(Debug)]
pub struct FieldBased<F, I, O> {
    pub field: F,
    pub inner: I,
    pub outer: O
}

impl<F, I, O> FieldBased<F, I, O> {
    pub fn new(field: F, inner: I, outer: O) -> Self {
        FieldBased {
            field: field,
            inner: inner,
            outer: outer
        }
    }
}

impl<F, I, O> Serialize for FieldBased<F, I, O>
    where F: Serialize,
          I: Serialize,
          O: Serialize {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        serializer.serialize_struct("FieldBasedQuery", FieldBasedMapVisitor {
            fbq: self,
            state: 0
        })
    }
}

struct FieldBasedMapVisitor<'a, F: 'a, I: 'a, O: 'a> {
    fbq: &'a FieldBased<F, I, O>,
    state: u8
}

impl<'a, F, I, O> MapVisitor for FieldBasedMapVisitor<'a, F, I, O>
    where F: Serialize,
          I: Serialize,
          O: Serialize {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: Serializer {

        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_map_elt(&self.fbq.field, &self.fbq.inner))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(self.fbq.outer.serialize(serializer))))
            },
            _ => {
                Ok(None)
            }
        }
    }
}

/// Macro to allow access to the inner object, assumes FieldBased is wrapped in a newtype
macro_rules! add_inner_field {
    ($n:ident, $f:ident, $t:ty) => (
        pub fn $n<T: Into<$t>>(mut self, val: T) -> Self {
            self.0.inner.$f = Some(val.into());
            self
        }
    );
}

#[cfg(test)]
pub mod tests {
    use serde_json;

    use super::{FieldBased, NoOuter};

    #[derive(Serialize)]
    struct TestOptions {
        opt_a: i64,
        opt_b: f64
    }

    #[derive(Serialize)]
    struct TestStruct(FieldBased<String, TestOptions, NoOuter>);

    impl TestStruct {
        fn new(key: String, options: TestOptions) -> TestStruct {
            TestStruct(FieldBased::new(key, options, NoOuter))
        }
    }

    #[test]
    fn test_simple_field_based() {
        let t = TestStruct::new("key".to_owned(),
                                TestOptions {opt_a: 4i64, opt_b: 3.5f64});
        let s = serde_json::to_string(&t).unwrap();
        assert_eq!("{\"key\":{\"opt_a\":4,\"opt_b\":3.5}}", s);
    }
}
<|endoftext|>