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

/*! Non-blocking access to stdin, stdout, and stderr.

This module provides bindings to the local event loop's TTY interface, using it
to offer synchronous but non-blocking versions of stdio. These handles can be
inspected for information about terminal dimensions or for related information
about the stream or terminal to which it is attached.

# Example

```rust
# #![allow(unused_must_use)]
use std::io;

let mut out = io::stdout();
out.write(b"Hello, world!");
```

*/

use failure::local_stderr;
use fmt;
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
         standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
use iter::Iterator;
use kinds::Send;
use libc;
use option::{Option, Some, None};
use boxed::Box;
use result::{Ok, Err};
use rt;
use rt::local::Local;
use rt::task::Task;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
use slice::ImmutableSlice;
use str::StrSlice;
use uint;

// And so begins the tale of acquiring a uv handle to a stdio stream on all
// platforms in all situations. Our story begins by splitting the world into two
// categories, windows and unix. Then one day the creators of unix said let
// there be redirection! And henceforth there was redirection away from the
// console for standard I/O streams.
//
// After this day, the world split into four factions:
//
// 1. Unix with stdout on a terminal.
// 2. Unix with stdout redirected.
// 3. Windows with stdout on a terminal.
// 4. Windows with stdout redirected.
//
// Many years passed, and then one day the nation of libuv decided to unify this
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
// These three ideas propagated throughout the lands and the four great factions
// decided to settle among them.
//
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
// doing so, they even enhanced themselves further then their Pipe/File
// brethren, becoming the dominant powers.
//
// The group of 4, however, decided to work independently. They abandoned the
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
// The members of the 4th faction decided to only align themselves with File.
//
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
//        case pipe also doesn't work, but magically file does!
enum StdSource {
    TTY(Box<RtioTTY + Send>),
    File(Box<RtioFileStream + Send>),
}

fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
    LocalIo::maybe_raise(|io| {
        Ok(match io.tty_open(fd, readable) {
            Ok(tty) => f(TTY(tty)),
            Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
        })
    }).map_err(IoError::from_rtio_error).unwrap()
}

local_data_key!(local_stdout: Box<Writer + Send>)

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// The returned handled is buffered by default with a `BufferedReader`. If
/// buffered access is not desired, the `stdin_raw` function is provided to
/// provided unbuffered access to stdin.
///
/// Care should be taken when creating multiple handles to the stdin of a
/// process. Because this is a buffered reader by default, it's possible for
/// pending input to be unconsumed in one reader and unavailable to other
/// readers. It is recommended that only one handle at a time is created for the
/// stdin of a process.
///
/// See `stdout()` for more notes about this function.
pub fn stdin() -> BufferedReader<StdReader> {
    // The default buffer capacity is 64k, but apparently windows doesn't like
    // 64k reads on stdin. See #13304 for details, but the idea is that on
    // windows we use a slightly smaller buffer that's been seen to be
    // acceptable.
    if cfg!(windows) {
        BufferedReader::with_capacity(8 * 1024, stdin_raw())
    } else {
        BufferedReader::new(stdin_raw())
    }
}

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// Unlike `stdin()`, the returned reader is *not* a buffered reader.
///
/// See `stdout()` for more notes about this function.
pub fn stdin_raw() -> StdReader {
    src(libc::STDIN_FILENO, true, |src| StdReader { inner: src })
}

/// Creates a line-buffered handle to the stdout of the current process.
///
/// Note that this is a fairly expensive operation in that at least one memory
/// allocation is performed. Additionally, this must be called from a runtime
/// task context because the stream returned will be a non-blocking object using
/// the local scheduler to perform the I/O.
///
/// Care should be taken when creating multiple handles to an output stream for
/// a single process. While usage is still safe, the output may be surprising if
/// no synchronization is performed to ensure a sane output.
pub fn stdout() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stdout_raw())
}

/// Creates an unbuffered handle to the stdout of the current process
///
/// See notes in `stdout()` for more information.
pub fn stdout_raw() -> StdWriter {
    src(libc::STDOUT_FILENO, false, |src| StdWriter { inner: src })
}

/// Creates a line-buffered handle to the stderr of the current process.
///
/// See `stdout()` for notes about this function.
pub fn stderr() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stderr_raw())
}

/// Creates an unbuffered handle to the stderr of the current process
///
/// See notes in `stdout()` for more information.
pub fn stderr_raw() -> StdWriter {
    src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stdout.replace(Some(stdout)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

/// Resets the task-local stderr handle to the specified writer
///
/// This will replace the current task's stderr handle, returning the old
/// handle. Currently, the stderr handle is used for printing failure messages
/// during task failure.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stderr.replace(Some(stderr)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

// Helper to access the local task's stdout handle
//
// Note that this is not a safe function to expose because you can create an
// aliased pointer very easily:
//
//  with_task_stdout(|io1| {
//      with_task_stdout(|io2| {
//          // io1 aliases io2
//      })
//  })
fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
    let result = if Local::exists(None::<Task>) {
        let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
            box stdout() as Box<Writer + Send>
        });
        let result = f(my_stdout);
        local_stdout.replace(Some(my_stdout));
        result
    } else {
        let mut io = rt::Stdout;
        f(&mut io as &mut Writer)
    };
    match result {
        Ok(()) => {}
        Err(e) => fail!("failed printing to stdout: {}", e),
    }
}

/// Flushes the local task's stdout handle.
///
/// By default, this stream is a line-buffering stream, so flushing may be
/// necessary to ensure that all output is printed to the screen (if there are
/// no newlines printed).
///
/// Note that logging macros do not use this stream. Using the logging macros
/// will emit output to stderr, and while they are line buffered the log
/// messages are always terminated in a newline (no need to flush).
pub fn flush() {
    with_task_stdout(|io| io.flush())
}

/// Prints a string to the stdout of the current process. No newline is emitted
/// after the string is printed.
pub fn print(s: &str) {
    with_task_stdout(|io| io.write(s.as_bytes()))
}

/// Prints a string to the stdout of the current process. A literal
/// `\n` character is printed to the console after the string.
pub fn println(s: &str) {
    with_task_stdout(|io| {
        io.write(s.as_bytes()).and_then(|()| io.write([b'\n']))
    })
}

/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
/// with the `format_args!` macro.
pub fn print_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| write!(io, "{}", fmt))
}

/// Similar to `println`, but takes a `fmt::Arguments` structure to be
/// compatible with the `format_args!` macro.
pub fn println_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| writeln!(io, "{}", fmt))
}

/// Representation of a reader of a standard input stream
pub struct StdReader {
    inner: StdSource
}

impl StdReader {
    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Reader for StdReader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let ret = match self.inner {
            TTY(ref mut tty) => {
                // Flush the task-local stdout so that weird issues like a
                // print!'d prompt not being shown until after the user hits
                // enter.
                flush();
                tty.read(buf)
            },
            File(ref mut file) => file.read(buf).map(|i| i as uint),
        }.map_err(IoError::from_rtio_error);
        match ret {
            // When reading a piped stdin, libuv will return 0-length reads when
            // stdin reaches EOF. For pretty much all other streams it will
            // return an actual EOF error, but apparently for stdin it's a
            // little different. Hence, here we convert a 0 length read to an
            // end-of-file indicator so the caller knows to stop reading.
            Ok(0) => { Err(standard_error(EndOfFile)) }
            ret @ Ok(..) | ret @ Err(..) => ret,
        }
    }
}

