<commit_before>
extern crate image;
extern crate nalgebra;

use std::f64::consts::{PI, FRAC_PI_2};
use std::fs::File;
use std::path::Path;
use image::{GenericImage, Pixel, Rgba};
use nalgebra::{DVec, Mat2, Pnt2, Rot2, Vec1, Vec2, Vec3};

fn draw(v: &DVec<f64>, path: &Path) {
    let width = v.len() as u32;
    let height = 128u32;
    let white: Rgba<u8> = Pixel::from_channels(255, 255, 255, 255);
    let buffer = image::ImageBuffer::from_pixel(width, height, white);
    let mut img = image::DynamicImage::ImageRgba8(buffer);
    let red = Pixel::from_channels(255, 0, 0, 255);
    for i in 0u32..(width) {
        let half = (height / 2) as f64;
        let y = half * (1.0 + v[i as usize]);
        let y = nalgebra::clamp(y as u32, 1u32, height);
        img.put_pixel(i, height - y, red);
    }
    let mut out = File::create(path).unwrap();
    let _ = img.save(&mut out, image::PNG);
}

fn main() {
    println!("24 days of Rust - nalgebra (day 14)");
    let v = Vec2::new(0.0f64, 1.0);
    // 90 degrees clockwise
    //  0, 1
    // -1, 0
    let rot = Mat2::new(0.0f64, -1.0, 1.0, 0.0);
    println!("{:?}", rot * v);
    let angle = FRAC_PI_2;
    let rot = Rot2::new(Vec1::new(angle));
    println!("{:?}", rot * v);
    let point = Pnt2::new(4.0f64, 4.0);
    println!("Translate from {:?} to {:?}", point, nalgebra::translate(&v, &point));

    let v1 = Vec3::new(2.0f64, 2.0, 0.0);
    let v2 = Vec3::new(2.0f64, -2.0, 0.0);
    if nalgebra::approx_eq(&0.0f64, &nalgebra::dot(&v1, &v2)) {
        println!("v1 is orthogonal to v2");
    }

    println!("{:?}", nalgebra::cross(&v1, &v2));
    println!("{:?}", nalgebra::cross(&v2, &v1));

    const SIZE: usize = 512;
    let sine = DVec::from_fn(SIZE, |i: usize| {
        let t = i as f64 / 16.0f64;
        t.sin()
    });
    draw(&sine, &Path::new("out_sine.png"));

    let window = DVec::from_fn(SIZE, |i: usize| {
        0.54f64 - 0.46 * (PI * 2.0 * (i as f64) / (SIZE - 1) as f64).cos()
    });
    draw(&window, &Path::new("out_window.png"));

    draw(&(sine * window), &Path::new("out_windowed.png"));
}
<commit_msg>Whitespace fix<commit_after>extern crate image;
extern crate nalgebra;

use std::f64::consts::{PI, FRAC_PI_2};
use std::fs::File;
use std::path::Path;
use image::{GenericImage, Pixel, Rgba};
use nalgebra::{DVec, Mat2, Pnt2, Rot2, Vec1, Vec2, Vec3};

fn draw(v: &DVec<f64>, path: &Path) {
    let width = v.len() as u32;
    let height = 128u32;
    let white: Rgba<u8> = Pixel::from_channels(255, 255, 255, 255);
    let buffer = image::ImageBuffer::from_pixel(width, height, white);
    let mut img = image::DynamicImage::ImageRgba8(buffer);
    let red = Pixel::from_channels(255, 0, 0, 255);
    for i in 0u32..(width) {
        let half = (height / 2) as f64;
        let y = half * (1.0 + v[i as usize]);
        let y = nalgebra::clamp(y as u32, 1u32, height);
        img.put_pixel(i, height - y, red);
    }
    let mut out = File::create(path).unwrap();
    let _ = img.save(&mut out, image::PNG);
}

fn main() {
    println!("24 days of Rust - nalgebra (day 14)");
    let v = Vec2::new(0.0f64, 1.0);
    // 90 degrees clockwise
    //  0, 1
    // -1, 0
    let rot = Mat2::new(0.0f64, -1.0, 1.0, 0.0);
    println!("{:?}", rot * v);
    let angle = FRAC_PI_2;
    let rot = Rot2::new(Vec1::new(angle));
    println!("{:?}", rot * v);
    let point = Pnt2::new(4.0f64, 4.0);
    println!("Translate from {:?} to {:?}", point, nalgebra::translate(&v, &point));

    let v1 = Vec3::new(2.0f64, 2.0, 0.0);
    let v2 = Vec3::new(2.0f64, -2.0, 0.0);
    if nalgebra::approx_eq(&0.0f64, &nalgebra::dot(&v1, &v2)) {
        println!("v1 is orthogonal to v2");
    }

    println!("{:?}", nalgebra::cross(&v1, &v2));
    println!("{:?}", nalgebra::cross(&v2, &v1));

    const SIZE: usize = 512;
    let sine = DVec::from_fn(SIZE, |i: usize| {
        let t = i as f64 / 16.0f64;
        t.sin()
    });
    draw(&sine, &Path::new("out_sine.png"));

    let window = DVec::from_fn(SIZE, |i: usize| {
        0.54f64 - 0.46 * (PI * 2.0 * (i as f64) / (SIZE - 1) as f64).cos()
    });
    draw(&window, &Path::new("out_window.png"));

    draw(&(sine * window), &Path::new("out_windowed.png"));
}
<|endoftext|>


<commit_before>//! Error and Result module
use std::{fmt, result};
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::io::Error as IoError;

use cookie;
use httparse;
use failure::Fail;
use http2::Error as Http2Error;
use http::{header, StatusCode, Error as HttpError};
use http_range::HttpRangeParseError;

// re-exports
pub use cookie::{ParseError as CookieParseError};

use body::Body;
use httpresponse::HttpResponse;
use httpcodes::{HTTPBadRequest, HTTPMethodNotAllowed, HTTPExpectationFailed};

/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
/// for actix web operations
///
/// This typedef is generally used to avoid writing out `actix_web::error::Error` directly and
/// is otherwise a direct mapping to `Result`.
pub type Result<T> = result::Result<T, Error>;

/// Actix web error
#[derive(Debug)]
pub struct Error {
    cause: Box<ErrorResponse>,
}

impl Error {

    /// Returns a reference to the underlying cause of this Error.
    // this should return &Fail but needs this https://github.com/rust-lang/rust/issues/5665
    pub fn cause(&self) -> &ErrorResponse {
        self.cause.as_ref()
    }
}

/// Error that can be converted to `HttpResponse`
pub trait ErrorResponse: Fail {

    /// Create response for error
    ///
    /// Internal server error is generated by default.
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty)
    }
}

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

/// `HttpResponse` for `Error`
impl From<Error> for HttpResponse {
    fn from(err: Error) -> Self {
        err.cause.error_response()
    }
}

impl<T: ErrorResponse> From<T> for Error {
    fn from(err: T) -> Error {
        Error { cause: Box::new(err) }
    }
}

// /// Default error is `InternalServerError`
// impl<T: StdError + Sync + Send + 'static> ErrorResponse for T {
//     fn error_response(&self) -> HttpResponse {
//         HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty)
//     }
// }

