<commit_before>// Copyright 2013-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.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two
//! implementations, the `TerminfoTerminal`, which uses control characters from
//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/term) and can be
//! used by adding `term` to the dependencies in your project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//!
//! term = "0.2"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate term;
//! ```
//!
//! # Examples
//!
//! ```no_run
//! extern crate term;
//! use std::io::prelude::*;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     write!(t, "hello, ").unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     writeln!(t, "world!").unwrap();
//!
//!     t.reset().unwrap();
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://stebalien.github.io/doc/term/term/",
       test(attr(deny(warnings))))]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

use std::io::prelude::*;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::{self, Stdout, Stderr};

pub mod terminfo;

#[cfg(windows)]
mod win;

/// Alias for stdout terminals.
pub type StdoutTerminal = Terminal<Output = Stdout> + Send;
/// Alias for stderr terminals.
pub type StderrTerminal = Terminal<Output = Stderr> + Send;

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout())
        .map(|t| Box::new(t) as Box<StdoutTerminal>)
        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr())
        .map(|t| Box::new(t) as Box<StderrTerminal>)
        .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
}

/// Terminal color definitions
#[allow(missing_docs)]
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub const BLACK: Color = 0;
    pub const RED: Color = 1;
    pub const GREEN: Color = 2;
    pub const YELLOW: Color = 3;
    pub const BLUE: Color = 4;
    pub const MAGENTA: Color = 5;
    pub const CYAN: Color = 6;
    pub const WHITE: Color = 7;

    pub const BRIGHT_BLACK: Color = 8;
    pub const BRIGHT_RED: Color = 9;
    pub const BRIGHT_GREEN: Color = 10;
    pub const BRIGHT_YELLOW: Color = 11;
    pub const BRIGHT_BLUE: Color = 12;
    pub const BRIGHT_MAGENTA: Color = 13;
    pub const BRIGHT_CYAN: Color = 14;
    pub const BRIGHT_WHITE: Color = 15;
}

/// Terminal attributes for use with term.attr().
///
/// Most attributes can only be turned on and must be turned off with term.reset().
/// The ones that can be turned off explicitly take a boolean value.
/// Color is also represented as an attribute for convenience.
#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)]
pub enum Attr {
    /// Bold (or possibly bright) mode
    Bold,
    /// Dim mode, also called faint or half-bright. Often not supported
    Dim,
    /// Italics mode. Often not supported
    Italic(bool),
    /// Underline mode
    Underline(bool),
    /// Blink mode
    Blink,
    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
    Standout(bool),
    /// Reverse mode, inverts the foreground and background colors
    Reverse,
    /// Secure mode, also called invis mode. Hides the printed text
    Secure,
    /// Convenience attribute to set the foreground color
    ForegroundColor(color::Color),
    /// Convenience attribute to set the background color
    BackgroundColor(color::Color),
}

/// An error arising from interacting with the terminal.
#[derive(Debug)]
pub enum Error {
    /// Indicates an error from any underlying IO
    Io(io::Error),
    /// Indicates an error during terminfo parsing
    TerminfoParsing(terminfo::Error),
    /// Indicates an error expanding a parameterized string from the terminfo database
    ParameterizedExpansion(terminfo::parm::Error),
    /// Indicates that the terminal does not support the requested operation.
    NotSupported,
    /// Indicates that the `TERM` environment variable was unset, and thus we were unable to detect
    /// which terminal we should be using.
    TermUnset,
    /// Indicates that we were unable to find a terminfo entry for the requested terminal.
    TerminfoEntryNotFound,
    /// Indicates that the cursor could not be moved to the requested position.
    CursorDestinationInvalid,
    /// Indicates that the terminal does not support displaying the requested color.
    ///
    /// This is like `NotSupported`, but more specific.
    ColorOutOfRange,
    #[doc(hidden)]
    /// Please don't match against this - if you do, we can't promise we won't break your crate
    /// with a semver-compliant version bump.
    __Nonexhaustive,
}

// manually implemented because std::io::Error does not implement Eq/PartialEq
impl std::cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        use Error::*;
        match *self {
            Io(_) => false,
            TerminfoParsing(ref inner1) => {
                match *other {
                    TerminfoParsing(ref inner2) => inner1 == inner2,
                    _ => false,
                }
            }
            ParameterizedExpansion(ref inner1) => {
                match *other {
                    ParameterizedExpansion(ref inner2) => inner1 == inner2,
                    _ => false,
                }
            }
            NotSupported => {
                match *other {
                    NotSupported => true,
                    _ => false,
                }
            }
            TermUnset => {
                match *other {
                    TermUnset => true,
                    _ => false,
                }
            }
            TerminfoEntryNotFound => {
                match *other {
                    TerminfoEntryNotFound => true,
                    _ => false,
                }
            }
            CursorDestinationInvalid => {
                match *other {
                    CursorDestinationInvalid => true,
                    _ => false,
                }
            }
            ColorOutOfRange => {
                match *other {
                    ColorOutOfRange => true,
                    _ => false,
                }
            }
            __Nonexhaustive => {
                match *other {
                    __Nonexhaustive => true,
                    _ => false,
                }
            }
        }
    }
}

/// The canonical `Result` type using this crate's Error type.
pub type Result<T> = std::result::Result<T, Error>;

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use std::error::Error;
        if let ::Error::Io(ref e) = *self {
            write!(f, "{}", e)
        } else {
            f.write_str(self.description())
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;
        match *self {
            Io(ref io) => io.description(),
            TerminfoParsing(ref e) => e.description(),
            ParameterizedExpansion(ref e) => e.description(),
            NotSupported => "operation not supported by the terminal",
            TermUnset => "TERM environment variable unset, unable to detect a terminal",
            TerminfoEntryNotFound => "could not find a terminfo entry for this terminal",
            CursorDestinationInvalid => "could not move cursor to requested position",
            ColorOutOfRange => "color not supported by the terminal",
            __Nonexhaustive => "placeholder variant that shouldn't be used",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref io) => Some(io),
            Error::TerminfoParsing(ref e) => Some(e),
            Error::ParameterizedExpansion(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        let kind = match err {
            Error::Io(ref e) => e.kind(),
            _ => io::ErrorKind::Other,
        };
        io::Error::new(kind, err)
    }
}

impl std::convert::From<io::Error> for Error {
    fn from(val: io::Error) -> Self {
        Error::Io(val)
    }
}

impl std::convert::From<terminfo::Error> for Error {
    fn from(val: terminfo::Error) -> Self {
        Error::TerminfoParsing(val)
    }
}

