<commit_before>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;
use std::slice;
use std::vec;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// # Error reporting in proc macros
///
/// The correct way to report errors back to the compiler from a procedural
/// macro is by emitting an appropriately spanned invocation of
/// [`compile_error!`] in the generated code. This produces a better diagnostic
/// message than simply panicking the macro.
///
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
/// conversion to `compile_error!` automatically.
///
/// ```
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
///     let args = parse_macro_input!(args as AttributeArgs);
///     let input = parse_macro_input!(input as ItemFn);
///
///     /* ... */
///     # TokenStream::new()
/// }
/// ```
///
/// For errors that arise later than the initial parsing stage, the
/// [`.to_compile_error()`] method can be used to perform an explicit conversion
/// to `compile_error!`.
///
/// [`.to_compile_error()`]: Error::to_compile_error
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, DeriveInput};
/// #
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_derive(MyDerive)]
/// # };
/// pub fn my_derive(input: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(input as DeriveInput);
///
///     // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
///     expand::my_derive(input)
///         .unwrap_or_else(|err| err.to_compile_error())
///         .into()
/// }
/// #
/// # mod expand {
/// #     use proc_macro2::TokenStream;
/// #     use syn::{DeriveInput, Result};
/// #
/// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
/// #         unimplemented!()
/// #     }
/// # }
/// ```
#[derive(Clone)]
pub struct Error {
    messages: Vec<ErrorMessage>,
}

struct ErrorMessage {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(span),
                end_span: ThreadBound::new(span),
                message: message.to_string(),
            }],
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(start),
                end_span: ThreadBound::new(end),
                message: message.to_string(),
            }],
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.messages[0].start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.messages[0].end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        self.messages
            .iter()
            .map(ErrorMessage::to_compile_error)
            .collect()
    }

    /// Add another error message to self such that when `to_compile_error()` is
    /// called, both errors will be emitted together.
    pub fn combine(&mut self, another: Error) {
        self.messages.extend(another.messages)
    }
}

impl ErrorMessage {
    fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.messages.len() == 1 {
            formatter
                .debug_tuple("Error")
                .field(&self.messages[0])
                .finish()
        } else {
            formatter
                .debug_tuple("Error")
                .field(&self.messages)
                .finish()
        }
    }
}

impl Debug for ErrorMessage {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.message, formatter)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.messages[0].message)
    }
}

impl Clone for ErrorMessage {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        ErrorMessage {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}

impl IntoIterator for Error {
    type Item = Error;
    type IntoIter = IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            messages: self.messages.into_iter(),
        }
    }
}

pub struct IntoIter {
    messages: vec::IntoIter<ErrorMessage>,
}

impl Iterator for IntoIter {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?],
        })
    }
}

impl<'a> IntoIterator for &'a Error {
    type Item = Error;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        Iter {
            messages: self.messages.iter(),
        }
    }
}

pub struct Iter<'a> {
    messages: slice::Iter<'a, ErrorMessage>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?.clone()],
        })
    }
}
<commit_msg>Work around intra doc link bug<commit_after>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;
use std::slice;
use std::vec;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// # Error reporting in proc macros
///
/// The correct way to report errors back to the compiler from a procedural
/// macro is by emitting an appropriately spanned invocation of
/// [`compile_error!`] in the generated code. This produces a better diagnostic
/// message than simply panicking the macro.
///
/// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
///
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
/// conversion to `compile_error!` automatically.
///
/// ```
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
///     let args = parse_macro_input!(args as AttributeArgs);
///     let input = parse_macro_input!(input as ItemFn);
///
///     /* ... */
///     # TokenStream::new()
/// }
/// ```
///
/// For errors that arise later than the initial parsing stage, the
/// [`.to_compile_error()`] method can be used to perform an explicit conversion
/// to `compile_error!`.
///
/// [`.to_compile_error()`]: Error::to_compile_error
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, DeriveInput};
/// #
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_derive(MyDerive)]
/// # };
/// pub fn my_derive(input: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(input as DeriveInput);
///
///     // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
///     expand::my_derive(input)
///         .unwrap_or_else(|err| err.to_compile_error())
///         .into()
/// }
/// #
/// # mod expand {
/// #     use proc_macro2::TokenStream;
/// #     use syn::{DeriveInput, Result};
/// #
/// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
/// #         unimplemented!()
/// #     }
/// # }
/// ```
#[derive(Clone)]
pub struct Error {
    messages: Vec<ErrorMessage>,
}

