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

use base64;
use serde_json;

/// A crate private constructor for `Error`.
pub(crate) fn new_error(kind: ErrorKind) -> Error {
    Error(Box::new(kind))
}

/// A type alias for `Result<T, jsonwebtoken::Error>`.
pub type Result<T> = result::Result<T, Error>;

/// An error that can occur when encoding/decoding JWTs
#[derive(Debug)]
pub struct Error(Box<ErrorKind>);

impl Error {
    /// Return the specific type of this error.
    pub fn kind(&self) -> &ErrorKind {
        &self.0
    }

    /// Unwrap this error into its underlying type.
    pub fn into_kind(self) -> ErrorKind {
        *self.0
    }
}

/// The specific type of an error.
#[derive(Debug)]
pub enum ErrorKind {
    /// When a token doesn't have a valid JWT shape
    InvalidToken,
    /// When the signature doesn't match
    InvalidSignature,
    /// When the secret given is not a valid ECDSA key
    InvalidEcdsaKey,
    /// When the secret given is not a valid RSA key
    InvalidRsaKey,
    /// When the algorithm from string doesn't match the one passed to `from_str`
    InvalidAlgorithmName,
    /// When a key is provided with an invalid format
    InvalidKeyFormat,

    // Validation errors
    /// When a token’s `exp` claim indicates that it has expired
    ExpiredSignature,
    /// When a token’s `iss` claim does not match the expected issuer
    InvalidIssuer,
    /// When a token’s `aud` claim does not match one of the expected audience values
    InvalidAudience,
    /// When a token’s `aud` claim does not match one of the expected audience values
    InvalidSubject,
    /// When a token’s nbf claim represents a time in the future
    ImmatureSignature,
    /// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
    /// used doesn't match the alg requested
    InvalidAlgorithm,

    // 3rd party errors
    /// An error happened when decoding some base64 text
    Base64(base64::DecodeError),
    /// An error happened while serializing/deserializing JSON
    Json(serde_json::Error),
    /// Some of the text was invalid UTF-8
    Utf8(::std::string::FromUtf8Error),
    /// Something unspecified went wrong with crypto
    Crypto(::ring::error::Unspecified),

    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self.0 {
            ErrorKind::InvalidToken => "invalid token",
            ErrorKind::InvalidSignature => "invalid signature",
            ErrorKind::InvalidEcdsaKey => "invalid ECDSA key",
            ErrorKind::InvalidRsaKey => "invalid RSA key",
            ErrorKind::ExpiredSignature => "expired signature",
            ErrorKind::InvalidIssuer => "invalid issuer",
            ErrorKind::InvalidAudience => "invalid audience",
            ErrorKind::InvalidSubject => "invalid subject",
            ErrorKind::ImmatureSignature => "immature signature",
            ErrorKind::InvalidAlgorithm => "algorithms don't match",
            ErrorKind::InvalidAlgorithmName => "not a known algorithm",
            ErrorKind::InvalidKeyFormat => "invalid key format",
            ErrorKind::Base64(ref err) => err.description(),
            ErrorKind::Json(ref err) => err.description(),
            ErrorKind::Utf8(ref err) => err.description(),
            ErrorKind::Crypto(ref err) => err.description(),
            ErrorKind::__Nonexhaustive => "unknown error",
        }
    }

    fn cause(&self) -> Option<&dyn StdError> {
        match *self.0 {
            ErrorKind::InvalidToken => None,
            ErrorKind::InvalidSignature => None,
            ErrorKind::InvalidEcdsaKey => None,
            ErrorKind::InvalidRsaKey => None,
            ErrorKind::ExpiredSignature => None,
            ErrorKind::InvalidIssuer => None,
            ErrorKind::InvalidAudience => None,
            ErrorKind::InvalidSubject => None,
            ErrorKind::ImmatureSignature => None,
            ErrorKind::InvalidAlgorithm => None,
            ErrorKind::InvalidAlgorithmName => None,
            ErrorKind::InvalidKeyFormat => None,
            ErrorKind::Base64(ref err) => Some(err),
            ErrorKind::Json(ref err) => Some(err),
            ErrorKind::Utf8(ref err) => Some(err),
            ErrorKind::Crypto(ref err) => Some(err),
            ErrorKind::__Nonexhaustive => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorKind::InvalidToken
            | ErrorKind::InvalidSignature
            | ErrorKind::InvalidEcdsaKey
            | ErrorKind::InvalidRsaKey
            | ErrorKind::ExpiredSignature
            | ErrorKind::InvalidIssuer
            | ErrorKind::InvalidAudience
            | ErrorKind::InvalidSubject
            | ErrorKind::ImmatureSignature
            | ErrorKind::InvalidAlgorithm
            | ErrorKind::InvalidKeyFormat
            | ErrorKind::InvalidAlgorithmName => write!(f, "{}", self.description()),
            ErrorKind::Json(ref err) => write!(f, "JSON error: {}", err),
            ErrorKind::Utf8(ref err) => write!(f, "UTF-8 error: {}", err),
            ErrorKind::Crypto(ref err) => write!(f, "Crypto error: {}", err),
            ErrorKind::Base64(ref err) => write!(f, "Base64 error: {}", err),
            ErrorKind::__Nonexhaustive => write!(f, "Unknown error"),
        }
    }
}

impl From<base64::DecodeError> for Error {
    fn from(err: base64::DecodeError) -> Error {
        new_error(ErrorKind::Base64(err))
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        new_error(ErrorKind::Json(err))
    }
}

impl From<::std::string::FromUtf8Error> for Error {
    fn from(err: ::std::string::FromUtf8Error) -> Error {
        new_error(ErrorKind::Utf8(err))
    }
}

impl From<::ring::error::Unspecified> for Error {
    fn from(err: ::ring::error::Unspecified) -> Error {
        new_error(ErrorKind::Crypto(err))
    }
}

impl From<::ring::error::KeyRejected> for Error {
    fn from(_err: ::ring::error::KeyRejected) -> Error {
        new_error(ErrorKind::InvalidEcdsaKey)
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        new_error(kind)
    }
}
<commit_msg>Get rid of deprecrated std error description<commit_after>use std::error::Error as StdError;
use std::fmt;
use std::result;

use base64;
use serde_json;

/// A crate private constructor for `Error`.
pub(crate) fn new_error(kind: ErrorKind) -> Error {
    Error(Box::new(kind))
}

/// A type alias for `Result<T, jsonwebtoken::Error>`.
pub type Result<T> = result::Result<T, Error>;

/// An error that can occur when encoding/decoding JWTs
#[derive(Debug)]
pub struct Error(Box<ErrorKind>);

impl Error {
    /// Return the specific type of this error.
    pub fn kind(&self) -> &ErrorKind {
        &self.0
    }

    /// Unwrap this error into its underlying type.
    pub fn into_kind(self) -> ErrorKind {
        *self.0
    }
}

/// The specific type of an error.
#[derive(Debug)]
pub enum ErrorKind {
    /// When a token doesn't have a valid JWT shape
    InvalidToken,
    /// When the signature doesn't match
    InvalidSignature,
    /// When the secret given is not a valid ECDSA key
    InvalidEcdsaKey,
    /// When the secret given is not a valid RSA key
    InvalidRsaKey,
    /// When the algorithm from string doesn't match the one passed to `from_str`
    InvalidAlgorithmName,
    /// When a key is provided with an invalid format
    InvalidKeyFormat,

    // Validation errors
    /// When a token’s `exp` claim indicates that it has expired
    ExpiredSignature,
    /// When a token’s `iss` claim does not match the expected issuer
    InvalidIssuer,
    /// When a token’s `aud` claim does not match one of the expected audience values
    InvalidAudience,
    /// When a token’s `aud` claim does not match one of the expected audience values
    InvalidSubject,
    /// When a token’s nbf claim represents a time in the future
    ImmatureSignature,
    /// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
    /// used doesn't match the alg requested
    InvalidAlgorithm,