impl std::convert::From<terminfo::parm::Error> for Error {
    fn from(val: terminfo::parm::Error) -> Self {
        Error::ParameterizedExpansion(val)
    }
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal: Write {
    /// The terminal's output writer type.
    type Output: Write;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there
    /// was an error.
    fn fg(&mut self, color: color::Color) -> Result<()>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there
    /// was an error.
    fn bg(&mut self, color: color::Color) -> Result<()>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(())` if the attribute is
    /// supported and was sent to the terminal, or `Err(e)` if there was an error or the attribute
    /// wasn't supported.
    fn attr(&mut self, attr: Attr) -> Result<()>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: Attr) -> bool;

    /// Resets all terminal attributes and colors to their defaults.
    ///
    /// Returns `Ok(())` if the reset code was printed, or `Err(e)` if there was an error.
    ///
    /// *Note: This does not flush.*
    ///
    /// That means the reset command may get buffered so, if you aren't planning on doing anything
    /// else that might flush stdout's buffer (e.g. writing a line of text), you should flush after
    /// calling reset.
    fn reset(&mut self) -> Result<()>;

    /// Returns true if reset is supported.
    fn supports_reset(&self) -> bool;

    /// Returns true if color is fully supported.
    ///
    /// If this function returns `true`, `bg`, `fg`, and `reset` will never
    /// return `Err(Error::NotSupported)`.
    fn supports_color(&self) -> bool;

    /// Moves the cursor up one line.
    ///
    /// Returns `Ok(())` if the cursor movement code was printed, or `Err(e)` if there was an
    /// error.
    fn cursor_up(&mut self) -> Result<()>;

    /// Deletes the text from the cursor location to the end of the line.
    ///
    /// Returns `Ok(())` if the deletion code was printed, or `Err(e)` if there was an error.
    fn delete_line(&mut self) -> Result<()>;

    /// Moves the cursor to the left edge of the current line.
    ///
    /// Returns `Ok(true)` if the deletion code was printed, or `Err(e)` if there was an error.
    fn carriage_return(&mut self) -> Result<()>;

    /// Gets an immutable reference to the stream inside
    fn get_ref(&self) -> &Self::Output;

    /// Gets a mutable reference to the stream inside
    fn get_mut(&mut self) -> &mut Self::Output;

    /// Returns the contained stream, destroying the `Terminal`
    fn into_inner(self) -> Self::Output where Self: Sized;
}
<commit_msg>Documented version number matches crates.io.<commit_after>// Copyright 2013-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.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two
//! implementations, the `TerminfoTerminal`, which uses control characters from
//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/term) and can be
//! used by adding `term` to the dependencies in your project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//!
//! term = "0.4.5"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate term;
//! ```
//!
//! # Examples
//!
//! ```no_run
//! extern crate term;
//! use std::io::prelude::*;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     write!(t, "hello, ").unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     writeln!(t, "world!").unwrap();
//!
//!     t.reset().unwrap();
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://stebalien.github.io/doc/term/term/",
       test(attr(deny(warnings))))]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

use std::io::prelude::*;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::{self, Stdout, Stderr};

pub mod terminfo;

#[cfg(windows)]
mod win;

/// Alias for stdout terminals.
pub type StdoutTerminal = Terminal<Output = Stdout> + Send;
/// Alias for stderr terminals.
pub type StderrTerminal = Terminal<Output = Stderr> + Send;

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout())
        .map(|t| Box::new(t) as Box<StdoutTerminal>)
        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr())
        .map(|t| Box::new(t) as Box<StderrTerminal>)
        .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
}

/// Terminal color definitions
#[allow(missing_docs)]
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub const BLACK: Color = 0;
    pub const RED: Color = 1;
    pub const GREEN: Color = 2;
    pub const YELLOW: Color = 3;
    pub const BLUE: Color = 4;
    pub const MAGENTA: Color = 5;
    pub const CYAN: Color = 6;
    pub const WHITE: Color = 7;

    pub const BRIGHT_BLACK: Color = 8;
    pub const BRIGHT_RED: Color = 9;
    pub const BRIGHT_GREEN: Color = 10;
    pub const BRIGHT_YELLOW: Color = 11;
    pub const BRIGHT_BLUE: Color = 12;
    pub const BRIGHT_MAGENTA: Color = 13;
    pub const BRIGHT_CYAN: Color = 14;
    pub const BRIGHT_WHITE: Color = 15;
}

/// Terminal attributes for use with term.attr().
///
/// Most attributes can only be turned on and must be turned off with term.reset().
/// The ones that can be turned off explicitly take a boolean value.
/// Color is also represented as an attribute for convenience.
#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)]
pub enum Attr {
    /// Bold (or possibly bright) mode
    Bold,
    /// Dim mode, also called faint or half-bright. Often not supported
    Dim,
    /// Italics mode. Often not supported
    Italic(bool),
    /// Underline mode
    Underline(bool),
    /// Blink mode
    Blink,
    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
    Standout(bool),
    /// Reverse mode, inverts the foreground and background colors
    Reverse,
    /// Secure mode, also called invis mode. Hides the printed text
    Secure,
    /// Convenience attribute to set the foreground color
    ForegroundColor(color::Color),
    /// Convenience attribute to set the background color
    BackgroundColor(color::Color),
}

/// An error arising from interacting with the terminal.
#[derive(Debug)]
pub enum Error {
    /// Indicates an error from any underlying IO
    Io(io::Error),
    /// Indicates an error during terminfo parsing
    TerminfoParsing(terminfo::Error),
    /// Indicates an error expanding a parameterized string from the terminfo database
    ParameterizedExpansion(terminfo::parm::Error),
    /// Indicates that the terminal does not support the requested operation.
    NotSupported,
    /// Indicates that the `TERM` environment variable was unset, and thus we were unable to detect
    /// which terminal we should be using.
    TermUnset,
    /// Indicates that we were unable to find a terminfo entry for the requested terminal.
    TerminfoEntryNotFound,
    /// Indicates that the cursor could not be moved to the requested position.
    CursorDestinationInvalid,
    /// Indicates that the terminal does not support displaying the requested color.
    ///
    /// This is like `NotSupported`, but more specific.
    ColorOutOfRange,
    #[doc(hidden)]
    /// Please don't match against this - if you do, we can't promise we won't break your crate
    /// with a semver-compliant version bump.
    __Nonexhaustive,
}

// manually implemented because std::io::Error does not implement Eq/PartialEq
impl std::cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        use Error::*;
        match *self {
            Io(_) => false,
            TerminfoParsing(ref inner1) => {
                match *other {
                    TerminfoParsing(ref inner2) => inner1 == inner2,
                    _ => false,
                }
            }
            ParameterizedExpansion(ref inner1) => {
                match *other {
                    ParameterizedExpansion(ref inner2) => inner1 == inner2,
                    _ => false,
                }
            }
            NotSupported => {
                match *other {
                    NotSupported => true,
                    _ => false,
                }
            }
            TermUnset => {
                match *other {
                    TermUnset => true,
                    _ => false,
                }
            }
            TerminfoEntryNotFound => {
                match *other {
                    TerminfoEntryNotFound => true,
                    _ => false,
                }
            }
            CursorDestinationInvalid => {
                match *other {
                    CursorDestinationInvalid => true,
                    _ => false,
                }
            }
            ColorOutOfRange => {
                match *other {
                    ColorOutOfRange => true,
                    _ => false,
                }
            }
            __Nonexhaustive => {
                match *other {
                    __Nonexhaustive => true,
                    _ => false,
                }
            }
        }
    }
}

/// The canonical `Result` type using this crate's Error type.
pub type Result<T> = std::result::Result<T, Error>;

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use std::error::Error;
        if let ::Error::Io(ref e) = *self {
            write!(f, "{}", e)
        } else {
            f.write_str(self.description())
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;
        match *self {
            Io(ref io) => io.description(),
            TerminfoParsing(ref e) => e.description(),
            ParameterizedExpansion(ref e) => e.description(),
            NotSupported => "operation not supported by the terminal",
            TermUnset => "TERM environment variable unset, unable to detect a terminal",
            TerminfoEntryNotFound => "could not find a terminfo entry for this terminal",
            CursorDestinationInvalid => "could not move cursor to requested position",
            ColorOutOfRange => "color not supported by the terminal",
            __Nonexhaustive => "placeholder variant that shouldn't be used",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref io) => Some(io),
            Error::TerminfoParsing(ref e) => Some(e),
            Error::ParameterizedExpansion(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        let kind = match err {
            Error::Io(ref e) => e.kind(),
            _ => io::ErrorKind::Other,
        };
        io::Error::new(kind, err)
    }
}

impl std::convert::From<io::Error> for Error {
    fn from(val: io::Error) -> Self {
        Error::Io(val)
    }
}

impl std::convert::From<terminfo::Error> for Error {
    fn from(val: terminfo::Error) -> Self {
        Error::TerminfoParsing(val)
    }
}