/// Representation of a writer to a standard output stream
pub struct StdWriter {
    inner: StdSource
}

impl StdWriter {
    /// Gets the size of this output window, if possible. This is typically used
    /// when the writer is attached to something like a terminal, this is used
    /// to fetch the dimensions of the terminal.
    ///
    /// If successful, returns `Ok((width, height))`.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn winsize(&mut self) -> IoResult<(int, int)> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.get_winsize().map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Controls whether this output stream is a "raw stream" or simply a normal
    /// stream.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.set_raw(raw).map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Writer for StdWriter {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        // As with stdin on windows, stdout often can't handle writes of large
        // sizes. For an example, see #14940. For this reason, chunk the output
        // buffer on windows, but on unix we can just write the whole buffer all
        // at once.
        let max_size = if cfg!(windows) {64 * 1024} else {uint::MAX};
        for chunk in buf.chunks(max_size) {
            try!(match self.inner {
                TTY(ref mut tty) => tty.write(chunk),
                File(ref mut file) => file.write(chunk),
            }.map_err(IoError::from_rtio_error))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    iotest!(fn smoke() {
        // Just make sure we can acquire handles
        stdin();
        stdout();
        stderr();
    })

    iotest!(fn capture_stdout() {
        use io::{ChanReader, ChanWriter};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            set_stdout(box w);
            println!("hello!");
        });
        assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
    })

    iotest!(fn capture_stderr() {
        use realstd::comm::channel;
        use realstd::io::{Writer, ChanReader, ChanWriter, Reader};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            ::realstd::io::stdio::set_stderr(box w);
            fail!("my special message");
        });
        let s = r.read_to_string().unwrap();
        assert!(s.as_slice().contains("my special message"));
    })
}
<commit_msg>std: Turn down the stdout chunk size<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Non-blocking access to stdin, stdout, and stderr.

This module provides bindings to the local event loop's TTY interface, using it
to offer synchronous but non-blocking versions of stdio. These handles can be
inspected for information about terminal dimensions or for related information
about the stream or terminal to which it is attached.

# Example

```rust
# #![allow(unused_must_use)]
use std::io;

let mut out = io::stdout();
out.write(b"Hello, world!");
```

*/

use failure::local_stderr;
use fmt;
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
         standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
use iter::Iterator;
use kinds::Send;
use libc;
use option::{Option, Some, None};
use boxed::Box;
use result::{Ok, Err};
use rt;
use rt::local::Local;
use rt::task::Task;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
use slice::ImmutableSlice;
use str::StrSlice;
use uint;

// And so begins the tale of acquiring a uv handle to a stdio stream on all
// platforms in all situations. Our story begins by splitting the world into two
// categories, windows and unix. Then one day the creators of unix said let
// there be redirection! And henceforth there was redirection away from the
// console for standard I/O streams.
//
// After this day, the world split into four factions:
//
// 1. Unix with stdout on a terminal.
// 2. Unix with stdout redirected.
// 3. Windows with stdout on a terminal.
// 4. Windows with stdout redirected.
//
// Many years passed, and then one day the nation of libuv decided to unify this
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
// These three ideas propagated throughout the lands and the four great factions
// decided to settle among them.
//
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
// doing so, they even enhanced themselves further then their Pipe/File
// brethren, becoming the dominant powers.
//
// The group of 4, however, decided to work independently. They abandoned the
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
// The members of the 4th faction decided to only align themselves with File.
//
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
//        case pipe also doesn't work, but magically file does!
enum StdSource {
    TTY(Box<RtioTTY + Send>),
    File(Box<RtioFileStream + Send>),
}

fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
    LocalIo::maybe_raise(|io| {
        Ok(match io.tty_open(fd, readable) {
            Ok(tty) => f(TTY(tty)),
            Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
        })
    }).map_err(IoError::from_rtio_error).unwrap()
}

local_data_key!(local_stdout: Box<Writer + Send>)

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// The returned handled is buffered by default with a `BufferedReader`. If
/// buffered access is not desired, the `stdin_raw` function is provided to
/// provided unbuffered access to stdin.
///
/// Care should be taken when creating multiple handles to the stdin of a
/// process. Because this is a buffered reader by default, it's possible for
/// pending input to be unconsumed in one reader and unavailable to other
/// readers. It is recommended that only one handle at a time is created for the
/// stdin of a process.
///
/// See `stdout()` for more notes about this function.
pub fn stdin() -> BufferedReader<StdReader> {
    // The default buffer capacity is 64k, but apparently windows doesn't like
    // 64k reads on stdin. See #13304 for details, but the idea is that on
    // windows we use a slightly smaller buffer that's been seen to be
    // acceptable.
    if cfg!(windows) {
        BufferedReader::with_capacity(8 * 1024, stdin_raw())
    } else {
        BufferedReader::new(stdin_raw())
    }
}

/// Creates a new non-blocking handle to the stdin of the current process.
///
/// Unlike `stdin()`, the returned reader is *not* a buffered reader.
///
/// See `stdout()` for more notes about this function.
pub fn stdin_raw() -> StdReader {
    src(libc::STDIN_FILENO, true, |src| StdReader { inner: src })
}

/// Creates a line-buffered handle to the stdout of the current process.
///
/// Note that this is a fairly expensive operation in that at least one memory
/// allocation is performed. Additionally, this must be called from a runtime
/// task context because the stream returned will be a non-blocking object using
/// the local scheduler to perform the I/O.
///
/// Care should be taken when creating multiple handles to an output stream for
/// a single process. While usage is still safe, the output may be surprising if
/// no synchronization is performed to ensure a sane output.
pub fn stdout() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stdout_raw())
}

/// Creates an unbuffered handle to the stdout of the current process
///
/// See notes in `stdout()` for more information.
pub fn stdout_raw() -> StdWriter {
    src(libc::STDOUT_FILENO, false, |src| StdWriter { inner: src })
}

/// Creates a line-buffered handle to the stderr of the current process.
///
/// See `stdout()` for notes about this function.
pub fn stderr() -> LineBufferedWriter<StdWriter> {
    LineBufferedWriter::new(stderr_raw())
}

/// Creates an unbuffered handle to the stderr of the current process
///
/// See notes in `stdout()` for more information.
pub fn stderr_raw() -> StdWriter {
    src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
}

/// Resets the task-local stdout handle to the specified writer
///
/// This will replace the current task's stdout handle, returning the old
/// handle. All future calls to `print` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stdout.replace(Some(stdout)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

/// Resets the task-local stderr handle to the specified writer
///
/// This will replace the current task's stderr handle, returning the old
/// handle. Currently, the stderr handle is used for printing failure messages
/// during task failure.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
    local_stderr.replace(Some(stderr)).and_then(|mut s| {
        let _ = s.flush();
        Some(s)
    })
}