struct ErrorMessage {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(span),
                end_span: ThreadBound::new(span),
                message: message.to_string(),
            }],
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(start),
                end_span: ThreadBound::new(end),
                message: message.to_string(),
            }],
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.messages[0].start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.messages[0].end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        self.messages
            .iter()
            .map(ErrorMessage::to_compile_error)
            .collect()
    }

    /// Add another error message to self such that when `to_compile_error()` is
    /// called, both errors will be emitted together.
    pub fn combine(&mut self, another: Error) {
        self.messages.extend(another.messages)
    }
}

impl ErrorMessage {
    fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.messages.len() == 1 {
            formatter
                .debug_tuple("Error")
                .field(&self.messages[0])
                .finish()
        } else {
            formatter
                .debug_tuple("Error")
                .field(&self.messages)
                .finish()
        }
    }
}

impl Debug for ErrorMessage {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.message, formatter)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.messages[0].message)
    }
}

impl Clone for ErrorMessage {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        ErrorMessage {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}

impl IntoIterator for Error {
    type Item = Error;
    type IntoIter = IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            messages: self.messages.into_iter(),
        }
    }
}

pub struct IntoIter {
    messages: vec::IntoIter<ErrorMessage>,
}

impl Iterator for IntoIter {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?],
        })
    }
}

impl<'a> IntoIterator for &'a Error {
    type Item = Error;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        Iter {
            messages: self.messages.iter(),
        }
    }
}

pub struct Iter<'a> {
    messages: slice::Iter<'a, ErrorMessage>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?.clone()],
        })
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::result;
use std::net::TcpStream;
use std::sync::mpsc::{RecvError, TrySendError, RecvTimeoutError};

use mqtt3::{self, ConnectReturnCode};
use openssl;

use publisher::PublishRequest;

pub type SslError = openssl::error::ErrorStack;
pub type HandShakeError = openssl::ssl::HandshakeError<TcpStream>;
pub type Result<T> = result::Result<T, Error>;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        TryRecv(err: RecvError) {
            from()
        }
        TrySend(err: TrySendError<PublishRequest>) {
            from()
        }
        RecvTimeout(err: RecvTimeoutError) {
            from()
        }
        Mqtt3(err: mqtt3::Error) {
            from()
            display("mqtt3 error: {:?}", err)
            description("Mqtt3 error {}")
        }
        Ssl(err: SslError) {
            from()
            display("ssl error: {:?}", err)
        }
        NoConnectionThread
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum PublishError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        PacketSizeLimitExceeded
        InvalidState
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum PingError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        AwaitPingResp
        InvalidState
        PingTimeout
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum IncomingError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        // might happen when broker refuses the connection
        // due to username/password mismatches after tcp connection
        MqttConnectionRefused(e: ConnectReturnCode) {
            from()
        }
        ConnectionAbort
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum AwaitError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        Reconnect
    }
}<commit_msg>adding handshake error<commit_after>use std::io;
use std::result;
use std::net::TcpStream;
use std::sync::mpsc::{RecvError, TrySendError, RecvTimeoutError};

use mqtt3::{self, ConnectReturnCode};
use openssl;

use publisher::PublishRequest;