impl std::convert::From<terminfo::parm::Error> for Error {
    fn from(val: terminfo::parm::Error) -> Self {
        Error::ParameterizedExpansion(val)
    }
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal: Write {
    /// The terminal's output writer type.
    type Output: Write;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there
    /// was an error.
    fn fg(&mut self, color: color::Color) -> Result<()>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there
    /// was an error.
    fn bg(&mut self, color: color::Color) -> Result<()>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(())` if the attribute is
    /// supported and was sent to the terminal, or `Err(e)` if there was an error or the attribute
    /// wasn't supported.
    fn attr(&mut self, attr: Attr) -> Result<()>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: Attr) -> bool;

    /// Resets all terminal attributes and colors to their defaults.
    ///
    /// Returns `Ok(())` if the reset code was printed, or `Err(e)` if there was an error.
    ///
    /// *Note: This does not flush.*
    ///
    /// That means the reset command may get buffered so, if you aren't planning on doing anything
    /// else that might flush stdout's buffer (e.g. writing a line of text), you should flush after
    /// calling reset.
    fn reset(&mut self) -> Result<()>;

    /// Returns true if reset is supported.
    fn supports_reset(&self) -> bool;

    /// Returns true if color is fully supported.
    ///
    /// If this function returns `true`, `bg`, `fg`, and `reset` will never
    /// return `Err(Error::NotSupported)`.
    fn supports_color(&self) -> bool;

    /// Moves the cursor up one line.
    ///
    /// Returns `Ok(())` if the cursor movement code was printed, or `Err(e)` if there was an
    /// error.
    fn cursor_up(&mut self) -> Result<()>;

    /// Deletes the text from the cursor location to the end of the line.
    ///
    /// Returns `Ok(())` if the deletion code was printed, or `Err(e)` if there was an error.
    fn delete_line(&mut self) -> Result<()>;

    /// Moves the cursor to the left edge of the current line.
    ///
    /// Returns `Ok(true)` if the deletion code was printed, or `Err(e)` if there was an error.
    fn carriage_return(&mut self) -> Result<()>;

    /// Gets an immutable reference to the stream inside
    fn get_ref(&self) -> &Self::Output;

    /// Gets a mutable reference to the stream inside
    fn get_mut(&mut self) -> &mut Self::Output;

    /// Returns the contained stream, destroying the `Terminal`
    fn into_inner(self) -> Self::Output where Self: Sized;
}
<|endoftext|>


<commit_before>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
#![warn(missing_docs)]

// Re-exported external crates
pub use libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
#[cfg(not(target_os = "redox"))]
#[allow(missing_docs)]
pub mod dir;
pub mod env;
#[allow(missing_docs)]
pub mod errno;
pub mod features;
#[allow(missing_docs)]
pub mod fcntl;
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "illumos",
          target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "android",
          target_os = "linux"))]
#[allow(missing_docs)]
pub mod kmod;
#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "linux"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
#[allow(missing_docs)]
pub mod mqueue;
#[cfg(not(target_os = "redox"))]
pub mod net;
pub mod poll;
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
pub mod pty;
pub mod sched;
pub mod sys;
#[allow(missing_docs)]
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
#[allow(missing_docs)]
pub mod ucontext;
#[allow(missing_docs)]
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::{c_char, PATH_MAX};

use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Errno>;

/// Nix's main error type.
///
/// It's a wrapper around Errno.  As such, it's very interoperable with
/// [`std::io::Error`], but it has the advantages of:
/// * `Clone`
/// * `Copy`
/// * `Eq`
/// * Small size
/// * Represents all of the system's errnos, instead of just the most common
/// ones.
pub type Error = Errno;

/// Common trait used to represent file system paths by many Nix functions.
pub trait NixPath {
    /// Is the path empty?
    fn is_empty(&self) -> bool;

    /// Length of the path in bytes
    fn len(&self) -> usize;

    /// Execute a function with this path as a `CStr`.
    ///
    /// Mostly used internally by Nix.
    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(OsStr::new(self))
    }

    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn is_empty(&self) -> bool {
        self.as_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn is_empty(&self) -> bool {
        self.to_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Errno::ENAMETOOLONG)
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn is_empty(&self) -> bool {
        self.is_empty()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Errno::ENAMETOOLONG)
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Errno::EINVAL),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}
<commit_msg>Remove unsafe in with_nix_path() for [u8]<commit_after>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
#![warn(missing_docs)]

// Re-exported external crates
pub use libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
#[cfg(not(target_os = "redox"))]
#[allow(missing_docs)]
pub mod dir;
pub mod env;
#[allow(missing_docs)]
pub mod errno;
pub mod features;
#[allow(missing_docs)]
pub mod fcntl;
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "illumos",
          target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "android",
          target_os = "linux"))]
#[allow(missing_docs)]
pub mod kmod;
#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "linux"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
#[allow(missing_docs)]
pub mod mqueue;
#[cfg(not(target_os = "redox"))]
pub mod net;
pub mod poll;
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
pub mod pty;
pub mod sched;
pub mod sys;
#[allow(missing_docs)]
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
#[allow(missing_docs)]
pub mod ucontext;
#[allow(missing_docs)]
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::PATH_MAX;

use std::result;
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Errno>;

/// Nix's main error type.
///
/// It's a wrapper around Errno.  As such, it's very interoperable with
/// [`std::io::Error`], but it has the advantages of:
/// * `Clone`
/// * `Copy`
/// * `Eq`
/// * Small size
/// * Represents all of the system's errnos, instead of just the most common
/// ones.
pub type Error = Errno;

/// Common trait used to represent file system paths by many Nix functions.
pub trait NixPath {
    /// Is the path empty?
    fn is_empty(&self) -> bool;

    /// Length of the path in bytes
    fn len(&self) -> usize;

    /// Execute a function with this path as a `CStr`.
    ///
    /// Mostly used internally by Nix.
    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(OsStr::new(self))
    }

    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn is_empty(&self) -> bool {
        self.as_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn is_empty(&self) -> bool {
        self.to_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Errno::ENAMETOOLONG)
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn is_empty(&self) -> bool {
        self.is_empty()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Errno::ENAMETOOLONG)
        }

        buf[..self.len()].copy_from_slice(self);
        match CStr::from_bytes_with_nul(&buf[..=self.len()]) {
            Ok(s) => Ok(f(s)),
            Err(_) => Err(Errno::EINVAL),
        }
    }
}

impl NixPath for Path {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde_json;
extern crate url;

mod lines;

use futures::{Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use lines::Lines;
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, BufReader};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Token<'a>(pub &'a str, pub &'a str);

pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    end_point: Option<&'a str>,
    client: Option<&'a Client>,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream {
    lines: Lines,
}

pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut,
    InternalPanicError,
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login(&self) -> Result<TwitterUserStream> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: lines::lines(BufReader::new(res))
        })
    }
}

impl TwitterUserStream {
    pub fn login<'a>(consumer: Token<'a>, token: Token<'a>) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login()
    }
}

impl Stream for TwitterUserStream {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        self.lines.poll()
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Url(ref e) => e.description(),
            &Error::Hyper(ref e) => e.description(),
            &Error::Http(ref status) => status.canonical_reason().unwrap_or("unknown HTTP error"),
            &Error::Io(ref e) => e.description(),
            &Error::TimedOut => "the connection has timed out",
            &Error::InternalPanicError => "internal error: sender panicked",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match self {
            &Error::Url(ref e) => e.cause(),
            &Error::Hyper(ref e) => e.cause(),
            &Error::Http(_) => None,
            &Error::Io(ref e) => e.cause(),
            &Error::TimedOut => None,
            &Error::InternalPanicError => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<commit_msg>Implement timeout<commit_after>extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde_json;
extern crate tokio_core;
extern crate url;

mod lines;

use futures::{Async, Future, Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use lines::Lines;
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, BufReader};
use std::time::Duration;
use tokio_core::reactor::{Handle, Timeout};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Token<'a>(pub &'a str, pub &'a str);

pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    client: Option<&'a Client>,
    end_point: Option<&'a str>,
    timeout: Duration,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream<'a> {
    lines: Lines,
    timeout: Duration,
    handle: &'a Handle,
    timer: Timeout,
}

pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut,
    InternalPanicError,
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            timeout: Duration::from_secs(95),
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login<'b>(&self, handle: &'b Handle) -> Result<TwitterUserStream<'b>> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: lines::lines(BufReader::new(res)),
            timeout: self.timeout,
            handle: handle,
            timer: Timeout::new(self.timeout, handle)?,
        })
    }
}

impl<'a> TwitterUserStream<'a> {
    pub fn login<'b>(consumer: Token<'b>, token: Token<'b>, handle: &'a Handle) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login(handle)
    }
}

impl<'a> Stream for TwitterUserStream<'a> {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        trace!("TwitterUserStream::poll");
        loop {
            match self.lines.poll()? {
                Async::Ready(line_opt) => {
                    self.timer = Timeout::new(self.timeout, self.handle)?;
                    match line_opt {
                        Some(line) => {
                            if !line.is_empty() {
                                return Ok(Some(line).into());
                            }
                        },
                        None => return Ok(None.into()),
                    }
                },
                Async::NotReady => {
                    if let Async::Ready(_) = self.timer.poll()? {
                        return Err(Error::TimedOut);
                    }
                },
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Url(ref e) => e.description(),
            &Error::Hyper(ref e) => e.description(),
            &Error::Http(ref status) => status.canonical_reason().unwrap_or("unknown HTTP error"),
            &Error::Io(ref e) => e.description(),
            &Error::TimedOut => "the connection has timed out",
            &Error::InternalPanicError => "internal error: sender panicked",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self {
            &Error::Url(ref e) => e.cause(),
            &Error::Hyper(ref e) => e.cause(),
            &Error::Http(_) => None,
            &Error::Io(ref e) => e.cause(),
            &Error::TimedOut => None,
            &Error::InternalPanicError => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```rust
//! extern crate serde_yaml;
//!
//! use std::collections::BTreeMap;
//!
//! // You have some type.
//! let mut map = BTreeMap::new();
//! map.insert("x".to_string(), 1.0);
//! map.insert("y".to_string(), 2.0);
//!
//! // Serialize it to a YAML string.
//! let s = serde_yaml::to_string(&map).unwrap();
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! // Deserialize it back to a Rust type.
//! let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s).unwrap();
//! assert_eq!(map, deserialized_map);
//! ```
//!
//! ## Using serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```rust
//! #[macro_use] extern crate serde_derive;
//! extern crate serde_yaml;
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point { x: f64, y: f64 }
//!
//! # fn main() {
//! let point = Point { x: 1.0, y: 2.0 };
//!
//! let s = serde_yaml::to_string(&point).unwrap();
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! let deserialized_point: Point = serde_yaml::from_str(&s).unwrap();
//! assert_eq!(point, deserialized_point);
//! # }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.7.3")]

#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// private Deserializer::next
    should_implement_trait,
// things are often more readable this way
    cast_lossless,
    single_match_else,
    stutter,
    use_self,
// not practical
    missing_docs_in_private_items,
// not stable
    empty_enum,
))]