/// A set of errors that can occur during parsing HTTP streams
#[derive(Fail, Debug)]
pub enum ParseError {
    /// An invalid `Method`, such as `GE.T`.
    #[fail(display="Invalid Method specified")]
    Method,
    /// An invalid `Uri`, such as `exam ple.domain`.
    #[fail(display="Uri error")]
    Uri,
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    #[fail(display="Invalid HTTP version specified")]
    Version,
    /// An invalid `Header`.
    #[fail(display="Invalid Header provided")]
    Header,
    /// A message head is too large to be reasonable.
    #[fail(display="Message head is too large")]
    TooLarge,
    /// A message reached EOF, but is not complete.
    #[fail(display="Message is incomplete")]
    Incomplete,
    /// An invalid `Status`, such as `1337 ELITE`.
    #[fail(display="Invalid Status provided")]
    Status,
    /// A timeout occurred waiting for an IO event.
    #[allow(dead_code)]
    #[fail(display="Timeout")]
    Timeout,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    #[fail(display="IO error: {}", _0)]
    Io(#[cause] IoError),
    /// Parsing a field as string failed
    #[fail(display="UTF8 error: {}", _0)]
    Utf8(#[cause] Utf8Error),
}

/// Return `BadRequest` for `ParseError`
impl ErrorResponse for ParseError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

impl From<IoError> for ParseError {
    fn from(err: IoError) -> ParseError {
        ParseError::Io(err)
    }
}

impl From<Utf8Error> for ParseError {
    fn from(err: Utf8Error) -> ParseError {
        ParseError::Utf8(err)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8(err.utf8_error())
    }
}

impl From<httparse::Error> for ParseError {
    fn from(err: httparse::Error) -> ParseError {
        match err {
            httparse::Error::HeaderName |
            httparse::Error::HeaderValue |
            httparse::Error::NewLine |
            httparse::Error::Token => ParseError::Header,
            httparse::Error::Status => ParseError::Status,
            httparse::Error::TooManyHeaders => ParseError::TooLarge,
            httparse::Error::Version => ParseError::Version,
        }
    }
}

#[derive(Fail, Debug)]
/// A set of errors that can occur during payload parsing
pub enum PayloadError {
    /// A payload reached EOF, but is not complete.
    #[fail(display="A payload reached EOF, but is not complete.")]
    Incomplete,
    /// Content encoding stream corruption
    #[fail(display="Can not decode content-encoding.")]
    EncodingCorrupted,
    /// Parse error
    #[fail(display="{}", _0)]
    ParseError(#[cause] IoError),
    /// Http2 error
    #[fail(display="{}", _0)]
    Http2(#[cause] Http2Error),
}

impl From<IoError> for PayloadError {
    fn from(err: IoError) -> PayloadError {
        PayloadError::ParseError(err)
    }
}

/// Return `InternalServerError` for `HttpError`,
/// Response generation can return `HttpError`, so it is internal error
impl ErrorResponse for HttpError {}

/// Return `InternalServerError` for `io::Error`
impl ErrorResponse for IoError {}

/// Return `BadRequest` for `cookie::ParseError`
impl ErrorResponse for cookie::ParseError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

/// Http range header parsing error
#[derive(Fail, PartialEq, Debug)]
pub enum HttpRangeError {
    /// Returned if range is invalid.
    #[fail(display="Range header is invalid")]
    InvalidRange,
    /// Returned if first-byte-pos of all of the byte-range-spec
    /// values is greater than the content size.
    /// See https://github.com/golang/go/commit/aa9b3d7
    #[fail(display="First-byte-pos of all of the byte-range-spec values is greater than the content size")]
    NoOverlap,
}

/// Return `BadRequest` for `HttpRangeError`
impl ErrorResponse for HttpRangeError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(
            StatusCode::BAD_REQUEST, Body::from("Invalid Range header provided"))
    }
}

impl From<HttpRangeParseError> for HttpRangeError {
    fn from(err: HttpRangeParseError) -> HttpRangeError {
        match err {
            HttpRangeParseError::InvalidRange => HttpRangeError::InvalidRange,
            HttpRangeParseError::NoOverlap => HttpRangeError::NoOverlap,
        }
    }
}

/// A set of errors that can occur during parsing multipart streams
#[derive(Fail, Debug)]
pub enum MultipartError {
    /// Content-Type header is not found
    #[fail(display="No Content-type header found")]
    NoContentType,
    /// Can not parse Content-Type header
    #[fail(display="Can not parse Content-Type header")]
    ParseContentType,
    /// Multipart boundary is not found
    #[fail(display="Multipart boundary is not found")]
    Boundary,
    /// Error during field parsing
    #[fail(display="{}", _0)]
    Parse(#[cause] ParseError),
    /// Payload error
    #[fail(display="{}", _0)]
    Payload(#[cause] PayloadError),
}

impl From<ParseError> for MultipartError {
    fn from(err: ParseError) -> MultipartError {
        MultipartError::Parse(err)
    }
}

impl From<PayloadError> for MultipartError {
    fn from(err: PayloadError) -> MultipartError {
        MultipartError::Payload(err)
    }
}

/// Return `BadRequest` for `MultipartError`
impl ErrorResponse for MultipartError {

    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

/// Error during handling `Expect` header
#[derive(Fail, PartialEq, Debug)]
pub enum ExpectError {
    /// Expect header value can not be converted to utf8
    #[fail(display="Expect header value can not be converted to utf8")]
    Encoding,
    /// Unknown expect value
    #[fail(display="Unknown expect value")]
    UnknownExpect,
}

impl ErrorResponse for ExpectError {

    fn error_response(&self) -> HttpResponse {
        HTTPExpectationFailed.with_body("Unknown Expect")
    }
}

/// Websocket handshake errors
#[derive(Fail, PartialEq, Debug)]
pub enum WsHandshakeError {
    /// Only get method is allowed
    #[fail(display="Method not allowed")]
    GetMethodRequired,
    /// Ugrade header if not set to websocket
    #[fail(display="Websocket upgrade is expected")]
    NoWebsocketUpgrade,
    /// Connection header is not set to upgrade
    #[fail(display="Connection upgrade is expected")]
    NoConnectionUpgrade,
    /// Websocket version header is not set
    #[fail(display="Websocket version header is required")]
    NoVersionHeader,
    /// Unsupported websockt version
    #[fail(display="Unsupported version")]
    UnsupportedVersion,
    /// Websocket key is not set or wrong
    #[fail(display="Unknown websocket key")]
    BadWebsocketKey,
}

impl ErrorResponse for WsHandshakeError {

    fn error_response(&self) -> HttpResponse {
        match *self {
            WsHandshakeError::GetMethodRequired => {
                HTTPMethodNotAllowed
                    .builder()
                    .header(header::ALLOW, "GET")
                    .finish()
                    .unwrap()
            }
            WsHandshakeError::NoWebsocketUpgrade =>
                HTTPBadRequest.with_reason("No WebSocket UPGRADE header found"),
            WsHandshakeError::NoConnectionUpgrade =>
                HTTPBadRequest.with_reason("No CONNECTION upgrade"),
            WsHandshakeError::NoVersionHeader =>
                HTTPBadRequest.with_reason("Websocket version header is required"),
            WsHandshakeError::UnsupportedVersion =>
                HTTPBadRequest.with_reason("Unsupported version"),
            WsHandshakeError::BadWebsocketKey =>
                HTTPBadRequest.with_reason("Handshake error")
        }
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use http::{StatusCode, Error as HttpError};
    use cookie::ParseError as CookieParseError;
    use super::*;

    #[test]
    fn test_into_response() {
        let resp: HttpResponse = ParseError::Incomplete.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = HttpRangeError::InvalidRange.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = CookieParseError::EmptyName.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = MultipartError::Boundary.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
        let resp: HttpResponse = err.error_response();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = ParseError::Io(orig);
        assert_eq!(format!("{}", e.cause().unwrap()), desc);
    }

    #[test]
    fn test_error_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Error::from(orig);
        assert_eq!(format!("{}", e.cause()), desc);
    }

    #[test]
    fn test_error_display() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Error::from(orig);
        assert_eq!(format!("{}", e), desc);
    }

    #[test]
    fn test_error_http_response() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let e = Error::from(orig);
        let resp: HttpResponse = e.into();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    #[test]
    fn test_range_error() {
        let e: HttpRangeError = HttpRangeParseError::InvalidRange.into();
        assert_eq!(e, HttpRangeError::InvalidRange);
        let e: HttpRangeError = HttpRangeParseError::NoOverlap.into();
        assert_eq!(e, HttpRangeError::NoOverlap);
    }

    #[test]
    fn test_wserror_http_response() {
        let resp: HttpResponse = WsHandshakeError::GetMethodRequired.error_response();
        assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
        let resp: HttpResponse = WsHandshakeError::NoWebsocketUpgrade.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::NoConnectionUpgrade.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::NoVersionHeader.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::UnsupportedVersion.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::BadWebsocketKey.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match ParseError::from($from) {
                e @ $error => {
                    assert!(format!("{}", e).len() >= 5);
                } ,
                e => panic!("{:?}", e)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match ParseError::from($from) {
                e @ $error => {
                    let desc = format!("{}", e.cause().unwrap());
                    assert_eq!(desc, $from.description().to_owned());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {
        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..));

        from!(httparse::Error::HeaderName => ParseError::Header);
        from!(httparse::Error::HeaderName => ParseError::Header);
        from!(httparse::Error::HeaderValue => ParseError::Header);
        from!(httparse::Error::NewLine => ParseError::Header);
        from!(httparse::Error::Status => ParseError::Status);
        from!(httparse::Error::Token => ParseError::Header);
        from!(httparse::Error::TooManyHeaders => ParseError::TooLarge);
        from!(httparse::Error::Version => ParseError::Version);
    }
}
<commit_msg>expect error tests<commit_after>//! Error and Result module
use std::{fmt, result};
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::io::Error as IoError;

use cookie;
use httparse;
use failure::Fail;
use http2::Error as Http2Error;
use http::{header, StatusCode, Error as HttpError};
use http_range::HttpRangeParseError;

// re-exports
pub use cookie::{ParseError as CookieParseError};

use body::Body;
use httpresponse::HttpResponse;
use httpcodes::{HTTPBadRequest, HTTPMethodNotAllowed, HTTPExpectationFailed};

/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
/// for actix web operations
///
/// This typedef is generally used to avoid writing out `actix_web::error::Error` directly and
/// is otherwise a direct mapping to `Result`.
pub type Result<T> = result::Result<T, Error>;

/// Actix web error
#[derive(Debug)]
pub struct Error {
    cause: Box<ErrorResponse>,
}

impl Error {

    /// Returns a reference to the underlying cause of this Error.
    // this should return &Fail but needs this https://github.com/rust-lang/rust/issues/5665
    pub fn cause(&self) -> &ErrorResponse {
        self.cause.as_ref()
    }
}

/// Error that can be converted to `HttpResponse`
pub trait ErrorResponse: Fail {

    /// Create response for error
    ///
    /// Internal server error is generated by default.
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty)
    }
}

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

/// `HttpResponse` for `Error`
impl From<Error> for HttpResponse {
    fn from(err: Error) -> Self {
        err.cause.error_response()
    }
}

impl<T: ErrorResponse> From<T> for Error {
    fn from(err: T) -> Error {
        Error { cause: Box::new(err) }
    }
}

// /// Default error is `InternalServerError`
// impl<T: StdError + Sync + Send + 'static> ErrorResponse for T {
//     fn error_response(&self) -> HttpResponse {
//         HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty)
//     }
// }

/// A set of errors that can occur during parsing HTTP streams
#[derive(Fail, Debug)]
pub enum ParseError {
    /// An invalid `Method`, such as `GE.T`.
    #[fail(display="Invalid Method specified")]
    Method,
    /// An invalid `Uri`, such as `exam ple.domain`.
    #[fail(display="Uri error")]
    Uri,
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    #[fail(display="Invalid HTTP version specified")]
    Version,
    /// An invalid `Header`.
    #[fail(display="Invalid Header provided")]
    Header,
    /// A message head is too large to be reasonable.
    #[fail(display="Message head is too large")]
    TooLarge,
    /// A message reached EOF, but is not complete.
    #[fail(display="Message is incomplete")]
    Incomplete,
    /// An invalid `Status`, such as `1337 ELITE`.
    #[fail(display="Invalid Status provided")]
    Status,
    /// A timeout occurred waiting for an IO event.
    #[allow(dead_code)]
    #[fail(display="Timeout")]
    Timeout,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    #[fail(display="IO error: {}", _0)]
    Io(#[cause] IoError),
    /// Parsing a field as string failed
    #[fail(display="UTF8 error: {}", _0)]
    Utf8(#[cause] Utf8Error),
}

/// Return `BadRequest` for `ParseError`
impl ErrorResponse for ParseError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

impl From<IoError> for ParseError {
    fn from(err: IoError) -> ParseError {
        ParseError::Io(err)
    }
}

impl From<Utf8Error> for ParseError {
    fn from(err: Utf8Error) -> ParseError {
        ParseError::Utf8(err)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8(err.utf8_error())
    }
}

impl From<httparse::Error> for ParseError {
    fn from(err: httparse::Error) -> ParseError {
        match err {
            httparse::Error::HeaderName |
            httparse::Error::HeaderValue |
            httparse::Error::NewLine |
            httparse::Error::Token => ParseError::Header,
            httparse::Error::Status => ParseError::Status,
            httparse::Error::TooManyHeaders => ParseError::TooLarge,
            httparse::Error::Version => ParseError::Version,
        }
    }
}

#[derive(Fail, Debug)]
/// A set of errors that can occur during payload parsing
pub enum PayloadError {
    /// A payload reached EOF, but is not complete.
    #[fail(display="A payload reached EOF, but is not complete.")]
    Incomplete,
    /// Content encoding stream corruption
    #[fail(display="Can not decode content-encoding.")]
    EncodingCorrupted,
    /// Parse error
    #[fail(display="{}", _0)]
    ParseError(#[cause] IoError),
    /// Http2 error
    #[fail(display="{}", _0)]
    Http2(#[cause] Http2Error),
}

impl From<IoError> for PayloadError {
    fn from(err: IoError) -> PayloadError {
        PayloadError::ParseError(err)
    }
}

/// Return `InternalServerError` for `HttpError`,
/// Response generation can return `HttpError`, so it is internal error
impl ErrorResponse for HttpError {}

/// Return `InternalServerError` for `io::Error`
impl ErrorResponse for IoError {}

/// Return `BadRequest` for `cookie::ParseError`
impl ErrorResponse for cookie::ParseError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

/// Http range header parsing error
#[derive(Fail, PartialEq, Debug)]
pub enum HttpRangeError {
    /// Returned if range is invalid.
    #[fail(display="Range header is invalid")]
    InvalidRange,
    /// Returned if first-byte-pos of all of the byte-range-spec
    /// values is greater than the content size.
    /// See https://github.com/golang/go/commit/aa9b3d7
    #[fail(display="First-byte-pos of all of the byte-range-spec values is greater than the content size")]
    NoOverlap,
}

/// Return `BadRequest` for `HttpRangeError`
impl ErrorResponse for HttpRangeError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(
            StatusCode::BAD_REQUEST, Body::from("Invalid Range header provided"))
    }
}

impl From<HttpRangeParseError> for HttpRangeError {
    fn from(err: HttpRangeParseError) -> HttpRangeError {
        match err {
            HttpRangeParseError::InvalidRange => HttpRangeError::InvalidRange,
            HttpRangeParseError::NoOverlap => HttpRangeError::NoOverlap,
        }
    }
}

/// A set of errors that can occur during parsing multipart streams
#[derive(Fail, Debug)]
pub enum MultipartError {
    /// Content-Type header is not found
    #[fail(display="No Content-type header found")]
    NoContentType,
    /// Can not parse Content-Type header
    #[fail(display="Can not parse Content-Type header")]
    ParseContentType,
    /// Multipart boundary is not found
    #[fail(display="Multipart boundary is not found")]
    Boundary,
    /// Error during field parsing
    #[fail(display="{}", _0)]
    Parse(#[cause] ParseError),
    /// Payload error
    #[fail(display="{}", _0)]
    Payload(#[cause] PayloadError),
}

impl From<ParseError> for MultipartError {
    fn from(err: ParseError) -> MultipartError {
        MultipartError::Parse(err)
    }
}

impl From<PayloadError> for MultipartError {
    fn from(err: PayloadError) -> MultipartError {
        MultipartError::Payload(err)
    }
}

/// Return `BadRequest` for `MultipartError`
impl ErrorResponse for MultipartError {

    fn error_response(&self) -> HttpResponse {
        HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
    }
}

/// Error during handling `Expect` header
#[derive(Fail, PartialEq, Debug)]
pub enum ExpectError {
    /// Expect header value can not be converted to utf8
    #[fail(display="Expect header value can not be converted to utf8")]
    Encoding,
    /// Unknown expect value
    #[fail(display="Unknown expect value")]
    UnknownExpect,
}

impl ErrorResponse for ExpectError {

    fn error_response(&self) -> HttpResponse {
        HTTPExpectationFailed.with_body("Unknown Expect")
    }
}

/// Websocket handshake errors
#[derive(Fail, PartialEq, Debug)]
pub enum WsHandshakeError {
    /// Only get method is allowed
    #[fail(display="Method not allowed")]
    GetMethodRequired,
    /// Ugrade header if not set to websocket
    #[fail(display="Websocket upgrade is expected")]
    NoWebsocketUpgrade,
    /// Connection header is not set to upgrade
    #[fail(display="Connection upgrade is expected")]
    NoConnectionUpgrade,
    /// Websocket version header is not set
    #[fail(display="Websocket version header is required")]
    NoVersionHeader,
    /// Unsupported websockt version
    #[fail(display="Unsupported version")]
    UnsupportedVersion,
    /// Websocket key is not set or wrong
    #[fail(display="Unknown websocket key")]
    BadWebsocketKey,
}

impl ErrorResponse for WsHandshakeError {

    fn error_response(&self) -> HttpResponse {
        match *self {
            WsHandshakeError::GetMethodRequired => {
                HTTPMethodNotAllowed
                    .builder()
                    .header(header::ALLOW, "GET")
                    .finish()
                    .unwrap()
            }
            WsHandshakeError::NoWebsocketUpgrade =>
                HTTPBadRequest.with_reason("No WebSocket UPGRADE header found"),
            WsHandshakeError::NoConnectionUpgrade =>
                HTTPBadRequest.with_reason("No CONNECTION upgrade"),
            WsHandshakeError::NoVersionHeader =>
                HTTPBadRequest.with_reason("Websocket version header is required"),
            WsHandshakeError::UnsupportedVersion =>
                HTTPBadRequest.with_reason("Unsupported version"),
            WsHandshakeError::BadWebsocketKey =>
                HTTPBadRequest.with_reason("Handshake error")
        }
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use http::{StatusCode, Error as HttpError};
    use cookie::ParseError as CookieParseError;
    use super::*;

    #[test]
    fn test_into_response() {
        let resp: HttpResponse = ParseError::Incomplete.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = HttpRangeError::InvalidRange.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = CookieParseError::EmptyName.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let resp: HttpResponse = MultipartError::Boundary.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

        let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
        let resp: HttpResponse = err.error_response();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = ParseError::Io(orig);
        assert_eq!(format!("{}", e.cause().unwrap()), desc);
    }

    #[test]
    fn test_error_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Error::from(orig);
        assert_eq!(format!("{}", e.cause()), desc);
    }

    #[test]
    fn test_error_display() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Error::from(orig);
        assert_eq!(format!("{}", e), desc);
    }

    #[test]
    fn test_error_http_response() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let e = Error::from(orig);
        let resp: HttpResponse = e.into();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    #[test]
    fn test_range_error() {
        let e: HttpRangeError = HttpRangeParseError::InvalidRange.into();
        assert_eq!(e, HttpRangeError::InvalidRange);
        let e: HttpRangeError = HttpRangeParseError::NoOverlap.into();
        assert_eq!(e, HttpRangeError::NoOverlap);
    }

    #[test]
    fn test_expect_error() {
        let resp: HttpResponse = ExpectError::Encoding.error_response();
        assert_eq!(resp.status(), StatusCode::EXPECTATION_FAILED);
        let resp: HttpResponse = ExpectError::UnknownExpect.error_response();
        assert_eq!(resp.status(), StatusCode::EXPECTATION_FAILED);
    }

    #[test]
    fn test_wserror_http_response() {
        let resp: HttpResponse = WsHandshakeError::GetMethodRequired.error_response();
        assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
        let resp: HttpResponse = WsHandshakeError::NoWebsocketUpgrade.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::NoConnectionUpgrade.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::NoVersionHeader.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::UnsupportedVersion.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
        let resp: HttpResponse = WsHandshakeError::BadWebsocketKey.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match ParseError::from($from) {
                e @ $error => {
                    assert!(format!("{}", e).len() >= 5);
                } ,
                e => panic!("{:?}", e)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match ParseError::from($from) {
                e @ $error => {
                    let desc = format!("{}", e.cause().unwrap());
                    assert_eq!(desc, $from.description().to_owned());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {
        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..));

        from!(httparse::Error::HeaderName => ParseError::Header);
        from!(httparse::Error::HeaderName => ParseError::Header);
        from!(httparse::Error::HeaderValue => ParseError::Header);
        from!(httparse::Error::NewLine => ParseError::Header);
        from!(httparse::Error::Status => ParseError::Status);
        from!(httparse::Error::Token => ParseError::Header);
        from!(httparse::Error::TooManyHeaders => ParseError::TooLarge);
        from!(httparse::Error::Version => ParseError::Version);
    }
}
<|endoftext|>


<commit_before>//! Defines error types used by this library.

use Value;

use reqwest::Error as ReqwestError;
use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::io;
use std::fmt::{self, Formatter, Display};
use std::error::Error;
use std::collections::BTreeMap;

/// A request could not be executed.
///
/// This is either a lower-level error (for example, the HTTP request failed), or a problem with the
/// server (maybe it's not implementing XML-RPC correctly). If the server sends a valid response,
/// this error will not occur.
#[derive(Debug)]
pub enum RequestError {
    /// An HTTP communication error occurred while sending the request or receiving the response.
    HttpError(ReqwestError),

    /// The HTTP status code did not indicate success.
    HttpStatus(String),

    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    // TODO make this extensible. anything missing?
}

impl From<ReqwestError> for RequestError {
    fn from(e: ReqwestError) -> Self {
        RequestError::HttpError(e)
    }
}

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

impl Display for RequestError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestError::HttpError(ref err) => write!(fmt, "HTTP error: {}", err),
            RequestError::HttpStatus(ref err) => write!(fmt, "HTTP status: {}", err),
            RequestError::ParseError(ref err) => write!(fmt, "parse error: {}", err),
        }
    }
}

impl Error for RequestError {
    fn description(&self) -> &str {
        match *self {
            RequestError::HttpError(ref err) => err.description(),
            RequestError::HttpStatus(ref err) => &err,
            RequestError::ParseError(ref err) => err.description(),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

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

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

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response - The call failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field.
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

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

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }
}
<commit_msg>impl Error for Fault<commit_after>//! Defines error types used by this library.

use Value;

use reqwest::Error as ReqwestError;
use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::io;
use std::fmt::{self, Formatter, Display};
use std::error::Error;
use std::collections::BTreeMap;

/// A request could not be executed.
///
/// This is either a lower-level error (for example, the HTTP request failed), or a problem with the
/// server (maybe it's not implementing XML-RPC correctly). If the server sends a valid response,
/// this error will not occur.
#[derive(Debug)]
pub enum RequestError {
    /// An HTTP communication error occurred while sending the request or receiving the response.
    HttpError(ReqwestError),

    /// The HTTP status code did not indicate success.
    HttpStatus(String),

    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    // TODO make this extensible. anything missing?
}

impl From<ReqwestError> for RequestError {
    fn from(e: ReqwestError) -> Self {
        RequestError::HttpError(e)
    }
}

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

impl Display for RequestError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestError::HttpError(ref err) => write!(fmt, "HTTP error: {}", err),
            RequestError::HttpStatus(ref err) => write!(fmt, "HTTP status: {}", err),
            RequestError::ParseError(ref err) => write!(fmt, "parse error: {}", err),
        }
    }
}

impl Error for RequestError {
    fn description(&self) -> &str {
        match *self {
            RequestError::HttpError(ref err) => err.description(),
            RequestError::HttpStatus(ref err) => &err,
            RequestError::ParseError(ref err) => err.description(),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

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

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

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response - The call failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field.
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

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

impl Error for Fault {
    fn description(&self) -> &str {
        &self.fault_string
    }
}

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

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }
}
<|endoftext|>


<commit_before>//! Define Errors

use std::error;
use std::fmt;
use ndarray::{Ixs, ShapeError};

#[derive(Debug, EnumError)]
pub enum LinalgError {
    NotSquare(NotSquareError),
    Lapack(LapackError),
    Stride(StrideError),
    Shape(ShapeError),
}

#[derive(Debug)]
pub struct LapackError {
    pub return_code: i32,
}

impl fmt::Display for LapackError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "LAPACK: return_code = {}", self.return_code)
    }
}

impl error::Error for LapackError {
    fn description(&self) -> &str {
        "LAPACK subroutine returns non-zero code"
    }
}

impl From<i32> for LapackError {
    fn from(code: i32) -> LapackError {
        LapackError { return_code: code }
    }
}

#[derive(Debug)]
pub struct NotSquareError {
    pub rows: usize,
    pub cols: usize,
}

impl fmt::Display for NotSquareError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not square: rows({}) != cols({})", self.rows, self.cols)
    }
}

