<commit_before>//! Core I/O traits and combinators when working with Tokio.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/tokio-io/0.1")]

#[macro_use]
extern crate log;

#[macro_use]
extern crate futures;
extern crate bytes;

use std::io as std_io;
use std::io::Write;

use futures::{Async, Poll};
use futures::future::BoxFuture;
use futures::stream::BoxStream;

use bytes::{Buf, BufMut};

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, std_io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, std_io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

pub mod io;
pub mod codec;

mod copy;
mod flush;
mod framed;
mod framed_read;
mod framed_write;
mod length_delimited;
mod lines;
mod read;
mod read_exact;
mod read_to_end;
mod read_until;
mod shutdown;
mod split;
mod window;
mod write_all;

use codec::{Decoder, Encoder, Framed};
use split::{ReadHalf, WriteHalf};

/// A trait for readable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Read` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are read. Specifically this means that the `read`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately read and placed into
///   the output buffer, where `n` == 0 implies that EOF has been reached.
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was read
///   into the buffer provided. The I/O object is not currently readable but may
///   become readable in the future. Most importantly, **the current future's
///   task is scheduled to get unparked when the object is readable**. This
///   means that like `Future::poll` you'll receive a notification when the I/O
///   object is readable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `read` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncRead: std_io::Read {
    /// Prepares an uninitialized buffer to be safe to pass to `read`. Returns
    /// `true` if the supplied buffer was zeroed out.
    ///
    /// While it would be highly unusual, implementations of [`io::Read`] are
    /// able to read data from the buffer passed as an argument. Because of
    /// this, the buffer passed to [`io::Read`] must be initialized memory. In
    /// situations where large numbers of buffers are used, constantly having to
    /// zero out buffers can be expensive.
    ///
    /// This function does any necessary work to prepare an uninitialized buffer
    /// to be safe to pass to `read`. If `read` guarantees to never attempt read
    /// data out of the supplied buffer, then `prepare_uninitialized_buffer`
    /// doesn't need to do any work.
    ///
    /// If this function returns `true`, then the memory has been zeroed out.
    /// This allows implementations of `AsyncRead` which are composed of
    /// multiple sub implementations to efficiently implement
    /// `prepare_uninitialized_buffer`.
    ///
    /// This function isn't actually `unsafe` to call but `unsafe` to implement. The
    /// implementor must ensure that either the whole `buf` has been zeroed or `read_buf()`.
    ///
    /// This function is called from [`read_buf`].
    ///
    /// [`io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
    /// [`read_buf`]: #method.read_buf
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        for i in 0..buf.len() {
            buf[i] = 0;
        }

        true
    }

    /// Pull some bytes from this source into the specified `Buf`, returning
    /// how many bytes were read.
    ///
    /// The `buf` provided will have bytes read into it and the internal cursor
    /// will be advanced if any bytes were read. Note that this method typically
    /// will not reallocate the buffer provided.
    fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, std_io::Error> {
        if !buf.has_remaining_mut() {
            return Ok(Async::Ready(0));
        }

        unsafe {
            let n = {
                let b = buf.bytes_mut();

                self.prepare_uninitialized_buffer(b);

                try_nb!(self.read(b))
            };

            buf.advance_mut(n);
            Ok(Async::Ready(n))
        }
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<T: Encoder + Decoder>(self, codec: T) -> Framed<Self, T>
        where Self: AsyncWrite + Sized,
    {
        framed::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        (**self).prepare_uninitialized_buffer(buf)
    }
}

impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        (**self).prepare_uninitialized_buffer(buf)
    }
}

impl<'a> AsyncRead for &'a [u8] {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        false
    }
}

/// A trait for writable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Write` and indicates that an I/O object is
/// **nonblocking**, meaning that it will return an error instead of blocking
/// when bytes are written. Specifically this means that the `write` function
/// for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately written .
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was
///   written from the buffer provided. The I/O object is not currently
///   writable but may become writable in the future. Most importantly, **the
///   current future's task is scheduled to get unparked when the object is
///   readable**. This means that like `Future::poll` you'll receive a
///   notification when the I/O object is writable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `write` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncWrite: std_io::Write {
    /// Initiates or attempts to shut down this writer, returning success when
    /// the I/O connection has completely shut down.
    ///
    /// This method is intended to be used for asynchronous shutdown of I/O
    /// connections. For example this is suitable for implementing shutdown of a
    /// TLS connection or calling `TcpStream::shutdown` on a proxied connection.
    ///
    /// This `shutdown` method is required by implementors of the
    /// `AsyncWrite` trait. Wrappers typically just want to proxy this call
    /// through to the wrapped type, and base types will typically implement
    /// shutdown logic here or just return `Ok(().into())`.
    ///
    /// Invocation of a `shutdown` implies invocation of `flush`. Once this
    /// method returns `Ready` it implies that a flush successfully happened
    /// before the shutdown happened.
    ///
    /// # Return value
    ///
    /// This function returns a `Poll<(), io::Error>` classified as such:
    ///
    /// * `Ok(Async::Ready(()))` - indicates that the connection was
    ///   successfully shut down and is now safe to deallocate/drop/close
    ///   resources associated with it. This method means that the current task
    ///   will no longer receive any notifications due to this method and the
    ///   I/O object itself is likely no longer usable.
    ///
    /// * `Ok(Async::NotReady)` - indicates that shutdown is initiated but could
    ///   not complete just yet. This may mean that more I/O needs to happen to
    ///   continue this shutdown operation. The current task is scheduled to
    ///   receive a notification when it's otherwise ready to continue the
    ///   shutdown operation. When woken up this method should be called again.
    ///
    /// * `Err(e)` - indicates a fatal error has happened with shutdown,
    ///   indicating that the shutdown operation did not complete successfully.
    ///   This typically means that the I/O object is no longer usable.
    ///
    /// # Errors
    ///
    /// This function can return normal I/O errors through `Err`, described
    /// above. Additionally this method may also render the underlying
    /// `Write::write` method no longer usable (e.g. will return errors in the
    /// future). It's recommended that once `shutdown` is called the
    /// `write` method is no longer called.
    ///
    /// # Panics
    ///
    /// This function will panic if not called within the context of a future's
    /// task.
    fn shutdown(&mut self) -> Poll<(), std_io::Error>;

    /// Write a `Buf` into this value, returning how many bytes were written.
    ///
    /// Note that this method will advance the `buf` provided automatically by
    /// the number of bytes written.
    fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, std_io::Error> {
        if !buf.has_remaining() {
            return Ok(Async::Ready(0));
        }

        let n = try_nb!(self.write(buf.bytes()));
        buf.advance(n);
        Ok(Async::Ready(n))
    }
}

impl<T: ?Sized + AsyncWrite> AsyncWrite for Box<T> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        (**self).shutdown()
    }
}
impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        (**self).shutdown()
    }
}

impl AsyncRead for std_io::Repeat {
    unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
        false
    }
}

impl AsyncWrite for std_io::Sink {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

// TODO: Implement `prepare_uninitialized_buffer` for `io::Take`.
// This is blocked on rust-lang/rust#27269
impl<T: AsyncRead> AsyncRead for std_io::Take<T> {
}

// TODO: Implement `prepare_uninitialized_buffer` when upstream exposes inner
// parts
impl<T, U> AsyncRead for std_io::Chain<T, U>
    where T: AsyncRead,
          U: AsyncRead,
{
}

impl<T: AsyncWrite> AsyncWrite for std_io::BufWriter<T> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        try_nb!(self.flush());
        self.get_mut().shutdown()
    }
}

impl<T: AsyncRead> AsyncRead for std_io::BufReader<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.get_ref().prepare_uninitialized_buffer(buf)
    }
}

impl<T: AsRef<[u8]>> AsyncRead for std_io::Cursor<T> {
}

impl<'a> AsyncWrite for std_io::Cursor<&'a mut [u8]> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

impl AsyncWrite for std_io::Cursor<Vec<u8>> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

impl AsyncWrite for std_io::Cursor<Box<[u8]>> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

<commit_msg>Fixed note about overwriting in buf_read()<commit_after>//! Core I/O traits and combinators when working with Tokio.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/tokio-io/0.1")]

#[macro_use]
extern crate log;

#[macro_use]
extern crate futures;
extern crate bytes;

use std::io as std_io;
use std::io::Write;

use futures::{Async, Poll};
use futures::future::BoxFuture;
use futures::stream::BoxStream;

use bytes::{Buf, BufMut};

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, std_io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, std_io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

pub mod io;
pub mod codec;

mod copy;
mod flush;
mod framed;
mod framed_read;
mod framed_write;
mod length_delimited;
mod lines;
mod read;
mod read_exact;
mod read_to_end;
mod read_until;
mod shutdown;
mod split;
mod window;
mod write_all;