extern crate dtoa;
extern crate linked_hash_map;
extern crate num_traits;
#[macro_use]
extern crate serde;
extern crate yaml_rust;

pub use self::de::{from_reader, from_slice, from_str};
pub use self::ser::{to_string, to_vec, to_writer};
pub use self::value::{Sequence, Value, from_value, to_value, Number};
pub use self::error::{Error, Location, Result};
pub use self::mapping::Mapping;

mod de;
mod ser;
mod value;
mod error;
mod path;
mod mapping;
mod number;
<commit_msg>Ignore result_unwrap_used lint<commit_after>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```rust
//! extern crate serde_yaml;
//!
//! use std::collections::BTreeMap;
//!
//! // You have some type.
//! let mut map = BTreeMap::new();
//! map.insert("x".to_string(), 1.0);
//! map.insert("y".to_string(), 2.0);
//!
//! // Serialize it to a YAML string.
//! let s = serde_yaml::to_string(&map).unwrap();
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! // Deserialize it back to a Rust type.
//! let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s).unwrap();
//! assert_eq!(map, deserialized_map);
//! ```
//!
//! ## Using serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```rust
//! #[macro_use] extern crate serde_derive;
//! extern crate serde_yaml;
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point { x: f64, y: f64 }
//!
//! # fn main() {
//! let point = Point { x: 1.0, y: 2.0 };
//!
//! let s = serde_yaml::to_string(&point).unwrap();
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! let deserialized_point: Point = serde_yaml::from_str(&s).unwrap();
//! assert_eq!(point, deserialized_point);
//! # }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.7.3")]

#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// private Deserializer::next
    should_implement_trait,
// things are often more readable this way
    cast_lossless,
    single_match_else,
    stutter,
    use_self,
// not practical
    missing_docs_in_private_items,
// not stable
    empty_enum,
// meh, some things won't fail
    result_unwrap_used,
))]

extern crate dtoa;
extern crate linked_hash_map;
extern crate num_traits;
#[macro_use]
extern crate serde;
extern crate yaml_rust;

pub use self::de::{from_reader, from_slice, from_str};
pub use self::ser::{to_string, to_vec, to_writer};
pub use self::value::{Sequence, Value, from_value, to_value, Number};
pub use self::error::{Error, Location, Result};
pub use self::mapping::Mapping;

mod de;
mod ser;
mod value;
mod error;
mod path;
mod mapping;
mod number;
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate "rustc-serialize" as rustc_serialize;

pub mod hpack;
pub mod http;
pub mod client;

mod tests {
}
<commit_msg>Add feature annotations for currently unstable features used<commit_after>#![feature(io, net, core, std_misc)]

#[macro_use] extern crate log;
extern crate "rustc-serialize" as rustc_serialize;

pub mod hpack;
pub mod http;
pub mod client;

mod tests {
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate time;
extern crate tiny_http;

pub use assets::match_assets;
pub use log::LogEntry;

use std::str::FromStr;

mod assets;
mod input;
mod log;
mod router;

pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    WrongInput,
}

pub struct Server {
    #[inline]
    server: tiny_http::Server,
}

impl Server {
    pub fn start() -> Server {
        Server {
            server: tiny_http::ServerBuilder::new().with_port(8000).build().unwrap(),
        }
    }
}

impl IntoIterator for Server {
    type Item = Request;
    type IntoIter = IncomingRequests;

    #[inline]
    fn into_iter(self) -> IncomingRequests {
        IncomingRequests { server: self.server }
    }
}

pub struct IncomingRequests {
    server: tiny_http::Server,
}

impl Iterator for IncomingRequests {
    type Item = Request;

    #[inline]
    fn next(&mut self) -> Option<Request> {
        Some(Request {
            request: self.server.recv().unwrap(),
        })
    }
}

/// Represents a request made by the client.
pub struct Request {
    request: tiny_http::Request,
}

impl Request {
    /// Returns the URL requested by the client. It is not decoded and thus can contain `%20` or
    /// other characters.
    #[inline]
    pub fn url(&self) -> &str {
        self.request.url()
    }

    /// Consumes the `Request` and sends the response to the client.
    #[inline]
    pub fn respond(self, response: Response) {
        self.request.respond(response.response)
    }

    /// Utility function similar to `respond`, but builds the "default" response corresponding to
    /// the `RouteError`.
    #[inline]
    pub fn respond_to_error(self, err: &RouteError) {
        let response = match err {
            &RouteError::NoRouteFound => tiny_http::Response::empty(404),
            &RouteError::WrongInput => tiny_http::Response::empty(400),
        };

        self.request.respond(response);
    }
}

/// Contains a prototype of a response. The response is only sent when you call `Request::respond`.
pub struct Response {
    response: tiny_http::ResponseBox,
}

