<commit_before>//! AWS API requests.
//!
//! Wraps the `hyper` library to send PUT, POST, DELETE and GET requests.

//extern crate lazy_static;

use std::env;
use std::error::Error;
use std::fmt;
use std::io;
use std::io::Error as IoError;
use std::mem;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;

use crate::tls::HttpsConnector;
use bytes::Bytes;
use futures::{Async, Future, Poll, Stream};
use http::{HeaderMap, StatusCode};
use hyper::body::Body;
use hyper::client::connect::Connect;
use hyper::client::Builder as HyperBuilder;
use hyper::client::HttpConnector;
use hyper::client::ResponseFuture as HyperResponseFuture;
use hyper::Error as HyperError;
use hyper::{Client as HyperClient, Response as HyperResponse};
use std::convert::TryInto;
use tokio_timer::Timeout;

use crate::signature::SignedRequest;
use crate::stream::ByteStream;

// Pulls in the statically generated rustc version.
include!(concat!(env!("OUT_DIR"), "/user_agent_vars.rs"));

// Use a lazy static to cache the default User-Agent header
// because it never changes once it's been computed.
lazy_static! {
    static ref DEFAULT_USER_AGENT: String = format!(
        "rusoto/{} rust/{} {}",
        env!("CARGO_PKG_VERSION"),
        RUST_VERSION,
        env::consts::OS
    );
}

/// Stores the response from a HTTP request.
pub struct HttpResponse {
    /// Status code of HTTP Request
    pub status: StatusCode,
    /// Contents of Response
    pub body: ByteStream,
    /// Response headers
    pub headers: HeaderMap<String>,
}

/// Stores the buffered response from a HTTP request.
#[derive(PartialEq)]
pub struct BufferedHttpResponse {
    /// Status code of HTTP Request
    pub status: StatusCode,
    /// Contents of Response
    pub body: Bytes,
    /// Response headers
    pub headers: HeaderMap<String>,
}

impl BufferedHttpResponse {
    ///! Best effort to turn response body into more readable &str.
    pub fn body_as_str(&self) -> &str {
        match std::str::from_utf8(&self.body) {
            Ok(msg) => msg,
            _ => "unknown error",
        }
    }
}

/// Best effort based Debug implementation to make generic error's body more readable.
impl fmt::Debug for BufferedHttpResponse {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match std::str::from_utf8(&self.body) {
            Ok(msg) => write!(
                f,
                "BufferedHttpResponse {{status: {:?}, body: {:?}, headers: {:?} }}",
                self.status, msg, self.headers
            ),
            _ => write!(
                f,
                "BufferedHttpResponse {{ status: {:?}, body: {:?}, headers: {:?} }}",
                self.status, self.body, self.headers
            ),
        }
    }
}

/// Future returned from `HttpResponse::buffer`.
pub struct BufferedHttpResponseFuture {
    status: StatusCode,
    headers: HeaderMap<String>,
    future: ::futures::stream::Concat2<ByteStream>,
}

impl Future for BufferedHttpResponseFuture {
    type Item = BufferedHttpResponse;
    type Error = HttpDispatchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future
            .poll()
            .map_err(std::convert::Into::into)
            .map(|r#async| {
                r#async.map(|body| BufferedHttpResponse {
                    status: self.status,
                    headers: mem::replace(&mut self.headers, Default::default()),
                    body,
                })
            })
    }
}

impl HttpResponse {
    /// Buffer the full response body in memory, resulting in a `BufferedHttpResponse`.
    pub fn buffer(self) -> BufferedHttpResponseFuture {
        BufferedHttpResponseFuture {
            status: self.status,
            headers: self.headers,
            future: self.body.concat2(),
        }
    }

    fn from_hyper(hyper_response: HyperResponse<Body>) -> HttpResponse {
        let status = hyper_response.status();
        let headers = hyper_response
            .headers()
            .iter()
            .map(|(h, v)| {
                let value_string = v.to_str().unwrap().to_owned();
                (h.clone(), value_string)
            })
            .collect();
        let body = hyper_response
            .into_body()
            .map(hyper::Chunk::into_bytes)
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        HttpResponse {
            status,
            headers,
            body: ByteStream::new(body),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
/// An error produced when sending the request, such as a timeout error.
pub struct HttpDispatchError {
    message: String,
}

impl HttpDispatchError {
    /// Construct a new HttpDispatchError for testing purposes
    pub fn new(message: String) -> HttpDispatchError {
        HttpDispatchError { message }
    }
}

impl Error for HttpDispatchError {
    fn description(&self) -> &str {
        &self.message
    }
}

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

impl From<HyperError> for HttpDispatchError {
    fn from(err: HyperError) -> HttpDispatchError {
        HttpDispatchError {
            message: err.to_string(),
        }
    }
}

impl From<IoError> for HttpDispatchError {
    fn from(err: IoError) -> HttpDispatchError {
        HttpDispatchError {
            message: err.to_string(),
        }
    }
}

/// Trait for implementing HTTP Request/Response
pub trait DispatchSignedRequest {
    /// The future response value.
    type Future: Future<Item = HttpResponse, Error = HttpDispatchError> + 'static;
    /// Dispatch Request, and then return a Response
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future;
}

impl<D: DispatchSignedRequest> DispatchSignedRequest for Rc<D> {
    type Future = D::Future;
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        D::dispatch(&*self, request, timeout)
    }
}

impl<D: DispatchSignedRequest> DispatchSignedRequest for Arc<D> {
    type Future = D::Future;
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        D::dispatch(&*self, request, timeout)
    }
}

/// A future that will resolve to an `HttpResponse`.
pub struct HttpClientFuture(ClientFutureInner);

enum ClientFutureInner {
    Hyper(HyperResponseFuture),
    HyperWithTimeout(Timeout<HyperResponseFuture>),
    Error(String),
}

impl Future for HttpClientFuture {
    type Item = HttpResponse;
    type Error = HttpDispatchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            ClientFutureInner::Error(ref message) => Err(HttpDispatchError {
                message: message.clone(),
            }),
            ClientFutureInner::Hyper(ref mut hyper_future) => {
                Ok(hyper_future.poll()?.map(HttpResponse::from_hyper))
            }
            ClientFutureInner::HyperWithTimeout(ref mut deadline_future) => {
                match deadline_future.poll() {
                    Err(deadline_err) => {
                        if deadline_err.is_elapsed() {
                            Err(HttpDispatchError {
                                message: "Request timed out".into(),
                            })
                        } else if deadline_err.is_inner() {
                            Err(deadline_err.into_inner().unwrap().into())
                        } else {
                            Err(HttpDispatchError {
                                message: format!("deadline error: {}", deadline_err),
                            })
                        }
                    }
                    Ok(Async::NotReady) => Ok(Async::NotReady),
                    Ok(Async::Ready(hyper_res)) => {
                        Ok(Async::Ready(HttpResponse::from_hyper(hyper_res)))
                    }
                }
            }
        }
    }
}

/// Http client for use with AWS services.
pub struct HttpClient<C = HttpsConnector<HttpConnector>> {
    inner: HyperClient<C, Body>,
}

impl HttpClient {
    /// Create a tls-enabled http client.
    pub fn new() -> Result<Self, TlsError> {
        #[cfg(feature = "native-tls")]
        let connector = match HttpsConnector::new(4) {
            Ok(connector) => connector,
            Err(tls_error) => {
                return Err(TlsError {
                    message: format!("Couldn't create NativeTlsClient: {}", tls_error),
                })
            }
        };

        #[cfg(feature = "rustls")]
        let connector = HttpsConnector::new(4);

        Ok(Self::from_connector(connector))
    }

    /// Create a tls-enabled http client.
    pub fn new_with_config(config: HttpConfig) -> Result<Self, TlsError> {
        #[cfg(feature = "native-tls")]
        let connector = match HttpsConnector::new(4) {
            Ok(connector) => connector,
            Err(tls_error) => {
                return Err(TlsError {
                    message: format!("Couldn't create NativeTlsClient: {}", tls_error),
                })
            }
        };

        #[cfg(feature = "rustls")]
        let connector = HttpsConnector::new(4);

        Ok(Self::from_connector_with_config(connector, config))
    }
}

impl<C> HttpClient<C>
where
    C: Connect,
    C::Future: 'static,
{
    /// Allows for a custom connector to be used with the HttpClient
    pub fn from_connector(connector: C) -> Self {
        let inner = HyperClient::builder().build(connector);
        HttpClient { inner }
    }

    /// Allows for a custom connector to be used with the HttpClient
    /// with extra configuration options
    pub fn from_connector_with_config(connector: C, config: HttpConfig) -> Self {
        let mut builder = HyperClient::builder();
        config
            .read_buf_size
            .map(|sz| builder.http1_read_buf_exact_size(sz));
        let inner = builder.build(connector);

        HttpClient { inner }
    }

    /// Alows for a custom builder and connector to be used with the HttpClient
    pub fn from_builder(builder: HyperBuilder, connector: C) -> Self {
        let inner = builder.build(connector);
        HttpClient { inner }
    }
}

/// Configuration options for the HTTP Client
pub struct HttpConfig {
    read_buf_size: Option<usize>,
}

impl HttpConfig {
    /// Create a new HttpConfig
    pub fn new() -> HttpConfig {
        HttpConfig {
            read_buf_size: None,
        }
    }
    /// Sets the size of the read buffer for inbound data
    /// A larger buffer size might result in better performance
    /// by requiring fewer copies out of the socket buffer.
    pub fn read_buf_size(&mut self, sz: usize) {
        self.read_buf_size = Some(sz);
    }
}

impl Default for HttpConfig {
    /// Create a new HttpConfig. Same as HttpConfig::new().
    fn default() -> HttpConfig {
        HttpConfig::new()
    }
}

impl<C> DispatchSignedRequest for HttpClient<C>
where
    C: Connect + 'static,
    C::Future: 'static,
{
    type Future = HttpClientFuture;

    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        // fixme: add default user agent when none is provided
        // if !request.headers().contains_key("user-agent") {
        //     request.add_header("user-agent", DEFAULT_USER_AGENT.as_str());
        // }
        let req = match request.try_into() {
            Ok(req) => req,
            Err(err) => {
                return HttpClientFuture(ClientFutureInner::Error(format!(
                    "Failed creating requests {}",
                    err
                )))
            }
        };

        let inner = match timeout {
            None => ClientFutureInner::Hyper(self.inner.request(req)),
            Some(duration) => {
                let future = Timeout::new(self.inner.request(req), duration);
                ClientFutureInner::HyperWithTimeout(future)
            }
        };

        HttpClientFuture(inner)
    }
}