impl error::Error for NotSquareError {
    fn description(&self) -> &str {
        "Matrix is not square"
    }
}

#[derive(Debug)]
pub struct StrideError {
    pub s0: Ixs,
    pub s1: Ixs,
}

impl fmt::Display for StrideError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "invalid stride: s0={}, s1={}", self.s0, self.s1)
    }
}

impl error::Error for StrideError {
    fn description(&self) -> &str {
        "invalid stride"
    }
}
<commit_msg>Add MemoryContError<commit_after>//! Define Errors

use std::error;
use std::fmt;
use ndarray::{Ixs, ShapeError};

#[derive(Debug, EnumError)]
pub enum LinalgError {
    NotSquare(NotSquareError),
    Lapack(LapackError),
    Stride(StrideError),
    MemoryCont(MemoryContError),
    Shape(ShapeError),
}

#[derive(Debug)]
pub struct LapackError {
    pub return_code: i32,
}

impl fmt::Display for LapackError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "LAPACK: return_code = {}", self.return_code)
    }
}

impl error::Error for LapackError {
    fn description(&self) -> &str {
        "LAPACK subroutine returns non-zero code"
    }
}

impl From<i32> for LapackError {
    fn from(code: i32) -> LapackError {
        LapackError { return_code: code }
    }
}