    // 3rd party errors
    /// An error happened when decoding some base64 text
    Base64(base64::DecodeError),
    /// An error happened while serializing/deserializing JSON
    Json(serde_json::Error),
    /// Some of the text was invalid UTF-8
    Utf8(::std::string::FromUtf8Error),
    /// Something unspecified went wrong with crypto
    Crypto(::ring::error::Unspecified),

    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl StdError for Error {
    fn cause(&self) -> Option<&dyn StdError> {
        match *self.0 {
            ErrorKind::InvalidToken => None,
            ErrorKind::InvalidSignature => None,
            ErrorKind::InvalidEcdsaKey => None,
            ErrorKind::InvalidRsaKey => None,
            ErrorKind::ExpiredSignature => None,
            ErrorKind::InvalidIssuer => None,
            ErrorKind::InvalidAudience => None,
            ErrorKind::InvalidSubject => None,
            ErrorKind::ImmatureSignature => None,
            ErrorKind::InvalidAlgorithm => None,
            ErrorKind::InvalidAlgorithmName => None,
            ErrorKind::InvalidKeyFormat => None,
            ErrorKind::Base64(ref err) => Some(err),
            ErrorKind::Json(ref err) => Some(err),
            ErrorKind::Utf8(ref err) => Some(err),
            ErrorKind::Crypto(ref err) => Some(err),
            ErrorKind::__Nonexhaustive => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorKind::InvalidToken
            | ErrorKind::InvalidSignature
            | ErrorKind::InvalidEcdsaKey
            | ErrorKind::InvalidRsaKey
            | ErrorKind::ExpiredSignature
            | ErrorKind::InvalidIssuer
            | ErrorKind::InvalidAudience
            | ErrorKind::InvalidSubject
            | ErrorKind::ImmatureSignature
            | ErrorKind::InvalidAlgorithm
            | ErrorKind::InvalidKeyFormat
            | ErrorKind::InvalidAlgorithmName => write!(f, "{}", self),
            ErrorKind::Json(ref err) => write!(f, "JSON error: {}", err),
            ErrorKind::Utf8(ref err) => write!(f, "UTF-8 error: {}", err),
            ErrorKind::Crypto(ref err) => write!(f, "Crypto error: {}", err),
            ErrorKind::Base64(ref err) => write!(f, "Base64 error: {}", err),
            ErrorKind::__Nonexhaustive => write!(f, "Unknown error"),
        }
    }
}

impl From<base64::DecodeError> for Error {
    fn from(err: base64::DecodeError) -> Error {
        new_error(ErrorKind::Base64(err))
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        new_error(ErrorKind::Json(err))
    }
}

impl From<::std::string::FromUtf8Error> for Error {
    fn from(err: ::std::string::FromUtf8Error) -> Error {
        new_error(ErrorKind::Utf8(err))
    }
}

impl From<::ring::error::Unspecified> for Error {
    fn from(err: ::ring::error::Unspecified) -> Error {
        new_error(ErrorKind::Crypto(err))
    }
}

impl From<::ring::error::KeyRejected> for Error {
    fn from(_err: ::ring::error::KeyRejected) -> Error {
        new_error(ErrorKind::InvalidEcdsaKey)
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        new_error(kind)
    }
}
<|endoftext|>


<commit_before>use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use rustc_serialize::Encodable;
use time;
use retry::retry;
use record::Record;
use record::FluentError;
use retry_conf::RetryConf;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: conf,
        }
    }

    /// Post record into Fluentd. Without time version.
    pub fn post<T>(self, record: T) -> Result<(), FluentError>
        where T: Encodable
    {
        let time = time::now();
        return self.post_with_time(record, time);
    }

    /// Post record into Fluentd. With time version.
    pub fn post_with_time<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        return self.send_data(message)
    }

    /// Post record into Fluentd. With retryable version.
    pub fn post_with_retry<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        let addr = self.addr;
        let (max, timeout) = self.conf.build();
        match retry(max, timeout, || Fluent::closure_send_data(&addr, message.clone()), |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn send_data(self, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(self.addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn closure_send_data(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn post_to_fluentd() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let result = fruently.post(obj);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_time() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_time(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_retry() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_retry(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }
}
<commit_msg>fluent: Use more proper test case name<commit_after>use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use rustc_serialize::Encodable;
use time;
use retry::retry;
use record::Record;
use record::FluentError;
use retry_conf::RetryConf;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: conf,
        }
    }

    /// Post record into Fluentd. Without time version.
    pub fn post<T>(self, record: T) -> Result<(), FluentError>
        where T: Encodable
    {
        let time = time::now();
        return self.post_with_time(record, time);
    }

    /// Post record into Fluentd. With time version.
    pub fn post_with_time<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        return self.send_data(message)
    }

    /// Post record into Fluentd. With retryable version.
    pub fn post_with_retry<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        let addr = self.addr;
        let (max, timeout) = self.conf.build();
        match retry(max, timeout, || Fluent::closure_send_data(&addr, message.clone()), |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn send_data(self, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(self.addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn closure_send_data(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let result = fruently.post(obj);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_time() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_time(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_retry() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_retry(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }
}
<|endoftext|>


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

use {AsyncRead, AsyncWrite};
use framed_read::{framed_read2, framed_read2_with_buffer, FramedRead2, Decoder};
use framed_write::{framed_write2, framed_write2_with_buffer, FramedWrite2, Encoder};

use futures::{Stream, Sink, StartSend, Poll};
use bytes::{BytesMut};

/// A unified `Stream` and `Sink` interface to an underlying I/O object, using
/// the `Encoder` and `Decoder` traits to encode and decode frames.
///
/// You can create a `Framed` instance by using the `AsyncRead::framed` adapter.
pub struct Framed<T, U> {
    inner: FramedRead2<FramedWrite2<Fuse<T, U>>>,
}

pub struct Fuse<T, U>(pub T, pub U);

pub fn framed<T, U>(inner: T, codec: U) -> Framed<T, U>
    where T: AsyncRead + AsyncWrite,
          U: Decoder + Encoder,
{
    Framed {
        inner: framed_read2(framed_write2(Fuse(inner, codec))),
    }
}

impl<T, U> Framed<T, U> {
    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// This objects takes a stream and a readbuffer and a writebuffer. These field
    /// can be obtained from an existing `Framed` with the `into_parts` method.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    pub fn from_parts(parts: FramedParts<T>, codec: U) -> Framed<T, U>
    {
        Framed {
            inner: framed_read2_with_buffer(framed_write2_with_buffer(Fuse(parts.inner, codec), parts.writebuf), parts.readbuf),
        }
    }

    /// Returns a reference to the underlying I/O stream wrapped by
    /// `Frame`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.get_ref().get_ref().0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `Frame`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.get_mut().get_mut().0
    }

    /// Consumes the `Frame`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.into_inner().into_inner().0
    }

    /// Consumes the `Frame`, returning its underlying I/O stream and the buffer
    /// with unprocessed data.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_parts(self) -> FramedParts<T> {
        let (inner, readbuf) = self.inner.into_parts();
	    let (inner, writebuf) = inner.into_parts();
        FramedParts { inner: inner.0, readbuf: readbuf, writebuf: writebuf }
    }
}

impl<T, U> Stream for Framed<T, U>
    where T: AsyncRead,
          U: Decoder,
{
    type Item = U::Item;
    type Error = U::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.poll()
    }
}

impl<T, U> Sink for Framed<T, U>
    where T: AsyncWrite,
          U: Encoder,
          U::Error: From<io::Error>,
{
    type SinkItem = U::Item;
    type SinkError = U::Error;

    fn start_send(&mut self,
                  item: Self::SinkItem)
                  -> StartSend<Self::SinkItem, Self::SinkError>
    {
        self.inner.get_mut().start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.get_mut().poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.get_mut().close()
    }
}

impl<T, U> fmt::Debug for Framed<T, U>
    where T: fmt::Debug,
          U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Framed")
         .field("io", &self.inner.get_ref().get_ref().0)
         .field("codec", &self.inner.get_ref().get_ref().1)
         .finish()
    }
}

// ===== impl Fuse =====

impl<T: Read, U> Read for Fuse<T, U> {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        self.0.read(dst)
    }
}

impl<T: AsyncRead, U> AsyncRead for Fuse<T, U> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.0.prepare_uninitialized_buffer(buf)
    }
}

impl<T: Write, U> Write for Fuse<T, U> {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        self.0.write(src)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl<T: AsyncWrite, U> AsyncWrite for Fuse<T, U> {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        self.0.shutdown()
    }
}

impl<T, U: Decoder> Decoder for Fuse<T, U> {
    type Item = U::Item;
    type Error = U::Error;

    fn decode(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        self.1.decode(buffer)
    }

    fn decode_eof(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        self.1.decode_eof(buffer)
    }
}

impl<T, U: Encoder> Encoder for Fuse<T, U> {
    type Item = U::Item;
    type Error = U::Error;

    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
        self.1.encode(item, dst)
    }
}

/// `FramedParts` contains an export of the data of a Framed transport.
/// It can be used to construct a new `Framed` with a different codec.
/// It contains all current buffers and the inner transport.
#[derive(Debug)]
pub struct FramedParts<T>
{
    /// The inner transport used to read bytes to and write bytes to
    pub inner: T,
    /// The buffer with read but unprocessed data.
    pub readbuf: BytesMut,
    /// A buffer with unprocessed data which are not written yet.
    pub writebuf: BytesMut
}<commit_msg>Add `Framed::into_parts_and_codec` as temporary solution for #53<commit_after>use std::io::{self, Read, Write};
use std::fmt;

use {AsyncRead, AsyncWrite};
use framed_read::{framed_read2, framed_read2_with_buffer, FramedRead2, Decoder};
use framed_write::{framed_write2, framed_write2_with_buffer, FramedWrite2, Encoder};

use futures::{Stream, Sink, StartSend, Poll};
use bytes::{BytesMut};

/// A unified `Stream` and `Sink` interface to an underlying I/O object, using
/// the `Encoder` and `Decoder` traits to encode and decode frames.
///
/// You can create a `Framed` instance by using the `AsyncRead::framed` adapter.
pub struct Framed<T, U> {
    inner: FramedRead2<FramedWrite2<Fuse<T, U>>>,
}

pub struct Fuse<T, U>(pub T, pub U);

pub fn framed<T, U>(inner: T, codec: U) -> Framed<T, U>
    where T: AsyncRead + AsyncWrite,
          U: Decoder + Encoder,
{
    Framed {
        inner: framed_read2(framed_write2(Fuse(inner, codec))),
    }
}

impl<T, U> Framed<T, U> {
    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// This objects takes a stream and a readbuffer and a writebuffer. These field
    /// can be obtained from an existing `Framed` with the `into_parts` method.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    pub fn from_parts(parts: FramedParts<T>, codec: U) -> Framed<T, U>
    {
        Framed {
            inner: framed_read2_with_buffer(framed_write2_with_buffer(Fuse(parts.inner, codec), parts.writebuf), parts.readbuf),
        }
    }

    /// Returns a reference to the underlying I/O stream wrapped by
    /// `Frame`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.get_ref().get_ref().0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `Frame`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.get_mut().get_mut().0
    }

    /// Consumes the `Frame`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.into_inner().into_inner().0
    }

    /// Consumes the `Frame`, returning its underlying I/O stream and the buffer
    /// with unprocessed data.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_parts(self) -> FramedParts<T> {
        let (inner, readbuf) = self.inner.into_parts();
	    let (inner, writebuf) = inner.into_parts();
        FramedParts { inner: inner.0, readbuf: readbuf, writebuf: writebuf }
    }

    /// Consumes the `Frame`, returning its underlying I/O stream and the buffer
    /// with unprocessed data, and also the current codec state.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    ///
    /// Note that this function will be removed once the codec has been
    /// integrated into `FramedParts` in a new version (see
    /// [#53](https://github.com/tokio-rs/tokio-io/pull/53)).
    pub fn into_parts_and_codec(self) -> (FramedParts<T>, U) {
        let (inner, readbuf) = self.inner.into_parts();
        let (inner, writebuf) = inner.into_parts();
        (FramedParts { inner: inner.0, readbuf: readbuf, writebuf: writebuf }, inner.1)
    }
}