// Helper to access the local task's stdout handle
//
// Note that this is not a safe function to expose because you can create an
// aliased pointer very easily:
//
//  with_task_stdout(|io1| {
//      with_task_stdout(|io2| {
//          // io1 aliases io2
//      })
//  })
fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
    let result = if Local::exists(None::<Task>) {
        let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
            box stdout() as Box<Writer + Send>
        });
        let result = f(my_stdout);
        local_stdout.replace(Some(my_stdout));
        result
    } else {
        let mut io = rt::Stdout;
        f(&mut io as &mut Writer)
    };
    match result {
        Ok(()) => {}
        Err(e) => fail!("failed printing to stdout: {}", e),
    }
}

/// Flushes the local task's stdout handle.
///
/// By default, this stream is a line-buffering stream, so flushing may be
/// necessary to ensure that all output is printed to the screen (if there are
/// no newlines printed).
///
/// Note that logging macros do not use this stream. Using the logging macros
/// will emit output to stderr, and while they are line buffered the log
/// messages are always terminated in a newline (no need to flush).
pub fn flush() {
    with_task_stdout(|io| io.flush())
}

/// Prints a string to the stdout of the current process. No newline is emitted
/// after the string is printed.
pub fn print(s: &str) {
    with_task_stdout(|io| io.write(s.as_bytes()))
}

/// Prints a string to the stdout of the current process. A literal
/// `\n` character is printed to the console after the string.
pub fn println(s: &str) {
    with_task_stdout(|io| {
        io.write(s.as_bytes()).and_then(|()| io.write([b'\n']))
    })
}

/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
/// with the `format_args!` macro.
pub fn print_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| write!(io, "{}", fmt))
}

/// Similar to `println`, but takes a `fmt::Arguments` structure to be
/// compatible with the `format_args!` macro.
pub fn println_args(fmt: &fmt::Arguments) {
    with_task_stdout(|io| writeln!(io, "{}", fmt))
}

/// Representation of a reader of a standard input stream
pub struct StdReader {
    inner: StdSource
}

impl StdReader {
    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Reader for StdReader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let ret = match self.inner {
            TTY(ref mut tty) => {
                // Flush the task-local stdout so that weird issues like a
                // print!'d prompt not being shown until after the user hits
                // enter.
                flush();
                tty.read(buf)
            },
            File(ref mut file) => file.read(buf).map(|i| i as uint),
        }.map_err(IoError::from_rtio_error);
        match ret {
            // When reading a piped stdin, libuv will return 0-length reads when
            // stdin reaches EOF. For pretty much all other streams it will
            // return an actual EOF error, but apparently for stdin it's a
            // little different. Hence, here we convert a 0 length read to an
            // end-of-file indicator so the caller knows to stop reading.
            Ok(0) => { Err(standard_error(EndOfFile)) }
            ret @ Ok(..) | ret @ Err(..) => ret,
        }
    }
}

/// Representation of a writer to a standard output stream
pub struct StdWriter {
    inner: StdSource
}

impl StdWriter {
    /// Gets the size of this output window, if possible. This is typically used
    /// when the writer is attached to something like a terminal, this is used
    /// to fetch the dimensions of the terminal.
    ///
    /// If successful, returns `Ok((width, height))`.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn winsize(&mut self) -> IoResult<(int, int)> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.get_winsize().map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Controls whether this output stream is a "raw stream" or simply a normal
    /// stream.
    ///
    /// # Error
    ///
    /// This function will return an error if the output stream is not actually
    /// connected to a TTY instance, or if querying the TTY instance fails.
    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        match self.inner {
            TTY(ref mut tty) => {
                tty.set_raw(raw).map_err(IoError::from_rtio_error)
            }
            File(..) => {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "stream is not a tty",
                    detail: None,
                })
            }
        }
    }

    /// Returns whether this stream is attached to a TTY instance or not.
    pub fn isatty(&self) -> bool {
        match self.inner {
            TTY(..) => true,
            File(..) => false,
        }
    }
}

impl Writer for StdWriter {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        // As with stdin on windows, stdout often can't handle writes of large
        // sizes. For an example, see #14940. For this reason, chunk the output
        // buffer on windows, but on unix we can just write the whole buffer all
        // at once.
        //
        // For some other references, it appears that this problem has been
        // encountered by others [1] [2]. We choose the number 8KB just because
        // libuv does the same.
        //
        // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
        // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
        let max_size = if cfg!(windows) {8192} else {uint::MAX};
        for chunk in buf.chunks(max_size) {
            try!(match self.inner {
                TTY(ref mut tty) => tty.write(chunk),
                File(ref mut file) => file.write(chunk),
            }.map_err(IoError::from_rtio_error))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    iotest!(fn smoke() {
        // Just make sure we can acquire handles
        stdin();
        stdout();
        stderr();
    })

    iotest!(fn capture_stdout() {
        use io::{ChanReader, ChanWriter};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            set_stdout(box w);
            println!("hello!");
        });
        assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
    })

    iotest!(fn capture_stderr() {
        use realstd::comm::channel;
        use realstd::io::{Writer, ChanReader, ChanWriter, Reader};

        let (tx, rx) = channel();
        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
        spawn(proc() {
            ::realstd::io::stdio::set_stderr(box w);
            fail!("my special message");
        });
        let s = r.read_to_string().unwrap();
        assert!(s.as_slice().contains("my special message"));
    })
}
<|endoftext|>


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

//! Converting decimal strings into IEEE 754 binary floating point numbers.
//!
//! # Problem statement
//!
//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero
//! when missing.
//!
//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal
//! string. It is well-known that many decimal strings do not have terminating representations in
//! base two, so we round to 0.5 units in the last place (in other words, as well as possible).
//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the
//! half-to-even strategy, also known as banker's rounding.
//!
//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms
//! of CPU cycles taken.
//!
//! # Implementation
//!
//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion
//! process and re-apply it at the very end. This is correct in all edge cases since IEEE
//! floats are symmetric around zero, negating one simply flips the first bit.
//!
//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns
//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`.
//! The `(f, e)` representation is used by almost all code past the parsing stage.
//!
//! We then try a long chain of progressively more general and expensive special cases using
//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then
//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a
//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative
//! search for the best approximation.
//!
//! Primarily, this module and its children implement the algorithms described in:
//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
//! available online: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152
//!
//! In addition, there are numerous helper functions that are used in the paper but not available
//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
//! overflow and underflow and the desire to handle subnormal numbers.  Bellerophon and
//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to
//! Algorithm M (with the modifications described in section 8 of the paper) well before the
//! inputs get into the critical region.
//!
//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions
//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to
//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using
//! base two or half-to-even rounding.
//!
//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal
//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding.
//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first,
//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other
//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision
//! and round *exactly once, at the end*, by considering all truncated bits at once.
//!
//! FIXME Although some code duplication is necessary, perhaps parts of the code could be shuffled
//! around such that less code is duplicated. Large parts of the algorithms are independent of the
//! float type to output, or only needs access to a few constants, which could be passed in as
//! parameters.
//!
//! # Other
//!
//! The conversion should *never* panic. There are assertions and explicit panics in the code,
//! but they should never be triggered and only serve as internal sanity checks. Any panics should
//! be considered a bug.
//!
//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
//! a small percentage of possible errors. Far more extensive tests are located in the directory
//! `src/etc/test-float-parse` as a Python script.
//!
//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on
//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means
//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
//! turned into {positive,negative} {zero,infinity}.