use codec::{Decoder, Encoder, Framed};
use split::{ReadHalf, WriteHalf};

/// A trait for readable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Read` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are read. Specifically this means that the `read`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately read and placed into
///   the output buffer, where `n` == 0 implies that EOF has been reached.
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was read
///   into the buffer provided. The I/O object is not currently readable but may
///   become readable in the future. Most importantly, **the current future's
///   task is scheduled to get unparked when the object is readable**. This
///   means that like `Future::poll` you'll receive a notification when the I/O
///   object is readable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `read` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncRead: std_io::Read {
    /// Prepares an uninitialized buffer to be safe to pass to `read`. Returns
    /// `true` if the supplied buffer was zeroed out.
    ///
    /// While it would be highly unusual, implementations of [`io::Read`] are
    /// able to read data from the buffer passed as an argument. Because of
    /// this, the buffer passed to [`io::Read`] must be initialized memory. In
    /// situations where large numbers of buffers are used, constantly having to
    /// zero out buffers can be expensive.
    ///
    /// This function does any necessary work to prepare an uninitialized buffer
    /// to be safe to pass to `read`. If `read` guarantees to never attempt read
    /// data out of the supplied buffer, then `prepare_uninitialized_buffer`
    /// doesn't need to do any work.
    ///
    /// If this function returns `true`, then the memory has been zeroed out.
    /// This allows implementations of `AsyncRead` which are composed of
    /// multiple sub implementations to efficiently implement
    /// `prepare_uninitialized_buffer`.
    ///
    /// This function isn't actually `unsafe` to call but `unsafe` to implement. The
    /// implementor must ensure that either the whole `buf` has been zeroed or `read_buf()`
    /// overwrites the buffer without reading it and returns correct value.
    ///
    /// This function is called from [`read_buf`].
    ///
    /// [`io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
    /// [`read_buf`]: #method.read_buf
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        for i in 0..buf.len() {
            buf[i] = 0;
        }

        true
    }

    /// Pull some bytes from this source into the specified `Buf`, returning
    /// how many bytes were read.
    ///
    /// The `buf` provided will have bytes read into it and the internal cursor
    /// will be advanced if any bytes were read. Note that this method typically
    /// will not reallocate the buffer provided.
    fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, std_io::Error> {
        if !buf.has_remaining_mut() {
            return Ok(Async::Ready(0));
        }

        unsafe {
            let n = {
                let b = buf.bytes_mut();

                self.prepare_uninitialized_buffer(b);

                try_nb!(self.read(b))
            };

            buf.advance_mut(n);
            Ok(Async::Ready(n))
        }
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<T: Encoder + Decoder>(self, codec: T) -> Framed<Self, T>
        where Self: AsyncWrite + Sized,
    {
        framed::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        (**self).prepare_uninitialized_buffer(buf)
    }
}

impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        (**self).prepare_uninitialized_buffer(buf)
    }
}

impl<'a> AsyncRead for &'a [u8] {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        false
    }
}

/// A trait for writable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Write` and indicates that an I/O object is
/// **nonblocking**, meaning that it will return an error instead of blocking
/// when bytes are written. Specifically this means that the `write` function
/// for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately written .
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was
///   written from the buffer provided. The I/O object is not currently
///   writable but may become writable in the future. Most importantly, **the
///   current future's task is scheduled to get unparked when the object is
///   readable**. This means that like `Future::poll` you'll receive a
///   notification when the I/O object is writable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `write` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncWrite: std_io::Write {
    /// Initiates or attempts to shut down this writer, returning success when
    /// the I/O connection has completely shut down.
    ///
    /// This method is intended to be used for asynchronous shutdown of I/O
    /// connections. For example this is suitable for implementing shutdown of a
    /// TLS connection or calling `TcpStream::shutdown` on a proxied connection.
    ///
    /// This `shutdown` method is required by implementors of the
    /// `AsyncWrite` trait. Wrappers typically just want to proxy this call
    /// through to the wrapped type, and base types will typically implement
    /// shutdown logic here or just return `Ok(().into())`.
    ///
    /// Invocation of a `shutdown` implies invocation of `flush`. Once this
    /// method returns `Ready` it implies that a flush successfully happened
    /// before the shutdown happened.
    ///
    /// # Return value
    ///
    /// This function returns a `Poll<(), io::Error>` classified as such:
    ///
    /// * `Ok(Async::Ready(()))` - indicates that the connection was
    ///   successfully shut down and is now safe to deallocate/drop/close
    ///   resources associated with it. This method means that the current task
    ///   will no longer receive any notifications due to this method and the
    ///   I/O object itself is likely no longer usable.
    ///
    /// * `Ok(Async::NotReady)` - indicates that shutdown is initiated but could
    ///   not complete just yet. This may mean that more I/O needs to happen to
    ///   continue this shutdown operation. The current task is scheduled to
    ///   receive a notification when it's otherwise ready to continue the
    ///   shutdown operation. When woken up this method should be called again.
    ///
    /// * `Err(e)` - indicates a fatal error has happened with shutdown,
    ///   indicating that the shutdown operation did not complete successfully.
    ///   This typically means that the I/O object is no longer usable.
    ///
    /// # Errors
    ///
    /// This function can return normal I/O errors through `Err`, described
    /// above. Additionally this method may also render the underlying
    /// `Write::write` method no longer usable (e.g. will return errors in the
    /// future). It's recommended that once `shutdown` is called the
    /// `write` method is no longer called.
    ///
    /// # Panics
    ///
    /// This function will panic if not called within the context of a future's
    /// task.
    fn shutdown(&mut self) -> Poll<(), std_io::Error>;

    /// Write a `Buf` into this value, returning how many bytes were written.
    ///
    /// Note that this method will advance the `buf` provided automatically by
    /// the number of bytes written.
    fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, std_io::Error> {
        if !buf.has_remaining() {
            return Ok(Async::Ready(0));
        }

        let n = try_nb!(self.write(buf.bytes()));
        buf.advance(n);
        Ok(Async::Ready(n))
    }
}

impl<T: ?Sized + AsyncWrite> AsyncWrite for Box<T> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        (**self).shutdown()
    }
}
impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        (**self).shutdown()
    }
}

impl AsyncRead for std_io::Repeat {
    unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
        false
    }
}

impl AsyncWrite for std_io::Sink {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

// TODO: Implement `prepare_uninitialized_buffer` for `io::Take`.
// This is blocked on rust-lang/rust#27269
impl<T: AsyncRead> AsyncRead for std_io::Take<T> {
}

// TODO: Implement `prepare_uninitialized_buffer` when upstream exposes inner
// parts
impl<T, U> AsyncRead for std_io::Chain<T, U>
    where T: AsyncRead,
          U: AsyncRead,
{
}

impl<T: AsyncWrite> AsyncWrite for std_io::BufWriter<T> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        try_nb!(self.flush());
        self.get_mut().shutdown()
    }
}

impl<T: AsyncRead> AsyncRead for std_io::BufReader<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.get_ref().prepare_uninitialized_buffer(buf)
    }
}

impl<T: AsRef<[u8]>> AsyncRead for std_io::Cursor<T> {
}

impl<'a> AsyncWrite for std_io::Cursor<&'a mut [u8]> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

impl AsyncWrite for std_io::Cursor<Vec<u8>> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

impl AsyncWrite for std_io::Cursor<Box<[u8]>> {
    fn shutdown(&mut self) -> Poll<(), std_io::Error> {
        Ok(().into())
    }
}

<|endoftext|>


<commit_before>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

use std::ops::Drop;
use std::fmt::Debug;

pub trait TestFixture<'param, P, R> : Drop
        where P: Debug + 'static {
    fn new(curried_params: &'param P) -> Self;

    fn parameters() -> Option<Box<Iterator<Item=P>>>;

    fn setup(&mut self) -> FixtureBinding<Self, R>
            where Self: std::marker::Sized;

    fn tear_down(&self) { }
}

pub struct FixtureBinding<'fixture, F:'fixture, R> {
    pub val: R,
    pub params: &'fixture F
}

impl<'fixture, F:'fixture, R> FixtureBinding<'fixture, F, R> {
    pub fn decompose(self) -> (R, &'fixture F) {
        (self.val, self.params)
    }

    pub fn into_val(self) -> R {
        self.val
    }

    pub fn into_params(self) -> &'fixture F {
        self.params
    }
}