#[derive(Debug)]
pub struct NotSquareError {
    pub rows: usize,
    pub cols: usize,
}

impl fmt::Display for NotSquareError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not square: rows({}) != cols({})", self.rows, self.cols)
    }
}

impl error::Error for NotSquareError {
    fn description(&self) -> &str {
        "Matrix is not square"
    }
}

#[derive(Debug)]
pub struct StrideError {
    pub s0: Ixs,
    pub s1: Ixs,
}

impl fmt::Display for StrideError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "invalid stride: s0={}, s1={}", self.s0, self.s1)
    }
}

impl error::Error for StrideError {
    fn description(&self) -> &str {
        "invalid stride"
    }
}

#[derive(Debug)]
pub struct MemoryContError {}

impl fmt::Display for MemoryContError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Memory is not contiguous")
    }
}

impl error::Error for MemoryContError {
    fn description(&self) -> &str {
        "Memory is not contiguous"
    }
}
<|endoftext|>


<commit_before>extern crate regex;
extern crate toml;

use constant::*;
use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{self, Display};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    CannotHappen(CannotHappenError),
    Config(ConfigError),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
}
impl Display for CliError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CliError::CannotHappen(ref e) => e.fmt(f),
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::CannotHappen(ref e) => Some(e),
            CliError::Config(ref e)       => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::CannotHappen(ref e) => e.description(),
            CliError::Config(ref e)       => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
        }
    }
}
impl From<CannotHappenError> for CliError {
    fn from(e: CannotHappenError) -> CliError {
        CliError::CannotHappen(e)
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}

#[derive(Debug)]
pub struct RunningPlaceError {
    pub dir: String,
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
impl Display for EssentialKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            EssentialKind::WorkingDir => format!("{} directory", WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("{} directory", STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("{} file"     , CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("{} file"     , IGNORE_FILE_NAME),
        })
    }
}

#[derive(Debug)]
pub struct EssentialLack {
    pub what: EssentialKind,
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} does not exist. Please use \"init\" command", self.what)
    }
}
impl Error for EssentialLack {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug)]
pub enum UsageKind {
    Nothing,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
}
impl Display for UsageKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            UsageKind::Nothing => format!(
r#"Usage:
    {} <command> [--help|-h]

Command:
    init    # Register current directory.
    config  # Set config's parameters.
    ignore  # Set ignored files.
    sweep   # Sweep files in current directory.
    burn    # Burn sweeped files.
    start   # Start "{}".
    end     # End "{}".
    destroy # Destroy "{}"."#,
                ME,
                ME,
                ME,
                ME,
            ),
            UsageKind::Init    => "init!"   .to_string(),
            UsageKind::Config  => "config!" .to_string(),
            UsageKind::Ignore  => "ignore!" .to_string(),
            UsageKind::Sweep   => "sweep!"  .to_string(),
            UsageKind::Burn    => "burn!"   .to_string(),
            UsageKind::Start   => "start!"  .to_string(),
            UsageKind::End     => "end!"    .to_string(),
            UsageKind::Destroy => "destroy!".to_string(),
        })
    }
}