impl<T, U> Stream for Framed<T, U>
    where T: AsyncRead,
          U: Decoder,
{
    type Item = U::Item;
    type Error = U::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.poll()
    }
}

impl<T, U> Sink for Framed<T, U>
    where T: AsyncWrite,
          U: Encoder,
          U::Error: From<io::Error>,
{
    type SinkItem = U::Item;
    type SinkError = U::Error;

    fn start_send(&mut self,
                  item: Self::SinkItem)
                  -> StartSend<Self::SinkItem, Self::SinkError>
    {
        self.inner.get_mut().start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.get_mut().poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.get_mut().close()
    }
}

impl<T, U> fmt::Debug for Framed<T, U>
    where T: fmt::Debug,
          U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Framed")
         .field("io", &self.inner.get_ref().get_ref().0)
         .field("codec", &self.inner.get_ref().get_ref().1)
         .finish()
    }
}

// ===== impl Fuse =====

impl<T: Read, U> Read for Fuse<T, U> {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        self.0.read(dst)
    }
}

impl<T: AsyncRead, U> AsyncRead for Fuse<T, U> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.0.prepare_uninitialized_buffer(buf)
    }
}

impl<T: Write, U> Write for Fuse<T, U> {
    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
        self.0.write(src)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl<T: AsyncWrite, U> AsyncWrite for Fuse<T, U> {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        self.0.shutdown()
    }
}

impl<T, U: Decoder> Decoder for Fuse<T, U> {
    type Item = U::Item;
    type Error = U::Error;

    fn decode(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        self.1.decode(buffer)
    }

    fn decode_eof(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        self.1.decode_eof(buffer)
    }
}

impl<T, U: Encoder> Encoder for Fuse<T, U> {
    type Item = U::Item;
    type Error = U::Error;

    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
        self.1.encode(item, dst)
    }
}

/// `FramedParts` contains an export of the data of a Framed transport.
/// It can be used to construct a new `Framed` with a different codec.
/// It contains all current buffers and the inner transport.
#[derive(Debug)]
pub struct FramedParts<T>
{
    /// The inner transport used to read bytes to and write bytes to
    pub inner: T,
    /// The buffer with read but unprocessed data.
    pub readbuf: BytesMut,
    /// A buffer with unprocessed data which are not written yet.
    pub writebuf: BytesMut
}<|endoftext|>


<commit_before>// Non-camel case types are used for Stomp Protocol version enum variants
#![allow(non_camel_case_types)]

use collections::slice::Iter;

// Ideally this would be a simple typedef. However:
// See Rust bug #11047: https://github.com/mozilla/rust/issues/11047
// Cannot call static methods (`with_capacity`) on type aliases (`HeaderList`)
pub struct HeaderList {
  pub headers: Vec<Header>
}

impl HeaderList {
  pub fn new() -> HeaderList {
    HeaderList::with_capacity(0)
  }
  pub fn with_capacity(capacity: usize) -> HeaderList {
    HeaderList {
      headers: Vec::with_capacity(capacity)
    }
  }

  pub fn push(&mut self, header: Header) {
    self.headers.push(header);
  }

  pub fn iter<'a>(&'a self) -> Iter<'a, Header> {
    self.headers.iter()
  }

}

pub struct Header {
  buffer : String,
  delimiter_index : u32
}

impl Header {
  fn from_string(raw_string: &str) -> Option<Header> {
    let delimiter_index = match raw_string.find(':') {
      Some(index) => index,
      None => return None
    };
    let mut header = Header{
      buffer: raw_string.to_string(),
      delimiter_index: delimiter_index as u32
    };
    header = Header::decode_key_value(header.get_key(), header.get_value());
    Some(header)
  }

  pub fn encode_string(raw_string: &str) -> Option<Header> {
    let header = Header::from_string(raw_string);
    header.map(|h| Header::encode_key_value(h.get_key(), h.get_value()))
  }

  pub fn decode_string(raw_string: &str) -> Option<Header> {
    let header = Header::from_string(raw_string);
    header.map(|h| Header::decode_key_value(h.get_key(), h.get_value()))
  }

  pub fn encode_key_value(key: &str, value: &str) -> Header {
    let raw_string = format!("{}:{}", key, Header::encode_value(value));
    Header {
      buffer: raw_string,
      delimiter_index: key.len() as u32
    }
  }

  pub fn decode_key_value(key: &str, value: &str) -> Header {
    let raw_string = format!("{}:{}", key, Header::decode_value(value));
    Header {
      buffer: raw_string,
      delimiter_index: key.len() as u32
    }
  }

  //TODO: Optimize this method.
  fn decode_value(value: &str) -> String {
    value
      .replace(r"\c", ":")
      .replace(r"\n", "\n")
      .replace(r"\r", "\r")
      .replace(r"\\", "\\")
  }

//TODO: Optimize this method.
  fn encode_value(value: &str) -> String {
    value
      .replace("\\", r"\\") // Order is significant
      .replace("\r", r"\r")
      .replace("\n", r"\n")
      .replace(":", r"\c")
  }

  pub fn get_raw<'a>(&'a self) -> &'a str {
    self.buffer.as_slice()
  }

  pub fn get_key<'a>(&'a self) -> &'a str {
    self.buffer.as_slice().slice_to(self.delimiter_index as usize)
  }

  pub fn get_value<'a>(&'a self) -> &'a str {
    self.buffer.as_slice().slice_from(self.delimiter_index as usize + 1)
  }

}

// Headers in the Spec
pub struct AcceptVersion(pub Vec<StompVersion>);
pub struct Ack<'a>(pub &'a str);
#[derive(Copy)]
pub struct ContentLength(pub u32);
pub struct Custom(pub Header);
pub struct Destination<'a> (pub &'a str);
#[derive(Copy)]
pub struct HeartBeat(pub u32, pub u32);
pub struct Host<'a>(pub &'a str);
pub struct Id<'a>(pub &'a str);
pub struct Login<'a>(pub &'a str);
pub struct MessageId<'a>(pub &'a str);
pub struct Passcode<'a>(pub &'a str);
pub struct Receipt<'a>(pub &'a str);
pub struct ReceiptId<'a>(pub &'a str);
pub struct Server<'a>(pub &'a str);
pub struct Session<'a> (pub &'a str);
pub struct Subscription<'a>(pub &'a str);
pub struct Transaction<'a>(pub &'a str);
#[derive(Copy)]
pub struct Version(pub StompVersion);

#[derive(Copy)]
pub enum StompVersion {
  Stomp_v1_0,
  Stomp_v1_1,
  Stomp_v1_2,
}

pub trait StompHeaderSet {
  fn get_content_length(&self) -> Option<ContentLength>;
  fn get_header<'a>(&'a self, key: &str) -> Option<&'a Header>;
  fn get_accept_version<'a>(&'a self) -> Option<Vec<StompVersion>>;
  fn get_ack<'a>(&'a self) -> Option<Ack<'a>>;
  fn get_destination<'a>(&'a self) -> Option<Destination<'a>>;
  fn get_heart_beat(&self) -> Option<HeartBeat>;
  fn get_host<'a>(&'a self) -> Option<Host<'a>>;
  fn get_id<'a>(&'a self) -> Option<Id<'a>>;
  fn get_login<'a>(&'a self) -> Option<Login<'a>>;
  fn get_message_id<'a>(&'a self) -> Option<MessageId<'a>>;
  fn get_passcode<'a>(&'a self) -> Option<Passcode<'a>>;
  fn get_receipt<'a>(&'a self) -> Option<Receipt<'a>>;
  fn get_receipt_id<'a>(&'a self) -> Option<ReceiptId<'a>>;
  fn get_server<'a>(&'a self) -> Option<Server<'a>>;
  fn get_session<'a>(&'a self) -> Option<Session<'a>>;
  fn get_subscription<'a>(&'a self) -> Option<Subscription<'a>>;
  fn get_transaction<'a>(&'a self) -> Option<Transaction<'a>>;
  fn get_version(&self) -> Option<Version>;
}

impl StompHeaderSet for HeaderList {