/// Creates a new `TestFixture` implementation.
///
/// A `fixture!` requires a name, parameters and a
#[macro_export]
macro_rules! fixture {
    ( @impl_drop $name:ident ) => {
        impl<'param> ::std::ops::Drop for $name<'param> {
            fn drop(&mut self) {
                use ::galvanic_test::TestFixture;
                self.tear_down();
            }
        }
    };

    ( @impl_struct $name:ident Params[$($param:ident : $param_ty:ty),*] Members[$($member:ident : $member_ty:ty),*] ) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $name<'param> {
            $(pub $param : &'param $param_ty,)*
            $($member : Option<$member_ty>,)*
        }
    };

    ( @new_method Params[$param:ident : $param_ty:ty] Members[$($member:ident),*] ) => {
        fn new($param : &'param $param_ty) -> Self {
            Self {
                $param,
                $($member: None,)*
            }
        }
    };
    ( @new_method Params[$($param:ident : $param_ty:ty),+] Members[$($member:ident),*] ) => {
        fn new(&($(ref $param),*) : &'param ($($param_ty),*)) -> Self {
            Self {
                $($param,)*
                $($member: None,)*
            }
        }
    };

    ( $name:ident ( ) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      }
    ) => {
        fixture!(@impl_struct $name Params[_phantom : ()] Members[$($($member : $member_ty),*),*]);

        impl<'param> ::galvanic_test::TestFixture<'param, (), $ret_ty> for $name<'param> {
            fn new(_phantom: &'param ()) -> Self {
                Self {
                    _phantom,
                    $($($member: None),*),*
                }
            }
            fn parameters() -> Option<Box<Iterator<Item=()>>> {
                Some(Box::new(Some(()).into_iter()))
            }
            fn setup(&mut $self_setup) -> ::galvanic_test::FixtureBinding<Self, $ret_ty> {
                let value = $setup_body;
                ::galvanic_test::FixtureBinding {
                    val: value,
                    params: $self_setup
                }
            }
            $(fn tear_down(&$self_td) $tear_down_body)*
        }

        fixture!(@impl_drop $name);
    };

    ( $name:ident ($($param:ident : $param_ty:ty),+) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          $(params $params_body:block)*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      }
    ) => {
        fixture!(@impl_struct $name Params[$($param : $param_ty),*] Members[$($($member : $member_ty),*),*]);

        impl<'param> ::galvanic_test::TestFixture<'param, ($($param_ty),*), $ret_ty> for $name<'param> {
            fixture!(@new_method Params[$($param : $param_ty),*] Members[$($($member),*),*]);
            fn parameters() -> Option<Box<Iterator<Item=($($param_ty),*)>>> {
                (None as Option<Box<Iterator<Item=($($param_ty),*)>>>)
                $(; Some(Box::new($params_body)))*
            }
            fn setup(&mut $self_setup) -> ::galvanic_test::FixtureBinding<Self, $ret_ty> {
                let value = $setup_body;
                ::galvanic_test::FixtureBinding {
                    val: value,
                    params: $self_setup
                }
            }
            $(fn tear_down(&$self_td) $tear_down_body)*
        }

        fixture!(@impl_drop $name);
    };
}