#![doc(hidden)]
#![unstable(feature = "dec2flt",
            reason = "internal routines only exposed for testing",
            issue = "0")]

use prelude::v1::*;
use fmt;
use str::FromStr;

use self::parse::{parse_decimal, Decimal, Sign};
use self::parse::ParseResult::{Valid, Invalid, ShortcutToInf, ShortcutToZero};
use self::num::digits_to_big;
use self::rawfp::RawFloat;

mod algorithm;
mod table;
mod num;
// These two have their own tests.
pub mod rawfp;
pub mod parse;

macro_rules! from_str_float_impl {
    ($t:ty, $func:ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl FromStr for $t {
            type Err = ParseFloatError;

            /// Converts a string in base 10 to a float.
            /// Accepts an optional decimal exponent.
            ///
            /// This function accepts strings such as
            ///
            /// * '3.14'
            /// * '-3.14'
            /// * '2.5E10', or equivalently, '2.5e10'
            /// * '2.5E-10'
            /// * '.' (understood as 0)
            /// * '5.'
            /// * '.5', or, equivalently,  '0.5'
            /// * 'inf', '-inf', 'NaN'
            ///
            /// Leading and trailing whitespace represent an error.
            ///
            /// # Arguments
            ///
            /// * src - A string
            ///
            /// # Return value
            ///
            /// `Err(ParseFloatError)` if the string did not represent a valid
            /// number.  Otherwise, `Ok(n)` where `n` is the floating-point
            /// number represented by `src`.
            #[inline]
            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
                dec2flt(src)
            }
        }
    }
}
from_str_float_impl!(f32, to_f32);
from_str_float_impl!(f64, to_f64);

/// An error which can be returned when parsing a float.
#[derive(Debug, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {
    kind: FloatErrorKind
}

#[derive(Debug, Clone, PartialEq)]
enum FloatErrorKind {
    Empty,
    Invalid,
}

impl ParseFloatError {
    #[unstable(feature = "int_error_internals",
               reason = "available through Error trait and this method should \
                         not be exposed publicly",
               issue = "0")]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            FloatErrorKind::Empty => "cannot parse float from empty string",
            FloatErrorKind::Invalid => "invalid float literal",
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.__description().fmt(f)
    }
}

fn pfe_empty() -> ParseFloatError {
    ParseFloatError { kind: FloatErrorKind::Empty }
}

fn pfe_invalid() -> ParseFloatError {
    ParseFloatError { kind: FloatErrorKind::Invalid }
}

/// Split decimal string into sign and the rest, without inspecting or validating the rest.
fn extract_sign(s: &str) -> (Sign, &str) {
    match s.as_bytes()[0] {
        b'+' => (Sign::Positive, &s[1..]),
        b'-' => (Sign::Negative, &s[1..]),
        // If the string is invalid, we never use the sign, so we don't need to validate here.
        _ => (Sign::Positive, s),
    }
}

/// Convert a decimal string into a floating point number.
fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
    if s.is_empty() {
        return Err(pfe_empty())
    }
    let (sign, s) = extract_sign(s);
    let flt = match parse_decimal(s) {
        Valid(decimal) => try!(convert(decimal)),
        ShortcutToInf => T::infinity(),
        ShortcutToZero => T::zero(),
        Invalid => match s {
            "inf" => T::infinity(),
            "NaN" => T::nan(),
            _ => { return Err(pfe_invalid()); }
        }
    };

    match sign {
        Sign::Positive => Ok(flt),
        Sign::Negative => Ok(-flt),
    }
}

/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
/// and figure out which algorithm should do the actual conversion.
fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, ParseFloatError> {
    simplify(&mut decimal);
    if let Some(x) = trivial_cases(&decimal) {
        return Ok(x);
    }
    // AlgorithmM and AlgorithmR both compute approximately `f * 10^e`.
    let max_digits = decimal.integral.len() + decimal.fractional.len() +
                     decimal.exp.abs() as usize;
    // Remove/shift out the decimal point.
    let e = decimal.exp - decimal.fractional.len() as i64;
    if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) {
        return Ok(x);
    }
    // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits.
    // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or Algorithm M,
    // we'll crash. So we error out before getting too close, with a generous safety margin.
    if max_digits > 375 {
        return Err(pfe_invalid());
    }
    let f = digits_to_big(decimal.integral, decimal.fractional);

    // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms.
    let e = e as i16;
    // FIXME These bounds are rather conservative. A more careful analysis of the failure modes
    // of Bellerophon could allow using it in more cases for a massive speed up.
    let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
    let value_in_range = max_digits <= T::max_normal_digits();
    if exponent_in_range && value_in_range {
        Ok(algorithm::bellerophon(&f, e))
    } else {
        Ok(algorithm::algorithm_m(&f, e))
    }
}

// As written, this optimizes badly (see #27130, though it refers to an old version of the code).
// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't
// make code size worse.

/// Strip zeros where possible, even when this requires changing the exponent
#[inline(always)]
fn simplify(decimal: &mut Decimal) {
    let is_zero = &|&&d: &&u8| -> bool { d == b'0' };
    // Trimming these zeros does not change anything but may enable the fast path (< 15 digits).
    let leading_zeros = decimal.integral.iter().take_while(is_zero).count();
    decimal.integral = &decimal.integral[leading_zeros..];
    let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count();
    let end = decimal.fractional.len() - trailing_zeros;
    decimal.fractional = &decimal.fractional[..end];
    // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly.
    // This may not always be a win (possibly pushes some numbers out of the fast path), but it
    // simplifies other parts significantly (notably, approximating the magnitude of the value).
    if decimal.integral.is_empty() {
        let leading_zeros = decimal.fractional.iter().take_while(is_zero).count();
        decimal.fractional = &decimal.fractional[leading_zeros..];
        decimal.exp -= leading_zeros as i64;
    } else if decimal.fractional.is_empty() {
        let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count();
        let end = decimal.integral.len() - trailing_zeros;
        decimal.integral = &decimal.integral[..end];
        decimal.exp += trailing_zeros as i64;
    }
}