  fn get_header<'a>(&'a self, key: &str) -> Option<&'a Header>{
    self.headers.iter().find(|header|
      match **header {
        ref h if h.get_key() == key => true,
        _ => false
      }
    )
  }

  fn get_accept_version(&self) -> Option<Vec<StompVersion>> {
    let versions : &str = match self.get_header("accept-version") {
      Some(h) => h.get_value(),
      None => return None
    };
    let versions: Vec<StompVersion> = versions.split(',').filter_map(|v| match v.trim() {
      "1.0" => Some(StompVersion::Stomp_v1_0),
      "1.1" => Some(StompVersion::Stomp_v1_1),
      "1.2" => Some(StompVersion::Stomp_v1_2),
      _ => None
    }).collect();
    Some(versions)
  }

  fn get_ack<'a>(&'a self) -> Option<Ack<'a>> {
    match self.get_header("ack") {
      Some(h) => Some(Ack(h.get_value())),
      None => None
    }
  }

  fn get_destination<'a>(&'a self) -> Option<Destination<'a>> {
    match self.get_header("destination") {
      Some(h) => Some(Destination(h.get_value())),
      None => return None
    }
  }

  fn get_heart_beat(&self) -> Option<HeartBeat> {
    let spec = match self.get_header("heart-beat") {
      Some(h) => h.get_value(),
      None => return None
    };
    let spec_list: Vec<u32> = spec.split(',').filter_map(|str_val| str_val.parse::<u32>()).collect();
    match spec_list.as_slice() {
      [x, y] => Some(HeartBeat(x, y)),
      _ => None
    }
  }

  fn get_host<'a>(&'a self) -> Option<Host<'a>> {
    match self.get_header("host") {
      Some(h) => Some(Host(h.get_value())),
      None => None
    }
  }

  fn get_id<'a>(&'a self) -> Option<Id<'a>> {
    match self.get_header("id") {
      Some(h) => Some(Id(h.get_value())),
      None => None
    }
  }

  fn get_login<'a>(&'a self) -> Option<Login<'a>> {
    match self.get_header("login"){
      Some(h) => Some(Login(h.get_value())),
      None => None
    }
  }

  fn get_message_id<'a>(&'a self) -> Option<MessageId<'a>> {
    match self.get_header("message-id"){
      Some(h) => Some(MessageId(h.get_value())),
      None => None
    }
  }

  fn get_passcode<'a>(&'a self) -> Option<Passcode<'a>> {
    match self.get_header("passcode"){
      Some(h) => Some(Passcode(h.get_value())),
      None => None
    }
  }

  fn get_receipt<'a>(&'a self) -> Option<Receipt<'a>> {
    match self.get_header("receipt"){
      Some(h) => Some(Receipt(h.get_value())),
      None => None
    }
  }

  fn get_receipt_id<'a>(&'a self) -> Option<ReceiptId<'a>> {
    match self.get_header("receipt-id"){
      Some(h) => Some(ReceiptId(h.get_value())),
      None => None
    }
  }

  fn get_server<'a>(&'a self) -> Option<Server<'a>> {
    match self.get_header("server"){
      Some(h) => Some(Server(h.get_value())),
      None => None
    }
  }

  fn get_session<'a>(&'a self) -> Option<Session<'a>> {
    match self.get_header("session"){
      Some(h) => Some(Session(h.get_value())),
      None => None
    }
  }

  fn get_subscription<'a>(&'a self) -> Option<Subscription<'a>> {
    match self.get_header("subscription"){
      Some(h) => Some(Subscription(h.get_value())),
      None => None
    }
  }

  fn get_transaction<'a>(&'a self) -> Option<Transaction<'a>> {
    match self.get_header("transaction"){
      Some(h) => Some(Transaction(h.get_value())),
      None => None
    }
  }

  fn get_version(&self) -> Option<Version> {
    let version = match self.get_header("version"){
      Some(h) => h.get_value(),
      None => return None
    };
    match (version).as_slice() {
      "1.0" => Some(Version(StompVersion::Stomp_v1_0)), // TODO: Impl FromStr for StompVersion
      "1.1" => Some(Version(StompVersion::Stomp_v1_1)),
      "1.2" => Some(Version(StompVersion::Stomp_v1_2)),
      _ => None
    }
  }

  fn get_content_length(&self) -> Option<ContentLength> {
    let length = match self.get_header("content-length") {
      Some(h) => h.get_value(),
      None => return None
    };
    match length.parse::<u32>() {
      Some(l) => Some(ContentLength(l)),
      None => None
    }
  }

}

<commit_msg>Add Header List Macro<commit_after>// Non-camel case types are used for Stomp Protocol version enum variants
#![allow(non_camel_case_types)]

use collections::slice::Iter;

// Ideally this would be a simple typedef. However:
// See Rust bug #11047: https://github.com/mozilla/rust/issues/11047
// Cannot call static methods (`with_capacity`) on type aliases (`HeaderList`)
pub struct HeaderList {
  pub headers: Vec<Header>
}

impl HeaderList {
  pub fn new() -> HeaderList {
    HeaderList::with_capacity(0)
  }
  pub fn with_capacity(capacity: usize) -> HeaderList {
    HeaderList {
      headers: Vec::with_capacity(capacity)
    }
  }

  pub fn push(&mut self, header: Header) {
    self.headers.push(header);
  }

  pub fn iter<'a>(&'a self) -> Iter<'a, Header> {
    self.headers.iter()
  }

}

pub struct Header {
  buffer : String,
  delimiter_index : u32
}

impl Header {
  fn from_string(raw_string: &str) -> Option<Header> {
    let delimiter_index = match raw_string.find(':') {
      Some(index) => index,
      None => return None
    };
    let mut header = Header{
      buffer: raw_string.to_string(),
      delimiter_index: delimiter_index as u32
    };
    header = Header::decode_key_value(header.get_key(), header.get_value());
    Some(header)
  }

  pub fn encode_string(raw_string: &str) -> Option<Header> {
    let header = Header::from_string(raw_string);
    header.map(|h| Header::encode_key_value(h.get_key(), h.get_value()))
  }

  pub fn decode_string(raw_string: &str) -> Option<Header> {
    let header = Header::from_string(raw_string);
    header.map(|h| Header::decode_key_value(h.get_key(), h.get_value()))
  }

  pub fn encode_key_value(key: &str, value: &str) -> Header {
    let raw_string = format!("{}:{}", key, Header::encode_value(value));
    Header {
      buffer: raw_string,
      delimiter_index: key.len() as u32
    }
  }

  pub fn decode_key_value(key: &str, value: &str) -> Header {
    let raw_string = format!("{}:{}", key, Header::decode_value(value));
    Header {
      buffer: raw_string,
      delimiter_index: key.len() as u32
    }
  }

  //TODO: Optimize this method.
  fn decode_value(value: &str) -> String {
    value
      .replace(r"\c", ":")
      .replace(r"\n", "\n")
      .replace(r"\r", "\r")
      .replace(r"\\", "\\")
  }

//TODO: Optimize this method.
  fn encode_value(value: &str) -> String {
    value
      .replace("\\", r"\\") // Order is significant
      .replace("\r", r"\r")
      .replace("\n", r"\n")
      .replace(":", r"\c")
  }

  pub fn get_raw<'a>(&'a self) -> &'a str {
    self.buffer.as_slice()
  }

  pub fn get_key<'a>(&'a self) -> &'a str {
    self.buffer.as_slice().slice_to(self.delimiter_index as usize)
  }

  pub fn get_value<'a>(&'a self) -> &'a str {
    self.buffer.as_slice().slice_from(self.delimiter_index as usize + 1)
  }

}

// Headers in the Spec
pub struct AcceptVersion(pub Vec<StompVersion>);
pub struct Ack<'a>(pub &'a str);
#[derive(Copy)]
pub struct ContentLength(pub u32);
pub struct Custom(pub Header);
pub struct Destination<'a> (pub &'a str);
#[derive(Copy)]
pub struct HeartBeat(pub u32, pub u32);
pub struct Host<'a>(pub &'a str);
pub struct Id<'a>(pub &'a str);
pub struct Login<'a>(pub &'a str);
pub struct MessageId<'a>(pub &'a str);
pub struct Passcode<'a>(pub &'a str);
pub struct Receipt<'a>(pub &'a str);
pub struct ReceiptId<'a>(pub &'a str);
pub struct Server<'a>(pub &'a str);
pub struct Session<'a> (pub &'a str);
pub struct Subscription<'a>(pub &'a str);
pub struct Transaction<'a>(pub &'a str);
#[derive(Copy)]
pub struct Version(pub StompVersion);

#[derive(Copy)]
pub enum StompVersion {
  Stomp_v1_0,
  Stomp_v1_1,
  Stomp_v1_2,
}

pub trait StompHeaderSet {
  fn get_content_length(&self) -> Option<ContentLength>;
  fn get_header<'a>(&'a self, key: &str) -> Option<&'a Header>;
  fn get_accept_version<'a>(&'a self) -> Option<Vec<StompVersion>>;
  fn get_ack<'a>(&'a self) -> Option<Ack<'a>>;
  fn get_destination<'a>(&'a self) -> Option<Destination<'a>>;
  fn get_heart_beat(&self) -> Option<HeartBeat>;
  fn get_host<'a>(&'a self) -> Option<Host<'a>>;
  fn get_id<'a>(&'a self) -> Option<Id<'a>>;
  fn get_login<'a>(&'a self) -> Option<Login<'a>>;
  fn get_message_id<'a>(&'a self) -> Option<MessageId<'a>>;
  fn get_passcode<'a>(&'a self) -> Option<Passcode<'a>>;
  fn get_receipt<'a>(&'a self) -> Option<Receipt<'a>>;
  fn get_receipt_id<'a>(&'a self) -> Option<ReceiptId<'a>>;
  fn get_server<'a>(&'a self) -> Option<Server<'a>>;
  fn get_session<'a>(&'a self) -> Option<Session<'a>>;
  fn get_subscription<'a>(&'a self) -> Option<Subscription<'a>>;
  fn get_transaction<'a>(&'a self) -> Option<Transaction<'a>>;
  fn get_version(&self) -> Option<Version>;
}

impl StompHeaderSet for HeaderList {