#[derive(Debug)]
pub struct Usage {
    pub kind: UsageKind,
}
impl Display for Usage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.kind)
    }
}
impl Error for Usage {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "show usage" }
}

#[derive(Debug)]
pub struct CannotHappenError;
impl Display for CannotHappenError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Cannot happen")
    }
}
impl Error for CannotHappenError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "cannot happen" }
}

#[derive(Debug)]
pub enum ConfigErrorKind {
    NotFoundBurnAfter,
    BurnAfter,
    NumOfBurnAfter,
    UnitOfBurnAfter,
}
impl Display for ConfigErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            ConfigErrorKind::NotFoundBurnAfter => r#"Please set [burn]after param"#,
            ConfigErrorKind::BurnAfter         => r#"Invalid "[burn]after" param"#,
            ConfigErrorKind::NumOfBurnAfter    => r#"Please set positive number as "[burn]after""#,
            ConfigErrorKind::UnitOfBurnAfter   => r#"Please set "day" or "week" as "[burn]after""#,
        })
    }
}

#[derive(Debug)]
pub struct ConfigError {
    pub kind: ConfigErrorKind,
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.kind)
    }
}
impl Error for ConfigError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "invalid params" }
}
<commit_msg>[Refactoring] Use "Formatter" directly and alias "FmtResult"<commit_after>extern crate regex;
extern crate toml;