pub type SslError = openssl::error::ErrorStack;
pub type HandShakeError = openssl::ssl::HandshakeError<TcpStream>;
pub type Result<T> = result::Result<T, Error>;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        TryRecv(err: RecvError) {
            from()
        }
        TrySend(err: TrySendError<PublishRequest>) {
            from()
        }
        RecvTimeout(err: RecvTimeoutError) {
            from()
        }
        Mqtt3(err: mqtt3::Error) {
            from()
            display("mqtt3 error: {:?}", err)
            description("Mqtt3 error {}")
        }
        Ssl(err: SslError) {
            from()
            display("ssl error: {:?}", err)
        }
        Handshake(err: HandShakeError) {
            from()
            display("handshake error: {:?}", err)
        }
        NoConnectionThread
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum PublishError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        PacketSizeLimitExceeded
        InvalidState
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum PingError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        AwaitPingResp
        InvalidState
        PingTimeout
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum IncomingError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        // might happen when broker refuses the connection
        // due to username/password mismatches after tcp connection
        MqttConnectionRefused(e: ConnectReturnCode) {
            from()
        }
        ConnectionAbort
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum AwaitError {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        Reconnect
    }
}<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::{fmt, io};
use rustc_serialize::{json, base64};
use hyper;

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum Error {
    ApiError(ApiError),
    ContentTypeError(String),
    DataTypeError(String),
    DataPathError(String),
    HttpError(hyper::error::Error),
    DecoderError(json::DecoderError),
    EncoderError(json::EncoderError),
    FromBase64Error(base64::FromBase64Error),
    IoError(io::Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

pub fn decode(json_str: &str) -> Error {
    match json::decode::<ApiErrorResponse>(json_str) {
        Ok(err_res) => err_res.error.into(),
        Err(err) => Error::DecoderError(err),
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ApiError(ref e) => e.description(),
            Error::ContentTypeError(ref msg) => &msg,
            Error::DataTypeError(ref msg) => &msg,
            Error::DataPathError(ref msg) => &msg,
            Error::HttpError(ref e) => e.description(),
            Error::DecoderError(ref e) => e.description(),
            Error::EncoderError(ref e) => e.description(),
            Error::FromBase64Error(ref e) => e.description(),
            Error::IoError(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::HttpError(ref e) => Some(e),
            Error::DecoderError(ref e) => Some(e),
            Error::EncoderError(ref e) => Some(e),
            Error::FromBase64Error(ref e) => Some(e),
            Error::IoError(ref e) => Some(e),
            _ => None,
        }
    }
}

//
// Implement Display trait
//

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

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

//
// Implement From trait (used by try! macro)
//

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

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

impl From<hyper::error::Error> for Error {
    fn from(err: hyper::error::Error) -> Error {
        Error::HttpError(err)
    }
}

impl From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::DecoderError(err)
    }
}

impl From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::EncoderError(err)
    }
}

impl From<base64::FromBase64Error> for Error {
    fn from(err: base64::FromBase64Error) -> Error {
        Error::FromBase64Error(err)
    }
}
<commit_msg>More error types<commit_after>use std::error::Error as StdError;
use std::{fmt, io, str, string};
use rustc_serialize::{json, base64};
use hyper;

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum Error {
    ApiError(ApiError),
    ContentTypeError(String),
    DataTypeError(String),
    DataPathError(String),
    HttpError(hyper::error::Error),
    DecoderError(json::DecoderError),
    EncoderError(json::EncoderError),
    FromBase64Error(base64::FromBase64Error),
    IoError(io::Error),
    Utf8Error(str::Utf8Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

pub fn decode(json_str: &str) -> Error {
    match json::decode::<ApiErrorResponse>(json_str) {
        Ok(err_res) => err_res.error.into(),
        Err(err) => Error::DecoderError(err),
    }
}

impl StdError for ApiError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ApiError(ref e) => e.description(),
            Error::ContentTypeError(ref msg) => &msg,
            Error::DataTypeError(ref msg) => &msg,
            Error::DataPathError(ref msg) => &msg,
            Error::HttpError(ref e) => e.description(),
            Error::DecoderError(ref e) => e.description(),
            Error::EncoderError(ref e) => e.description(),
            Error::FromBase64Error(ref e) => e.description(),
            Error::IoError(ref e) => e.description(),
            Error::Utf8Error(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::HttpError(ref e) => Some(e),
            Error::DecoderError(ref e) => Some(e),
            Error::EncoderError(ref e) => Some(e),
            Error::FromBase64Error(ref e) => Some(e),
            Error::IoError(ref e) => Some(e),
            Error::Utf8Error(ref e) => Some(e),
            _ => None,
        }
    }
}

//
// Implement Display trait
//

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

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

//
// Implement From trait (used by try! macro)
//

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

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

impl From<hyper::error::Error> for Error {
    fn from(err: hyper::error::Error) -> Error {
        Error::HttpError(err)
    }
}