  fn get_header<'a>(&'a self, key: &str) -> Option<&'a Header>{
    self.headers.iter().find(|header|
      match **header {
        ref h if h.get_key() == key => true,
        _ => false
      }
    )
  }

  fn get_accept_version(&self) -> Option<Vec<StompVersion>> {
    let versions : &str = match self.get_header("accept-version") {
      Some(h) => h.get_value(),
      None => return None
    };
    let versions: Vec<StompVersion> = versions.split(',').filter_map(|v| match v.trim() {
      "1.0" => Some(StompVersion::Stomp_v1_0),
      "1.1" => Some(StompVersion::Stomp_v1_1),
      "1.2" => Some(StompVersion::Stomp_v1_2),
      _ => None
    }).collect();
    Some(versions)
  }

  fn get_ack<'a>(&'a self) -> Option<Ack<'a>> {
    match self.get_header("ack") {
      Some(h) => Some(Ack(h.get_value())),
      None => None
    }
  }

  fn get_destination<'a>(&'a self) -> Option<Destination<'a>> {
    match self.get_header("destination") {
      Some(h) => Some(Destination(h.get_value())),
      None => return None
    }
  }

  fn get_heart_beat(&self) -> Option<HeartBeat> {
    let spec = match self.get_header("heart-beat") {
      Some(h) => h.get_value(),
      None => return None
    };
    let spec_list: Vec<u32> = spec.split(',').filter_map(|str_val| str_val.parse::<u32>()).collect();
    match spec_list.as_slice() {
      [x, y] => Some(HeartBeat(x, y)),
      _ => None
    }
  }

  fn get_host<'a>(&'a self) -> Option<Host<'a>> {
    match self.get_header("host") {
      Some(h) => Some(Host(h.get_value())),
      None => None
    }
  }

  fn get_id<'a>(&'a self) -> Option<Id<'a>> {
    match self.get_header("id") {
      Some(h) => Some(Id(h.get_value())),
      None => None
    }
  }

  fn get_login<'a>(&'a self) -> Option<Login<'a>> {
    match self.get_header("login"){
      Some(h) => Some(Login(h.get_value())),
      None => None
    }
  }

  fn get_message_id<'a>(&'a self) -> Option<MessageId<'a>> {
    match self.get_header("message-id"){
      Some(h) => Some(MessageId(h.get_value())),
      None => None
    }
  }

  fn get_passcode<'a>(&'a self) -> Option<Passcode<'a>> {
    match self.get_header("passcode"){
      Some(h) => Some(Passcode(h.get_value())),
      None => None
    }
  }

  fn get_receipt<'a>(&'a self) -> Option<Receipt<'a>> {
    match self.get_header("receipt"){
      Some(h) => Some(Receipt(h.get_value())),
      None => None
    }
  }

  fn get_receipt_id<'a>(&'a self) -> Option<ReceiptId<'a>> {
    match self.get_header("receipt-id"){
      Some(h) => Some(ReceiptId(h.get_value())),
      None => None
    }
  }

  fn get_server<'a>(&'a self) -> Option<Server<'a>> {
    match self.get_header("server"){
      Some(h) => Some(Server(h.get_value())),
      None => None
    }
  }

  fn get_session<'a>(&'a self) -> Option<Session<'a>> {
    match self.get_header("session"){
      Some(h) => Some(Session(h.get_value())),
      None => None
    }
  }

  fn get_subscription<'a>(&'a self) -> Option<Subscription<'a>> {
    match self.get_header("subscription"){
      Some(h) => Some(Subscription(h.get_value())),
      None => None
    }
  }

  fn get_transaction<'a>(&'a self) -> Option<Transaction<'a>> {
    match self.get_header("transaction"){
      Some(h) => Some(Transaction(h.get_value())),
      None => None
    }
  }

  fn get_version(&self) -> Option<Version> {
    let version = match self.get_header("version"){
      Some(h) => h.get_value(),
      None => return None
    };
    match (version).as_slice() {
      "1.0" => Some(Version(StompVersion::Stomp_v1_0)), // TODO: Impl FromStr for StompVersion
      "1.1" => Some(Version(StompVersion::Stomp_v1_1)),
      "1.2" => Some(Version(StompVersion::Stomp_v1_2)),
      _ => None
    }
  }

  fn get_content_length(&self) -> Option<ContentLength> {
    let length = match self.get_header("content-length") {
      Some(h) => h.get_value(),
      None => return None
    };
    match length.parse::<u32>() {
      Some(l) => Some(ContentLength(l)),
      None => None
    }
  }

}

#[macro_export]
macro_rules! header_list [

  ($($header: expr), *) => ({
    let mut header_list = HeaderList::new();

    $(header_list.push($header);)*

    header_list
  })

];
<|endoftext|>


<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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.

#[cfg(not(feature = "ssl"))]
use ::futures::future::ok;
use ::futures::{stream, Async, Poll};
#[cfg(feature = "ssl")]
use ::futures::{Future, IntoFuture};
use mysql_common::packets::RawPacket;
#[cfg(feature = "ssl")]
use native_tls::{Certificate, Identity, TlsConnector};
use tokio::net::TcpStream;
use tokio_codec::Framed;
#[cfg(feature = "ssl")]
use tokio_codec::FramedParts;
use tokio_io::{AsyncRead, AsyncWrite};

use std::{fmt, io, net::ToSocketAddrs, time::Duration};
#[cfg(feature = "ssl")]
use std::{fs::File, io::Read};

use crate::{
    error::*,
    io::futures::{new_connecting_stream, new_write_packet, ConnectingStream, WritePacket},
    opts::SslOpts,
    MyFuture,
};

#[cfg(feature = "ssl")]
mod async_tls;
pub mod futures;
mod packet_codec;

#[derive(Debug)]
pub enum Endpoint {
    Plain(TcpStream),
    #[cfg(feature = "ssl")]
    Secure(self::async_tls::TlsStream<TcpStream>),
}

impl Endpoint {
    #[cfg(feature = "ssl")]
    pub fn is_secure(&self) -> bool {
        if let Endpoint::Secure(_) = self {
            true
        } else {
            false
        }
    }

    #[cfg(not(feature = "ssl"))]
    pub fn is_secure(&self) -> bool {
        false
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        let ms = ms.map(|val| Duration::from_millis(val as u64));
        match *self {
            Endpoint::Plain(ref stream) => stream.set_keepalive(ms)?,
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.get_ref().get_ref().set_keepalive(ms)?,
        }
        Ok(())
    }

    pub fn set_tcp_nodelay(&self, val: bool) -> Result<()> {
        match *self {
            Endpoint::Plain(ref stream) => stream.set_nodelay(val)?,
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.get_ref().get_ref().set_nodelay(val)?,
        }
        Ok(())
    }

    #[cfg(feature = "ssl")]
    pub fn make_secure(self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        (|| {
            let mut builder = TlsConnector::builder();
            match ssl_opts.root_cert_path() {
                Some(root_cert_path) => {
                    let mut root_cert_der = vec![];
                    let mut root_cert_file = File::open(root_cert_path)?;
                    root_cert_file.read_to_end(&mut root_cert_der)?;
                    let root_cert = Certificate::from_der(&*root_cert_der).map_err(Error::from)?;
                    builder.add_root_certificate(root_cert);
                }
                None => (),
            }
            if let Some(pkcs12_path) = ssl_opts.pkcs12_path() {
                let der = std::fs::read(pkcs12_path)?;
                let identity = Identity::from_pkcs12(&*der, ssl_opts.password().unwrap_or(""))
                    .map_err(Error::from)?;
                builder.identity(identity);
            }
            builder.danger_accept_invalid_hostnames(ssl_opts.skip_domain_validation());
            builder.danger_accept_invalid_certs(ssl_opts.accept_invalid_certs());
            builder.build().map_err(Error::from)
        })()
        .into_future()
        .and_then(move |tls_connector| match self {
            Endpoint::Plain(stream) => {
                self::async_tls::connect_async(&tls_connector, &*domain, stream)
                    .map_err(Error::from)
            }
            Endpoint::Secure(_) => unreachable!(),
        })
        .map(|tls_stream| Endpoint::Secure(tls_stream))
    }
}

impl From<TcpStream> for Endpoint {
    fn from(stream: TcpStream) -> Self {
        Endpoint::Plain(stream)
    }
}

#[cfg(feature = "ssl")]
impl From<self::async_tls::TlsStream<TcpStream>> for Endpoint {
    fn from(stream: self::async_tls::TlsStream<TcpStream>) -> Self {
        Endpoint::Secure(stream)
    }
}

impl io::Read for Endpoint {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.read(buf),
        }
    }
}

impl io::Write for Endpoint {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.write(buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.flush(),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.flush(),
        }
    }
}

impl AsyncRead for Endpoint {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        match *self {
            Endpoint::Plain(ref stream) => stream.prepare_uninitialized_buffer(_buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.prepare_uninitialized_buffer(_buf),
        }
    }
}

impl AsyncWrite for Endpoint {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.shutdown(),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.shutdown(),
        }
    }
}

/// Stream connected to MySql server.
pub struct Stream {
    closed: bool,
    codec: Option<Box<Framed<Endpoint, packet_codec::PacketCodec>>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Stream (endpoint={:?})",
            self.codec.as_ref().unwrap().get_ref()
        )
    }
}

impl Stream {
    pub fn connect<S>(addr: S) -> ConnectingStream
    where
        S: ToSocketAddrs,
    {
        new_connecting_stream(addr)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        self.codec.as_ref().unwrap().get_ref().set_keepalive_ms(ms)
    }

    pub fn set_tcp_nodelay(&self, val: bool) -> Result<()> {
        self.codec.as_ref().unwrap().get_ref().set_tcp_nodelay(val)
    }

    #[cfg(not(feature = "ssl"))]
    #[allow(unused)]
    pub fn make_secure(self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        ok(panic!("Ssl connection requires `ssl` feature"))
    }

    #[cfg(feature = "ssl")]
    pub fn make_secure(mut self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        let codec = self.codec.take().unwrap();
        let FramedParts { io, codec, .. } = codec.into_parts();
        io.make_secure(domain, ssl_opts).map(move |endpoint| {
            let codec = Framed::new(endpoint, codec);
            self.codec = Some(codec);
            self
        })
    }

    pub fn is_secure(&self) -> bool {
        self.codec.as_ref().unwrap().get_ref().is_secure()
    }
}