/// Detect obvious overflows and underflows without even looking at the decimal digits.
fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
    // There were zeros but they were stripped by simplify()
    if decimal.integral.is_empty() && decimal.fractional.is_empty() {
        return Some(T::zero());
    }
    // This is a crude approximation of ceil(log10(the real value)).
    let max_place = decimal.exp + decimal.integral.len() as i64;
    if max_place > T::inf_cutoff() {
        return Some(T::infinity());
    } else if max_place < T::zero_cutoff() {
        return Some(T::zero());
    }
    None
}
<commit_msg>dec2flt: Remove unused macro argument<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Converting decimal strings into IEEE 754 binary floating point numbers.
//!
//! # Problem statement
//!
//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero
//! when missing.
//!
//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal
//! string. It is well-known that many decimal strings do not have terminating representations in
//! base two, so we round to 0.5 units in the last place (in other words, as well as possible).
//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the
//! half-to-even strategy, also known as banker's rounding.
//!
//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms
//! of CPU cycles taken.
//!
//! # Implementation
//!
//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion
//! process and re-apply it at the very end. This is correct in all edge cases since IEEE
//! floats are symmetric around zero, negating one simply flips the first bit.
//!
//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns
//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`.
//! The `(f, e)` representation is used by almost all code past the parsing stage.
//!
//! We then try a long chain of progressively more general and expensive special cases using
//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then
//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a
//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative
//! search for the best approximation.
//!
//! Primarily, this module and its children implement the algorithms described in:
//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
//! available online: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152
//!
//! In addition, there are numerous helper functions that are used in the paper but not available
//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
//! overflow and underflow and the desire to handle subnormal numbers.  Bellerophon and
//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to
//! Algorithm M (with the modifications described in section 8 of the paper) well before the
//! inputs get into the critical region.
//!
//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions
//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to
//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using
//! base two or half-to-even rounding.
//!
//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal
//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding.
//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first,
//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other
//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision
//! and round *exactly once, at the end*, by considering all truncated bits at once.
//!
//! FIXME Although some code duplication is necessary, perhaps parts of the code could be shuffled
//! around such that less code is duplicated. Large parts of the algorithms are independent of the
//! float type to output, or only needs access to a few constants, which could be passed in as
//! parameters.
//!
//! # Other
//!
//! The conversion should *never* panic. There are assertions and explicit panics in the code,
//! but they should never be triggered and only serve as internal sanity checks. Any panics should
//! be considered a bug.
//!
//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
//! a small percentage of possible errors. Far more extensive tests are located in the directory
//! `src/etc/test-float-parse` as a Python script.
//!
//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on
//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means
//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
//! turned into {positive,negative} {zero,infinity}.

#![doc(hidden)]
#![unstable(feature = "dec2flt",
            reason = "internal routines only exposed for testing",
            issue = "0")]

use prelude::v1::*;
use fmt;
use str::FromStr;

use self::parse::{parse_decimal, Decimal, Sign};
use self::parse::ParseResult::{Valid, Invalid, ShortcutToInf, ShortcutToZero};
use self::num::digits_to_big;
use self::rawfp::RawFloat;

mod algorithm;
mod table;
mod num;
// These two have their own tests.
pub mod rawfp;
pub mod parse;

macro_rules! from_str_float_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl FromStr for $t {
            type Err = ParseFloatError;

            /// Converts a string in base 10 to a float.
            /// Accepts an optional decimal exponent.
            ///
            /// This function accepts strings such as
            ///
            /// * '3.14'
            /// * '-3.14'
            /// * '2.5E10', or equivalently, '2.5e10'
            /// * '2.5E-10'
            /// * '.' (understood as 0)
            /// * '5.'
            /// * '.5', or, equivalently,  '0.5'
            /// * 'inf', '-inf', 'NaN'
            ///
            /// Leading and trailing whitespace represent an error.
            ///
            /// # Arguments
            ///
            /// * src - A string
            ///
            /// # Return value
            ///
            /// `Err(ParseFloatError)` if the string did not represent a valid
            /// number.  Otherwise, `Ok(n)` where `n` is the floating-point
            /// number represented by `src`.
            #[inline]
            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
                dec2flt(src)
            }
        }
    }
}
from_str_float_impl!(f32);
from_str_float_impl!(f64);

/// An error which can be returned when parsing a float.
#[derive(Debug, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {
    kind: FloatErrorKind
}

#[derive(Debug, Clone, PartialEq)]
enum FloatErrorKind {
    Empty,
    Invalid,
}

impl ParseFloatError {
    #[unstable(feature = "int_error_internals",
               reason = "available through Error trait and this method should \
                         not be exposed publicly",
               issue = "0")]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        match self.kind {
            FloatErrorKind::Empty => "cannot parse float from empty string",
            FloatErrorKind::Invalid => "invalid float literal",
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.__description().fmt(f)
    }
}

fn pfe_empty() -> ParseFloatError {
    ParseFloatError { kind: FloatErrorKind::Empty }
}

fn pfe_invalid() -> ParseFloatError {
    ParseFloatError { kind: FloatErrorKind::Invalid }
}

/// Split decimal string into sign and the rest, without inspecting or validating the rest.
fn extract_sign(s: &str) -> (Sign, &str) {
    match s.as_bytes()[0] {
        b'+' => (Sign::Positive, &s[1..]),
        b'-' => (Sign::Negative, &s[1..]),
        // If the string is invalid, we never use the sign, so we don't need to validate here.
        _ => (Sign::Positive, s),
    }
}

/// Convert a decimal string into a floating point number.
fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
    if s.is_empty() {
        return Err(pfe_empty())
    }
    let (sign, s) = extract_sign(s);
    let flt = match parse_decimal(s) {
        Valid(decimal) => try!(convert(decimal)),
        ShortcutToInf => T::infinity(),
        ShortcutToZero => T::zero(),
        Invalid => match s {
            "inf" => T::infinity(),
            "NaN" => T::nan(),
            _ => { return Err(pfe_invalid()); }
        }
    };

    match sign {
        Sign::Positive => Ok(flt),
        Sign::Negative => Ok(-flt),
    }
}

/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
/// and figure out which algorithm should do the actual conversion.
fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, ParseFloatError> {
    simplify(&mut decimal);
    if let Some(x) = trivial_cases(&decimal) {
        return Ok(x);
    }
    // AlgorithmM and AlgorithmR both compute approximately `f * 10^e`.
    let max_digits = decimal.integral.len() + decimal.fractional.len() +
                     decimal.exp.abs() as usize;
    // Remove/shift out the decimal point.
    let e = decimal.exp - decimal.fractional.len() as i64;
    if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) {
        return Ok(x);
    }
    // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits.
    // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or Algorithm M,
    // we'll crash. So we error out before getting too close, with a generous safety margin.
    if max_digits > 375 {
        return Err(pfe_invalid());
    }
    let f = digits_to_big(decimal.integral, decimal.fractional);

    // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms.
    let e = e as i16;
    // FIXME These bounds are rather conservative. A more careful analysis of the failure modes
    // of Bellerophon could allow using it in more cases for a massive speed up.
    let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
    let value_in_range = max_digits <= T::max_normal_digits();
    if exponent_in_range && value_in_range {
        Ok(algorithm::bellerophon(&f, e))
    } else {
        Ok(algorithm::algorithm_m(&f, e))
    }
}

// As written, this optimizes badly (see #27130, though it refers to an old version of the code).
// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't
// make code size worse.

