<commit_before>
use utils::clampf32;
use std::default::Default;
use std::fmt::{Show, Formatter, FormatError};
use std::num::abs;
use std::rand::random;
use std::ascii::OwnedAsciiExt;
use serialize::hex::ToHex;

/// A basic color struct for general color use
/// made of red, green, blue and alpha elements.
pub struct Color(pub [f32, ..4]);

impl Color {

    /// Basic constructor for a Color struct.
    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Color {
        Color([r, g, b, a])
    }

    /// Returns the red component of the color.
    #[inline(always)]
    pub fn r(&self) -> f32 {
        let &Color(c) = self;
        c[0]
    }

    /// Returns the green component of the color.
    #[inline(always)]
    pub fn g(&self) -> f32 {
        let &Color(c) = self;
        c[1]
    }

    /// Returns the blue component of the color.
    #[inline(always)]
    pub fn b(&self) -> f32 {
        let &Color(c) = self;
        c[2]
    }

    /// Sets the red component of the color.
    #[inline(always)]
    pub fn set_r(&mut self, r: f32) {
        let &Color(ref mut c) = self;
        c[0] = r;
    }

    /// Sets the green component of the color.
    #[inline(always)]
    pub fn set_g(&mut self, g: f32) {
        let &Color(ref mut c) = self;
        c[1] = g;
    }

    /// Sets the blue component of the color.
    #[inline(always)]
    pub fn set_b(&mut self, b: f32) {
        let &Color(ref mut c) = self;
        c[2] = b;
    }

    /// Sets the alpha component of the color.
    #[inline(always)]
    pub fn set_a(&mut self, a: f32) {
        let &Color(ref mut c) = self;
        c[3] = a;
    }

    /// Returns the alpha component of the color.
    #[inline(always)]
    pub fn a(&self) -> f32 {
        let &Color(c) = self;
        c[3]
    }

    /// Basic constructor for a Black Color struct.
    pub fn black() -> Color {
        Color([0f32, 0f32, 0f32, 1f32])
    }

    /// Basic constructor for a White Color struct.
    pub fn white() -> Color {
        Color([1f32, 1f32, 1f32, 1f32])
    }

    /// Return color as a vector.
    pub fn as_vec(&self) -> Vec<f32> {
        vec![self.r(), self.g(), self.b(), self.a()]
    }

    /// Return color as a tuple.
    pub fn as_tuple(&self) -> (f32, f32, f32, f32) {
        let &Color(c) = self;
        (c[0], c[1], c[2], c[3])
    }

    /// Clamp the Color's values between 0f32 and 1f32.
    fn clamp(c: Color) -> Color {
        Color([
            clampf32(c.r()),
            clampf32(c.g()),
            clampf32(c.b()),
            clampf32(c.a())
        ])
    }

    /// Return a highlighted version of the current Color.
    pub fn highlighted(&self) -> Color {
        let luminance = self.luminance();
        let (r, g, b) = {
            if luminance > 0.8 {
                (self.r() - 0.2,
                 self.g() - 0.2,
                 self.b() - 0.2)
            }
            else if luminance < 0.2 {
                (self.r() + 0.2,
                 self.g() + 0.2,
                 self.b() + 0.2)
            }
            else {
                (clampf32((1f32 - self.r()) * 0.5f32 * self.r() + self.r()),
                 clampf32((1f32 - self.g()) * 0.1f32 * self.g() + self.g()),
                 clampf32((1f32 - self.b()) * 0.1f32 * self.b() + self.b()))
            }
        };
        let a = clampf32((1f32 - self.a()) * 0.5f32 + self.a());
        Color::new(r, g, b, a)
    }

    /// Return a clicked version of the current Color.
    pub fn clicked(&self) -> Color {
        let luminance = self.luminance();
        let (r, g, b) = {
            if luminance > 0.8 {
                (self.r(),
                 self.g() - 0.2,
                 self.b() - 0.2)
            }
            else if luminance < 0.2 {
                (self.r() + 0.4,
                 self.g() + 0.2,
                 self.b() + 0.2)
            }
            else {
                (clampf32((1f32 - self.r()) * 0.75f32 + self.r()),
                 clampf32((1f32 - self.g()) * 0.25f32 + self.g()),
                 clampf32((1f32 - self.b()) * 0.25f32 + self.b()))
            }
        };
        let a = clampf32((1f32 - self.a()) * 0.75f32 + self.a());
        Color::new(r, g, b, a)
    }

    /// Return a random color.
    pub fn random() -> Color {
        let r = random::<f32>();
        let g = random::<f32>();
        let b = random::<f32>();
        let a = 1f32;
        Color::new(r, g, b, a)
    }

    /// Return an inverted version of the color.
    pub fn invert(&self) -> Color {
        let r = abs(1f32 - self.r());
        let g = abs(1f32 - self.g());
        let b = abs(1f32 - self.b());
        Color::new(r, g, b, self.a())
    }

    /// Return either black or white, depending which contrasts
    /// the Color the most. This will be useful for determining
    /// a readable color for text on any given background Color.
    pub fn plain_contrast(&self) -> Color {
        if self.luminance() > 0.5f32 { Color::black() }
        else { Color::white() }
    }

    /// Return the luminance of the color.
    pub fn luminance(&self) -> f32 {
        (self.r() + self.g() + self.b()) / 3f32
    }

    pub fn to_32_bit(&self) -> [u8, ..4] {
        [
            to_8_bit(self.r()),
            to_8_bit(self.g()),
            to_8_bit(self.b()),
            to_8_bit(self.a()),
        ]
    }
}

fn to_8_bit(chan: f32) -> u8 {
    let chan = clampf32(chan);
    (chan * 255.0) as u8
}

impl Clone for Color {
    fn clone(&self) -> Color {
        *self
    }
}

impl Default for Color {
    /// Default constructor for a Color struct.
    fn default() -> Color {
        Color([0.5, 0.8, 0.6, 1.0])
    }
}

impl Add<Color, Color> for Color {
    fn add(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() + rhs.r(),
                self.g() + rhs.g(),
                self.b() + rhs.b(),
                self.a()
            ])
        )
    }
}

impl Sub<Color, Color> for Color {
    fn sub(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() - rhs.r(),
                self.g() - rhs.g(),
                self.b() - rhs.b(),
                self.a()
            ])
        )
    }
}

impl Div<Color, Color> for Color {
    fn div(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() / rhs.r(),
                self.g() / rhs.g(),
                self.b() / rhs.b(),
                self.a() / rhs.a(),
            ])
        )
    }
}

impl Mul<Color, Color> for Color {
    fn mul(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() * rhs.r(),
                self.g() * rhs.g(),
                self.b() * rhs.b(),
                self.a() * rhs.a(),
            ])
        )
    }
}

impl Show for Color {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        let vals = self.to_32_bit();
        // Hex colors are always uppercased
        let hex = vals.as_slice().to_hex().into_ascii_upper();
        write!(fmt, "#{}", hex.as_slice())
    }
}
<commit_msg>Added rustdoc comments, exposed to_hex()<commit_after>
use utils::clampf32;
use std::default::Default;
use std::fmt::{Show, Formatter, FormatError};
use std::num::abs;
use std::rand::random;
use std::ascii::OwnedAsciiExt;
use serialize::hex::ToHex;

/// A basic color struct for general color use
/// made of red, green, blue and alpha elements.
pub struct Color(pub [f32, ..4]);

impl Color {

    /// Basic constructor for a Color struct.
    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Color {
        Color([r, g, b, a])
    }

    /// Returns the red component of the color.
    #[inline(always)]
    pub fn r(&self) -> f32 {
        let &Color(c) = self;
        c[0]
    }

    /// Returns the green component of the color.
    #[inline(always)]
    pub fn g(&self) -> f32 {
        let &Color(c) = self;
        c[1]
    }

    /// Returns the blue component of the color.
    #[inline(always)]
    pub fn b(&self) -> f32 {
        let &Color(c) = self;
        c[2]
    }

    /// Sets the red component of the color.
    #[inline(always)]
    pub fn set_r(&mut self, r: f32) {
        let &Color(ref mut c) = self;
        c[0] = r;
    }

    /// Sets the green component of the color.
    #[inline(always)]
    pub fn set_g(&mut self, g: f32) {
        let &Color(ref mut c) = self;
        c[1] = g;
    }

    /// Sets the blue component of the color.
    #[inline(always)]
    pub fn set_b(&mut self, b: f32) {
        let &Color(ref mut c) = self;
        c[2] = b;
    }

    /// Sets the alpha component of the color.
    #[inline(always)]
    pub fn set_a(&mut self, a: f32) {
        let &Color(ref mut c) = self;
        c[3] = a;
    }

    /// Returns the alpha component of the color.
    #[inline(always)]
    pub fn a(&self) -> f32 {
        let &Color(c) = self;
        c[3]
    }

    /// Basic constructor for a Black Color struct.
    pub fn black() -> Color {
        Color([0f32, 0f32, 0f32, 1f32])
    }

    /// Basic constructor for a White Color struct.
    pub fn white() -> Color {
        Color([1f32, 1f32, 1f32, 1f32])
    }

    /// Return color as a vector.
    pub fn as_vec(&self) -> Vec<f32> {
        vec![self.r(), self.g(), self.b(), self.a()]
    }

    /// Return color as a tuple.
    pub fn as_tuple(&self) -> (f32, f32, f32, f32) {
        let &Color(c) = self;
        (c[0], c[1], c[2], c[3])
    }