impl From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::DecoderError(err)
    }
}

impl From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::EncoderError(err)
    }
}

impl From<base64::FromBase64Error> for Error {
    fn from(err: base64::FromBase64Error) -> Error {
        Error::FromBase64Error(err)
    }
}

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

impl From<string::FromUtf8Error> for Error {
    fn from(err: string::FromUtf8Error) -> Error {
        Error::Utf8Error(err.utf8_error())
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = &b"Hello, world!"[..];
/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Creates a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Creates a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `new` except that no runtime assertion
    /// is made that `v` contains no 0 bytes, and it requires an actual
    /// byte vector, not anything that can be converted to one with Into.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::new`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Casts a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Returns the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Converts this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Converts this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<commit_msg>Simplify CString doc comment<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let c_to_print = CString::new("Hello, world!").unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Creates a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Creates a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `new` except that no runtime assertion
    /// is made that `v` contains no 0 bytes, and it requires an actual
    /// byte vector, not anything that can be converted to one with Into.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::new`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Casts a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Returns the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Converts this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Converts this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<|endoftext|>


<commit_before>//! Implement record manupulation mechanisms.

use time;
use time::Tm;
use std::io;
use retry;
use serde_json;
use serde::ser::{Serialize, Serializer};
use rmp_serde;
use serde::ser::SerializeTuple;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Serialize> {
    tag: String,
    time: Tm,
    record: T,
}

#[derive(Debug)]
pub enum FluentError {
    JsonEncode(serde_json::Error),
    MsgpackEncode(rmp_serde::encode::Error),
    IO(io::Error),
    Retry(retry::RetryError),
    FileStored(String),
    #[doc(hidden)]
    Dummy(String),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IO(err)
    }
}

impl From<rmp_serde::encode::Error> for FluentError {
    fn from(err: rmp_serde::encode::Error) -> FluentError {
        FluentError::MsgpackEncode(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::Retry(err)
    }
}

impl From<serde_json::Error> for FluentError {
    fn from(err: serde_json::Error) -> FluentError {
        FluentError::JsonEncode(err)
    }
}

impl<T: Serialize> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let message = serde_json::to_string(&self)?;
        Ok(message)
    }

    #[doc(hidden)]
    pub fn dump(self) -> String {
        format!("{}\t{}\t{}\n",
                time::strftime("%FT%T%z", &self.time).unwrap(),
                self.tag,
                serde_json::to_string(&self.record).unwrap())
    }
}

/// Construct custom encoding json/msgpack style.
///
/// Because `Record` struct should map following style json/msgpack:
///
/// `[tag, unixtime/eventtime, record]`
///
/// ref: https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v0#message-mode
impl<T: Serialize> Serialize for Record<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut seq = s.serialize_tuple(4)?;
        seq.serialize_element(&self.tag)?;
        seq.serialize_element(&self.time.to_timespec().sec)?;
        seq.serialize_element(&self.record)?;
        seq.serialize_element(&None::<T>)?;
        seq.end()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use serde_json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = serde_json::to_string(&tag.clone()).ok().unwrap();
        let json_obj = serde_json::to_string(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},{}]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj,
                               serde_json::Value::Null);
        assert_eq!(expected, forwardable_json);
    }
}
<commit_msg>Use strict use derective<commit_after>//! Implement record manupulation mechanisms.

use time;
use time::Tm;
use std::io;
use retry;
use serde_json;
use serde::ser::{Serialize, Serializer};
use rmp_serde::encode;
use serde::ser::SerializeTuple;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Serialize> {
    tag: String,
    time: Tm,
    record: T,
}

#[derive(Debug)]
pub enum FluentError {
    JsonEncode(serde_json::Error),
    MsgpackEncode(encode::Error),
    IO(io::Error),
    Retry(retry::RetryError),
    FileStored(String),
    #[doc(hidden)]
    Dummy(String),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IO(err)
    }
}