/// Strip zeros where possible, even when this requires changing the exponent
#[inline(always)]
fn simplify(decimal: &mut Decimal) {
    let is_zero = &|&&d: &&u8| -> bool { d == b'0' };
    // Trimming these zeros does not change anything but may enable the fast path (< 15 digits).
    let leading_zeros = decimal.integral.iter().take_while(is_zero).count();
    decimal.integral = &decimal.integral[leading_zeros..];
    let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count();
    let end = decimal.fractional.len() - trailing_zeros;
    decimal.fractional = &decimal.fractional[..end];
    // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly.
    // This may not always be a win (possibly pushes some numbers out of the fast path), but it
    // simplifies other parts significantly (notably, approximating the magnitude of the value).
    if decimal.integral.is_empty() {
        let leading_zeros = decimal.fractional.iter().take_while(is_zero).count();
        decimal.fractional = &decimal.fractional[leading_zeros..];
        decimal.exp -= leading_zeros as i64;
    } else if decimal.fractional.is_empty() {
        let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count();
        let end = decimal.integral.len() - trailing_zeros;
        decimal.integral = &decimal.integral[..end];
        decimal.exp += trailing_zeros as i64;
    }
}

/// Detect obvious overflows and underflows without even looking at the decimal digits.
fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
    // There were zeros but they were stripped by simplify()
    if decimal.integral.is_empty() && decimal.fractional.is_empty() {
        return Some(T::zero());
    }
    // This is a crude approximation of ceil(log10(the real value)).
    let max_place = decimal.exp + decimal.integral.len() as i64;
    if max_place > T::inf_cutoff() {
        return Some(T::infinity());
    } else if max_place < T::zero_cutoff() {
        return Some(T::zero());
    }
    None
}
<|endoftext|>


<commit_before>use std::mem;

struct Fibonacci {
    curr: uint,
    next: uint,
}

// Implement 'Iterator' for 'Fibonacci'
impl Iterator<uint> for Fibonacci {
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<uint> {
        let new_next = self.curr + self.next;
        let new_curr = mem::replace(&mut self.next, new_next);

        // 'Some' is always returned, this is an infinite value generator
        Some(mem::replace(&mut self.curr, new_curr))
    }
}

// Returns a fibonacci sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // Iterator that generates: 0, 1 and 2
    let mut sequence = range(0u, 3);

    println!("Four consecutive `next` calls on range(0, 3)")
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());

    // The for construct will iterate an 'Iterator' until it returns 'None',
    // all the 'Some' values are unwrapped and bind to a variable
    println!("Iterate over range(0, 3) using for");
    for i in range(0u, 3) {
        println!("> {}", i);
    }

    // The 'take(n)' method will reduce an iterator to its first 'n' terms,
    // which is pretty useful for infinite value generators
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // The 'skip(n)' method will shorten an iterator by dropping its first 'n'
    // terms
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u, 3, 3, 7];

    // The 'iter' method produces an 'Iterator' over an array/slice
    println!("Iterate the following array {}", array.as_slice());
    for i in array.iter() {
        println!("> {}", i);
    }
}
<commit_msg>Sentences worded oddly.  Tried to improve a little.<commit_after>use std::mem;

struct Fibonacci {
    curr: uint,
    next: uint,
}

// Implement 'Iterator' for 'Fibonacci'
impl Iterator<uint> for Fibonacci {
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<uint> {
        let new_next = self.curr + self.next;
        let new_curr = mem::replace(&mut self.next, new_next);

        // 'Some' is always returned, this is an infinite value generator
        Some(mem::replace(&mut self.curr, new_curr))
    }
}

// Returns a fibonacci sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // Iterator that generates: 0, 1 and 2
    let mut sequence = range(0u, 3);

    println!("Four consecutive `next` calls on range(0, 3)")
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());
    println!("> {}", sequence.next());

    // The for construct will iterate an 'Iterator' until it returns 'None'.
    // Every 'Some' value is unwrapped and bound to a variable.
    println!("Iterate over range(0, 3) using for");
    for i in range(0u, 3) {
        println!("> {}", i);
    }

    // The 'take(n)' method will reduce an iterator to its first 'n' terms,
    // which is pretty useful for infinite value generators
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // The 'skip(n)' method will shorten an iterator by dropping its first 'n'
    // terms
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u, 3, 3, 7];

    // The 'iter' method produces an 'Iterator' over an array/slice
    println!("Iterate the following array {}", array.as_slice());
    for i in array.iter() {
        println!("> {}", i);
    }
}
<|endoftext|>


<commit_before><commit_msg>Move 'point', 'get', 'put' out of impl<commit_after><|endoftext|>


<commit_before><commit_msg>Improve 'Route' documentation.<commit_after><|endoftext|>


<commit_before>// pp-exact - Make sure we actually print the attributes

struct cat {
    #[cat_maker]
    new(name: ~str) { self.name = name; }
    #[cat_dropper]
    drop { error! {"%s landed on hir feet",self.name }; }
    let name: ~str;
}

fn main() { let _kitty = cat(~"Spotty"); }
<commit_msg>Another attempt on class-attribute-1.rs.<commit_after>// pp-exact - Make sure we actually print the attributes

struct cat {
    #[cat_maker]
    new(name: ~str) { self.name = name; }
    #[cat_dropper]
    drop { error! {"%s landed on hir feet",self.name }; }
    name: ~str;
}

fn main() { let _kitty = cat(~"Spotty"); }
<|endoftext|>


<commit_before><commit_msg>audio.edit method<commit_after><|endoftext|>


<commit_before><commit_msg>Automatically derive the combined image sampler uniforms from reflection data<commit_after><|endoftext|>


<commit_before><commit_msg>Chore(trash): cleanup imports again, fix indent<commit_after><|endoftext|>


<commit_before><commit_msg>video.createComment method<commit_after><|endoftext|>


<commit_before><commit_msg>impl render trait for world<commit_after><|endoftext|>


<commit_before><commit_msg>Fix compilation errors caused by Lettre's builder not being cloneable<commit_after><|endoftext|>


<commit_before><commit_msg>Added testcase for the missing do compile note<commit_after>// Regression test for issue #2783

fn foo(f: fn()) { f() }

fn main() {
    "" || 42; //! ERROR binary operation || cannot be applied to type `str`
    foo || {}; //! ERROR binary operation || cannot be applied to type `extern fn(fn())`
    //!^ NOTE did you forget the 'do' keyword for the call?
}
<|endoftext|>


<commit_before><commit_msg>match added as an expression<commit_after><|endoftext|>


<commit_before><commit_msg>Test of pde::Pair<commit_after>extern crate eom;
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::*;
use std::f64::consts::PI;

use eom::pde::*;

#[test]
fn pair_r2c2r() {
    let n = 128;
    let a: Array1<f64> = random(n);
    let mut p = Pair::new(n);
    p.r.copy_from_slice(&a.as_slice().unwrap());
    p.r2c();
    p.c2r();
    let b: Array1<f64> = Array::from_iter(p.r.iter().cloned());
    assert_close_l2!(&a, &b, 1e-7);
}

#[test]
fn pair_c2r() {
    let n = 128;
    let k0 = 2.0 * PI / n as f64;
    let a = Array::from_shape_fn(n, |i| 2.0 * (i as f64 * k0).cos());
    let mut p = Pair::new(n);
    p.c[1] = c64::new(1.0, 0.0);
    p.c2r();
    let b = Array::from_iter(p.r.iter().cloned());
    assert_close_l2!(&a, &b, 1e-7);
}
<|endoftext|>


<commit_before><commit_msg>Added tests on std::Vec<commit_after>// Tests to understand how some Rust collections work