    /// Clamp the Color's values between 0f32 and 1f32.
    fn clamp(c: Color) -> Color {
        Color([
            clampf32(c.r()),
            clampf32(c.g()),
            clampf32(c.b()),
            clampf32(c.a())
        ])
    }

    /// Return a highlighted version of the current Color.
    pub fn highlighted(&self) -> Color {
        let luminance = self.luminance();
        let (r, g, b) = {
            if luminance > 0.8 {
                (self.r() - 0.2,
                 self.g() - 0.2,
                 self.b() - 0.2)
            }
            else if luminance < 0.2 {
                (self.r() + 0.2,
                 self.g() + 0.2,
                 self.b() + 0.2)
            }
            else {
                (clampf32((1f32 - self.r()) * 0.5f32 * self.r() + self.r()),
                 clampf32((1f32 - self.g()) * 0.1f32 * self.g() + self.g()),
                 clampf32((1f32 - self.b()) * 0.1f32 * self.b() + self.b()))
            }
        };
        let a = clampf32((1f32 - self.a()) * 0.5f32 + self.a());
        Color::new(r, g, b, a)
    }

    /// Return a clicked version of the current Color.
    pub fn clicked(&self) -> Color {
        let luminance = self.luminance();
        let (r, g, b) = {
            if luminance > 0.8 {
                (self.r(),
                 self.g() - 0.2,
                 self.b() - 0.2)
            }
            else if luminance < 0.2 {
                (self.r() + 0.4,
                 self.g() + 0.2,
                 self.b() + 0.2)
            }
            else {
                (clampf32((1f32 - self.r()) * 0.75f32 + self.r()),
                 clampf32((1f32 - self.g()) * 0.25f32 + self.g()),
                 clampf32((1f32 - self.b()) * 0.25f32 + self.b()))
            }
        };
        let a = clampf32((1f32 - self.a()) * 0.75f32 + self.a());
        Color::new(r, g, b, a)
    }

    /// Return a random color.
    pub fn random() -> Color {
        let r = random::<f32>();
        let g = random::<f32>();
        let b = random::<f32>();
        let a = 1f32;
        Color::new(r, g, b, a)
    }

    /// Return an inverted version of the color.
    pub fn invert(&self) -> Color {
        let r = abs(1f32 - self.r());
        let g = abs(1f32 - self.g());
        let b = abs(1f32 - self.b());
        Color::new(r, g, b, self.a())
    }

    /// Return either black or white, depending which contrasts
    /// the Color the most. This will be useful for determining
    /// a readable color for text on any given background Color.
    pub fn plain_contrast(&self) -> Color {
        if self.luminance() > 0.5f32 { Color::black() }
        else { Color::white() }
    }

    /// Return the luminance of the color.
    pub fn luminance(&self) -> f32 {
        (self.r() + self.g() + self.b()) / 3f32
    }

    /// Return an array of the channels in this color
    /// clamped to [0..255]
    pub fn to_32_bit(&self) -> [u8, ..4] {
        [
            to_8_bit(self.r()),
            to_8_bit(self.g()),
            to_8_bit(self.b()),
            to_8_bit(self.a()),
        ]
    }

    /// Return the hex representation of this color
    /// in the format #RRGGBBAA
    /// e.g. `Color(1.0, 0.0, 5.0, 1.0) == "#FF0080FF"`
    pub fn to_hex(&self) -> String {
        let vals = self.to_32_bit();
        // Hex colors are always uppercased
        let hex = vals.as_slice().to_hex().into_ascii_upper();
        format!("#{}", hex.as_slice())
    }
}

fn to_8_bit(chan: f32) -> u8 {
    let chan = clampf32(chan);
    (chan * 255.0) as u8
}

impl Clone for Color {
    fn clone(&self) -> Color {
        *self
    }
}

impl Default for Color {
    /// Default constructor for a Color struct.
    fn default() -> Color {
        Color([0.5, 0.8, 0.6, 1.0])
    }
}

impl Add<Color, Color> for Color {
    fn add(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() + rhs.r(),
                self.g() + rhs.g(),
                self.b() + rhs.b(),
                self.a()
            ])
        )
    }
}

impl Sub<Color, Color> for Color {
    fn sub(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() - rhs.r(),
                self.g() - rhs.g(),
                self.b() - rhs.b(),
                self.a()
            ])
        )
    }
}

impl Div<Color, Color> for Color {
    fn div(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() / rhs.r(),
                self.g() / rhs.g(),
                self.b() / rhs.b(),
                self.a() / rhs.a(),
            ])
        )
    }
}

impl Mul<Color, Color> for Color {
    fn mul(&self, rhs: &Color) -> Color {
        Color::clamp(
            Color([
                self.r() * rhs.r(),
                self.g() * rhs.g(),
                self.b() * rhs.b(),
                self.a() * rhs.a(),
            ])
        )
    }
}

impl Show for Color {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        let hex = self.to_hex();
        fmt.pad(hex.as_slice())
    }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::fmt;
use std::io;

use {StatusCode, Url};

/// The Errors that may occur when processing a `Request`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate reqwest;
///
/// #[derive(Deserialize)]
/// struct Simple {
///    key: String
/// }
/// # fn main() { }
///
/// fn run() {
///    match make_request() {
///        Err(e) => handler(e),
///        Ok(_)  => return,
///    }
/// }
/// // Response is not a json object conforming to the Simple struct
/// fn make_request() -> Result<Simple, reqwest::Error> {
///   reqwest::get("http://httpbin.org/ip")?.json()
/// }
///
/// fn handler(e: reqwest::Error) {
///    if e.is_http() {
///        match e.url() {
///            None => println!("No Url given"),
///            Some(url) => println!("Problem making request to: {}", url),
///        }
///    }
///    // Inspect the internal error and output it
///    if e.is_serialization() {
///       let serde_error = match e.get_ref() {
///            None => return,
///            Some(err) => err,
///        };
///        println!("problem parsing information {}", serde_error);
///    }
///    if e.is_redirect() {
///        println!("server redirecting too many times or making loop");
///    }
/// }
/// ```
#[derive(Debug)]
pub struct Error {
    kind: Kind,
    url: Option<Url>,
}