#[macro_export]
macro_rules! test {
    ( @parameters | $body:block $test_case_failed:ident ) => { $body };

    ( @parameters | $body:block $test_case_failed:ident $(($fixture_obj:ident, $params:expr, $fixture:ident))+) => {
        let mut described_parameters = String::from("Test panicked before all fixtures have been assigned.");
        let result = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
            let mut described_params = Vec::new();
            $(
                let params = &$params;
                let mut $fixture_obj = $fixture::new(params);
                described_params.push(format!("{:?}", $fixture_obj));
                let mut $fixture = $fixture_obj.setup();
            )*
            described_parameters = described_params.join(", ");
            $body
        }));
        if result.is_err() {
            println!("The above error occured with the following parameterisation of the test case:\n    {}\n",
                     described_parameters);
            $test_case_failed.set(true);
        }
    };

    ( @parameters , $($remainder:tt)+ ) => {
        test!(@parameters $($remainder)*);
    };

    ( @parameters $fixture:ident ( $($expr:expr),* ) $($remainder:tt)+ ) => {
        test!(@parameters $($remainder)* (fixture_obj, ($($expr),*), $fixture));
    };

    ( @parameters $fixture:ident $($remainder:tt)+ ) => {
        match $fixture::parameters() {
            Some(iterator) => {
                for params in iterator {
                    test!(@parameters $($remainder)* (fixture_obj, params, $fixture));
                }
            },
            None => panic!(concat!(
                "If a test fixture should be injected without supplying parameters, ",
                "it either needs to have no arguments ",
                "or a `params` block returning an iterator of parameter tuples ",
                "must be given for the fixture."))
        }
    };

    ( $(#[$attr:meta])* $name:ident | $($args_and_body:tt)* ) => {
        #[test]
        $(#[$attr])*
        fn $name() {
            // Cell is a workaround for #![allow(unused_mut)] which would affect the whole fn
            let test_case_failed = ::std::cell::Cell::new(false);
            test!(@parameters $($args_and_body)* test_case_failed);
            if test_case_failed.get() {
                panic!("Some parameterised test cases failed");
            }
        }
    };

    ( $(#[$attr:meta])* $name:ident $body:block ) => {
        #[test]
        $(#[$attr])*
        fn $name() {
            $body
        }
    };
}

#[macro_export]
#[cfg(not(feature = "galvanic_mock_integration"))]
macro_rules! test_suite {
    // named test suite
    ( name $name:ident ; $($remainder:tt)* ) => {
        #[cfg(test)]
        mod $name {
            use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };

    // anonymous test suite
    ( $($remainder:tt)* ) => {
        #[cfg(test)]
        mod __test {
            use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };
}

#[macro_export]
#[cfg(feature = "galvanic_mock_integration")]
macro_rules! test_suite {
    // named test suite
    ( name $name:ident ; $($remainder:tt)* ) => {
        #[allow(unused_imports)] use ::galvanic_mock::use_mocks;
        #[cfg(test)]
        #[use_mocks]
        mod $name {
            use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };

    // anonymous test suite
    ( $($remainder:tt)* ) => {
        #[allow(unused_imports)] use ::galvanic_mock::use_mocks;
        #[cfg(test)]
        #[use_mocks]
        mod __test {
            use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };
}

#[macro_export]
macro_rules! __test_suite_int {
    // internal: fixture in test_suite
    ( @int $(#[$attr:meta])* fixture $name:ident ($($param:ident : $param_ty:ty),*) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          $(params $params_body:block)*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      } $($remainder:tt)*
    ) => {
        fixture!( $(#[$attr])* $name ($($param : $param_ty),*) -> $ret_ty {
              $(members { $($member : Option<$member_ty>),* })*
              $(params $params_body)*
              setup(& mut $self_setup) $setup_body
              $(tear_down(&$self_td) $tear_down_body)*
        });
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: test in test_suite
    ( @int $(#[$attr:meta])* test $name:ident ( $($fixture:ident $(($($expr:expr),*))*),* )
            $body:block
            $($remainder:tt)*
    ) => {
        test!( $(#[$attr])* $name | $($fixture $(($($expr),*))* ),* | $body);
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: arbitrary item in test suite
    ( @int $item:item
            $($remainder:tt)*
    ) => {
        $item
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: empty test suite
    ( @int ) => { };
}
<commit_msg>Silence warnings on unused TestFixture import<commit_after>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

use std::ops::Drop;
use std::fmt::Debug;

pub trait TestFixture<'param, P, R> : Drop
        where P: Debug + 'static {
    fn new(curried_params: &'param P) -> Self;

    fn parameters() -> Option<Box<Iterator<Item=P>>>;

    fn setup(&mut self) -> FixtureBinding<Self, R>
            where Self: std::marker::Sized;

    fn tear_down(&self) { }
}

pub struct FixtureBinding<'fixture, F:'fixture, R> {
    pub val: R,
    pub params: &'fixture F
}

impl<'fixture, F:'fixture, R> FixtureBinding<'fixture, F, R> {
    pub fn decompose(self) -> (R, &'fixture F) {
        (self.val, self.params)
    }

    pub fn into_val(self) -> R {
        self.val
    }

    pub fn into_params(self) -> &'fixture F {
        self.params
    }
}

/// Creates a new `TestFixture` implementation.
///
/// A `fixture!` requires a name, parameters and a
#[macro_export]
macro_rules! fixture {
    ( @impl_drop $name:ident ) => {
        impl<'param> ::std::ops::Drop for $name<'param> {
            fn drop(&mut self) {
                use ::galvanic_test::TestFixture;
                self.tear_down();
            }
        }
    };

    ( @impl_struct $name:ident Params[$($param:ident : $param_ty:ty),*] Members[$($member:ident : $member_ty:ty),*] ) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $name<'param> {
            $(pub $param : &'param $param_ty,)*
            $($member : Option<$member_ty>,)*
        }
    };

    ( @new_method Params[$param:ident : $param_ty:ty] Members[$($member:ident),*] ) => {
        fn new($param : &'param $param_ty) -> Self {
            Self {
                $param,
                $($member: None,)*
            }
        }
    };
    ( @new_method Params[$($param:ident : $param_ty:ty),+] Members[$($member:ident),*] ) => {
        fn new(&($(ref $param),*) : &'param ($($param_ty),*)) -> Self {
            Self {
                $($param,)*
                $($member: None,)*
            }
        }
    };

    ( $name:ident ( ) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      }
    ) => {
        fixture!(@impl_struct $name Params[_phantom : ()] Members[$($($member : $member_ty),*),*]);

        impl<'param> ::galvanic_test::TestFixture<'param, (), $ret_ty> for $name<'param> {
            fn new(_phantom: &'param ()) -> Self {
                Self {
                    _phantom,
                    $($($member: None),*),*
                }
            }
            fn parameters() -> Option<Box<Iterator<Item=()>>> {
                Some(Box::new(Some(()).into_iter()))
            }
            fn setup(&mut $self_setup) -> ::galvanic_test::FixtureBinding<Self, $ret_ty> {
                let value = $setup_body;
                ::galvanic_test::FixtureBinding {
                    val: value,
                    params: $self_setup
                }
            }
            $(fn tear_down(&$self_td) $tear_down_body)*
        }

        fixture!(@impl_drop $name);
    };

    ( $name:ident ($($param:ident : $param_ty:ty),+) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          $(params $params_body:block)*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      }
    ) => {
        fixture!(@impl_struct $name Params[$($param : $param_ty),*] Members[$($($member : $member_ty),*),*]);

        impl<'param> ::galvanic_test::TestFixture<'param, ($($param_ty),*), $ret_ty> for $name<'param> {
            fixture!(@new_method Params[$($param : $param_ty),*] Members[$($($member),*),*]);
            fn parameters() -> Option<Box<Iterator<Item=($($param_ty),*)>>> {
                (None as Option<Box<Iterator<Item=($($param_ty),*)>>>)
                $(; Some(Box::new($params_body)))*
            }
            fn setup(&mut $self_setup) -> ::galvanic_test::FixtureBinding<Self, $ret_ty> {
                let value = $setup_body;
                ::galvanic_test::FixtureBinding {
                    val: value,
                    params: $self_setup
                }
            }
            $(fn tear_down(&$self_td) $tear_down_body)*
        }

        fixture!(@impl_drop $name);
    };
}

#[macro_export]
macro_rules! test {
    ( @parameters | $body:block $test_case_failed:ident ) => { $body };

    ( @parameters | $body:block $test_case_failed:ident $(($fixture_obj:ident, $params:expr, $fixture:ident))+) => {
        let mut described_parameters = String::from("Test panicked before all fixtures have been assigned.");
        let result = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
            let mut described_params = Vec::new();
            $(
                let params = &$params;
                let mut $fixture_obj = $fixture::new(params);
                described_params.push(format!("{:?}", $fixture_obj));
                let mut $fixture = $fixture_obj.setup();
            )*
            described_parameters = described_params.join(", ");
            $body
        }));
        if result.is_err() {
            println!("The above error occured with the following parameterisation of the test case:\n    {}\n",
                     described_parameters);
            $test_case_failed.set(true);
        }
    };

    ( @parameters , $($remainder:tt)+ ) => {
        test!(@parameters $($remainder)*);
    };

    ( @parameters $fixture:ident ( $($expr:expr),* ) $($remainder:tt)+ ) => {
        test!(@parameters $($remainder)* (fixture_obj, ($($expr),*), $fixture));
    };

    ( @parameters $fixture:ident $($remainder:tt)+ ) => {
        match $fixture::parameters() {
            Some(iterator) => {
                for params in iterator {
                    test!(@parameters $($remainder)* (fixture_obj, params, $fixture));
                }
            },
            None => panic!(concat!(
                "If a test fixture should be injected without supplying parameters, ",
                "it either needs to have no arguments ",
                "or a `params` block returning an iterator of parameter tuples ",
                "must be given for the fixture."))
        }
    };

    ( $(#[$attr:meta])* $name:ident | $($args_and_body:tt)* ) => {
        #[test]
        $(#[$attr])*
        fn $name() {
            // Cell is a workaround for #![allow(unused_mut)] which would affect the whole fn
            let test_case_failed = ::std::cell::Cell::new(false);
            test!(@parameters $($args_and_body)* test_case_failed);
            if test_case_failed.get() {
                panic!("Some parameterised test cases failed");
            }
        }
    };

    ( $(#[$attr:meta])* $name:ident $body:block ) => {
        #[test]
        $(#[$attr])*
        fn $name() {
            $body
        }
    };
}

#[macro_export]
#[cfg(not(feature = "galvanic_mock_integration"))]
macro_rules! test_suite {
    // named test suite
    ( name $name:ident ; $($remainder:tt)* ) => {
        #[cfg(test)]
        mod $name {
            #[allow(unused_imports)] use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };

    // anonymous test suite
    ( $($remainder:tt)* ) => {
        #[cfg(test)]
        mod __test {
            #[allow(unused_imports)] use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };
}

#[macro_export]
#[cfg(feature = "galvanic_mock_integration")]
macro_rules! test_suite {
    // named test suite
    ( name $name:ident ; $($remainder:tt)* ) => {
        #[allow(unused_imports)] use ::galvanic_mock::use_mocks;
        #[cfg(test)]
        #[use_mocks]
        mod $name {
            #[allow(unused_imports)] use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };

    // anonymous test suite
    ( $($remainder:tt)* ) => {
        #[allow(unused_imports)] use ::galvanic_mock::use_mocks;
        #[cfg(test)]
        #[use_mocks]
        mod __test {
            #[allow(unused_imports)] use ::galvanic_test::TestFixture;
            __test_suite_int!(@int $($remainder)*);
        }
    };
}

#[macro_export]
macro_rules! __test_suite_int {
    // internal: fixture in test_suite
    ( @int $(#[$attr:meta])* fixture $name:ident ($($param:ident : $param_ty:ty),*) -> $ret_ty:ty {
          $(members { $($member:ident : Option<$member_ty:ty>),* })*
          $(params $params_body:block)*
          setup(& mut $self_setup:ident) $setup_body:block
          $(tear_down(&$self_td:ident) $tear_down_body:block)*
      } $($remainder:tt)*
    ) => {
        fixture!( $(#[$attr])* $name ($($param : $param_ty),*) -> $ret_ty {
              $(members { $($member : Option<$member_ty>),* })*
              $(params $params_body)*
              setup(& mut $self_setup) $setup_body
              $(tear_down(&$self_td) $tear_down_body)*
        });
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: test in test_suite
    ( @int $(#[$attr:meta])* test $name:ident ( $($fixture:ident $(($($expr:expr),*))*),* )
            $body:block
            $($remainder:tt)*
    ) => {
        test!( $(#[$attr])* $name | $($fixture $(($($expr),*))* ),* | $body);
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: arbitrary item in test suite
    ( @int $item:item
            $($remainder:tt)*
    ) => {
        $item
        __test_suite_int!(@int $($remainder)*);
    };

    // internal: empty test suite
    ( @int ) => { };
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]
//! **Smithay: the wayland compositor smithy**
//!
//! Most entry points in the modules can take an optionnal `slog::Logger` as argument
//! that will be used as a drain for logging. If `None` is provided, they'll log to `slog-stdlog`.

// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]

extern crate image;
#[macro_use]
extern crate nix;
#[macro_use]
extern crate rental;
extern crate tempfile;
extern crate wayland_protocols;
extern crate wayland_server;
extern crate xkbcommon;

#[cfg(feature = "backend_drm")]
extern crate drm;
#[cfg(feature = "backend_drm")]
extern crate gbm;
#[cfg(feature = "backend_libinput")]
extern crate input;
#[cfg(feature = "backend_udev")]
extern crate udev;
/*
#[cfg(feature = "backend_session_logind")]
extern crate dbus;
#[cfg(feature = "backend_session_logind")]
extern crate systemd;
*/
#[cfg(feature = "backend_winit")]
extern crate wayland_client;
#[cfg(feature = "backend_winit")]
extern crate winit;

extern crate libloading;

#[cfg(feature = "renderer_glium")]
extern crate glium;

#[macro_use]
extern crate slog;
extern crate slog_stdlog;

#[macro_use]
extern crate error_chain;

pub mod backend;
pub mod wayland;
pub mod utils;

fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger
where
    L: Into<Option<::slog::Logger>>,
{
    use slog::Drain;
    logger
        .into()
        .unwrap_or_else(|| ::slog::Logger::root(::slog_stdlog::StdLog.fuse(), o!()))
}
<commit_msg>Fix backend_session_udev without backend_udev<commit_after>#![warn(missing_docs)]
//! **Smithay: the wayland compositor smithy**
//!
//! Most entry points in the modules can take an optionnal `slog::Logger` as argument
//! that will be used as a drain for logging. If `None` is provided, they'll log to `slog-stdlog`.

// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]

extern crate image;
#[macro_use]
extern crate nix;
#[macro_use]
extern crate rental;
extern crate tempfile;
extern crate wayland_protocols;
extern crate wayland_server;
extern crate xkbcommon;

#[cfg(feature = "backend_drm")]
extern crate drm;
#[cfg(feature = "backend_drm")]
extern crate gbm;
#[cfg(feature = "backend_libinput")]
extern crate input;
#[cfg(feature = "udev")]
extern crate udev;
/*
#[cfg(feature = "backend_session_logind")]
extern crate dbus;
#[cfg(feature = "backend_session_logind")]
extern crate systemd;
*/
#[cfg(feature = "backend_winit")]
extern crate wayland_client;
#[cfg(feature = "backend_winit")]
extern crate winit;

extern crate libloading;

#[cfg(feature = "renderer_glium")]
extern crate glium;

#[macro_use]
extern crate slog;
extern crate slog_stdlog;

#[macro_use]
extern crate error_chain;

pub mod backend;
pub mod wayland;
pub mod utils;

fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger
where
    L: Into<Option<::slog::Logger>>,
{
    use slog::Drain;
    logger
        .into()
        .unwrap_or_else(|| ::slog::Logger::root(::slog_stdlog::StdLog.fuse(), o!()))
}
<|endoftext|>


<commit_before>#![crate_type = "cdylib"]

extern "C" {
    fn observe(ptr: *const u8, len: usize);

    fn get_u8() -> u8;
    fn get_i8() -> i8;
    fn get_u16() -> u16;
    fn get_i16() -> i16;
    fn get_u32() -> u32;
    fn get_i32() -> i32;
    fn get_u64() -> u64;
    fn get_i64() -> i64;
    fn get_usize() -> usize;
    fn get_isize() -> isize;
}

macro_rules! stringify {
    ( $($f:ident)* ) => {
        $(
            let s = $f().to_string();
            observe(s.as_ptr(), s.len());
        )*
    };
}

#[no_mangle]
pub unsafe extern "C" fn foo() {
    stringify!(get_u8);
    stringify!(get_i8);
    stringify!(get_u16);
    stringify!(get_i16);
    stringify!(get_u32);
    stringify!(get_i32);
    stringify!(get_u64);
    stringify!(get_i64);
    stringify!(get_usize);
    stringify!(get_isize);
}
<commit_msg>Don't shadow the provided `stringify!` macro in a wasm code size test case<commit_after>#![crate_type = "cdylib"]

extern "C" {
    fn observe(ptr: *const u8, len: usize);
}

macro_rules! s {
    ( $( $f:ident -> $t:ty );* $(;)* ) => {
        $(
            extern "C" {
                fn $f() -> $t;
            }
            let s = $f().to_string();
            observe(s.as_ptr(), s.len());
        )*
    };
}

#[no_mangle]
pub unsafe extern "C" fn foo() {
    s! {
        get_u8 -> u8;
        get_i8 -> i8;
        get_u16 -> u16;
        get_i16 -> i16;
        get_u32 -> u32;
        get_i32 -> i32;
        get_u64 -> u64;
        get_i64 -> i64;
        get_usize -> usize;
        get_isize -> isize;
    }
}
<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,ignore
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,ignore
//! let i: i32 = read!("The answer: {}!");
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::io::Read;
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<commit_msg>Ensure the doctests compile but skip running them<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::io::Read;
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<|endoftext|>


<commit_before>//! # Mime
//!
//! Mime is now Media Type, technically, but `Mime` is more immediately
//! understandable, so the main type here is `Mime`.
//!
//! ## What is Mime?
//!
//! Example mime string: `text/plain;charset=utf-8`
//!
//! ```rust
//! # use std::str::FromStr;
//! # use mime::Mime;
//! # use mime::TopLevel::Text;
//! # use mime::SubLevel::Plain;
//! # use mime::Attr::Charset;
//! # use mime::Value::Utf8;
//! let mime: Mime = FromStr::from_str("text/plain;charset=utf-8").unwrap();
//! assert_eq!(mime, Mime(Text, Plain, vec![(Charset, Utf8)]));
//! ```

#![doc(html_root_url = "http://hyperium.github.io/mime.rs")]
#![experimental]
#![feature(macro_rules, phase)]
#![deny(warnings)]

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate test;

use std::ascii::AsciiExt;
use std::fmt;
use std::str::FromStr;
use std::iter::Enumerate;
use std::str::Chars;

macro_rules! inspect(
    ($s:expr, $t:expr) => ({
        let t = $t;
        debug!("inspect {}: {}", $s, t);
        t
    })
);

/// Mime, or Media Type. Encapsulates common registers types.
///
/// Consider that a traditional mime type contains a "top level type",
/// a "sub level type", and 0-N "parameters". And they're all strings.
/// Strings everywhere. Strings mean typos. Rust has type safety. We should
/// use types!
///
/// So, Mime bundles together this data into types so the compiler can catch
/// your typos.
///
/// This improves things so you use match without Strings:
///
/// ```rust
/// use std::str::FromStr;
/// use mime::{Mime, TopLevel, SubLevel};
///
/// let mime: mime::Mime = FromStr::from_str("application/json").unwrap();
///
/// match mime {
///     Mime(TopLevel::Application, SubLevel::Json, _) => println!("matched json!"),
///     _ => ()
/// }
/// ```
#[derive(Clone, PartialEq)]
pub struct Mime(pub TopLevel, pub SubLevel, pub Vec<Param>);

macro_rules! enoom {
    (pub enum $en:ident; $ext:ident; $($ty:ident, $text:expr;)*) => (

        #[derive(Clone)]
        pub enum $en {
            $($ty),*,
            $ext(String)
        }

        impl PartialEq for $en {
            fn eq(&self, other: &$en) -> bool {
                match (self, other) {
                    $( (&$en::$ty, &$en::$ty) => true ),*,
                    (&$en::$ext(ref a), &$en::$ext(ref b)) => a == b,
                    _ => self.to_string() == other.to_string()
                }
            }
        }

        impl fmt::Show for $en {
            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $($en::$ty => $text),*,
                    $en::$ext(ref s) => return s.fmt(fmt)
                }.fmt(fmt)
            }
        }

        impl FromStr for $en {
            fn from_str(s: &str) -> Option<$en> {
                Some(match s {
                    $(_s if _s == $text => $en::$ty),*,
                    s => $en::$ext(inspect!(stringify!($ext), s).to_string())
                })
            }
        }
    )
}

enoom! {
    pub enum TopLevel;
    Ext;
    Star, "*";
    Text, "text";
    Image, "image";
    Audio, "audio";
    Video, "video";
    Application, "application";
    Multipart, "multipart";
    Message, "message";
    Model, "model";
}

enoom! {
    pub enum SubLevel;
    Ext;
    Star, "*";

    // common text/*
    Plain, "plain";
    Html, "html";
    Xml, "xml";
    Javascript, "javascript";
    Css, "css";

    // common application/*
    Json, "json";
    WwwFormUrlEncoded, "x-www-form-urlencoded";

    // multipart/*
    FormData, "form-data";

    // common image/*
    Png, "png";
    Gif, "gif";
    Bmp, "bmp";
    Jpeg, "jpeg";
}

enoom! {
    pub enum Attr;
    Ext;
    Charset, "charset";
    Q, "q";
}

enoom! {
    pub enum Value;
    Ext;
    Utf8, "utf-8";
}

pub type Param = (Attr, Value);

impl fmt::Show for Mime {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Mime(ref top, ref sub, ref params) = *self;
        try!(write!(fmt, "{}/{}", top, sub));
        fmt_params(params.as_slice(), fmt)
    }
}

impl FromStr for Mime {
    fn from_str(raw: &str) -> Option<Mime> {
        let ascii = raw.to_ascii_lowercase(); // lifetimes :(
        let raw = ascii.as_slice();
        let len = raw.len();
        let mut iter = raw.chars().enumerate();
        let mut params = vec![];
        // toplevel
        let mut start;
        let mut top;
        loop {
            match inspect!("top iter", iter.next()) {
                Some((0, c)) if is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > 0 && is_restricted_name_char(c) => (),
                Some((i, '/')) if i > 0 => match FromStr::from_str(raw.slice_to(i)) {
                    Some(t) => {
                        top = t;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                _ => return None // EOF and no toplevel is no Mime
            };

        }

        // sublevel
        let mut sub;
        loop {
            match inspect!("sub iter", iter.next()) {
                Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > start && is_restricted_name_char(c) => (),
                Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                    Some(s) => {
                        sub = s;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                None => match FromStr::from_str(raw.slice_from(start)) {
                    Some(s) => return Some(Mime(top, s, params)),
                    None => return None
                },
                _ => return None
            };
        }

        // params
        debug!("starting params, len={}", len);
        loop {
            match inspect!("param", param_from_str(raw, &mut iter, start)) {
                Some((p, end)) => {
                    params.push(p);
                    start = end;
                    if start >= len {
                        break;
                    }
                }
                None => break
            }
        }

        Some(Mime(top, sub, params))
    }
}

fn param_from_str(raw: &str, iter: &mut Enumerate<Chars>, mut start: uint) -> Option<(Param, uint)> {
    let mut attr;
    debug!("param_from_str, start={}", start);
    loop {
        match inspect!("attr iter", iter.next()) {
            Some((i, ' ')) if i == start => start = i + 1,
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, c)) if i > start && is_restricted_name_char(c) => (),
            Some((i, '=')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(a) => {
                    attr = inspect!("attr", a);
                    start = i + 1;
                    break;
                },
                None => return None
            },
            _ => return None
        }
    }
    let mut value;
    // values must be restrict-name-char or "anything goes"
    let mut is_quoted = false;
    loop {
        match inspect!("value iter", iter.next()) {
            Some((i, '"')) if i == start => {
                debug!("quoted");
                is_quoted = true;
                start = i + 1;
            },
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, '"')) if i > start && is_quoted => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            Some((i, c)) if i > start && is_quoted || is_restricted_name_char(c) => (),
            Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            None => match FromStr::from_str(raw.slice_from(start)) {
                Some(v) => {
                    value = v;
                    start = raw.len();
                    break;
                },
                None => return None
            },

            _ => return None
        }
    }

    Some(((attr, value), start))
}

// From [RFC6838](http://tools.ietf.org/html/rfc6838#section-4.2):
//
// > All registered media types MUST be assigned top-level type and
// > subtype names.  The combination of these names serves to uniquely
// > identify the media type, and the subtype name facet (or the absence
// > of one) identifies the registration tree.  Both top-level type and
// > subtype names are case-insensitive.
// >
// > Type and subtype names MUST conform to the following ABNF:
// >
// >     type-name = restricted-name
// >     subtype-name = restricted-name
// >
// >     restricted-name = restricted-name-first *126restricted-name-chars
// >     restricted-name-first  = ALPHA / DIGIT
// >     restricted-name-chars  = ALPHA / DIGIT / "!" / "#" /
// >                              "$" / "&" / "-" / "^" / "_"
// >     restricted-name-chars =/ "." ; Characters before first dot always
// >                                  ; specify a facet name
// >     restricted-name-chars =/ "+" ; Characters after last plus always
// >                                  ; specify a structured syntax suffix
//
fn is_restricted_name_first_char(c: char) -> bool {
    match c {
        'a'...'z' |
        '0'...'9' => true,
        _ => false
    }
}

fn is_restricted_name_char(c: char) -> bool {
    if is_restricted_name_first_char(c) {
        true
    } else {
        match c {
            '!' |
            '#' |
            '$' |
            '&' |
            '-' |
            '^' |
            '.' |
            '+' |
            '_' => true,
            _ => false
        }
    }
}

#[inline]
fn fmt_params<T: AsSlice<Param>>(params: T, fmt: &mut fmt::Formatter) -> fmt::Result {
    for param in params.as_slice().iter() {
        try!(fmt_param(param, fmt));
    }
    Ok(())
}

#[inline]
fn fmt_param(param: &Param, fmt: &mut fmt::Formatter) -> fmt::Result {
    let (ref attr, ref value) = *param;
    write!(fmt, "; {}={}", attr, value)
}

#[cfg(test)]
mod tests {
    use std::str::{FromStr, from_str};
    use test::Bencher;
    use super::{TopLevel, SubLevel, Attr, Value, Mime};

    #[test]
    fn test_mime_show() {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![]);
        assert_eq!(mime.to_string(), "text/plain".to_string());
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]);
        assert_eq!(mime.to_string(), "text/plain; charset=utf-8".to_string());
    }

    #[test]
    fn test_mime_from_str() {
        assert_eq!(FromStr::from_str("text/plain"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("TEXT/PLAIN"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain;charset=\"utf-8\""), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8; foo=bar"),
            Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8),
                                        (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string())) ])));
    }

    #[bench]
    fn bench_show(b: &mut Bencher) {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8), (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string()))]);
        b.bytes = mime.to_string().as_bytes().len() as u64;
        b.iter(|| mime.to_string())
    }

    #[bench]
    fn bench_from_str(b: &mut Bencher) {
        let s = "text/plain; charset=utf-8; foo=bar";
        b.bytes = s.as_bytes().len() as u64;
        b.iter(|| s.parse::<Mime>())
    }
}
<commit_msg>rustupgrade<commit_after>//! # Mime
//!
//! Mime is now Media Type, technically, but `Mime` is more immediately
//! understandable, so the main type here is `Mime`.
//!
//! ## What is Mime?
//!
//! Example mime string: `text/plain;charset=utf-8`
//!
//! ```rust
//! # use mime::Mime;
//! # use mime::TopLevel::Text;
//! # use mime::SubLevel::Plain;
//! # use mime::Attr::Charset;
//! # use mime::Value::Utf8;
//! let mime: Mime = "text/plain;charset=utf-8".parse().unwrap();
//! assert_eq!(mime, Mime(Text, Plain, vec![(Charset, Utf8)]));
//! ```

#![doc(html_root_url = "http://hyperium.github.io/mime.rs")]
#![experimental]
#![feature(macro_rules, phase)]
#![deny(warnings)]

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate test;

use std::ascii::AsciiExt;
use std::fmt;
use std::str::FromStr;
use std::iter::Enumerate;
use std::str::Chars;

macro_rules! inspect(
    ($s:expr, $t:expr) => ({
        let t = $t;
        debug!("inspect {}: {}", $s, t);
        t
    })
);

/// Mime, or Media Type. Encapsulates common registers types.
///
/// Consider that a traditional mime type contains a "top level type",
/// a "sub level type", and 0-N "parameters". And they're all strings.
/// Strings everywhere. Strings mean typos. Rust has type safety. We should
/// use types!
///
/// So, Mime bundles together this data into types so the compiler can catch
/// your typos.
///
/// This improves things so you use match without Strings:
///
/// ```rust
/// use mime::{Mime, TopLevel, SubLevel};
///
/// let mime: mime::Mime = "application/json".parse().unwrap();
///
/// match mime {
///     Mime(TopLevel::Application, SubLevel::Json, _) => println!("matched json!"),
///     _ => ()
/// }
/// ```
#[derive(Clone, PartialEq)]
pub struct Mime(pub TopLevel, pub SubLevel, pub Vec<Param>);

macro_rules! enoom {
    (pub enum $en:ident; $ext:ident; $($ty:ident, $text:expr;)*) => (

        #[derive(Clone)]
        pub enum $en {
            $($ty),*,
            $ext(String)
        }

        impl PartialEq for $en {
            fn eq(&self, other: &$en) -> bool {
                match (self, other) {
                    $( (&$en::$ty, &$en::$ty) => true ),*,
                    (&$en::$ext(ref a), &$en::$ext(ref b)) => a == b,
                    _ => self.to_string() == other.to_string()
                }
            }
        }

        impl fmt::Show for $en {
            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $($en::$ty => $text),*,
                    $en::$ext(ref s) => return s.fmt(fmt)
                }.fmt(fmt)
            }
        }

        impl FromStr for $en {
            fn from_str(s: &str) -> Option<$en> {
                Some(match s {
                    $(_s if _s == $text => $en::$ty),*,
                    s => $en::$ext(inspect!(stringify!($ext), s).to_string())
                })
            }
        }
    )
}

enoom! {
    pub enum TopLevel;
    Ext;
    Star, "*";
    Text, "text";
    Image, "image";
    Audio, "audio";
    Video, "video";
    Application, "application";
    Multipart, "multipart";
    Message, "message";
    Model, "model";
}

enoom! {
    pub enum SubLevel;
    Ext;
    Star, "*";

    // common text/*
    Plain, "plain";
    Html, "html";
    Xml, "xml";
    Javascript, "javascript";
    Css, "css";

    // common application/*
    Json, "json";
    WwwFormUrlEncoded, "x-www-form-urlencoded";

    // multipart/*
    FormData, "form-data";

    // common image/*
    Png, "png";
    Gif, "gif";
    Bmp, "bmp";
    Jpeg, "jpeg";
}

enoom! {
    pub enum Attr;
    Ext;
    Charset, "charset";
    Q, "q";
}

enoom! {
    pub enum Value;
    Ext;
    Utf8, "utf-8";
}

pub type Param = (Attr, Value);

impl fmt::Show for Mime {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Mime(ref top, ref sub, ref params) = *self;
        try!(write!(fmt, "{}/{}", top, sub));
        fmt_params(params.as_slice(), fmt)
    }
}

impl FromStr for Mime {
    fn from_str(raw: &str) -> Option<Mime> {
        let ascii = raw.to_ascii_lowercase(); // lifetimes :(
        let raw = ascii.as_slice();
        let len = raw.len();
        let mut iter = raw.chars().enumerate();
        let mut params = vec![];
        // toplevel
        let mut start;
        let mut top;
        loop {
            match inspect!("top iter", iter.next()) {
                Some((0, c)) if is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > 0 && is_restricted_name_char(c) => (),
                Some((i, '/')) if i > 0 => match FromStr::from_str(raw.slice_to(i)) {
                    Some(t) => {
                        top = t;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                _ => return None // EOF and no toplevel is no Mime
            };

        }

        // sublevel
        let mut sub;
        loop {
            match inspect!("sub iter", iter.next()) {
                Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
                Some((i, c)) if i > start && is_restricted_name_char(c) => (),
                Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                    Some(s) => {
                        sub = s;
                        start = i + 1;
                        break;
                    }
                    None => return None
                },
                None => match FromStr::from_str(raw.slice_from(start)) {
                    Some(s) => return Some(Mime(top, s, params)),
                    None => return None
                },
                _ => return None
            };
        }

        // params
        debug!("starting params, len={}", len);
        loop {
            match inspect!("param", param_from_str(raw, &mut iter, start)) {
                Some((p, end)) => {
                    params.push(p);
                    start = end;
                    if start >= len {
                        break;
                    }
                }
                None => break
            }
        }

        Some(Mime(top, sub, params))
    }
}

fn param_from_str(raw: &str, iter: &mut Enumerate<Chars>, mut start: uint) -> Option<(Param, uint)> {
    let mut attr;
    debug!("param_from_str, start={}", start);
    loop {
        match inspect!("attr iter", iter.next()) {
            Some((i, ' ')) if i == start => start = i + 1,
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, c)) if i > start && is_restricted_name_char(c) => (),
            Some((i, '=')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(a) => {
                    attr = inspect!("attr", a);
                    start = i + 1;
                    break;
                },
                None => return None
            },
            _ => return None
        }
    }
    let mut value;
    // values must be restrict-name-char or "anything goes"
    let mut is_quoted = false;
    loop {
        match inspect!("value iter", iter.next()) {
            Some((i, '"')) if i == start => {
                debug!("quoted");
                is_quoted = true;
                start = i + 1;
            },
            Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
            Some((i, '"')) if i > start && is_quoted => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            Some((i, c)) if i > start && is_quoted || is_restricted_name_char(c) => (),
            Some((i, ';')) if i > start => match FromStr::from_str(raw.slice(start, i)) {
                Some(v) => {
                    value = v;
                    start = i + 1;
                    break;
                },
                None => return None
            },
            None => match FromStr::from_str(raw.slice_from(start)) {
                Some(v) => {
                    value = v;
                    start = raw.len();
                    break;
                },
                None => return None
            },

            _ => return None
        }
    }

    Some(((attr, value), start))
}