impl From<encode::Error> for FluentError {
    fn from(err: encode::Error) -> FluentError {
        FluentError::MsgpackEncode(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::Retry(err)
    }
}

impl From<serde_json::Error> for FluentError {
    fn from(err: serde_json::Error) -> FluentError {
        FluentError::JsonEncode(err)
    }
}

impl<T: Serialize> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let message = serde_json::to_string(&self)?;
        Ok(message)
    }

    #[doc(hidden)]
    pub fn dump(self) -> String {
        format!("{}\t{}\t{}\n",
                time::strftime("%FT%T%z", &self.time).unwrap(),
                self.tag,
                serde_json::to_string(&self.record).unwrap())
    }
}

/// Construct custom encoding json/msgpack style.
///
/// Because `Record` struct should map following style json/msgpack:
///
/// `[tag, unixtime/eventtime, record]`
///
/// ref: https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v0#message-mode
impl<T: Serialize> Serialize for Record<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut seq = s.serialize_tuple(4)?;
        seq.serialize_element(&self.tag)?;
        seq.serialize_element(&self.time.to_timespec().sec)?;
        seq.serialize_element(&self.record)?;
        seq.serialize_element(&None::<T>)?;
        seq.end()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use serde_json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = serde_json::to_string(&tag.clone()).ok().unwrap();
        let json_obj = serde_json::to_string(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},{}]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj,
                               serde_json::Value::Null);
        assert_eq!(expected, forwardable_json);
    }
}
<|endoftext|>


<commit_before>#![crate_type="lib"]
#![feature(lang_items, intrinsics, no_std)]
#![no_std]

use pebblerust::lib::*;
use pebblerust::types::*;

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

mod pebblerust {
  pub mod lib;
  pub mod c;
  pub mod types;
  pub mod zero;
}

extern fn select_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
  text_layer_set_text(text_layer, "Select!\0");
}

extern fn up_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
  text_layer_set_text(text_layer, "Up!\0");
}

extern fn down_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
  text_layer_set_text(text_layer, "Down!\0");
}

extern fn click_config_provider(_: *mut TextLayer) {
  window_single_click_subscribe(1, up_click_handler);
  window_single_click_subscribe(2, select_click_handler);
  window_single_click_subscribe(3, down_click_handler);
}

extern fn window_load_handler(window: *mut Window) {
  let window_layer = window_get_root_layer(window);
  let window_bounds = layer_get_bounds(window_layer);

  let text_bounds = GRect {
    origin: GPoint { x: 0, y: 72 },
    size: GSize { w: window_bounds.size.w, h: 20 }
  };
  let text_layer = text_layer_create(text_bounds);

  text_layer_set_text(text_layer, "Press a button\0");
  layer_add_child(window_layer, text_layer_get_layer(text_layer));

  window_set_click_config_provider_with_context(window, click_config_provider, text_layer);
}

extern fn window_unload_handler(_: *mut Window) {
}
extern fn window_appear_handler(_: *mut Window) {
}
extern fn window_disappear_handler(_: *mut Window) {
}

#[no_mangle]
pub extern fn main() -> i32 {
  let window = window_create();
  let window_handlers = WindowHandlers {
    load: window_load_handler,
    unload: window_unload_handler,
    appear: window_appear_handler,
    disappear: window_disappear_handler
  };
  window_set_window_handlers(window, window_handlers);
  window_stack_push(window, true);
  app_event_loop();
  0
}
<commit_msg>fixed some formatting things<commit_after>#![crate_type="lib"]
#![feature(lang_items, intrinsics, no_std)]
#![no_std]

use pebblerust::lib::*;
use pebblerust::types::*;

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

mod pebblerust {
  pub mod lib;
  pub mod c;
  pub mod types;
  pub mod zero;
}

extern fn select_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
    text_layer_set_text(text_layer, "Select!\0");
}

extern fn up_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
    text_layer_set_text(text_layer, "Up!\0");
}

extern fn down_click_handler(_: ClickRecognizerRef, text_layer: *mut TextLayer) {
    text_layer_set_text(text_layer, "Down!\0");
}

extern fn click_config_provider(_: *mut TextLayer) {
    window_single_click_subscribe(1, up_click_handler);
    window_single_click_subscribe(2, select_click_handler);
    window_single_click_subscribe(3, down_click_handler);
}