#[derive(Debug, PartialEq)]
/// An error produced when the user has an invalid TLS client
pub struct TlsError {
    message: String,
}

impl Error for TlsError {
    fn description(&self) -> &str {
        &self.message
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use crate::signature::SignedRequest;
    use crate::Region;

    #[test]
    fn http_client_is_send_and_sync() {
        fn is_send_and_sync<T: Send + Sync>() {}

        is_send_and_sync::<HttpClient>();
    }

    #[test]
    fn http_client_future_is_send() {
        fn is_send<T: Send>() {}

        is_send::<HttpClientFuture>();
    }

    #[test]
    fn custom_region_http() {
        let a_region = Region::Custom {
            endpoint: "http://localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("http", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_https() {
        let a_region = Region::Custom {
            endpoint: "https://localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_with_port() {
        let a_region = Region::Custom {
            endpoint: "https://localhost:8000".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost:8000", request.hostname());
    }

    #[test]
    fn custom_region_no_scheme() {
        let a_region = Region::Custom {
            endpoint: "localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn from_io_error_preserves_error_message() {
        let io_error = ::std::io::Error::new(::std::io::ErrorKind::Other, "my error message");
        let error = HttpDispatchError::from(io_error);
        assert_eq!(error.to_string(), "my error message")
    }
}
<commit_msg>keep previous error message<commit_after>//! AWS API requests.
//!
//! Wraps the `hyper` library to send PUT, POST, DELETE and GET requests.

//extern crate lazy_static;

use std::env;
use std::error::Error;
use std::fmt;
use std::io;
use std::io::Error as IoError;
use std::mem;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;

use crate::tls::HttpsConnector;
use bytes::Bytes;
use futures::{Async, Future, Poll, Stream};
use http::{HeaderMap, StatusCode};
use hyper::body::Body;
use hyper::client::connect::Connect;
use hyper::client::Builder as HyperBuilder;
use hyper::client::HttpConnector;
use hyper::client::ResponseFuture as HyperResponseFuture;
use hyper::Error as HyperError;
use hyper::{Client as HyperClient, Response as HyperResponse};
use std::convert::TryInto;
use tokio_timer::Timeout;

use crate::signature::SignedRequest;
use crate::stream::ByteStream;

// Pulls in the statically generated rustc version.
include!(concat!(env!("OUT_DIR"), "/user_agent_vars.rs"));

// Use a lazy static to cache the default User-Agent header
// because it never changes once it's been computed.
lazy_static! {
    static ref DEFAULT_USER_AGENT: String = format!(
        "rusoto/{} rust/{} {}",
        env!("CARGO_PKG_VERSION"),
        RUST_VERSION,
        env::consts::OS
    );
}

/// Stores the response from a HTTP request.
pub struct HttpResponse {
    /// Status code of HTTP Request
    pub status: StatusCode,
    /// Contents of Response
    pub body: ByteStream,
    /// Response headers
    pub headers: HeaderMap<String>,
}

/// Stores the buffered response from a HTTP request.
#[derive(PartialEq)]
pub struct BufferedHttpResponse {
    /// Status code of HTTP Request
    pub status: StatusCode,
    /// Contents of Response
    pub body: Bytes,
    /// Response headers
    pub headers: HeaderMap<String>,
}

impl BufferedHttpResponse {
    ///! Best effort to turn response body into more readable &str.
    pub fn body_as_str(&self) -> &str {
        match std::str::from_utf8(&self.body) {
            Ok(msg) => msg,
            _ => "unknown error",
        }
    }
}

/// Best effort based Debug implementation to make generic error's body more readable.
impl fmt::Debug for BufferedHttpResponse {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match std::str::from_utf8(&self.body) {
            Ok(msg) => write!(
                f,
                "BufferedHttpResponse {{status: {:?}, body: {:?}, headers: {:?} }}",
                self.status, msg, self.headers
            ),
            _ => write!(
                f,
                "BufferedHttpResponse {{ status: {:?}, body: {:?}, headers: {:?} }}",
                self.status, self.body, self.headers
            ),
        }
    }
}

/// Future returned from `HttpResponse::buffer`.
pub struct BufferedHttpResponseFuture {
    status: StatusCode,
    headers: HeaderMap<String>,
    future: ::futures::stream::Concat2<ByteStream>,
}

impl Future for BufferedHttpResponseFuture {
    type Item = BufferedHttpResponse;
    type Error = HttpDispatchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future
            .poll()
            .map_err(std::convert::Into::into)
            .map(|r#async| {
                r#async.map(|body| BufferedHttpResponse {
                    status: self.status,
                    headers: mem::replace(&mut self.headers, Default::default()),
                    body,
                })
            })
    }
}

impl HttpResponse {
    /// Buffer the full response body in memory, resulting in a `BufferedHttpResponse`.
    pub fn buffer(self) -> BufferedHttpResponseFuture {
        BufferedHttpResponseFuture {
            status: self.status,
            headers: self.headers,
            future: self.body.concat2(),
        }
    }

    fn from_hyper(hyper_response: HyperResponse<Body>) -> HttpResponse {
        let status = hyper_response.status();
        let headers = hyper_response
            .headers()
            .iter()
            .map(|(h, v)| {
                let value_string = v.to_str().unwrap().to_owned();
                (h.clone(), value_string)
            })
            .collect();
        let body = hyper_response
            .into_body()
            .map(hyper::Chunk::into_bytes)
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        HttpResponse {
            status,
            headers,
            body: ByteStream::new(body),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
/// An error produced when sending the request, such as a timeout error.
pub struct HttpDispatchError {
    message: String,
}

impl HttpDispatchError {
    /// Construct a new HttpDispatchError for testing purposes
    pub fn new(message: String) -> HttpDispatchError {
        HttpDispatchError { message }
    }
}

impl Error for HttpDispatchError {
    fn description(&self) -> &str {
        &self.message
    }
}

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

impl From<HyperError> for HttpDispatchError {
    fn from(err: HyperError) -> HttpDispatchError {
        HttpDispatchError {
            message: err.to_string(),
        }
    }
}

impl From<IoError> for HttpDispatchError {
    fn from(err: IoError) -> HttpDispatchError {
        HttpDispatchError {
            message: err.to_string(),
        }
    }
}

/// Trait for implementing HTTP Request/Response
pub trait DispatchSignedRequest {
    /// The future response value.
    type Future: Future<Item = HttpResponse, Error = HttpDispatchError> + 'static;
    /// Dispatch Request, and then return a Response
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future;
}

impl<D: DispatchSignedRequest> DispatchSignedRequest for Rc<D> {
    type Future = D::Future;
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        D::dispatch(&*self, request, timeout)
    }
}

impl<D: DispatchSignedRequest> DispatchSignedRequest for Arc<D> {
    type Future = D::Future;
    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        D::dispatch(&*self, request, timeout)
    }
}

/// A future that will resolve to an `HttpResponse`.
pub struct HttpClientFuture(ClientFutureInner);

enum ClientFutureInner {
    Hyper(HyperResponseFuture),
    HyperWithTimeout(Timeout<HyperResponseFuture>),
    Error(String),
}

impl Future for HttpClientFuture {
    type Item = HttpResponse;
    type Error = HttpDispatchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            ClientFutureInner::Error(ref message) => Err(HttpDispatchError {
                message: message.clone(),
            }),
            ClientFutureInner::Hyper(ref mut hyper_future) => {
                Ok(hyper_future.poll()?.map(HttpResponse::from_hyper))
            }
            ClientFutureInner::HyperWithTimeout(ref mut deadline_future) => {
                match deadline_future.poll() {
                    Err(deadline_err) => {
                        if deadline_err.is_elapsed() {
                            Err(HttpDispatchError {
                                message: "Request timed out".into(),
                            })
                        } else if deadline_err.is_inner() {
                            Err(deadline_err.into_inner().unwrap().into())
                        } else {
                            Err(HttpDispatchError {
                                message: format!("deadline error: {}", deadline_err),
                            })
                        }
                    }
                    Ok(Async::NotReady) => Ok(Async::NotReady),
                    Ok(Async::Ready(hyper_res)) => {
                        Ok(Async::Ready(HttpResponse::from_hyper(hyper_res)))
                    }
                }
            }
        }
    }
}

/// Http client for use with AWS services.
pub struct HttpClient<C = HttpsConnector<HttpConnector>> {
    inner: HyperClient<C, Body>,
}

impl HttpClient {
    /// Create a tls-enabled http client.
    pub fn new() -> Result<Self, TlsError> {
        #[cfg(feature = "native-tls")]
        let connector = match HttpsConnector::new(4) {
            Ok(connector) => connector,
            Err(tls_error) => {
                return Err(TlsError {
                    message: format!("Couldn't create NativeTlsClient: {}", tls_error),
                })
            }
        };

        #[cfg(feature = "rustls")]
        let connector = HttpsConnector::new(4);

        Ok(Self::from_connector(connector))
    }

    /// Create a tls-enabled http client.
    pub fn new_with_config(config: HttpConfig) -> Result<Self, TlsError> {
        #[cfg(feature = "native-tls")]
        let connector = match HttpsConnector::new(4) {
            Ok(connector) => connector,
            Err(tls_error) => {
                return Err(TlsError {
                    message: format!("Couldn't create NativeTlsClient: {}", tls_error),
                })
            }
        };

        #[cfg(feature = "rustls")]
        let connector = HttpsConnector::new(4);

        Ok(Self::from_connector_with_config(connector, config))
    }
}

impl<C> HttpClient<C>
where
    C: Connect,
    C::Future: 'static,
{
    /// Allows for a custom connector to be used with the HttpClient
    pub fn from_connector(connector: C) -> Self {
        let inner = HyperClient::builder().build(connector);
        HttpClient { inner }
    }

    /// Allows for a custom connector to be used with the HttpClient
    /// with extra configuration options
    pub fn from_connector_with_config(connector: C, config: HttpConfig) -> Self {
        let mut builder = HyperClient::builder();
        config
            .read_buf_size
            .map(|sz| builder.http1_read_buf_exact_size(sz));
        let inner = builder.build(connector);

        HttpClient { inner }
    }

    /// Alows for a custom builder and connector to be used with the HttpClient
    pub fn from_builder(builder: HyperBuilder, connector: C) -> Self {
        let inner = builder.build(connector);
        HttpClient { inner }
    }
}

/// Configuration options for the HTTP Client
pub struct HttpConfig {
    read_buf_size: Option<usize>,
}

impl HttpConfig {
    /// Create a new HttpConfig
    pub fn new() -> HttpConfig {
        HttpConfig {
            read_buf_size: None,
        }
    }
    /// Sets the size of the read buffer for inbound data
    /// A larger buffer size might result in better performance
    /// by requiring fewer copies out of the socket buffer.
    pub fn read_buf_size(&mut self, sz: usize) {
        self.read_buf_size = Some(sz);
    }
}