impl Response {
    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        let response = tiny_http::Response::empty(303);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str(&format!("Location: {}", target)).unwrap());

        Response { response: response.boxed() }
    }
}
<commit_msg>Add Response::html<commit_after>extern crate rustc_serialize;
extern crate time;
extern crate tiny_http;

pub use assets::match_assets;
pub use log::LogEntry;

use std::str::FromStr;

mod assets;
mod input;
mod log;
mod router;

pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    WrongInput,
}

pub struct Server {
    #[inline]
    server: tiny_http::Server,
}

impl Server {
    pub fn start() -> Server {
        Server {
            server: tiny_http::ServerBuilder::new().with_port(8000).build().unwrap(),
        }
    }
}

impl IntoIterator for Server {
    type Item = Request;
    type IntoIter = IncomingRequests;

    #[inline]
    fn into_iter(self) -> IncomingRequests {
        IncomingRequests { server: self.server }
    }
}

pub struct IncomingRequests {
    server: tiny_http::Server,
}

impl Iterator for IncomingRequests {
    type Item = Request;

    #[inline]
    fn next(&mut self) -> Option<Request> {
        Some(Request {
            request: self.server.recv().unwrap(),
        })
    }
}

/// Represents a request made by the client.
pub struct Request {
    request: tiny_http::Request,
}

impl Request {
    /// Returns the URL requested by the client. It is not decoded and thus can contain `%20` or
    /// other characters.
    #[inline]
    pub fn url(&self) -> &str {
        self.request.url()
    }

    /// Consumes the `Request` and sends the response to the client.
    #[inline]
    pub fn respond(self, response: Response) {
        self.request.respond(response.response)
    }

    /// Utility function similar to `respond`, but builds the "default" response corresponding to
    /// the `RouteError`.
    #[inline]
    pub fn respond_to_error(self, err: &RouteError) {
        let response = match err {
            &RouteError::NoRouteFound => tiny_http::Response::empty(404),
            &RouteError::WrongInput => tiny_http::Response::empty(400),
        };

        self.request.respond(response);
    }
}

/// Contains a prototype of a response. The response is only sent when you call `Request::respond`.
pub struct Response {
    response: tiny_http::ResponseBox,
}

impl Response {
    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        let response = tiny_http::Response::empty(303);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str(&format!("Location: {}", target)).unwrap());

        Response { response: response.boxed() }
    }

    /// Builds a `Response` that outputs HTML.
    #[inline]
    pub fn html(content: &[u8]) -> Response {
        let response = tiny_http::Response::from_data(content);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str("Content-Type: text/html; charset=utf8").unwrap());

        Response { response: response.boxed() }
    }
}
<|endoftext|>


<commit_before>//! This crate is a Rust port of Google's high-performance [SwissTable] hash
//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
//! and `HashSet` types.
//!
//! The original C++ version of [SwissTable] can be found [here], and this
//! [CppCon talk] gives an overview of how the algorithm works.
//!
//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4

#![no_std]
#![cfg_attr(
    feature = "nightly",
    feature(
        alloc_layout_extra,
        allocator_api,
        ptr_offset_from,
        test,
        core_intrinsics,
        dropck_eyepatch,
        min_specialization,
        extend_one,
    )
)]
#![allow(
    clippy::doc_markdown,
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::option_if_let_else,
)]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(has_extern_crate_alloc)]
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[cfg(not(has_extern_crate_alloc))]
extern crate std as alloc;

#[cfg(feature = "nightly")]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[macro_use]
mod macros;

#[cfg(feature = "raw")]
/// Experimental and unsafe `RawTable` API. This module is only available if the
/// `raw` feature is enabled.
pub mod raw {
    // The RawTable API is still experimental and is not properly documented yet.
    #[allow(missing_docs)]
    #[path = "mod.rs"]
    mod inner;
    pub use inner::*;

    #[cfg(feature = "rayon")]
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::raw::*;
    }
}
#[cfg(not(feature = "raw"))]
mod raw;

mod external_trait_impls;
mod map;
#[cfg(feature = "rustc-internal-api")]
mod rustc_entry;
mod scopeguard;
mod set;

pub mod hash_map {
    //! A hash map implemented with quadratic probing and SIMD lookup.
    pub use crate::map::*;

    #[cfg(feature = "rustc-internal-api")]
    pub use crate::rustc_entry::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash maps.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::map::*;
    }
}
pub mod hash_set {
    //! A hash set implemented as a `HashMap` where the value is `()`.
    pub use crate::set::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash sets.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::set::*;
    }
}

pub use crate::map::HashMap;
pub use crate::set::HashSet;

/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TryReserveError {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,

    /// The memory allocator returned an error
    AllocError {
        /// The layout of the allocation request that failed.
        layout: alloc::alloc::Layout,
    },
}
<commit_msg>Fix a rustfmt error<commit_after>//! This crate is a Rust port of Google's high-performance [SwissTable] hash
//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
//! and `HashSet` types.
//!
//! The original C++ version of [SwissTable] can be found [here], and this
//! [CppCon talk] gives an overview of how the algorithm works.
//!
//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4

#![no_std]
#![cfg_attr(
    feature = "nightly",
    feature(
        alloc_layout_extra,
        allocator_api,
        ptr_offset_from,
        test,
        core_intrinsics,
        dropck_eyepatch,
        min_specialization,
        extend_one,
    )
)]
#![allow(
    clippy::doc_markdown,
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::option_if_let_else
)]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(has_extern_crate_alloc)]
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[cfg(not(has_extern_crate_alloc))]
extern crate std as alloc;

#[cfg(feature = "nightly")]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[macro_use]
mod macros;

#[cfg(feature = "raw")]
/// Experimental and unsafe `RawTable` API. This module is only available if the
/// `raw` feature is enabled.
pub mod raw {
    // The RawTable API is still experimental and is not properly documented yet.
    #[allow(missing_docs)]
    #[path = "mod.rs"]
    mod inner;
    pub use inner::*;

    #[cfg(feature = "rayon")]
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::raw::*;
    }
}
#[cfg(not(feature = "raw"))]
mod raw;

mod external_trait_impls;
mod map;
#[cfg(feature = "rustc-internal-api")]
mod rustc_entry;
mod scopeguard;
mod set;

pub mod hash_map {
    //! A hash map implemented with quadratic probing and SIMD lookup.
    pub use crate::map::*;

    #[cfg(feature = "rustc-internal-api")]
    pub use crate::rustc_entry::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash maps.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::map::*;
    }
}
pub mod hash_set {
    //! A hash set implemented as a `HashMap` where the value is `()`.
    pub use crate::set::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash sets.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::set::*;
    }
}

pub use crate::map::HashMap;
pub use crate::set::HashSet;

/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TryReserveError {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,

    /// The memory allocator returned an error
    AllocError {
        /// The layout of the allocation request that failed.
        layout: alloc::alloc::Layout,
    },
}
<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate core;

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

use core::cell::{Cell, RefCell};
#[cfg(feature = "alloc")]
use core::ops::Deref;
use core::ptr::{self, NonNull};
#[cfg(feature = "std")]
use std::ffi::{CStr, CString};
#[cfg(feature = "std")]
use std::os::raw::c_char;

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::sync::Arc;

macro_rules! asptr_wrapper {
    ($name:ident) => {
        impl<T> AsPtr for $name<T> {
            type Raw = T;
            #[inline]
            fn as_ptr(&self) -> *const T {
                $name::as_ptr(self)
            }
        }
    };
}

#[cfg(feature = "alloc")]
macro_rules! owned_ptr_wrapper {
    ($name:ident) => {
        impl<T> IntoRaw for $name<T> {
            type Raw = T;
            fn into_raw(self) -> *mut T {
                $name::into_raw(self) as *mut T
            }
        }
        impl<T> FromRaw<T> for $name<T> {
            unsafe fn from_raw(raw: *mut T) -> $name<T> {
                $name::from_raw(raw)
            }
        }
    };
}