use constant::*;
use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    CannotHappen(CannotHappenError),
    Config(ConfigError),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
}
impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            CliError::CannotHappen(ref e) => e.fmt(f),
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::CannotHappen(ref e) => Some(e),
            CliError::Config(ref e)       => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::CannotHappen(ref e) => e.description(),
            CliError::Config(ref e)       => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
        }
    }
}
impl From<CannotHappenError> for CliError {
    fn from(e: CannotHappenError) -> CliError {
        CliError::CannotHappen(e)
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}

#[derive(Debug)]
pub struct RunningPlaceError {
    pub dir: String,
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
impl Display for EssentialKind {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match *self {
            EssentialKind::WorkingDir => format!("{} directory", WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("{} directory", STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("{} file"     , CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("{} file"     , IGNORE_FILE_NAME),
        })
    }
}

#[derive(Debug)]
pub struct EssentialLack {
    pub what: EssentialKind,
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{} does not exist. Please use \"init\" command", self.what)
    }
}
impl Error for EssentialLack {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug)]
pub enum UsageKind {
    Nothing,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
}
impl Display for UsageKind {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match *self {
            UsageKind::Nothing => format!(
r#"Usage:
    {} <command> [--help|-h]

Command:
    init    # Register current directory.
    config  # Set config's parameters.
    ignore  # Set ignored files.
    sweep   # Sweep files in current directory.
    burn    # Burn sweeped files.
    start   # Start "{}".
    end     # End "{}".
    destroy # Destroy "{}"."#,
                ME,
                ME,
                ME,
                ME,
            ),
            UsageKind::Init    => "init!"   .to_string(),
            UsageKind::Config  => "config!" .to_string(),
            UsageKind::Ignore  => "ignore!" .to_string(),
            UsageKind::Sweep   => "sweep!"  .to_string(),
            UsageKind::Burn    => "burn!"   .to_string(),
            UsageKind::Start   => "start!"  .to_string(),
            UsageKind::End     => "end!"    .to_string(),
            UsageKind::Destroy => "destroy!".to_string(),
        })
    }
}

#[derive(Debug)]
pub struct Usage {
    pub kind: UsageKind,
}
impl Display for Usage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.kind)
    }
}
impl Error for Usage {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "show usage" }
}

#[derive(Debug)]
pub struct CannotHappenError;
impl Display for CannotHappenError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot happen")
    }
}
impl Error for CannotHappenError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "cannot happen" }
}

#[derive(Debug)]
pub enum ConfigErrorKind {
    NotFoundBurnAfter,
    BurnAfter,
    NumOfBurnAfter,
    UnitOfBurnAfter,
}
impl Display for ConfigErrorKind {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match *self {
            ConfigErrorKind::NotFoundBurnAfter => r#"Please set [burn]after param"#,
            ConfigErrorKind::BurnAfter         => r#"Invalid "[burn]after" param"#,
            ConfigErrorKind::NumOfBurnAfter    => r#"Please set positive number as "[burn]after""#,
            ConfigErrorKind::UnitOfBurnAfter   => r#"Please set "day" or "week" as "[burn]after""#,
        })
    }
}

#[derive(Debug)]
pub struct ConfigError {
    pub kind: ConfigErrorKind,
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.kind)
    }
}
impl Error for ConfigError {
    fn cause(&self) -> Option<&Error> { None }