impl Default for HttpConfig {
    /// Create a new HttpConfig. Same as HttpConfig::new().
    fn default() -> HttpConfig {
        HttpConfig::new()
    }
}

impl<C> DispatchSignedRequest for HttpClient<C>
where
    C: Connect + 'static,
    C::Future: 'static,
{
    type Future = HttpClientFuture;

    fn dispatch(&self, request: SignedRequest, timeout: Option<Duration>) -> Self::Future {
        // fixme: add default user agent when none is provided
        // if !request.headers().contains_key("user-agent") {
        //     request.add_header("user-agent", DEFAULT_USER_AGENT.as_str());
        // }
        let req = match request.try_into() {
            Ok(req) => req,
            Err(err) => {
                return HttpClientFuture(ClientFutureInner::Error(format!(
                    "error building request: {}",
                    err
                )))
            }
        };

        let inner = match timeout {
            None => ClientFutureInner::Hyper(self.inner.request(req)),
            Some(duration) => {
                let future = Timeout::new(self.inner.request(req), duration);
                ClientFutureInner::HyperWithTimeout(future)
            }
        };

        HttpClientFuture(inner)
    }
}

#[derive(Debug, PartialEq)]
/// An error produced when the user has an invalid TLS client
pub struct TlsError {
    message: String,
}