/// Trait for types that implement `as_ptr`.
///
/// This is implemented by types which can be converted
/// to a pointer from a borrowed reference.
///
/// # Example
/// ```
/// use ptrplus::AsPtr;
///
/// let x: &u32 = &5;
/// let y: *const u32 = x.as_ptr();
/// unsafe {
///     assert_eq!(*y, 5);
/// }
/// ```
///
/// ```
/// use ptrplus::AsPtr;
///
/// let x = 5;
/// let o1: Option<&u32> = None;
/// let o2: Option<&u32> = Some(&x);
///
/// assert!(o1.as_ptr().is_null());
/// assert!(!o2.as_ptr().is_null());
/// unsafe {
///     assert_eq!(*o2.as_ptr(), 5);
/// }
/// ```
pub trait AsPtr {
    /// The type pointed to
    ///
    /// `as_ptr` will return a pointer to this type
    type Raw;

    /// Returns a raw pointer to the contained content
    ///
    /// The caller must ensure `self` outlives the pointer
    /// that is returned, or else it will end up pointing
    /// to garbage.
    ///
    /// Mutating `self` may also invalidate this pointer,
    /// depending on the implementation.
    fn as_ptr(&self) -> *const Self::Raw;
}

impl<T> AsPtr for [T] {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        <[T]>::as_ptr(self)
    }
}

impl<'a, T> AsPtr for &'a T
where
    T: Sized,
{
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        *self as *const T
    }
}

impl<T> AsPtr for NonNull<T> {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        NonNull::as_ptr(*self)
    }
}

impl<T> AsPtr for *const T {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        *self
    }
}

#[cfg(feature = "std")]
impl AsPtr for CStr {
    type Raw = c_char;
    #[inline]
    fn as_ptr(&self) -> *const c_char {
        CStr::as_ptr(self)
    }
}

#[cfg(feature = "std")]
impl AsPtr for CString {
    type Raw = c_char;
    #[inline]
    fn as_ptr(&self) -> *const c_char {
        CStr::as_ptr(self)
    }
}

#[cfg(feature = "alloc")]
impl<T> AsPtr for Box<T> {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        self.deref().as_ptr()
    }
}

impl<T> AsPtr for Option<T>
where
    T: AsPtr,
{
    type Raw = T::Raw;
    #[inline]
    fn as_ptr(&self) -> *const T::Raw {
        match self {
            Some(ref v) => v.as_ptr(),
            None => ptr::null(),
        }
    }
}

asptr_wrapper!(Cell);
asptr_wrapper!(RefCell);
#[cfg(feature = "alloc")]
asptr_wrapper!(Rc);
#[cfg(feature = "alloc")]
asptr_wrapper!(Arc);

/// Trait for types that implement `into_raw`
///
/// This is implemented by types that can be converted
/// into a pointer by consuming ownership of the object
///
/// # Example
/// ```
/// use ptrplus::IntoRaw;
///
/// let x: Box<u32> = Box::new(5);
/// let y: *mut u32 = IntoRaw::into_raw(x);
/// unsafe {
///   assert_eq!(*y, 5);
///   *y = 6;
///   Box::from_raw(y);
/// }
///
/// ```
///
/// ```
/// use ptrplus::{FromRaw, IntoRaw};
///
/// let o1: Option<Box<u32>> = None;
/// let o2: Option<Box<u32>> = Some(Box::new(5));
///
/// let p1: *mut u32 = o1.into_raw();
/// let p2: *mut u32 = o2.into_raw();
///
/// assert!(p1.is_null());
/// assert!(!p2.is_null());
/// unsafe {
///     assert_eq!(*p2, 5);
///     let o1: Option<Box<u32>> = Option::from_raw(p1);
///     let o2: Option<Box<u32>> = Option::from_raw(p2);
///     assert!(o1.is_none());
///     assert!(!o2.is_none());
/// }
/// ```
pub trait IntoRaw {
    /// The type pointed to
    ///
    /// `into_raw` returns a mutable pointer to this type
    type Raw;

    /// Consumes `self` returning the wrapped raw pointer.
    ///
    /// After calling this method, the caller is responsable
    /// for making sure any resources attached to this pointer
    /// (such as memory) are cleaned up. The proper way to do this
    /// is to convert the pointer back to `Self`.
    ///
    /// See `FromRaw`
    fn into_raw(self) -> *mut Self::Raw;
}

#[cfg(feature = "std")]
impl IntoRaw for CString {
    type Raw = c_char;
    #[inline]
    fn into_raw(self) -> *mut c_char {
        CString::into_raw(self)
    }
}

impl<T> IntoRaw for *mut T {
    type Raw = T;
    #[inline]
    fn into_raw(self) -> *mut T {
        self
    }
}

impl<T> IntoRaw for NonNull<T> {
    type Raw = T;
    #[inline]
    fn into_raw(self) -> *mut T {
        self.as_ptr()
    }
}

impl<T> IntoRaw for Option<T>
where
    T: IntoRaw,
{
    type Raw = T::Raw;
    #[inline]
    fn into_raw(self) -> *mut T::Raw {
        match self {
            Some(v) => v.into_raw(),
            None => ptr::null_mut(),
        }
    }
}

/// Trait for types that can be created from a raw pointer
///
/// # Examples
/// ```
/// use ptrplus::{FromRaw, IntoRaw};
///
/// let x: Box<u32> = Box::new(5);
/// let y = x.into_raw();
/// let z: Box<u32> = unsafe { FromRaw::from_raw(y) };
/// assert_eq!(*z, 5);
///
/// ```
///
pub trait FromRaw<T> {
    /// Create `Self` from a raw pointer
    ///
    /// After calling this method the raw pointer
    /// is owned by the resulting object. This
    /// means that the resulting object should
    /// clean up any resources associated with
    /// the pointer (such as memory).
    ///
    /// # Safety
    ///
    /// `raw` must be a pointer that is compatible with
    /// the resulting type. For example, if `Self` is
    /// `Box<T>`, then `raw` must be a pointer to memory allocated
    /// as a Box. The exact requirements depend on the implementation.
    ///
    /// Generally, the `raw` pointer must be the result of a previous
    /// call to `into_raw` on the corresponding type. This the case for
    /// types such as `Box`, `Rc`, and `Arc`.
    ///
    /// Additionally, this function takes ownership of the pointer. If
    /// `raw` or an alias thereof is used after calling this function
    /// it can potentially result in double-free, data races, or other
    /// undefined behavior.
    unsafe fn from_raw(raw: *mut T) -> Self;
}

#[cfg(feature = "std")]
impl FromRaw<c_char> for CString {
    #[inline]
    unsafe fn from_raw(raw: *mut c_char) -> CString {
        CString::from_raw(raw)
    }
}

/// This implementation is always safe
impl<T> FromRaw<T> for *mut T {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> *mut T {
        raw
    }
}

/// This implementation is always safe
impl<T> FromRaw<T> for *const T {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> *const T {
        raw
    }
}

/// ## Safety
/// The input pointer must be non-null.
///
/// `Option<NonNull<T>>::from_raw` can be used if the pointer may be null.
impl<T> FromRaw<T> for NonNull<T> {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> NonNull<T> {
        NonNull::new_unchecked(raw)
    }
}

/// ## Safety
/// The input pointer must either be null (resulting in `None`), or be safe
/// to convert into the inner pointer type.
impl<T, U> FromRaw<U> for Option<T>
where
    T: FromRaw<U>,
{
    unsafe fn from_raw(raw: *mut U) -> Option<T> {
        if raw.is_null() {
            None
        } else {
            Some(T::from_raw(raw))
        }
    }
}

#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Box);
#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Rc);
#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Arc);
<commit_msg>Add a bunch of tests<commit_after>#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate core;

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