// From [RFC6838](http://tools.ietf.org/html/rfc6838#section-4.2):
//
// > All registered media types MUST be assigned top-level type and
// > subtype names.  The combination of these names serves to uniquely
// > identify the media type, and the subtype name facet (or the absence
// > of one) identifies the registration tree.  Both top-level type and
// > subtype names are case-insensitive.
// >
// > Type and subtype names MUST conform to the following ABNF:
// >
// >     type-name = restricted-name
// >     subtype-name = restricted-name
// >
// >     restricted-name = restricted-name-first *126restricted-name-chars
// >     restricted-name-first  = ALPHA / DIGIT
// >     restricted-name-chars  = ALPHA / DIGIT / "!" / "#" /
// >                              "$" / "&" / "-" / "^" / "_"
// >     restricted-name-chars =/ "." ; Characters before first dot always
// >                                  ; specify a facet name
// >     restricted-name-chars =/ "+" ; Characters after last plus always
// >                                  ; specify a structured syntax suffix
//
fn is_restricted_name_first_char(c: char) -> bool {
    match c {
        'a'...'z' |
        '0'...'9' => true,
        _ => false
    }
}

fn is_restricted_name_char(c: char) -> bool {
    if is_restricted_name_first_char(c) {
        true
    } else {
        match c {
            '!' |
            '#' |
            '$' |
            '&' |
            '-' |
            '^' |
            '.' |
            '+' |
            '_' => true,
            _ => false
        }
    }
}