impl Error for TlsError {
    fn description(&self) -> &str {
        &self.message
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use crate::signature::SignedRequest;
    use crate::Region;

    #[test]
    fn http_client_is_send_and_sync() {
        fn is_send_and_sync<T: Send + Sync>() {}

        is_send_and_sync::<HttpClient>();
    }

    #[test]
    fn http_client_future_is_send() {
        fn is_send<T: Send>() {}

        is_send::<HttpClientFuture>();
    }

    #[test]
    fn custom_region_http() {
        let a_region = Region::Custom {
            endpoint: "http://localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("http", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_https() {
        let a_region = Region::Custom {
            endpoint: "https://localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_with_port() {
        let a_region = Region::Custom {
            endpoint: "https://localhost:8000".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost:8000", request.hostname());
    }

    #[test]
    fn custom_region_no_scheme() {
        let a_region = Region::Custom {
            endpoint: "localhost".to_owned(),
            name: "eu-west-3".to_owned(),
        };
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("https", request.scheme());
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn from_io_error_preserves_error_message() {
        let io_error = ::std::io::Error::new(::std::io::ErrorKind::Other, "my error message");
        let error = HttpDispatchError::from(io_error);
        assert_eq!(error.to_string(), "my error message")
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use fnv::FnvHashMap;
use std::cmp;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use std::thread;

use command_buffer::pool::CommandPool;
use command_buffer::pool::CommandPoolAlloc;
use command_buffer::pool::CommandPoolBuilderAlloc;
use command_buffer::pool::UnsafeCommandPool;
use command_buffer::pool::UnsafeCommandPoolAlloc;
use instance::QueueFamily;

use OomError;
use VulkanObject;
use device::Device;
use device::DeviceOwned;

/// Standard implementation of a command pool.
///
/// Will use one Vulkan pool per thread in order to avoid locking. Will try to reuse command
/// buffers. Command buffers can't be moved between threads during the building process, but
/// finished command buffers can.
pub struct StandardCommandPool {
    // The device.
    device: Arc<Device>,

    // Identifier of the queue family.
    queue_family: u32,

    // For each thread, we store thread-specific info.
    per_thread: Mutex<FnvHashMap<thread::ThreadId, Weak<Mutex<StandardCommandPoolPerThread>>>>,
}

unsafe impl Send for StandardCommandPool {
}
unsafe impl Sync for StandardCommandPool {
}

struct StandardCommandPoolPerThread {
    // The Vulkan pool of this thread.
    pool: UnsafeCommandPool,
    // List of existing primary command buffers that are available for reuse.
    available_primary_command_buffers: Vec<UnsafeCommandPoolAlloc>,
    // List of existing secondary command buffers that are available for reuse.
    available_secondary_command_buffers: Vec<UnsafeCommandPoolAlloc>,
}

impl StandardCommandPool {
    /// Builds a new pool.
    ///
    /// # Panic
    ///
    /// - Panics if the device and the queue family don't belong to the same physical device.
    ///
    pub fn new(device: Arc<Device>, queue_family: QueueFamily) -> StandardCommandPool {
        assert_eq!(device.physical_device().internal_object(),
                   queue_family.physical_device().internal_object());

        StandardCommandPool {
            device: device,
            queue_family: queue_family.id(),
            per_thread: Mutex::new(Default::default()),
        }
    }
}

unsafe impl CommandPool for Arc<StandardCommandPool> {
    type Iter = Box<Iterator<Item = StandardCommandPoolBuilder>>; // TODO: meh for Box
    type Builder = StandardCommandPoolBuilder;
    type Alloc = StandardCommandPoolAlloc;

    fn alloc(&self, secondary: bool, count: u32) -> Result<Self::Iter, OomError> {
        // Find the correct `StandardCommandPoolPerThread` structure.
        let mut hashmap = self.per_thread.lock().unwrap();
        //hashmap.retain(|_, w| w.upgrade().is_some());     // TODO: unstable     // TODO: meh for iterating everything every time

        // TODO: this hashmap lookup can probably be optimized
        let curr_thread_id = thread::current().id();
        let per_thread = hashmap.get(&curr_thread_id).and_then(|p| p.upgrade());
        let per_thread = match per_thread {
            Some(pt) => pt,
            None => {
                let new_pool =
                    UnsafeCommandPool::new(self.device.clone(), self.queue_family(), false, true)?;
                let pt = Arc::new(Mutex::new(StandardCommandPoolPerThread {
                                                 pool: new_pool,
                                                 available_primary_command_buffers: Vec::new(),
                                                 available_secondary_command_buffers: Vec::new(),
                                             }));

                hashmap.insert(curr_thread_id, Arc::downgrade(&pt));
                pt
            },
        };

        let mut pt_lock = per_thread.lock().unwrap();

        // Build an iterator to pick from already-existing command buffers.
        let (num_from_existing, from_existing) = {
            // Which list of already-existing command buffers we are going to pick CBs from.
            let mut existing = if secondary {
                &mut pt_lock.available_secondary_command_buffers
            } else {
                &mut pt_lock.available_primary_command_buffers
            };
            let num_from_existing = cmp::min(count as usize, existing.len());
            let from_existing = existing
                .drain(0 .. num_from_existing)
                .collect::<Vec<_>>()
                .into_iter();
            (num_from_existing, from_existing)
        };

        // Build an iterator to construct the missing command buffers from the Vulkan pool.
        let num_new = count as usize - num_from_existing;
        debug_assert!(num_new <= count as usize); // Check overflows.
        let newly_allocated = pt_lock.pool.alloc_command_buffers(secondary, num_new)?;

        // Returning them as a chain.
        let device = self.device.clone();
        let per_thread = per_thread.clone();
        let final_iter = from_existing
            .chain(newly_allocated)
            .map(move |cmd| {
                StandardCommandPoolBuilder {
                    cmd: Some(cmd),
                    pool: per_thread.clone(),
                    secondary: secondary,
                    device: device.clone(),
                    dummy_avoid_send_sync: PhantomData,
                }
            })
            .collect::<Vec<_>>();

        Ok(Box::new(final_iter.into_iter()))
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.device
            .physical_device()
            .queue_family_by_id(self.queue_family)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPool {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

/// Command buffer allocated from a `StandardCommandPool` and that is currently being built.
pub struct StandardCommandPoolBuilder {
    // The actual command buffer. Must always be `Some`. Value extracted in `into_alloc` or in the
    // destructor.
    cmd: Option<UnsafeCommandPoolAlloc>,
    // We hold a reference to the command pool for our destructor.
    pool: Arc<Mutex<StandardCommandPoolPerThread>>,
    // True if secondary command buffer.
    secondary: bool,
    // The device we belong to. Necessary because of the `DeviceOwned` trait implementation.
    device: Arc<Device>,
    // Unimplemented `Send` and `Sync` from the builder.
    dummy_avoid_send_sync: PhantomData<*const u8>,
}

unsafe impl CommandPoolBuilderAlloc for StandardCommandPoolBuilder {
    type Alloc = StandardCommandPoolAlloc;

    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.cmd.as_ref().unwrap()
    }

    #[inline]
    fn into_alloc(mut self) -> Self::Alloc {
        StandardCommandPoolAlloc {
            cmd: Some(self.cmd.take().unwrap()),
            pool: self.pool.clone(),
            secondary: self.secondary,
            device: self.device.clone(),
        }
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        let queue_family_id = self.pool.lock().unwrap().pool.queue_family().id();

        self.device
            .physical_device()
            .queue_family_by_id(queue_family_id)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolBuilder {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

impl Drop for StandardCommandPoolBuilder {
    fn drop(&mut self) {
        if let Some(cmd) = self.cmd.take() {
            // This happens if the builder is dropped without `into_alloc` being called.
            let mut pool = self.pool.lock().unwrap();

            if self.secondary {
                pool.available_secondary_command_buffers.push(cmd);
            } else {
                pool.available_primary_command_buffers.push(cmd);
            }
        }
    }
}

/// Command buffer allocated from a `StandardCommandPool`.
pub struct StandardCommandPoolAlloc {
    // The actual command buffer. Must always be `Some`. Value extracted in the destructor.
    cmd: Option<UnsafeCommandPoolAlloc>,
    // We hold a reference to the command pool for our destructor.
    pool: Arc<Mutex<StandardCommandPoolPerThread>>,
    // True if secondary command buffer.
    secondary: bool,
    // The device we belong to. Necessary because of the `DeviceOwned` trait implementation.
    device: Arc<Device>,
}

unsafe impl Send for StandardCommandPoolAlloc {
}
unsafe impl Sync for StandardCommandPoolAlloc {
}

unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc {
    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.cmd.as_ref().unwrap()
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        let queue_family_id = self.pool.lock().unwrap().pool.queue_family().id();

        self.device
            .physical_device()
            .queue_family_by_id(queue_family_id)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolAlloc {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        // Note that we could grab the device from `self.pool`. Unfortunately this requires a mutex
        // lock, so it isn't compatible with the API of `DeviceOwned`.
        &self.device
    }
}

impl Drop for StandardCommandPoolAlloc {
    fn drop(&mut self) {
        let mut pool = self.pool.lock().unwrap();

        if self.secondary {
            pool.available_secondary_command_buffers
                .push(self.cmd.take().unwrap());
        } else {
            pool.available_primary_command_buffers
                .push(self.cmd.take().unwrap());
        }
    }
}
<commit_msg>Better code reuse in the standard command pool<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use fnv::FnvHashMap;
use std::cmp;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use std::thread;

use command_buffer::pool::CommandPool;
use command_buffer::pool::CommandPoolAlloc;
use command_buffer::pool::CommandPoolBuilderAlloc;
use command_buffer::pool::UnsafeCommandPool;
use command_buffer::pool::UnsafeCommandPoolAlloc;
use instance::QueueFamily;

use OomError;
use VulkanObject;
use device::Device;
use device::DeviceOwned;

/// Standard implementation of a command pool.
///
/// Will use one Vulkan pool per thread in order to avoid locking. Will try to reuse command
/// buffers. Command buffers can't be moved between threads during the building process, but
/// finished command buffers can.
pub struct StandardCommandPool {
    // The device.
    device: Arc<Device>,

    // Identifier of the queue family.
    queue_family: u32,

    // For each thread, we store thread-specific info.
    per_thread: Mutex<FnvHashMap<thread::ThreadId, Weak<Mutex<StandardCommandPoolPerThread>>>>,
}

unsafe impl Send for StandardCommandPool {
}
unsafe impl Sync for StandardCommandPool {
}

struct StandardCommandPoolPerThread {
    // The Vulkan pool of this thread.
    pool: UnsafeCommandPool,
    // List of existing primary command buffers that are available for reuse.
    available_primary_command_buffers: Vec<UnsafeCommandPoolAlloc>,
    // List of existing secondary command buffers that are available for reuse.
    available_secondary_command_buffers: Vec<UnsafeCommandPoolAlloc>,
}

impl StandardCommandPool {
    /// Builds a new pool.
    ///
    /// # Panic
    ///
    /// - Panics if the device and the queue family don't belong to the same physical device.
    ///
    pub fn new(device: Arc<Device>, queue_family: QueueFamily) -> StandardCommandPool {
        assert_eq!(device.physical_device().internal_object(),
                   queue_family.physical_device().internal_object());

        StandardCommandPool {
            device: device,
            queue_family: queue_family.id(),
            per_thread: Mutex::new(Default::default()),
        }
    }
}

unsafe impl CommandPool for Arc<StandardCommandPool> {
    type Iter = Box<Iterator<Item = StandardCommandPoolBuilder>>; // TODO: meh for Box
    type Builder = StandardCommandPoolBuilder;
    type Alloc = StandardCommandPoolAlloc;

    fn alloc(&self, secondary: bool, count: u32) -> Result<Self::Iter, OomError> {
        // Find the correct `StandardCommandPoolPerThread` structure.
        let mut hashmap = self.per_thread.lock().unwrap();
        //hashmap.retain(|_, w| w.upgrade().is_some());     // TODO: unstable     // TODO: meh for iterating everything every time

        // TODO: this hashmap lookup can probably be optimized
        let curr_thread_id = thread::current().id();
        let per_thread = hashmap.get(&curr_thread_id).and_then(|p| p.upgrade());
        let per_thread = match per_thread {
            Some(pt) => pt,
            None => {
                let new_pool =
                    UnsafeCommandPool::new(self.device.clone(), self.queue_family(), false, true)?;
                let pt = Arc::new(Mutex::new(StandardCommandPoolPerThread {
                                                 pool: new_pool,
                                                 available_primary_command_buffers: Vec::new(),
                                                 available_secondary_command_buffers: Vec::new(),
                                             }));

                hashmap.insert(curr_thread_id, Arc::downgrade(&pt));
                pt
            },
        };

        let mut pt_lock = per_thread.lock().unwrap();

        // Build an iterator to pick from already-existing command buffers.
        let (num_from_existing, from_existing) = {
            // Which list of already-existing command buffers we are going to pick CBs from.
            let mut existing = if secondary {
                &mut pt_lock.available_secondary_command_buffers
            } else {
                &mut pt_lock.available_primary_command_buffers
            };
            let num_from_existing = cmp::min(count as usize, existing.len());
            let from_existing = existing
                .drain(0 .. num_from_existing)
                .collect::<Vec<_>>()
                .into_iter();
            (num_from_existing, from_existing)
        };

        // Build an iterator to construct the missing command buffers from the Vulkan pool.
        let num_new = count as usize - num_from_existing;
        debug_assert!(num_new <= count as usize); // Check overflows.
        let newly_allocated = pt_lock.pool.alloc_command_buffers(secondary, num_new)?;

        // Returning them as a chain.
        let device = self.device.clone();
        let per_thread = per_thread.clone();
        let final_iter = from_existing
            .chain(newly_allocated)
            .map(move |cmd| {
                StandardCommandPoolBuilder {
                    inner: StandardCommandPoolAlloc {
                        cmd: Some(cmd),
                        pool: per_thread.clone(),
                        secondary: secondary,
                        device: device.clone(),
                    },
                    dummy_avoid_send_sync: PhantomData,
                }
            })
            .collect::<Vec<_>>();

        Ok(Box::new(final_iter.into_iter()))
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.device
            .physical_device()
            .queue_family_by_id(self.queue_family)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPool {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

/// Command buffer allocated from a `StandardCommandPool` and that is currently being built.
pub struct StandardCommandPoolBuilder {
    // The only difference between a `StandardCommandPoolBuilder` and a `StandardCommandPoolAlloc`
    // is that the former must not implement `Send` and `Sync`. Therefore we just share the structs.
    inner: StandardCommandPoolAlloc,
    // Unimplemented `Send` and `Sync` from the builder.
    dummy_avoid_send_sync: PhantomData<*const u8>,
}

unsafe impl CommandPoolBuilderAlloc for StandardCommandPoolBuilder {
    type Alloc = StandardCommandPoolAlloc;

    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.inner.inner()
    }

    #[inline]
    fn into_alloc(self) -> Self::Alloc {
        self.inner
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.inner.queue_family()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolBuilder {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

/// Command buffer allocated from a `StandardCommandPool`.
pub struct StandardCommandPoolAlloc {
    // The actual command buffer. Must always be `Some`. Value extracted in the destructor.
    cmd: Option<UnsafeCommandPoolAlloc>,
    // We hold a reference to the command pool for our destructor.
    pool: Arc<Mutex<StandardCommandPoolPerThread>>,
    // True if secondary command buffer.
    secondary: bool,
    // The device we belong to. Necessary because of the `DeviceOwned` trait implementation.
    device: Arc<Device>,
}

unsafe impl Send for StandardCommandPoolAlloc {
}
unsafe impl Sync for StandardCommandPoolAlloc {
}

unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc {
    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.cmd.as_ref().unwrap()
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        let queue_family_id = self.pool.lock().unwrap().pool.queue_family().id();

        self.device
            .physical_device()
            .queue_family_by_id(queue_family_id)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolAlloc {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        // Note that we could grab the device from `self.pool`. Unfortunately this requires a mutex
        // lock, so it isn't compatible with the API of `DeviceOwned`.
        &self.device
    }
}

impl Drop for StandardCommandPoolAlloc {
    fn drop(&mut self) {
        let mut pool = self.pool.lock().unwrap();

        if self.secondary {
            pool.available_secondary_command_buffers
                .push(self.cmd.take().unwrap());
        } else {
            pool.available_primary_command_buffers
                .push(self.cmd.take().unwrap());
        }
    }
}
<|endoftext|>


<commit_before>use fake_tty::FakeIO;
use tty::IO;

struct Ansi<'a> {
    io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = format!("\x1b[{}", message);
        self.io.write(out.as_slice());
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    fn set_position(&mut self, line: isize, column: isize) {
        let message = format!("{};{}H", line+1, column+1);
        self.escape(message.as_slice());
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

<commit_msg>Can invert and reset<commit_after>use fake_tty::FakeIO;
use tty::IO;

struct Ansi<'a> {
    io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = format!("\x1b[{}", message);
        self.io.write(out.as_slice());
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    fn set_position(&mut self, line: isize, column: isize) {
        let message = format!("{};{}H", line+1, column+1);
        self.escape(message.as_slice());
    }

    fn invert(&mut self) {
        self.escape("7m");
    }

    fn reset(&mut self) {
        self.escape("0m");
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

#[test]
fn it_inverts() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.invert();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7m");
}

#[test]
fn it_resets() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.reset();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[0m");
}

<|endoftext|>


<commit_before>use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(non_camel_case_types)]
pub type uintptr_t = u64;

pub struct Registers {
  rsp: *mut uintptr_t
}

impl Copy for Registers {}

#[inline(always)]
pub unsafe fn swap(regs: &mut Registers) {
  asm!(include_str!("swap.s")
        :
        : "{rdi}" (&mut regs.rsp)
        : "rax", "rbx", "rcx", "rdx", "rsi", "rdi",
          "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
          "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
          "cc"
        : "volatile");
}

#[inline]
pub unsafe fn initialize_call_frame<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
  let sp_limit = stack.limit();
  let mut sp = stack.top() as *mut uintptr_t;
  let f_ptr = push(&mut sp, f);

  asm!(include_str!("init.s")
        : "={rdi}"(sp)
        : "{rdi}" (sp),
          "{rsi}" (rust_trampoline::<F>),
          "{rdx}" (f_ptr),
          "{rcx}" (sp_limit)
        :
        : "volatile");

  Registers { rsp: sp }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut uintptr_t, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut uintptr_t;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<commit_msg>add AVX registers to clobbers, do some formatting<commit_after>use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(non_camel_case_types)]
pub type uintptr_t = u64;

pub struct Registers {
  rsp: *mut uintptr_t
}

impl Copy for Registers {}

#[inline(always)]
pub unsafe fn swap(regs: &mut Registers) {
  asm!(include_str!("swap.s")
        :
        : "{rdi}" (&mut regs.rsp)
        : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
          "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
          "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
          "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
          "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
          "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
          "cc"
        : "volatile");
}

#[inline]
pub unsafe fn initialize_call_frame<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
  let sp_limit = stack.limit();
  let mut sp = stack.top() as *mut uintptr_t;
  let f_ptr = push(&mut sp, f);

  asm!(include_str!("init.s")
        : "={rdi}"(sp)
        : "{rdi}" (sp),
          "{rsi}" (rust_trampoline::<F>),
          "{rdx}" (f_ptr),
          "{rcx}" (sp_limit)
        :
        : "volatile");

  Registers { rsp: sp }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut uintptr_t, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut uintptr_t;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rand::thread_rng;
use std::cmp::min;
/// Keychain trait and its main supporting types. The Identifier is a
/// semi-opaque structure (just bytes) to track keys within the Keychain.
/// BlindingFactor is a useful wrapper around a private key to help with
/// commitment generation.
use std::{error, fmt};

use blake2::blake2b::blake2b;
use serde::{de, ser};

use util;
use util::secp::constants::SECRET_KEY_SIZE;
use util::secp::key::{PublicKey, SecretKey};
use util::secp::pedersen::Commitment;
use util::secp::{self, Message, Secp256k1, Signature};

// Size of an identifier in bytes
pub const IDENTIFIER_SIZE: usize = 10;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Error {
	Secp(secp::Error),
	KeyDerivation(String),
	Transaction(String),
	RangeProof(String),
}

impl From<secp::Error> for Error {
	fn from(e: secp::Error) -> Error {
		Error::Secp(e)
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			_ => "some kind of keychain error",
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			_ => write!(f, "some kind of keychain error"),
		}
	}
}

#[derive(Clone, PartialEq, Eq, Ord, Hash, PartialOrd)]
pub struct Identifier([u8; IDENTIFIER_SIZE]);

impl ser::Serialize for Identifier {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: ser::Serializer,
	{
		serializer.serialize_str(&self.to_hex())
	}
}

impl<'de> de::Deserialize<'de> for Identifier {
	fn deserialize<D>(deserializer: D) -> Result<Identifier, D::Error>
	where
		D: de::Deserializer<'de>,
	{
		deserializer.deserialize_str(IdentifierVisitor)
	}
}

struct IdentifierVisitor;

impl<'de> de::Visitor<'de> for IdentifierVisitor {
	type Value = Identifier;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str("an identifier")
	}

	fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
	where
		E: de::Error,
	{
		let identifier = Identifier::from_hex(s).unwrap();
		Ok(identifier)
	}
}

impl Identifier {
	pub fn zero() -> Identifier {
		Identifier::from_bytes(&[0; IDENTIFIER_SIZE])
	}

	pub fn from_bytes(bytes: &[u8]) -> Identifier {
		let mut identifier = [0; IDENTIFIER_SIZE];
		for i in 0..min(IDENTIFIER_SIZE, bytes.len()) {
			identifier[i] = bytes[i];
		}
		Identifier(identifier)
	}

	pub fn to_bytes(&self) -> [u8; IDENTIFIER_SIZE] {
		self.0.clone()
	}

	pub fn from_pubkey(secp: &Secp256k1, pubkey: &PublicKey) -> Identifier {
		let bytes = pubkey.serialize_vec(secp, true);
		let identifier = blake2b(IDENTIFIER_SIZE, &[], &bytes[..]);
		Identifier::from_bytes(&identifier.as_bytes())
	}

	/// Return the identifier of the secret key
	/// which is the blake2b (10 byte) digest of the PublicKey
	/// corresponding to the secret key provided.
	pub fn from_secret_key(secp: &Secp256k1, key: &SecretKey) -> Result<Identifier, Error> {
		let key_id = PublicKey::from_secret_key(secp, key)?;
		Ok(Identifier::from_pubkey(secp, &key_id))
	}

	pub fn from_hex(hex: &str) -> Result<Identifier, Error> {
		let bytes = util::from_hex(hex.to_string()).unwrap();
		Ok(Identifier::from_bytes(&bytes))
	}

	pub fn to_hex(&self) -> String {
		util::to_hex(self.0.to_vec())
	}
}

impl AsRef<[u8]> for Identifier {
	fn as_ref(&self) -> &[u8] {
		&self.0.as_ref()
	}
}

impl ::std::fmt::Debug for Identifier {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
		try!(write!(f, "{}(", stringify!(Identifier)));
		try!(write!(f, "{}", self.to_hex()));
		write!(f, ")")
	}
}

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

#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct BlindingFactor([u8; SECRET_KEY_SIZE]);

impl AsRef<[u8]> for BlindingFactor {
	fn as_ref(&self) -> &[u8] {
		&self.0
	}
}

impl BlindingFactor {
	pub fn from_secret_key(skey: secp::key::SecretKey) -> BlindingFactor {
		BlindingFactor::from_slice(&skey.as_ref())
	}

	pub fn from_slice(data: &[u8]) -> BlindingFactor {
		let mut blind = [0; SECRET_KEY_SIZE];
		for i in 0..min(SECRET_KEY_SIZE, data.len()) {
			blind[i] = data[i];
		}
		BlindingFactor(blind)
	}

	pub fn zero() -> BlindingFactor {
		BlindingFactor::from_secret_key(secp::key::ZERO_KEY)
	}

	pub fn to_hex(&self) -> String {
		util::to_hex(self.0.to_vec())
	}

	pub fn from_hex(hex: &str) -> Result<BlindingFactor, Error> {
		let bytes = util::from_hex(hex.to_string()).unwrap();
		Ok(BlindingFactor::from_slice(&bytes))
	}

	pub fn secret_key(&self, secp: &Secp256k1) -> Result<secp::key::SecretKey, Error> {
		if *self == BlindingFactor::zero() {
			// TODO - need this currently for tx tests
			// the "zero" secret key is not actually a valid secret_key
			// and secp lib checks this
			Ok(secp::key::ZERO_KEY)
		} else {
			secp::key::SecretKey::from_slice(secp, &self.0).map_err(|e| Error::Secp(e))
		}
	}

	/// Split a blinding_factor (aka secret_key) into a pair of
	/// blinding_factors. We use one of these (k1) to sign the tx_kernel (k1G)
	/// and the other gets aggregated in the block_header as the "offset".
	/// This prevents an actor from being able to sum a set of inputs, outputs
	/// and kernels from a block to identify and reconstruct a particular tx
	/// from a block. You would need both k1, k2 to do this.
	pub fn split(&self, secp: &Secp256k1) -> Result<SplitBlindingFactor, Error> {
		let skey_1 = secp::key::SecretKey::new(secp, &mut thread_rng());

		// use blind_sum to subtract skey_1 from our key (to give k = k1 + k2)
		let skey = self.secret_key(secp)?;
		let skey_2 = secp.blind_sum(vec![skey], vec![skey_1])?;

		let blind_1 = BlindingFactor::from_secret_key(skey_1);
		let blind_2 = BlindingFactor::from_secret_key(skey_2);

		Ok(SplitBlindingFactor { blind_1, blind_2 })
	}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SplitBlindingFactor {
	pub blind_1: BlindingFactor,
	pub blind_2: BlindingFactor,
}

/// Accumulator to compute the sum of blinding factors. Keeps track of each
/// factor as well as the "sign" with which they should be combined.
#[derive(Clone, Debug, PartialEq)]
pub struct BlindSum {
	pub positive_key_ids: Vec<Identifier>,
	pub negative_key_ids: Vec<Identifier>,
	pub positive_blinding_factors: Vec<BlindingFactor>,
	pub negative_blinding_factors: Vec<BlindingFactor>,
}

impl BlindSum {
	/// Creates a new blinding factor sum.
	pub fn new() -> BlindSum {
		BlindSum {
			positive_key_ids: vec![],
			negative_key_ids: vec![],
			positive_blinding_factors: vec![],
			negative_blinding_factors: vec![],
		}
	}

	pub fn add_key_id(mut self, key_id: Identifier) -> BlindSum {
		self.positive_key_ids.push(key_id);
		self
	}

	pub fn sub_key_id(mut self, key_id: Identifier) -> BlindSum {
		self.negative_key_ids.push(key_id);
		self
	}

	/// Adds the provided key to the sum of blinding factors.
	pub fn add_blinding_factor(mut self, blind: BlindingFactor) -> BlindSum {
		self.positive_blinding_factors.push(blind);
		self
	}

	/// Subtracts the provided key to the sum of blinding factors.
	pub fn sub_blinding_factor(mut self, blind: BlindingFactor) -> BlindSum {
		self.negative_blinding_factors.push(blind);
		self
	}
}

pub trait Keychain: Sync + Send + Clone {
	fn from_seed(seed: &[u8]) -> Result<Self, Error>;
	fn from_random_seed() -> Result<Self, Error>;
	fn root_key_id(&self) -> Identifier;
	fn derive_key_id(&self, derivation: u32) -> Result<Identifier, Error>;
	fn derived_key(&self, key_id: &Identifier) -> Result<SecretKey, Error>;
	fn commit(&self, amount: u64, key_id: &Identifier) -> Result<Commitment, Error>;
	fn commit_with_key_index(&self, amount: u64, derivation: u32) -> Result<Commitment, Error>;
	fn blind_sum(&self, blind_sum: &BlindSum) -> Result<BlindingFactor, Error>;
	fn sign(&self, msg: &Message, key_id: &Identifier) -> Result<Signature, Error>;
	fn sign_with_blinding(&self, &Message, &BlindingFactor) -> Result<Signature, Error>;
	fn secp(&self) -> &Secp256k1;
}

#[cfg(test)]
mod test {
	use rand::thread_rng;

	use types::BlindingFactor;
	use util::secp::Secp256k1;
	use util::secp::key::{SecretKey, ZERO_KEY};

	#[test]
	fn split_blinding_factor() {
		let secp = Secp256k1::new();
		let skey_in = SecretKey::new(&secp, &mut thread_rng());
		let blind = BlindingFactor::from_secret_key(skey_in);
		let split = blind.split(&secp).unwrap();

		// split a key, sum the split keys and confirm the sum matches the original key
		let mut skey_sum = split.blind_1.secret_key(&secp).unwrap();
		let skey_2 = split.blind_2.secret_key(&secp).unwrap();
		let _ = skey_sum.add_assign(&secp, &skey_2).unwrap();
		assert_eq!(skey_in, skey_sum);
	}

	// Sanity check that we can add the zero key to a secret key and it is still
	// the same key that we started with (k + 0 = k)
	#[test]
	fn zero_key_addition() {
		let secp = Secp256k1::new();
		let skey_in = SecretKey::new(&secp, &mut thread_rng());
		let skey_zero = ZERO_KEY;

		let mut skey_out = skey_in.clone();
		let _ = skey_out.add_assign(&secp, &skey_zero).unwrap();

		assert_eq!(skey_in, skey_out);
	}
}
<commit_msg>add impl fmt::Debug for BlindingFactor, for pretty print (#1382)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rand::thread_rng;
use std::cmp::min;
/// Keychain trait and its main supporting types. The Identifier is a
/// semi-opaque structure (just bytes) to track keys within the Keychain.
/// BlindingFactor is a useful wrapper around a private key to help with
/// commitment generation.
use std::{error, fmt};

use blake2::blake2b::blake2b;
use serde::{de, ser};

use util;
use util::secp::constants::SECRET_KEY_SIZE;
use util::secp::key::{PublicKey, SecretKey};
use util::secp::pedersen::Commitment;
use util::secp::{self, Message, Secp256k1, Signature};

// Size of an identifier in bytes
pub const IDENTIFIER_SIZE: usize = 10;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Error {
	Secp(secp::Error),
	KeyDerivation(String),
	Transaction(String),
	RangeProof(String),
}

impl From<secp::Error> for Error {
	fn from(e: secp::Error) -> Error {
		Error::Secp(e)
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			_ => "some kind of keychain error",
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			_ => write!(f, "some kind of keychain error"),
		}
	}
}

#[derive(Clone, PartialEq, Eq, Ord, Hash, PartialOrd)]
pub struct Identifier([u8; IDENTIFIER_SIZE]);

impl ser::Serialize for Identifier {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: ser::Serializer,
	{
		serializer.serialize_str(&self.to_hex())
	}
}

impl<'de> de::Deserialize<'de> for Identifier {
	fn deserialize<D>(deserializer: D) -> Result<Identifier, D::Error>
	where
		D: de::Deserializer<'de>,
	{
		deserializer.deserialize_str(IdentifierVisitor)
	}
}

struct IdentifierVisitor;

impl<'de> de::Visitor<'de> for IdentifierVisitor {
	type Value = Identifier;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str("an identifier")
	}

	fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
	where
		E: de::Error,
	{
		let identifier = Identifier::from_hex(s).unwrap();
		Ok(identifier)
	}
}

impl Identifier {
	pub fn zero() -> Identifier {
		Identifier::from_bytes(&[0; IDENTIFIER_SIZE])
	}

	pub fn from_bytes(bytes: &[u8]) -> Identifier {
		let mut identifier = [0; IDENTIFIER_SIZE];
		for i in 0..min(IDENTIFIER_SIZE, bytes.len()) {
			identifier[i] = bytes[i];
		}
		Identifier(identifier)
	}

	pub fn to_bytes(&self) -> [u8; IDENTIFIER_SIZE] {
		self.0.clone()
	}

	pub fn from_pubkey(secp: &Secp256k1, pubkey: &PublicKey) -> Identifier {
		let bytes = pubkey.serialize_vec(secp, true);
		let identifier = blake2b(IDENTIFIER_SIZE, &[], &bytes[..]);
		Identifier::from_bytes(&identifier.as_bytes())
	}

	/// Return the identifier of the secret key
	/// which is the blake2b (10 byte) digest of the PublicKey
	/// corresponding to the secret key provided.
	pub fn from_secret_key(secp: &Secp256k1, key: &SecretKey) -> Result<Identifier, Error> {
		let key_id = PublicKey::from_secret_key(secp, key)?;
		Ok(Identifier::from_pubkey(secp, &key_id))
	}

	pub fn from_hex(hex: &str) -> Result<Identifier, Error> {
		let bytes = util::from_hex(hex.to_string()).unwrap();
		Ok(Identifier::from_bytes(&bytes))
	}

	pub fn to_hex(&self) -> String {
		util::to_hex(self.0.to_vec())
	}
}

impl AsRef<[u8]> for Identifier {
	fn as_ref(&self) -> &[u8] {
		&self.0.as_ref()
	}
}

impl ::std::fmt::Debug for Identifier {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
		try!(write!(f, "{}(", stringify!(Identifier)));
		try!(write!(f, "{}", self.to_hex()));
		write!(f, ")")
	}
}

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

#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct BlindingFactor([u8; SECRET_KEY_SIZE]);

impl fmt::Debug for BlindingFactor {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.to_hex())
	}
}

impl AsRef<[u8]> for BlindingFactor {
	fn as_ref(&self) -> &[u8] {
		&self.0
	}
}

impl BlindingFactor {
	pub fn from_secret_key(skey: secp::key::SecretKey) -> BlindingFactor {
		BlindingFactor::from_slice(&skey.as_ref())
	}

	pub fn from_slice(data: &[u8]) -> BlindingFactor {
		let mut blind = [0; SECRET_KEY_SIZE];
		for i in 0..min(SECRET_KEY_SIZE, data.len()) {
			blind[i] = data[i];
		}
		BlindingFactor(blind)
	}

	pub fn zero() -> BlindingFactor {
		BlindingFactor::from_secret_key(secp::key::ZERO_KEY)
	}

	pub fn to_hex(&self) -> String {
		util::to_hex(self.0.to_vec())
	}

	pub fn from_hex(hex: &str) -> Result<BlindingFactor, Error> {
		let bytes = util::from_hex(hex.to_string()).unwrap();
		Ok(BlindingFactor::from_slice(&bytes))
	}

	pub fn secret_key(&self, secp: &Secp256k1) -> Result<secp::key::SecretKey, Error> {
		if *self == BlindingFactor::zero() {
			// TODO - need this currently for tx tests
			// the "zero" secret key is not actually a valid secret_key
			// and secp lib checks this
			Ok(secp::key::ZERO_KEY)
		} else {
			secp::key::SecretKey::from_slice(secp, &self.0).map_err(|e| Error::Secp(e))
		}
	}

	/// Split a blinding_factor (aka secret_key) into a pair of
	/// blinding_factors. We use one of these (k1) to sign the tx_kernel (k1G)
	/// and the other gets aggregated in the block_header as the "offset".
	/// This prevents an actor from being able to sum a set of inputs, outputs
	/// and kernels from a block to identify and reconstruct a particular tx
	/// from a block. You would need both k1, k2 to do this.
	pub fn split(&self, secp: &Secp256k1) -> Result<SplitBlindingFactor, Error> {
		let skey_1 = secp::key::SecretKey::new(secp, &mut thread_rng());

		// use blind_sum to subtract skey_1 from our key (to give k = k1 + k2)
		let skey = self.secret_key(secp)?;
		let skey_2 = secp.blind_sum(vec![skey], vec![skey_1])?;

		let blind_1 = BlindingFactor::from_secret_key(skey_1);
		let blind_2 = BlindingFactor::from_secret_key(skey_2);

		Ok(SplitBlindingFactor { blind_1, blind_2 })
	}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SplitBlindingFactor {
	pub blind_1: BlindingFactor,
	pub blind_2: BlindingFactor,
}

/// Accumulator to compute the sum of blinding factors. Keeps track of each
/// factor as well as the "sign" with which they should be combined.
#[derive(Clone, Debug, PartialEq)]
pub struct BlindSum {
	pub positive_key_ids: Vec<Identifier>,
	pub negative_key_ids: Vec<Identifier>,
	pub positive_blinding_factors: Vec<BlindingFactor>,
	pub negative_blinding_factors: Vec<BlindingFactor>,
}

impl BlindSum {
	/// Creates a new blinding factor sum.
	pub fn new() -> BlindSum {
		BlindSum {
			positive_key_ids: vec![],
			negative_key_ids: vec![],
			positive_blinding_factors: vec![],
			negative_blinding_factors: vec![],
		}
	}

	pub fn add_key_id(mut self, key_id: Identifier) -> BlindSum {
		self.positive_key_ids.push(key_id);
		self
	}

	pub fn sub_key_id(mut self, key_id: Identifier) -> BlindSum {
		self.negative_key_ids.push(key_id);
		self
	}

	/// Adds the provided key to the sum of blinding factors.
	pub fn add_blinding_factor(mut self, blind: BlindingFactor) -> BlindSum {
		self.positive_blinding_factors.push(blind);
		self
	}

	/// Subtracts the provided key to the sum of blinding factors.
	pub fn sub_blinding_factor(mut self, blind: BlindingFactor) -> BlindSum {
		self.negative_blinding_factors.push(blind);
		self
	}
}

pub trait Keychain: Sync + Send + Clone {
	fn from_seed(seed: &[u8]) -> Result<Self, Error>;
	fn from_random_seed() -> Result<Self, Error>;
	fn root_key_id(&self) -> Identifier;
	fn derive_key_id(&self, derivation: u32) -> Result<Identifier, Error>;
	fn derived_key(&self, key_id: &Identifier) -> Result<SecretKey, Error>;
	fn commit(&self, amount: u64, key_id: &Identifier) -> Result<Commitment, Error>;
	fn commit_with_key_index(&self, amount: u64, derivation: u32) -> Result<Commitment, Error>;
	fn blind_sum(&self, blind_sum: &BlindSum) -> Result<BlindingFactor, Error>;
	fn sign(&self, msg: &Message, key_id: &Identifier) -> Result<Signature, Error>;
	fn sign_with_blinding(&self, &Message, &BlindingFactor) -> Result<Signature, Error>;
	fn secp(&self) -> &Secp256k1;
}

#[cfg(test)]
mod test {
	use rand::thread_rng;

	use types::BlindingFactor;
	use util::secp::key::{SecretKey, ZERO_KEY};
	use util::secp::Secp256k1;

	#[test]
	fn split_blinding_factor() {
		let secp = Secp256k1::new();
		let skey_in = SecretKey::new(&secp, &mut thread_rng());
		let blind = BlindingFactor::from_secret_key(skey_in);
		let split = blind.split(&secp).unwrap();

		// split a key, sum the split keys and confirm the sum matches the original key
		let mut skey_sum = split.blind_1.secret_key(&secp).unwrap();
		let skey_2 = split.blind_2.secret_key(&secp).unwrap();
		let _ = skey_sum.add_assign(&secp, &skey_2).unwrap();
		assert_eq!(skey_in, skey_sum);
	}

	// Sanity check that we can add the zero key to a secret key and it is still
	// the same key that we started with (k + 0 = k)
	#[test]
	fn zero_key_addition() {
		let secp = Secp256k1::new();
		let skey_in = SecretKey::new(&secp, &mut thread_rng());
		let skey_zero = ZERO_KEY;

		let mut skey_out = skey_in.clone();
		let _ = skey_out.add_assign(&secp, &skey_zero).unwrap();

		assert_eq!(skey_in, skey_out);
	}
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;

use super::ffi;
use {SqliteError, SqliteResult, SqliteConnection};

pub struct SqliteBlob<'conn> {
    conn: &'conn SqliteConnection,
    blob: *mut ffi::sqlite3_blob,
    pos: i32,
}

pub enum SeekFrom {
    Start(i32),
    End(i32),
    Current(i32),
}

impl SqliteConnection {
    pub fn blob_open<'a>(&'a self, db: &str, table: &str, column: &str, row: i64, read_only: bool) -> SqliteResult<SqliteBlob<'a>> {
        let mut c = self.db.borrow_mut();
        let mut blob = ptr::null_mut();
        let db = try!(super::str_to_cstring(db));
        let table = try!(super::str_to_cstring(table));
        let column = try!(super::str_to_cstring(column));
        let rc = unsafe{ ffi::sqlite3_blob_open(c.db(), db.as_ptr(), table.as_ptr(), column.as_ptr(), row, if read_only { 0 } else { 1 }, &mut blob) };
        c.decode_result(rc).map(|_| {
            SqliteBlob{ conn: self, blob: blob, pos: 0 }
        })
    }
}

impl<'conn> SqliteBlob<'conn> {
    pub fn reopen(&mut self, row: i64) -> SqliteResult<()> {
        let rc = unsafe{ ffi::sqlite3_blob_reopen(self.blob, row) };
        if rc != ffi::SQLITE_OK {
            return self.conn.decode_result(rc);
        }
        self.pos = 0;
        Ok(())
    }

    pub fn size(&self) -> i32 {
        unsafe{ ffi::sqlite3_blob_bytes(self.blob) }
    }

    pub fn read(&mut self, buf: &mut [u8]) -> SqliteResult<i32> {
        let mut n = buf.len() as i32;
        let size = self.size();
        if self.pos + n > size {
            n = size - self.pos;
        }
        if n <= 0 {
            return Ok(0);
        }
        let rc = unsafe { ffi::sqlite3_blob_read(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) };
        self.conn.decode_result(rc).map(|_| {
            self.pos += n;
            n
        })
    }

    pub fn write(&mut self, buf: &[u8]) -> SqliteResult<i32> {
        let n = buf.len() as i32;
        let size = self.size();
        if self.pos + n > size {
            return Err(SqliteError{code: ffi::SQLITE_MISUSE, message: format!("pos = {} + n = {} > size = {}", self.pos, n, size)});
        }
        if n <= 0 {
            return Ok(0);
        }
        let rc = unsafe { ffi::sqlite3_blob_write(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) };
        self.conn.decode_result(rc).map(|_| {
            self.pos += n;
            n
        })
    }

    pub fn seek(&mut self, pos: SeekFrom) {
        self.pos  = match pos {
            SeekFrom::Start(offset) => offset,
            SeekFrom::Current(offset) => self.pos + offset,
            SeekFrom::End(offset) => self.size() + offset
        };
    }

    pub fn close(mut self) -> SqliteResult<()> {
        self.close_()
    }

    fn close_(&mut self) -> SqliteResult<()> {
        let rc = unsafe { ffi::sqlite3_blob_close(self.blob) };
        self.blob = ptr::null_mut();
        self.conn.decode_result(rc)
    }
}

#[allow(unused_must_use)]
impl<'conn> Drop for SqliteBlob<'conn> {
    fn drop(&mut self) {
        self.close_();
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

   #[test]
    fn test_blob() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                CREATE TABLE test (content BLOB);
                INSERT INTO test VALUES (ZEROBLOB(10));
                END;";
        db.execute_batch(sql).unwrap();
        let rowid = db.last_insert_rowid();

        let mut blob = db.blob_open("main", "test", "content", rowid, false).unwrap();
        blob.write(b"Clob").unwrap();
        let err = blob.write(b"5678901");
        //writeln!(io::stderr(), "{:?}", err);
        assert!(err.is_err());

        assert!(blob.reopen(rowid).is_ok());
        assert!(blob.close().is_ok());

        blob = db.blob_open("main", "test", "content", rowid, true).unwrap();
        let mut bytes = [0u8; 5];
        assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
        assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
        assert_eq!(0, blob.read(&mut bytes[..]).unwrap());

        assert!(blob.reopen(rowid).is_ok());
        blob.seek(super::SeekFrom::Start(0));
    }
}<commit_msg>Check when buffer is too long.<commit_after>use std::mem;
use std::ptr;

use super::ffi;
use {SqliteError, SqliteResult, SqliteConnection};

pub struct SqliteBlob<'conn> {
    conn: &'conn SqliteConnection,
    blob: *mut ffi::sqlite3_blob,
    pos: i32,
}

pub enum SeekFrom {
    Start(i32),
    End(i32),
    Current(i32),
}

impl SqliteConnection {
    pub fn blob_open<'a>(&'a self, db: &str, table: &str, column: &str, row: i64, read_only: bool) -> SqliteResult<SqliteBlob<'a>> {
        let mut c = self.db.borrow_mut();
        let mut blob = ptr::null_mut();
        let db = try!(super::str_to_cstring(db));
        let table = try!(super::str_to_cstring(table));
        let column = try!(super::str_to_cstring(column));
        let rc = unsafe{ ffi::sqlite3_blob_open(c.db(), db.as_ptr(), table.as_ptr(), column.as_ptr(), row, if read_only { 0 } else { 1 }, &mut blob) };
        c.decode_result(rc).map(|_| {
            SqliteBlob{ conn: self, blob: blob, pos: 0 }
        })
    }
}

impl<'conn> SqliteBlob<'conn> {
    pub fn reopen(&mut self, row: i64) -> SqliteResult<()> {
        let rc = unsafe{ ffi::sqlite3_blob_reopen(self.blob, row) };
        if rc != ffi::SQLITE_OK {
            return self.conn.decode_result(rc);
        }
        self.pos = 0;
        Ok(())
    }

    pub fn size(&self) -> i32 {
        unsafe{ ffi::sqlite3_blob_bytes(self.blob) }
    }

    pub fn read(&mut self, buf: &mut [u8]) -> SqliteResult<i32> {
        if buf.len() > ::std::i32::MAX as usize {
            return Err(SqliteError {
                code: ffi::SQLITE_TOOBIG,
                message: "buffer too long".to_string()
            });
        }
        let mut n = buf.len() as i32;
        let size = self.size();
        if self.pos + n > size {
            n = size - self.pos;
        }
        if n <= 0 {
            return Ok(0);
        }
        let rc = unsafe { ffi::sqlite3_blob_read(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) };
        self.conn.decode_result(rc).map(|_| {
            self.pos += n;
            n
        })
    }

    pub fn write(&mut self, buf: &[u8]) -> SqliteResult<i32> {
        if buf.len() > ::std::i32::MAX as usize {
            return Err(SqliteError {
                code: ffi::SQLITE_TOOBIG,
                message: "buffer too long".to_string()
            });
        }
        let n = buf.len() as i32;
        let size = self.size();
        if self.pos + n > size {
            return Err(SqliteError{code: ffi::SQLITE_MISUSE, message: format!("pos = {} + n = {} > size = {}", self.pos, n, size)});
        }
        if n <= 0 {
            return Ok(0);
        }
        let rc = unsafe { ffi::sqlite3_blob_write(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) };
        self.conn.decode_result(rc).map(|_| {
            self.pos += n;
            n
        })
    }

    pub fn seek(&mut self, pos: SeekFrom) {
        self.pos  = match pos {
            SeekFrom::Start(offset) => offset,
            SeekFrom::Current(offset) => self.pos + offset,
            SeekFrom::End(offset) => self.size() + offset
        };
    }

    pub fn close(mut self) -> SqliteResult<()> {
        self.close_()
    }

    fn close_(&mut self) -> SqliteResult<()> {
        let rc = unsafe { ffi::sqlite3_blob_close(self.blob) };
        self.blob = ptr::null_mut();
        self.conn.decode_result(rc)
    }
}

#[allow(unused_must_use)]
impl<'conn> Drop for SqliteBlob<'conn> {
    fn drop(&mut self) {
        self.close_();
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

   #[test]
    fn test_blob() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                CREATE TABLE test (content BLOB);
                INSERT INTO test VALUES (ZEROBLOB(10));
                END;";
        db.execute_batch(sql).unwrap();
        let rowid = db.last_insert_rowid();

        let mut blob = db.blob_open("main", "test", "content", rowid, false).unwrap();
        blob.write(b"Clob").unwrap();
        let err = blob.write(b"5678901");
        //writeln!(io::stderr(), "{:?}", err);
        assert!(err.is_err());

        assert!(blob.reopen(rowid).is_ok());
        assert!(blob.close().is_ok());

        blob = db.blob_open("main", "test", "content", rowid, true).unwrap();
        let mut bytes = [0u8; 5];
        assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
        assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
        assert_eq!(0, blob.read(&mut bytes[..]).unwrap());

        assert!(blob.reopen(rowid).is_ok());
        blob.seek(super::SeekFrom::Start(0));
    }
}<|endoftext|>


<commit_before>use std::rc::Rc;
use std::sync::Arc;
use bytes::{Bytes, BytesMut};

/// Represents various types of http message body.
#[derive(Debug)]
pub enum Body {
    /// Empty response. `Content-Length` header is set to `0`
    Empty,
    /// Specific response body.
    Binary(BinaryBody),
    /// Streaming response body with specified length.
    Length(u64),
    /// Unspecified streaming response. Developer is responsible for setting
    /// right `Content-Length` or `Transfer-Encoding` headers.
    Streaming,
    /// Upgrade connection.
    Upgrade,
}

/// Represents various types of binary body.
/// `Content-Length` header is set to length of the body.
#[derive(Debug)]
pub enum BinaryBody {
    /// Bytes body
    Bytes(Bytes),
    /// Static slice
    Slice(&'static [u8]),
    /// Shared bytes body
    SharedBytes(Rc<Bytes>),
    /// Shared stirng body
    SharedString(Rc<String>),
    /// Shared bytes body
    #[doc(hidden)]
    ArcSharedBytes(Arc<Bytes>),
    /// Shared string body
    #[doc(hidden)]
    ArcSharedString(Arc<String>),
}

impl Body {
    /// Does this body have payload.
    pub fn has_body(&self) -> bool {
        match *self {
            Body::Length(_) | Body::Streaming => true,
            _ => false
        }
    }

    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Binary(BinaryBody::Bytes(Bytes::from(s)))
    }
}

impl<T> From<T> for Body where T: Into<BinaryBody>{
    fn from(b: T) -> Body {
        Body::Binary(b.into())
    }
}

impl BinaryBody {
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn len(&self) -> usize {
        match *self {
            BinaryBody::Bytes(ref bytes) => bytes.len(),
            BinaryBody::Slice(slice) => slice.len(),
            BinaryBody::SharedBytes(ref bytes) => bytes.len(),
            BinaryBody::ArcSharedBytes(ref bytes) => bytes.len(),
            BinaryBody::SharedString(ref s) => s.len(),
            BinaryBody::ArcSharedString(ref s) => s.len(),
        }
    }

    /// Create binary body from slice
    pub fn from_slice(s: &[u8]) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(s))
    }
}

impl From<&'static str> for BinaryBody {
    fn from(s: &'static str) -> BinaryBody {
        BinaryBody::Slice(s.as_ref())
    }
}

impl From<&'static [u8]> for BinaryBody {
    fn from(s: &'static [u8]) -> BinaryBody {
        BinaryBody::Slice(s)
    }
}

impl From<Vec<u8>> for BinaryBody {
    fn from(vec: Vec<u8>) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(vec))
    }
}

