azure_core_sdk 0.1.1

Core library for the unofficial Azure SDK for Rust
Documentation
use hyper;
use native_tls;
use hyper::StatusCode;
use chrono;
use std::io::Error as IOError;
use std::num;
use xml::BuilderError as XMLError;
use url::ParseError as URLParseError;
use enumerations::ParsingError;
use range::ParseError;
use serde_json;
use futures::Future;
use futures::Stream;
use std::str;
use std::string;
use futures::future::*;
use std;

#[derive(Debug, Clone, PartialEq)]
pub struct UnexpectedHTTPResult {
    expected: StatusCode,
    received: StatusCode,
    body: String,
}

impl UnexpectedHTTPResult {
    pub fn new(expected: StatusCode, received: StatusCode, body: &str) -> UnexpectedHTTPResult {
        UnexpectedHTTPResult {
            expected: expected,
            received: received,
            body: body.to_owned(),
        }
    }
}

impl std::fmt::Display for UnexpectedHTTPResult {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "Unexpected HTTP result (expected: {}, received: {})",
            self.expected, self.received
        )
    }
}

impl std::error::Error for UnexpectedHTTPResult {
    fn description(&self) -> &str {
        "Unexpected HTTP result"
    }

    fn cause(&self) -> Option<&std::error::Error> {
        None
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum AzureError {
        JSONError(err: serde_json::Error) {
            from()
            display("json error: {}", err)
            cause(err)
        }
        HyperError(err: hyper::error::Error){
            from()
            display("Hyper error: {}", err)
            cause(err)
        }
        IOError(err: IOError){
            from()
            display("IO error: {}", err)
            cause(err)
        }
        XMLError(err: XMLError){
            from()
            display("XML error: {}", err)
            cause(err)
        }
        UnexpectedHTTPResult(err: UnexpectedHTTPResult){
            from()
            display("UnexpectedHTTPResult error")
        }
        HeaderNotFound(msg: String) {
            display("Header not found: {}", msg)
        }
        ResponseParsingError(err: TraversingError){
            from()
            display("Traversing error: {}", err)
            cause(err)
        }
        ParseIntError(err: num::ParseIntError){
            from()
            display("Parse int error: {}", err)
            cause(err)
        }
        ParseError(err: ParseError){
            from()
            display("Parse error")
        }
        GenericError
        GenericErrorWithText(err: String) {
            display("Generic error: {}", err)
        }
        ParsingError(err: ParsingError){
            from()
            display("Parsing error")
        }
        InputParametersError(msg: String) {
            display("Input parameters error: {}", msg)
        }
        URLParseError(err: URLParseError){
            from()
            display("URL parse error: {}", err)
            cause(err)
        }
        URIParseError(err: hyper::error::UriError) {
            from()
            display("URI parse error: {}", err)
            cause(err)
        }
        ChronoParserError(err: chrono::ParseError) {
            from()
            display("Chrono parser error: {}", err)
            cause(err)
        }
        UTF8Error(err: str::Utf8Error) {
            from()
            display("UTF8 conversion error: {}", err)
            cause(err)
        }
        FromUtf8Error(err: string::FromUtf8Error) {
            from()
            display("FromUTF8 error: {}", err)
            cause(err)
        }
        NativeTLSError(err: native_tls::Error) {
            from()
            display("Native TLS error: {}", err)
            cause(err)
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum TraversingError {
        PathNotFound(msg: String) {
            display("Path not found: {}", msg)
        }
        MultipleNode(msg: String) {
            display("Multiple node: {}", msg)
        }
        EnumerationNotMatched(msg: String) {
            display("Enumeration not matched: {}", msg)
        }
        DateTimeParseError(err: chrono::format::ParseError){
            from()
            display("DateTime parse error: {}", err)
            cause(err)
        }
        TextNotFound
        ParseIntError(err: num::ParseIntError){
            from()
            display("Parse int error: {}", err)
            cause(err)
        }
        GenericParseError(msg: String) {
            display("Generic parse error: {}", msg)
        }
        ParsingError(err: ParsingError){
            from()
            display("Parsing error: {:?}", err)
        }
   }
}

impl From<()> for AzureError {
    fn from(_: ()) -> AzureError {
        AzureError::GenericError
    }
}

#[inline]
pub fn extract_status_headers_and_body(
    resp: hyper::client::FutureResponse,
) -> impl Future<Item = (hyper::StatusCode, hyper::Headers, Vec<u8>), Error = AzureError> {
    resp.from_err().and_then(|res| {
        let status = res.status();
        let headers = res.headers().clone();
        res.body()
            .concat2()
            .from_err()
            .and_then(move |whole_body| ok((status, headers, Vec::from(&whole_body as &[u8]))))
    })
}

#[inline]
pub fn check_status_extract_headers_and_body(
    resp: hyper::client::FutureResponse,
    expected_status_code: hyper::StatusCode,
) -> impl Future<Item = (hyper::Headers, Vec<u8>), Error = AzureError> {
    extract_status_headers_and_body(resp).and_then(move |(status, headers, body)| {
        if status == expected_status_code {
            ok((headers, body))
        } else {
            match str::from_utf8(&body) {
                Ok(s_body) => err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult {
                    expected: expected_status_code,
                    received: status,
                    body: s_body.to_owned(),
                })),
                Err(error) => err(AzureError::UTF8Error(error)),
            }
        }
    })
}

#[inline]
pub fn extract_status_and_body(
    resp: hyper::client::FutureResponse,
) -> impl Future<Item = (hyper::StatusCode, String), Error = AzureError> {
    resp.from_err().and_then(|res| {
        let status = res.status();
        res.body().concat2().from_err().and_then(move |whole_body| {
            match str::from_utf8(&whole_body) {
                Ok(s_body) => ok((status, s_body.to_owned())),
                Err(error) => err(AzureError::UTF8Error(error)),
            }
        })
    })
}

#[inline]
pub fn check_status_extract_body(
    resp: hyper::client::FutureResponse,
    expected_status_code: hyper::StatusCode,
) -> impl Future<Item = String, Error = AzureError> {
    extract_status_and_body(resp).and_then(move |(status, body)| {
        if status == expected_status_code {
            ok(body)
        } else {
            err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult {
                expected: expected_status_code,
                received: status,
                body: body,
            }))
        }
    })
}