extern fn window_load_handler(window: *mut Window) {
    let window_layer = window_get_root_layer(window);
    let window_bounds = layer_get_bounds(window_layer);

    let text_bounds = GRect {
        origin: GPoint { x: 0, y: 72 },
        size: GSize { w: window_bounds.size.w, h: 20 }
    };
    let text_layer = text_layer_create(text_bounds);

    text_layer_set_text(text_layer, "Press a button\0");
    layer_add_child(window_layer, text_layer_get_layer(text_layer));

    window_set_click_config_provider_with_context(window, click_config_provider, text_layer);
}

extern fn window_unload_handler(_: *mut Window) { }
extern fn window_appear_handler(_: *mut Window) { }
extern fn window_disappear_handler(_: *mut Window) { }

#[no_mangle]
pub extern fn main() -> i32 {
    let window = window_create();

    let window_handlers = WindowHandlers {
        load: window_load_handler,
        unload: window_unload_handler,
        appear: window_appear_handler,
        disappear: window_disappear_handler
    };
    window_set_window_handlers(window, window_handlers);

    window_stack_push(window, true);

    app_event_loop();

    0
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate futures;
extern crate redis;

use futures::Future;
use futures::Stream;
use futures::future::ok as FutureOk;

use hyper::{Client, Body, Uri, StatusCode};
use hyper::server::{Request, Response, Service};
use hyper::client::HttpConnector;
use hyper::error::UriError;
use hyper::Get;
use hyper::header::ContentLength;
use std::sync::Arc;

use host_resolver::HostResolver;
use redis_service::Cache;
use file_utils::FileReader;

#[derive(Clone)]
pub struct Proxy {
    pub client: Client<HttpConnector, Body>,
    pub host_resolver: Arc<HostResolver>,
    pub cache: Arc<Cache>,
}

impl Proxy {

    pub fn new(client: Client<HttpConnector, Body>, host_resolver: Arc<HostResolver>, cache: Arc<Cache>) -> Proxy {
        Proxy { client, host_resolver, cache }
    }
}

impl Service for Proxy {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item=Self::Response, Error = Self::Error>>;

    fn call(&self, req: Self::Request) -> Self::Future {
        info!("Dispatching request: {:?}", &req);
        Router::new(self.host_resolver.clone(), self.cache.clone())
            .dispatch_request(&self.client, req)
    }
}

#[derive(Clone)]
pub struct Router {
    max_retry: Arc<u32>,
    host_resolver: Arc<HostResolver>,
    cache: Arc<Cache>
}

impl Router {

    pub fn new(host_resolver: Arc<HostResolver>, cache: Arc<Cache>) -> Router {
        Router { max_retry: Arc::new(3), host_resolver: host_resolver, cache: cache }
    }

    fn clone_req(req: &Request) -> Request {
        let mut new_req = Request::new(req.method().clone(), req.uri().clone());
        new_req.headers_mut().extend(req.headers().iter());
        new_req
    }

    fn clone_req_custom_uri(req: &Request, uri: &Uri) -> Request {
        let mut new_req = Request::new(req.method().clone(), uri.clone());
        new_req.headers_mut().extend(req.headers().iter());
        new_req
    }

    fn create_url(host: &str, uri: Uri) -> Result<Uri, UriError> {
        format!("{}{}{}", host, uri.path(), uri.query().unwrap_or("")).parse()
    }

    fn req_is_cacheable(req: & Request<Body>) -> bool {
        (*req.method() == Get) // TODO check header Cache: False
    }

    fn cache_key(req: &Request<Body>) -> String {
        req.uri().path().clone().to_string()
    }

    fn map_req(&self, req: Request) -> Request {
        let host = self.host_resolver.clone().get_next();
        let uri = Self::create_url(host.as_ref(), req.uri().clone())
            .expect(&format!("Failed trying to parse uri. Origin: {:?}", &req.uri()));
        Self::clone_req_custom_uri(&req, &uri)
    }

    fn dispatch_request(self, client: &Client<HttpConnector, Body>, req: Request<Body>) -> Box<Future<Error=hyper::Error, Item=Response>> {
        if Self::req_is_cacheable(&req) {
            self.with_cache(client, req)
        } else {
            self.forward_to_server(client, req, 1)
        }
    }

    fn with_cache(self, client: &Client<HttpConnector, Body>, req: Request<Body>) -> Box<Future<Error=hyper::Error, Item=Response>> {
        let cache_key = Self::cache_key(&req);
        let cache_ref: Arc<Cache> = self.cache.clone();
        let cache_response = cache_ref.clone().get(&cache_key[..]);
        let resp: Box<Future<Error=hyper::Error, Item=Response>> = match cache_response {
            Ok(response) =>  {
                info!("Response from Redis: {:?}", response);
                Box::new(FutureOk(Response::new().with_body(response)))
            },
            Err(e) => {
                let resp = self
                    .forward_to_server(client, req, 1)
                    .and_then(move |response| {
                        let resp = response
                            .body()
                            .fold(Vec::new(), |mut acc, chunk| {
                                acc.extend_from_slice(&*chunk);
                                futures::future::ok::<_, hyper::Error>(acc)
                            })
                            .map(move |body| {
                                cache_ref.clone().set(&cache_key.clone()[..], String::from_utf8(body.clone()).unwrap());
                                let body_str = String::from_utf8(body).unwrap();
                                let resp: Response<Body> = Response::new()
                                    .with_header(ContentLength(body_str.len() as u64))
                                    .with_body(body_str.clone());
                                resp
                            });
                        Box::new(resp)
                    });
                Box::new(resp)
            }
        };
        resp
    }

    fn forward_to_server(self, client: &Client<HttpConnector, Body>, req: Request<Body>, n_retry: u32) -> Box<Future<Error=hyper::Error, Item=Response>>
    {

        let client_clone = client.clone();
        let ref_max = self.max_retry.clone();

        let cloned_req = self.map_req(Self::clone_req(&req));

        info!("Attemp {} for url: {:?}", n_retry, cloned_req);

        let resp = client.request(Self::clone_req(&cloned_req)).then(move |result| {
            debug!("Max retry: {}. Current attemp: {}", ref_max.clone(), n_retry);
            match result {
                Ok(client_resp) => Box::new(FutureOk(client_resp)),
                Err(e) => {
                    error!("Connection error: {:?}", &e);
                    if (n_retry < *ref_max.clone()) && (*cloned_req.method() == Get) {
                        self.forward_to_server(&client_clone, Self::clone_req(&cloned_req), n_retry + 1)
                    } else {
                        Box::new(FutureOk(Response::new().with_status(StatusCode::ServiceUnavailable)))
                    }

                }
            }
        });
        Box::new(resp)
    }
}
<commit_msg>save in cache only response with status 200 + propagate properly the headers and the status<commit_after>extern crate hyper;
extern crate futures;
extern crate redis;

use futures::Future;
use futures::Stream;
use futures::future::ok as FutureOk;

use hyper::{Client, Body, Uri, StatusCode};
use hyper::server::{Request, Response, Service};
use hyper::client::HttpConnector;
use hyper::error::UriError;
use hyper::Get;
use hyper::header::ContentLength;
use std::sync::Arc;

use host_resolver::HostResolver;
use redis_service::Cache;
use file_utils::FileReader;

#[derive(Clone)]
pub struct Proxy {
    pub client: Client<HttpConnector, Body>,
    pub host_resolver: Arc<HostResolver>,
    pub cache: Arc<Cache>,
}

impl Proxy {

    pub fn new(client: Client<HttpConnector, Body>, host_resolver: Arc<HostResolver>, cache: Arc<Cache>) -> Proxy {
        Proxy { client, host_resolver, cache }
    }
}

impl Service for Proxy {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item=Self::Response, Error = Self::Error>>;

    fn call(&self, req: Self::Request) -> Self::Future {
        info!("Dispatching request: {:?}", &req);
        Router::new(self.host_resolver.clone(), self.cache.clone())
            .dispatch_request(&self.client, req)
    }
}

#[derive(Clone)]
pub struct Router {
    max_retry: Arc<u32>,
    host_resolver: Arc<HostResolver>,
    cache: Arc<Cache>
}

impl Router {

    pub fn new(host_resolver: Arc<HostResolver>, cache: Arc<Cache>) -> Router {
        Router { max_retry: Arc::new(3), host_resolver: host_resolver, cache: cache }
    }

    fn clone_req(req: &Request) -> Request {
        let mut new_req = Request::new(req.method().clone(), req.uri().clone());
        new_req.headers_mut().extend(req.headers().iter());
        new_req
    }

    fn clone_req_custom_uri(req: &Request, uri: &Uri) -> Request {
        let mut new_req = Request::new(req.method().clone(), uri.clone());
        new_req.headers_mut().extend(req.headers().iter());
        new_req
    }

    fn create_url(host: &str, uri: Uri) -> Result<Uri, UriError> {
        format!("{}{}{}", host, uri.path(), uri.query().unwrap_or("")).parse()
    }

    fn req_is_cacheable(req: & Request<Body>) -> bool {
        (*req.method() == Get) // TODO check header Cache: False
    }

    fn cache_key(req: &Request<Body>) -> String {
        req.uri().path().clone().to_string()
    }

    fn map_req(&self, req: Request) -> Request {
        let host = self.host_resolver.clone().get_next();
        let uri = Self::create_url(host.as_ref(), req.uri().clone())
            .expect(&format!("Failed trying to parse uri. Origin: {:?}", &req.uri()));
        Self::clone_req_custom_uri(&req, &uri)
    }

    fn dispatch_request(self, client: &Client<HttpConnector, Body>, req: Request<Body>) -> Box<Future<Error=hyper::Error, Item=Response>> {
        if Self::req_is_cacheable(&req) {
            self.with_cache(client, req)
        } else {
            self.forward_to_server(client, req, 1)
        }
    }

    fn with_cache(self, client: &Client<HttpConnector, Body>, req: Request<Body>) -> Box<Future<Error=hyper::Error, Item=Response>> {
        let cache_key = Self::cache_key(&req);
        let cache_ref: Arc<Cache> = self.cache.clone();
        let cache_response = cache_ref.clone().get(&cache_key[..]);
        let resp: Box<Future<Error=hyper::Error, Item=Response>> = match cache_response {
            Ok(response) =>  {
                info!("Response from Redis: {:?}", response);
                Box::new(FutureOk(Response::new().with_body(response)))
            },
            Err(e) => {
                let resp = self
                    .forward_to_server(client, req, 1)
                    .and_then(move |response| {
                        let original_headers = response.headers().clone();
                        let original_status = response.status().clone();
                        let resp = response
                            .body()
                            .fold(Vec::new(), |mut acc, chunk| {
                                acc.extend_from_slice(&*chunk);
                                futures::future::ok::<_, hyper::Error>(acc)
                            })
                            .map(move |body| {
                                if original_status == StatusCode::Ok {
                                    cache_ref.clone().set(&cache_key.clone()[..], String::from_utf8(body.clone()).unwrap());
                                }
                                let body_str = String::from_utf8(body).unwrap();
                                let resp: Response<Body> = Response::new()
                                    .with_headers(original_headers)
                                    .with_header(ContentLength(body_str.len() as u64))
                                    .with_status(original_status)
                                    .with_body(body_str.clone());
                                resp
                            });
                        Box::new(resp)
                    });
                Box::new(resp)
            }
        };
        resp
    }

    fn forward_to_server(self, client: &Client<HttpConnector, Body>, req: Request<Body>, n_retry: u32) -> Box<Future<Error=hyper::Error, Item=Response>>
    {

        let client_clone = client.clone();
        let ref_max = self.max_retry.clone();

        let cloned_req = self.map_req(Self::clone_req(&req));

        info!("Attemp {} for url: {:?}", n_retry, cloned_req);

        let resp = client.request(Self::clone_req(&cloned_req)).then(move |result| {
            debug!("Max retry: {}. Current attemp: {}", ref_max.clone(), n_retry);
            match result {
                Ok(client_resp) => Box::new(FutureOk(client_resp)),
                Err(e) => {
                    error!("Connection error: {:?}", &e);
                    if (n_retry < *ref_max.clone()) && (*cloned_req.method() == Get) {
                        self.forward_to_server(&client_clone, Self::clone_req(&cloned_req), n_retry + 1)
                    } else {
                        Box::new(FutureOk(Response::new().with_status(StatusCode::ServiceUnavailable)))
                    }

                }
            }
        });
        Box::new(resp)
    }
}
<|endoftext|>