impl From<String> for BinaryBody {
    fn from(s: String) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(s))
    }
}

impl From<Bytes> for BinaryBody {
    fn from(s: Bytes) -> BinaryBody {
        BinaryBody::Bytes(s)
    }
}

impl From<BytesMut> for BinaryBody {
    fn from(s: BytesMut) -> BinaryBody {
        BinaryBody::Bytes(s.freeze())
    }
}

impl From<Rc<Bytes>> for BinaryBody {
    fn from(body: Rc<Bytes>) -> BinaryBody {
        BinaryBody::SharedBytes(body)
    }
}

impl<'a> From<&'a Rc<Bytes>> for BinaryBody {
    fn from(body: &'a Rc<Bytes>) -> BinaryBody {
        BinaryBody::SharedBytes(Rc::clone(body))
    }
}

impl From<Arc<Bytes>> for BinaryBody {
    fn from(body: Arc<Bytes>) -> BinaryBody {
        BinaryBody::ArcSharedBytes(body)
    }
}

impl<'a> From<&'a Arc<Bytes>> for BinaryBody {
    fn from(body: &'a Arc<Bytes>) -> BinaryBody {
        BinaryBody::ArcSharedBytes(Arc::clone(body))
    }
}

impl From<Rc<String>> for BinaryBody {
    fn from(body: Rc<String>) -> BinaryBody {
        BinaryBody::SharedString(body)
    }
}