use core::cell::{Cell, RefCell};
#[cfg(feature = "alloc")]
use core::ops::Deref;
use core::ptr::{self, NonNull};
#[cfg(feature = "std")]
use std::ffi::{CStr, CString};
#[cfg(feature = "std")]
use std::os::raw::c_char;

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::sync::Arc;

macro_rules! asptr_wrapper {
    ($name:ident) => {
        impl<T> AsPtr for $name<T> {
            type Raw = T;
            #[inline]
            fn as_ptr(&self) -> *const T {
                $name::as_ptr(self)
            }
        }
    };
}

#[cfg(feature = "alloc")]
macro_rules! owned_ptr_wrapper {
    ($name:ident) => {
        impl<T> IntoRaw for $name<T> {
            type Raw = T;
            fn into_raw(self) -> *mut T {
                $name::into_raw(self) as *mut T
            }
        }
        impl<T> FromRaw<T> for $name<T> {
            unsafe fn from_raw(raw: *mut T) -> $name<T> {
                $name::from_raw(raw)
            }
        }
    };
}

/// Trait for types that implement `as_ptr`.
///
/// This is implemented by types which can be converted
/// to a pointer from a borrowed reference.
///
/// # Example
/// ```
/// use ptrplus::AsPtr;
///
/// let x: &u32 = &5;
/// let y: *const u32 = x.as_ptr();
/// unsafe {
///     assert_eq!(*y, 5);
/// }
/// ```
///
/// ```
/// use ptrplus::AsPtr;
///
/// let x = 5;
/// let o1: Option<&u32> = None;
/// let o2: Option<&u32> = Some(&x);
///
/// assert!(o1.as_ptr().is_null());
/// assert!(!o2.as_ptr().is_null());
/// unsafe {
///     assert_eq!(*o2.as_ptr(), 5);
/// }
/// ```
pub trait AsPtr {
    /// The type pointed to
    ///
    /// `as_ptr` will return a pointer to this type
    type Raw;

    /// Returns a raw pointer to the contained content
    ///
    /// The caller must ensure `self` outlives the pointer
    /// that is returned, or else it will end up pointing
    /// to garbage.
    ///
    /// Mutating `self` may also invalidate this pointer,
    /// depending on the implementation.
    fn as_ptr(&self) -> *const Self::Raw;
}

impl<T> AsPtr for [T] {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        <[T]>::as_ptr(self)
    }
}

impl<'a, T: Sized> AsPtr for &'a T
where
    T: Sized,
{
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        *self as *const T
    }
}

impl<T> AsPtr for NonNull<T> {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        NonNull::as_ptr(*self)
    }
}

impl<T> AsPtr for *const T {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        *self
    }
}

#[cfg(feature = "std")]
impl AsPtr for CStr {
    type Raw = c_char;
    #[inline]
    fn as_ptr(&self) -> *const c_char {
        CStr::as_ptr(self)
    }
}

#[cfg(feature = "std")]
impl AsPtr for CString {
    type Raw = c_char;
    #[inline]
    fn as_ptr(&self) -> *const c_char {
        CStr::as_ptr(self)
    }
}

#[cfg(feature = "alloc")]
impl<T> AsPtr for Box<T> {
    type Raw = T;
    #[inline]
    fn as_ptr(&self) -> *const T {
        self.deref().as_ptr()
    }
}

impl<T> AsPtr for Option<T>
where
    T: AsPtr,
{
    type Raw = T::Raw;
    #[inline]
    fn as_ptr(&self) -> *const T::Raw {
        match self {
            Some(ref v) => v.as_ptr(),
            None => ptr::null(),
        }
    }
}

asptr_wrapper!(Cell);
asptr_wrapper!(RefCell);
#[cfg(feature = "alloc")]
asptr_wrapper!(Rc);
#[cfg(feature = "alloc")]
asptr_wrapper!(Arc);

/// Trait for types that implement `into_raw`
///
/// This is implemented by types that can be converted
/// into a pointer by consuming ownership of the object
///
/// # Example
/// ```
/// use ptrplus::IntoRaw;
///
/// let x: Box<u32> = Box::new(5);
/// let y: *mut u32 = IntoRaw::into_raw(x);
/// unsafe {
///   assert_eq!(*y, 5);
///   *y = 6;
///   Box::from_raw(y);
/// }
///
/// ```
///
/// ```
/// use ptrplus::{FromRaw, IntoRaw};
///
/// let o1: Option<Box<u32>> = None;
/// let o2: Option<Box<u32>> = Some(Box::new(5));
///
/// let p1: *mut u32 = o1.into_raw();
/// let p2: *mut u32 = o2.into_raw();
///
/// assert!(p1.is_null());
/// assert!(!p2.is_null());
/// unsafe {
///     assert_eq!(*p2, 5);
///     let o1: Option<Box<u32>> = Option::from_raw(p1);
///     let o2: Option<Box<u32>> = Option::from_raw(p2);
///     assert!(o1.is_none());
///     assert!(!o2.is_none());
/// }
/// ```
pub trait IntoRaw {
    /// The type pointed to
    ///
    /// `into_raw` returns a mutable pointer to this type
    type Raw;

    /// Consumes `self` returning the wrapped raw pointer.
    ///
    /// After calling this method, the caller is responsable
    /// for making sure any resources attached to this pointer
    /// (such as memory) are cleaned up. The proper way to do this
    /// is to convert the pointer back to `Self`.
    ///
    /// See `FromRaw`
    fn into_raw(self) -> *mut Self::Raw;
}

#[cfg(feature = "std")]
impl IntoRaw for CString {
    type Raw = c_char;
    #[inline]
    fn into_raw(self) -> *mut c_char {
        CString::into_raw(self)
    }
}

impl<T> IntoRaw for *mut T {
    type Raw = T;
    #[inline]
    fn into_raw(self) -> *mut T {
        self
    }
}

impl<T> IntoRaw for NonNull<T> {
    type Raw = T;
    #[inline]
    fn into_raw(self) -> *mut T {
        self.as_ptr()
    }
}

impl<T> IntoRaw for Option<T>
where
    T: IntoRaw,
{
    type Raw = T::Raw;
    #[inline]
    fn into_raw(self) -> *mut T::Raw {
        match self {
            Some(v) => v.into_raw(),
            None => ptr::null_mut(),
        }
    }
}

/// Trait for types that can be created from a raw pointer
///
/// # Examples
/// ```
/// use ptrplus::{FromRaw, IntoRaw};
///
/// let x: Box<u32> = Box::new(5);
/// let y = x.into_raw();
/// let z: Box<u32> = unsafe { FromRaw::from_raw(y) };
/// assert_eq!(*z, 5);
///
/// ```
///
pub trait FromRaw<T> {
    /// Create `Self` from a raw pointer
    ///
    /// After calling this method the raw pointer
    /// is owned by the resulting object. This
    /// means that the resulting object should
    /// clean up any resources associated with
    /// the pointer (such as memory).
    ///
    /// # Safety
    ///
    /// `raw` must be a pointer that is compatible with
    /// the resulting type. For example, if `Self` is
    /// `Box<T>`, then `raw` must be a pointer to memory allocated
    /// as a Box. The exact requirements depend on the implementation.
    ///
    /// Generally, the `raw` pointer must be the result of a previous
    /// call to `into_raw` on the corresponding type. This the case for
    /// types such as `Box`, `Rc`, and `Arc`.
    ///
    /// Additionally, this function takes ownership of the pointer. If
    /// `raw` or an alias thereof is used after calling this function
    /// it can potentially result in double-free, data races, or other
    /// undefined behavior.
    unsafe fn from_raw(raw: *mut T) -> Self;
}

#[cfg(feature = "std")]
impl FromRaw<c_char> for CString {
    #[inline]
    unsafe fn from_raw(raw: *mut c_char) -> CString {
        CString::from_raw(raw)
    }
}