#[inline]
fn fmt_params<T: AsSlice<Param>>(params: T, fmt: &mut fmt::Formatter) -> fmt::Result {
    for param in params.as_slice().iter() {
        try!(fmt_param(param, fmt));
    }
    Ok(())
}

#[inline]
fn fmt_param(param: &Param, fmt: &mut fmt::Formatter) -> fmt::Result {
    let (ref attr, ref value) = *param;
    write!(fmt, "; {}={}", attr, value)
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;
    use test::Bencher;
    use super::{TopLevel, SubLevel, Attr, Value, Mime};

    #[test]
    fn test_mime_show() {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![]);
        assert_eq!(mime.to_string(), "text/plain".to_string());
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]);
        assert_eq!(mime.to_string(), "text/plain; charset=utf-8".to_string());
    }

    #[test]
    fn test_mime_from_str() {
        assert_eq!(FromStr::from_str("text/plain"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("TEXT/PLAIN"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8"), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain;charset=\"utf-8\""), Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])));
        assert_eq!(FromStr::from_str("text/plain; charset=utf-8; foo=bar"),
            Some(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8),
                                        (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string())) ])));
    }

    #[bench]
    fn bench_show(b: &mut Bencher) {
        let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8), (Attr::Ext("foo".to_string()), Value::Ext("bar".to_string()))]);
        b.bytes = mime.to_string().as_bytes().len() as u64;
        b.iter(|| mime.to_string())
    }

    #[bench]
    fn bench_from_str(b: &mut Bencher) {
        let s = "text/plain; charset=utf-8; foo=bar";
        b.bytes = s.as_bytes().len() as u64;
        b.iter(|| s.parse::<Mime>())
    }
}
<|endoftext|>