impl<'a> From<&'a Rc<String>> for BinaryBody {
    fn from(body: &'a Rc<String>) -> BinaryBody {
        BinaryBody::SharedString(Rc::clone(body))
    }
}

impl From<Arc<String>> for BinaryBody {
    fn from(body: Arc<String>) -> BinaryBody {
        BinaryBody::ArcSharedString(body)
    }
}

impl<'a> From<&'a Arc<String>> for BinaryBody {
    fn from(body: &'a Arc<String>) -> BinaryBody {
        BinaryBody::ArcSharedString(Arc::clone(body))
    }
}

impl AsRef<[u8]> for BinaryBody {
    fn as_ref(&self) -> &[u8] {
        match *self {
            BinaryBody::Bytes(ref bytes) => bytes.as_ref(),
            BinaryBody::Slice(slice) => slice,
            BinaryBody::SharedBytes(ref bytes) => bytes.as_ref(),
            BinaryBody::ArcSharedBytes(ref bytes) => bytes.as_ref(),
            BinaryBody::SharedString(ref s) => s.as_bytes(),
            BinaryBody::ArcSharedString(ref s) => s.as_bytes(),
        }
    }
}

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

    #[test]
    fn test_static_str() {
        assert_eq!(BinaryBody::from("test").len(), 4);
        assert_eq!(BinaryBody::from("test").as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(BinaryBody::from(b"test".as_ref()).len(), 4);
        assert_eq!(BinaryBody::from(b"test".as_ref()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from_slice(b"test".as_ref()).len(), 4);
        assert_eq!(BinaryBody::from_slice(b"test".as_ref()).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_vec() {
        assert_eq!(BinaryBody::from(Vec::from("test")).len(), 4);
        assert_eq!(BinaryBody::from(Vec::from("test")).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_bytes() {
        assert_eq!(BinaryBody::from(Bytes::from("test")).len(), 4);
        assert_eq!(BinaryBody::from(Bytes::from("test")).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_rc_bytes() {
        let b = Rc::new(Bytes::from("test"));
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_rc_string() {
        let b = Rc::new("test".to_owned());
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_arc_bytes() {
        let b = Arc::new(Bytes::from("test"));
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_arc_string() {
        let b = Arc::new("test".to_owned());
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }
}
<commit_msg>convert from ref string into body<commit_after>use std::rc::Rc;
use std::sync::Arc;
use bytes::{Bytes, BytesMut};

/// Represents various types of http message body.
#[derive(Debug)]
pub enum Body {
    /// Empty response. `Content-Length` header is set to `0`
    Empty,
    /// Specific response body.
    Binary(BinaryBody),
    /// Streaming response body with specified length.
    Length(u64),
    /// Unspecified streaming response. Developer is responsible for setting
    /// right `Content-Length` or `Transfer-Encoding` headers.
    Streaming,
    /// Upgrade connection.
    Upgrade,
}

/// Represents various types of binary body.
/// `Content-Length` header is set to length of the body.
#[derive(Debug)]
pub enum BinaryBody {
    /// Bytes body
    Bytes(Bytes),
    /// Static slice
    Slice(&'static [u8]),
    /// Shared bytes body
    SharedBytes(Rc<Bytes>),
    /// Shared stirng body
    SharedString(Rc<String>),
    /// Shared bytes body
    #[doc(hidden)]
    ArcSharedBytes(Arc<Bytes>),
    /// Shared string body
    #[doc(hidden)]
    ArcSharedString(Arc<String>),
}

impl Body {
    /// Does this body have payload.
    pub fn has_body(&self) -> bool {
        match *self {
            Body::Length(_) | Body::Streaming => true,
            _ => false
        }
    }

    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Binary(BinaryBody::Bytes(Bytes::from(s)))
    }
}

impl<T> From<T> for Body where T: Into<BinaryBody>{
    fn from(b: T) -> Body {
        Body::Binary(b.into())
    }
}

impl BinaryBody {
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn len(&self) -> usize {
        match *self {
            BinaryBody::Bytes(ref bytes) => bytes.len(),
            BinaryBody::Slice(slice) => slice.len(),
            BinaryBody::SharedBytes(ref bytes) => bytes.len(),
            BinaryBody::ArcSharedBytes(ref bytes) => bytes.len(),
            BinaryBody::SharedString(ref s) => s.len(),
            BinaryBody::ArcSharedString(ref s) => s.len(),
        }
    }

    /// Create binary body from slice
    pub fn from_slice(s: &[u8]) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(s))
    }
}

impl From<&'static str> for BinaryBody {
    fn from(s: &'static str) -> BinaryBody {
        BinaryBody::Slice(s.as_ref())
    }
}

impl From<&'static [u8]> for BinaryBody {
    fn from(s: &'static [u8]) -> BinaryBody {
        BinaryBody::Slice(s)
    }
}

impl From<Vec<u8>> for BinaryBody {
    fn from(vec: Vec<u8>) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(vec))
    }
}

impl From<String> for BinaryBody {
    fn from(s: String) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(s))
    }
}

impl<'a> From<&'a String> for BinaryBody {
    fn from(s: &'a String) -> BinaryBody {
        BinaryBody::Bytes(Bytes::from(AsRef::<[u8]>::as_ref(&s)))
    }
}

impl From<Bytes> for BinaryBody {
    fn from(s: Bytes) -> BinaryBody {
        BinaryBody::Bytes(s)
    }
}

impl From<BytesMut> for BinaryBody {
    fn from(s: BytesMut) -> BinaryBody {
        BinaryBody::Bytes(s.freeze())
    }
}

impl From<Rc<Bytes>> for BinaryBody {
    fn from(body: Rc<Bytes>) -> BinaryBody {
        BinaryBody::SharedBytes(body)
    }
}

impl<'a> From<&'a Rc<Bytes>> for BinaryBody {
    fn from(body: &'a Rc<Bytes>) -> BinaryBody {
        BinaryBody::SharedBytes(Rc::clone(body))
    }
}

impl From<Arc<Bytes>> for BinaryBody {
    fn from(body: Arc<Bytes>) -> BinaryBody {
        BinaryBody::ArcSharedBytes(body)
    }
}

impl<'a> From<&'a Arc<Bytes>> for BinaryBody {
    fn from(body: &'a Arc<Bytes>) -> BinaryBody {
        BinaryBody::ArcSharedBytes(Arc::clone(body))
    }
}

impl From<Rc<String>> for BinaryBody {
    fn from(body: Rc<String>) -> BinaryBody {
        BinaryBody::SharedString(body)
    }
}

impl<'a> From<&'a Rc<String>> for BinaryBody {
    fn from(body: &'a Rc<String>) -> BinaryBody {
        BinaryBody::SharedString(Rc::clone(body))
    }
}

impl From<Arc<String>> for BinaryBody {
    fn from(body: Arc<String>) -> BinaryBody {
        BinaryBody::ArcSharedString(body)
    }
}

impl<'a> From<&'a Arc<String>> for BinaryBody {
    fn from(body: &'a Arc<String>) -> BinaryBody {
        BinaryBody::ArcSharedString(Arc::clone(body))
    }
}

impl AsRef<[u8]> for BinaryBody {
    fn as_ref(&self) -> &[u8] {
        match *self {
            BinaryBody::Bytes(ref bytes) => bytes.as_ref(),
            BinaryBody::Slice(slice) => slice,
            BinaryBody::SharedBytes(ref bytes) => bytes.as_ref(),
            BinaryBody::ArcSharedBytes(ref bytes) => bytes.as_ref(),
            BinaryBody::SharedString(ref s) => s.as_bytes(),
            BinaryBody::ArcSharedString(ref s) => s.as_bytes(),
        }
    }
}

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

    #[test]
    fn test_static_str() {
        assert_eq!(BinaryBody::from("test").len(), 4);
        assert_eq!(BinaryBody::from("test").as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(BinaryBody::from(b"test".as_ref()).len(), 4);
        assert_eq!(BinaryBody::from(b"test".as_ref()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from_slice(b"test".as_ref()).len(), 4);
        assert_eq!(BinaryBody::from_slice(b"test".as_ref()).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_vec() {
        assert_eq!(BinaryBody::from(Vec::from("test")).len(), 4);
        assert_eq!(BinaryBody::from(Vec::from("test")).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_bytes() {
        assert_eq!(BinaryBody::from(Bytes::from("test")).len(), 4);
        assert_eq!(BinaryBody::from(Bytes::from("test")).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_rc_bytes() {
        let b = Rc::new(Bytes::from("test"));
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_ref_string() {
        let b = Rc::new("test".to_owned());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_rc_string() {
        let b = Rc::new("test".to_owned());
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_arc_bytes() {
        let b = Arc::new(Bytes::from("test"));
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }

    #[test]
    fn test_arc_string() {
        let b = Arc::new("test".to_owned());
        assert_eq!(BinaryBody::from(b.clone()).len(), 4);
        assert_eq!(BinaryBody::from(b.clone()).as_ref(), "test".as_bytes());
        assert_eq!(BinaryBody::from(&b).len(), 4);
        assert_eq!(BinaryBody::from(&b).as_ref(), "test".as_bytes());
    }
}
<|endoftext|>