#[test]
fn double_ended_iter() {
    let v = vec![0, 1, 2, 3];
    let mut iter = v.iter();
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    // returns the end of the range and consume it
    assert_eq!(iter.next_back(), Some(&3));
    assert_eq!(iter.next(), Some(&2));
    // now we are at the end: element 3 was consumed by prev next_back
    assert_eq!(iter.next(), None);
}

#[test]
fn peek() {
    let v = vec![0, 1, 2, 3];
    let mut iter = v.iter().peekable();
    assert_eq!(iter.peek(), Some(&&0));
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.peek(), Some(&&2));
    assert_eq!(iter.peek(), Some(&&2));
}
<|endoftext|>


<commit_before><commit_msg>more namespace nonsense<commit_after><|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fmt;
use std::str::from_utf8;

use header::{Header, Raw};
use header::internals::VecMap;

/// `Cookie` header, defined in [RFC6265](http://tools.ietf.org/html/rfc6265#section-5.4)
///
/// If the user agent does attach a Cookie header field to an HTTP
/// request, the user agent must send the cookie-string
/// as the value of the header field.
///
/// When the user agent generates an HTTP request, the user agent MUST NOT
/// attach more than one Cookie header field.
///
/// # Example values
/// * `SID=31d4d96e407aad42`
/// * `SID=31d4d96e407aad42; lang=en-US`
///
/// # Example
/// ```
/// use hyper::header::{Headers, Cookie};
///
/// let mut headers = Headers::new();
/// let mut cookie = Cookie::new();
/// cookie.append("foo", "bar");
///
/// assert_eq!(cookie.get("foo"), Some("bar"));
///
/// headers.set(cookie);
/// ```
#[derive(Clone)]
pub struct Cookie(VecMap<Cow<'static, str>, Cow<'static, str>>);

impl Cookie {
    /// Creates a new `Cookie` header.
    pub fn new() -> Cookie {
        Cookie(VecMap::with_capacity(0))
    }

    /// Sets a name and value for the `Cookie`.
    ///
    /// # Note
    ///
    /// This will remove all other instances with the same name,
    /// and insert the new value.
    pub fn set<K, V>(&mut self, key: K, value: V)
    where K: Into<Cow<'static, str>>,
          V: Into<Cow<'static, str>>,
    {
        let key = key.into();
        let value = value.into();
        self.0.remove_all(&key);
        self.0.append(key, value);
    }

    /// Append a name and value for the `Cookie`.
    ///
    /// # Note
    ///
    /// Cookies are allowed to set a name with a
    /// a value multiple times. For example:
    ///
    /// ```
    /// use hyper::header::Cookie;
    /// let mut cookie = Cookie::new();
    /// cookie.append("foo", "bar");
    /// cookie.append("foo", "quux");
    /// assert_eq!(cookie.to_string(), "foo=bar; foo=quux");
    pub fn append<K, V>(&mut self, key: K, value: V)
    where K: Into<Cow<'static, str>>,
          V: Into<Cow<'static, str>>,
    {
        self.0.append(key.into(), value.into());
    }

    /// Get a value for the name, if it exists.
    ///
    /// # Note
    ///
    /// Only returns the first instance found. To access
    /// any other values associated with the name, parse
    /// the `str` representation.
    pub fn get(&self, key: &str) -> Option<&str> {
        self.0.get(key).map(AsRef::as_ref)
    }
}

impl Header for Cookie {
    fn header_name() -> &'static str {
        static NAME: &'static str = "Cookie";
        NAME
    }

    fn parse_header(raw: &Raw) -> ::Result<Cookie> {
        let mut vec_map = VecMap::with_capacity(raw.len());
        for cookies_raw in raw.iter() {
            let cookies_str = try!(from_utf8(&cookies_raw[..]));
            for cookie_str in cookies_str.split(';') {
                let mut key_val = cookie_str.splitn(2, '=');
                let key_val = (key_val.next(), key_val.next());
                if let (Some(key), Some(val)) = key_val {
                    vec_map.insert(key.trim().to_owned().into(), val.trim().to_owned().into());
                } else {
                    return Err(::Error::Header);
                }
            }
        }

        if vec_map.len() != 0 {
            Ok(Cookie(vec_map))
        } else {
            Err(::Error::Header)
        }
    }

    fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
        f.fmt_line(self)
    }
}

impl PartialEq for Cookie {
    fn eq(&self, other: &Cookie) -> bool {
        if self.0.len() == other.0.len() {
            for &(ref k, ref v) in self.0.iter() {
                if other.get(k) != Some(v) {
                    return false;
                }
            }
            true
        } else {
            false
        }
    }
}

impl fmt::Debug for Cookie {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map()
            .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
            .finish()
    }
}

impl fmt::Display for Cookie {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.0.iter();
        if let Some(&(ref key, ref val)) = iter.next() {
            try!(write!(f, "{}={}", key, val));
        }
        for &(ref key, ref val) in iter {
            try!(write!(f, "; {}={}", key, val));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use ::header::Header;
    use super::Cookie;

    #[test]
    fn test_set_and_get() {
        let mut cookie = Cookie::new();
        cookie.append("foo", "bar");
        cookie.append(String::from("dyn"), String::from("amic"));

        assert_eq!(cookie.get("foo"), Some("bar"));
        assert_eq!(cookie.get("dyn"), Some("amic"));
        assert!(cookie.get("nope").is_none());

        cookie.append("foo", "notbar");
        assert_eq!(cookie.get("foo"), Some("bar"));

        cookie.set("foo", "hi");
        assert_eq!(cookie.get("foo"), Some("hi"));
        assert_eq!(cookie.get("dyn"), Some("amic"));
    }

    #[test]
    fn test_eq() {
        let mut cookie = Cookie::new();
        let mut cookie2 = Cookie::new();

        // empty is equal
        assert_eq!(cookie, cookie2);

        // left has more params
        cookie.append("foo", "bar");
        assert!(cookie != cookie2);

        // same len, different params
        cookie2.append("bar", "foo");
        assert!(cookie != cookie2);

        // right has more params, and matching KV
        cookie2.append("foo", "bar");
        assert!(cookie != cookie2);

        // same params, different order
        cookie.append("bar", "foo");
        assert_eq!(cookie, cookie2);
    }

    #[test]
    fn test_parse() {
        let mut cookie = Cookie::new();

        let parsed = Cookie::parse_header(&b"foo=bar".to_vec().into()).unwrap();
        cookie.append("foo", "bar");
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&b"foo=bar; baz=quux".to_vec().into()).unwrap();
        cookie.append("baz", "quux");
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&b" foo  =    bar;baz= quux  ".to_vec().into()).unwrap();
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&vec![b"foo  =    bar".to_vec(),b"baz= quux  ".to_vec()].into()).unwrap();
        assert_eq!(cookie, parsed);

        Cookie::parse_header(&b"foo;bar=baz;quux".to_vec().into()).unwrap_err();

    }
}

bench_header!(bench, Cookie, { vec![b"foo=bar; baz=quux".to_vec()] });
<commit_msg>test(header): test valid corner cases<commit_after>use std::borrow::Cow;
use std::fmt;
use std::str::from_utf8;