<commit_before>//! Rust bindings to libbitcoinconsensus
//!
//! ```rust
//! extern crate bitcoin_consensus;
//! extern crate hex;
//!
//! use hex::FromHex;
//! use bitcoin_consensus::{verify_script, ScriptVerificationFlags};
//!
//! fn main() {
//!     let pubkey: Vec<u8> = Vec::from_hex("76a9144621d47f08fcb1e6be0b91144202de7a186deade88ac").unwrap();
//!     let tx: Vec<u8> = Vec::from_hex("01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a4730440220340f35055aceb14250e4954b23743332f671eb803263f363d1d7272f1d487209022037a0eaf7cb73897ba9069fc538e7275c5ae188e934ae47ca4a70453b64fc836401210234257444bd3aead2b851bda4288d60abe34095a2a8d49aff1d4d19773d22b32cffffffff01a0860100000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000").unwrap();
//!     match verify_script(&pubkey, &tx, 0, ScriptVerificationFlags::empty()) {
//!         Ok(_) => println!("transaction verified"),
//!         Err(e) => panic!("transaction did not verify: {:?}", e)
//!     }
//! }
//! ```

// Copyright 2017 Jasper Bryant-Greene
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use] extern crate bitflags;

extern {
    fn bitcoinconsensus_verify_script(script_pub_key: *const u8, script_pub_key_len: u16, tx_to: *const u8, tx_to_len: u16, n_in: u16, flags: u16, error: *mut u16) -> u16;
    fn bitcoinconsensus_verify_script_with_amount(script_pub_key: *const u8, script_pub_key_len: u16, amount: i64, tx_to: *const u8, tx_to_len: u16, n_in: u16, flags: u16, error: *mut u16) -> u16;
    fn bitcoinconsensus_version() -> u16;
}

#[derive(Debug)]
pub enum ScriptVerificationError {
    TxIndexError,
    TxSizeMismatch,
    TxDeserializeError,
    AmountRequired,
    InvalidFlags,
    UnknownError(u16)
}

bitflags! {
    pub struct ScriptVerificationFlags: u16 {
        const VERIFY_P2SH = 1;
        const VERIFY_DER_SIG = (1 << 2);
        const VERIFY_NULL_DUMMY = (1 << 4);
        const VERIFY_CHECK_LOCK_TIME = (1 << 9);
        const VERIFY_CHECK_SEQUENCE = (1 << 10);
        const VERIFY_WITNESS = (1 << 11);
    }
}

fn map_error(err: u16) -> ScriptVerificationError {
    match err {
        1 => ScriptVerificationError::TxIndexError,
        2 => ScriptVerificationError::TxSizeMismatch,
        3 => ScriptVerificationError::TxDeserializeError,
        4 => ScriptVerificationError::AmountRequired,
        5 => ScriptVerificationError::InvalidFlags,
        _ => ScriptVerificationError::UnknownError(err)
    }
}