impl stream::Stream for Stream {
    type Item = (RawPacket, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(RawPacket, u8)>, Error> {
        if !self.closed {
            self.codec.as_mut().unwrap().poll().map_err(Error::from)
        } else {
            Ok(Async::Ready(None))
        }
    }
}
<commit_msg>Fix codec for ssl feature<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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.

#[cfg(not(feature = "ssl"))]
use ::futures::future::ok;
use ::futures::{stream, Async, Poll};
#[cfg(feature = "ssl")]
use ::futures::{Future, IntoFuture};
use mysql_common::packets::RawPacket;
#[cfg(feature = "ssl")]
use native_tls::{Certificate, Identity, TlsConnector};
use tokio::net::TcpStream;
use tokio_codec::Framed;
#[cfg(feature = "ssl")]
use tokio_codec::FramedParts;
use tokio_io::{AsyncRead, AsyncWrite};

use std::{fmt, io, net::ToSocketAddrs, time::Duration};
#[cfg(feature = "ssl")]
use std::{fs::File, io::Read};

use crate::{
    error::*,
    io::futures::{new_connecting_stream, new_write_packet, ConnectingStream, WritePacket},
    opts::SslOpts,
    MyFuture,
};

#[cfg(feature = "ssl")]
mod async_tls;
pub mod futures;
mod packet_codec;

#[derive(Debug)]
pub enum Endpoint {
    Plain(TcpStream),
    #[cfg(feature = "ssl")]
    Secure(self::async_tls::TlsStream<TcpStream>),
}

impl Endpoint {
    #[cfg(feature = "ssl")]
    pub fn is_secure(&self) -> bool {
        if let Endpoint::Secure(_) = self {
            true
        } else {
            false
        }
    }

    #[cfg(not(feature = "ssl"))]
    pub fn is_secure(&self) -> bool {
        false
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        let ms = ms.map(|val| Duration::from_millis(val as u64));
        match *self {
            Endpoint::Plain(ref stream) => stream.set_keepalive(ms)?,
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.get_ref().get_ref().set_keepalive(ms)?,
        }
        Ok(())
    }

    pub fn set_tcp_nodelay(&self, val: bool) -> Result<()> {
        match *self {
            Endpoint::Plain(ref stream) => stream.set_nodelay(val)?,
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.get_ref().get_ref().set_nodelay(val)?,
        }
        Ok(())
    }

    #[cfg(feature = "ssl")]
    pub fn make_secure(self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        (|| {
            let mut builder = TlsConnector::builder();
            match ssl_opts.root_cert_path() {
                Some(root_cert_path) => {
                    let mut root_cert_der = vec![];
                    let mut root_cert_file = File::open(root_cert_path)?;
                    root_cert_file.read_to_end(&mut root_cert_der)?;
                    let root_cert = Certificate::from_der(&*root_cert_der).map_err(Error::from)?;
                    builder.add_root_certificate(root_cert);
                }
                None => (),
            }
            if let Some(pkcs12_path) = ssl_opts.pkcs12_path() {
                let der = std::fs::read(pkcs12_path)?;
                let identity = Identity::from_pkcs12(&*der, ssl_opts.password().unwrap_or(""))
                    .map_err(Error::from)?;
                builder.identity(identity);
            }
            builder.danger_accept_invalid_hostnames(ssl_opts.skip_domain_validation());
            builder.danger_accept_invalid_certs(ssl_opts.accept_invalid_certs());
            builder.build().map_err(Error::from)
        })()
        .into_future()
        .and_then(move |tls_connector| match self {
            Endpoint::Plain(stream) => {
                self::async_tls::connect_async(&tls_connector, &*domain, stream)
                    .map_err(Error::from)
            }
            Endpoint::Secure(_) => unreachable!(),
        })
        .map(|tls_stream| Endpoint::Secure(tls_stream))
    }
}

impl From<TcpStream> for Endpoint {
    fn from(stream: TcpStream) -> Self {
        Endpoint::Plain(stream)
    }
}

#[cfg(feature = "ssl")]
impl From<self::async_tls::TlsStream<TcpStream>> for Endpoint {
    fn from(stream: self::async_tls::TlsStream<TcpStream>) -> Self {
        Endpoint::Secure(stream)
    }
}

impl io::Read for Endpoint {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.read(buf),
        }
    }
}

impl io::Write for Endpoint {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.write(buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.flush(),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.flush(),
        }
    }
}

impl AsyncRead for Endpoint {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        match *self {
            Endpoint::Plain(ref stream) => stream.prepare_uninitialized_buffer(_buf),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref stream) => stream.prepare_uninitialized_buffer(_buf),
        }
    }
}

impl AsyncWrite for Endpoint {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        match *self {
            Endpoint::Plain(ref mut stream) => stream.shutdown(),
            #[cfg(feature = "ssl")]
            Endpoint::Secure(ref mut stream) => stream.shutdown(),
        }
    }
}

/// Stream connected to MySql server.
pub struct Stream {
    closed: bool,
    codec: Option<Box<Framed<Endpoint, packet_codec::PacketCodec>>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Stream (endpoint={:?})",
            self.codec.as_ref().unwrap().get_ref()
        )
    }
}

impl Stream {
    pub fn connect<S>(addr: S) -> ConnectingStream
    where
        S: ToSocketAddrs,
    {
        new_connecting_stream(addr)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        self.codec.as_ref().unwrap().get_ref().set_keepalive_ms(ms)
    }

    pub fn set_tcp_nodelay(&self, val: bool) -> Result<()> {
        self.codec.as_ref().unwrap().get_ref().set_tcp_nodelay(val)
    }

    #[cfg(not(feature = "ssl"))]
    #[allow(unused)]
    pub fn make_secure(self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        ok(panic!("Ssl connection requires `ssl` feature"))
    }

    #[cfg(feature = "ssl")]
    pub fn make_secure(mut self, domain: String, ssl_opts: SslOpts) -> impl MyFuture<Self> {
        let codec = self.codec.take().unwrap();
        let FramedParts { io, codec, .. } = codec.into_parts();
        io.make_secure(domain, ssl_opts).map(move |endpoint| {
            let codec = Framed::new(endpoint, codec);
            self.codec = Some(Box::new(codec));
            self
        })
    }

    pub fn is_secure(&self) -> bool {
        self.codec.as_ref().unwrap().get_ref().is_secure()
    }
}

impl stream::Stream for Stream {
    type Item = (RawPacket, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(RawPacket, u8)>, Error> {
        if !self.closed {
            self.codec.as_mut().unwrap().poll().map_err(Error::from)
        } else {
            Ok(Async::Ready(None))
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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 errors::*;
use std::fmt;
use lib_futures::Async::NotReady;
use lib_futures::Async::Ready;
use lib_futures::Poll;
use lib_futures::stream;
use io::futures::ConnectingStream;
use io::futures::new_connecting_stream;
use io::futures::new_write_packet;
use io::futures::WritePacket;
use proto::NewPacket;
use proto::Packet;
use proto::ParseResult;
use std::cmp;
use std::collections::vec_deque::VecDeque;
use std::io;
use std::io::Read;
use std::net::ToSocketAddrs;
use tokio::net::TcpStream;
use tokio::reactor::Handle;

pub mod futures;

/// Stream connected to MySql server.
pub struct Stream {
    endpoint: Option<TcpStream>,
    closed: bool,
    next_packet: Option<ParseResult>,
    buf: Option<VecDeque<u8>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Stream (endpoint={:?})", self.endpoint)
    }
}

impl Stream {
    pub fn connect<S>(addr: S, handle: &Handle) -> ConnectingStream
        where S: ToSocketAddrs,
    {
        new_connecting_stream(addr, handle)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        Ok(self.endpoint.as_ref().expect("Should be here").set_keepalive_ms(ms)?)
    }
}

impl io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().read(buf)
    }
}

impl io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.endpoint.as_mut().unwrap().flush()
    }
}

impl stream::Stream for Stream {
    type Item = (Packet, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(Packet, u8)>, Error> {
        // should read everything from self.endpoint
        if !self.closed {
            let mut buf = [0u8; 4096];
            loop {
                match self.endpoint.as_mut().unwrap().read(&mut buf[..]) {
                    Ok(0) => {
                        break;
                    },
                    Ok(size) => {
                        let buf_handle = self.buf.as_mut().unwrap();
                        buf_handle.extend(&buf[..size]);
                    },
                    Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                        break;
                    },
                    Err(error) => {
                        self.closed = true;
                        return Err(Error::from(error));
                    },
                };
            }
        } else {
            return Ok(Ready(None));
        }

        // need to call again if there is a data in self.buf
        // or data was written to packet parser
        let mut should_poll = false;

        let next_packet = self.next_packet.take().expect("Stream.next_packet should not be None");
        let next_packet = match next_packet {
            ParseResult::Done(packet, seq_id) => {
                self.next_packet = Some(NewPacket::empty().parse());
                return Ok(Ready(Some((packet, seq_id))));
            },
            ParseResult::NeedHeader(mut new_packet, needed) => {
                let buf_handle = self.buf.as_mut().unwrap();
                let buf_len = buf_handle.len();
                for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                    new_packet.push_header(byte);
                }
                if buf_len != 0 {
                    should_poll = true;
                }

                new_packet
            },
            ParseResult::Incomplete(mut new_packet, needed) => {
                let buf_handle = self.buf.as_mut().unwrap();
                let buf_len = buf_handle.len();
                for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                    new_packet.push(byte);
                }
                if buf_len != 0 {
                    should_poll = true;
                }

                new_packet
            },
        };

        self.next_packet = Some(next_packet.parse());

        if should_poll {
            self.poll()
        } else {
            Ok(NotReady)
        }
    }
}
<commit_msg>Poll io stream again if it does not return NotReady<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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 errors::*;
use std::fmt;
use lib_futures::Async::NotReady;
use lib_futures::Async::Ready;
use lib_futures::Poll;
use lib_futures::stream;
use io::futures::ConnectingStream;
use io::futures::new_connecting_stream;
use io::futures::new_write_packet;
use io::futures::WritePacket;
use proto::NewPacket;
use proto::Packet;
use proto::ParseResult;
use std::cmp;
use std::collections::vec_deque::VecDeque;
use std::io;
use std::io::Read;
use std::net::ToSocketAddrs;
use tokio::net::TcpStream;
use tokio::reactor::Handle;