/// This implementation is always safe
impl<T> FromRaw<T> for *mut T {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> *mut T {
        raw
    }
}

/// This implementation is always safe
impl<T> FromRaw<T> for *const T {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> *const T {
        raw
    }
}

/// ## Safety
/// The input pointer must be non-null.
///
/// `Option<NonNull<T>>::from_raw` can be used if the pointer may be null.
impl<T> FromRaw<T> for NonNull<T> {
    #[inline]
    unsafe fn from_raw(raw: *mut T) -> NonNull<T> {
        NonNull::new_unchecked(raw)
    }
}

/// ## Safety
/// The input pointer must either be null (resulting in `None`), or be safe
/// to convert into the inner pointer type.
impl<T, U> FromRaw<U> for Option<T>
where
    T: FromRaw<U>,
{
    unsafe fn from_raw(raw: *mut U) -> Option<T> {
        if raw.is_null() {
            None
        } else {
            Some(T::from_raw(raw))
        }
    }
}

#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Box);
#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Rc);
#[cfg(feature = "alloc")]
owned_ptr_wrapper!(Arc);

#[cfg(test)]
mod tests {
    use super::*;

    macro_rules! as_ptr_test {
        ($name:ident, $t:ty, $init:expr, $compare:expr) => {
            #[test]
            fn $name() {
                let x = $init;
                let y: *const <$t as AsPtr>::Raw = <$t as AsPtr>::as_ptr(&x);
                unsafe {
                    assert_eq!(*y, $compare);
                }
            }
        };
    }

    as_ptr_test!(ref_as_ptr, &u32, &5, 5);
    //as_ptr_test!(slice_as_ptr, &[u32], &[5, 2]);
    as_ptr_test!(nonnull_as_ptr, NonNull<u32>, NonNull::from(&5), 5);
    as_ptr_test!(ptr_as_ptr, *const u32, &5u32 as *const u32, 5);
    #[cfg(feature = "std")]
    as_ptr_test!(
        cstr_as_ptr,
        CStr,
        CStr::from_bytes_with_nul("abc\0".as_bytes()).unwrap(),
        'a' as c_char
    );
    #[cfg(feature = "std")]
    as_ptr_test!(
        cstring_as_ptr,
        CString,
        CString::new("abc").unwrap(),
        'a' as c_char
    );
    #[cfg(feature = "alloc")]
    as_ptr_test!(box_as_ptr, Box<u16>, Box::new(3u16), 3);
    as_ptr_test!(cell_as_ptr, Cell<u16>, Cell::new(7u16), 7);
    as_ptr_test!(refcell_as_ptr, RefCell<u16>, RefCell::new(7u16), 7);
    #[cfg(feature = "alloc")]
    as_ptr_test!(rc_as_ptr, Rc<u16>, Rc::new(8u16), 8);
    #[cfg(feature = "alloc")]
    as_ptr_test!(arc_as_ptr, Arc<u16>, Arc::new(8u16), 8);

    as_ptr_test!(some_as_ptr, Option<&u32>, Some(&1u32), 1);
    #[test]
    fn none_as_ptr() {
        let x: Option<&u16> = None;
        let y: *const u16 = <Option<&u16> as AsPtr>::as_ptr(&x);
        assert!(y.is_null());
    }

    #[cfg(feature = "alloc")]
    macro_rules! from_into_test {
        ($name:ident, $t:ty, $init: expr, $cmp:expr) => {
            #[test]
            fn $name() {
                let orig = $init;
                let p = <$t as IntoRaw>::into_raw(orig);
                let back = unsafe {
                    <$t as FromRaw<_>>::from_raw(p)
                };
                assert_eq!(*back, $cmp);
            }
        }
    }

    #[cfg(feature = "std")]
    from_into_test!(cstring_from_into, CString, CString::new("abc").unwrap(), *CStr::from_bytes_with_nul("abc\0".as_bytes()).unwrap());
    #[cfg(feature = "alloc")]
    from_into_test!(box_from_into, Box<u16>, Box::new(4u16), 4);
    #[cfg(feature = "alloc")]
    from_into_test!(rc_from_into,  Rc<u16>, Rc::new(4u16), 4);
    #[cfg(feature = "alloc")]
    from_into_test!(arc_from_into, Arc<u16>, Arc::new(4u16), 4);

    #[test]
    fn ptr_from_into() {
        let mut data: u32 = 10;
        let p = <*mut u32 as IntoRaw>::into_raw(&mut data);
        unsafe {
            let mptr: *mut u32 = <*mut u32 as FromRaw<_>>::from_raw(p);
            *mptr = 54;
        }
        unsafe {
            let cptr = <*const u32 as FromRaw<_>>::from_raw(p);
            assert_eq!(*cptr, 54);
        }
    }

    #[test]
    fn nonnull_from_into() {
        let mut data: u32 = 10;
        let p = <NonNull<u32> as IntoRaw>::into_raw(NonNull::from(&mut data));
        unsafe {
            *p = 34;
            let p = <NonNull<u32> as FromRaw<_>>::from_raw(p);
            assert_eq!(p, NonNull::from(&data));
        }
        assert_eq!(data, 34);
    }

    #[test]
    fn some_from_into() {
        let mut data: u32 = 10;
        let p = <Option<*mut u32> as IntoRaw>::into_raw(Some(&mut data));
        unsafe {
            *p = 54;
            let p = <Option<*const u32> as FromRaw<_>>::from_raw(p);
            assert_eq!(p, Some(&data as *const u32));
        };
        assert_eq!(data, 54);
    }

    #[test]
    fn none_into() {
        assert!(<Option<*mut u16> as IntoRaw>::into_raw(None).is_null());
    }

    #[test]
    fn none_from() {
        let p = unsafe {
            <Option<*mut u16> as FromRaw<_>>::from_raw(core::ptr::null_mut())
        };
        assert_eq!(p, None);
    }

}
<|endoftext|>


<commit_before>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use Context = context::Context;
pub use BackEnd = back_end::BackEnd;
pub use Transform2d = transform2d::Transform2d;
pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddTween = add_tween::AddTween;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use Fill = fill::Fill;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use LineContext = line_context::LineContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;

mod context;
mod back_end;
mod transform2d;
mod add_color;
mod add_ellipse;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_tween;
mod relative_rectangle;
mod fill;
mod clear;
mod color_context;
mod ellipse_context;
mod ellipse_color_context;
mod line_context;
mod polygon_context;
mod polygon_color_context;
mod rectangle_context;
mod rectangle_color_context;
mod round_rectangle_context;
mod round_rectangle_color_context;
mod tween_context;
mod tween_color_context;
mod tween_polygons_color_context;
pub mod vecmath;
pub mod triangulation;
pub mod interpolation;
pub mod modular_index;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x, y, w, h, radius]
pub type RoundRectangle = [f64, ..5];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

<commit_msg>Added  `PixelRectangle`<commit_after>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use Context = context::Context;
pub use BackEnd = back_end::BackEnd;
pub use Transform2d = transform2d::Transform2d;
pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddTween = add_tween::AddTween;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use Fill = fill::Fill;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use LineContext = line_context::LineContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;

mod context;
mod back_end;
mod transform2d;
mod add_color;
mod add_ellipse;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_tween;
mod relative_rectangle;
mod fill;
mod clear;
mod color_context;
mod ellipse_context;
mod ellipse_color_context;
mod line_context;
mod polygon_context;
mod polygon_color_context;
mod rectangle_context;
mod rectangle_color_context;
mod round_rectangle_context;
mod round_rectangle_color_context;
mod tween_context;
mod tween_color_context;
mod tween_polygons_color_context;
pub mod vecmath;
pub mod triangulation;
pub mod interpolation;
pub mod modular_index;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type PixelRectangle = [u32, ..4];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x, y, w, h, radius]
pub type RoundRectangle = [f64, ..5];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

<|endoftext|>