/// Verify that the transaction input correctly spends the previous output, considering any
/// additional constraints specified by flags.
pub fn verify_script(pub_key: &[u8], tx: &[u8], input: u16, flags: ScriptVerificationFlags) -> Result<(), ScriptVerificationError> {
    unsafe {
        let mut err: u16 = 0;
        let res = bitcoinconsensus_verify_script(pub_key.as_ptr(), pub_key.len() as u16, tx.as_ptr(), tx.len() as u16, input, flags.bits, &mut err as *mut u16);
        if res == 1 { Ok(()) } else { Err(map_error(err)) }
    }
}

/// Verify that the transaction input correctly spends the previous output, considering any
/// additional constraints specified by flags.
pub fn verify_script_with_amount(pub_key: &[u8], amount: i64, tx: &[u8], input: u16, flags: ScriptVerificationFlags) -> Result<(), ScriptVerificationError> {
    unsafe {
        let mut err: u16 = 0;
        let res = bitcoinconsensus_verify_script_with_amount(pub_key.as_ptr(), pub_key.len() as u16, amount, tx.as_ptr(), tx.len() as u16, input, flags.bits, &mut err as *mut u16);
        if res == 1 { Ok(()) } else { Err(map_error(err)) }
    }
}

/// Return the linked version of libbitcoinconsensus.
pub fn version() -> u16 {
    unsafe {
        bitcoinconsensus_version()
    }
}
<commit_msg>re-introduce link macro<commit_after>//! Rust bindings to libbitcoinconsensus
//!
//! ```rust
//! extern crate bitcoin_consensus;
//! extern crate hex;
//!
//! use hex::FromHex;
//! use bitcoin_consensus::{verify_script, ScriptVerificationFlags};
//!
//! fn main() {
//!     let pubkey: Vec<u8> = Vec::from_hex("76a9144621d47f08fcb1e6be0b91144202de7a186deade88ac").unwrap();
//!     let tx: Vec<u8> = Vec::from_hex("01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a4730440220340f35055aceb14250e4954b23743332f671eb803263f363d1d7272f1d487209022037a0eaf7cb73897ba9069fc538e7275c5ae188e934ae47ca4a70453b64fc836401210234257444bd3aead2b851bda4288d60abe34095a2a8d49aff1d4d19773d22b32cffffffff01a0860100000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000").unwrap();
//!     match verify_script(&pubkey, &tx, 0, ScriptVerificationFlags::empty()) {
//!         Ok(_) => println!("transaction verified"),
//!         Err(e) => panic!("transaction did not verify: {:?}", e)
//!     }
//! }
//! ```

// Copyright 2017 Jasper Bryant-Greene
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use] extern crate bitflags;

#[link(name="bitcoinconsensus")]
extern {
    fn bitcoinconsensus_verify_script(script_pub_key: *const u8, script_pub_key_len: u16, tx_to: *const u8, tx_to_len: u16, n_in: u16, flags: u16, error: *mut u16) -> u16;
    fn bitcoinconsensus_verify_script_with_amount(script_pub_key: *const u8, script_pub_key_len: u16, amount: i64, tx_to: *const u8, tx_to_len: u16, n_in: u16, flags: u16, error: *mut u16) -> u16;
    fn bitcoinconsensus_version() -> u16;
}

#[derive(Debug)]
pub enum ScriptVerificationError {
    TxIndexError,
    TxSizeMismatch,
    TxDeserializeError,
    AmountRequired,
    InvalidFlags,
    UnknownError(u16)
}

bitflags! {
    pub struct ScriptVerificationFlags: u16 {
        const VERIFY_P2SH = 1;
        const VERIFY_DER_SIG = (1 << 2);
        const VERIFY_NULL_DUMMY = (1 << 4);
        const VERIFY_CHECK_LOCK_TIME = (1 << 9);
        const VERIFY_CHECK_SEQUENCE = (1 << 10);
        const VERIFY_WITNESS = (1 << 11);
    }
}

fn map_error(err: u16) -> ScriptVerificationError {
    match err {
        1 => ScriptVerificationError::TxIndexError,
        2 => ScriptVerificationError::TxSizeMismatch,
        3 => ScriptVerificationError::TxDeserializeError,
        4 => ScriptVerificationError::AmountRequired,
        5 => ScriptVerificationError::InvalidFlags,
        _ => ScriptVerificationError::UnknownError(err)
    }
}

/// Verify that the transaction input correctly spends the previous output, considering any
/// additional constraints specified by flags.
pub fn verify_script(pub_key: &[u8], tx: &[u8], input: u16, flags: ScriptVerificationFlags) -> Result<(), ScriptVerificationError> {
    unsafe {
        let mut err: u16 = 0;
        let res = bitcoinconsensus_verify_script(pub_key.as_ptr(), pub_key.len() as u16, tx.as_ptr(), tx.len() as u16, input, flags.bits, &mut err as *mut u16);
        if res == 1 { Ok(()) } else { Err(map_error(err)) }
    }
}

/// Verify that the transaction input correctly spends the previous output, considering any
/// additional constraints specified by flags.
pub fn verify_script_with_amount(pub_key: &[u8], amount: i64, tx: &[u8], input: u16, flags: ScriptVerificationFlags) -> Result<(), ScriptVerificationError> {
    unsafe {
        let mut err: u16 = 0;
        let res = bitcoinconsensus_verify_script_with_amount(pub_key.as_ptr(), pub_key.len() as u16, amount, tx.as_ptr(), tx.len() as u16, input, flags.bits, &mut err as *mut u16);
        if res == 1 { Ok(()) } else { Err(map_error(err)) }
    }
}

/// Return the linked version of libbitcoinconsensus.
pub fn version() -> u16 {
    unsafe {
        bitcoinconsensus_version()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::CString;
mod postgres;

use postgres::{LogicalDecodingContext, OutputPluginOptions, OUTPUT_PLUGIN_TEXTUAL_OUTPUT};

extern {
  fn OutputPluginPrepareWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn OutputPluginWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn appendStringInfoString(str: *mut postgres::Struct_StringInfoData, s: *const i8);
}

pub struct DontTouch;

#[no_mangle]
pub extern fn pg_decode_startup(ctx: &LogicalDecodingContext, opt: &mut OutputPluginOptions, is_init: bool) {
	opt.output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

#[no_mangle]
pub extern fn pg_decode_change(ctx: &LogicalDecodingContext, a: &DontTouch, b: &DontTouch, c: &DontTouch) {
    let to_print = &b"Hello, world! -- rust"[..];
    let c_to_print = CString::new(to_print).unwrap();

    unsafe {
	  OutputPluginPrepareWrite(ctx, true);
      appendStringInfoString(ctx.out, c_to_print.as_ptr());
	  OutputPluginWrite(ctx, true);
    }
}

#[no_mangle]
pub extern fn pg_decode_commit_txn(ctx: &LogicalDecodingContext, txn: &DontTouch, commit_lsn: u64) {
}

#[no_mangle]
pub extern fn pg_decode_begin_txn(ctx: &LogicalDecodingContext, txn: &DontTouch) {
}

#[no_mangle]
pub extern fn pg_decode_shutdown(ctx: &LogicalDecodingContext) {
}
<commit_msg>Turns of tons of Rust linter warnings<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

extern crate libc;

use std::ffi::CString;
mod postgres;

use postgres::{LogicalDecodingContext, OutputPluginOptions, OUTPUT_PLUGIN_TEXTUAL_OUTPUT};

extern {
  fn OutputPluginPrepareWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn OutputPluginWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn appendStringInfoString(str: *mut postgres::Struct_StringInfoData, s: *const i8);
}

pub struct DontTouch;

#[no_mangle]
pub extern fn pg_decode_startup(ctx: &LogicalDecodingContext, opt: &mut OutputPluginOptions, is_init: bool) {
	opt.output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

#[no_mangle]
pub extern fn pg_decode_change(ctx: &LogicalDecodingContext, a: &DontTouch, b: &DontTouch, c: &DontTouch) {
    let to_print = &b"OMG, world! -- rust"[..];
    let c_to_print = CString::new(to_print).unwrap();

    unsafe {
	  OutputPluginPrepareWrite(ctx, true);
      appendStringInfoString(ctx.out, c_to_print.as_ptr());
	  OutputPluginWrite(ctx, true);
    }
}

#[no_mangle]
pub extern fn pg_decode_commit_txn(ctx: &LogicalDecodingContext, txn: &DontTouch, commit_lsn: u64) {
}

#[no_mangle]
pub extern fn pg_decode_begin_txn(ctx: &LogicalDecodingContext, txn: &DontTouch) {
}

#[no_mangle]
pub extern fn pg_decode_shutdown(ctx: &LogicalDecodingContext) {
}
<|endoftext|>