pub mod futures;

/// Stream connected to MySql server.
pub struct Stream {
    endpoint: Option<TcpStream>,
    closed: bool,
    next_packet: Option<ParseResult>,
    buf: Option<VecDeque<u8>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Stream (endpoint={:?})", self.endpoint)
    }
}

impl Stream {
    pub fn connect<S>(addr: S, handle: &Handle) -> ConnectingStream
        where S: ToSocketAddrs,
    {
        new_connecting_stream(addr, handle)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }

    pub fn set_keepalive_ms(&self, ms: Option<u32>) -> Result<()> {
        Ok(self.endpoint.as_ref().expect("Should be here").set_keepalive_ms(ms)?)
    }
}

impl io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().read(buf)
    }
}

impl io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.endpoint.as_mut().unwrap().flush()
    }
}

impl stream::Stream for Stream {
    type Item = (Packet, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(Packet, u8)>, Error> {
        // should read everything from self.endpoint
        let mut would_block = false;
        if !self.closed {
            let mut buf = [0u8; 4096];
            loop {
                match self.endpoint.as_mut().unwrap().read(&mut buf[..]) {
                    Ok(0) => {
                        break;
                    },
                    Ok(size) => {
                        let buf_handle = self.buf.as_mut().unwrap();
                        buf_handle.extend(&buf[..size]);
                    },
                    Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                        would_block = true;
                        break;
                    },
                    Err(error) => {
                        self.closed = true;
                        return Err(Error::from(error));
                    },
                };
            }
        } else {
            return Ok(Ready(None));
        }

        // need to call again if there is a data in self.buf
        // or data was written to packet parser
        let mut should_poll = false;

        let next_packet = self.next_packet.take().expect("Stream.next_packet should not be None");
        let next_packet = match next_packet {
            ParseResult::Done(packet, seq_id) => {
                self.next_packet = Some(NewPacket::empty().parse());
                return Ok(Ready(Some((packet, seq_id))));
            },
            ParseResult::NeedHeader(mut new_packet, needed) => {
                let buf_handle = self.buf.as_mut().unwrap();
                let buf_len = buf_handle.len();
                for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                    new_packet.push_header(byte);
                }
                if buf_len != 0 {
                    should_poll = true;
                }

                new_packet
            },
            ParseResult::Incomplete(mut new_packet, needed) => {
                let buf_handle = self.buf.as_mut().unwrap();
                let buf_len = buf_handle.len();
                for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                    new_packet.push(byte);
                }
                if buf_len != 0 {
                    should_poll = true;
                }

                new_packet
            },
        };

        self.next_packet = Some(next_packet.parse());

        if should_poll || !would_block {
            self.poll()
        } else {
            Ok(NotReady)
        }
    }
}
<|endoftext|>


<commit_before>use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

#[cfg(feature="rblas")]
use std::any::TypeId;

#[cfg(feature="rblas")]
use ShapeError;

#[cfg(feature="rblas")]
use error::{from_kind, ErrorKind};

#[cfg(feature="rblas")]
use blas::{AsBlas, BlasArrayView};

#[cfg(feature="rblas")]
use imp_prelude::*;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }

#[cfg(feature = "rblas")]
pub trait AsBlasAny<A, S, D> : AsBlas<A, S, D> {
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data;
}

#[cfg(feature = "rblas")]
/// ***Requires `features = "rblas"`***
impl<A, S, D> AsBlasAny<A, S, D> for ArrayBase<S, D>
    where S: Data<Elem=A>,
          D: Dimension,
          A: Any,
{
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data
    {
        if TypeId::of::<A>() == TypeId::of::<T>() {
            unsafe {
                let v = self.view();
                let u = ArrayView::new_(v.ptr as *const T, v.dim, v.strides);
                Priv(u).into_blas_view()
            }
        } else {
            Err(from_kind(ErrorKind::IncompatibleLayout))
        }
    }
}
<commit_msg>Edit docs for NdFloat<commit_after>use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

#[cfg(feature="rblas")]
use std::any::TypeId;

#[cfg(feature="rblas")]
use ShapeError;

#[cfg(feature="rblas")]
use error::{from_kind, ErrorKind};

#[cfg(feature="rblas")]
use blas::{AsBlas, BlasArrayView};

#[cfg(feature="rblas")]
use imp_prelude::*;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
///
/// This trait can only be implemented by `f32` and `f64`.
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }

#[cfg(feature = "rblas")]
pub trait AsBlasAny<A, S, D> : AsBlas<A, S, D> {
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data;
}