/// A `Result` alias where the `Err` case is `reqwest::Error`.
pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    /// Returns a possible URL related to this error.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn run() {
    /// // displays last stop of a redirect loop
    /// let response = reqwest::get("http://site.with.redirect.loop");
    /// if let Err(e) = response {
    ///     if e.is_redirect() {
    ///         if let Some(final_stop) = e.url() {
    ///             println!("redirect loop at {}", final_stop);
    ///         }
    ///     }
    /// }
    /// # }
    /// ```
    #[inline]
    pub fn url(&self) -> Option<&Url> {
        self.url.as_ref()
    }

    pub(crate) fn with_url(mut self, url: Url) -> Error {
        debug_assert_eq!(self.url, None, "with_url overriding existing url");
        self.url = Some(url);
        self
    }

    /// Returns a reference to the internal error, if available.
    ///
    /// The `'static` bounds allows using `downcast_ref` to check the
    /// details of the error.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate url;
    /// # extern crate reqwest;
    /// // retries requests with no host on localhost
    /// # fn run() {
    /// let invalid_request = "http://";
    /// let mut response = reqwest::get(invalid_request);
    /// if let Err(e) = response {
    ///     match e.get_ref().and_then(|e| e.downcast_ref::<url::ParseError>()) {
    ///         Some(&url::ParseError::EmptyHost) => {
    ///             let valid_request = format!("{}{}",invalid_request, "localhost");
    ///             response = reqwest::get(&valid_request);
    ///         },
    ///         _ => (),
    ///     }
    /// }
    /// # }
    /// # fn main() {}
    /// ```
    #[inline]
    pub fn get_ref(&self) -> Option<&(StdError + Send + Sync + 'static)> {
        match self.kind {
            Kind::Http(ref e) => Some(e),
            Kind::Hyper(ref e) => Some(e),
            Kind::Mime(ref e) => Some(e),
            Kind::Url(ref e) => Some(e),
            Kind::Tls(ref e) => Some(e),
            Kind::Io(ref e) => Some(e),
            Kind::UrlEncoded(ref e) => Some(e),
            Kind::Json(ref e) => Some(e),
            Kind::UrlBadScheme |
            Kind::TooManyRedirects |
            Kind::RedirectLoop |
            Kind::ClientError(_) |
            Kind::ServerError(_) => None,
        }
    }

    /// Returns true if the error is related to HTTP.
    #[inline]
    pub fn is_http(&self) -> bool {
        match self.kind {
            Kind::Http(_) => true,
            Kind::Hyper(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is serialization related.
    #[inline]
    pub fn is_serialization(&self) -> bool {
        match self.kind {
            Kind::Json(_) |
            Kind::UrlEncoded(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a `RedirectPolicy`.
    #[inline]
    pub fn is_redirect(&self) -> bool {
        match self.kind {
            Kind::TooManyRedirects |
            Kind::RedirectLoop => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a request returning a 4xx error.
    #[inline]
    pub fn is_client_error(&self) -> bool {
        match self.kind {
            Kind::ClientError(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a request returning a 5xx error.
    #[inline]
    pub fn is_server_error(&self) -> bool {
        match self.kind {
            Kind::ServerError(_) => true,
            _ => false,
        }
    }

    /// Returns the status code, if the error was generated from a response.
    #[inline]
    pub fn status(&self) -> Option<StatusCode> {
        match self.kind {
            Kind::ClientError(code) |
            Kind::ServerError(code) => Some(code),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref url) = self.url {
            try!(fmt::Display::fmt(url, f));
            try!(f.write_str(": "));
        }
        match self.kind {
            Kind::Http(ref e) => fmt::Display::fmt(e, f),
            Kind::Hyper(ref e) => fmt::Display::fmt(e, f),
            Kind::Mime(ref e) => fmt::Display::fmt(e, f),
            Kind::Url(ref e) => fmt::Display::fmt(e, f),
            Kind::UrlBadScheme => f.write_str("URL scheme is not allowed"),
            Kind::Tls(ref e) => fmt::Display::fmt(e, f),
            Kind::Io(ref e) => fmt::Display::fmt(e, f),
            Kind::UrlEncoded(ref e) => fmt::Display::fmt(e, f),
            Kind::Json(ref e) => fmt::Display::fmt(e, f),
            Kind::TooManyRedirects => f.write_str("Too many redirects"),
            Kind::RedirectLoop => f.write_str("Infinite redirect loop"),
            Kind::ClientError(ref code) => {
                f.write_str("Client Error: ")?;
                fmt::Display::fmt(code, f)
            }
            Kind::ServerError(ref code) => {
                f.write_str("Server Error: ")?;
                fmt::Display::fmt(code, f)
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self.kind {
            Kind::Http(ref e) => e.description(),
            Kind::Hyper(ref e) => e.description(),
            Kind::Mime(ref e) => e.description(),
            Kind::Url(ref e) => e.description(),
            Kind::UrlBadScheme => "URL scheme is not allowed",
            Kind::Tls(ref e) => e.description(),
            Kind::Io(ref e) => e.description(),
            Kind::UrlEncoded(ref e) => e.description(),
            Kind::Json(ref e) => e.description(),
            Kind::TooManyRedirects => "Too many redirects",
            Kind::RedirectLoop => "Infinite redirect loop",
            Kind::ClientError(_) => "Client Error",
            Kind::ServerError(_) => "Server Error",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self.kind {
            Kind::Http(ref e) => e.cause(),
            Kind::Hyper(ref e) => e.cause(),
            Kind::Mime(ref e) => e.cause(),
            Kind::Url(ref e) => e.cause(),
            Kind::Tls(ref e) => e.cause(),
            Kind::Io(ref e) => e.cause(),
            Kind::UrlEncoded(ref e) => e.cause(),
            Kind::Json(ref e) => e.cause(),
            Kind::UrlBadScheme |
            Kind::TooManyRedirects |
            Kind::RedirectLoop |
            Kind::ClientError(_) |
            Kind::ServerError(_) => None,
        }
    }
}

// pub(crate)

#[derive(Debug)]
pub(crate) enum Kind {
    Http(::http::Error),
    Hyper(::hyper::Error),
    Mime(::mime::FromStrError),
    Url(::url::ParseError),
    UrlBadScheme,
    Tls(::native_tls::Error),
    Io(io::Error),
    UrlEncoded(::serde_urlencoded::ser::Error),
    Json(::serde_json::Error),
    TooManyRedirects,
    RedirectLoop,
    ClientError(StatusCode),
    ServerError(StatusCode),
}

impl From<::http::Error> for Kind {
    #[inline]
    fn from(err: ::http::Error) -> Kind {
        Kind::Http(err)
    }
}

impl From<::hyper::Error> for Kind {
    #[inline]
    fn from(err: ::hyper::Error) -> Kind {
        Kind::Hyper(err)
    }
}

impl From<::mime::FromStrError> for Kind {
    #[inline]
    fn from(err: ::mime::FromStrError) -> Kind {
        Kind::Mime(err)
    }
}

impl From<io::Error> for Kind {
    #[inline]
    fn from(err: io::Error) -> Kind {
        Kind::Io(err)
    }
}

impl From<::url::ParseError> for Kind {
    #[inline]
    fn from(err: ::url::ParseError) -> Kind {
        Kind::Url(err)
    }
}

impl From<::serde_urlencoded::ser::Error> for Kind {
    #[inline]
    fn from(err: ::serde_urlencoded::ser::Error) -> Kind {
        Kind::UrlEncoded(err)
    }
}

impl From<::serde_json::Error> for Kind {
    #[inline]
    fn from(err: ::serde_json::Error) -> Kind {
        Kind::Json(err)
    }
}

impl From<::native_tls::Error> for Kind {
    fn from(err: ::native_tls::Error) -> Kind {
        Kind::Tls(err)
    }
}

impl<T> From<::wait::Waited<T>> for Kind
where T: Into<Kind> {
    fn from(err: ::wait::Waited<T>) -> Kind {
        match err {
            ::wait::Waited::TimedOut =>  io_timeout().into(),
            ::wait::Waited::Err(e) => e.into(),
        }
    }
}

#[cfg(unix)]
fn io_timeout() -> io::Error {
    io::Error::new(io::ErrorKind::WouldBlock, "timed out")
}

#[cfg(windows)]
fn io_timeout() -> io::Error {
    io::Error::new(io::ErrorKind::TimedOut, "timed out")
}

#[allow(missing_debug_implementations)]
pub(crate) struct InternalFrom<T>(pub T, pub Option<Url>);

#[doc(hidden)] // https://github.com/rust-lang/rust/issues/42323
impl From<InternalFrom<Error>> for Error {
    #[inline]
    fn from(other: InternalFrom<Error>) -> Error {
        other.0
    }
}

#[doc(hidden)] // https://github.com/rust-lang/rust/issues/42323
impl<T> From<InternalFrom<T>> for Error
where
    T: Into<Kind>,
{
    #[inline]
    fn from(other: InternalFrom<T>) -> Error {
        Error {
            kind: other.0.into(),
            url: other.1,
        }
    }
}

pub(crate) fn from<T>(err: T) -> Error
where
    T: Into<Kind>,
{
    InternalFrom(err, None).into()
}

pub(crate) fn into_io(e: Error) -> io::Error {
    match e.kind {
        Kind::Io(io) => io,
        _ => io::Error::new(io::ErrorKind::Other, e),
    }
}

macro_rules! try_ {
    ($e:expr) => (
        match $e {
            Ok(v) => v,
            Err(err) => {
                return Err(::error::from(err));
            }
        }
    );
    ($e:expr, $url:expr) => (
        match $e {
            Ok(v) => v,
            Err(err) => {
                return Err(::Error::from(::error::InternalFrom(err, Some($url.clone()))));
            }
        }
    )
}

pub(crate) fn loop_detected(url: Url) -> Error {
    Error {
        kind: Kind::RedirectLoop,
        url: Some(url),
    }
}

pub(crate) fn too_many_redirects(url: Url) -> Error {
    Error {
        kind: Kind::TooManyRedirects,
        url: Some(url),
    }
}

pub(crate) fn timedout(url: Option<Url>) -> Error {
    Error {
        kind: Kind::Io(io_timeout()),
        url: url,
    }
}

pub(crate) fn client_error(url: Url, status: StatusCode) -> Error {
    Error {
        kind: Kind::ClientError(status),
        url: Some(url),
    }
}

pub(crate) fn server_error(url: Url, status: StatusCode) -> Error {
    Error {
        kind: Kind::ServerError(status),
        url: Some(url),
    }
}

pub(crate) fn url_bad_scheme(url: Url) -> Error {
    Error {
        kind: Kind::UrlBadScheme,
        url: Some(url),
    }
}

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

    #[test]
    fn test_cause_chain() {
        #[derive(Debug)]
        struct Chain<T>(Option<T>);

        impl<T: fmt::Display> fmt::Display  for Chain<T> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                if let Some(ref link) = self.0 {
                    write!(f, "chain: {}", link)
                } else {
                    f.write_str("root")
                }
            }
        }

        impl<T: StdError> StdError for Chain<T> {
            fn description(&self) -> &str {
                if self.0.is_some() {
                    "chain"
                } else {
                    "root"
                }
            }
            fn cause(&self) -> Option<&StdError> {
                if let Some(ref e) = self.0 {
                    Some(e)
                } else {
                    None
                }
            }
        }

        let root = Chain(None::<Error>);
        let io = ::std::io::Error::new(::std::io::ErrorKind::Other, root);
        let err = Error { kind: Kind::Io(io), url: None };
        assert!(err.cause().is_none());
        assert_eq!(err.to_string(), "root");

        let root = ::std::io::Error::new(::std::io::ErrorKind::Other, Chain(None::<Error>));
        let link = Chain(Some(root));
        let io = ::std::io::Error::new(::std::io::ErrorKind::Other, link);
        let err = Error { kind: Kind::Io(io), url: None };
        assert!(err.cause().is_some());
        assert_eq!(err.to_string(), "chain: root");
    }
}
<commit_msg>reduce size of Error<commit_after>use std::error::Error as StdError;
use std::fmt;
use std::io;

use {StatusCode, Url};

/// The Errors that may occur when processing a `Request`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate reqwest;
///
/// #[derive(Deserialize)]
/// struct Simple {
///    key: String
/// }
/// # fn main() { }
///
/// fn run() {
///    match make_request() {
///        Err(e) => handler(e),
///        Ok(_)  => return,
///    }
/// }
/// // Response is not a json object conforming to the Simple struct
/// fn make_request() -> Result<Simple, reqwest::Error> {
///   reqwest::get("http://httpbin.org/ip")?.json()
/// }
///
/// fn handler(e: reqwest::Error) {
///    if e.is_http() {
///        match e.url() {
///            None => println!("No Url given"),
///            Some(url) => println!("Problem making request to: {}", url),
///        }
///    }
///    // Inspect the internal error and output it
///    if e.is_serialization() {
///       let serde_error = match e.get_ref() {
///            None => return,
///            Some(err) => err,
///        };
///        println!("problem parsing information {}", serde_error);
///    }
///    if e.is_redirect() {
///        println!("server redirecting too many times or making loop");
///    }
/// }
/// ```
pub struct Error {
    inner: Box<Inner>,
}

#[derive(Debug)]
struct Inner {
    kind: Kind,
    url: Option<Url>,
}

/// A `Result` alias where the `Err` case is `reqwest::Error`.
pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    fn new(kind: Kind, url: Option<Url>) -> Error {
        Error {
            inner: Box::new(Inner {
                kind,
                url,
            }),
        }
    }

    /// Returns a possible URL related to this error.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn run() {
    /// // displays last stop of a redirect loop
    /// let response = reqwest::get("http://site.with.redirect.loop");
    /// if let Err(e) = response {
    ///     if e.is_redirect() {
    ///         if let Some(final_stop) = e.url() {
    ///             println!("redirect loop at {}", final_stop);
    ///         }
    ///     }
    /// }
    /// # }
    /// ```
    #[inline]
    pub fn url(&self) -> Option<&Url> {
        self.inner.url.as_ref()
    }

    pub(crate) fn with_url(mut self, url: Url) -> Error {
        debug_assert_eq!(self.inner.url, None, "with_url overriding existing url");
        self.inner.url = Some(url);
        self
    }

    /// Returns a reference to the internal error, if available.
    ///
    /// The `'static` bounds allows using `downcast_ref` to check the
    /// details of the error.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate url;
    /// # extern crate reqwest;
    /// // retries requests with no host on localhost
    /// # fn run() {
    /// let invalid_request = "http://";
    /// let mut response = reqwest::get(invalid_request);
    /// if let Err(e) = response {
    ///     match e.get_ref().and_then(|e| e.downcast_ref::<url::ParseError>()) {
    ///         Some(&url::ParseError::EmptyHost) => {
    ///             let valid_request = format!("{}{}",invalid_request, "localhost");
    ///             response = reqwest::get(&valid_request);
    ///         },
    ///         _ => (),
    ///     }
    /// }
    /// # }
    /// # fn main() {}
    /// ```
    #[inline]
    pub fn get_ref(&self) -> Option<&(StdError + Send + Sync + 'static)> {
        match self.inner.kind {
            Kind::Http(ref e) => Some(e),
            Kind::Hyper(ref e) => Some(e),
            Kind::Mime(ref e) => Some(e),
            Kind::Url(ref e) => Some(e),
            Kind::Tls(ref e) => Some(e),
            Kind::Io(ref e) => Some(e),
            Kind::UrlEncoded(ref e) => Some(e),
            Kind::Json(ref e) => Some(e),
            Kind::UrlBadScheme |
            Kind::TooManyRedirects |
            Kind::RedirectLoop |
            Kind::ClientError(_) |
            Kind::ServerError(_) => None,
        }
    }

    /// Returns true if the error is related to HTTP.
    #[inline]
    pub fn is_http(&self) -> bool {
        match self.inner.kind {
            Kind::Http(_) => true,
            Kind::Hyper(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is serialization related.
    #[inline]
    pub fn is_serialization(&self) -> bool {
        match self.inner.kind {
            Kind::Json(_) |
            Kind::UrlEncoded(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a `RedirectPolicy`.
    #[inline]
    pub fn is_redirect(&self) -> bool {
        match self.inner.kind {
            Kind::TooManyRedirects |
            Kind::RedirectLoop => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a request returning a 4xx error.
    #[inline]
    pub fn is_client_error(&self) -> bool {
        match self.inner.kind {
            Kind::ClientError(_) => true,
            _ => false,
        }
    }

    /// Returns true if the error is from a request returning a 5xx error.
    #[inline]
    pub fn is_server_error(&self) -> bool {
        match self.inner.kind {
            Kind::ServerError(_) => true,
            _ => false,
        }
    }

    /// Returns the status code, if the error was generated from a response.
    #[inline]
    pub fn status(&self) -> Option<StatusCode> {
        match self.inner.kind {
            Kind::ClientError(code) |
            Kind::ServerError(code) => Some(code),
            _ => None,
        }
    }
}

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref url) = self.inner.url {
            try!(fmt::Display::fmt(url, f));
            try!(f.write_str(": "));
        }
        match self.inner.kind {
            Kind::Http(ref e) => fmt::Display::fmt(e, f),
            Kind::Hyper(ref e) => fmt::Display::fmt(e, f),
            Kind::Mime(ref e) => fmt::Display::fmt(e, f),
            Kind::Url(ref e) => fmt::Display::fmt(e, f),
            Kind::UrlBadScheme => f.write_str("URL scheme is not allowed"),
            Kind::Tls(ref e) => fmt::Display::fmt(e, f),
            Kind::Io(ref e) => fmt::Display::fmt(e, f),
            Kind::UrlEncoded(ref e) => fmt::Display::fmt(e, f),
            Kind::Json(ref e) => fmt::Display::fmt(e, f),
            Kind::TooManyRedirects => f.write_str("Too many redirects"),
            Kind::RedirectLoop => f.write_str("Infinite redirect loop"),
            Kind::ClientError(ref code) => {
                f.write_str("Client Error: ")?;
                fmt::Display::fmt(code, f)
            }
            Kind::ServerError(ref code) => {
                f.write_str("Server Error: ")?;
                fmt::Display::fmt(code, f)
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self.inner.kind {
            Kind::Http(ref e) => e.description(),
            Kind::Hyper(ref e) => e.description(),
            Kind::Mime(ref e) => e.description(),
            Kind::Url(ref e) => e.description(),
            Kind::UrlBadScheme => "URL scheme is not allowed",
            Kind::Tls(ref e) => e.description(),
            Kind::Io(ref e) => e.description(),
            Kind::UrlEncoded(ref e) => e.description(),
            Kind::Json(ref e) => e.description(),
            Kind::TooManyRedirects => "Too many redirects",
            Kind::RedirectLoop => "Infinite redirect loop",
            Kind::ClientError(_) => "Client Error",
            Kind::ServerError(_) => "Server Error",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self.inner.kind {
            Kind::Http(ref e) => e.cause(),
            Kind::Hyper(ref e) => e.cause(),
            Kind::Mime(ref e) => e.cause(),
            Kind::Url(ref e) => e.cause(),
            Kind::Tls(ref e) => e.cause(),
            Kind::Io(ref e) => e.cause(),
            Kind::UrlEncoded(ref e) => e.cause(),
            Kind::Json(ref e) => e.cause(),
            Kind::UrlBadScheme |
            Kind::TooManyRedirects |
            Kind::RedirectLoop |
            Kind::ClientError(_) |
            Kind::ServerError(_) => None,
        }
    }
}

// pub(crate)

#[derive(Debug)]
pub(crate) enum Kind {
    Http(::http::Error),
    Hyper(::hyper::Error),
    Mime(::mime::FromStrError),
    Url(::url::ParseError),
    UrlBadScheme,
    Tls(::native_tls::Error),
    Io(io::Error),
    UrlEncoded(::serde_urlencoded::ser::Error),
    Json(::serde_json::Error),
    TooManyRedirects,
    RedirectLoop,
    ClientError(StatusCode),
    ServerError(StatusCode),
}

impl From<::http::Error> for Kind {
    #[inline]
    fn from(err: ::http::Error) -> Kind {
        Kind::Http(err)
    }
}

impl From<::hyper::Error> for Kind {
    #[inline]
    fn from(err: ::hyper::Error) -> Kind {
        Kind::Hyper(err)
    }
}

impl From<::mime::FromStrError> for Kind {
    #[inline]
    fn from(err: ::mime::FromStrError) -> Kind {
        Kind::Mime(err)
    }
}

impl From<io::Error> for Kind {
    #[inline]
    fn from(err: io::Error) -> Kind {
        Kind::Io(err)
    }
}

impl From<::url::ParseError> for Kind {
    #[inline]
    fn from(err: ::url::ParseError) -> Kind {
        Kind::Url(err)
    }
}

impl From<::serde_urlencoded::ser::Error> for Kind {
    #[inline]
    fn from(err: ::serde_urlencoded::ser::Error) -> Kind {
        Kind::UrlEncoded(err)
    }
}

impl From<::serde_json::Error> for Kind {
    #[inline]
    fn from(err: ::serde_json::Error) -> Kind {
        Kind::Json(err)
    }
}

impl From<::native_tls::Error> for Kind {
    fn from(err: ::native_tls::Error) -> Kind {
        Kind::Tls(err)
    }
}

impl<T> From<::wait::Waited<T>> for Kind
where T: Into<Kind> {
    fn from(err: ::wait::Waited<T>) -> Kind {
        match err {
            ::wait::Waited::TimedOut =>  io_timeout().into(),
            ::wait::Waited::Err(e) => e.into(),
        }
    }
}

#[cfg(unix)]
fn io_timeout() -> io::Error {
    io::Error::new(io::ErrorKind::WouldBlock, "timed out")
}

#[cfg(windows)]
fn io_timeout() -> io::Error {
    io::Error::new(io::ErrorKind::TimedOut, "timed out")
}

#[allow(missing_debug_implementations)]
pub(crate) struct InternalFrom<T>(pub T, pub Option<Url>);

#[doc(hidden)] // https://github.com/rust-lang/rust/issues/42323
impl From<InternalFrom<Error>> for Error {
    #[inline]
    fn from(other: InternalFrom<Error>) -> Error {
        other.0
    }
}

#[doc(hidden)] // https://github.com/rust-lang/rust/issues/42323
impl<T> From<InternalFrom<T>> for Error
where
    T: Into<Kind>,
{
    #[inline]
    fn from(other: InternalFrom<T>) -> Error {
        Error::new(other.0.into(), other.1)
    }
}

pub(crate) fn from<T>(err: T) -> Error
where
    T: Into<Kind>,
{
    InternalFrom(err, None).into()
}

pub(crate) fn into_io(e: Error) -> io::Error {
    match e.inner.kind {
        Kind::Io(io) => io,
        _ => io::Error::new(io::ErrorKind::Other, e),
    }
}

macro_rules! try_ {
    ($e:expr) => (
        match $e {
            Ok(v) => v,
            Err(err) => {
                return Err(::error::from(err));
            }
        }
    );
    ($e:expr, $url:expr) => (
        match $e {
            Ok(v) => v,
            Err(err) => {
                return Err(::Error::from(::error::InternalFrom(err, Some($url.clone()))));
            }
        }
    )
}

pub(crate) fn loop_detected(url: Url) -> Error {
    Error::new(Kind::RedirectLoop, Some(url))
}

pub(crate) fn too_many_redirects(url: Url) -> Error {
    Error::new(Kind::TooManyRedirects, Some(url))
}

pub(crate) fn timedout(url: Option<Url>) -> Error {
    Error::new(Kind::Io(io_timeout()), url)
}

pub(crate) fn client_error(url: Url, status: StatusCode) -> Error {
    Error::new(Kind::ClientError(status), Some(url))
}

pub(crate) fn server_error(url: Url, status: StatusCode) -> Error {
    Error::new(Kind::ServerError(status), Some(url))
}

pub(crate) fn url_bad_scheme(url: Url) -> Error {
    Error::new(Kind::UrlBadScheme, Some(url))
}

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

    #[test]
    fn test_cause_chain() {
        #[derive(Debug)]
        struct Chain<T>(Option<T>);

        impl<T: fmt::Display> fmt::Display  for Chain<T> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                if let Some(ref link) = self.0 {
                    write!(f, "chain: {}", link)
                } else {
                    f.write_str("root")
                }
            }
        }

        impl<T: StdError> StdError for Chain<T> {
            fn description(&self) -> &str {
                if self.0.is_some() {
                    "chain"
                } else {
                    "root"
                }
            }
            fn cause(&self) -> Option<&StdError> {
                if let Some(ref e) = self.0 {
                    Some(e)
                } else {
                    None
                }
            }
        }

        let root = Chain(None::<Error>);
        let io = ::std::io::Error::new(::std::io::ErrorKind::Other, root);
        let err = Error::new(Kind::Io(io), None);
        assert!(err.cause().is_none());
        assert_eq!(err.to_string(), "root");

        let root = ::std::io::Error::new(::std::io::ErrorKind::Other, Chain(None::<Error>));
        let link = Chain(Some(root));
        let io = ::std::io::Error::new(::std::io::ErrorKind::Other, link);
        let err = Error::new(Kind::Io(io), None);
        assert!(err.cause().is_some());
        assert_eq!(err.to_string(), "chain: root");
    }

    #[test]
    fn mem_size_of() {
        use std::mem::size_of;
        assert_eq!(size_of::<Error>(), size_of::<usize>());
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use libc::c_int;
use {ffi, errmsg_to_string};

/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;

#[derive(Debug)]
pub enum Error {
    SqliteFailure(ffi::Error, Option<String>),
    FromSqlConversionFailure(Box<error::Error>),
    Utf8Error(str::Utf8Error),
    NulError(::std::ffi::NulError),
    InvalidParameterName(String),
    InvalidPath(PathBuf),
    ExecuteReturnedResults,
    QueryReturnedNoRows,
    GetFromStaleRow,
    InvalidColumnIndex(c_int),
    InvalidColumnType,

    #[cfg(feature = "functions")]
    InvalidFunctionParameterType,
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<error::Error>),
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::SqliteFailure(ref err, None) => err.fmt(f),
            &Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            &Error::FromSqlConversionFailure(ref err) => err.fmt(f),
            &Error::Utf8Error(ref err) => err.fmt(f),
            &Error::NulError(ref err) => err.fmt(f),
            &Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            &Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            &Error::ExecuteReturnedResults => write!(f, "Execute returned results - did you mean to call query?"),
            &Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            &Error::GetFromStaleRow => write!(f, "Attempted to get a value from a stale row"),
            &Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            &Error::InvalidColumnType => write!(f, "Invalid column type"),

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"),
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SqliteFailure(ref err, None) => err.description(),
            &Error::SqliteFailure(_, Some(ref s)) => s,
            &Error::FromSqlConversionFailure(ref err) => err.description(),
            &Error::Utf8Error(ref err) => err.description(),
            &Error::InvalidParameterName(_) => "invalid parameter name",
            &Error::NulError(ref err) => err.description(),
            &Error::InvalidPath(_) => "invalid path",
            &Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?",
            &Error::QueryReturnedNoRows => "query returned no rows",
            &Error::GetFromStaleRow => "attempted to get a value from a stale row",
            &Error::InvalidColumnIndex(_) => "invalid column index",
            &Error::InvalidColumnType => "invalid column type",

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => "invalid function parameter type",
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::SqliteFailure(ref err, _) => Some(err),
            &Error::FromSqlConversionFailure(ref err) => Some(&**err),
            &Error::Utf8Error(ref err) => Some(err),
            &Error::NulError(ref err) => Some(err),
            &Error::InvalidParameterName(_) => None,
            &Error::InvalidPath(_) => None,
            &Error::ExecuteReturnedResults => None,
            &Error::QueryReturnedNoRows => None,
            &Error::GetFromStaleRow => None,
            &Error::InvalidColumnIndex(_) => None,
            &Error::InvalidColumnType => None,

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => None,
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => Some(&**err),
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}
<commit_msg>Add Send and Sync bounds to boxed errors to be comaptible with io::Error.<commit_after>use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use libc::c_int;
use {ffi, errmsg_to_string};

/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;

#[derive(Debug)]
pub enum Error {
    SqliteFailure(ffi::Error, Option<String>),
    FromSqlConversionFailure(Box<error::Error + Send + Sync>),
    Utf8Error(str::Utf8Error),
    NulError(::std::ffi::NulError),
    InvalidParameterName(String),
    InvalidPath(PathBuf),
    ExecuteReturnedResults,
    QueryReturnedNoRows,
    GetFromStaleRow,
    InvalidColumnIndex(c_int),
    InvalidColumnType,

    #[cfg(feature = "functions")]
    InvalidFunctionParameterType,
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<error::Error + Send + Sync>),
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::SqliteFailure(ref err, None) => err.fmt(f),
            &Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            &Error::FromSqlConversionFailure(ref err) => err.fmt(f),
            &Error::Utf8Error(ref err) => err.fmt(f),
            &Error::NulError(ref err) => err.fmt(f),
            &Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            &Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            &Error::ExecuteReturnedResults => write!(f, "Execute returned results - did you mean to call query?"),
            &Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            &Error::GetFromStaleRow => write!(f, "Attempted to get a value from a stale row"),
            &Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            &Error::InvalidColumnType => write!(f, "Invalid column type"),

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"),
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SqliteFailure(ref err, None) => err.description(),
            &Error::SqliteFailure(_, Some(ref s)) => s,
            &Error::FromSqlConversionFailure(ref err) => err.description(),
            &Error::Utf8Error(ref err) => err.description(),
            &Error::InvalidParameterName(_) => "invalid parameter name",
            &Error::NulError(ref err) => err.description(),
            &Error::InvalidPath(_) => "invalid path",
            &Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?",
            &Error::QueryReturnedNoRows => "query returned no rows",
            &Error::GetFromStaleRow => "attempted to get a value from a stale row",
            &Error::InvalidColumnIndex(_) => "invalid column index",
            &Error::InvalidColumnType => "invalid column type",

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => "invalid function parameter type",
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::SqliteFailure(ref err, _) => Some(err),
            &Error::FromSqlConversionFailure(ref err) => Some(&**err),
            &Error::Utf8Error(ref err) => Some(err),
            &Error::NulError(ref err) => Some(err),
            &Error::InvalidParameterName(_) => None,
            &Error::InvalidPath(_) => None,
            &Error::ExecuteReturnedResults => None,
            &Error::QueryReturnedNoRows => None,
            &Error::GetFromStaleRow => None,
            &Error::InvalidColumnIndex(_) => None,
            &Error::InvalidColumnType => None,

            #[cfg(feature = "functions")]
            &Error::InvalidFunctionParameterType => None,
            #[cfg(feature = "functions")]
            &Error::UserFunctionError(ref err) => Some(&**err),
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

use support::{database, project};

#[test]
fn run_infer_schema_without_docs() {
    test_print_schema("print_schema_simple_without_docs", vec![]);
}

#[test]
fn run_infer_schema() {
    test_print_schema("print_schema_simple", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_include() {
    test_print_schema("print_schema_only_tables", vec!["--with-docs", "-w", "users1"]);
}

#[test]
fn run_infer_schema_exclude() {
    test_print_schema("print_schema_except_tables", vec!["--with-docs", "-b", "users1"]);
}

#[test]
fn run_infer_schema_order() {
    test_print_schema("print_schema_order", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_compound_primary_key() {
    test_print_schema("print_schema_compound_primary_key", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name() {
    test_print_schema(
        "print_schema_specifying_schema_name",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name_with_foreign_keys() {
    test_print_schema(
        "print_schema_specifying_schema_name_with_foreign_keys",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_with_foreign_keys() {
    test_print_schema("print_schema_with_foreign_keys", vec!["--with-docs"]);
}

#[test]
fn print_schema_column_renaming() {
    test_print_schema("print_schema_column_renaming", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "mysql")]
fn print_schema_unsigned() {
    test_print_schema("print_schema_unsigned", vec!["--with-docs"]);
}

#[test]
fn print_schema_patch_file() {
    let path_to_patch_file = backend_file_path("print_schema_patch_file", "schema.patch");
    let path = path_to_patch_file.display().to_string();
    test_print_schema("print_schema_patch_file", vec!["--patch-file", &path]);
}

#[test]
fn print_schema_custom_types() {
    test_print_schema(
        "print_schema_custom_types",
        vec!["--import-types", "foo::*", "--import-types", "bar::*"],
    );
}

#[cfg(feature = "sqlite")]
const BACKEND: &str = "sqlite";
#[cfg(feature = "postgres")]
const BACKEND: &str = "postgres";
#[cfg(feature = "mysql")]
const BACKEND: &str = "mysql";

fn backend_file_path(test_name: &str, file: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name)
        .join(BACKEND)
        .join(file)
}

fn test_print_schema(test_name: &str, args: Vec<&str>) {
    let test_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name);
    let p = project(test_name).build();
    let db = database(&p.database_url());

    p.command("setup").run();

    let schema = read_file(&backend_file_path(test_name, "schema.sql"));
    db.execute(&schema);

    let result = p.command("print-schema").args(args).run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    let expected = read_file(&backend_file_path(test_name, "expected.rs"));

    assert_diff!(&expected, result.stdout(), "\n", 0);

    test_print_schema_config(test_name, &test_path, schema, expected);
}

fn test_print_schema_config(test_name: &str, test_path: &Path, schema: String, expected: String) {
    let config = read_file(&test_path.join("diesel.toml"));
    let mut p = project(&format!("{}_config", test_name)).file("diesel.toml", &config);

    let patch_file = backend_file_path(test_name, "schema.patch");
    if patch_file.exists() {
        let patch_contents = read_file(&patch_file);
        p = p.file("schema.patch", &patch_contents);
    }

    let p = p.build();

    p.command("setup").run();
    p.create_migration("12345_create_schema", &schema, "");

    let result = p.command("migration").arg("run").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    let schema = p.file_contents("src/schema.rs");
    assert_diff!(&expected, &schema, "\n", 0);

    let result = p.command("print-schema").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    assert_diff!(&expected, result.stdout(), "\n", 0);
}

fn read_file(path: &Path) -> String {
    let mut file = File::open(path).expect(&format!("Could not open {}", path.display()));
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();
    string
}
<commit_msg>cargo fmt --all<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

use support::{database, project};

#[test]
fn run_infer_schema_without_docs() {
    test_print_schema("print_schema_simple_without_docs", vec![]);
}

#[test]
fn run_infer_schema() {
    test_print_schema("print_schema_simple", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_include() {
    test_print_schema(
        "print_schema_only_tables",
        vec!["--with-docs", "-w", "users1"],
    );
}

#[test]
fn run_infer_schema_exclude() {
    test_print_schema(
        "print_schema_except_tables",
        vec!["--with-docs", "-b", "users1"],
    );
}

#[test]
fn run_infer_schema_order() {
    test_print_schema("print_schema_order", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_compound_primary_key() {
    test_print_schema("print_schema_compound_primary_key", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name() {
    test_print_schema(
        "print_schema_specifying_schema_name",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name_with_foreign_keys() {
    test_print_schema(
        "print_schema_specifying_schema_name_with_foreign_keys",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_with_foreign_keys() {
    test_print_schema("print_schema_with_foreign_keys", vec!["--with-docs"]);
}

#[test]
fn print_schema_column_renaming() {
    test_print_schema("print_schema_column_renaming", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "mysql")]
fn print_schema_unsigned() {
    test_print_schema("print_schema_unsigned", vec!["--with-docs"]);
}

#[test]
fn print_schema_patch_file() {
    let path_to_patch_file = backend_file_path("print_schema_patch_file", "schema.patch");
    let path = path_to_patch_file.display().to_string();
    test_print_schema("print_schema_patch_file", vec!["--patch-file", &path]);
}

#[test]
fn print_schema_custom_types() {
    test_print_schema(
        "print_schema_custom_types",
        vec!["--import-types", "foo::*", "--import-types", "bar::*"],
    );
}

#[cfg(feature = "sqlite")]
const BACKEND: &str = "sqlite";
#[cfg(feature = "postgres")]
const BACKEND: &str = "postgres";
#[cfg(feature = "mysql")]
const BACKEND: &str = "mysql";

fn backend_file_path(test_name: &str, file: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name)
        .join(BACKEND)
        .join(file)
}

fn test_print_schema(test_name: &str, args: Vec<&str>) {
    let test_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name);
    let p = project(test_name).build();
    let db = database(&p.database_url());

    p.command("setup").run();

    let schema = read_file(&backend_file_path(test_name, "schema.sql"));
    db.execute(&schema);

    let result = p.command("print-schema").args(args).run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    let expected = read_file(&backend_file_path(test_name, "expected.rs"));

    assert_diff!(&expected, result.stdout(), "\n", 0);

    test_print_schema_config(test_name, &test_path, schema, expected);
}

fn test_print_schema_config(test_name: &str, test_path: &Path, schema: String, expected: String) {
    let config = read_file(&test_path.join("diesel.toml"));
    let mut p = project(&format!("{}_config", test_name)).file("diesel.toml", &config);

    let patch_file = backend_file_path(test_name, "schema.patch");
    if patch_file.exists() {
        let patch_contents = read_file(&patch_file);
        p = p.file("schema.patch", &patch_contents);
    }

    let p = p.build();

    p.command("setup").run();
    p.create_migration("12345_create_schema", &schema, "");

    let result = p.command("migration").arg("run").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    let schema = p.file_contents("src/schema.rs");
    assert_diff!(&expected, &schema, "\n", 0);

    let result = p.command("print-schema").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    assert_diff!(&expected, result.stdout(), "\n", 0);
}

fn read_file(path: &Path) -> String {
    let mut file = File::open(path).expect(&format!("Could not open {}", path.display()));
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();
    string
}
<|endoftext|>


<commit_before>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/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.

#![allow(dead_code)]

use libc;
use libc::{c_int};
use std::mem;
use std::io;
use nix::from_ffi;
use std::os::unix::io::RawFd;

pub fn from_nix_error(err: ::nix::Error) -> io::Error {
    // taken from mio::io, line 178
    use std::mem;

    // TODO: Remove insane hacks once `std::io::Error::from_os_error` lands
    //       rust-lang/rust#24028
    #[allow(dead_code)]
    enum Repr {
        Os(i32),
        Custom(*const ()),
    }

    unsafe {
        mem::transmute(Repr::Os(err.errno() as i32))
    }
}

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

bitflags! {
    flags IoctlDirFlags: u8 {
        const IOC_NONE  = 0x00,
        const IOC_WRITE = 0x01,
        const IOC_READ  = 0x02,
    }
}

pub fn build_op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: u16) -> u32 {
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size as u32) << IOC_SIZESHIFT))
}

pub fn build_op_none(ioctl_type: u8, nr: u8) -> u32 {
    build_op(IOC_NONE, ioctl_type, nr, 0)
}

pub fn build_op_read(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_READ, ioctl_type, nr, size)
}

pub fn build_op_write(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_WRITE, ioctl_type, nr, size)
}

pub fn build_op_read_write(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
pub fn ioctl_read<T>(fd: RawFd, op: u32) -> io::Result<T> {
    unsafe {
        // allocate memory for the result (should get a value from kernel)
        let mut dst: T = mem::zeroed();
        let dst_ptr: *mut T = &mut dst;
        let ioctl_res: c_int = libc::funcs::bsd44::ioctl(fd as c_int, op as c_int, dst_ptr);
        match from_ffi(ioctl_res) {
            Err(err) => Err(from_nix_error(err)),
            Ok(_) => Ok(dst),
        }
    }
}
<commit_msg>WIP: cleanup from_nix_error implementation using from_raw_os_error<commit_after>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/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.

#![allow(dead_code)]

use libc;
use libc::{c_int};
use std::mem;
use std::io;
use nix::from_ffi;
use std::os::unix::io::RawFd;

// low-level ioctl functions and definitions matching the
// macros provided in ioctl.h from the kernel
const IOC_NRBITS: u32 = 8;
const IOC_TYPEBITS: u32 = 8;
const IOC_SIZEBITS: u32 = 14;
const IOC_DIRBITS: u32 = 2;

const IOC_NRSHIFT: u32 = 0;
const IOC_TYPESHIFT: u32 = IOC_NRSHIFT + IOC_NRBITS;
const IOC_SIZESHIFT: u32 = IOC_TYPESHIFT + IOC_TYPEBITS;
const IOC_DIRSHIFT: u32 = IOC_SIZESHIFT + IOC_SIZEBITS;

bitflags! {
    flags IoctlDirFlags: u8 {
        const IOC_NONE  = 0x00,
        const IOC_WRITE = 0x01,
        const IOC_READ  = 0x02,
    }
}

pub fn build_op(dir: IoctlDirFlags, ioctl_type: u8, nr: u8, size: u16) -> u32 {
    (((dir.bits as u32) << IOC_DIRSHIFT) |
     ((ioctl_type as u32) << IOC_TYPESHIFT) |
     ((nr as u32) << IOC_NRSHIFT) |
     ((size as u32) << IOC_SIZESHIFT))
}

pub fn build_op_none(ioctl_type: u8, nr: u8) -> u32 {
    build_op(IOC_NONE, ioctl_type, nr, 0)
}

pub fn build_op_read(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_READ, ioctl_type, nr, size)
}

pub fn build_op_write(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_WRITE, ioctl_type, nr, size)
}

pub fn build_op_read_write(ioctl_type: u8, nr: u8, size: u16) -> u32 {
    build_op(IOC_WRITE | IOC_READ, ioctl_type, nr, size)
}

fn from_nix_error(err: ::nix::Error) -> io::Error {
    io::Error::from_raw_os_error(err.errno() as i32)
}

/// Ioctl call that is expected to return a result
/// but which does not take any additional arguments on the input side
pub fn ioctl_read<T>(fd: RawFd, op: u32) -> io::Result<T> {
    unsafe {
        // allocate memory for the result (should get a value from kernel)
        let mut dst: T = mem::zeroed();
        let dst_ptr: *mut T = &mut dst;
        let ioctl_res: c_int = libc::funcs::bsd44::ioctl(fd as c_int, op as c_int, dst_ptr);
        match from_ffi(ioctl_res) {
            Err(err) => Err(from_nix_error(err)),
            Ok(_) => Ok(dst),
        }
    }
}
<|endoftext|>


<commit_before>use libc::{c_int, ptrace};

use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::ptr::null;

use ReadsMemory;

pub struct MemReader {
  pid: u32
}

impl MemReader {
  pub fn new(pid: u32) -> Result<MemReader, c_int> {
    Ok(MemReader {
      pid: pid
    })
  }

  fn get_memory_file(&self) -> Result<File, c_int> {
    File::open(&format!("/proc/{}/maps", self.pid)).map_err(|_| -1)
  }
}

impl ReadsMemory for MemReader {
  fn read_bytes(&self, address: usize, n: usize) -> Result<Vec<u8>, c_int> {
    unsafe { ptrace(libc::PTRACE_SEIZE, self.pid, null(), null()); }
    let mut file = self.get_memory_file()?;
    file.seek(SeekFrom::Start(address as u64)).map_err(|_| -2)?;
    let mut bytes: Vec<u8> = Vec::with_capacity(n);
    unsafe { bytes.set_len(n) };
    file.read_exact(&mut bytes).map_err(|_| -3)?;
    unsafe { ptrace(libc::PTRACE_DETACH, self.pid, null(), null()); }
    Ok(bytes)
  }
}
<commit_msg>fix: read mem, not maps<commit_after>use libc::{c_int, ptrace};

use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::ptr::null;

use ReadsMemory;

pub struct MemReader {
  pid: u32
}

impl MemReader {
  pub fn new(pid: u32) -> Result<MemReader, c_int> {
    Ok(MemReader {
      pid: pid
    })
  }

  fn get_memory_file(&self) -> Result<File, c_int> {
    File::open(&format!("/proc/{}/mem", self.pid)).map_err(|_| -1)
  }
}

impl ReadsMemory for MemReader {
  fn read_bytes(&self, address: usize, n: usize) -> Result<Vec<u8>, c_int> {
    unsafe { ptrace(libc::PTRACE_SEIZE, self.pid, null(), null()); }
    let mut file = self.get_memory_file()?;
    file.seek(SeekFrom::Start(address as u64)).map_err(|_| -2)?;
    let mut bytes: Vec<u8> = Vec::with_capacity(n);
    unsafe { bytes.set_len(n) };
    file.read_exact(&mut bytes).map_err(|_| -3)?;
    unsafe { ptrace(libc::PTRACE_DETACH, self.pid, null(), null()); }
    Ok(bytes)
  }
}
<|endoftext|>


<commit_before>
//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::ptr;

use user32::{FindWindowExA, SendMessageA};
use winapi::WM_USER;
use winapi::windef::HWND;

use super::{Handle, Session};
use super::ipc::*;
use super::raw::MutRawBytes;

/// A handle to FSUIPc that uses local IPC communication to the FSUIPC module
/// This kind of handle must be used from code running in the same process as FSUIPC does.
pub struct LocalHandle {
    handle: HWND,
}

impl LocalHandle {
    pub fn new() -> io::Result<Self> {
        unsafe {
            let win_name = CString::new("UIPCMAIN").unwrap();
            let handle = FindWindowExA(
                ptr::null_mut(), ptr::null_mut(), win_name.as_ptr(), ptr::null_mut());
            if handle != ptr::null_mut() {
                Ok(LocalHandle { handle: handle })
            } else {
                Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to local FSUIPC: cannot create window handle"))
            }
        }
    }
}

impl<'a> Handle<'a> for LocalHandle {
    type Sess = LocalSession;

    fn session(&'a mut self) -> LocalSession {
        LocalSession::new(self.handle)
    }
}

pub struct LocalSession {
    handle: HWND,
    buffer: io::Cursor<Vec<u8>>,
}

impl LocalSession {
    fn new(handle: HWND) -> Self {
        let mut session = LocalSession {
            handle: handle,
            buffer: io::Cursor::new(Vec::with_capacity(4096))
        };
        // First 4-bytes seems to be for a stack frame pointer that is not actually used
        session.buffer.set_position(4);
        session
    }
}

impl Session for LocalSession {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        self.buffer.write_rsd(offset, dest, len)
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        self.buffer.write_wsd(offset, src, len)
    }

    fn process(mut self) -> io::Result<usize> {
        unsafe {
            try!(self.buffer.write_header(&MsgHeader::TerminationMark));
            let nbytes = self.buffer.position() as usize;
            let buff = self.buffer.get_ref().as_ptr() as i32;
            let send_result = SendMessageA(self.handle, WM_IPCTHREADACCESS, nbytes as u32, buff);
            if send_result != FS6IPC_MESSAGE_SUCCESS {
                return Err(io::Error::new(io::ErrorKind::InvalidData, format!(
                    "FSUIPC rejected the requests with error {}; possible buffer corruption in bytes: {:?}",
                    send_result, self.buffer.get_ref())));
            }
            // First 4-bytes seems to be for a stack frame pointer that is not actually used
            self.buffer.set_position(4);
            loop {
                let header = try!(self.buffer.read_header());
                match &header {
                    &MsgHeader::ReadStateData { offset: _, len, target } => {
                        let mut output = MutRawBytes::new(target, len);
                        try!(self.buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::WriteStateData { offset: _, len: _ } => {
                        let mut output = io::sink();
                        try!(self.buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::TerminationMark => return Ok(nbytes),
                }
            }
        }
    }
}

const FS6IPC_MESSAGE_SUCCESS: i32 = 1;
const WM_IPCTHREADACCESS: u32 = WM_USER + 130;
<commit_msg>Use `SendMessageTimeout` to send messages to FSUIPC<commit_after>
//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::ptr;

use user32::{FindWindowExA, SendMessageTimeoutA};
use winapi::WM_USER;
use winapi::windef::HWND;
use winapi::winuser::SMTO_BLOCK;

use super::{Handle, Session};
use super::ipc::*;
use super::raw::MutRawBytes;

/// A handle to FSUIPc that uses local IPC communication to the FSUIPC module
/// This kind of handle must be used from code running in the same process as FSUIPC does.
pub struct LocalHandle {
    handle: HWND,
}

impl LocalHandle {
    pub fn new() -> io::Result<Self> {
        unsafe {
            let win_name = CString::new("UIPCMAIN").unwrap();
            let handle = FindWindowExA(
                ptr::null_mut(), ptr::null_mut(), win_name.as_ptr(), ptr::null_mut());
            if handle != ptr::null_mut() {
                Ok(LocalHandle { handle: handle })
            } else {
                Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to local FSUIPC: cannot create window handle"))
            }
        }
    }
}

impl<'a> Handle<'a> for LocalHandle {
    type Sess = LocalSession;

    fn session(&'a mut self) -> LocalSession {
        LocalSession::new(self.handle)
    }
}

pub struct LocalSession {
    handle: HWND,
    buffer: io::Cursor<Vec<u8>>,
}

impl LocalSession {
    fn new(handle: HWND) -> Self {
        let mut session = LocalSession {
            handle: handle,
            buffer: io::Cursor::new(Vec::with_capacity(4096))
        };
        // First 4-bytes seems to be for a stack frame pointer that is not actually used
        session.buffer.set_position(4);
        session
    }
}

impl Session for LocalSession {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        self.buffer.write_rsd(offset, dest, len)
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        self.buffer.write_wsd(offset, src, len)
    }

    fn process(mut self) -> io::Result<usize> {
        unsafe {
            try!(self.buffer.write_header(&MsgHeader::TerminationMark));
            let nbytes = self.buffer.position() as usize;
            let buff = self.buffer.get_ref().as_ptr() as i32;
            let mut process_result: u32 = 0;
            let send_result = SendMessageTimeoutA(
                self.handle,
                WM_IPCTHREADACCESS,
                nbytes as u32,
                buff,
                SMTO_BLOCK,
                WM_IPC_TIMEOUT,
                &mut process_result as *mut u32);
            if send_result == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::TimedOut,
                    "timed out while waiting for a response from FSUIPC"));
            }
            if process_result != FS6IPC_MESSAGE_SUCCESS {
                return Err(io::Error::new(io::ErrorKind::InvalidData, format!(
                    "FSUIPC rejected the requests with error {}; possible buffer corruption in bytes: {:?}",
                    send_result, self.buffer.get_ref())));
            }
            // First 4-bytes seems to be for a stack frame pointer that is not actually used
            self.buffer.set_position(4);
            loop {
                let header = try!(self.buffer.read_header());
                match &header {
                    &MsgHeader::ReadStateData { offset: _, len, target } => {
                        let mut output = MutRawBytes::new(target, len);
                        try!(self.buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::WriteStateData { offset: _, len: _ } => {
                        let mut output = io::sink();
                        try!(self.buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::TerminationMark => return Ok(nbytes),
                }
            }
        }
    }
}

const FS6IPC_MESSAGE_SUCCESS: u32 = 1;
const WM_IPCTHREADACCESS: u32 = WM_USER + 130;
const WM_IPC_TIMEOUT: u32 = 10000;
<|endoftext|>


<commit_before>extern crate core_graphics;
extern crate libc;

//TODO(dustin): use only the things i need
use self::core_graphics::display::*;
use self::core_graphics::event::*;
use self::core_graphics::geometry::*;
use self::core_graphics::event_source::*;

use std::ptr;
use std::mem;
use self::libc::*;

use super::MouseControllable;

// little hack until servo fixed a bug in core_graphics
// https://github.com/servo/core-graphics-rs/issues/70
// https://github.com/servo/core-graphics-rs/pull/71
#[link(name = "ApplicationServices", kind = "framework")]
extern {
    fn CGEventCreateMouseEvent( source: CGEventSourceRef,
                                mouseType: FIXMEEventType,
                                mouseCursorPosition: CGPoint,
                                mouseButton: CGMouseButton) -> CGEventRef;

    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    // not present in servo/core-graphics
    fn CGEventCreateScrollWheelEvent( source: CGEventSourceRef,
                                      units: ScrollUnit,
                                      wheelCount: uint32_t,
                                      wheel1: int32_t, ...) -> CGEventRef;
}

#[derive(Debug)]
enum FIXMEEventType {
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    MouseMoved = 5,
}

// not present in servo/core-graphics
#[derive(Debug)]
enum ScrollUnit {
    Pixel = 0,
    Line = 1,
}
// hack

pub struct Enigo {
    current_x: i32,
    current_y: i32,
    display_width: usize,
    display_height: usize,
}

impl Enigo {
    pub fn new() -> Self {
        let displayID = unsafe{CGMainDisplayID()};
        let width = unsafe{CGDisplayPixelsWide(displayID)};
        let height = unsafe{CGDisplayPixelsHigh(displayID)};

        Enigo {
            current_x: 500,
            current_y: 500,
            display_width: width,
            display_height: height,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        self.current_x = x;
        self.current_y = y;

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::MouseMoved,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        let new_x = self.current_x + x;
        let new_y = self.current_y + y;

        if new_x < 0 ||
            new_x as usize > self.display_width ||
            new_y < 0 ||
            new_y as usize > self.display_height {
            return;
        }

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::MouseMoved,
                CGPoint::new(new_x as f64, new_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }

        //TODO(dustin): use interior mutability
        self.current_x = new_x;
        self.current_y = new_y;
    }

    //TODO(dustin): use button parameter, current implementation
    //is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::LeftMouseDown,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    //TODO(dustin): use button parameter, current implementation
    //is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::LeftMouseUp,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(
                    ptr::null(),
                    ScrollUnit::Line,
                    2, //CGWheelCount 1 = y 2 = xy 3 = xyz
                    0,
                    scroll_direction
                );

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(
                    ptr::null(),
                    ScrollUnit::Line,
                    1, //CGWheelCount 1 = y 2 = xy 3 = xyz
                    scroll_direction
                );

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }
}<commit_msg>fixed enigo implement KeyboardControllable on macOS<commit_after>extern crate core_graphics;
extern crate libc;

//TODO(dustin): use only the things i need
use self::core_graphics::display::*;
use self::core_graphics::event::*;
use self::core_graphics::geometry::*;
use self::core_graphics::event_source::*;

use std::ptr;
use std::mem;
use self::libc::*;

use super::{MouseControllable, KeyboardControllable};

// little hack until servo fixed a bug in core_graphics
// https://github.com/servo/core-graphics-rs/issues/70
// https://github.com/servo/core-graphics-rs/pull/71
#[link(name = "ApplicationServices", kind = "framework")]
extern {
    fn CGEventCreateMouseEvent( source: CGEventSourceRef,
                                mouseType: FIXMEEventType,
                                mouseCursorPosition: CGPoint,
                                mouseButton: CGMouseButton) -> CGEventRef;

    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    // not present in servo/core-graphics
    fn CGEventCreateScrollWheelEvent( source: CGEventSourceRef,
                                      units: ScrollUnit,
                                      wheelCount: uint32_t,
                                      wheel1: int32_t, ...) -> CGEventRef;
}

#[derive(Debug)]
enum FIXMEEventType {
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    MouseMoved = 5,
}

// not present in servo/core-graphics
#[derive(Debug)]
enum ScrollUnit {
    Pixel = 0,
    Line = 1,
}
// hack

pub struct Enigo {
    current_x: i32,
    current_y: i32,
    display_width: usize,
    display_height: usize,
}

impl Enigo {
    pub fn new() -> Self {
        let displayID = unsafe{CGMainDisplayID()};
        let width = unsafe{CGDisplayPixelsWide(displayID)};
        let height = unsafe{CGDisplayPixelsHigh(displayID)};

        Enigo {
            current_x: 500,
            current_y: 500,
            display_width: width,
            display_height: height,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        self.current_x = x;
        self.current_y = y;

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::MouseMoved,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        let new_x = self.current_x + x;
        let new_y = self.current_y + y;

        if new_x < 0 ||
            new_x as usize > self.display_width ||
            new_y < 0 ||
            new_y as usize > self.display_height {
            return;
        }

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::MouseMoved,
                CGPoint::new(new_x as f64, new_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }

        //TODO(dustin): use interior mutability
        self.current_x = new_x;
        self.current_y = new_y;
    }

    //TODO(dustin): use button parameter, current implementation
    //is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::LeftMouseDown,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    //TODO(dustin): use button parameter, current implementation
    //is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(
                ptr::null(),
                FIXMEEventType::LeftMouseUp,
                CGPoint::new(self.current_x as f64, self.current_y as f64),
                CGMouseButton::Left
            );

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(
                    ptr::null(),
                    ScrollUnit::Line,
                    2, //CGWheelCount 1 = y 2 = xy 3 = xyz
                    0,
                    scroll_direction
                );

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(
                    ptr::null(),
                    ScrollUnit::Line,
                    1, //CGWheelCount 1 = y 2 = xy 3 = xyz
                    scroll_direction
                );

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }
}

impl KeyboardControllable for Enigo {
     fn key_sequence(&self, sequence: &str) {
         unimplemented!()
     }
}<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::fmt::{Debug, Error, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};

use ffi::futex;
use thread;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

struct MutexInner {
    lock: AtomicUsize,
    futex: i32
}

impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    pub fn lock(&mut self) {
        unsafe {
            let inner = &mut *self.inner.get();
            inner.lock()
        }
    }

    pub fn unlock(&mut self) {
        unsafe {
            let inner = &mut *self.inner.get();
            inner.unlock()
        }
    }
}

impl Debug for Mutex {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let tid = unsafe {
            let inner = &mut *self.inner.get();
            inner.lock.load(Ordering::Relaxed)
        };

        if tid == LOCK_FREE {
            fmt.write_str("Mutex { unlocked }")
        } else {
            fmt.write_fmt(format_args!("Mutex {{ owned by {} }}", tid))
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            futex: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != thread::get_current_thread().tid as usize {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.futex, 1);
    }

    pub fn lock(&mut self) {
        loop {
            let tid = thread::get_current_thread().tid;
            let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

            // If compare_and_swap didn't return LOCK_FREE, we weren't the ones
            // to set it, so go to sleep and spin.
            if swap != LOCK_FREE {
                // Go to sleep, wait for someone to unlock
                let _ = futex::wait(&mut self.futex, 0);
            }

            // Otherwise we've got the mutex, time to return.
            else {
                break;
            }
        }
    }
}
<commit_msg>Add try_lock to mutex<commit_after>use std::cell::UnsafeCell;
use std::fmt::{Debug, Error, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};

use ffi::futex;
use thread;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

struct MutexInner {
    lock: AtomicUsize,
    futex: i32
}

// TODO: a scoped / RAII lock would be useful.
impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    fn get_inner(&self) -> &mut MutexInner {
        unsafe { &mut *self.inner.get() }
    }

    pub fn try_lock(&mut self) -> bool {
        self.get_inner().try_lock()
    }

    pub fn lock(&mut self) {
        self.get_inner().lock()
    }

    pub fn unlock(&mut self) {
        self.get_inner().unlock()
    }
}

impl Debug for Mutex {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let tid = unsafe {
            let inner = &mut *self.inner.get();
            inner.lock.load(Ordering::Relaxed)
        };

        if tid == LOCK_FREE {
            fmt.write_str("Mutex { unlocked }")
        } else {
            fmt.write_fmt(format_args!("Mutex {{ owned by {} }}", tid))
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            futex: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != thread::get_current_thread().tid as usize {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.futex, 1);
    }

    pub fn try_lock(&mut self) -> bool {
        let tid = thread::get_current_thread().tid;
        let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

        // If compare_and_swap returned LOCK_FREE, we were the first ones
        // to grab the lock, so we currently own the mutex.
        swap == LOCK_FREE
    }

    pub fn lock(&mut self) {
        while !self.try_lock() {
            // We didn't get the lock this time, wait for owner to unlock
            let _ = futex::wait(&mut self.futex, 0);
        }
    }
}
<|endoftext|>