    fn description(&self) -> &str { "invalid params" }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde_json;

use self::ErrorType::*;
use std::error::Error as StdError;
use std::fmt;
use std::io;

#[derive(Debug)]
pub enum ErrorType {
    Unauthorized,
    SerdeJson(serde_json::error::Error),
    Hyper(hyper::error::Error),
    Io(io::Error),
    StatusCode(hyper::status::StatusCode),
    Api(ApiError),
}

#[derive(Debug)]
pub struct Error {
    pub err: ErrorType,
    pub url: Option<hyper::Url>,
}

impl Error {
    pub fn new<T: Into<Error>>(err: T, url: Option<hyper::Url>) -> Error {
        Error {
            err: err.into().err,
            url: url,
        }
    }
}

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

impl From<ErrorType> for Error {
    fn from(err: ErrorType) -> Error {
        Error {
            err: err,
            url: None,
        }
    }
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Error {
        Error {
            err: ErrorType::SerdeJson(err),
            url: None,
        }
    }
}

impl From<hyper::error::Error> for Error {
    fn from(err: hyper::error::Error) -> Error {
        Error {
            err: ErrorType::Hyper(err),
            url: None,
        }
    }
}

impl From<hyper::error::ParseError> for Error {
    fn from(err: hyper::error::ParseError) -> Error {
        Error {
            err: ErrorType::Hyper(hyper::Error::Uri(err)),
            url: None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error {
            err: ErrorType::Io(err),
            url: None,
        }
    }
}

impl From<hyper::status::StatusCode> for Error {
    fn from(code: hyper::status::StatusCode) -> Error {
        Error {
            err: {
                if code == hyper::status::StatusCode::Unauthorized {
                    ErrorType::Unauthorized
                } else {
                    ErrorType::StatusCode(code)
                }
            },
            url: None,
        }
    }
}

impl From<ApiError> for Error {
    fn from(err: ApiError) -> Error {
        Error {
            err: ErrorType::Api(err),
            url: None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            SerdeJson(ref err) => fmt::Display::fmt(err, f),
            Hyper(ref err) => fmt::Display::fmt(err, f),
            Io(ref err) => fmt::Display::fmt(err, f),
            StatusCode(ref status) => fmt::Display::fmt(status, f),
            Api(ref err) => fmt::Display::fmt(err, f),
            Unauthorized => {
                write!(f, "access not authorized: token expired, username/password incorrect or no login provided")
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self.err {
            SerdeJson(ref err) => err.description(),
            Hyper(ref err) => err.description(),
            Io(ref err) => err.description(),
            StatusCode(ref status) => {
                match status.canonical_reason() {
                    Some(reason) => reason,
                    None => {
                        use hyper::status::StatusClass::*;
                        match status.class() {
                            Informational => "status code error: informational",
                            Success => "status code error: success",
                            Redirection => "status code error: redirection",
                            ClientError => "status code error: client error",
                            ServerError => "status code error: server error",
                            NoClass => "status code error: strange status",
                        }
                    }
                }
            }
            Api(ref err) => err.description(),
            Unauthorized => "access not authorized: token expired, username/password incorrect or no login provided",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self.err {
            SerdeJson(ref err) => Some(err),
            Hyper(ref err) => Some(err),
            Io(ref err) => Some(err),
            StatusCode(_) => None,
            Api(ref err) => Some(err),
            Unauthorized => None,
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub enum ApiError {
    NotOk(i32),
    MissingField(&'static str),
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ApiError::NotOk(code) => write!(f, "non-ok result from api call: {}", code),
            ApiError::MissingField(field) => write!(f, "missing field from api call: {}", field),
        }
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        match *self {
            ApiError::NotOk(_) => "non-ok result from api call",
            ApiError::MissingField(_) => "missing field from api call",
        }
    }

    fn cause(&self) -> Option<&StdError> { None }
}
<commit_msg>Update Error::new to possibly grab url from the error into() produced if it has one.<commit_after>extern crate hyper;
extern crate serde_json;

use self::ErrorType::*;
use std::error::Error as StdError;
use std::fmt;
use std::io;

#[derive(Debug)]
pub enum ErrorType {
    Unauthorized,
    SerdeJson(serde_json::error::Error),
    Hyper(hyper::error::Error),
    Io(io::Error),
    StatusCode(hyper::status::StatusCode),
    Api(ApiError),
}

#[derive(Debug)]
pub struct Error {
    pub err: ErrorType,
    pub url: Option<hyper::Url>,
}

impl Error {
    pub fn new<T: Into<Error>>(err: T, url: Option<hyper::Url>) -> Error {
        let err = err.into();
        Error {
            err: err.err,
            url: url.or(err.url),
        }
    }
}

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

impl From<ErrorType> for Error {
    fn from(err: ErrorType) -> Error {
        Error {
            err: err,
            url: None,
        }
    }
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Error {
        Error {
            err: ErrorType::SerdeJson(err),
            url: None,
        }
    }
}

impl From<hyper::error::Error> for Error {
    fn from(err: hyper::error::Error) -> Error {
        Error {
            err: ErrorType::Hyper(err),
            url: None,
        }
    }
}

impl From<hyper::error::ParseError> for Error {
    fn from(err: hyper::error::ParseError) -> Error {
        Error {
            err: ErrorType::Hyper(hyper::Error::Uri(err)),
            url: None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error {
            err: ErrorType::Io(err),
            url: None,
        }
    }
}

impl From<hyper::status::StatusCode> for Error {
    fn from(code: hyper::status::StatusCode) -> Error {
        Error {
            err: {
                if code == hyper::status::StatusCode::Unauthorized {
                    ErrorType::Unauthorized
                } else {
                    ErrorType::StatusCode(code)
                }
            },
            url: None,
        }
    }
}

impl From<ApiError> for Error {
    fn from(err: ApiError) -> Error {
        Error {
            err: ErrorType::Api(err),
            url: None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            SerdeJson(ref err) => fmt::Display::fmt(err, f),
            Hyper(ref err) => fmt::Display::fmt(err, f),
            Io(ref err) => fmt::Display::fmt(err, f),
            StatusCode(ref status) => fmt::Display::fmt(status, f),
            Api(ref err) => fmt::Display::fmt(err, f),
            Unauthorized => {
                write!(f, "access not authorized: token expired, username/password incorrect or no login provided")
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match self.err {
            SerdeJson(ref err) => err.description(),
            Hyper(ref err) => err.description(),
            Io(ref err) => err.description(),
            StatusCode(ref status) => {
                match status.canonical_reason() {
                    Some(reason) => reason,
                    None => {
                        use hyper::status::StatusClass::*;
                        match status.class() {
                            Informational => "status code error: informational",
                            Success => "status code error: success",
                            Redirection => "status code error: redirection",
                            ClientError => "status code error: client error",
                            ServerError => "status code error: server error",
                            NoClass => "status code error: strange status",
                        }
                    }
                }
            }
            Api(ref err) => err.description(),
            Unauthorized => "access not authorized: token expired, username/password incorrect or no login provided",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self.err {
            SerdeJson(ref err) => Some(err),
            Hyper(ref err) => Some(err),
            Io(ref err) => Some(err),
            StatusCode(_) => None,
            Api(ref err) => Some(err),
            Unauthorized => None,
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub enum ApiError {
    NotOk(i32),
    MissingField(&'static str),
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ApiError::NotOk(code) => write!(f, "non-ok result from api call: {}", code),
            ApiError::MissingField(field) => write!(f, "missing field from api call: {}", field),
        }
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        match *self {
            ApiError::NotOk(_) => "non-ok result from api call",
            ApiError::MissingField(_) => "missing field from api call",
        }
    }

    fn cause(&self) -> Option<&StdError> { None }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};
use std::io;

use prettyprint::PrettyPrintError;

pub enum Error {
    Io(io::Error),
    Print(PrettyPrintError),
    Toml(toml::ser::Error),
}

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

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

impl From<PrettyPrintError> for Error {
    fn from(error: PrettyPrintError) -> Self {
        Error::Print(error)
    }
}

impl From<toml::ser::Error> for Error {
    fn from(error: toml::ser::Error) -> Self {
        Error::Toml(error)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(error) => Display::fmt(error, formatter),
            Error::Print(error) => Display::fmt(error, formatter),
            Error::Toml(error) => Display::fmt(error, formatter),
        }
    }
}
<commit_msg>Abbreviate implementation of Display for Error<commit_after>use std::fmt::{self, Display};
use std::io;

use prettyprint::PrettyPrintError;

pub enum Error {
    Io(io::Error),
    Print(PrettyPrintError),
    Toml(toml::ser::Error),
}

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

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

impl From<PrettyPrintError> for Error {
    fn from(error: PrettyPrintError) -> Self {
        Error::Print(error)
    }
}

impl From<toml::ser::Error> for Error {
    fn from(error: toml::ser::Error) -> Self {
        Error::Toml(error)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            Io(e) => e.fmt(formatter),
            Print(e) => e.fmt(formatter),
            Toml(e) => e.fmt(formatter),
        }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::error::Error;
use std::fs;
use std::io::{self, Write, Stderr};
use std::path::Path;
use std::process::exit;
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{rm} */ r#"NAME
    rm - remove files and directories

SYNOPSIS
    rm [-h | --help] [-d | --dir] [-i] [-r | -R | --recursive] [-v | --verbose] TARGETS...

DESCRIPTION
    Removes each specified file, but does not remove directories by default.

OPTIONS
    -h
    --help
        Display this help information and exit.

    -d
    --dir
        Remove empty directories in addition to files.

    -i
    --interactive
        Prompt before removing all files and directories.

    -r
    -R
    --recursive
        Remove directories and their contents recursively.

    -v
    --verbose
        Print the file changes that have been successfully performed.

AUTHOR
    Written by Michael Murphy.
"#; /* @MANEND */

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["i", "interactive"])
        .add_flag(&["r", "R", "recursive"])
        .add_flag(&["d", "dir"])
        .add_flag(&["v", "verbose"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }
    if parser.found("recursive") {
        *parser.flag("directory") = true;
    }
    if let Err(err) = parser.found_invalid() {
        stderr.write(err.as_bytes()).try(&mut stderr);
        stderr.flush().try(&mut stderr);
    }
    if parser.args.is_empty() {
        stdout.write(b"missing operand\nTry 'rm --help' for more information.\n").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let mut exit_status = 0i32;
    for arg in &parser.args {
        if fs::metadata(&arg).is_err() {
            stderr.write(b"aborting due to invalid path: '").try(&mut stderr);
            stderr.write(arg.as_bytes()).try(&mut stderr);
            stderr.write(b"'\n").try(&mut stderr);
            stderr.flush().try(&mut stderr);
            exit(1);
        }
    }
    for arg in &parser.args {
        if Path::new(arg).is_dir() {
            if parser.found("interactive") {
                stdout.write(b"remove directory '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'? ").try(&mut stderr);
                stdout.flush().try(&mut stderr);
                let input = &mut String::new();
                let stdin = io::stdin();
                stdin.read_line(input).try(&mut stderr);
                if input.chars().next().unwrap() != 'y' { continue }
            }
            if parser.found("directory") {
                // Attempt to remove a directory and all of it's contents if recursive mode is enabled.
                // If recursion is not enabled, attempt to remove the directory if it is empty.
                if parser.found("recursive") {
                    // TODO: Use walkdir when it is implemented in Redox instead of fs::remove_dir_all().
                    if let Err(message) = fs::remove_dir_all(Path::new(arg)) {
                        stderr.write(b"cannot remove directory '").try(&mut stderr);
                        stderr.write(arg.as_bytes()).try(&mut stderr);
                        stderr.write(b"': ").try(&mut stderr);
                        print_error(message, &mut stderr);
                        exit_status = 1;
                    } else if parser.found("verbose") {
                        stdout.write(b"removed directory '").try(&mut stderr);
                        stdout.write(arg.as_bytes()).try(&mut stderr);
                        stdout.write(b"'\n").try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                    }
                } else {
                    if let Err(message) = fs::remove_dir(Path::new(arg)) {
                        stderr.write(b"cannot remove directory '").try(&mut stderr);
                        stderr.write(arg.as_bytes()).try(&mut stderr);
                        stderr.write(b"': ").try(&mut stderr);
                        print_error(message, &mut stderr);
                        exit_status = 1;
                    } else if parser.found("verbose") {
                        stdout.write(b"removed directory '").try(&mut stderr);
                        stdout.write(arg.as_bytes()).try(&mut stderr);
                        stdout.write(b"'\n").try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                    }
                }
            } else {
                stderr.write(b"cannot remove '").try(&mut stderr);
                stderr.write(arg.as_bytes()).try(&mut stderr);
                stderr.write(b"': is a directory\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit_status = 1;
            }
        }
        else {
            // Attempt to remove the file given as an input argument.
            if parser.found("interactive") {
                stdout.write(b"remove file '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'? ").try(&mut stderr);
                stdout.flush().try(&mut stderr);
                let input = &mut String::new();
                let stdin = io::stdin();
                stdin.read_line(input).try(&mut stderr);
                if input.chars().next().unwrap() != 'y' { continue }
            }
            if let Err(message) = fs::remove_file(Path::new(arg)) {
                stderr.write(b"cannot remove '").try(&mut stderr);
                stderr.write(arg.as_bytes()).try(&mut stderr);
                stderr.write(b"': ").try(&mut stderr);
                print_error(message, &mut stderr);
                exit_status = 1;
            } else if parser.found("verbose") {
                stdout.write(b"removed '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'\n").try(&mut stderr);
                stdout.flush().try(&mut stderr);
            }
        }
    }
    exit(exit_status);
}

/// Print the message given by an io::Error to stderr.
fn print_error(message: io::Error, stderr: &mut Stderr) {
    stderr.write(message.description().as_bytes()).try(stderr);
    stderr.write(b"\n").try(stderr);
    stderr.flush().try(stderr);
}
<commit_msg>rm: -f argument<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::error::Error;
use std::fs;
use std::io::{self, Write, Stderr};
use std::path::Path;
use std::process::exit;
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{rm} */ r#"NAME
    rm - remove files and directories

SYNOPSIS
    rm [-h | --help] [-d | --dir] [-i] [-r | -R | --recursive] [-v | --verbose] TARGETS...

DESCRIPTION
    Removes each specified file, but does not remove directories by default.

OPTIONS
    -h
    --help
        Display this help information and exit.

    -d
    --dir
        Remove empty directories in addition to files.

    -i
    --interactive
        Prompt before removing all files and directories.

    -r
    -R
    --recursive
        Remove directories and their contents recursively.

    -f
    --force
        Ignore nonexistent files.

    -v
    --verbose
        Print the file changes that have been successfully performed.

AUTHOR
    Written by Michael Murphy.
"#; /* @MANEND */

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["i", "interactive"])
        .add_flag(&["r", "R", "recursive"])
        .add_flag(&["f", "force"])
        .add_flag(&["d", "dir"])
        .add_flag(&["v", "verbose"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    let force = parser.found("force");

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }
    if parser.found("recursive") {
        *parser.flag("directory") = true;
    }
    if let Err(err) = parser.found_invalid() {
        stderr.write(err.as_bytes()).try(&mut stderr);
        stderr.flush().try(&mut stderr);
    }
    if parser.args.is_empty() {
        stdout.write(b"missing operand\nTry 'rm --help' for more information.\n").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let mut exit_status = 0i32;
    if !force {
        for arg in &parser.args {
            if fs::metadata(&arg).is_err() {
                stderr.write(b"aborting due to invalid path: '").try(&mut stderr);
                stderr.write(arg.as_bytes()).try(&mut stderr);
                stderr.write(b"'\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            }
        }
    }
    for arg in &parser.args {
        if Path::new(arg).is_dir() {
            if parser.found("interactive") {
                stdout.write(b"remove directory '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'? ").try(&mut stderr);
                stdout.flush().try(&mut stderr);
                let input = &mut String::new();
                let stdin = io::stdin();
                stdin.read_line(input).try(&mut stderr);
                if input.chars().next().unwrap() != 'y' { continue }
            }
            if parser.found("directory") {
                // Attempt to remove a directory and all of it's contents if recursive mode is enabled.
                // If recursion is not enabled, attempt to remove the directory if it is empty.
                if parser.found("recursive") {
                    // TODO: Use walkdir when it is implemented in Redox instead of fs::remove_dir_all().
                    if let Err(message) = fs::remove_dir_all(Path::new(arg)) {
                        stderr.write(b"cannot remove directory '").try(&mut stderr);
                        stderr.write(arg.as_bytes()).try(&mut stderr);
                        stderr.write(b"': ").try(&mut stderr);
                        print_error(message, &mut stderr);
                        exit_status = 1;
                    } else if parser.found("verbose") {
                        stdout.write(b"removed directory '").try(&mut stderr);
                        stdout.write(arg.as_bytes()).try(&mut stderr);
                        stdout.write(b"'\n").try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                    }
                } else {
                    if let Err(message) = fs::remove_dir(Path::new(arg)) {
                        stderr.write(b"cannot remove directory '").try(&mut stderr);
                        stderr.write(arg.as_bytes()).try(&mut stderr);
                        stderr.write(b"': ").try(&mut stderr);
                        print_error(message, &mut stderr);
                        exit_status = 1;
                    } else if parser.found("verbose") {
                        stdout.write(b"removed directory '").try(&mut stderr);
                        stdout.write(arg.as_bytes()).try(&mut stderr);
                        stdout.write(b"'\n").try(&mut stderr);
                        stdout.flush().try(&mut stderr);
                    }
                }
            } else {
                stderr.write(b"cannot remove '").try(&mut stderr);
                stderr.write(arg.as_bytes()).try(&mut stderr);
                stderr.write(b"': is a directory\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit_status = 1;
            }
        }
        else {
            // Attempt to remove the file given as an input argument.
            if parser.found("interactive") {
                stdout.write(b"remove file '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'? ").try(&mut stderr);
                stdout.flush().try(&mut stderr);
                let input = &mut String::new();
                let stdin = io::stdin();
                stdin.read_line(input).try(&mut stderr);
                if input.chars().next().unwrap() != 'y' { continue }
            }
            if let Err(message) = fs::remove_file(Path::new(arg)) {
                if message.kind() != io::ErrorKind::NotFound {
                    stderr.write(b"cannot remove '").try(&mut stderr);
                    stderr.write(arg.as_bytes()).try(&mut stderr);
                    stderr.write(b"': ").try(&mut stderr);
                    print_error(message, &mut stderr);
                    exit_status = 1;
                    continue;
                }
            }
            if parser.found("verbose") {
                stdout.write(b"removed '").try(&mut stderr);
                stdout.write(arg.as_bytes()).try(&mut stderr);
                stdout.write(b"'\n").try(&mut stderr);
                stdout.flush().try(&mut stderr);
            }
        }
    }
    exit(exit_status);
}

/// Print the message given by an io::Error to stderr.
fn print_error(message: io::Error, stderr: &mut Stderr) {
    stderr.write(message.description().as_bytes()).try(stderr);
    stderr.write(b"\n").try(stderr);
    stderr.flush().try(stderr);
}
<|endoftext|>