#[cfg(feature = "rblas")]
/// ***Requires `features = "rblas"`***
impl<A, S, D> AsBlasAny<A, S, D> for ArrayBase<S, D>
    where S: Data<Elem=A>,
          D: Dimension,
          A: Any,
{
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data
    {
        if TypeId::of::<A>() == TypeId::of::<T>() {
            unsafe {
                let v = self.view();
                let u = ArrayView::new_(v.ptr as *const T, v.dim, v.strides);
                Priv(u).into_blas_view()
            }
        } else {
            Err(from_kind(ErrorKind::IncompatibleLayout))
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

use ll;
use ll::limb::Limb;

pub unsafe fn gcd(gp: *mut Limb, mut ap: *mut Limb, mut an: i32, mut bp: *mut Limb, mut bn: i32) -> i32 {
    assert!(an >= bn);

    let mut gc = 0;
    while *ap == 0 && !ll::is_zero(ap, an) && *bp == 0 && !ll::is_zero(bp, bn){
        ap = ap.offset(1);
        bp = bp.offset(1);
        an -= 1;
        bn -= 1;
        gc += 1;
    }

    let a_trailing = (*ap).trailing_zeros() as u32;
    let b_trailing = (*bp).trailing_zeros() as u32;

    let trailing = if a_trailing < b_trailing {
        a_trailing
    } else {
        b_trailing
    };

    if trailing > 0 {
        ll::shr(ap, ap, an, trailing);
        ll::shr(bp, bp, bn, trailing);
    }

    ll::copy_incr(bp, gp, bn);
    bp = gp;

    while !ll::is_zero(ap, an) {

        while *ap == 0 && !ll::is_zero(ap, an) {
            ap = ap.offset(1);
            an -= 1;
        }

        let at = (*ap).trailing_zeros() as u32;
        if at > 0 {
            ll::shr(ap, ap, an, at);
        }

        while *bp == 0 && !ll::is_zero(bp, bn) {
            bp = bp.offset(1);
            bn -= 1;
        }

        let bt = (*bp).trailing_zeros() as u32;
        if bt > 0 {
            ll::shr(bp, bp, bn, bt);
        }

        let c = ll::cmp(ap, bp, an);

        // FIXME find better way to compute |ap - bp| / 2
        if c == Ordering::Equal || c == Ordering::Greater {
            ll::sub(ap, ap, an, bp, bn);
            ll::shr(ap, ap, an, 1);
        } else {
            ll::sub(gp, bp, an, ap, an);
            ll::shr(gp, gp, an, 1);
            bp = gp;
        }
    }

    // FIXME what's the best way for the left shift, using offset
    let gn = bn + gc;
    for _ in 0..gc {
        ll::shl(gp, gp, gn, (Limb::BITS - 1) as u32);
        ll::shl(gp, gp, gn, 1);
    }
    if trailing > 0 {
        ll::shl(gp, gp, gn, trailing);
    }

    gn
}
<commit_msg>Refactor right shift for result computation<commit_after>use std::cmp::Ordering;

use ll;
use ll::limb::Limb;

pub unsafe fn gcd(mut gp: *mut Limb, mut ap: *mut Limb, mut an: i32, mut bp: *mut Limb, mut bn: i32) -> i32 {
    assert!(an >= bn);

    let mut gc = 0;
    while *ap == 0 && !ll::is_zero(ap, an) && *bp == 0 && !ll::is_zero(bp, bn){
        ap = ap.offset(1);
        bp = bp.offset(1);
        gp = gp.offset(1);
        an -= 1;
        bn -= 1;
        gc += 1;
    }

    let a_trailing = (*ap).trailing_zeros() as u32;
    let b_trailing = (*bp).trailing_zeros() as u32;

    let trailing = if a_trailing < b_trailing {
        a_trailing
    } else {
        b_trailing
    };

    if trailing > 0 {
        ll::shr(ap, ap, an, trailing);
        ll::shr(bp, bp, bn, trailing);
    }

    ll::copy_incr(bp, gp, bn);
    bp = gp;

    while !ll::is_zero(ap, an) {

        while *ap == 0 && !ll::is_zero(ap, an) {
            ap = ap.offset(1);
            an -= 1;
        }

        let at = (*ap).trailing_zeros() as u32;
        if at > 0 {
            ll::shr(ap, ap, an, at);
        }

        while *bp == 0 && !ll::is_zero(bp, bn) {
            bp = bp.offset(1);
            bn -= 1;
        }

        let bt = (*bp).trailing_zeros() as u32;
        if bt > 0 {
            ll::shr(bp, bp, bn, bt);
        }

        let c = ll::cmp(ap, bp, an);

        if c == Ordering::Equal || c == Ordering::Greater {
            ll::sub(ap, ap, an, bp, bn);
            ll::shr(ap, ap, an, 1);
        } else {
            ll::sub(gp, bp, bn, ap, bn);
            ll::shr(gp, gp, bn, 1);
            bp = gp;
        }
    }

    if trailing > 0 {
        let v = ll::shl(gp, gp, bn, trailing);
        if v > 0 {
            *gp.offset(bn as isize) = v;
            gc += 1;
        }
    }

    gc + bn
}
<|endoftext|>


<commit_before>#![macro_use]
#[allow(unused_imports)]
use std::io::Write;

#[macro_export]
macro_rules! println_stderr(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)*) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

#[macro_export]
macro_rules! println_err(
    ($($args:tt)*) => (
        println_stderr!("{}", format!("{}{}{}", ::color::Color::Red.to_color_code(), format!($($args)*), ::color::Color::Reset.to_color_code()))
    )
);

#[macro_export]
macro_rules! println_ok(
    ($($args:tt)*) => (
        println_stderr!("{}", format!("{}{}{}", ::color::Color::Green.to_color_code(), format!($($args)*), ::color::Color::Reset.to_color_code()))
    )
);

#[macro_export]
macro_rules! println_title(
    ($($args:tt)*) => (
        println_stderr!("{}", format!("{}{}{}", ::color::Color::Cyan.to_color_code(), format!($($args)*), ::color::Color::Reset.to_color_code()))
    )
);

#[macro_export]
macro_rules! print_stderr(
    ($($arg:tt)*) => (
        match write!(::std::io::stderr(), $($arg)*) {
            Ok(_) => {
                match ::std::io::stderr().flush() {
                    Ok(_) => {},
                    Err(x) => panic!("Unable to write to stderr: {}", x)
                }
            },
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

#[macro_export]
macro_rules! print_stdout(
    ($($arg:tt)*) => (
        match write!(::std::io::stdout(), $($arg)*) {
            Ok(_) => {
                match ::std::io::stdout().flush() {
                    Ok(_) => {},
                    Err(x) => panic!("Unable to write to stdout: {}", x)
                }
            },
            Err(x) => panic!("Unable to write to stdout: {}", x),
        }
    )
);
<commit_msg>fixes macro styles so rustfmt can read them<commit_after>#![macro_use]
#[allow(unused_imports)]
use std::io::Write;

#[macro_export]
macro_rules! println_stderr(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)*) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

#[macro_export]
macro_rules! println_err(
    ($($args:tt)*) => (
        println_stderr!(
            "{}",
            format!(
                "{}{}{}",
                ::color::Color::Red.to_color_code(),
                format!($($args)*),
                ::color::Color::Reset.to_color_code()
            )
        )
    )
);

#[macro_export]
macro_rules! println_ok(
    ($($args:tt)*) => (
        println_stderr!(
            "{}",
            format!(
                "{}{}{}",
                ::color::Color::Green.to_color_code(),
                format!($($args)*),
                ::color::Color::Reset.to_color_code()
            )
        )
    )
);

#[macro_export]
macro_rules! println_title(
    ($($args:tt)*) => (
        println_stderr!(
            "{}",
            format!(
                "{}{}{}",
                ::color::Color::Cyan.to_color_code(),
                format!($($args)*),
                ::color::Color::Reset.to_color_code()
            )
        )
    )
);

#[macro_export]
macro_rules! print_stderr(
    ($($arg:tt)*) => (
        match write!(::std::io::stderr(), $($arg)*) {
            Ok(_) => {
                match ::std::io::stderr().flush() {
                    Ok(_) => {},
                    Err(x) => panic!("Unable to write to stderr: {}", x)
                }
            },
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

#[macro_export]
macro_rules! print_stdout(
    ($($arg:tt)*) => (
        match write!(::std::io::stdout(), $($arg)*) {
            Ok(_) => {
                match ::std::io::stdout().flush() {
                    Ok(_) => {},
                    Err(x) => panic!("Unable to write to stdout: {}", x)
                }
            },
            Err(x) => panic!("Unable to write to stdout: {}", x),
        }
    )
);
<|endoftext|>


<commit_before>macro_rules! char_num {
    (0) => (30); (1) => (31); (2) => (32); (3) => (33); (4) => (34); (5) => (35);
    (6) => (36); (7) => (37); (8) => (38); (9) => (39); (A) => (65); (B) => (66);
    (C) => (67); (D) => (68); (E) => (69); (F) => (70); (G) => (71); (H) => (72);
    (I) => (73); (J) => (74); (K) => (75); (L) => (76); (M) => (77); (N) => (78);
    (O) => (79); (P) => (80); (Q) => (81); (R) => (82); (S) => (83); (T) => (84);
    (U) => (85); (V) => (86); (W) => (87); (X) => (88); (Y) => (89); (Z) => (90);
}

#[macro_export]
macro_rules! tag {
    ($a:tt $b:tt $c:tt $d:tt) => (
        char_num!($a) << 24 |
        char_num!($b) << 16 |
        char_num!($c) << 8 |
        char_num!($d)
    );
}

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

    #[test]
    fn tag_macro() {
        const SHAP: Tag = tag!(S H A P);
        const PATH: Tag = tag!(P A T H);

        assert_eq!(SHAP, 1397244240u32);
        assert_eq!(PATH, 1346458696u32);
    }
}
<commit_msg>Export char_num! so tag! can be used externally<commit_after>#[macro_export]
macro_rules! char_num {
    (0) => (30); (1) => (31); (2) => (32); (3) => (33); (4) => (34); (5) => (35);
    (6) => (36); (7) => (37); (8) => (38); (9) => (39); (A) => (65); (B) => (66);
    (C) => (67); (D) => (68); (E) => (69); (F) => (70); (G) => (71); (H) => (72);
    (I) => (73); (J) => (74); (K) => (75); (L) => (76); (M) => (77); (N) => (78);
    (O) => (79); (P) => (80); (Q) => (81); (R) => (82); (S) => (83); (T) => (84);
    (U) => (85); (V) => (86); (W) => (87); (X) => (88); (Y) => (89); (Z) => (90);
}

#[macro_export]
macro_rules! tag {
    ($a:tt $b:tt $c:tt $d:tt) => (
        char_num!($a) << 24 |
        char_num!($b) << 16 |
        char_num!($c) << 8 |
        char_num!($d)
    );
}

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

    #[test]
    fn tag_macro() {
        const SHAP: Tag = tag!(S H A P);
        const PATH: Tag = tag!(P A T H);

        assert_eq!(SHAP, 1397244240u32);
        assert_eq!(PATH, 1346458696u32);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![macro_use]

macro_rules! debug(
    ($($args:tt)*) => (
        if cfg!(not(ndebug)) {
            println!("({}:{}) {}", module_path!(), line!(), format_args!($($args)*));
        }
    )
);

#[cfg(feature = "valgrind")]
pub mod valgrind {
    extern crate vgrs;
    pub use self::vgrs::memcheck::{malloclike_block, freelike_block, do_quick_leak_check, count_leaks};
}

#[cfg(not(feature = "valgrind"))]
#[allow(unused_variables)]
pub mod valgrind {
    pub struct LeakCount {
        pub leaked: usize,
    }
    pub unsafe fn malloclike_block(addr: *const (), size: usize, redzone: usize, is_zeroed: bool) { }
    pub unsafe fn freelike_block(addr: *const (), redzone: usize) { }
    pub unsafe fn do_quick_leak_check() { }
    pub unsafe fn count_leaks() -> LeakCount { return  LeakCount { leaked: 0 } }
}

macro_rules! valgrind_malloclike(
    ($addr:expr, $size:expr) => (
        if cfg!(feature = "valgrind") {
            unsafe{
                debug!("Mark object {:p} with malloclike_block for valgrind", $addr);
                ::macros::valgrind::malloclike_block($addr as *const (), $size, 0, true);
            }
        }
    )
);

macro_rules! valgrind_freelike(
    ($addr:expr) => (
        if cfg!(feature = "valgrind") {
            unsafe{
                debug!("Mark object {:p} with freelike_block for valgrind", $addr);
                ::macros:: valgrind::freelike_block($addr as *const (), 0);
            }
        }
    )
);

macro_rules! valgrind_assert_no_leaks(
    () => (
        if cfg!(feature = "valgrind") {
            unsafe{
                if cfg!(not(ndebug)) {
                    ::macros::valgrind::do_quick_leak_check();
                }
                let leak_count = ::macros::valgrind::count_leaks();
                assert!(leak_count.leaked == 0, "Valgrind reported leaked memory");
            }
        }
    )
);
<commit_msg>Use debug_assertions for debug! macro<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![macro_use]

macro_rules! debug(
    ($($args:tt)*) => (
        if cfg!(debug_assertions) {
            println!("({}:{}) {}", module_path!(), line!(), format_args!($($args)*));
        }
    )
);

#[cfg(feature = "valgrind")]
pub mod valgrind {
    extern crate vgrs;
    pub use self::vgrs::memcheck::{malloclike_block, freelike_block, do_quick_leak_check, count_leaks};
}

#[cfg(not(feature = "valgrind"))]
#[allow(unused_variables)]
pub mod valgrind {
    pub struct LeakCount {
        pub leaked: usize,
    }
    pub unsafe fn malloclike_block(addr: *const (), size: usize, redzone: usize, is_zeroed: bool) { }
    pub unsafe fn freelike_block(addr: *const (), redzone: usize) { }
    pub unsafe fn do_quick_leak_check() { }
    pub unsafe fn count_leaks() -> LeakCount { return  LeakCount { leaked: 0 } }
}

macro_rules! valgrind_malloclike(
    ($addr:expr, $size:expr) => (
        if cfg!(feature = "valgrind") {
            unsafe{
                debug!("Mark object {:p} with malloclike_block for valgrind", $addr);
                ::macros::valgrind::malloclike_block($addr as *const (), $size, 0, true);
            }
        }
    )
);

macro_rules! valgrind_freelike(
    ($addr:expr) => (
        if cfg!(feature = "valgrind") {
            unsafe{
                debug!("Mark object {:p} with freelike_block for valgrind", $addr);
                ::macros:: valgrind::freelike_block($addr as *const (), 0);
            }
        }
    )
);

macro_rules! valgrind_assert_no_leaks(
    () => (
        if cfg!(feature = "valgrind") {
            unsafe{
                if cfg!(debug_assertions) {
                    ::macros::valgrind::do_quick_leak_check();
                }
                let leak_count = ::macros::valgrind::count_leaks();
                assert!(leak_count.leaked == 0, "Valgrind reported leaked memory");
            }
        }
    )
);
<|endoftext|>