use header::{Header, Raw};
use header::internals::VecMap;

/// `Cookie` header, defined in [RFC6265](http://tools.ietf.org/html/rfc6265#section-5.4)
///
/// If the user agent does attach a Cookie header field to an HTTP
/// request, the user agent must send the cookie-string
/// as the value of the header field.
///
/// When the user agent generates an HTTP request, the user agent MUST NOT
/// attach more than one Cookie header field.
///
/// # Example values
/// * `SID=31d4d96e407aad42`
/// * `SID=31d4d96e407aad42; lang=en-US`
///
/// # Example
/// ```
/// use hyper::header::{Headers, Cookie};
///
/// let mut headers = Headers::new();
/// let mut cookie = Cookie::new();
/// cookie.append("foo", "bar");
///
/// assert_eq!(cookie.get("foo"), Some("bar"));
///
/// headers.set(cookie);
/// ```
#[derive(Clone)]
pub struct Cookie(VecMap<Cow<'static, str>, Cow<'static, str>>);

impl Cookie {
    /// Creates a new `Cookie` header.
    pub fn new() -> Cookie {
        Cookie(VecMap::with_capacity(0))
    }

    /// Sets a name and value for the `Cookie`.
    ///
    /// # Note
    ///
    /// This will remove all other instances with the same name,
    /// and insert the new value.
    pub fn set<K, V>(&mut self, key: K, value: V)
        where K: Into<Cow<'static, str>>,
              V: Into<Cow<'static, str>>
    {
        let key = key.into();
        let value = value.into();
        self.0.remove_all(&key);
        self.0.append(key, value);
    }

    /// Append a name and value for the `Cookie`.
    ///
    /// # Note
    ///
    /// Cookies are allowed to set a name with a
    /// a value multiple times. For example:
    ///
    /// ```
    /// use hyper::header::Cookie;
    /// let mut cookie = Cookie::new();
    /// cookie.append("foo", "bar");
    /// cookie.append("foo", "quux");
    /// assert_eq!(cookie.to_string(), "foo=bar; foo=quux");
    pub fn append<K, V>(&mut self, key: K, value: V)
        where K: Into<Cow<'static, str>>,
              V: Into<Cow<'static, str>>
    {
        self.0.append(key.into(), value.into());
    }

    /// Get a value for the name, if it exists.
    ///
    /// # Note
    ///
    /// Only returns the first instance found. To access
    /// any other values associated with the name, parse
    /// the `str` representation.
    pub fn get(&self, key: &str) -> Option<&str> {
        self.0.get(key).map(AsRef::as_ref)
    }
}

impl Header for Cookie {
    fn header_name() -> &'static str {
        static NAME: &'static str = "Cookie";
        NAME
    }

    fn parse_header(raw: &Raw) -> ::Result<Cookie> {
        let mut vec_map = VecMap::with_capacity(raw.len());
        for cookies_raw in raw.iter() {
            let cookies_str = try!(from_utf8(&cookies_raw[..]));
            for cookie_str in cookies_str.split(';') {
                let mut key_val = cookie_str.splitn(2, '=');
                let key_val = (key_val.next(), key_val.next());
                if let (Some(key), Some(val)) = key_val {
                    vec_map.insert(key.trim().to_owned().into(), val.trim().to_owned().into());
                } else {
                    return Err(::Error::Header);
                }
            }
        }

        if vec_map.len() != 0 {
            Ok(Cookie(vec_map))
        } else {
            Err(::Error::Header)
        }
    }

    fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
        f.fmt_line(self)
    }
}

impl PartialEq for Cookie {
    fn eq(&self, other: &Cookie) -> bool {
        if self.0.len() == other.0.len() {
            for &(ref k, ref v) in self.0.iter() {
                if other.get(k) != Some(v) {
                    return false;
                }
            }
            true
        } else {
            false
        }
    }
}

impl fmt::Debug for Cookie {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map()
            .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
            .finish()
    }
}

impl fmt::Display for Cookie {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.0.iter();
        if let Some(&(ref key, ref val)) = iter.next() {
            try!(write!(f, "{}={}", key, val));
        }
        for &(ref key, ref val) in iter {
            try!(write!(f, "; {}={}", key, val));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use header::Header;
    use super::Cookie;

    #[test]
    fn test_set_and_get() {
        let mut cookie = Cookie::new();
        cookie.append("foo", "bar");
        cookie.append(String::from("dyn"), String::from("amic"));

        assert_eq!(cookie.get("foo"), Some("bar"));
        assert_eq!(cookie.get("dyn"), Some("amic"));
        assert!(cookie.get("nope").is_none());

        cookie.append("foo", "notbar");
        assert_eq!(cookie.get("foo"), Some("bar"));

        cookie.set("foo", "hi");
        assert_eq!(cookie.get("foo"), Some("hi"));
        assert_eq!(cookie.get("dyn"), Some("amic"));
    }

    #[test]
    fn test_eq() {
        let mut cookie = Cookie::new();
        let mut cookie2 = Cookie::new();

        // empty is equal
        assert_eq!(cookie, cookie2);

        // left has more params
        cookie.append("foo", "bar");
        assert!(cookie != cookie2);

        // same len, different params
        cookie2.append("bar", "foo");
        assert!(cookie != cookie2);

        // right has more params, and matching KV
        cookie2.append("foo", "bar");
        assert!(cookie != cookie2);

        // same params, different order
        cookie.append("bar", "foo");
        assert_eq!(cookie, cookie2);
    }

    #[test]
    fn test_parse() {
        let mut cookie = Cookie::new();

        let parsed = Cookie::parse_header(&b"foo=bar".to_vec().into()).unwrap();
        cookie.append("foo", "bar");
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&b"foo=bar; baz=quux".to_vec().into()).unwrap();
        cookie.append("baz", "quux");
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&b" foo  =    bar;baz= quux  ".to_vec().into()).unwrap();
        assert_eq!(cookie, parsed);

        let parsed =
            Cookie::parse_header(&vec![b"foo  =    bar".to_vec(), b"baz= quux  ".to_vec()].into())
                .unwrap();
        assert_eq!(cookie, parsed);

        let parsed = Cookie::parse_header(&b"foo=bar; baz=quux ; empty=".to_vec().into()).unwrap();
        cookie.append("empty", "");
        assert_eq!(cookie, parsed);

        let mut cookie = Cookie::new();

        let parsed = Cookie::parse_header(&b"middle=equals=in=the=middle".to_vec().into()).unwrap();
        cookie.append("middle", "equals=in=the=middle");
        assert_eq!(cookie, parsed);

        let parsed =
            Cookie::parse_header(&b"middle=equals=in=the=middle; double==2".to_vec().into())
                .unwrap();
        cookie.append("double", "=2");
        assert_eq!(cookie, parsed);

        Cookie::parse_header(&b"foo;bar=baz;quux".to_vec().into()).unwrap_err();

    }
}

bench_header!(bench, Cookie, {
    vec![b"foo=bar; baz=quux".to_vec()]
});
<|endoftext|>


<commit_before><commit_msg>lib: remove some pub modules<commit_after><|endoftext|>